| @@ -70,8 +70,11 @@ static void Key(unsigned char key, int x, int y) | |||
| static void Draw(void) | |||
| { | |||
| glColorMask(1,1,1,1); | |||
| glClear(GL_COLOR_BUFFER_BIT); | |||
| /* right triangle: green */ | |||
| glBegin(GL_TRIANGLES); | |||
| glColor3f(0,1,0); | |||
| glVertex3f( 0.9, -0.9, -30.0); | |||
| @@ -81,6 +84,7 @@ static void Draw(void) | |||
| glColorMask(1,0,1,0); | |||
| /* left triangle: white&mask: purple middle region: white */ | |||
| glBegin(GL_TRIANGLES); | |||
| glColor3f(1,1,1); | |||
| glVertex3f(-0.9, -0.9, -30.0); | |||
| @@ -102,8 +102,6 @@ static void cso_release_all( struct cso_context *ctx ) | |||
| void cso_destroy_context( struct cso_context *ctx ) | |||
| { | |||
| debug_printf("%s\n", __FUNCTION__); | |||
| if (ctx) | |||
| cso_release_all( ctx ); | |||
| @@ -99,7 +99,7 @@ static void *cso_data_allocate_node(struct cso_hash_data *hash) | |||
| return MALLOC(hash->nodeSize); | |||
| } | |||
| static void cso_data_free_node(struct cso_node *node) | |||
| static void cso_free_node(struct cso_node *node) | |||
| { | |||
| FREE(node); | |||
| } | |||
| @@ -248,7 +248,7 @@ void cso_hash_delete(struct cso_hash *hash) | |||
| struct cso_node *cur = *bucket++; | |||
| while (cur != e_for_x) { | |||
| struct cso_node *next = cur->next; | |||
| cso_data_free_node(cur); | |||
| cso_free_node(cur); | |||
| cur = next; | |||
| } | |||
| } | |||
| @@ -367,7 +367,7 @@ void * cso_hash_take(struct cso_hash *hash, | |||
| if (*node != hash->data.e) { | |||
| void *t = (*node)->value; | |||
| struct cso_node *next = (*node)->next; | |||
| cso_data_free_node(*node); | |||
| cso_free_node(*node); | |||
| *node = next; | |||
| --hash->data.d->size; | |||
| cso_data_has_shrunk(hash->data.d); | |||
| @@ -393,3 +393,22 @@ int cso_hash_size(struct cso_hash *hash) | |||
| { | |||
| return hash->data.d->size; | |||
| } | |||
| struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter) | |||
| { | |||
| struct cso_hash_iter ret = iter; | |||
| struct cso_node *node = iter.node; | |||
| struct cso_node **node_ptr; | |||
| if (node == hash->data.e) | |||
| return iter; | |||
| ret = cso_hash_iter_next(ret); | |||
| node_ptr = (struct cso_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]); | |||
| while (*node_ptr != node) | |||
| node_ptr = &(*node_ptr)->next; | |||
| *node_ptr = node->next; | |||
| cso_free_node(node); | |||
| --hash->data.d->size; | |||
| return ret; | |||
| } | |||
| @@ -26,19 +26,20 @@ | |||
| **************************************************************************/ | |||
| /** | |||
| This file provides a hash implementation that is capable of dealing | |||
| with collisions. It stores colliding entries in linked list. All | |||
| functions operating on the hash return an iterator. The iterator | |||
| itself points to the collision list. If there wasn't any collision | |||
| the list will have just one entry, otherwise client code should | |||
| iterate over the entries to find the exact entry among ones that | |||
| had the same key (e.g. memcmp could be used on the data to check | |||
| that) | |||
| */ | |||
| /* | |||
| * Authors: | |||
| * Zack Rusin <zack@tungstengraphics.com> | |||
| */ | |||
| * @file | |||
| * Hash table implementation. | |||
| * | |||
| * This file provides a hash implementation that is capable of dealing | |||
| * with collisions. It stores colliding entries in linked list. All | |||
| * functions operating on the hash return an iterator. The iterator | |||
| * itself points to the collision list. If there wasn't any collision | |||
| * the list will have just one entry, otherwise client code should | |||
| * iterate over the entries to find the exact entry among ones that | |||
| * had the same key (e.g. memcmp could be used on the data to check | |||
| * that) | |||
| * | |||
| * @author Zack Rusin <zack@tungstengraphics.com> | |||
| */ | |||
| #ifndef CSO_HASH_H | |||
| #define CSO_HASH_H | |||
| @@ -48,24 +49,50 @@ | |||
| extern "C" { | |||
| #endif | |||
| struct cso_hash; | |||
| struct cso_node; | |||
| struct cso_hash_iter { | |||
| struct cso_hash *hash; | |||
| struct cso_node *node; | |||
| }; | |||
| struct cso_hash *cso_hash_create(void); | |||
| void cso_hash_delete(struct cso_hash *hash); | |||
| int cso_hash_size(struct cso_hash *hash); | |||
| /** | |||
| * Adds a data with the given key to the hash. If entry with the given | |||
| * key is already in the hash, this current entry is instered before it | |||
| * in the collision list. | |||
| * Function returns iterator pointing to the inserted item in the hash. | |||
| */ | |||
| struct cso_hash_iter cso_hash_insert(struct cso_hash *hash, unsigned key, | |||
| void *data); | |||
| /** | |||
| * Removes the item pointed to by the current iterator from the hash. | |||
| * Note that the data itself is not erased and if it was a malloc'ed pointer | |||
| * it will have to be freed after calling this function by the callee. | |||
| * Function returns iterator pointing to the item after the removed one in | |||
| * the hash. | |||
| */ | |||
| struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter); | |||
| void *cso_hash_take(struct cso_hash *hash, unsigned key); | |||
| struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash); | |||
| /** | |||
| * Return an iterator pointing to the first entry in the collision list. | |||
| */ | |||
| struct cso_hash_iter cso_hash_find(struct cso_hash *hash, unsigned key); | |||
| @@ -73,11 +100,15 @@ int cso_hash_iter_is_null(struct cso_hash_iter iter); | |||
| unsigned cso_hash_iter_key(struct cso_hash_iter iter); | |||
| void *cso_hash_iter_data(struct cso_hash_iter iter); | |||
| struct cso_hash_iter cso_hash_iter_next(struct cso_hash_iter iter); | |||
| struct cso_hash_iter cso_hash_iter_prev(struct cso_hash_iter iter); | |||
| /* KW: a convenience routine: | |||
| /** | |||
| * Convenience routine to iterate over the collision list while doing a memory | |||
| * comparison to see which entry in the list is a direct copy of our template | |||
| * and returns that entry. | |||
| */ | |||
| void *cso_hash_find_data_from_template( struct cso_hash *hash, | |||
| unsigned hash_key, | |||
| @@ -15,6 +15,7 @@ C_SOURCES = \ | |||
| draw_debug.c \ | |||
| draw_flatshade.c \ | |||
| draw_offset.c \ | |||
| draw_passthrough.c \ | |||
| draw_prim.c \ | |||
| draw_pstipple.c \ | |||
| draw_stipple.c \ | |||
| @@ -14,9 +14,9 @@ draw = env.ConvenienceLibrary( | |||
| 'draw_debug.c', | |||
| 'draw_flatshade.c', | |||
| 'draw_offset.c', | |||
| 'draw_passthrough.c', | |||
| 'draw_prim.c', | |||
| 'draw_pstipple.c', | |||
| 'draw_passthrough.c', | |||
| 'draw_stipple.c', | |||
| 'draw_twoside.c', | |||
| 'draw_unfilled.c', | |||
| @@ -340,12 +340,6 @@ generate_aaline_fs(struct aaline_stage *aaline) | |||
| tgsi_dump(aaline_fs.tokens, 0); | |||
| #endif | |||
| #if 1 /* XXX remove */ | |||
| 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++; | |||
| #endif | |||
| aaline->fs->aaline_fs | |||
| = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs); | |||
| @@ -514,12 +514,6 @@ generate_aapoint_fs(struct aapoint_stage *aapoint) | |||
| tgsi_dump(aapoint_fs.tokens, 0); | |||
| #endif | |||
| #if 1 /* XXX remove */ | |||
| 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++; | |||
| #endif | |||
| aapoint->fs->aapoint_fs | |||
| = aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs); | |||
| @@ -85,6 +85,8 @@ struct draw_context *draw_create( void ) | |||
| /* these defaults are oriented toward the needs of softpipe */ | |||
| draw->wide_point_threshold = 1000000.0; /* infinity */ | |||
| draw->wide_line_threshold = 1.0; | |||
| draw->line_stipple = TRUE; | |||
| draw->point_sprite = TRUE; | |||
| draw->reduced_prim = ~0; /* != any of PIPE_PRIM_x */ | |||
| @@ -254,6 +256,28 @@ draw_wide_line_threshold(struct draw_context *draw, float threshold) | |||
| } | |||
| /** | |||
| * Tells the draw module whether or not to implement line stipple. | |||
| */ | |||
| void | |||
| draw_enable_line_stipple(struct draw_context *draw, boolean enable) | |||
| { | |||
| draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); | |||
| draw->line_stipple = enable; | |||
| } | |||
| /** | |||
| * Tells draw module whether to convert points to quads for sprite mode. | |||
| */ | |||
| void | |||
| draw_enable_point_sprites(struct draw_context *draw, boolean enable) | |||
| { | |||
| draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); | |||
| draw->point_sprite = enable; | |||
| } | |||
| /** | |||
| * Ask the draw module for the location/slot of the given vertex attribute in | |||
| * a post-transformed vertex. | |||
| @@ -299,7 +323,7 @@ uint | |||
| draw_num_vs_outputs(struct draw_context *draw) | |||
| { | |||
| uint count = draw->vertex_shader->info.num_outputs; | |||
| if (draw->extra_vp_outputs.slot >= 0) | |||
| if (draw->extra_vp_outputs.slot > 0) | |||
| count++; | |||
| return count; | |||
| } | |||
| @@ -94,6 +94,11 @@ void draw_wide_point_threshold(struct draw_context *draw, float threshold); | |||
| void draw_wide_line_threshold(struct draw_context *draw, float threshold); | |||
| void draw_enable_line_stipple(struct draw_context *draw, boolean enable); | |||
| void draw_enable_point_sprites(struct draw_context *draw, boolean enable); | |||
| boolean draw_use_sse(struct draw_context *draw); | |||
| void | |||
| @@ -66,6 +66,95 @@ | |||
| #include "draw/draw_vertex.h" | |||
| /** | |||
| * General-purpose fetch from user's vertex arrays, emit to driver's | |||
| * vertex buffer. | |||
| * | |||
| * XXX this is totally temporary. | |||
| */ | |||
| static void | |||
| fetch_store_general( struct draw_context *draw, | |||
| float *out, | |||
| unsigned start, | |||
| unsigned count ) | |||
| { | |||
| const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render); | |||
| const unsigned nr_attrs = vinfo->num_attribs; | |||
| uint i, j; | |||
| const unsigned *pitch = draw->vertex_fetch.pitch; | |||
| const ubyte **src = draw->vertex_fetch.src_ptr; | |||
| for (i = start; i < count; i++) { | |||
| for (j = 0; j < nr_attrs; j++) { | |||
| const uint jj = vinfo->src_index[j]; | |||
| const enum pipe_format srcFormat = draw->vertex_element[jj].src_format; | |||
| const ubyte *from = src[jj] + i * pitch[jj]; | |||
| float attrib[4]; | |||
| switch (srcFormat) { | |||
| case PIPE_FORMAT_R32G32B32A32_FLOAT: | |||
| { | |||
| float *f = (float *) from; | |||
| attrib[0] = f[0]; | |||
| attrib[1] = f[1]; | |||
| attrib[2] = f[2]; | |||
| attrib[3] = f[3]; | |||
| } | |||
| break; | |||
| case PIPE_FORMAT_R32G32B32_FLOAT: | |||
| { | |||
| float *f = (float *) from; | |||
| attrib[0] = f[0]; | |||
| attrib[1] = f[1]; | |||
| attrib[2] = f[2]; | |||
| attrib[3] = 1.0; | |||
| } | |||
| break; | |||
| case PIPE_FORMAT_R32G32_FLOAT: | |||
| { | |||
| float *f = (float *) from; | |||
| attrib[0] = f[0]; | |||
| attrib[1] = f[1]; | |||
| attrib[2] = 0.0; | |||
| attrib[3] = 1.0; | |||
| } | |||
| break; | |||
| case PIPE_FORMAT_R32_FLOAT: | |||
| { | |||
| float *f = (float *) from; | |||
| attrib[0] = f[0]; | |||
| attrib[1] = 0.0; | |||
| attrib[2] = 0.0; | |||
| attrib[3] = 1.0; | |||
| } | |||
| break; | |||
| default: | |||
| abort(); | |||
| } | |||
| /* XXX this will probably only work for softpipe */ | |||
| switch (vinfo->emit[j]) { | |||
| case EMIT_HEADER: | |||
| memset(out, 0, sizeof(struct vertex_header)); | |||
| out += sizeof(struct vertex_header) / 4; | |||
| break; | |||
| case EMIT_4F: | |||
| out[0] = attrib[0]; | |||
| out[1] = attrib[1]; | |||
| out[2] = attrib[2]; | |||
| out[3] = attrib[3]; | |||
| out += 4; | |||
| break; | |||
| default: | |||
| abort(); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* Example of a fetch/emit passthrough shader which could be | |||
| * generated when bypass_clipping is enabled on a passthrough vertex | |||
| @@ -116,7 +205,6 @@ static void fetch_xyz_rgb_st( struct draw_context *draw, | |||
| } | |||
| } | |||
| static boolean update_shader( struct draw_context *draw ) | |||
| { | |||
| const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render); | |||
| @@ -143,11 +231,15 @@ static boolean update_shader( struct draw_context *draw ) | |||
| /* Just trying to figure out how this would work: | |||
| */ | |||
| if (nr_attrs == 3 && | |||
| 0 /* some other tests */) | |||
| if (draw->rasterizer->bypass_vs || | |||
| (nr_attrs == 3 && 0 /* some other tests */)) | |||
| { | |||
| #if 0 | |||
| draw->vertex_fetch.pt_fetch = fetch_xyz_rgb_st; | |||
| assert(vinfo->size == 10); | |||
| #else | |||
| draw->vertex_fetch.pt_fetch = fetch_store_general; | |||
| #endif | |||
| /*assert(vinfo->size == 10);*/ | |||
| return TRUE; | |||
| } | |||
| @@ -175,7 +267,6 @@ static boolean set_prim( struct draw_context *draw, | |||
| } | |||
| boolean | |||
| draw_passthrough_arrays(struct draw_context *draw, | |||
| unsigned prim, | |||
| @@ -184,10 +275,13 @@ draw_passthrough_arrays(struct draw_context *draw, | |||
| { | |||
| float *hw_verts; | |||
| if (draw_need_pipeline(draw)) | |||
| return FALSE; | |||
| if (!set_prim(draw, prim)) | |||
| return FALSE; | |||
| if (!update_shader( draw )) | |||
| if (!update_shader(draw)) | |||
| return FALSE; | |||
| hw_verts = draw->render->allocate_vertices( draw->render, | |||
| @@ -31,6 +31,7 @@ | |||
| */ | |||
| #include "pipe/p_debug.h" | |||
| #include "pipe/p_util.h" | |||
| #include "draw_private.h" | |||
| #include "draw_context.h" | |||
| @@ -118,7 +119,42 @@ static void draw_prim_queue_flush( struct draw_context *draw ) | |||
| draw_vertex_cache_unreference( draw ); | |||
| } | |||
| static INLINE void fetch_and_store(struct draw_context *draw) | |||
| { | |||
| /* run vertex shader on vertex cache entries, four per invokation */ | |||
| #if 0 | |||
| { | |||
| const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render); | |||
| memcpy(draw->vs.queue[0].vertex, draw->vs.queue[i + j].elt, | |||
| count * vinfo->size); | |||
| } | |||
| #elif 0 | |||
| unsigned i; | |||
| draw_update_vertex_fetch(draw); | |||
| for (i = 0; i < draw->vs.queue_nr; i += 4) { | |||
| struct vertex_header *dests[4]; | |||
| unsigned elts[4]; | |||
| struct tgsi_exec_machine *machine = &draw->machine; | |||
| int j, n = MIN2(4, draw->vs.queue_nr - i); | |||
| for (j = 0; j < n; j++) { | |||
| elts[j] = draw->vs.queue[i + j].elt; | |||
| dests[j] = draw->vs.queue[i + j].vertex; | |||
| } | |||
| for ( ; j < 4; j++) { | |||
| elts[j] = elts[0]; | |||
| dests[j] = draw->vs.queue[i + j].vertex; | |||
| } | |||
| //fetch directly into dests | |||
| draw->vertex_fetch.fetch_func(draw, machine, dests, count); | |||
| } | |||
| #endif | |||
| draw->vs.post_nr = draw->vs.queue_nr; | |||
| draw->vs.queue_nr = 0; | |||
| } | |||
| void draw_do_flush( struct draw_context *draw, unsigned flags ) | |||
| { | |||
| @@ -134,7 +170,10 @@ void draw_do_flush( struct draw_context *draw, unsigned flags ) | |||
| if (flags >= DRAW_FLUSH_SHADER_QUEUE) { | |||
| if (draw->vs.queue_nr) | |||
| (*draw->shader_queue_flush)(draw); | |||
| if (draw->rasterizer->bypass_vs) | |||
| fetch_and_store(draw); | |||
| else | |||
| (*draw->shader_queue_flush)(draw); | |||
| if (flags >= DRAW_FLUSH_PRIM_QUEUE) { | |||
| if (draw->pq.queue_nr) | |||
| @@ -485,7 +524,11 @@ draw_arrays(struct draw_context *draw, unsigned prim, | |||
| } | |||
| /* drawing done here: */ | |||
| draw_prim(draw, prim, start, count); | |||
| if (!draw->rasterizer->bypass_vs || | |||
| !draw_passthrough_arrays(draw, prim, start, count)) { | |||
| /* we have to run the whole pipeline */ | |||
| draw_prim(draw, prim, start, count); | |||
| } | |||
| } | |||
| @@ -238,6 +238,8 @@ struct draw_context | |||
| float wide_point_threshold; /**< convert pnts to tris if larger than this */ | |||
| float wide_line_threshold; /**< convert lines to tris if wider than this */ | |||
| boolean line_stipple; /**< do line stipple? */ | |||
| boolean point_sprite; /**< convert points to quads for sprites? */ | |||
| boolean use_sse; | |||
| /* If a prim stage introduces new vertex attributes, they'll be stored here | |||
| @@ -344,10 +346,10 @@ extern void draw_vertex_cache_reset_vertex_ids( struct draw_context *draw ); | |||
| extern void draw_vertex_shader_queue_flush( struct draw_context *draw ); | |||
| struct tgsi_exec_machine; | |||
| extern void draw_update_vertex_fetch( struct draw_context *draw ); | |||
| extern boolean draw_need_pipeline(const struct draw_context *draw); | |||
| /* Prototype/hack | |||
| */ | |||
| @@ -324,21 +324,13 @@ generate_pstip_fs(struct pstip_stage *pstip) | |||
| (struct tgsi_token *) pstip_fs.tokens, | |||
| MAX, &transform.base); | |||
| #if 1 /* DEBUG */ | |||
| #if 0 /* DEBUG */ | |||
| tgsi_dump(orig_fs->tokens, 0); | |||
| tgsi_dump(pstip_fs.tokens, 0); | |||
| #endif | |||
| pstip->sampler_unit = transform.maxSampler + 1; | |||
| #if 1 /* XXX remove */ | |||
| 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] = (ubyte)transform.maxInput; | |||
| pstip_fs.num_inputs++; | |||
| } | |||
| #endif | |||
| pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs); | |||
| } | |||
| @@ -488,16 +480,16 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header) | |||
| struct pipe_context *pipe = pstip->pipe; | |||
| uint num_samplers; | |||
| /* how many samplers? */ | |||
| /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ | |||
| num_samplers = MAX2(pstip->num_textures, pstip->num_samplers); | |||
| num_samplers = MAX2(num_samplers, pstip->sampler_unit + 1); | |||
| assert(stage->draw->rasterizer->poly_stipple_enable); | |||
| /* bind our fragprog */ | |||
| bind_pstip_fragment_shader(pstip); | |||
| /* how many samplers? */ | |||
| /* we'll use sampler/texture[pstip->sampler_unit] for the stipple */ | |||
| num_samplers = MAX2(pstip->num_textures, pstip->num_samplers); | |||
| num_samplers = MAX2(num_samplers, pstip->sampler_unit + 1); | |||
| /* plug in our sampler, texture */ | |||
| pstip->state.samplers[pstip->sampler_unit] = pstip->sampler_cso; | |||
| pstip->state.textures[pstip->sampler_unit] = pstip->texture; | |||
| @@ -33,6 +33,63 @@ | |||
| #include "draw_private.h" | |||
| /** | |||
| * Check if we need any special pipeline stages, or whether prims/verts | |||
| * can go through untouched. | |||
| */ | |||
| boolean | |||
| draw_need_pipeline(const struct draw_context *draw) | |||
| { | |||
| /* clipping */ | |||
| if (!draw->rasterizer->bypass_clipping) | |||
| return TRUE; | |||
| /* vertex shader */ | |||
| if (!draw->rasterizer->bypass_vs) | |||
| return TRUE; | |||
| /* line stipple */ | |||
| if (draw->rasterizer->line_stipple_enable && draw->line_stipple) | |||
| return TRUE; | |||
| /* wide lines */ | |||
| if (draw->rasterizer->line_width > draw->wide_line_threshold) | |||
| return TRUE; | |||
| /* large points */ | |||
| if (draw->rasterizer->point_size > draw->wide_point_threshold) | |||
| return TRUE; | |||
| /* AA lines */ | |||
| if (draw->rasterizer->line_smooth && draw->pipeline.aaline) | |||
| return TRUE; | |||
| /* AA points */ | |||
| if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) | |||
| return TRUE; | |||
| /* polygon stipple */ | |||
| if (draw->rasterizer->poly_stipple_enable && draw->pipeline.pstipple) | |||
| return TRUE; | |||
| /* polygon offset */ | |||
| if (draw->rasterizer->offset_cw || draw->rasterizer->offset_ccw) | |||
| return TRUE; | |||
| /* point sprites */ | |||
| if (draw->rasterizer->point_sprite && draw->point_sprite) | |||
| return TRUE; | |||
| /* two-side lighting */ | |||
| if (draw->rasterizer->light_twoside) | |||
| return TRUE; | |||
| /* polygon cull */ | |||
| if (draw->rasterizer->cull_mode) | |||
| return TRUE; | |||
| return FALSE; | |||
| } | |||
| @@ -57,7 +114,9 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) | |||
| && !draw->rasterizer->line_smooth); | |||
| /* drawing large points? */ | |||
| if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) | |||
| if (draw->rasterizer->point_sprite && draw->point_sprite) | |||
| wide_points = TRUE; | |||
| else if (draw->rasterizer->point_smooth && draw->pipeline.aapoint) | |||
| wide_points = FALSE; | |||
| else if (draw->rasterizer->point_size > draw->wide_point_threshold) | |||
| wide_points = TRUE; | |||
| @@ -92,7 +151,7 @@ static struct draw_stage *validate_pipeline( struct draw_stage *stage ) | |||
| next = draw->pipeline.wide_point; | |||
| } | |||
| if (draw->rasterizer->line_stipple_enable) { | |||
| if (draw->rasterizer->line_stipple_enable && draw->line_stipple) { | |||
| draw->pipeline.stipple->next = next; | |||
| next = draw->pipeline.stipple; | |||
| precalc_flat = 1; /* only needed for lines really */ | |||
| @@ -225,6 +225,11 @@ emit_vertex( struct vbuf_stage *vbuf, | |||
| vbuf->vertex_ptr += vinfo->size; | |||
| count += vinfo->size; | |||
| break; | |||
| case EMIT_HEADER: | |||
| memcpy(vbuf->vertex_ptr, vertex, sizeof(*vertex)); | |||
| *vbuf->vertex_ptr += sizeof(*vertex) / 4; | |||
| count += sizeof(*vertex) / 4; | |||
| break; | |||
| case EMIT_1F: | |||
| *vbuf->vertex_ptr++ = fui(vertex->data[j][0]); | |||
| count++; | |||
| @@ -52,6 +52,9 @@ draw_compute_vertex_size(struct vertex_info *vinfo) | |||
| switch (vinfo->emit[i]) { | |||
| case EMIT_OMIT: | |||
| break; | |||
| case EMIT_HEADER: | |||
| vinfo->size += sizeof(struct vertex_header) / 4; | |||
| break; | |||
| case EMIT_4UB: | |||
| /* fall-through */ | |||
| case EMIT_1F_PSIZE: | |||
| @@ -48,6 +48,7 @@ | |||
| enum attrib_emit { | |||
| EMIT_OMIT, /**< don't emit the attribute */ | |||
| EMIT_ALL, /**< emit whole post-xform vertex, w/ header */ | |||
| EMIT_HEADER, /**< emit vertex_header struct (XXX temp?) */ | |||
| EMIT_1F, | |||
| EMIT_1F_PSIZE, /**< insert constant point size */ | |||
| EMIT_2F, | |||
| @@ -263,6 +263,14 @@ void draw_vf_set_vertex_info( struct draw_vertex_fetch *vf, | |||
| } | |||
| break; | |||
| } | |||
| case EMIT_HEADER: | |||
| /* XXX emit new DRAW_EMIT_HEADER attribute??? */ | |||
| attrs[nr_attrs].attrib = 0; | |||
| attrs[nr_attrs].format = DRAW_EMIT_PAD; | |||
| attrs[nr_attrs].offset = offsetof(struct vertex_header, data); | |||
| count += offsetof(struct vertex_header, data)/4; | |||
| nr_attrs++; | |||
| break; | |||
| case EMIT_1F: | |||
| attrs[nr_attrs].attrib = j; | |||
| attrs[nr_attrs].format = DRAW_EMIT_1F; | |||
| @@ -166,6 +166,19 @@ vs_exec_run( struct draw_vertex_shader *shader, | |||
| vOut[j]->data[slot][2] = machine->Outputs[slot].xyzw[2].f[j]; | |||
| vOut[j]->data[slot][3] = machine->Outputs[slot].xyzw[3].f[j]; | |||
| } | |||
| #if 0 /*DEBUG*/ | |||
| printf("Post xform vert:\n"); | |||
| for (slot = 0; slot < draw->num_vs_outputs; slot++) { | |||
| printf("%d: %f %f %f %f\n", slot, | |||
| vOut[j]->data[slot][0], | |||
| vOut[j]->data[slot][1], | |||
| vOut[j]->data[slot][2], | |||
| vOut[j]->data[slot][3]); | |||
| } | |||
| #endif | |||
| } /* loop over vertices */ | |||
| } | |||
| @@ -184,7 +184,8 @@ static void widepoint_first_point( struct draw_stage *stage, | |||
| wide->half_point_size = 0.5f * draw->rasterizer->point_size; | |||
| /* XXX we won't know the real size if it's computed by the vertex shader! */ | |||
| if (draw->rasterizer->point_size > draw->wide_point_threshold) { | |||
| if ((draw->rasterizer->point_size > draw->wide_point_threshold) || | |||
| (draw->rasterizer->point_sprite && draw->point_sprite)) { | |||
| stage->point = widepoint_point; | |||
| } | |||
| else { | |||
| @@ -143,8 +143,16 @@ std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector) | |||
| void InstructionsSoa::createFunctionMap() | |||
| { | |||
| m_functionsMap[TGSI_OPCODE_DP3] = "dp3"; | |||
| m_functionsMap[TGSI_OPCODE_DP4] = "dp4"; | |||
| m_functionsMap[TGSI_OPCODE_DP3] = "dp3"; | |||
| m_functionsMap[TGSI_OPCODE_DP4] = "dp4"; | |||
| m_functionsMap[TGSI_OPCODE_POWER] = "pow"; | |||
| } | |||
| void InstructionsSoa::createDependencies() | |||
| { | |||
| std::vector<std::string> powDeps(1); | |||
| powDeps[0] = "powf"; | |||
| m_builtinDependencies["pow"] = powDeps; | |||
| } | |||
| llvm::Function * InstructionsSoa::function(int op) | |||
| @@ -154,15 +162,14 @@ llvm::Function * InstructionsSoa::function(int op) | |||
| std::string name = m_functionsMap[op]; | |||
| std::vector<std::string> deps = m_builtinDependencies[name]; | |||
| for (unsigned int i = 0; i < deps.size(); ++i) { | |||
| injectFunction(m_builtins->getFunction(deps[i])); | |||
| } | |||
| llvm::Function *originalFunc = m_builtins->getFunction(name); | |||
| llvm::Function *func = CloneFunction(originalFunc); | |||
| currentModule()->getFunctionList().push_back(func); | |||
| std::cout << "Func parent is "<<func->getParent() | |||
| <<", cur is "<<currentModule() <<std::endl; | |||
| func->dump(); | |||
| //func->setParent(currentModule()); | |||
| m_functions[op] = func; | |||
| return func; | |||
| injectFunction(originalFunc, op); | |||
| return m_functions[op]; | |||
| } | |||
| llvm::Module * InstructionsSoa::currentModule() const | |||
| @@ -177,6 +184,7 @@ llvm::Module * InstructionsSoa::currentModule() const | |||
| void InstructionsSoa::createBuiltins() | |||
| { | |||
| m_builtins = createSoaBuiltins(); | |||
| createDependencies(); | |||
| } | |||
| std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1, | |||
| @@ -304,3 +312,71 @@ std::vector<Value*> InstructionsSoa::callBuiltin(llvm::Function *func, const std | |||
| return allocaToResult(allocaPtr); | |||
| } | |||
| std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> in1, | |||
| const std::vector<llvm::Value*> in2) | |||
| { | |||
| llvm::Function *func = function(TGSI_OPCODE_POWER); | |||
| return callBuiltin(func, in1, in2); | |||
| } | |||
| void checkFunction(Function *func) | |||
| { | |||
| for (Function::const_iterator BI = func->begin(), BE = func->end(); | |||
| BI != BE; ++BI) { | |||
| const BasicBlock &BB = *BI; | |||
| for (BasicBlock::const_iterator II = BB.begin(), IE = BB.end(); | |||
| II != IE; ++II) { | |||
| const Instruction &I = *II; | |||
| std::cout<< "Instr = "<<I; | |||
| for (unsigned op = 0, E = I.getNumOperands(); op != E; ++op) { | |||
| const Value *Op = I.getOperand(op); | |||
| std::cout<< "\top = "<<Op<<"("<<op<<")"<<std::endl; | |||
| //I->setOperand(op, V); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op) | |||
| { | |||
| assert(originalFunc); | |||
| std::cout << "injecting function originalFunc " <<originalFunc->getName() <<std::endl; | |||
| if (op != TGSI_OPCODE_LAST) { | |||
| /* in this case it's possible the function has been already | |||
| * injected as part of the dependency chain, which gets | |||
| * injected below */ | |||
| llvm::Function *func = currentModule()->getFunction(originalFunc->getName()); | |||
| if (func) { | |||
| m_functions[op] = func; | |||
| return; | |||
| } | |||
| } | |||
| llvm::Function *func = 0; | |||
| if (originalFunc->isDeclaration()) { | |||
| std::cout << "function decleration" <<std::endl; | |||
| func = new Function(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage, | |||
| originalFunc->getName(), currentModule()); | |||
| func->setCallingConv(CallingConv::C); | |||
| const ParamAttrsList *pal = 0; | |||
| func->setParamAttrs(pal); | |||
| currentModule()->dump(); | |||
| } else { | |||
| DenseMap<const Value*, Value *> val; | |||
| val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf"); | |||
| std::cout <<" replacing "<<m_builtins->getFunction("powf") | |||
| <<", with " <<currentModule()->getFunction("powf")<<std::endl; | |||
| func = CloneFunction(originalFunc, val); | |||
| std::cout<<"1111-------------------------------"<<std::endl; | |||
| checkFunction(originalFunc); | |||
| std::cout<<"2222-------------------------------"<<std::endl; | |||
| checkFunction(func); | |||
| std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl; | |||
| currentModule()->getFunctionList().push_back(func); | |||
| std::cout << "Func parent is "<<func->getParent() | |||
| <<", cur is "<<currentModule() <<std::endl; | |||
| } | |||
| if (op != TGSI_OPCODE_LAST) { | |||
| m_functions[op] = func; | |||
| } | |||
| } | |||
| @@ -28,6 +28,7 @@ | |||
| #ifndef INSTRUCTIONSSOA_H | |||
| #define INSTRUCTIONSSOA_H | |||
| #include <pipe/p_shader_tokens.h> | |||
| #include <llvm/Support/LLVMBuilder.h> | |||
| #include <map> | |||
| @@ -59,6 +60,8 @@ public: | |||
| const std::vector<llvm::Value*> in3); | |||
| std::vector<llvm::Value*> mul(const std::vector<llvm::Value*> in1, | |||
| const std::vector<llvm::Value*> in2); | |||
| std::vector<llvm::Value*> pow(const std::vector<llvm::Value*> in1, | |||
| const std::vector<llvm::Value*> in2); | |||
| void end(); | |||
| std::vector<llvm::Value*> extractVector(llvm::Value *vector); | |||
| @@ -68,6 +71,7 @@ private: | |||
| llvm::Value *z, llvm::Value *w); | |||
| void createFunctionMap(); | |||
| void createBuiltins(); | |||
| void createDependencies(); | |||
| llvm::Function *function(int); | |||
| llvm::Module *currentModule() const; | |||
| llvm::Value *allocaTemp(); | |||
| @@ -81,6 +85,7 @@ private: | |||
| const std::vector<llvm::Value*> in1, | |||
| const std::vector<llvm::Value*> in2, | |||
| const std::vector<llvm::Value*> in3); | |||
| void injectFunction(llvm::Function *originalFunc, int op = TGSI_OPCODE_LAST); | |||
| private: | |||
| llvm::LLVMFoldingBuilder m_builder; | |||
| StorageSoa *m_storage; | |||
| @@ -88,6 +93,7 @@ private: | |||
| std::map<int, std::string> m_functionsMap; | |||
| std::map<int, llvm::Function*> m_functions; | |||
| llvm::Module *m_builtins; | |||
| std::map<std::string, std::vector<std::string> > m_builtinDependencies; | |||
| private: | |||
| mutable int m_idx; | |||
| @@ -60,6 +60,24 @@ void dp4(float4 *res, | |||
| res[3] = dot; | |||
| } | |||
| extern float powf(float num, float p); | |||
| void pow(float4 *res, | |||
| float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w, | |||
| float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w) | |||
| { | |||
| float4 p; | |||
| p.x = powf(tmp0x.x, tmp1x.x); | |||
| p.y = powf(tmp0x.y, tmp1x.y); | |||
| p.z = powf(tmp0x.z, tmp1x.z); | |||
| p.w = powf(tmp0x.w, tmp1x.w); | |||
| res[0] = p; | |||
| res[1] = p; | |||
| res[2] = p; | |||
| res[3] = p; | |||
| } | |||
| #if 0 | |||
| void yo(float4 *out, float4 *in) | |||
| { | |||
| @@ -588,40 +588,6 @@ translate_instruction(llvm::Module *module, | |||
| break; | |||
| case TGSI_OPCODE_NOP: | |||
| break; | |||
| case TGSI_OPCODE_TEXBEM: | |||
| break; | |||
| case TGSI_OPCODE_TEXBEML: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2AR: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2PAD: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3PAD: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3SPEC: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3VSPEC: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2GB: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2RGB: | |||
| break; | |||
| case TGSI_OPCODE_TEXDP3TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXDP3: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2DEPTH: | |||
| break; | |||
| case TGSI_OPCODE_TEXDEPTH: | |||
| break; | |||
| case TGSI_OPCODE_BEM: | |||
| break; | |||
| case TGSI_OPCODE_M4X3: | |||
| break; | |||
| case TGSI_OPCODE_M3X4: | |||
| @@ -806,6 +772,7 @@ translate_instructionir(llvm::Module *module, | |||
| } | |||
| break; | |||
| case TGSI_OPCODE_POWER: { | |||
| out = instr->pow(inputs[0], inputs[1]); | |||
| } | |||
| break; | |||
| case TGSI_OPCODE_CROSSPRODUCT: { | |||
| @@ -980,40 +947,6 @@ translate_instructionir(llvm::Module *module, | |||
| break; | |||
| case TGSI_OPCODE_NOP: | |||
| break; | |||
| case TGSI_OPCODE_TEXBEM: | |||
| break; | |||
| case TGSI_OPCODE_TEXBEML: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2AR: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2PAD: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3PAD: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3SPEC: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3VSPEC: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2GB: | |||
| break; | |||
| case TGSI_OPCODE_TEXREG2RGB: | |||
| break; | |||
| case TGSI_OPCODE_TEXDP3TEX: | |||
| break; | |||
| case TGSI_OPCODE_TEXDP3: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X3: | |||
| break; | |||
| case TGSI_OPCODE_TEXM3X2DEPTH: | |||
| break; | |||
| case TGSI_OPCODE_TEXDEPTH: | |||
| break; | |||
| case TGSI_OPCODE_BEM: | |||
| break; | |||
| case TGSI_OPCODE_M4X3: | |||
| break; | |||
| case TGSI_OPCODE_M3X4: | |||
| @@ -1516,11 +1516,41 @@ exec_instruction( | |||
| break; | |||
| case TGSI_OPCODE_EXP: | |||
| assert (0); | |||
| debug_printf("TGSI: EXP opcode not implemented\n"); | |||
| /* from ARB_v_p: | |||
| tmp = ScalarLoad(op0); | |||
| result.x = 2^floor(tmp); | |||
| result.y = tmp - floor(tmp); | |||
| result.z = RoughApprox2ToX(tmp); | |||
| result.w = 1.0; | |||
| */ | |||
| #if 0 | |||
| /* something like this: */ | |||
| FETCH( &r[0], 0, CHAN_X ); | |||
| micro_exp2( &r[0], &r[0] ); | |||
| FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | |||
| STORE( &r[0], 0, chan_index ); | |||
| } | |||
| #endif | |||
| break; | |||
| case TGSI_OPCODE_LOG: | |||
| assert (0); | |||
| debug_printf("TGSI: LOG opcode not implemented\n"); | |||
| /* from ARB_v_p: | |||
| tmp = fabs(ScalarLoad(op0)); | |||
| result.x = floor(log2(tmp)); | |||
| result.y = tmp / 2^(floor(log2(tmp))); | |||
| result.z = RoughApproxLog2(tmp); | |||
| result.w = 1.0; | |||
| */ | |||
| #if 0 | |||
| /* something like this: */ | |||
| FETCH( &r[0], 0, CHAN_X ); | |||
| micro_lg2( &r[0], &r[0] ); | |||
| FOR_EACH_ENABLED_CHANNEL( *inst, chan_index ) { | |||
| STORE( &r[0], 0, chan_index ); | |||
| } | |||
| #endif | |||
| break; | |||
| case TGSI_OPCODE_MUL: | |||
| @@ -1821,7 +1821,11 @@ emit_instruction( | |||
| STORE( func, *inst, 5, 0, CHAN_Z ); | |||
| } | |||
| IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) { | |||
| FETCH( func, *inst, 0, TGSI_EXEC_TEMP_ONE_I, TGSI_EXEC_TEMP_ONE_C ); | |||
| emit_tempf( | |||
| func, | |||
| 0, | |||
| TGSI_EXEC_TEMP_ONE_I, | |||
| TGSI_EXEC_TEMP_ONE_C ); | |||
| STORE( func, *inst, 0, 0, CHAN_W ); | |||
| } | |||
| break; | |||
| @@ -2021,11 +2025,19 @@ emit_instruction( | |||
| STORE( func, *inst, 0, 0, CHAN_Y ); | |||
| } | |||
| IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_Z ) { | |||
| FETCH( func, *inst, 0, TGSI_EXEC_TEMP_00000000_I, TGSI_EXEC_TEMP_00000000_C ); | |||
| emit_tempf( | |||
| func, | |||
| 0, | |||
| TGSI_EXEC_TEMP_00000000_I, | |||
| TGSI_EXEC_TEMP_00000000_C ); | |||
| STORE( func, *inst, 0, 0, CHAN_Z ); | |||
| } | |||
| IF_IS_DST0_CHANNEL_ENABLED( *inst, CHAN_W ) { | |||
| FETCH( func, *inst, 0, TGSI_EXEC_TEMP_ONE_I, TGSI_EXEC_TEMP_ONE_C ); | |||
| emit_tempf( | |||
| func, | |||
| 0, | |||
| TGSI_EXEC_TEMP_ONE_I, | |||
| TGSI_EXEC_TEMP_ONE_C ); | |||
| STORE( func, *inst, 0, 0, CHAN_W ); | |||
| } | |||
| break; | |||
| @@ -324,7 +324,7 @@ static const char *TGSI_IMMS_SHORT[] = | |||
| "FLT32" | |||
| }; | |||
| static const char *TGSI_OPCODES[] = | |||
| static const char *TGSI_OPCODES[TGSI_OPCODE_LAST] = | |||
| { | |||
| "OPCODE_ARL", | |||
| "OPCODE_MOV", | |||
| @@ -380,6 +380,7 @@ static const char *TGSI_OPCODES[] = | |||
| "OPCODE_STR", | |||
| "OPCODE_TEX", | |||
| "OPCODE_TXD", | |||
| "OPCODE_TXP", | |||
| "OPCODE_UP2H", | |||
| "OPCODE_UP2US", | |||
| "OPCODE_UP4B", | |||
| @@ -433,23 +434,6 @@ static const char *TGSI_OPCODES[] = | |||
| "OPCODE_NOISE3", | |||
| "OPCODE_NOISE4", | |||
| "OPCODE_NOP", | |||
| "OPCODE_TEXBEM", | |||
| "OPCODE_TEXBEML", | |||
| "OPCODE_TEXREG2AR", | |||
| "OPCODE_TEXM3X2PAD", | |||
| "OPCODE_TEXM3X2TEX", | |||
| "OPCODE_TEXM3X3PAD", | |||
| "OPCODE_TEXM3X3TEX", | |||
| "OPCODE_TEXM3X3SPEC", | |||
| "OPCODE_TEXM3X3VSPEC", | |||
| "OPCODE_TEXREG2GB", | |||
| "OPCODE_TEXREG2RGB", | |||
| "OPCODE_TEXDP3TEX", | |||
| "OPCODE_TEXDP3", | |||
| "OPCODE_TEXM3X3", | |||
| "OPCODE_TEXM3X2DEPTH", | |||
| "OPCODE_TEXDEPTH", | |||
| "OPCODE_BEM", | |||
| "OPCODE_M4X3", | |||
| "OPCODE_M3X4", | |||
| "OPCODE_M3X3", | |||
| @@ -459,11 +443,10 @@ static const char *TGSI_OPCODES[] = | |||
| "OPCODE_IFC", | |||
| "OPCODE_BREAKC", | |||
| "OPCODE_KIL", | |||
| "OPCODE_END", | |||
| "OPCODE_TXP" | |||
| "OPCODE_END" | |||
| }; | |||
| static const char *TGSI_OPCODES_SHORT[] = | |||
| static const char *TGSI_OPCODES_SHORT[TGSI_OPCODE_LAST] = | |||
| { | |||
| "ARL", | |||
| "MOV", | |||
| @@ -519,6 +502,7 @@ static const char *TGSI_OPCODES_SHORT[] = | |||
| "STR", | |||
| "TEX", | |||
| "TXD", | |||
| "TXP", | |||
| "UP2H", | |||
| "UP2US", | |||
| "UP4B", | |||
| @@ -572,23 +556,6 @@ static const char *TGSI_OPCODES_SHORT[] = | |||
| "NOISE3", | |||
| "NOISE4", | |||
| "NOP", | |||
| "TEXBEM", | |||
| "TEXBEML", | |||
| "TEXREG2AR", | |||
| "TEXM3X2PAD", | |||
| "TEXM3X2TEX", | |||
| "TEXM3X3PAD", | |||
| "TEXM3X3TEX", | |||
| "TEXM3X3SPEC", | |||
| "TEXM3X3VSPEC", | |||
| "TEXREG2GB", | |||
| "TEXREG2RGB", | |||
| "TEXDP3TEX", | |||
| "TEXDP3", | |||
| "TEXM3X3", | |||
| "TEXM3X2DEPTH", | |||
| "TEXDEPTH", | |||
| "BEM", | |||
| "M4X3", | |||
| "M3X4", | |||
| "M3X3", | |||
| @@ -598,8 +565,7 @@ static const char *TGSI_OPCODES_SHORT[] = | |||
| "IFC", | |||
| "BREAKC", | |||
| "KIL", | |||
| "END", | |||
| "TXP" | |||
| "END" | |||
| }; | |||
| static const char *TGSI_SATS[] = | |||
| @@ -1597,3 +1563,25 @@ tgsi_dump_str( | |||
| *str = dump.text; | |||
| } | |||
| void tgsi_debug_dump( struct tgsi_token *tokens ) | |||
| { | |||
| char *str, *p; | |||
| tgsi_dump_str( &str, tokens, 0 ); | |||
| p = str; | |||
| while (p != NULL) | |||
| { | |||
| char *end = strchr( p, '\n' ); | |||
| if (end != NULL) | |||
| { | |||
| *end++ = '\0'; | |||
| } | |||
| debug_printf( "%s\n", p ); | |||
| p = end; | |||
| } | |||
| FREE( str ); | |||
| } | |||
| @@ -20,6 +20,10 @@ tgsi_dump_str( | |||
| const struct tgsi_token *tokens, | |||
| unsigned flags ); | |||
| /* Dump to debug_printf() | |||
| */ | |||
| void tgsi_debug_dump( struct tgsi_token *tokens ); | |||
| #if defined __cplusplus | |||
| } | |||
| #endif | |||
| @@ -56,7 +56,7 @@ struct tgsi_full_immediate | |||
| }; | |||
| #define TGSI_FULL_MAX_DST_REGISTERS 2 | |||
| #define TGSI_FULL_MAX_SRC_REGISTERS 3 | |||
| #define TGSI_FULL_MAX_SRC_REGISTERS 4 /* TXD has 4 */ | |||
| struct tgsi_full_instruction | |||
| { | |||
| @@ -8,6 +8,7 @@ C_SOURCES = \ | |||
| p_tile.c \ | |||
| p_util.c \ | |||
| u_handle_table.c \ | |||
| u_hash_table.c \ | |||
| u_mm.c \ | |||
| u_snprintf.c | |||
| @@ -7,6 +7,7 @@ util = env.ConvenienceLibrary( | |||
| 'p_tile.c', | |||
| 'p_util.c', | |||
| 'u_handle_table.c', | |||
| 'u_hash_table.c', | |||
| 'u_mm.c', | |||
| 'u_snprintf.c', | |||
| ]) | |||
| @@ -109,20 +109,30 @@ enum { | |||
| /* Check for aborts enabled. */ | |||
| static unsigned abort_en() | |||
| { | |||
| if (!mapped_config_file) | |||
| { | |||
| /* Open an 8 byte file for configuration data. */ | |||
| mapped_config_file = EngMapFile(L"\\??\\c:\\gaDebug.cfg", 8, &debug_config_file); | |||
| } | |||
| /* An value of "0" (ascii) in the configuration file will clear the first 8 bits in the test byte. */ | |||
| /* An value of "1" (ascii) in the configuration file will set the first bit in the test byte. */ | |||
| /* An value of "2" (ascii) in the configuration file will set the second bit in the test byte. */ | |||
| return ((((char *)mapped_config_file)[0]) - 0x30) & eAssertAbortEn; | |||
| if (!mapped_config_file) | |||
| { | |||
| /* Open an 8 byte file for configuration data. */ | |||
| mapped_config_file = EngMapFile(L"\\??\\c:\\gaDebug.cfg", 8, &debug_config_file); | |||
| } | |||
| /* A value of "0" (ascii) in the configuration file will clear the | |||
| * first 8 bits in the test byte. | |||
| * | |||
| * A value of "1" (ascii) in the configuration file will set the | |||
| * first bit in the test byte. | |||
| * | |||
| * A value of "2" (ascii) in the configuration file will set the | |||
| * second bit in the test byte. | |||
| * | |||
| * Currently the only interesting values are 0 and 1, which clear | |||
| * and set abort-on-assert behaviour respectively. | |||
| */ | |||
| return ((((char *)mapped_config_file)[0]) - 0x30) & eAssertAbortEn; | |||
| } | |||
| #else /* WIN32 */ | |||
| static unsigned abort_en() | |||
| { | |||
| return !GETENV("GALLIUM_ABORT_ON_ASSERT"); | |||
| return !GETENV("GALLIUM_ABORT_ON_ASSERT"); | |||
| } | |||
| #endif | |||
| @@ -26,6 +26,7 @@ | |||
| **************************************************************************/ | |||
| /** | |||
| * @file | |||
| * Generic handle table implementation. | |||
| * | |||
| * @author José Fonseca <jrfonseca@tungstengraphics.com> | |||
| @@ -90,6 +91,39 @@ handle_table_set_destroy(struct handle_table *ht, | |||
| } | |||
| /** | |||
| * Resize the table if necessary | |||
| */ | |||
| static INLINE int | |||
| handle_table_resize(struct handle_table *ht, | |||
| unsigned minimum_size) | |||
| { | |||
| unsigned new_size; | |||
| void **new_objects; | |||
| if(ht->size > minimum_size) | |||
| return ht->size; | |||
| new_size = ht->size; | |||
| while(!(new_size > minimum_size)) | |||
| new_size *= 2; | |||
| assert(new_size); | |||
| new_objects = (void **)REALLOC((void *)ht->objects, | |||
| ht->size*sizeof(void *), | |||
| new_size*sizeof(void *)); | |||
| if(!new_objects) | |||
| return 0; | |||
| memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *)); | |||
| ht->size = new_size; | |||
| ht->objects = new_objects; | |||
| return ht->size; | |||
| } | |||
| unsigned | |||
| handle_table_add(struct handle_table *ht, | |||
| void *object) | |||
| @@ -109,34 +143,17 @@ handle_table_add(struct handle_table *ht, | |||
| ++ht->filled; | |||
| } | |||
| /* grow the table */ | |||
| if(ht->filled == ht->size) { | |||
| unsigned new_size; | |||
| void **new_objects; | |||
| new_size = ht->size*2; | |||
| assert(new_size); | |||
| new_objects = (void **)REALLOC((void *)ht->objects, | |||
| ht->size*sizeof(void *), | |||
| new_size*sizeof(void *)); | |||
| if(!new_objects) | |||
| return 0; | |||
| memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *)); | |||
| ht->size = new_size; | |||
| ht->objects = new_objects; | |||
| } | |||
| index = ht->filled; | |||
| handle = index + 1; | |||
| /* check integer overflow */ | |||
| if(!handle) | |||
| return 0; | |||
| /* grow the table if necessary */ | |||
| if(!handle_table_resize(ht, index)) | |||
| return 0; | |||
| assert(!ht->objects[index]); | |||
| ht->objects[index] = object; | |||
| ++ht->filled; | |||
| @@ -145,6 +162,36 @@ handle_table_add(struct handle_table *ht, | |||
| } | |||
| unsigned | |||
| handle_table_set(struct handle_table *ht, | |||
| unsigned handle, | |||
| void *object) | |||
| { | |||
| unsigned index; | |||
| assert(ht); | |||
| assert(handle > 0); | |||
| assert(handle <= ht->size); | |||
| if(!handle || handle > ht->size) | |||
| return 0; | |||
| assert(object); | |||
| if(!object) | |||
| return 0; | |||
| index = handle - 1; | |||
| /* grow the table if necessary */ | |||
| if(!handle_table_resize(ht, index)) | |||
| return 0; | |||
| assert(!ht->objects[index]); | |||
| ht->objects[index] = object; | |||
| return handle; | |||
| } | |||
| void * | |||
| handle_table_get(struct handle_table *ht, | |||
| unsigned handle) | |||
| @@ -26,6 +26,7 @@ | |||
| **************************************************************************/ | |||
| /** | |||
| * @file | |||
| * Generic handle table. | |||
| * | |||
| * @author José Fonseca <jrfonseca@tungstengraphics.com> | |||
| @@ -42,6 +43,8 @@ extern "C" { | |||
| /** | |||
| * Abstract data type to map integer handles to objects. | |||
| * | |||
| * Also referred as "pointer array". | |||
| */ | |||
| struct handle_table; | |||
| @@ -70,6 +73,14 @@ unsigned | |||
| handle_table_add(struct handle_table *ht, | |||
| void *object); | |||
| /** | |||
| * Returns zero on failure (out of memory). | |||
| */ | |||
| unsigned | |||
| handle_table_set(struct handle_table *ht, | |||
| unsigned handle, | |||
| void *object); | |||
| /** | |||
| * Fetch an existing object. | |||
| * | |||
| @@ -0,0 +1,199 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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 | |||
| * General purpose hash table implementation. | |||
| * | |||
| * Just uses the cso_hash for now, but it might be better switch to a linear | |||
| * probing hash table implementation at some point -- as it is said they have | |||
| * better lookup and cache performance and it appears to be possible to write | |||
| * a lock-free implementation of such hash tables . | |||
| * | |||
| * @author José Fonseca <jrfonseca@tungstengraphics.com> | |||
| */ | |||
| #include "pipe/p_compiler.h" | |||
| #include "pipe/p_debug.h" | |||
| #include "pipe/p_util.h" | |||
| #include "cso_cache/cso_hash.h" | |||
| #include "u_hash_table.h" | |||
| struct hash_table | |||
| { | |||
| struct cso_hash *cso; | |||
| /** Hash function */ | |||
| unsigned (*hash)(void *key); | |||
| /** Compare two keys */ | |||
| int (*compare)(void *key1, void *key2); | |||
| /* TODO: key, value destructors? */ | |||
| }; | |||
| struct hash_table_item | |||
| { | |||
| void *key; | |||
| void *value; | |||
| }; | |||
| struct hash_table * | |||
| hash_table_create(unsigned (*hash)(void *key), | |||
| int (*compare)(void *key1, void *key2)) | |||
| { | |||
| struct hash_table *ht; | |||
| ht = MALLOC_STRUCT(hash_table); | |||
| if(!ht) | |||
| return NULL; | |||
| ht->cso = cso_hash_create(); | |||
| if(!ht->cso) { | |||
| FREE(ht); | |||
| return NULL; | |||
| } | |||
| ht->hash = hash; | |||
| ht->compare = compare; | |||
| return ht; | |||
| } | |||
| static struct hash_table_item * | |||
| hash_table_find_item(struct hash_table *ht, | |||
| void *key, | |||
| unsigned key_hash) | |||
| { | |||
| struct cso_hash_iter iter; | |||
| struct hash_table_item *item; | |||
| iter = cso_hash_find(ht->cso, key_hash); | |||
| while (!cso_hash_iter_is_null(iter)) { | |||
| item = (struct hash_table_item *)cso_hash_iter_data(iter); | |||
| if (!ht->compare(item->key, key)) | |||
| return item; | |||
| iter = cso_hash_iter_next(iter); | |||
| } | |||
| return NULL; | |||
| } | |||
| enum pipe_error | |||
| hash_table_set(struct hash_table *ht, | |||
| void *key, | |||
| void *value) | |||
| { | |||
| unsigned key_hash; | |||
| struct hash_table_item *item; | |||
| assert(ht); | |||
| key_hash = ht->hash(key); | |||
| item = hash_table_find_item(ht, key, key_hash); | |||
| if(item) { | |||
| /* TODO: key/value destruction? */ | |||
| item->value = value; | |||
| return PIPE_OK; | |||
| } | |||
| item = MALLOC_STRUCT(hash_table_item); | |||
| if(!item) | |||
| return PIPE_ERROR_OUT_OF_MEMORY; | |||
| item->key = key; | |||
| item->value = value; | |||
| cso_hash_insert(ht->cso, key_hash, item); | |||
| /* FIXME: there is no OOM propagation in cso_hash */ | |||
| if(0) { | |||
| FREE(item); | |||
| return PIPE_ERROR_OUT_OF_MEMORY; | |||
| } | |||
| return PIPE_OK; | |||
| } | |||
| void * | |||
| hash_table_get(struct hash_table *ht, | |||
| void *key) | |||
| { | |||
| unsigned key_hash; | |||
| struct hash_table_item *item; | |||
| assert(ht); | |||
| key_hash = ht->hash(key); | |||
| item = hash_table_find_item(ht, key, key_hash); | |||
| if(!item) | |||
| return NULL; | |||
| return item->value; | |||
| } | |||
| void | |||
| hash_table_remove(struct hash_table *ht, | |||
| void *key) | |||
| { | |||
| unsigned key_hash; | |||
| struct hash_table_item *item; | |||
| assert(ht); | |||
| key_hash = ht->hash(key); | |||
| item = hash_table_find_item(ht, key, key_hash); | |||
| if(!item) | |||
| return; | |||
| /* FIXME: cso_hash_take takes the first element of the collision list | |||
| * indiscriminately, so we can not take the item down. */ | |||
| item->value = NULL; | |||
| } | |||
| void | |||
| hash_table_destroy(struct hash_table *ht) | |||
| { | |||
| assert(ht); | |||
| cso_hash_delete(ht->cso); | |||
| FREE(ht); | |||
| } | |||
| @@ -0,0 +1,86 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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. | |||
| * | |||
| **************************************************************************/ | |||
| /** | |||
| * General purpose hash table. | |||
| * | |||
| * @author José Fonseca <jrfonseca@tungstengraphics.com> | |||
| */ | |||
| #ifndef U_HASH_TABLE_H_ | |||
| #define U_HASH_TABLE_H_ | |||
| #include "pipe/p_error.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** | |||
| * Generic purpose hash table. | |||
| */ | |||
| struct hash_table; | |||
| /** | |||
| * Create an hash table. | |||
| * | |||
| * @param hash hash function | |||
| * @param compare should return 0 for two equal keys. | |||
| */ | |||
| struct hash_table * | |||
| hash_table_create(unsigned (*hash)(void *key), | |||
| int (*compare)(void *key1, void *key2)); | |||
| enum pipe_error | |||
| hash_table_set(struct hash_table *ht, | |||
| void *key, | |||
| void *value); | |||
| void * | |||
| hash_table_get(struct hash_table *ht, | |||
| void *key); | |||
| void | |||
| hash_table_remove(struct hash_table *ht, | |||
| void *key); | |||
| void | |||
| hash_table_destroy(struct hash_table *ht); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* U_HASH_TABLE_H_ */ | |||
| @@ -37,13 +37,14 @@ | |||
| #include "cell_winsys.h" | |||
| #include "cell/common.h" | |||
| #include "rtasm/rtasm_ppc_spe.h" | |||
| #include "tgsi/util/tgsi_scan.h" | |||
| struct cell_vbuf_render; | |||
| struct cell_vertex_shader_state | |||
| { | |||
| struct pipe_shader_state shader; | |||
| struct tgsi_shader_info info; | |||
| void *draw_data; | |||
| }; | |||
| @@ -51,6 +52,7 @@ struct cell_vertex_shader_state | |||
| struct cell_fragment_shader_state | |||
| { | |||
| struct pipe_shader_state shader; | |||
| struct tgsi_shader_info info; | |||
| void *data; | |||
| }; | |||
| @@ -36,14 +36,14 @@ | |||
| static int | |||
| find_vs_output(const struct pipe_shader_state *vs, | |||
| find_vs_output(const struct cell_vertex_shader_state *vs, | |||
| uint semantic_name, | |||
| uint semantic_index) | |||
| { | |||
| uint i; | |||
| for (i = 0; i < vs->num_outputs; i++) { | |||
| if (vs->output_semantic_name[i] == semantic_name && | |||
| vs->output_semantic_index[i] == semantic_index) | |||
| for (i = 0; i < vs->info.num_outputs; i++) { | |||
| if (vs->info.output_semantic_name[i] == semantic_name && | |||
| vs->info.output_semantic_index[i] == semantic_index) | |||
| return i; | |||
| } | |||
| return -1; | |||
| @@ -58,8 +58,8 @@ find_vs_output(const struct pipe_shader_state *vs, | |||
| static void | |||
| calculate_vertex_layout( struct cell_context *cell ) | |||
| { | |||
| const struct pipe_shader_state *vs = &cell->vs->shader; | |||
| const struct pipe_shader_state *fs = &cell->fs->shader; | |||
| const struct cell_vertex_shader_state *vs = cell->vs; | |||
| const struct cell_fragment_shader_state *fs = cell->fs; | |||
| const enum interp_mode colorInterp | |||
| = cell->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR; | |||
| struct vertex_info *vinfo = &cell->vertex_info; | |||
| @@ -91,15 +91,15 @@ calculate_vertex_layout( struct cell_context *cell ) | |||
| * Loop over fragment shader inputs, searching for the matching output | |||
| * from the vertex shader. | |||
| */ | |||
| for (i = 0; i < fs->num_inputs; i++) { | |||
| switch (fs->input_semantic_name[i]) { | |||
| for (i = 0; i < fs->info.num_inputs; i++) { | |||
| switch (fs->info.input_semantic_name[i]) { | |||
| case TGSI_SEMANTIC_POSITION: | |||
| /* already done above */ | |||
| break; | |||
| case TGSI_SEMANTIC_COLOR: | |||
| src = find_vs_output(vs, TGSI_SEMANTIC_COLOR, | |||
| fs->input_semantic_index[i]); | |||
| fs->info.input_semantic_index[i]); | |||
| assert(src >= 0); | |||
| draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src); | |||
| break; | |||
| @@ -117,7 +117,7 @@ calculate_vertex_layout( struct cell_context *cell ) | |||
| case TGSI_SEMANTIC_GENERIC: | |||
| /* this includes texcoords and varying vars */ | |||
| src = find_vs_output(vs, TGSI_SEMANTIC_GENERIC, | |||
| fs->input_semantic_index[i]); | |||
| fs->info.input_semantic_index[i]); | |||
| assert(src >= 0); | |||
| draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src); | |||
| break; | |||
| @@ -54,27 +54,7 @@ cell_create_fs_state(struct pipe_context *pipe, | |||
| state->shader = *templ; | |||
| #if 0 | |||
| if (cell->dump_fs) { | |||
| tgsi_dump(state->shader.tokens, 0); | |||
| } | |||
| #if defined(__i386__) || defined(__386__) | |||
| if (cell->use_sse) { | |||
| x86_init_func( &state->sse2_program ); | |||
| tgsi_emit_sse2_fs( state->shader.tokens, &state->sse2_program ); | |||
| } | |||
| #endif | |||
| #ifdef MESA_LLVM | |||
| state->llvm_prog = 0; | |||
| if (!gallivm_global_cpu_engine()) { | |||
| gallivm_cpu_engine_create(state->llvm_prog); | |||
| } | |||
| else | |||
| gallivm_cpu_jit_compile(gallivm_global_cpu_engine(), state->llvm_prog); | |||
| #endif | |||
| #endif | |||
| tgsi_scan_shader(templ->tokens, &state->info); | |||
| return state; | |||
| } | |||
| @@ -113,6 +93,7 @@ cell_create_vs_state(struct pipe_context *pipe, | |||
| return NULL; | |||
| state->shader = *templ; | |||
| tgsi_scan_shader(templ->tokens, &state->info); | |||
| state->draw_data = draw_create_vertex_shader(cell->draw, &state->shader); | |||
| if (state->draw_data == NULL) { | |||
| @@ -672,7 +672,7 @@ fetch_texel( struct spu_sampler *sampler, | |||
| static void | |||
| exec_tex(struct spu_exec_machine *mach, | |||
| const struct tgsi_full_instruction *inst, | |||
| boolean biasLod) | |||
| boolean biasLod, boolean projected) | |||
| { | |||
| const uint unit = inst->FullSrcRegisters[1].SrcRegister.Index; | |||
| union spu_exec_channel r[8]; | |||
| @@ -686,17 +686,9 @@ exec_tex(struct spu_exec_machine *mach, | |||
| FETCH(&r[0], 0, CHAN_X); | |||
| switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { | |||
| case TGSI_EXTSWIZZLE_W: | |||
| if (projected) { | |||
| FETCH(&r[1], 0, CHAN_W); | |||
| r[0].q = micro_div(r[0].q, r[1].q); | |||
| break; | |||
| case TGSI_EXTSWIZZLE_ONE: | |||
| break; | |||
| default: | |||
| assert (0); | |||
| } | |||
| if (biasLod) { | |||
| @@ -718,19 +710,11 @@ exec_tex(struct spu_exec_machine *mach, | |||
| FETCH(&r[1], 0, CHAN_Y); | |||
| FETCH(&r[2], 0, CHAN_Z); | |||
| switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { | |||
| case TGSI_EXTSWIZZLE_W: | |||
| if (projected) { | |||
| FETCH(&r[3], 0, CHAN_W); | |||
| r[0].q = micro_div(r[0].q, r[3].q); | |||
| r[1].q = micro_div(r[1].q, r[3].q); | |||
| r[2].q = micro_div(r[2].q, r[3].q); | |||
| break; | |||
| case TGSI_EXTSWIZZLE_ONE: | |||
| break; | |||
| default: | |||
| assert (0); | |||
| } | |||
| if (biasLod) { | |||
| @@ -752,19 +736,11 @@ exec_tex(struct spu_exec_machine *mach, | |||
| FETCH(&r[1], 0, CHAN_Y); | |||
| FETCH(&r[2], 0, CHAN_Z); | |||
| switch (inst->FullSrcRegisters[0].SrcRegisterExtSwz.ExtDivide) { | |||
| case TGSI_EXTSWIZZLE_W: | |||
| if (projected) { | |||
| FETCH(&r[3], 0, CHAN_W); | |||
| r[0].q = micro_div(r[0].q, r[3].q); | |||
| r[1].q = micro_div(r[1].q, r[3].q); | |||
| r[2].q = micro_div(r[2].q, r[3].q); | |||
| break; | |||
| case TGSI_EXTSWIZZLE_ONE: | |||
| break; | |||
| default: | |||
| assert (0); | |||
| } | |||
| if (biasLod) { | |||
| @@ -1450,14 +1426,14 @@ exec_instruction( | |||
| /* simple texture lookup */ | |||
| /* src[0] = texcoord */ | |||
| /* src[1] = sampler unit */ | |||
| exec_tex(mach, inst, FALSE); | |||
| exec_tex(mach, inst, FALSE, FALSE); | |||
| break; | |||
| case TGSI_OPCODE_TXB: | |||
| /* Texture lookup with lod bias */ | |||
| /* src[0] = texcoord (src[0].w = load bias) */ | |||
| /* src[1] = sampler unit */ | |||
| exec_tex(mach, inst, TRUE); | |||
| exec_tex(mach, inst, TRUE, FALSE); | |||
| break; | |||
| case TGSI_OPCODE_TXD: | |||
| @@ -1473,7 +1449,14 @@ exec_instruction( | |||
| /* Texture lookup with explit LOD */ | |||
| /* src[0] = texcoord (src[0].w = load bias) */ | |||
| /* src[1] = sampler unit */ | |||
| exec_tex(mach, inst, TRUE); | |||
| exec_tex(mach, inst, TRUE, FALSE); | |||
| break; | |||
| case TGSI_OPCODE_TXP: | |||
| /* Texture lookup with projection | |||
| /* src[0] = texcoord (src[0].w = projection) */ | |||
| /* src[1] = sampler unit */ | |||
| exec_tex(mach, inst, TRUE, TRUE); | |||
| break; | |||
| case TGSI_OPCODE_UP2H: | |||
| @@ -516,7 +516,7 @@ static void i915_set_constant_buffer(struct pipe_context *pipe, | |||
| * stays the same. In that case we should only be updating the first | |||
| * N constants, leaving any extras from shader translation alone. | |||
| */ | |||
| { | |||
| if (buf) { | |||
| void *mapped; | |||
| if (buf->size && | |||
| (mapped = ws->buffer_map(ws, buf->buffer, | |||
| @@ -55,6 +55,7 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, | |||
| if (ps == sp_tile_cache_get_surface(softpipe->zsbuf_cache)) { | |||
| sp_tile_cache_clear(softpipe->zsbuf_cache, clearValue); | |||
| softpipe->framebuffer.zsbuf->status = PIPE_SURFACE_STATUS_CLEAR; | |||
| #if TILE_CLEAR_OPTIMIZATION | |||
| return; | |||
| #endif | |||
| @@ -63,6 +64,7 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, | |||
| for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) { | |||
| if (ps == sp_tile_cache_get_surface(softpipe->cbuf_cache[i])) { | |||
| sp_tile_cache_clear(softpipe->cbuf_cache[i], clearValue); | |||
| softpipe->framebuffer.cbufs[i]->status = PIPE_SURFACE_STATUS_CLEAR; | |||
| } | |||
| } | |||
| @@ -1,243 +1,243 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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. | |||
| * | |||
| **************************************************************************/ | |||
| /* Author: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "draw/draw_context.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_inlines.h" | |||
| #include "pipe/p_util.h" | |||
| #include "sp_clear.h" | |||
| #include "sp_context.h" | |||
| #include "sp_flush.h" | |||
| #include "sp_prim_setup.h" | |||
| #include "sp_prim_vbuf.h" | |||
| #include "sp_state.h" | |||
| #include "sp_surface.h" | |||
| #include "sp_tile_cache.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_winsys.h" | |||
| #include "sp_query.h" | |||
| /** | |||
| * Map any drawing surfaces which aren't already mapped | |||
| */ | |||
| void | |||
| softpipe_map_surfaces(struct softpipe_context *sp) | |||
| { | |||
| unsigned i; | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) { | |||
| sp_tile_cache_map_surfaces(sp->cbuf_cache[i]); | |||
| } | |||
| sp_tile_cache_map_surfaces(sp->zsbuf_cache); | |||
| } | |||
| /** | |||
| * Unmap any mapped drawing surfaces | |||
| */ | |||
| void | |||
| softpipe_unmap_surfaces(struct softpipe_context *sp) | |||
| { | |||
| uint i; | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) | |||
| sp_flush_tile_cache(sp, sp->cbuf_cache[i]); | |||
| sp_flush_tile_cache(sp, sp->zsbuf_cache); | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) { | |||
| sp_tile_cache_unmap_surfaces(sp->cbuf_cache[i]); | |||
| } | |||
| sp_tile_cache_unmap_surfaces(sp->zsbuf_cache); | |||
| } | |||
| static void softpipe_destroy( struct pipe_context *pipe ) | |||
| { | |||
| struct softpipe_context *softpipe = softpipe_context( pipe ); | |||
| struct pipe_winsys *ws = pipe->winsys; | |||
| uint i; | |||
| draw_destroy( softpipe->draw ); | |||
| softpipe->quad.polygon_stipple->destroy( softpipe->quad.polygon_stipple ); | |||
| softpipe->quad.earlyz->destroy( softpipe->quad.earlyz ); | |||
| softpipe->quad.shade->destroy( softpipe->quad.shade ); | |||
| softpipe->quad.alpha_test->destroy( softpipe->quad.alpha_test ); | |||
| softpipe->quad.depth_test->destroy( softpipe->quad.depth_test ); | |||
| softpipe->quad.stencil_test->destroy( softpipe->quad.stencil_test ); | |||
| softpipe->quad.occlusion->destroy( softpipe->quad.occlusion ); | |||
| softpipe->quad.coverage->destroy( softpipe->quad.coverage ); | |||
| softpipe->quad.bufloop->destroy( softpipe->quad.bufloop ); | |||
| softpipe->quad.blend->destroy( softpipe->quad.blend ); | |||
| softpipe->quad.colormask->destroy( softpipe->quad.colormask ); | |||
| softpipe->quad.output->destroy( softpipe->quad.output ); | |||
| for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) | |||
| sp_destroy_tile_cache(softpipe->cbuf_cache[i]); | |||
| sp_destroy_tile_cache(softpipe->zsbuf_cache); | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) | |||
| sp_destroy_tile_cache(softpipe->tex_cache[i]); | |||
| for (i = 0; i < Elements(softpipe->constants); i++) { | |||
| if (softpipe->constants[i].buffer) { | |||
| pipe_buffer_reference(ws, &softpipe->constants[i].buffer, NULL); | |||
| } | |||
| } | |||
| FREE( softpipe ); | |||
| } | |||
| struct pipe_context * | |||
| softpipe_create( struct pipe_screen *screen, | |||
| struct pipe_winsys *pipe_winsys, | |||
| struct softpipe_winsys *softpipe_winsys ) | |||
| { | |||
| struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); | |||
| uint i; | |||
| #if defined(__i386__) || defined(__386__) | |||
| softpipe->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; | |||
| #else | |||
| softpipe->use_sse = FALSE; | |||
| #endif | |||
| softpipe->dump_fs = GETENV( "GALLIUM_DUMP_FS" ) != NULL; | |||
| softpipe->pipe.winsys = pipe_winsys; | |||
| softpipe->pipe.screen = screen; | |||
| softpipe->pipe.destroy = softpipe_destroy; | |||
| /* state setters */ | |||
| softpipe->pipe.create_blend_state = softpipe_create_blend_state; | |||
| softpipe->pipe.bind_blend_state = softpipe_bind_blend_state; | |||
| softpipe->pipe.delete_blend_state = softpipe_delete_blend_state; | |||
| softpipe->pipe.create_sampler_state = softpipe_create_sampler_state; | |||
| softpipe->pipe.bind_sampler_states = softpipe_bind_sampler_states; | |||
| softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state; | |||
| softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; | |||
| softpipe->pipe.bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; | |||
| softpipe->pipe.delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; | |||
| softpipe->pipe.create_rasterizer_state = softpipe_create_rasterizer_state; | |||
| softpipe->pipe.bind_rasterizer_state = softpipe_bind_rasterizer_state; | |||
| softpipe->pipe.delete_rasterizer_state = softpipe_delete_rasterizer_state; | |||
| softpipe->pipe.create_fs_state = softpipe_create_fs_state; | |||
| softpipe->pipe.bind_fs_state = softpipe_bind_fs_state; | |||
| softpipe->pipe.delete_fs_state = softpipe_delete_fs_state; | |||
| softpipe->pipe.create_vs_state = softpipe_create_vs_state; | |||
| softpipe->pipe.bind_vs_state = softpipe_bind_vs_state; | |||
| softpipe->pipe.delete_vs_state = softpipe_delete_vs_state; | |||
| softpipe->pipe.set_blend_color = softpipe_set_blend_color; | |||
| softpipe->pipe.set_clip_state = softpipe_set_clip_state; | |||
| softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer; | |||
| softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; | |||
| softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; | |||
| softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; | |||
| softpipe->pipe.set_sampler_textures = softpipe_set_sampler_textures; | |||
| softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; | |||
| softpipe->pipe.set_vertex_buffer = softpipe_set_vertex_buffer; | |||
| softpipe->pipe.set_vertex_element = softpipe_set_vertex_element; | |||
| softpipe->pipe.draw_arrays = softpipe_draw_arrays; | |||
| softpipe->pipe.draw_elements = softpipe_draw_elements; | |||
| softpipe->pipe.clear = softpipe_clear; | |||
| softpipe->pipe.flush = softpipe_flush; | |||
| softpipe_init_query_funcs( softpipe ); | |||
| softpipe_init_texture_funcs( softpipe ); | |||
| /* | |||
| * Alloc caches for accessing drawing surfaces and textures. | |||
| * Must be before quad stage setup! | |||
| */ | |||
| for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) | |||
| softpipe->cbuf_cache[i] = sp_create_tile_cache(); | |||
| softpipe->zsbuf_cache = sp_create_tile_cache(); | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) | |||
| softpipe->tex_cache[i] = sp_create_tile_cache(); | |||
| /* setup quad rendering stages */ | |||
| softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe); | |||
| softpipe->quad.earlyz = sp_quad_earlyz_stage(softpipe); | |||
| softpipe->quad.shade = sp_quad_shade_stage(softpipe); | |||
| softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe); | |||
| softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); | |||
| softpipe->quad.stencil_test = sp_quad_stencil_test_stage(softpipe); | |||
| softpipe->quad.occlusion = sp_quad_occlusion_stage(softpipe); | |||
| softpipe->quad.coverage = sp_quad_coverage_stage(softpipe); | |||
| softpipe->quad.bufloop = sp_quad_bufloop_stage(softpipe); | |||
| softpipe->quad.blend = sp_quad_blend_stage(softpipe); | |||
| softpipe->quad.colormask = sp_quad_colormask_stage(softpipe); | |||
| softpipe->quad.output = sp_quad_output_stage(softpipe); | |||
| softpipe->winsys = softpipe_winsys; | |||
| /* | |||
| * Create drawing context and plug our rendering stage into it. | |||
| */ | |||
| softpipe->draw = draw_create(); | |||
| assert(softpipe->draw); | |||
| softpipe->setup = sp_draw_render_stage(softpipe); | |||
| if (GETENV( "SP_VBUF" ) != NULL) { | |||
| sp_init_vbuf(softpipe); | |||
| } | |||
| else { | |||
| 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_init_surface_functions(softpipe); | |||
| return &softpipe->pipe; | |||
| } | |||
| /************************************************************************** | |||
| * | |||
| * 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. | |||
| * | |||
| **************************************************************************/ | |||
| /* Author: | |||
| * Keith Whitwell <keith@tungstengraphics.com> | |||
| */ | |||
| #include "draw/draw_context.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_inlines.h" | |||
| #include "pipe/p_util.h" | |||
| #include "sp_clear.h" | |||
| #include "sp_context.h" | |||
| #include "sp_flush.h" | |||
| #include "sp_prim_setup.h" | |||
| #include "sp_prim_vbuf.h" | |||
| #include "sp_state.h" | |||
| #include "sp_surface.h" | |||
| #include "sp_tile_cache.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_winsys.h" | |||
| #include "sp_query.h" | |||
| /** | |||
| * Map any drawing surfaces which aren't already mapped | |||
| */ | |||
| void | |||
| softpipe_map_surfaces(struct softpipe_context *sp) | |||
| { | |||
| unsigned i; | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) { | |||
| sp_tile_cache_map_surfaces(sp->cbuf_cache[i]); | |||
| } | |||
| sp_tile_cache_map_surfaces(sp->zsbuf_cache); | |||
| } | |||
| /** | |||
| * Unmap any mapped drawing surfaces | |||
| */ | |||
| void | |||
| softpipe_unmap_surfaces(struct softpipe_context *sp) | |||
| { | |||
| uint i; | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) | |||
| sp_flush_tile_cache(sp, sp->cbuf_cache[i]); | |||
| sp_flush_tile_cache(sp, sp->zsbuf_cache); | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++) { | |||
| sp_tile_cache_unmap_surfaces(sp->cbuf_cache[i]); | |||
| } | |||
| sp_tile_cache_unmap_surfaces(sp->zsbuf_cache); | |||
| } | |||
| static void softpipe_destroy( struct pipe_context *pipe ) | |||
| { | |||
| struct softpipe_context *softpipe = softpipe_context( pipe ); | |||
| struct pipe_winsys *ws = pipe->winsys; | |||
| uint i; | |||
| draw_destroy( softpipe->draw ); | |||
| softpipe->quad.polygon_stipple->destroy( softpipe->quad.polygon_stipple ); | |||
| softpipe->quad.earlyz->destroy( softpipe->quad.earlyz ); | |||
| softpipe->quad.shade->destroy( softpipe->quad.shade ); | |||
| softpipe->quad.alpha_test->destroy( softpipe->quad.alpha_test ); | |||
| softpipe->quad.depth_test->destroy( softpipe->quad.depth_test ); | |||
| softpipe->quad.stencil_test->destroy( softpipe->quad.stencil_test ); | |||
| softpipe->quad.occlusion->destroy( softpipe->quad.occlusion ); | |||
| softpipe->quad.coverage->destroy( softpipe->quad.coverage ); | |||
| softpipe->quad.bufloop->destroy( softpipe->quad.bufloop ); | |||
| softpipe->quad.blend->destroy( softpipe->quad.blend ); | |||
| softpipe->quad.colormask->destroy( softpipe->quad.colormask ); | |||
| softpipe->quad.output->destroy( softpipe->quad.output ); | |||
| for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) | |||
| sp_destroy_tile_cache(softpipe->cbuf_cache[i]); | |||
| sp_destroy_tile_cache(softpipe->zsbuf_cache); | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) | |||
| sp_destroy_tile_cache(softpipe->tex_cache[i]); | |||
| for (i = 0; i < Elements(softpipe->constants); i++) { | |||
| if (softpipe->constants[i].buffer) { | |||
| pipe_buffer_reference(ws, &softpipe->constants[i].buffer, NULL); | |||
| } | |||
| } | |||
| FREE( softpipe ); | |||
| } | |||
| struct pipe_context * | |||
| softpipe_create( struct pipe_screen *screen, | |||
| struct pipe_winsys *pipe_winsys, | |||
| struct softpipe_winsys *softpipe_winsys ) | |||
| { | |||
| struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); | |||
| uint i; | |||
| #if defined(__i386__) || defined(__386__) | |||
| softpipe->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL; | |||
| #else | |||
| softpipe->use_sse = FALSE; | |||
| #endif | |||
| softpipe->dump_fs = GETENV( "GALLIUM_DUMP_FS" ) != NULL; | |||
| softpipe->pipe.winsys = pipe_winsys; | |||
| softpipe->pipe.screen = screen; | |||
| softpipe->pipe.destroy = softpipe_destroy; | |||
| /* state setters */ | |||
| softpipe->pipe.create_blend_state = softpipe_create_blend_state; | |||
| softpipe->pipe.bind_blend_state = softpipe_bind_blend_state; | |||
| softpipe->pipe.delete_blend_state = softpipe_delete_blend_state; | |||
| softpipe->pipe.create_sampler_state = softpipe_create_sampler_state; | |||
| softpipe->pipe.bind_sampler_states = softpipe_bind_sampler_states; | |||
| softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state; | |||
| softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; | |||
| softpipe->pipe.bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; | |||
| softpipe->pipe.delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; | |||
| softpipe->pipe.create_rasterizer_state = softpipe_create_rasterizer_state; | |||
| softpipe->pipe.bind_rasterizer_state = softpipe_bind_rasterizer_state; | |||
| softpipe->pipe.delete_rasterizer_state = softpipe_delete_rasterizer_state; | |||
| softpipe->pipe.create_fs_state = softpipe_create_fs_state; | |||
| softpipe->pipe.bind_fs_state = softpipe_bind_fs_state; | |||
| softpipe->pipe.delete_fs_state = softpipe_delete_fs_state; | |||
| softpipe->pipe.create_vs_state = softpipe_create_vs_state; | |||
| softpipe->pipe.bind_vs_state = softpipe_bind_vs_state; | |||
| softpipe->pipe.delete_vs_state = softpipe_delete_vs_state; | |||
| softpipe->pipe.set_blend_color = softpipe_set_blend_color; | |||
| softpipe->pipe.set_clip_state = softpipe_set_clip_state; | |||
| softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer; | |||
| softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; | |||
| softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; | |||
| softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; | |||
| softpipe->pipe.set_sampler_textures = softpipe_set_sampler_textures; | |||
| softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; | |||
| softpipe->pipe.set_vertex_buffer = softpipe_set_vertex_buffer; | |||
| softpipe->pipe.set_vertex_element = softpipe_set_vertex_element; | |||
| softpipe->pipe.draw_arrays = softpipe_draw_arrays; | |||
| softpipe->pipe.draw_elements = softpipe_draw_elements; | |||
| softpipe->pipe.clear = softpipe_clear; | |||
| softpipe->pipe.flush = softpipe_flush; | |||
| softpipe_init_query_funcs( softpipe ); | |||
| softpipe_init_texture_funcs( softpipe ); | |||
| /* | |||
| * Alloc caches for accessing drawing surfaces and textures. | |||
| * Must be before quad stage setup! | |||
| */ | |||
| for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) | |||
| softpipe->cbuf_cache[i] = sp_create_tile_cache(); | |||
| softpipe->zsbuf_cache = sp_create_tile_cache(); | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) | |||
| softpipe->tex_cache[i] = sp_create_tile_cache(); | |||
| /* setup quad rendering stages */ | |||
| softpipe->quad.polygon_stipple = sp_quad_polygon_stipple_stage(softpipe); | |||
| softpipe->quad.earlyz = sp_quad_earlyz_stage(softpipe); | |||
| softpipe->quad.shade = sp_quad_shade_stage(softpipe); | |||
| softpipe->quad.alpha_test = sp_quad_alpha_test_stage(softpipe); | |||
| softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); | |||
| softpipe->quad.stencil_test = sp_quad_stencil_test_stage(softpipe); | |||
| softpipe->quad.occlusion = sp_quad_occlusion_stage(softpipe); | |||
| softpipe->quad.coverage = sp_quad_coverage_stage(softpipe); | |||
| softpipe->quad.bufloop = sp_quad_bufloop_stage(softpipe); | |||
| softpipe->quad.blend = sp_quad_blend_stage(softpipe); | |||
| softpipe->quad.colormask = sp_quad_colormask_stage(softpipe); | |||
| softpipe->quad.output = sp_quad_output_stage(softpipe); | |||
| softpipe->winsys = softpipe_winsys; | |||
| /* | |||
| * Create drawing context and plug our rendering stage into it. | |||
| */ | |||
| softpipe->draw = draw_create(); | |||
| assert(softpipe->draw); | |||
| softpipe->setup = sp_draw_render_stage(softpipe); | |||
| if (GETENV( "SP_VBUF" ) != NULL) { | |||
| sp_init_vbuf(softpipe); | |||
| } | |||
| else { | |||
| 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_init_surface_functions(softpipe); | |||
| return &softpipe->pipe; | |||
| } | |||
| @@ -62,6 +62,14 @@ softpipe_unmap_constant_buffers(struct softpipe_context *sp) | |||
| { | |||
| struct pipe_winsys *ws = sp->pipe.winsys; | |||
| uint i; | |||
| /* really need to flush all prims since the vert/frag shaders const buffers | |||
| * are going away now. | |||
| */ | |||
| draw_flush(sp->draw); | |||
| draw_set_mapped_constant_buffer(sp->draw, NULL); | |||
| for (i = 0; i < 2; i++) { | |||
| if (sp->constants[i].size) | |||
| ws->buffer_unmap(ws, sp->constants[i].buffer); | |||
| @@ -1164,11 +1164,22 @@ static void setup_begin( struct draw_stage *stage ) | |||
| struct setup_stage *setup = setup_stage(stage); | |||
| struct softpipe_context *sp = setup->softpipe; | |||
| const struct sp_fragment_shader *fs = setup->softpipe->fs; | |||
| uint i; | |||
| if (sp->dirty) { | |||
| softpipe_update_derived(sp); | |||
| } | |||
| /* Mark surfaces as defined now */ | |||
| for (i = 0; i < sp->framebuffer.num_cbufs; i++){ | |||
| if (sp->framebuffer.cbufs[i]) { | |||
| sp->framebuffer.cbufs[i]->status = PIPE_SURFACE_STATUS_DEFINED; | |||
| } | |||
| } | |||
| if (sp->framebuffer.zsbuf) { | |||
| sp->framebuffer.zsbuf->status = PIPE_SURFACE_STATUS_DEFINED; | |||
| } | |||
| setup->quad.nr_attrs = fs->info.num_inputs; | |||
| sp->quad.first->begin(sp->quad.first); | |||
| @@ -183,6 +183,60 @@ sp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr_indices) | |||
| } | |||
| /** | |||
| * This function is hit when the draw module is working in pass-through mode. | |||
| * It's up to us to convert the vertex array into point/line/tri prims. | |||
| */ | |||
| static void | |||
| sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr) | |||
| { | |||
| struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr); | |||
| struct softpipe_context *softpipe = cvbr->softpipe; | |||
| struct draw_stage *setup = softpipe->setup; | |||
| struct prim_header prim; | |||
| const void *vertex_buffer = cvbr->vertex_buffer; | |||
| const unsigned vertex_size = softpipe->vertex_info_vbuf.size * sizeof(float); | |||
| unsigned i; | |||
| prim.det = 0; | |||
| prim.reset_line_stipple = 0; | |||
| prim.edgeflags = 0; | |||
| prim.pad = 0; | |||
| #define VERTEX(I) \ | |||
| (struct vertex_header *) ((char *) vertex_buffer + (I) * vertex_size) | |||
| switch (cvbr->prim) { | |||
| case PIPE_PRIM_TRIANGLES: | |||
| assert(nr % 3 == 0); | |||
| for (i = 0; i < nr; i += 3) { | |||
| prim.v[0] = VERTEX(i + 0); | |||
| prim.v[1] = VERTEX(i + 1); | |||
| prim.v[2] = VERTEX(i + 2); | |||
| calc_det(&prim); | |||
| setup->tri( setup, &prim ); | |||
| } | |||
| break; | |||
| case PIPE_PRIM_POLYGON: | |||
| /* draw as tri fan */ | |||
| for (i = 2; i < nr; i++) { | |||
| prim.v[0] = VERTEX(0); | |||
| prim.v[1] = VERTEX(i - 1); | |||
| prim.v[2] = VERTEX(i); | |||
| calc_det(&prim); | |||
| setup->tri( setup, &prim ); | |||
| } | |||
| break; | |||
| default: | |||
| /* XXX finish remaining prim types */ | |||
| assert(0); | |||
| } | |||
| #undef VERTEX | |||
| } | |||
| static void | |||
| sp_vbuf_destroy(struct vbuf_render *vbr) | |||
| { | |||
| @@ -210,6 +264,7 @@ sp_init_vbuf(struct softpipe_context *sp) | |||
| sp->vbuf_render->base.allocate_vertices = sp_vbuf_allocate_vertices; | |||
| sp->vbuf_render->base.set_primitive = sp_vbuf_set_primitive; | |||
| sp->vbuf_render->base.draw = sp_vbuf_draw; | |||
| sp->vbuf_render->base.draw_arrays = sp_vbuf_draw_arrays; | |||
| sp->vbuf_render->base.release_vertices = sp_vbuf_release_vertices; | |||
| sp->vbuf_render->base.destroy = sp_vbuf_destroy; | |||
| @@ -218,4 +273,6 @@ sp_init_vbuf(struct softpipe_context *sp) | |||
| sp->vbuf = draw_vbuf_stage(sp->draw, &sp->vbuf_render->base); | |||
| draw_set_rasterize_stage(sp->draw, sp->vbuf); | |||
| draw_set_render(sp->draw, &sp->vbuf_render->base); | |||
| } | |||
| @@ -1,209 +1,209 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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. | |||
| * | |||
| **************************************************************************/ | |||
| /* Vertices are just an array of floats, with all the attributes | |||
| * packed. We currently assume a layout like: | |||
| * | |||
| * attr[0][0..3] - window position | |||
| * attr[1..n][0..3] - remaining attributes. | |||
| * | |||
| * Attributes are assumed to be 4 floats wide but are packed so that | |||
| * all the enabled attributes run contiguously. | |||
| */ | |||
| #include "pipe/p_util.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_shader_tokens.h" | |||
| #include "sp_context.h" | |||
| #include "sp_state.h" | |||
| #include "sp_headers.h" | |||
| #include "sp_quad.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_tex_sample.h" | |||
| struct quad_shade_stage | |||
| { | |||
| struct quad_stage stage; | |||
| struct tgsi_sampler samplers[PIPE_MAX_SAMPLERS]; | |||
| struct tgsi_exec_machine machine; | |||
| struct tgsi_exec_vector *inputs, *outputs; | |||
| int colorOutSlot, depthOutSlot; | |||
| }; | |||
| /** cast wrapper */ | |||
| static INLINE struct quad_shade_stage * | |||
| quad_shade_stage(struct quad_stage *qs) | |||
| { | |||
| return (struct quad_shade_stage *) qs; | |||
| } | |||
| /** | |||
| * Execute fragment shader for the four fragments in the quad. | |||
| */ | |||
| static void | |||
| shade_quad( | |||
| struct quad_stage *qs, | |||
| struct quad_header *quad ) | |||
| { | |||
| struct quad_shade_stage *qss = quad_shade_stage( qs ); | |||
| struct softpipe_context *softpipe = qs->softpipe; | |||
| struct tgsi_exec_machine *machine = &qss->machine; | |||
| /* Consts do not require 16 byte alignment. */ | |||
| machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT]; | |||
| machine->InterpCoefs = quad->coef; | |||
| /* run shader */ | |||
| quad->mask &= softpipe->fs->run( softpipe->fs, | |||
| &qss->machine, | |||
| quad ); | |||
| /* store result color */ | |||
| if (qss->colorOutSlot >= 0) { | |||
| /* XXX need to handle multiple color outputs someday */ | |||
| assert(qss->stage.softpipe->fs->info.output_semantic_name[qss->colorOutSlot] | |||
| == TGSI_SEMANTIC_COLOR); | |||
| memcpy( | |||
| quad->outputs.color, | |||
| &machine->Outputs[qss->colorOutSlot].xyzw[0].f[0], | |||
| sizeof( quad->outputs.color ) ); | |||
| } | |||
| /* | |||
| * XXX the following code for updating quad->outputs.depth | |||
| * isn't really needed if we did early z testing. | |||
| */ | |||
| /* store result Z */ | |||
| if (qss->depthOutSlot >= 0) { | |||
| /* output[slot] is new Z */ | |||
| uint i; | |||
| for (i = 0; i < 4; i++) { | |||
| quad->outputs.depth[i] = machine->Outputs[0].xyzw[2].f[i]; | |||
| } | |||
| } | |||
| else { | |||
| /* copy input Z (which was interpolated by the executor) to output Z */ | |||
| uint i; | |||
| for (i = 0; i < 4; i++) { | |||
| quad->outputs.depth[i] = machine->Inputs[0].xyzw[2].f[i]; | |||
| /* XXX not sure the above line is always correct. The following | |||
| * might be better: | |||
| quad->outputs.depth[i] = machine->QuadPos.xyzw[2].f[i]; | |||
| */ | |||
| } | |||
| } | |||
| /* shader may cull fragments */ | |||
| if( quad->mask ) { | |||
| qs->next->run( qs->next, quad ); | |||
| } | |||
| } | |||
| /** | |||
| * Per-primitive (or per-begin?) setup | |||
| */ | |||
| static void shade_begin(struct quad_stage *qs) | |||
| { | |||
| struct quad_shade_stage *qss = quad_shade_stage(qs); | |||
| struct softpipe_context *softpipe = qs->softpipe; | |||
| unsigned i; | |||
| unsigned num = MAX2(softpipe->num_textures, softpipe->num_samplers); | |||
| /* set TGSI sampler state that varies */ | |||
| for (i = 0; i < num; i++) { | |||
| qss->samplers[i].state = softpipe->sampler[i]; | |||
| qss->samplers[i].texture = softpipe->texture[i]; | |||
| } | |||
| /* find output slots for depth, color */ | |||
| qss->colorOutSlot = -1; | |||
| qss->depthOutSlot = -1; | |||
| for (i = 0; i < qss->stage.softpipe->fs->info.num_outputs; i++) { | |||
| switch (qss->stage.softpipe->fs->info.output_semantic_name[i]) { | |||
| case TGSI_SEMANTIC_POSITION: | |||
| qss->depthOutSlot = i; | |||
| break; | |||
| case TGSI_SEMANTIC_COLOR: | |||
| qss->colorOutSlot = i; | |||
| break; | |||
| } | |||
| } | |||
| softpipe->fs->prepare( softpipe->fs, | |||
| &qss->machine, | |||
| qss->samplers ); | |||
| qs->next->begin(qs->next); | |||
| } | |||
| static void shade_destroy(struct quad_stage *qs) | |||
| { | |||
| struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; | |||
| tgsi_exec_machine_free_data(&qss->machine); | |||
| FREE( qss->inputs ); | |||
| FREE( qss->outputs ); | |||
| FREE( qs ); | |||
| } | |||
| struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ) | |||
| { | |||
| struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage); | |||
| uint i; | |||
| /* allocate storage for program inputs/outputs, aligned to 16 bytes */ | |||
| qss->inputs = MALLOC(PIPE_ATTRIB_MAX * sizeof(*qss->inputs) + 16); | |||
| qss->outputs = MALLOC(PIPE_ATTRIB_MAX * sizeof(*qss->outputs) + 16); | |||
| qss->machine.Inputs = align16(qss->inputs); | |||
| qss->machine.Outputs = align16(qss->outputs); | |||
| qss->stage.softpipe = softpipe; | |||
| qss->stage.begin = shade_begin; | |||
| qss->stage.run = shade_quad; | |||
| qss->stage.destroy = shade_destroy; | |||
| /* set TGSI sampler state that's constant */ | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { | |||
| assert(softpipe->tex_cache[i]); | |||
| qss->samplers[i].get_samples = sp_get_samples; | |||
| qss->samplers[i].pipe = &softpipe->pipe; | |||
| qss->samplers[i].cache = softpipe->tex_cache[i]; | |||
| } | |||
| tgsi_exec_machine_init( &qss->machine ); | |||
| return &qss->stage; | |||
| } | |||
| /************************************************************************** | |||
| * | |||
| * 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. | |||
| * | |||
| **************************************************************************/ | |||
| /* Vertices are just an array of floats, with all the attributes | |||
| * packed. We currently assume a layout like: | |||
| * | |||
| * attr[0][0..3] - window position | |||
| * attr[1..n][0..3] - remaining attributes. | |||
| * | |||
| * Attributes are assumed to be 4 floats wide but are packed so that | |||
| * all the enabled attributes run contiguously. | |||
| */ | |||
| #include "pipe/p_util.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_shader_tokens.h" | |||
| #include "sp_context.h" | |||
| #include "sp_state.h" | |||
| #include "sp_headers.h" | |||
| #include "sp_quad.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_tex_sample.h" | |||
| struct quad_shade_stage | |||
| { | |||
| struct quad_stage stage; | |||
| struct tgsi_sampler samplers[PIPE_MAX_SAMPLERS]; | |||
| struct tgsi_exec_machine machine; | |||
| struct tgsi_exec_vector *inputs, *outputs; | |||
| int colorOutSlot, depthOutSlot; | |||
| }; | |||
| /** cast wrapper */ | |||
| static INLINE struct quad_shade_stage * | |||
| quad_shade_stage(struct quad_stage *qs) | |||
| { | |||
| return (struct quad_shade_stage *) qs; | |||
| } | |||
| /** | |||
| * Execute fragment shader for the four fragments in the quad. | |||
| */ | |||
| static void | |||
| shade_quad( | |||
| struct quad_stage *qs, | |||
| struct quad_header *quad ) | |||
| { | |||
| struct quad_shade_stage *qss = quad_shade_stage( qs ); | |||
| struct softpipe_context *softpipe = qs->softpipe; | |||
| struct tgsi_exec_machine *machine = &qss->machine; | |||
| /* Consts do not require 16 byte alignment. */ | |||
| machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT]; | |||
| machine->InterpCoefs = quad->coef; | |||
| /* run shader */ | |||
| quad->mask &= softpipe->fs->run( softpipe->fs, | |||
| &qss->machine, | |||
| quad ); | |||
| /* store result color */ | |||
| if (qss->colorOutSlot >= 0) { | |||
| /* XXX need to handle multiple color outputs someday */ | |||
| assert(qss->stage.softpipe->fs->info.output_semantic_name[qss->colorOutSlot] | |||
| == TGSI_SEMANTIC_COLOR); | |||
| memcpy( | |||
| quad->outputs.color, | |||
| &machine->Outputs[qss->colorOutSlot].xyzw[0].f[0], | |||
| sizeof( quad->outputs.color ) ); | |||
| } | |||
| /* | |||
| * XXX the following code for updating quad->outputs.depth | |||
| * isn't really needed if we did early z testing. | |||
| */ | |||
| /* store result Z */ | |||
| if (qss->depthOutSlot >= 0) { | |||
| /* output[slot] is new Z */ | |||
| uint i; | |||
| for (i = 0; i < 4; i++) { | |||
| quad->outputs.depth[i] = machine->Outputs[0].xyzw[2].f[i]; | |||
| } | |||
| } | |||
| else { | |||
| /* copy input Z (which was interpolated by the executor) to output Z */ | |||
| uint i; | |||
| for (i = 0; i < 4; i++) { | |||
| quad->outputs.depth[i] = machine->Inputs[0].xyzw[2].f[i]; | |||
| /* XXX not sure the above line is always correct. The following | |||
| * might be better: | |||
| quad->outputs.depth[i] = machine->QuadPos.xyzw[2].f[i]; | |||
| */ | |||
| } | |||
| } | |||
| /* shader may cull fragments */ | |||
| if( quad->mask ) { | |||
| qs->next->run( qs->next, quad ); | |||
| } | |||
| } | |||
| /** | |||
| * Per-primitive (or per-begin?) setup | |||
| */ | |||
| static void shade_begin(struct quad_stage *qs) | |||
| { | |||
| struct quad_shade_stage *qss = quad_shade_stage(qs); | |||
| struct softpipe_context *softpipe = qs->softpipe; | |||
| unsigned i; | |||
| unsigned num = MAX2(softpipe->num_textures, softpipe->num_samplers); | |||
| /* set TGSI sampler state that varies */ | |||
| for (i = 0; i < num; i++) { | |||
| qss->samplers[i].state = softpipe->sampler[i]; | |||
| qss->samplers[i].texture = softpipe->texture[i]; | |||
| } | |||
| /* find output slots for depth, color */ | |||
| qss->colorOutSlot = -1; | |||
| qss->depthOutSlot = -1; | |||
| for (i = 0; i < qss->stage.softpipe->fs->info.num_outputs; i++) { | |||
| switch (qss->stage.softpipe->fs->info.output_semantic_name[i]) { | |||
| case TGSI_SEMANTIC_POSITION: | |||
| qss->depthOutSlot = i; | |||
| break; | |||
| case TGSI_SEMANTIC_COLOR: | |||
| qss->colorOutSlot = i; | |||
| break; | |||
| } | |||
| } | |||
| softpipe->fs->prepare( softpipe->fs, | |||
| &qss->machine, | |||
| qss->samplers ); | |||
| qs->next->begin(qs->next); | |||
| } | |||
| static void shade_destroy(struct quad_stage *qs) | |||
| { | |||
| struct quad_shade_stage *qss = (struct quad_shade_stage *) qs; | |||
| tgsi_exec_machine_free_data(&qss->machine); | |||
| FREE( qss->inputs ); | |||
| FREE( qss->outputs ); | |||
| FREE( qs ); | |||
| } | |||
| struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ) | |||
| { | |||
| struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage); | |||
| uint i; | |||
| /* allocate storage for program inputs/outputs, aligned to 16 bytes */ | |||
| qss->inputs = MALLOC(PIPE_ATTRIB_MAX * sizeof(*qss->inputs) + 16); | |||
| qss->outputs = MALLOC(PIPE_ATTRIB_MAX * sizeof(*qss->outputs) + 16); | |||
| qss->machine.Inputs = align16(qss->inputs); | |||
| qss->machine.Outputs = align16(qss->outputs); | |||
| qss->stage.softpipe = softpipe; | |||
| qss->stage.begin = shade_begin; | |||
| qss->stage.run = shade_quad; | |||
| qss->stage.destroy = shade_destroy; | |||
| /* set TGSI sampler state that's constant */ | |||
| for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { | |||
| assert(softpipe->tex_cache[i]); | |||
| qss->samplers[i].get_samples = sp_get_samples; | |||
| qss->samplers[i].pipe = &softpipe->pipe; | |||
| qss->samplers[i].cache = softpipe->tex_cache[i]; | |||
| } | |||
| tgsi_exec_machine_init( &qss->machine ); | |||
| return &qss->stage; | |||
| } | |||
| @@ -1,195 +1,195 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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> | |||
| */ | |||
| #ifndef SP_STATE_H | |||
| #define SP_STATE_H | |||
| #include "pipe/p_state.h" | |||
| #include "tgsi/util/tgsi_scan.h" | |||
| #define SP_NEW_VIEWPORT 0x1 | |||
| #define SP_NEW_RASTERIZER 0x2 | |||
| #define SP_NEW_FS 0x4 | |||
| #define SP_NEW_BLEND 0x8 | |||
| #define SP_NEW_CLIP 0x10 | |||
| #define SP_NEW_SCISSOR 0x20 | |||
| #define SP_NEW_STIPPLE 0x40 | |||
| #define SP_NEW_FRAMEBUFFER 0x80 | |||
| #define SP_NEW_DEPTH_STENCIL_ALPHA 0x100 | |||
| #define SP_NEW_CONSTANTS 0x200 | |||
| #define SP_NEW_SAMPLER 0x400 | |||
| #define SP_NEW_TEXTURE 0x800 | |||
| #define SP_NEW_VERTEX 0x1000 | |||
| #define SP_NEW_VS 0x2000 | |||
| #define SP_NEW_QUERY 0x4000 | |||
| struct tgsi_sampler; | |||
| struct tgsi_exec_machine; | |||
| /** Subclass of pipe_shader_state (though it doesn't really need to be). | |||
| * | |||
| * This is starting to look an awful lot like a quad pipeline stage... | |||
| */ | |||
| struct sp_fragment_shader { | |||
| struct pipe_shader_state shader; | |||
| struct tgsi_shader_info info; | |||
| void (*prepare)( const struct sp_fragment_shader *shader, | |||
| struct tgsi_exec_machine *machine, | |||
| struct tgsi_sampler *samplers); | |||
| /* Run the shader - this interface will get cleaned up in the | |||
| * future: | |||
| */ | |||
| unsigned (*run)( const struct sp_fragment_shader *shader, | |||
| struct tgsi_exec_machine *machine, | |||
| struct quad_header *quad ); | |||
| void (*delete)( struct sp_fragment_shader * ); | |||
| }; | |||
| struct vertex_info; | |||
| /** Subclass of pipe_shader_state */ | |||
| struct sp_vertex_shader { | |||
| struct pipe_shader_state shader; | |||
| struct draw_vertex_shader *draw_data; | |||
| }; | |||
| void * | |||
| softpipe_create_blend_state(struct pipe_context *, | |||
| const struct pipe_blend_state *); | |||
| void softpipe_bind_blend_state(struct pipe_context *, | |||
| void *); | |||
| void softpipe_delete_blend_state(struct pipe_context *, | |||
| void *); | |||
| void * | |||
| softpipe_create_sampler_state(struct pipe_context *, | |||
| const struct pipe_sampler_state *); | |||
| void softpipe_bind_sampler_states(struct pipe_context *, unsigned, void **); | |||
| void softpipe_delete_sampler_state(struct pipe_context *, void *); | |||
| void * | |||
| softpipe_create_depth_stencil_state(struct pipe_context *, | |||
| const struct pipe_depth_stencil_alpha_state *); | |||
| void softpipe_bind_depth_stencil_state(struct pipe_context *, void *); | |||
| void softpipe_delete_depth_stencil_state(struct pipe_context *, void *); | |||
| void * | |||
| softpipe_create_rasterizer_state(struct pipe_context *, | |||
| const struct pipe_rasterizer_state *); | |||
| void softpipe_bind_rasterizer_state(struct pipe_context *, void *); | |||
| void softpipe_delete_rasterizer_state(struct pipe_context *, void *); | |||
| void softpipe_set_framebuffer_state( struct pipe_context *, | |||
| const struct pipe_framebuffer_state * ); | |||
| void softpipe_set_blend_color( struct pipe_context *pipe, | |||
| const struct pipe_blend_color *blend_color ); | |||
| void softpipe_set_clip_state( struct pipe_context *, | |||
| const struct pipe_clip_state * ); | |||
| void softpipe_set_constant_buffer(struct pipe_context *, | |||
| uint shader, uint index, | |||
| const struct pipe_constant_buffer *buf); | |||
| void *softpipe_create_fs_state(struct pipe_context *, | |||
| const struct pipe_shader_state *); | |||
| void softpipe_bind_fs_state(struct pipe_context *, void *); | |||
| void softpipe_delete_fs_state(struct pipe_context *, void *); | |||
| void *softpipe_create_vs_state(struct pipe_context *, | |||
| const struct pipe_shader_state *); | |||
| void softpipe_bind_vs_state(struct pipe_context *, void *); | |||
| void softpipe_delete_vs_state(struct pipe_context *, void *); | |||
| void softpipe_set_polygon_stipple( struct pipe_context *, | |||
| const struct pipe_poly_stipple * ); | |||
| void softpipe_set_scissor_state( struct pipe_context *, | |||
| const struct pipe_scissor_state * ); | |||
| void softpipe_set_sampler_textures( struct pipe_context *, | |||
| unsigned num, | |||
| struct pipe_texture ** ); | |||
| void softpipe_set_viewport_state( struct pipe_context *, | |||
| const struct pipe_viewport_state * ); | |||
| void softpipe_set_vertex_element(struct pipe_context *, | |||
| unsigned index, | |||
| const struct pipe_vertex_element *); | |||
| void softpipe_set_vertex_buffer(struct pipe_context *, | |||
| unsigned index, | |||
| const struct pipe_vertex_buffer *); | |||
| void softpipe_update_derived( struct softpipe_context *softpipe ); | |||
| boolean softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, | |||
| unsigned start, unsigned count); | |||
| boolean softpipe_draw_elements(struct pipe_context *pipe, | |||
| struct pipe_buffer *indexBuffer, | |||
| unsigned indexSize, | |||
| unsigned mode, unsigned start, unsigned count); | |||
| void | |||
| softpipe_map_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_unmap_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_map_texture_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_unmap_texture_surfaces(struct softpipe_context *sp); | |||
| struct vertex_info * | |||
| softpipe_get_vertex_info(struct softpipe_context *softpipe); | |||
| struct vertex_info * | |||
| softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe); | |||
| #endif | |||
| /************************************************************************** | |||
| * | |||
| * 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> | |||
| */ | |||
| #ifndef SP_STATE_H | |||
| #define SP_STATE_H | |||
| #include "pipe/p_state.h" | |||
| #include "tgsi/util/tgsi_scan.h" | |||
| #define SP_NEW_VIEWPORT 0x1 | |||
| #define SP_NEW_RASTERIZER 0x2 | |||
| #define SP_NEW_FS 0x4 | |||
| #define SP_NEW_BLEND 0x8 | |||
| #define SP_NEW_CLIP 0x10 | |||
| #define SP_NEW_SCISSOR 0x20 | |||
| #define SP_NEW_STIPPLE 0x40 | |||
| #define SP_NEW_FRAMEBUFFER 0x80 | |||
| #define SP_NEW_DEPTH_STENCIL_ALPHA 0x100 | |||
| #define SP_NEW_CONSTANTS 0x200 | |||
| #define SP_NEW_SAMPLER 0x400 | |||
| #define SP_NEW_TEXTURE 0x800 | |||
| #define SP_NEW_VERTEX 0x1000 | |||
| #define SP_NEW_VS 0x2000 | |||
| #define SP_NEW_QUERY 0x4000 | |||
| struct tgsi_sampler; | |||
| struct tgsi_exec_machine; | |||
| /** Subclass of pipe_shader_state (though it doesn't really need to be). | |||
| * | |||
| * This is starting to look an awful lot like a quad pipeline stage... | |||
| */ | |||
| struct sp_fragment_shader { | |||
| struct pipe_shader_state shader; | |||
| struct tgsi_shader_info info; | |||
| void (*prepare)( const struct sp_fragment_shader *shader, | |||
| struct tgsi_exec_machine *machine, | |||
| struct tgsi_sampler *samplers); | |||
| /* Run the shader - this interface will get cleaned up in the | |||
| * future: | |||
| */ | |||
| unsigned (*run)( const struct sp_fragment_shader *shader, | |||
| struct tgsi_exec_machine *machine, | |||
| struct quad_header *quad ); | |||
| void (*delete)( struct sp_fragment_shader * ); | |||
| }; | |||
| struct vertex_info; | |||
| /** Subclass of pipe_shader_state */ | |||
| struct sp_vertex_shader { | |||
| struct pipe_shader_state shader; | |||
| struct draw_vertex_shader *draw_data; | |||
| }; | |||
| void * | |||
| softpipe_create_blend_state(struct pipe_context *, | |||
| const struct pipe_blend_state *); | |||
| void softpipe_bind_blend_state(struct pipe_context *, | |||
| void *); | |||
| void softpipe_delete_blend_state(struct pipe_context *, | |||
| void *); | |||
| void * | |||
| softpipe_create_sampler_state(struct pipe_context *, | |||
| const struct pipe_sampler_state *); | |||
| void softpipe_bind_sampler_states(struct pipe_context *, unsigned, void **); | |||
| void softpipe_delete_sampler_state(struct pipe_context *, void *); | |||
| void * | |||
| softpipe_create_depth_stencil_state(struct pipe_context *, | |||
| const struct pipe_depth_stencil_alpha_state *); | |||
| void softpipe_bind_depth_stencil_state(struct pipe_context *, void *); | |||
| void softpipe_delete_depth_stencil_state(struct pipe_context *, void *); | |||
| void * | |||
| softpipe_create_rasterizer_state(struct pipe_context *, | |||
| const struct pipe_rasterizer_state *); | |||
| void softpipe_bind_rasterizer_state(struct pipe_context *, void *); | |||
| void softpipe_delete_rasterizer_state(struct pipe_context *, void *); | |||
| void softpipe_set_framebuffer_state( struct pipe_context *, | |||
| const struct pipe_framebuffer_state * ); | |||
| void softpipe_set_blend_color( struct pipe_context *pipe, | |||
| const struct pipe_blend_color *blend_color ); | |||
| void softpipe_set_clip_state( struct pipe_context *, | |||
| const struct pipe_clip_state * ); | |||
| void softpipe_set_constant_buffer(struct pipe_context *, | |||
| uint shader, uint index, | |||
| const struct pipe_constant_buffer *buf); | |||
| void *softpipe_create_fs_state(struct pipe_context *, | |||
| const struct pipe_shader_state *); | |||
| void softpipe_bind_fs_state(struct pipe_context *, void *); | |||
| void softpipe_delete_fs_state(struct pipe_context *, void *); | |||
| void *softpipe_create_vs_state(struct pipe_context *, | |||
| const struct pipe_shader_state *); | |||
| void softpipe_bind_vs_state(struct pipe_context *, void *); | |||
| void softpipe_delete_vs_state(struct pipe_context *, void *); | |||
| void softpipe_set_polygon_stipple( struct pipe_context *, | |||
| const struct pipe_poly_stipple * ); | |||
| void softpipe_set_scissor_state( struct pipe_context *, | |||
| const struct pipe_scissor_state * ); | |||
| void softpipe_set_sampler_textures( struct pipe_context *, | |||
| unsigned num, | |||
| struct pipe_texture ** ); | |||
| void softpipe_set_viewport_state( struct pipe_context *, | |||
| const struct pipe_viewport_state * ); | |||
| void softpipe_set_vertex_element(struct pipe_context *, | |||
| unsigned index, | |||
| const struct pipe_vertex_element *); | |||
| void softpipe_set_vertex_buffer(struct pipe_context *, | |||
| unsigned index, | |||
| const struct pipe_vertex_buffer *); | |||
| void softpipe_update_derived( struct softpipe_context *softpipe ); | |||
| boolean softpipe_draw_arrays(struct pipe_context *pipe, unsigned mode, | |||
| unsigned start, unsigned count); | |||
| boolean softpipe_draw_elements(struct pipe_context *pipe, | |||
| struct pipe_buffer *indexBuffer, | |||
| unsigned indexSize, | |||
| unsigned mode, unsigned start, unsigned count); | |||
| void | |||
| softpipe_map_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_unmap_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_map_texture_surfaces(struct softpipe_context *sp); | |||
| void | |||
| softpipe_unmap_texture_surfaces(struct softpipe_context *sp); | |||
| struct vertex_info * | |||
| softpipe_get_vertex_info(struct softpipe_context *softpipe); | |||
| struct vertex_info * | |||
| softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe); | |||
| #endif | |||
| @@ -71,11 +71,25 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe) | |||
| * simply emit the whole post-xform vertex as-is: | |||
| */ | |||
| struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf; | |||
| #if 0 | |||
| vinfo_vbuf->num_attribs = 0; | |||
| /* special-case to allow memcpy of whole vertex */ | |||
| draw_emit_vertex_attr(vinfo_vbuf, EMIT_ALL, INTERP_NONE, 0); | |||
| /* size in dwords or floats */ | |||
| vinfo_vbuf->size = 4 * draw_num_vs_outputs(softpipe->draw) | |||
| + sizeof(struct vertex_header) / 4; | |||
| #else | |||
| /* for pass-through mode, we need a more explicit list of attribs */ | |||
| const uint num = draw_num_vs_outputs(softpipe->draw); | |||
| uint i; | |||
| vinfo_vbuf->num_attribs = 0; | |||
| draw_emit_vertex_attr(vinfo_vbuf, EMIT_HEADER, INTERP_NONE, 0); | |||
| for (i = 0; i < num; i++) { | |||
| draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i); | |||
| } | |||
| draw_compute_vertex_size(vinfo_vbuf); | |||
| #endif | |||
| } | |||
| /* | |||
| @@ -1,202 +1,202 @@ | |||
| /************************************************************************** | |||
| * | |||
| * Copyright 2006 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> | |||
| * Michel Dänzer <michel@tungstengraphics.com> | |||
| */ | |||
| #include "pipe/p_context.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_inlines.h" | |||
| #include "pipe/p_util.h" | |||
| #include "pipe/p_winsys.h" | |||
| #include "sp_context.h" | |||
| #include "sp_state.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_tile_cache.h" | |||
| /* Simple, maximally packed layout. | |||
| */ | |||
| static unsigned minify( unsigned d ) | |||
| { | |||
| return MAX2(1, d>>1); | |||
| } | |||
| static void | |||
| softpipe_texture_layout(struct softpipe_texture * spt) | |||
| { | |||
| struct pipe_texture *pt = &spt->base; | |||
| unsigned level; | |||
| unsigned width = pt->width[0]; | |||
| unsigned height = pt->height[0]; | |||
| unsigned depth = pt->depth[0]; | |||
| spt->buffer_size = 0; | |||
| for (level = 0; level <= pt->last_level; level++) { | |||
| pt->width[level] = width; | |||
| pt->height[level] = height; | |||
| pt->depth[level] = depth; | |||
| spt->level_offset[level] = spt->buffer_size; | |||
| spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) * | |||
| ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * | |||
| width * pt->cpp; | |||
| width = minify(width); | |||
| height = minify(height); | |||
| depth = minify(depth); | |||
| } | |||
| } | |||
| static struct pipe_texture * | |||
| softpipe_texture_create_screen(struct pipe_screen *screen, | |||
| const struct pipe_texture *templat) | |||
| { | |||
| struct pipe_winsys *ws = screen->winsys; | |||
| struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture); | |||
| if (!spt) | |||
| return NULL; | |||
| spt->base = *templat; | |||
| spt->base.refcount = 1; | |||
| spt->base.screen = screen; | |||
| softpipe_texture_layout(spt); | |||
| spt->buffer = ws->buffer_create(ws, 32, | |||
| PIPE_BUFFER_USAGE_PIXEL, | |||
| spt->buffer_size); | |||
| if (!spt->buffer) { | |||
| FREE(spt); | |||
| return NULL; | |||
| } | |||
| assert(spt->base.refcount == 1); | |||
| return &spt->base; | |||
| } | |||
| static void | |||
| softpipe_texture_release_screen(struct pipe_screen *screen, | |||
| struct pipe_texture **pt) | |||
| { | |||
| if (!*pt) | |||
| return; | |||
| /* | |||
| DBG("%s %p refcount will be %d\n", | |||
| __FUNCTION__, (void *) *pt, (*pt)->refcount - 1); | |||
| */ | |||
| if (--(*pt)->refcount <= 0) { | |||
| struct softpipe_texture *spt = softpipe_texture(*pt); | |||
| /* | |||
| DBG("%s deleting %p\n", __FUNCTION__, (void *) spt); | |||
| */ | |||
| pipe_buffer_reference(screen->winsys, &spt->buffer, NULL); | |||
| FREE(spt); | |||
| } | |||
| *pt = NULL; | |||
| } | |||
| static struct pipe_surface * | |||
| softpipe_get_tex_surface_screen(struct pipe_screen *screen, | |||
| struct pipe_texture *pt, | |||
| unsigned face, unsigned level, unsigned zslice) | |||
| { | |||
| struct pipe_winsys *ws = screen->winsys; | |||
| struct softpipe_texture *spt = softpipe_texture(pt); | |||
| struct pipe_surface *ps; | |||
| assert(level <= pt->last_level); | |||
| ps = ws->surface_alloc(ws); | |||
| if (ps) { | |||
| assert(ps->refcount); | |||
| assert(ps->winsys); | |||
| pipe_buffer_reference(ws, &ps->buffer, spt->buffer); | |||
| ps->format = pt->format; | |||
| ps->cpp = pt->cpp; | |||
| ps->width = pt->width[level]; | |||
| ps->height = pt->height[level]; | |||
| ps->pitch = ps->width; | |||
| ps->offset = spt->level_offset[level]; | |||
| if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) { | |||
| ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) * | |||
| (pt->compressed ? ps->height/4 : ps->height) * | |||
| ps->width * ps->cpp; | |||
| } | |||
| else { | |||
| assert(face == 0); | |||
| assert(zslice == 0); | |||
| } | |||
| } | |||
| return ps; | |||
| } | |||
| static 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 < softpipe->num_textures; unit++) { | |||
| if (softpipe->texture[unit] == texture) { | |||
| sp_flush_tile_cache(softpipe, softpipe->tex_cache[unit]); | |||
| } | |||
| } | |||
| } | |||
| void | |||
| softpipe_init_texture_funcs( struct softpipe_context *softpipe ) | |||
| { | |||
| softpipe->pipe.texture_update = softpipe_texture_update; | |||
| } | |||
| void | |||
| softpipe_init_screen_texture_funcs(struct pipe_screen *screen) | |||
| { | |||
| screen->texture_create = softpipe_texture_create_screen; | |||
| screen->texture_release = softpipe_texture_release_screen; | |||
| screen->get_tex_surface = softpipe_get_tex_surface_screen; | |||
| } | |||
| /************************************************************************** | |||
| * | |||
| * Copyright 2006 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> | |||
| * Michel Dänzer <michel@tungstengraphics.com> | |||
| */ | |||
| #include "pipe/p_context.h" | |||
| #include "pipe/p_defines.h" | |||
| #include "pipe/p_inlines.h" | |||
| #include "pipe/p_util.h" | |||
| #include "pipe/p_winsys.h" | |||
| #include "sp_context.h" | |||
| #include "sp_state.h" | |||
| #include "sp_texture.h" | |||
| #include "sp_tile_cache.h" | |||
| /* Simple, maximally packed layout. | |||
| */ | |||
| static unsigned minify( unsigned d ) | |||
| { | |||
| return MAX2(1, d>>1); | |||
| } | |||
| static void | |||
| softpipe_texture_layout(struct softpipe_texture * spt) | |||
| { | |||
| struct pipe_texture *pt = &spt->base; | |||
| unsigned level; | |||
| unsigned width = pt->width[0]; | |||
| unsigned height = pt->height[0]; | |||
| unsigned depth = pt->depth[0]; | |||
| spt->buffer_size = 0; | |||
| for (level = 0; level <= pt->last_level; level++) { | |||
| pt->width[level] = width; | |||
| pt->height[level] = height; | |||
| pt->depth[level] = depth; | |||
| spt->level_offset[level] = spt->buffer_size; | |||
| spt->buffer_size += ((pt->compressed) ? MAX2(1, height/4) : height) * | |||
| ((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) * | |||
| width * pt->cpp; | |||
| width = minify(width); | |||
| height = minify(height); | |||
| depth = minify(depth); | |||
| } | |||
| } | |||
| static struct pipe_texture * | |||
| softpipe_texture_create_screen(struct pipe_screen *screen, | |||
| const struct pipe_texture *templat) | |||
| { | |||
| struct pipe_winsys *ws = screen->winsys; | |||
| struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture); | |||
| if (!spt) | |||
| return NULL; | |||
| spt->base = *templat; | |||
| spt->base.refcount = 1; | |||
| spt->base.screen = screen; | |||
| softpipe_texture_layout(spt); | |||
| spt->buffer = ws->buffer_create(ws, 32, | |||
| PIPE_BUFFER_USAGE_PIXEL, | |||
| spt->buffer_size); | |||
| if (!spt->buffer) { | |||
| FREE(spt); | |||
| return NULL; | |||
| } | |||
| assert(spt->base.refcount == 1); | |||
| return &spt->base; | |||
| } | |||
| static void | |||
| softpipe_texture_release_screen(struct pipe_screen *screen, | |||
| struct pipe_texture **pt) | |||
| { | |||
| if (!*pt) | |||
| return; | |||
| /* | |||
| DBG("%s %p refcount will be %d\n", | |||
| __FUNCTION__, (void *) *pt, (*pt)->refcount - 1); | |||
| */ | |||
| if (--(*pt)->refcount <= 0) { | |||
| struct softpipe_texture *spt = softpipe_texture(*pt); | |||
| /* | |||
| DBG("%s deleting %p\n", __FUNCTION__, (void *) spt); | |||
| */ | |||
| pipe_buffer_reference(screen->winsys, &spt->buffer, NULL); | |||
| FREE(spt); | |||
| } | |||
| *pt = NULL; | |||
| } | |||
| static struct pipe_surface * | |||
| softpipe_get_tex_surface_screen(struct pipe_screen *screen, | |||
| struct pipe_texture *pt, | |||
| unsigned face, unsigned level, unsigned zslice) | |||
| { | |||
| struct pipe_winsys *ws = screen->winsys; | |||
| struct softpipe_texture *spt = softpipe_texture(pt); | |||
| struct pipe_surface *ps; | |||
| assert(level <= pt->last_level); | |||
| ps = ws->surface_alloc(ws); | |||
| if (ps) { | |||
| assert(ps->refcount); | |||
| assert(ps->winsys); | |||
| pipe_buffer_reference(ws, &ps->buffer, spt->buffer); | |||
| ps->format = pt->format; | |||
| ps->cpp = pt->cpp; | |||
| ps->width = pt->width[level]; | |||
| ps->height = pt->height[level]; | |||
| ps->pitch = ps->width; | |||
| ps->offset = spt->level_offset[level]; | |||
| if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) { | |||
| ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) * | |||
| (pt->compressed ? ps->height/4 : ps->height) * | |||
| ps->width * ps->cpp; | |||
| } | |||
| else { | |||
| assert(face == 0); | |||
| assert(zslice == 0); | |||
| } | |||
| } | |||
| return ps; | |||
| } | |||
| static 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 < softpipe->num_textures; unit++) { | |||
| if (softpipe->texture[unit] == texture) { | |||
| sp_flush_tile_cache(softpipe, softpipe->tex_cache[unit]); | |||
| } | |||
| } | |||
| } | |||
| void | |||
| softpipe_init_texture_funcs( struct softpipe_context *softpipe ) | |||
| { | |||
| softpipe->pipe.texture_update = softpipe_texture_update; | |||
| } | |||
| void | |||
| softpipe_init_screen_texture_funcs(struct pipe_screen *screen) | |||
| { | |||
| screen->texture_create = softpipe_texture_create_screen; | |||
| screen->texture_release = softpipe_texture_release_screen; | |||
| screen->get_tex_surface = softpipe_get_tex_surface_screen; | |||
| } | |||
| @@ -121,7 +121,8 @@ uint32_t debug_mask_get(uint32_t uuid); | |||
| * @code | |||
| * #define MYDRIVER_UUID 0x12345678 // random 32 bit identifier | |||
| * | |||
| * static inline mydriver_debug(uint32_t what, const char *format, ...) | |||
| * static void inline | |||
| * mydriver_debug(uint32_t what, const char *format, ...) | |||
| * { | |||
| * #ifdef DEBUG | |||
| * va_list ap; | |||
| @@ -0,0 +1,65 @@ | |||
| /************************************************************************** | |||
| * | |||
| * 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 | |||
| * Gallium error codes. | |||
| * | |||
| * @author José Fonseca <jrfonseca@tungstengraphics.com> | |||
| */ | |||
| #ifndef P_ERROR_H_ | |||
| #define P_ERROR_H_ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| /** | |||
| * Gallium error codes. | |||
| * | |||
| * - A zero value always means success. | |||
| * - A negative value always means failure. | |||
| * - The meaning of a positive value is function dependent. | |||
| */ | |||
| enum pipe_error { | |||
| PIPE_OK = 0, | |||
| PIPE_ERROR = -1, /**< Generic error */ | |||
| PIPE_ERROR_BAD_INPUT = -2, | |||
| PIPE_ERROR_OUT_OF_MEMORY = -3, | |||
| PIPE_ERROR_RETRY = -4 | |||
| /* TODO */ | |||
| }; | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| #endif /* P_ERROR_H_ */ | |||
| @@ -227,22 +227,22 @@ struct tgsi_immediate_float32 | |||
| #define TGSI_OPCODE_STR 51 | |||
| #define TGSI_OPCODE_TEX 52 | |||
| #define TGSI_OPCODE_TXD 53 | |||
| #define TGSI_OPCODE_TXP 134 | |||
| #define TGSI_OPCODE_UP2H 54 | |||
| #define TGSI_OPCODE_UP2US 55 | |||
| #define TGSI_OPCODE_UP4B 56 | |||
| #define TGSI_OPCODE_UP4UB 57 | |||
| #define TGSI_OPCODE_X2D 58 | |||
| #define TGSI_OPCODE_TXP 54 | |||
| #define TGSI_OPCODE_UP2H 55 | |||
| #define TGSI_OPCODE_UP2US 56 | |||
| #define TGSI_OPCODE_UP4B 57 | |||
| #define TGSI_OPCODE_UP4UB 58 | |||
| #define TGSI_OPCODE_X2D 59 | |||
| /* | |||
| * GL_NV_vertex_program2 | |||
| */ | |||
| #define TGSI_OPCODE_ARA 59 | |||
| #define TGSI_OPCODE_ARR 60 | |||
| #define TGSI_OPCODE_BRA 61 | |||
| #define TGSI_OPCODE_CAL 62 | |||
| #define TGSI_OPCODE_RET 63 | |||
| #define TGSI_OPCODE_SSG 64 | |||
| #define TGSI_OPCODE_ARA 60 | |||
| #define TGSI_OPCODE_ARR 61 | |||
| #define TGSI_OPCODE_BRA 62 | |||
| #define TGSI_OPCODE_CAL 63 | |||
| #define TGSI_OPCODE_RET 64 | |||
| #define TGSI_OPCODE_SSG 65 | |||
| /* | |||
| * GL_ARB_vertex_program | |||
| @@ -253,9 +253,9 @@ struct tgsi_immediate_float32 | |||
| /* | |||
| * GL_ARB_fragment_program | |||
| */ | |||
| #define TGSI_OPCODE_CMP 65 | |||
| #define TGSI_OPCODE_SCS 66 | |||
| #define TGSI_OPCODE_TXB 67 | |||
| #define TGSI_OPCODE_CMP 66 | |||
| #define TGSI_OPCODE_SCS 67 | |||
| #define TGSI_OPCODE_TXB 68 | |||
| /* | |||
| * GL_NV_fragment_program_option | |||
| @@ -265,19 +265,19 @@ struct tgsi_immediate_float32 | |||
| /* | |||
| * GL_NV_fragment_program2 | |||
| */ | |||
| #define TGSI_OPCODE_NRM 68 | |||
| #define TGSI_OPCODE_DIV 69 | |||
| #define TGSI_OPCODE_DP2 70 | |||
| #define TGSI_OPCODE_NRM 69 | |||
| #define TGSI_OPCODE_DIV 70 | |||
| #define TGSI_OPCODE_DP2 71 | |||
| #define TGSI_OPCODE_DP2A TGSI_OPCODE_DOT2ADD | |||
| #define TGSI_OPCODE_TXL 71 | |||
| #define TGSI_OPCODE_BRK 72 | |||
| #define TGSI_OPCODE_IF 73 | |||
| #define TGSI_OPCODE_LOOP 74 | |||
| #define TGSI_OPCODE_REP 75 | |||
| #define TGSI_OPCODE_ELSE 76 | |||
| #define TGSI_OPCODE_ENDIF 77 | |||
| #define TGSI_OPCODE_ENDLOOP 78 | |||
| #define TGSI_OPCODE_ENDREP 79 | |||
| #define TGSI_OPCODE_TXL 72 | |||
| #define TGSI_OPCODE_BRK 73 | |||
| #define TGSI_OPCODE_IF 74 | |||
| #define TGSI_OPCODE_LOOP 75 | |||
| #define TGSI_OPCODE_REP 76 | |||
| #define TGSI_OPCODE_ELSE 77 | |||
| #define TGSI_OPCODE_ENDIF 78 | |||
| #define TGSI_OPCODE_ENDLOOP 79 | |||
| #define TGSI_OPCODE_ENDREP 80 | |||
| /* | |||
| * GL_NV_vertex_program2_option | |||
| @@ -286,26 +286,26 @@ struct tgsi_immediate_float32 | |||
| /* | |||
| * GL_NV_vertex_program3 | |||
| */ | |||
| #define TGSI_OPCODE_PUSHA 80 | |||
| #define TGSI_OPCODE_POPA 81 | |||
| #define TGSI_OPCODE_PUSHA 81 | |||
| #define TGSI_OPCODE_POPA 82 | |||
| /* | |||
| * GL_NV_gpu_program4 | |||
| */ | |||
| #define TGSI_OPCODE_CEIL 82 | |||
| #define TGSI_OPCODE_I2F 83 | |||
| #define TGSI_OPCODE_NOT 84 | |||
| #define TGSI_OPCODE_TRUNC 85 | |||
| #define TGSI_OPCODE_SHL 86 | |||
| #define TGSI_OPCODE_SHR 87 | |||
| #define TGSI_OPCODE_AND 88 | |||
| #define TGSI_OPCODE_OR 89 | |||
| #define TGSI_OPCODE_MOD 90 | |||
| #define TGSI_OPCODE_XOR 91 | |||
| #define TGSI_OPCODE_SAD 92 | |||
| #define TGSI_OPCODE_TXF 93 | |||
| #define TGSI_OPCODE_TXQ 94 | |||
| #define TGSI_OPCODE_CONT 95 | |||
| #define TGSI_OPCODE_CEIL 83 | |||
| #define TGSI_OPCODE_I2F 84 | |||
| #define TGSI_OPCODE_NOT 85 | |||
| #define TGSI_OPCODE_TRUNC 86 | |||
| #define TGSI_OPCODE_SHL 87 | |||
| #define TGSI_OPCODE_SHR 88 | |||
| #define TGSI_OPCODE_AND 89 | |||
| #define TGSI_OPCODE_OR 90 | |||
| #define TGSI_OPCODE_MOD 91 | |||
| #define TGSI_OPCODE_XOR 92 | |||
| #define TGSI_OPCODE_SAD 93 | |||
| #define TGSI_OPCODE_TXF 94 | |||
| #define TGSI_OPCODE_TXQ 95 | |||
| #define TGSI_OPCODE_CONT 96 | |||
| /* | |||
| * GL_NV_vertex_program4 | |||
| @@ -321,72 +321,53 @@ struct tgsi_immediate_float32 | |||
| * GL_NV_geometry_program4 | |||
| */ | |||
| /* Same as GL_NV_gpu_program4 */ | |||
| #define TGSI_OPCODE_EMIT 96 | |||
| #define TGSI_OPCODE_ENDPRIM 97 | |||
| #define TGSI_OPCODE_EMIT 97 | |||
| #define TGSI_OPCODE_ENDPRIM 98 | |||
| /* | |||
| * GLSL | |||
| */ | |||
| #define TGSI_OPCODE_BGNLOOP2 98 | |||
| #define TGSI_OPCODE_BGNSUB 99 | |||
| #define TGSI_OPCODE_ENDLOOP2 100 | |||
| #define TGSI_OPCODE_ENDSUB 101 | |||
| #define TGSI_OPCODE_BGNLOOP2 99 | |||
| #define TGSI_OPCODE_BGNSUB 100 | |||
| #define TGSI_OPCODE_ENDLOOP2 101 | |||
| #define TGSI_OPCODE_ENDSUB 102 | |||
| #define TGSI_OPCODE_INT TGSI_OPCODE_TRUNC | |||
| #define TGSI_OPCODE_NOISE1 102 | |||
| #define TGSI_OPCODE_NOISE2 103 | |||
| #define TGSI_OPCODE_NOISE3 104 | |||
| #define TGSI_OPCODE_NOISE4 105 | |||
| #define TGSI_OPCODE_NOP 106 | |||
| #define TGSI_OPCODE_NOISE1 103 | |||
| #define TGSI_OPCODE_NOISE2 104 | |||
| #define TGSI_OPCODE_NOISE3 105 | |||
| #define TGSI_OPCODE_NOISE4 106 | |||
| #define TGSI_OPCODE_NOP 107 | |||
| /* | |||
| * ps_1_1 | |||
| */ | |||
| #define TGSI_OPCODE_TEXCOORD TGSI_OPCODE_NOP | |||
| #define TGSI_OPCODE_TEXKILL TGSI_OPCODE_KILP | |||
| #define TGSI_OPCODE_TEXBEM 107 | |||
| #define TGSI_OPCODE_TEXBEML 108 | |||
| #define TGSI_OPCODE_TEXREG2AR 109 | |||
| #define TGSI_OPCODE_TEXM3X2PAD 110 | |||
| #define TGSI_OPCODE_TEXM3X2TEX 111 | |||
| #define TGSI_OPCODE_TEXM3X3PAD 112 | |||
| #define TGSI_OPCODE_TEXM3X3TEX 113 | |||
| #define TGSI_OPCODE_TEXM3X3SPEC 114 | |||
| #define TGSI_OPCODE_TEXM3X3VSPEC 115 | |||
| /* | |||
| * ps_1_2 | |||
| */ | |||
| #define TGSI_OPCODE_TEXREG2GB 116 | |||
| #define TGSI_OPCODE_TEXREG2RGB 117 | |||
| #define TGSI_OPCODE_TEXDP3TEX 118 | |||
| #define TGSI_OPCODE_TEXDP3 119 | |||
| #define TGSI_OPCODE_TEXM3X3 120 | |||
| /* CMP - use TGSI_OPCODE_CND0 */ | |||
| /* | |||
| * ps_1_3 | |||
| */ | |||
| #define TGSI_OPCODE_TEXM3X2DEPTH 121 | |||
| /* CMP - use TGSI_OPCODE_CND0 */ | |||
| /* | |||
| * ps_1_4 | |||
| */ | |||
| #define TGSI_OPCODE_TEXCRD TGSI_OPCODE_TEXCOORD | |||
| #define TGSI_OPCODE_TEXLD TGSI_OPCODE_TEX | |||
| #define TGSI_OPCODE_TEXDEPTH 122 | |||
| #define TGSI_OPCODE_BEM 123 | |||
| /* | |||
| * ps_2_0 | |||
| */ | |||
| #define TGSI_OPCODE_M4X4 TGSI_OPCODE_MULTIPLYMATRIX | |||
| #define TGSI_OPCODE_M4X3 124 | |||
| #define TGSI_OPCODE_M3X4 125 | |||
| #define TGSI_OPCODE_M3X3 126 | |||
| #define TGSI_OPCODE_M3X2 127 | |||
| #define TGSI_OPCODE_M4X3 108 | |||
| #define TGSI_OPCODE_M3X4 109 | |||
| #define TGSI_OPCODE_M3X3 110 | |||
| #define TGSI_OPCODE_M3X2 111 | |||
| #define TGSI_OPCODE_CRS TGSI_OPCODE_XPD | |||
| #define TGSI_OPCODE_NRM4 128 | |||
| #define TGSI_OPCODE_NRM4 112 | |||
| #define TGSI_OPCODE_SINCOS TGSI_OPCODE_SCS | |||
| #define TGSI_OPCODE_TEXLDB TGSI_OPCODE_TXB | |||
| #define TGSI_OPCODE_DP2ADD TGSI_OPCODE_DP2A | |||
| @@ -395,10 +376,10 @@ struct tgsi_immediate_float32 | |||
| * ps_2_x | |||
| */ | |||
| #define TGSI_OPCODE_CALL TGSI_OPCODE_CAL | |||
| #define TGSI_OPCODE_CALLNZ 129 | |||
| #define TGSI_OPCODE_IFC 130 | |||
| #define TGSI_OPCODE_CALLNZ 113 | |||
| #define TGSI_OPCODE_IFC 114 | |||
| #define TGSI_OPCODE_BREAK TGSI_OPCODE_BRK | |||
| #define TGSI_OPCODE_BREAKC 131 | |||
| #define TGSI_OPCODE_BREAKC 115 | |||
| #define TGSI_OPCODE_DSX TGSI_OPCODE_DDX | |||
| #define TGSI_OPCODE_DSY TGSI_OPCODE_DDY | |||
| #define TGSI_OPCODE_TEXLDD TGSI_OPCODE_TXD | |||
| @@ -419,10 +400,10 @@ struct tgsi_immediate_float32 | |||
| * vs_2_x | |||
| */ | |||
| #define TGSI_OPCODE_KIL 132 /* unpredicated kill */ | |||
| #define TGSI_OPCODE_END 133 /* aka HALT */ | |||
| #define TGSI_OPCODE_KIL 116 /* unpredicated kill */ | |||
| #define TGSI_OPCODE_END 117 /* aka HALT */ | |||
| #define TGSI_OPCODE_LAST 135 | |||
| #define TGSI_OPCODE_LAST 118 | |||
| #define TGSI_SAT_NONE 0 /* do not saturate */ | |||
| #define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */ | |||
| @@ -110,6 +110,7 @@ struct pipe_rasterizer_state | |||
| unsigned line_stipple_pattern:16; | |||
| unsigned line_last_pixel:1; | |||
| unsigned bypass_clipping:1; | |||
| unsigned bypass_vs:1; /**< vertices are already fully transformed */ | |||
| unsigned origin_lower_left:1; /**< Is (0,0) the lower-left corner? */ | |||
| float line_width; | |||
| @@ -162,13 +163,6 @@ struct pipe_constant_buffer | |||
| struct pipe_shader_state | |||
| { | |||
| const struct tgsi_token *tokens; | |||
| /* XXX these are going away */ | |||
| ubyte num_inputs; | |||
| ubyte num_outputs; | |||
| ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; /**< TGSI_SEMANTIC_x */ | |||
| ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; | |||
| ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */ | |||
| ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; | |||
| }; | |||
| @@ -18,3 +18,7 @@ subdirs: | |||
| clean: | |||
| rm -f `find . -name \*.[oa]` | |||
| # Dummy install target | |||
| install: | |||
| @@ -1398,12 +1398,13 @@ static void build_pointsize( struct tnl_program *p ) | |||
| /* 1 / sqrt(factor) */ | |||
| emit_op1(p, OPCODE_RSQ, ut, WRITEMASK_X, ut ); | |||
| #if 1 | |||
| #if 0 | |||
| /* out = pointSize / sqrt(factor) */ | |||
| emit_op2(p, OPCODE_MUL, out, WRITEMASK_X, ut, state_size); | |||
| #else | |||
| /* not sure, might make sense to do clamping here, | |||
| but it's not done in t_vb_points neither */ | |||
| /* this is a good place to clamp the point size since there's likely | |||
| * no hardware registers to clamp point size at rasterization time. | |||
| */ | |||
| emit_op2(p, OPCODE_MUL, ut, WRITEMASK_X, ut, state_size); | |||
| emit_op2(p, OPCODE_MAX, ut, WRITEMASK_X, ut, swizzle1(state_size, Y)); | |||
| emit_op2(p, OPCODE_MIN, out, WRITEMASK_X, ut, swizzle1(state_size, Z)); | |||
| @@ -1087,7 +1087,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, | |||
| slang_operation_copy(inlined, fun->body); | |||
| /*** XXX review this */ | |||
| assert(inlined->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE); | |||
| assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE); | |||
| inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE; | |||
| #if 0 | |||
| @@ -677,6 +677,7 @@ static struct prog_instruction * | |||
| emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n) | |||
| { | |||
| struct prog_instruction *inst; | |||
| slang_ir_node tmpNode; | |||
| assert(n->Opcode == IR_CLAMP); | |||
| /* ch[0] = value | |||
| @@ -722,18 +723,27 @@ emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n) | |||
| emit(emitInfo, n->Children[1]); | |||
| emit(emitInfo, n->Children[2]); | |||
| /* Some GPUs don't allow reading from output registers. So if the | |||
| * dest for this clamp() is an output reg, we can't use that reg for | |||
| * the intermediate result. Use a temp register instead. | |||
| */ | |||
| _mesa_bzero(&tmpNode, sizeof(tmpNode)); | |||
| alloc_temp_storage(emitInfo, &tmpNode, n->Store->Size); | |||
| /* tmp = max(ch[0], ch[1]) */ | |||
| inst = new_instruction(emitInfo, OPCODE_MAX); | |||
| storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); | |||
| storage_to_dst_reg(&inst->DstReg, tmpNode.Store, n->Writemask); | |||
| storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store); | |||
| storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store); | |||
| /* tmp = min(tmp, ch[2]) */ | |||
| /* n->dest = min(tmp, ch[2]) */ | |||
| inst = new_instruction(emitInfo, OPCODE_MIN); | |||
| storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask); | |||
| storage_to_src_reg(&inst->SrcReg[0], n->Store); | |||
| storage_to_src_reg(&inst->SrcReg[0], tmpNode.Store); | |||
| storage_to_src_reg(&inst->SrcReg[1], n->Children[2]->Store); | |||
| free_temp_storage(emitInfo->vt, &tmpNode); | |||
| return inst; | |||
| } | |||
| @@ -223,7 +223,12 @@ static void update_raster_state( struct st_context *st ) | |||
| raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled; | |||
| } | |||
| } | |||
| if (!raster->point_size_per_vertex) { | |||
| /* clamp size now */ | |||
| raster->point_size = CLAMP(ctx->Point.Size, | |||
| ctx->Point.MinSize, | |||
| ctx->Point.MaxSize); | |||
| } | |||
| /* _NEW_LINE | |||
| */ | |||
| @@ -52,7 +52,8 @@ | |||
| #include "cso_cache/cso_context.h" | |||
| /* XXX for testing draw module vertex passthrough: */ | |||
| #define TEST_DRAW_PASSTHROUGH 0 | |||
| static GLuint | |||
| @@ -229,6 +230,12 @@ draw_quad(GLcontext *ctx, | |||
| GLfloat verts[4][2][4]; /* four verts, two attribs, XYZW */ | |||
| GLuint i; | |||
| #if TEST_DRAW_PASSTHROUGH | |||
| /* invert Y coords (may be off by one pixel) */ | |||
| y0 = ctx->DrawBuffer->Height - y0; | |||
| y1 = ctx->DrawBuffer->Height - y1; | |||
| #endif | |||
| /* positions */ | |||
| verts[0][0][0] = x0; | |||
| verts[0][0][1] = y0; | |||
| @@ -252,7 +259,13 @@ draw_quad(GLcontext *ctx, | |||
| verts[i][1][3] = color[3]; | |||
| } | |||
| st_draw_vertices(ctx, PIPE_PRIM_QUADS, 4, (float *) verts, 2, GL_FALSE); | |||
| st_draw_vertices(ctx, PIPE_PRIM_POLYGON, 4, (float *) verts, 2, | |||
| #if TEST_DRAW_PASSTHROUGH | |||
| GL_TRUE | |||
| #else | |||
| GL_FALSE | |||
| #endif | |||
| ); | |||
| } | |||
| @@ -335,6 +348,10 @@ clear_with_quad(GLcontext *ctx, | |||
| */ | |||
| if (ctx->Scissor.Enabled) | |||
| raster.scissor = 1; | |||
| #endif | |||
| #if TEST_DRAW_PASSTHROUGH | |||
| raster.bypass_clipping = 1; | |||
| raster.bypass_vs = 1; | |||
| #endif | |||
| cso_set_rasterizer(st->cso_context, &raster); | |||
| } | |||
| @@ -348,6 +365,7 @@ clear_with_quad(GLcontext *ctx, | |||
| pipe->bind_fs_state(pipe, stfp->driver_shader); | |||
| } | |||
| #if !TEST_DRAW_PASSTHROUGH | |||
| /* vertex shader state: color/position pass-through */ | |||
| { | |||
| static struct st_vertex_program *stvp = NULL; | |||
| @@ -356,7 +374,9 @@ clear_with_quad(GLcontext *ctx, | |||
| } | |||
| pipe->bind_vs_state(pipe, stvp->driver_shader); | |||
| } | |||
| #endif | |||
| #if !TEST_DRAW_PASSTHROUGH | |||
| /* viewport state: viewport matching window dims */ | |||
| { | |||
| const float width = ctx->DrawBuffer->Width; | |||
| @@ -372,6 +392,7 @@ clear_with_quad(GLcontext *ctx, | |||
| vp.translate[3] = 0.0; | |||
| pipe->set_viewport_state(pipe, &vp); | |||
| } | |||
| #endif | |||
| /* draw quad matching scissor rect (XXX verify coord round-off) */ | |||
| draw_quad(ctx, x0, y0, x1, y1, ctx->Depth.Clear, ctx->Color.ClearColor); | |||
| @@ -178,6 +178,11 @@ static void st_program_string_notify( GLcontext *ctx, | |||
| stfp->param_state = stfp->Base.Base.Parameters->StateFlags; | |||
| if (stfp->state.tokens) { | |||
| FREE((void *) stfp->state.tokens); | |||
| stfp->state.tokens = NULL; | |||
| } | |||
| if (st->fp == stfp) | |||
| st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM; | |||
| } | |||
| @@ -201,6 +206,11 @@ static void st_program_string_notify( GLcontext *ctx, | |||
| stvp->param_state = stvp->Base.Base.Parameters->StateFlags; | |||
| if (stvp->state.tokens) { | |||
| FREE((void *) stvp->state.tokens); | |||
| stvp->state.tokens = NULL; | |||
| } | |||
| if (st->vp == stvp) | |||
| st->dirty.st |= ST_NEW_VERTEX_PROGRAM; | |||
| } | |||
| @@ -52,10 +52,12 @@ st_print_current(void) | |||
| struct st_context *st = ctx->st; | |||
| int i; | |||
| #if 0 | |||
| printf("Vertex Transform Inputs:\n"); | |||
| for (i = 0; i < st->vp->state.num_inputs; i++) { | |||
| printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]); | |||
| } | |||
| #endif | |||
| tgsi_dump( st->vp->state.tokens, 0 ); | |||
| if (st->vp->Base.Base.Parameters) | |||
| @@ -223,7 +223,7 @@ st_draw_vbo(GLcontext *ctx, | |||
| /* loop over TGSI shader inputs to determine vertex buffer | |||
| * and attribute info | |||
| */ | |||
| for (attr = 0; attr < vs->num_inputs; attr++) { | |||
| for (attr = 0; attr < /*vs*/vp->num_inputs; attr++) { | |||
| const GLuint mesaAttr = vp->index_to_input[attr]; | |||
| struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; | |||
| struct pipe_vertex_element velement; | |||
| @@ -333,7 +333,7 @@ st_draw_vbo(GLcontext *ctx, | |||
| } | |||
| /* unreference buffers (frees wrapped user-space buffer objects) */ | |||
| for (attr = 0; attr < vs->num_inputs; attr++) { | |||
| for (attr = 0; attr < /*vs*/vp->num_inputs; attr++) { | |||
| pipe_buffer_reference(winsys, &vbuffer[attr].buffer, NULL); | |||
| assert(!vbuffer[attr].buffer); | |||
| pipe->set_vertex_buffer(pipe, attr, &vbuffer[attr]); | |||
| @@ -502,7 +502,7 @@ st_feedback_draw_vbo(GLcontext *ctx, | |||
| /* loop over TGSI shader inputs to determine vertex buffer | |||
| * and attribute info | |||
| */ | |||
| for (attr = 0; attr < vs->num_inputs; attr++) { | |||
| for (attr = 0; attr < /*vs*/vp->num_inputs; attr++) { | |||
| const GLuint mesaAttr = vp->index_to_input[attr]; | |||
| struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj; | |||
| struct pipe_vertex_element velement; | |||
| @@ -85,6 +85,14 @@ st_translate_vertex_program(struct st_context *st, | |||
| GLuint num_generic = 0; | |||
| GLuint num_tokens; | |||
| ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; | |||
| ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; | |||
| uint vs_num_inputs = 0; | |||
| ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; | |||
| ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; | |||
| uint vs_num_outputs = 0; | |||
| memset(&vs, 0, sizeof(vs)); | |||
| /* | |||
| @@ -93,36 +101,36 @@ st_translate_vertex_program(struct st_context *st, | |||
| */ | |||
| for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { | |||
| if (stvp->Base.Base.InputsRead & (1 << attr)) { | |||
| const GLuint slot = vs.num_inputs; | |||
| const GLuint slot = vs_num_inputs; | |||
| vs.num_inputs++; | |||
| vs_num_inputs++; | |||
| stvp->input_to_index[attr] = slot; | |||
| stvp->index_to_input[slot] = attr; | |||
| switch (attr) { | |||
| case VERT_ATTRIB_POS: | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| vs.input_semantic_index[slot] = 0; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| vs_input_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_ATTRIB_WEIGHT: | |||
| /* fall-through */ | |||
| case VERT_ATTRIB_NORMAL: | |||
| /* just label as a generic */ | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs.input_semantic_index[slot] = 0; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs_input_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_ATTRIB_COLOR0: | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs.input_semantic_index[slot] = 0; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs_input_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_ATTRIB_COLOR1: | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs.input_semantic_index[slot] = 1; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs_input_semantic_index[slot] = 1; | |||
| break; | |||
| case VERT_ATTRIB_FOG: | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| vs.input_semantic_index[slot] = 0; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| vs_input_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_ATTRIB_TEX0: | |||
| case VERT_ATTRIB_TEX1: | |||
| @@ -132,8 +140,8 @@ st_translate_vertex_program(struct st_context *st, | |||
| case VERT_ATTRIB_TEX5: | |||
| case VERT_ATTRIB_TEX6: | |||
| case VERT_ATTRIB_TEX7: | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs.input_semantic_index[slot] = num_generic++; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs_input_semantic_index[slot] = num_generic++; | |||
| break; | |||
| case VERT_ATTRIB_GENERIC0: | |||
| case VERT_ATTRIB_GENERIC1: | |||
| @@ -144,8 +152,8 @@ st_translate_vertex_program(struct st_context *st, | |||
| case VERT_ATTRIB_GENERIC6: | |||
| case VERT_ATTRIB_GENERIC7: | |||
| assert(attr < VERT_ATTRIB_MAX); | |||
| vs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs.input_semantic_index[slot] = num_generic++; | |||
| vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs_input_semantic_index[slot] = num_generic++; | |||
| break; | |||
| default: | |||
| assert(0); | |||
| @@ -155,8 +163,8 @@ st_translate_vertex_program(struct st_context *st, | |||
| /* initialize output semantics to defaults */ | |||
| for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { | |||
| vs.output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; | |||
| vs.output_semantic_index[i] = 0; | |||
| vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; | |||
| vs_output_semantic_index[i] = 0; | |||
| } | |||
| num_generic = 0; | |||
| @@ -173,8 +181,8 @@ st_translate_vertex_program(struct st_context *st, | |||
| assert(slot != ~0); | |||
| } | |||
| else { | |||
| slot = vs.num_outputs; | |||
| vs.num_outputs++; | |||
| slot = vs_num_outputs; | |||
| vs_num_outputs++; | |||
| defaultOutputMapping[attr] = slot; | |||
| } | |||
| @@ -185,32 +193,32 @@ st_translate_vertex_program(struct st_context *st, | |||
| switch (attr) { | |||
| case VERT_RESULT_HPOS: | |||
| assert(slot == 0); | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| vs.output_semantic_index[slot] = 0; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| vs_output_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_RESULT_COL0: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs.output_semantic_index[slot] = 0; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs_output_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_RESULT_COL1: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs.output_semantic_index[slot] = 1; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| vs_output_semantic_index[slot] = 1; | |||
| break; | |||
| case VERT_RESULT_BFC0: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; | |||
| vs.output_semantic_index[slot] = 0; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; | |||
| vs_output_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_RESULT_BFC1: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; | |||
| vs.output_semantic_index[slot] = 1; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; | |||
| vs_output_semantic_index[slot] = 1; | |||
| break; | |||
| case VERT_RESULT_FOGC: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| vs.output_semantic_index[slot] = 0; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| vs_output_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_RESULT_PSIZ: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; | |||
| vs.output_semantic_index[slot] = 0; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; | |||
| vs_output_semantic_index[slot] = 0; | |||
| break; | |||
| case VERT_RESULT_EDGE: | |||
| assert(0); | |||
| @@ -223,30 +231,30 @@ st_translate_vertex_program(struct st_context *st, | |||
| case VERT_RESULT_TEX5: | |||
| case VERT_RESULT_TEX6: | |||
| case VERT_RESULT_TEX7: | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs.output_semantic_index[slot] = num_generic++; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs_output_semantic_index[slot] = num_generic++; | |||
| break; | |||
| case VERT_RESULT_VAR0: | |||
| /* fall-through */ | |||
| default: | |||
| assert(attr - VERT_RESULT_VAR0 < MAX_VARYING); | |||
| vs.output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs.output_semantic_index[slot] = num_generic++; | |||
| vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| vs_output_semantic_index[slot] = num_generic++; | |||
| } | |||
| } | |||
| } | |||
| assert(vs.output_semantic_name[0] == TGSI_SEMANTIC_POSITION); | |||
| assert(vs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); | |||
| if (outputMapping) { | |||
| /* find max output slot referenced to compute vs.num_outputs */ | |||
| /* find max output slot referenced to compute vs_num_outputs */ | |||
| GLuint maxSlot = 0; | |||
| for (attr = 0; attr < VERT_RESULT_MAX; attr++) { | |||
| if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) | |||
| maxSlot = outputMapping[attr]; | |||
| } | |||
| vs.num_outputs = maxSlot + 1; | |||
| vs_num_outputs = maxSlot + 1; | |||
| } | |||
| else { | |||
| outputMapping = defaultOutputMapping; | |||
| @@ -257,22 +265,23 @@ st_translate_vertex_program(struct st_context *st, | |||
| num_tokens = tgsi_translate_mesa_program( TGSI_PROCESSOR_VERTEX, | |||
| &stvp->Base.Base, | |||
| /* inputs */ | |||
| vs.num_inputs, | |||
| vs_num_inputs, | |||
| stvp->input_to_index, | |||
| vs.input_semantic_name, | |||
| vs.input_semantic_index, | |||
| vs_input_semantic_name, | |||
| vs_input_semantic_index, | |||
| NULL, | |||
| /* outputs */ | |||
| vs.num_outputs, | |||
| vs_num_outputs, | |||
| outputMapping, | |||
| vs.output_semantic_name, | |||
| vs.output_semantic_index, | |||
| vs_output_semantic_name, | |||
| vs_output_semantic_index, | |||
| /* tokenized result */ | |||
| tokens, ST_MAX_SHADER_TOKENS); | |||
| vs.tokens = (struct tgsi_token *) | |||
| mem_dup(tokens, num_tokens * sizeof(tokens[0])); | |||
| stvp->num_inputs = vs_num_inputs; | |||
| stvp->state = vs; /* struct copy */ | |||
| stvp->driver_shader = pipe->create_vs_state(pipe, &vs); | |||
| @@ -310,6 +319,14 @@ st_translate_fragment_program(struct st_context *st, | |||
| GLuint num_generic = 0; | |||
| GLuint num_tokens; | |||
| ubyte fs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; | |||
| ubyte fs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; | |||
| uint fs_num_inputs = 0; | |||
| ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; | |||
| ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; | |||
| uint fs_num_outputs = 0; | |||
| memset(&fs, 0, sizeof(fs)); | |||
| /* which vertex output goes to the first fragment input: */ | |||
| @@ -323,33 +340,33 @@ st_translate_fragment_program(struct st_context *st, | |||
| */ | |||
| for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { | |||
| if (inputsRead & (1 << attr)) { | |||
| const GLuint slot = fs.num_inputs; | |||
| const GLuint slot = fs_num_inputs; | |||
| defaultInputMapping[attr] = slot; | |||
| stfp->input_map[slot] = vslot++; | |||
| fs.num_inputs++; | |||
| fs_num_inputs++; | |||
| switch (attr) { | |||
| case FRAG_ATTRIB_WPOS: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| fs.input_semantic_index[slot] = 0; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; | |||
| fs_input_semantic_index[slot] = 0; | |||
| interpMode[slot] = TGSI_INTERPOLATE_LINEAR; | |||
| break; | |||
| case FRAG_ATTRIB_COL0: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| fs.input_semantic_index[slot] = 0; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| fs_input_semantic_index[slot] = 0; | |||
| interpMode[slot] = TGSI_INTERPOLATE_LINEAR; | |||
| break; | |||
| case FRAG_ATTRIB_COL1: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| fs.input_semantic_index[slot] = 1; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; | |||
| fs_input_semantic_index[slot] = 1; | |||
| interpMode[slot] = TGSI_INTERPOLATE_LINEAR; | |||
| break; | |||
| case FRAG_ATTRIB_FOGC: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| fs.input_semantic_index[slot] = 0; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; | |||
| fs_input_semantic_index[slot] = 0; | |||
| interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; | |||
| break; | |||
| case FRAG_ATTRIB_TEX0: | |||
| @@ -360,15 +377,15 @@ st_translate_fragment_program(struct st_context *st, | |||
| case FRAG_ATTRIB_TEX5: | |||
| case FRAG_ATTRIB_TEX6: | |||
| case FRAG_ATTRIB_TEX7: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| fs.input_semantic_index[slot] = num_generic++; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| fs_input_semantic_index[slot] = num_generic++; | |||
| interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; | |||
| break; | |||
| case FRAG_ATTRIB_VAR0: | |||
| /* fall-through */ | |||
| default: | |||
| fs.input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| fs.input_semantic_index[slot] = num_generic++; | |||
| fs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; | |||
| fs_input_semantic_index[slot] = num_generic++; | |||
| interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; | |||
| } | |||
| } | |||
| @@ -383,10 +400,10 @@ st_translate_fragment_program(struct st_context *st, | |||
| /* if z is written, emit that first */ | |||
| if (outputsWritten & (1 << FRAG_RESULT_DEPR)) { | |||
| fs.output_semantic_name[fs.num_outputs] = TGSI_SEMANTIC_POSITION; | |||
| fs.output_semantic_index[fs.num_outputs] = 0; | |||
| outputMapping[FRAG_RESULT_DEPR] = fs.num_outputs; | |||
| fs.num_outputs++; | |||
| fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; | |||
| fs_output_semantic_index[fs_num_outputs] = 0; | |||
| outputMapping[FRAG_RESULT_DEPR] = fs_num_outputs; | |||
| fs_num_outputs++; | |||
| outputsWritten &= ~(1 << FRAG_RESULT_DEPR); | |||
| } | |||
| @@ -399,15 +416,15 @@ st_translate_fragment_program(struct st_context *st, | |||
| assert(0); | |||
| break; | |||
| case FRAG_RESULT_COLR: | |||
| fs.output_semantic_name[fs.num_outputs] = TGSI_SEMANTIC_COLOR; | |||
| fs.output_semantic_index[fs.num_outputs] = numColors; | |||
| outputMapping[attr] = fs.num_outputs; | |||
| fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; | |||
| fs_output_semantic_index[fs_num_outputs] = numColors; | |||
| outputMapping[attr] = fs_num_outputs; | |||
| numColors++; | |||
| break; | |||
| default: | |||
| assert(0); | |||
| } | |||
| fs.num_outputs++; | |||
| fs_num_outputs++; | |||
| } | |||
| } | |||
| } | |||
| @@ -420,16 +437,16 @@ st_translate_fragment_program(struct st_context *st, | |||
| num_tokens = tgsi_translate_mesa_program( TGSI_PROCESSOR_FRAGMENT, | |||
| &stfp->Base.Base, | |||
| /* inputs */ | |||
| fs.num_inputs, | |||
| fs_num_inputs, | |||
| inputMapping, | |||
| fs.input_semantic_name, | |||
| fs.input_semantic_index, | |||
| fs_input_semantic_name, | |||
| fs_input_semantic_index, | |||
| interpMode, | |||
| /* outputs */ | |||
| fs.num_outputs, | |||
| fs_num_outputs, | |||
| outputMapping, | |||
| fs.output_semantic_name, | |||
| fs.output_semantic_index, | |||
| fs_output_semantic_name, | |||
| fs_output_semantic_index, | |||
| /* tokenized result */ | |||
| tokens, ST_MAX_SHADER_TOKENS); | |||
| @@ -85,6 +85,8 @@ struct st_vertex_program | |||
| /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */ | |||
| GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; | |||
| GLuint num_inputs; | |||
| struct pipe_shader_state state; | |||
| struct pipe_shader_state *driver_shader; | |||
| @@ -309,23 +309,16 @@ static void vbo_exec_fixup_vertex( GLcontext *ctx, | |||
| GLuint attr, GLuint sz ) | |||
| { | |||
| struct vbo_exec_context *exec = &vbo_context(ctx)->exec; | |||
| static const GLfloat id[4] = { 0, 0, 0, 1 }; | |||
| int i; | |||
| if (exec->vtx.prim_count == 0) { | |||
| GLfloat *current = (GLfloat *)vbo_context(ctx)->currval[attr].Ptr; | |||
| exec->vtx.attrptr[attr] = current; | |||
| memcpy(current, id, sizeof(id)); | |||
| ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; | |||
| return; | |||
| } | |||
| else if (sz > exec->vtx.attrsz[attr]) { | |||
| if (sz > exec->vtx.attrsz[attr]) { | |||
| /* New size is larger. Need to flush existing vertices and get | |||
| * an enlarged vertex format. | |||
| */ | |||
| vbo_exec_wrap_upgrade_vertex( exec, attr, sz ); | |||
| } | |||
| else if (sz < exec->vtx.active_sz[attr]) { | |||
| static const GLfloat id[4] = { 0, 0, 0, 1 }; | |||
| /* New size is smaller - just need to fill in some | |||
| * zeros. Don't need to flush or wrap. | |||