Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1

This commit is contained in:
Ben Skeggs 2008-03-25 12:14:49 +11:00
commit 9e1f7b2c57
38 changed files with 1897 additions and 249 deletions

View file

@ -76,6 +76,8 @@ int textureWidth = 64;
int textureHeight = 64;
int winWidth = 580, winHeight = 720;
static int Win;
struct formatInfo {
GLenum baseFormat;
@ -288,6 +290,7 @@ static void keyboard( unsigned char c, int x, int y )
displayLevelInfo = !displayLevelInfo;
break;
case 27: /* Escape key should force exit. */
glutDestroyWindow(Win);
exit(0);
break;
default:
@ -785,7 +788,7 @@ int main( int argc, char *argv[] )
glutInitWindowSize( winWidth, winHeight );
glutInitWindowPosition( 0, 0 );
glutCreateWindow( "Texture Environment Test" );
Win = glutCreateWindow( "Texture Environment Test" );
initialize();
instructions();

View file

@ -29,6 +29,7 @@
*/
#include "pipe/p_util.h"
#include "pipe/p_debug.h"
#include "cso_cache.h"
#include "cso_hash.h"
@ -131,75 +132,77 @@ static int _cso_size_for_type(enum cso_cache_type type)
static void delete_blend_state(void *state, void *data)
{
struct cso_blend *cso = (struct cso_blend *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static void delete_depth_stencil_state(void *state, void *data)
{
struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static void delete_sampler_state(void *state, void *data)
{
struct cso_sampler *cso = (struct cso_sampler *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static void delete_rasterizer_state(void *state, void *data)
{
struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static void delete_fs_state(void *state, void *data)
{
struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static void delete_vs_state(void *state, void *data)
{
struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
if (cso->delete_state && cso->data != &cso->state)
if (cso->delete_state)
cso->delete_state(cso->context, cso->data);
FREE(state);
}
static INLINE void delete_cso(void *state, enum cso_cache_type type)
{
switch (type) {
case CSO_BLEND: {
case CSO_BLEND:
delete_blend_state(state, 0);
}
break;
case CSO_SAMPLER: {
case CSO_SAMPLER:
delete_sampler_state(state, 0);
}
break;
case CSO_DEPTH_STENCIL_ALPHA: {
case CSO_DEPTH_STENCIL_ALPHA:
delete_depth_stencil_state(state, 0);
}
break;
case CSO_RASTERIZER: {
case CSO_RASTERIZER:
delete_rasterizer_state(state, 0);
}
break;
case CSO_FRAGMENT_SHADER: {
case CSO_FRAGMENT_SHADER:
delete_fs_state(state, 0);
}
break;
case CSO_VERTEX_SHADER: {
case CSO_VERTEX_SHADER:
delete_vs_state(state, 0);
}
break;
default:
assert(0);
FREE(state);
}
FREE(state);
}
static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,

View file

@ -16,6 +16,10 @@ C_SOURCES = \
draw_flatshade.c \
draw_offset.c \
draw_passthrough.c \
draw_pt.c \
draw_pt_vcache.c \
draw_pt_fetch_emit.c \
draw_pt_elts.c \
draw_prim.c \
draw_pstipple.c \
draw_stipple.c \

View file

@ -14,7 +14,11 @@ draw = env.ConvenienceLibrary(
'draw_debug.c',
'draw_flatshade.c',
'draw_offset.c',
'draw_passthrough.c',
'draw_passthrough.c', # going away soon
'draw_pt.c',
'draw_pt_vcache.c',
'draw_pt_fetch_emit.c',
'draw_pt_elts.c',
'draw_prim.c',
'draw_pstipple.c',
'draw_stipple.c',

View file

@ -621,7 +621,7 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header)
bind_aaline_fragment_shader(aaline);
aaline->state.sampler[num] = aaline->sampler_cso;
aaline->state.texture[num] = aaline->texture;
pipe_texture_reference(&aaline->state.texture[num], aaline->texture);
aaline->driver_bind_sampler_states(pipe, num + 1, aaline->state.sampler);
aaline->driver_set_sampler_textures(pipe, num + 1, aaline->state.texture);
@ -769,9 +769,14 @@ aaline_set_sampler_textures(struct pipe_context *pipe,
unsigned num, struct pipe_texture **texture)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
uint i;
/* save current */
memcpy(aaline->state.texture, texture, num * sizeof(struct pipe_texture *));
for (i = 0; i < num; i++) {
pipe_texture_reference(&aaline->state.texture[i], texture[i]);
}
aaline->num_textures = num;
/* pass-through */
aaline->driver_set_sampler_textures(aaline->pipe, num, texture);
}

View file

@ -37,10 +37,11 @@
#include "draw_vbuf.h"
struct draw_context *draw_create( void )
{
struct draw_context *draw = CALLOC_STRUCT( draw_context );
if (draw == NULL)
goto fail;
#if defined(__i386__) || defined(__386__)
draw->use_sse = GETENV( "GALLIUM_NOSSE" ) == NULL;
@ -61,6 +62,19 @@ struct draw_context *draw_create( void )
draw->pipeline.validate = draw_validate_stage( draw );
draw->pipeline.first = draw->pipeline.validate;
if (!draw->pipeline.wide_line ||
!draw->pipeline.wide_point ||
!draw->pipeline.stipple ||
!draw->pipeline.unfilled ||
!draw->pipeline.twoside ||
!draw->pipeline.offset ||
!draw->pipeline.clip ||
!draw->pipeline.flatshade ||
!draw->pipeline.cull ||
!draw->pipeline.validate)
goto fail;
ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 );
ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 );
ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 );
@ -75,6 +89,8 @@ struct draw_context *draw_create( void )
uint i;
const unsigned size = (MAX_VERTEX_SIZE + 0x0f) & ~0x0f;
char *tmp = align_malloc(Elements(draw->vs.queue) * size, 16);
if (!tmp)
goto fail;
for (i = 0; i < Elements(draw->vs.queue); i++)
draw->vs.queue[i].vertex = (struct vertex_header *)(tmp + i * size);
@ -93,22 +109,42 @@ struct draw_context *draw_create( void )
draw_vertex_cache_invalidate( draw );
draw_set_mapped_element_buffer( draw, 0, NULL );
if (!draw_pt_init( draw ))
goto fail;
return draw;
fail:
draw_destroy( draw );
return NULL;
}
void draw_destroy( struct draw_context *draw )
{
draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
draw->pipeline.stipple->destroy( draw->pipeline.stipple );
draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
draw->pipeline.twoside->destroy( draw->pipeline.twoside );
draw->pipeline.offset->destroy( draw->pipeline.offset );
draw->pipeline.clip->destroy( draw->pipeline.clip );
draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
draw->pipeline.cull->destroy( draw->pipeline.cull );
draw->pipeline.validate->destroy( draw->pipeline.validate );
if (!draw)
return;
if (draw->pipeline.wide_line)
draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
if (draw->pipeline.wide_point)
draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
if (draw->pipeline.stipple)
draw->pipeline.stipple->destroy( draw->pipeline.stipple );
if (draw->pipeline.unfilled)
draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
if (draw->pipeline.twoside)
draw->pipeline.twoside->destroy( draw->pipeline.twoside );
if (draw->pipeline.offset)
draw->pipeline.offset->destroy( draw->pipeline.offset );
if (draw->pipeline.clip)
draw->pipeline.clip->destroy( draw->pipeline.clip );
if (draw->pipeline.flatshade)
draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
if (draw->pipeline.cull)
draw->pipeline.cull->destroy( draw->pipeline.cull );
if (draw->pipeline.validate)
draw->pipeline.validate->destroy( draw->pipeline.validate );
if (draw->pipeline.aaline)
draw->pipeline.aaline->destroy( draw->pipeline.aaline );
if (draw->pipeline.aapoint)
@ -117,8 +153,11 @@ void draw_destroy( struct draw_context *draw )
draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
if (draw->pipeline.rasterize)
draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
tgsi_exec_machine_free_data(&draw->machine);
align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
if (draw->vs.queue[0].vertex)
align_free( draw->vs.queue[0].vertex ); /* Frees all the vertices. */
/* Not so fast -- we're just borrowing this at the moment.
*
@ -126,6 +165,8 @@ void draw_destroy( struct draw_context *draw )
draw->render->destroy( draw->render );
*/
draw_pt_destroy( draw );
FREE( draw );
}

View file

@ -125,9 +125,9 @@ fetch_store_general( struct draw_context *draw,
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *ub = (ubyte *) from;
attrib[0] = UBYTE_TO_FLOAT(ub[0]);
attrib[2] = UBYTE_TO_FLOAT(ub[0]);
attrib[1] = UBYTE_TO_FLOAT(ub[1]);
attrib[2] = UBYTE_TO_FLOAT(ub[2]);
attrib[0] = UBYTE_TO_FLOAT(ub[2]);
attrib[3] = UBYTE_TO_FLOAT(ub[3]);
}
break;

View file

@ -526,7 +526,7 @@ draw_arrays(struct draw_context *draw, unsigned prim,
/* drawing done here: */
if (!draw->rasterizer->bypass_vs ||
!draw_passthrough_arrays(draw, prim, start, count)) {
!draw_pt_arrays(draw, prim, start, count)) {
/* we have to run the whole pipeline */
draw_prim(draw, prim, start, count);
}

View file

@ -53,6 +53,9 @@ struct pipe_context;
struct gallivm_prog;
struct gallivm_cpu_engine;
struct draw_pt_middle_end;
struct draw_pt_front_end;
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
@ -203,8 +206,21 @@ struct draw_context
/* Support prototype passthrough path:
*/
struct {
unsigned prim;
unsigned hw_vertex_size;
unsigned prim; /* XXX: to be removed */
unsigned hw_vertex_size; /* XXX: to be removed */
struct {
struct draw_pt_middle_end *fetch_emit;
struct draw_pt_middle_end *fetch_shade_emit;
struct draw_pt_middle_end *fetch_shade_cliptest_pipeline_or_emit;
} middle;
struct {
struct draw_pt_front_end *noop;
struct draw_pt_front_end *split_arrays;
struct draw_pt_front_end *vcache;
} front;
} pt;
@ -351,7 +367,18 @@ extern void draw_update_vertex_fetch( struct draw_context *draw );
extern boolean draw_need_pipeline(const struct draw_context *draw);
/* Prototype/hack
/* Passthrough mode (second attempt):
*/
boolean draw_pt_init( struct draw_context *draw );
void draw_pt_destroy( struct draw_context *draw );
boolean draw_pt_arrays( struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count );
/* Prototype/hack (DEPRECATED)
*/
boolean
draw_passthrough_arrays(struct draw_context *draw,

View file

@ -56,6 +56,7 @@ struct pstip_fragment_shader
struct pipe_shader_state state;
void *driver_fs;
void *pstip_fs;
uint sampler_unit;
};
@ -67,7 +68,6 @@ struct pstip_stage
struct draw_stage stage;
void *sampler_cso;
uint sampler_unit;
struct pipe_texture *texture;
uint num_samplers;
uint num_textures;
@ -329,7 +329,7 @@ generate_pstip_fs(struct pstip_stage *pstip)
tgsi_dump(pstip_fs.tokens, 0);
#endif
pstip->sampler_unit = transform.maxSampler + 1;
pstip->fs->sampler_unit = transform.maxSampler + 1;
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
}
@ -398,6 +398,7 @@ pstip_create_texture(struct pstip_stage *pstip)
texTemp.cpp = 1;
pstip->texture = screen->texture_create(screen, &texTemp);
assert(pstip->texture->refcount == 1);
//pstip_update_texture(pstip);
}
@ -488,11 +489,14 @@ pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
/* 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);
num_samplers = MAX2(num_samplers, pstip->fs->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;
pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
pipe_texture_reference(&pstip->state.textures[pstip->fs->sampler_unit],
pstip->texture);
assert(num_samplers <= PIPE_MAX_SAMPLERS);
pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
pstip->driver_set_sampler_textures(pipe, num_samplers, pstip->state.textures);
@ -624,8 +628,14 @@ pstip_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
uint i;
/* save current */
memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
pstip->state.samplers[i] = NULL;
}
pstip->num_samplers = num;
/* pass-through */
pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
@ -637,9 +647,18 @@ pstip_set_sampler_textures(struct pipe_context *pipe,
unsigned num, struct pipe_texture **texture)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
uint i;
/* save current */
memcpy(pstip->state.textures, texture, num * sizeof(struct pipe_texture *));
for (i = 0; i < num; i++) {
pipe_texture_reference(&pstip->state.textures[i], texture[i]);
}
for (; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&pstip->state.textures[i], NULL);
}
pstip->num_textures = num;
/* pass-through */
pstip->driver_set_sampler_textures(pstip->pipe, num, texture);
}

View file

@ -0,0 +1,206 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "pipe/p_util.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
static boolean too_many_verts( struct draw_context *draw,
unsigned verts )
{
return verts < 1024;
}
static boolean too_many_elts( struct draw_context *draw,
unsigned elts )
{
return elts < (16 * 1024);
}
boolean
draw_pt_arrays(struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count)
{
const boolean pipeline = draw_need_pipeline(draw);
const boolean cliptest = !draw->rasterizer->bypass_clipping;
const boolean shading = !draw->rasterizer->bypass_vs;
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
/* Overall we do:
* - frontend -- prepare fetch_elts, draw_elts - eg vcache
* - middle -- fetch, shade, cliptest, viewport
* - pipeline -- the prim pipeline: clipping, wide lines, etc
* - backend -- the vbuf_render provided by the driver.
*/
#if 0
if (!cliptest && !pipeline && !shading) {
/* This is the 'passthrough' path:
*/
/* Fetch user verts, emit hw verts:
*/
middle = draw->pt.middle.fetch_emit;
}
else if (!cliptest && !pipeline) {
/* Fetch user verts, run vertex shader, emit hw verts:
*/
middle = draw->pt.middle.fetch_shade_emit;
}
else if (!pipeline) {
/* Even though !pipeline, we have to run it to get clipping. We
* do know that the pipeline is just the clipping operation, but
* that probably doesn't help much.
*
* This is going to be the most important path for a lot of
* swtnl cards.
*/
/* Fetch user verts,
* run vertex shader,
* cliptest and viewport trasform
* if no clipped vertices,
* emit hw verts
* else
* run pipline
*/
middle = draw->pt.middle.fetch_shade_cliptest_pipeline_or_emit;
}
else if (!cliptest) {
/* Fetch user verts, run vertex shader, run pipeline:
*/
middle = draw->pt.middle.fetch_shade_pipeline;
}
else {
/* This is what we're currently always doing:
*/
/* Fetch user verts, run vertex shader, cliptest, run pipeline:
*/
middle = draw->pt.middle.fetch_shade_cliptest_pipeline;
}
#else
if (cliptest || pipeline || shading)
return FALSE;
middle = draw->pt.middle.fetch_emit;
#endif
/* If !pipeline, need to make sure we respect the driver's limited
* capabilites to receive blocks of vertex data and elements.
*/
#if 0
if (!pipeline) {
unsigned vertex_mode = passthrough;
unsigned nr_verts = count_vertices( draw, start, count );
unsigned hw_prim = prim;
if (is_elts(draw)) {
frontend = draw->pt.front.vcache;
hw_prim = reduced_prim(prim);
}
if (too_many_verts(nr_verts)) {
/* if (is_verts(draw) && can_split(prim)) {
draw = draw_arrays_split;
}
else */ {
frontend = draw->pt.front.vcache;
hw_prim = reduced_prim(prim);
}
}
if (too_many_elts(count)) {
/* if (is_elts(draw) && can_split(prim)) {
draw = draw_elts_split;
}
else */ {
frontend = draw->pt.front.vcache;
hw_prim = reduced_prim(prim);
}
}
if (!good_prim(hw_prim)) {
draw = draw->pt.front.vcache;
}
}
#else
frontend = draw->pt.front.vcache;
#endif
frontend->prepare( frontend, middle );
frontend->run( frontend,
prim,
draw_pt_elt_func( draw ),
draw_pt_elt_ptr( draw, start ),
count );
frontend->finish( frontend );
return TRUE;
}
boolean draw_pt_init( struct draw_context *draw )
{
draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
if (!draw->pt.middle.fetch_emit)
return FALSE;
draw->pt.front.vcache = draw_pt_vcache();
if (!draw->pt.front.vcache)
return FALSE;
return TRUE;
}
void draw_pt_destroy( struct draw_context *draw )
{
if (draw->pt.middle.fetch_emit) {
draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
draw->pt.middle.fetch_emit = NULL;
}
if (draw->pt.front.vcache) {
draw->pt.front.vcache->destroy( draw->pt.front.vcache );
draw->pt.front.vcache = NULL;
}
}

View file

@ -0,0 +1,118 @@
/**************************************************************************
*
* 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 DRAW_PT_H
#define DRAW_PT_H
#include "pipe/p_compiler.h"
typedef unsigned (*pt_elt_func)( const void *elts, unsigned idx );
struct draw_pt_middle_end;
struct draw_context;
/* The "front end" - prepare sets of fetch, draw elements for the
* middle end.
*
* Currenly one version of this:
* - vcache - catchall implementation, decomposes to TRI/LINE/POINT prims
* Later:
* - varray, varray_split
* - velement, velement_split
*
* Currenly only using the vcache version.
*/
struct draw_pt_front_end {
void (*prepare)( struct draw_pt_front_end *,
struct draw_pt_middle_end * );
void (*run)( struct draw_pt_front_end *,
unsigned prim,
pt_elt_func elt_func,
const void *elt_ptr,
unsigned count );
void (*finish)( struct draw_pt_front_end * );
void (*destroy)( struct draw_pt_front_end * );
};
/* The "middle end" - prepares actual hardware vertices for the
* hardware backend.
*
* Currently two versions of this:
* - fetch, vertex shade, cliptest, prim-pipeline
* - fetch, emit (ie passthrough)
* Later:
* - fetch, vertex shade, cliptest, maybe-pipeline, maybe-emit
* - fetch, vertex shade, emit
*
* Currenly only using the passthrough version.
*/
struct draw_pt_middle_end {
void (*prepare)( struct draw_pt_middle_end * );
void (*run)( struct draw_pt_middle_end *,
unsigned prim,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count );
void (*finish)( struct draw_pt_middle_end * );
void (*destroy)( struct draw_pt_middle_end * );
};
/* The "back end" - supplied by the driver, defined in draw_vbuf.h.
*
* Not sure whether to wrap the prim pipeline up as an alternate
* backend. Would be a win for everything except pure passthrough
* mode...
*/
struct vbuf_render;
/* Helper functions.
*/
pt_elt_func draw_pt_elt_func( struct draw_context *draw );
const void *draw_pt_elt_ptr( struct draw_context *draw,
unsigned start );
/* Implementations:
*/
struct draw_pt_front_end *draw_pt_vcache( void );
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
#endif

View file

@ -0,0 +1,88 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "draw/draw_pt.h"
#include "draw/draw_private.h"
/* Neat get_elt func that also works for varrays drawing by encoding
* the start value into a pointer.
*/
static unsigned elt_uint( const void *elts, unsigned idx )
{
return *(((const uint *)elts) + idx);
}
static unsigned elt_ushort( const void *elts, unsigned idx )
{
return *(((const ushort *)elts) + idx);
}
static unsigned elt_ubyte( const void *elts, unsigned idx )
{
return *(((const ubyte *)elts) + idx);
}
static unsigned elt_vert( const void *elts, unsigned idx )
{
return (const ubyte *)elts - (const ubyte *)NULL + idx;
}
pt_elt_func draw_pt_elt_func( struct draw_context *draw )
{
switch (draw->user.eltSize) {
case 0: return elt_vert;
case 1: return elt_ubyte;
case 2: return elt_ushort;
case 4: return elt_uint;
default: return NULL;
}
}
const void *draw_pt_elt_ptr( struct draw_context *draw,
unsigned start )
{
const char *elts = draw->user.elts;
switch (draw->user.eltSize) {
case 0:
return (const void *)(((const ubyte *)NULL) + start);
case 1:
return (const void *)(((const ubyte *)elts) + start);
case 2:
return (const void *)(((const ushort *)elts) + start);
case 4:
return (const void *)(((const uint *)elts) + start);
default:
return NULL;
}
}

View file

@ -0,0 +1,364 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "pipe/p_util.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
/* The simplest 'middle end' in the new vertex code.
*
* The responsibilities of a middle end are to:
* - perform vertex fetch using
* - draw vertex element/buffer state
* - a list of fetch indices we received as an input
* - run the vertex shader
* - cliptest,
* - clip coord calculation
* - viewport transformation
* - if necessary, run the primitive pipeline, passing it:
* - a linear array of vertex_header vertices constructed here
* - a set of draw indices we received as an input
* - otherwise, drive the hw backend,
* - allocate space for hardware format vertices
* - translate the vertex-shader output vertices to hw format
* - calling the backend draw functions.
*
* For convenience, we provide a helper function to drive the hardware
* backend given similar inputs to those required to run the pipeline.
*
* In the case of passthrough mode, many of these actions are disabled
* or noops, so we end up doing:
*
* - perform vertex fetch
* - drive the hw backend
*
* IE, basically just vertex fetch to post-vs-format vertices,
* followed by a call to the backend helper function.
*/
struct fetch_emit_middle_end {
struct draw_pt_middle_end base;
struct draw_context *draw;
struct {
const ubyte *ptr;
unsigned pitch;
void (*fetch)( const void *from, float *attrib);
void (*emit)( const float *attrib, float **out );
} fetch[PIPE_ATTRIB_MAX];
unsigned nr_fetch;
unsigned hw_vertex_size;
};
static void fetch_B8G8R8A8_UNORM( const void *from,
float *attrib )
{
ubyte *ub = (ubyte *) from;
attrib[2] = UBYTE_TO_FLOAT(ub[0]);
attrib[1] = UBYTE_TO_FLOAT(ub[1]);
attrib[0] = UBYTE_TO_FLOAT(ub[2]);
attrib[3] = UBYTE_TO_FLOAT(ub[3]);
}
static void fetch_R32G32B32A32_FLOAT( const void *from,
float *attrib )
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = f[2];
attrib[3] = f[3];
}
static void fetch_R32G32B32_FLOAT( const void *from,
float *attrib )
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = f[2];
attrib[3] = 1.0;
}
static void fetch_R32G32_FLOAT( const void *from,
float *attrib )
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = f[1];
attrib[2] = 0.0;
attrib[3] = 1.0;
}
static void fetch_R32_FLOAT( const void *from,
float *attrib )
{
float *f = (float *) from;
attrib[0] = f[0];
attrib[1] = 0.0;
attrib[2] = 0.0;
attrib[3] = 1.0;
}
static void emit_R32_FLOAT( const float *attrib,
float **out )
{
(*out)[0] = attrib[0];
(*out) += 1;
}
static void emit_R32G32_FLOAT( const float *attrib,
float **out )
{
(*out)[0] = attrib[0];
(*out)[1] = attrib[1];
(*out) += 2;
}
static void emit_R32G32B32_FLOAT( const float *attrib,
float **out )
{
(*out)[0] = attrib[0];
(*out)[1] = attrib[1];
(*out)[2] = attrib[2];
(*out) += 3;
}
static void emit_R32G32B32A32_FLOAT( const float *attrib,
float **out )
{
(*out)[0] = attrib[0];
(*out)[1] = attrib[1];
(*out)[2] = attrib[2];
(*out)[3] = attrib[3];
(*out) += 4;
}
/**
* 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 fetch_emit_middle_end *feme,
void *out_ptr,
const unsigned *fetch_elts,
unsigned count )
{
float *out = (float *)out_ptr;
struct vbuf_render *render = feme->draw->render;
uint i, j;
for (i = 0; i < count; i++) {
unsigned elt = fetch_elts[i];
for (j = 0; j < feme->nr_fetch; j++) {
float attrib[4];
const ubyte *from = (feme->fetch[j].ptr +
feme->fetch[j].pitch * elt);
feme->fetch[j].fetch( from, attrib );
feme->fetch[j].emit( attrib, &out );
}
}
}
static void fetch_emit_prepare( struct draw_pt_middle_end *middle )
{
static const float zero = 0;
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
const struct vertex_info *vinfo = draw->render->get_vertex_info(draw->render);
unsigned nr_attrs = vinfo->num_attribs;
unsigned i;
for (i = 0; i < nr_attrs; i++) {
unsigned src_element = vinfo->src_index[i];
unsigned src_buffer = draw->vertex_element[src_element].vertex_buffer_index;
feme->fetch[i].ptr = ((const ubyte *)draw->user.vbuffer[src_buffer] +
draw->vertex_buffer[src_buffer].buffer_offset +
draw->vertex_element[src_element].src_offset);
feme->fetch[i].pitch = draw->vertex_buffer[src_buffer].pitch;
switch (draw->vertex_element[src_element].src_format) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
feme->fetch[i].fetch = fetch_B8G8R8A8_UNORM;
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
feme->fetch[i].fetch = fetch_R32G32B32A32_FLOAT;
break;
case PIPE_FORMAT_R32G32B32_FLOAT:
feme->fetch[i].fetch = fetch_R32G32B32_FLOAT;
break;
case PIPE_FORMAT_R32G32_FLOAT:
feme->fetch[i].fetch = fetch_R32G32_FLOAT;
break;
case PIPE_FORMAT_R32_FLOAT:
feme->fetch[i].fetch = fetch_R32_FLOAT;
break;
default:
assert(0);
feme->fetch[i].fetch = NULL;
break;
}
switch (vinfo->emit[i]) {
case EMIT_4F:
feme->fetch[i].emit = emit_R32G32B32A32_FLOAT;
break;
case EMIT_3F:
feme->fetch[i].emit = emit_R32G32B32_FLOAT;
break;
case EMIT_2F:
feme->fetch[i].emit = emit_R32G32_FLOAT;
break;
case EMIT_1F:
feme->fetch[i].emit = emit_R32_FLOAT;
break;
case EMIT_HEADER:
feme->fetch[i].ptr = (const ubyte *)&zero;
feme->fetch[i].pitch = 0;
feme->fetch[i].fetch = fetch_R32_FLOAT;
feme->fetch[i].emit = emit_R32_FLOAT;
break;
case EMIT_1F_PSIZE:
feme->fetch[i].ptr = (const ubyte *)&feme->draw->rasterizer->point_size;
feme->fetch[i].pitch = 0;
feme->fetch[i].fetch = fetch_R32_FLOAT;
feme->fetch[i].emit = emit_R32_FLOAT;
default:
assert(0);
feme->fetch[i].emit = NULL;
break;
}
}
feme->nr_fetch = nr_attrs;
feme->hw_vertex_size = vinfo->size * 4;
}
static void fetch_emit_run( struct draw_pt_middle_end *middle,
unsigned prim,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
void *hw_verts;
boolean ok;
ok = draw->render->set_primitive( draw->render,
prim );
if (!ok) {
assert(0);
return;
}
hw_verts = draw->render->allocate_vertices( draw->render,
(ushort)feme->hw_vertex_size,
(ushort)fetch_count );
if (!hw_verts) {
assert(0);
return;
}
/* Single routine to fetch vertices and emit HW verts.
*/
fetch_store_general( feme,
hw_verts,
fetch_elts,
fetch_count );
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw( draw->render,
draw_elts,
draw_count );
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render,
hw_verts,
feme->hw_vertex_size,
fetch_count );
}
static void fetch_emit_finish( struct draw_pt_middle_end *middle )
{
/* nothing to do */
}
static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
{
FREE(middle);
}
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
{
struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
fetch_emit->base.prepare = fetch_emit_prepare;
fetch_emit->base.run = fetch_emit_run;
fetch_emit->base.finish = fetch_emit_finish;
fetch_emit->base.destroy = fetch_emit_destroy;
fetch_emit->draw = draw;
return &fetch_emit->base;
}

View file

@ -0,0 +1,337 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "pipe/p_util.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
//#include "draw/draw_vbuf.h"
//#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#define CACHE_MAX 32
#define FETCH_MAX 128
#define DRAW_MAX (16*1024)
struct vcache_frontend {
struct draw_pt_front_end base;
unsigned in[CACHE_MAX];
ushort out[CACHE_MAX];
ushort draw_elts[DRAW_MAX];
unsigned fetch_elts[FETCH_MAX];
unsigned draw_count;
unsigned fetch_count;
pt_elt_func elt_func;
const void *elt_ptr;
struct draw_pt_middle_end *middle;
unsigned output_prim;
};
static void vcache_flush( struct vcache_frontend *vcache )
{
#if 0
/* Should always be true if output_prim == input_prim, otherwise
* not so much...
*/
unsigned i;
for (i = 0; i < vcache->draw_count; i++) {
assert( vcache->fetch_elts[vcache->draw_elts[i]] ==
vcache->elt_func(vcache->elt_ptr, i) );
}
#endif
if (vcache->draw_count) {
vcache->middle->run( vcache->middle,
vcache->output_prim,
vcache->fetch_elts,
vcache->fetch_count,
vcache->draw_elts,
vcache->draw_count );
}
memset(vcache->in, ~0, sizeof(vcache->in));
vcache->fetch_count = 0;
vcache->draw_count = 0;
}
static void vcache_check_flush( struct vcache_frontend *vcache )
{
if ( vcache->draw_count + 6 >= DRAW_MAX ||
vcache->fetch_count + 4 >= FETCH_MAX )
{
vcache_flush( vcache );
}
}
static void vcache_elt( struct vcache_frontend *vcache,
unsigned felt )
{
unsigned idx = felt % CACHE_MAX;
if (vcache->in[idx] != felt) {
assert(vcache->fetch_count < FETCH_MAX);
vcache->in[idx] = felt;
vcache->out[idx] = vcache->fetch_count;
vcache->fetch_elts[vcache->fetch_count++] = felt;
}
vcache->draw_elts[vcache->draw_count++] = vcache->out[idx];
}
static void vcache_triangle( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2 )
{
/* TODO: encode edgeflags in draw_elts */
vcache_elt(vcache, i0);
vcache_elt(vcache, i1);
vcache_elt(vcache, i2);
vcache_check_flush(vcache);
}
static void vcache_line( struct vcache_frontend *vcache,
boolean reset,
unsigned i0,
unsigned i1 )
{
/* TODO: encode reset-line-stipple in draw_elts */
(void) reset;
vcache_elt(vcache, i0);
vcache_elt(vcache, i1);
vcache_check_flush(vcache);
}
static void vcache_point( struct vcache_frontend *vcache,
unsigned i0 )
{
vcache_elt(vcache, i0);
vcache_check_flush(vcache);
}
static void vcache_quad( struct vcache_frontend *vcache,
unsigned i0,
unsigned i1,
unsigned i2,
unsigned i3 )
{
vcache_triangle( vcache, i0, i1, i3 );
vcache_triangle( vcache, i1, i2, i3 );
}
static void vcache_prepare( struct draw_pt_front_end *frontend,
struct draw_pt_middle_end *middle )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
vcache->middle = middle;
middle->prepare( middle );
}
static unsigned reduced_prim[PIPE_PRIM_POLYGON + 1] = {
PIPE_PRIM_POINTS,
PIPE_PRIM_LINES,
PIPE_PRIM_LINES,
PIPE_PRIM_LINES,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLES,
PIPE_PRIM_TRIANGLES
};
static void vcache_run( struct draw_pt_front_end *frontend,
unsigned prim,
pt_elt_func get_elt,
const void *elts,
unsigned count )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
unsigned i;
/* These are for validation only:
*/
vcache->elt_func = get_elt;
vcache->elt_ptr = elts;
vcache->output_prim = reduced_prim[prim];
switch (prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < count; i ++) {
vcache_point( vcache,
get_elt(elts, i) );
}
break;
case PIPE_PRIM_LINES:
for (i = 0; i+1 < count; i += 2) {
vcache_line( vcache,
TRUE,
get_elt(elts, i + 0),
get_elt(elts, i + 1));
}
break;
case PIPE_PRIM_LINE_LOOP:
if (count >= 2) {
for (i = 1; i < count; i++) {
vcache_line( vcache,
i == 1, /* XXX: only if vb not split */
get_elt(elts, i - 1),
get_elt(elts, i) );
}
vcache_line( vcache,
0,
get_elt(elts, count - 1),
get_elt(elts, 0) );
}
break;
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < count; i++) {
vcache_line( vcache,
i == 1,
get_elt(elts, i - 1),
get_elt(elts, i) );
}
break;
case PIPE_PRIM_TRIANGLES:
for (i = 0; i+2 < count; i += 3) {
vcache_triangle( vcache,
get_elt(elts, i + 0),
get_elt(elts, i + 1),
get_elt(elts, i + 2) );
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
for (i = 0; i+2 < count; i++) {
if (i & 1) {
vcache_triangle( vcache,
get_elt(elts, i + 1),
get_elt(elts, i + 0),
get_elt(elts, i + 2) );
}
else {
vcache_triangle( vcache,
get_elt(elts, i + 0),
get_elt(elts, i + 1),
get_elt(elts, i + 2) );
}
}
break;
case PIPE_PRIM_TRIANGLE_FAN:
for (i = 0; i+2 < count; i++) {
vcache_triangle( vcache,
get_elt(elts, 0),
get_elt(elts, i + 1),
get_elt(elts, i + 2) );
}
break;
case PIPE_PRIM_QUADS:
for (i = 0; i+3 < count; i += 4) {
vcache_quad( vcache,
get_elt(elts, i + 0),
get_elt(elts, i + 1),
get_elt(elts, i + 2),
get_elt(elts, i + 3));
}
break;
case PIPE_PRIM_QUAD_STRIP:
for (i = 0; i+3 < count; i += 2) {
vcache_quad( vcache,
get_elt(elts, i + 2),
get_elt(elts, i + 0),
get_elt(elts, i + 1),
get_elt(elts, i + 3));
}
break;
case PIPE_PRIM_POLYGON:
for (i = 0; i+2 < count; i++) {
vcache_triangle( vcache,
get_elt(elts, i + 1),
get_elt(elts, i + 2),
get_elt(elts, 0));
}
break;
default:
assert(0);
break;
}
vcache_flush( vcache );
}
static void vcache_finish( struct draw_pt_front_end *frontend )
{
struct vcache_frontend *vcache = (struct vcache_frontend *)frontend;
vcache->middle->finish( vcache->middle );
vcache->middle = NULL;
}
static void vcache_destroy( struct draw_pt_front_end *frontend )
{
FREE(frontend);
}
struct draw_pt_front_end *draw_pt_vcache( void )
{
struct vcache_frontend *vcache = CALLOC_STRUCT( vcache_frontend );
vcache->base.prepare = vcache_prepare;
vcache->base.run = vcache_run;
vcache->base.finish = vcache_finish;
vcache->base.destroy = vcache_destroy;
memset(vcache->in, ~0, sizeof(vcache->in));
return &vcache->base;
}

View file

@ -34,20 +34,14 @@
/**
* Check if we need any special pipeline stages, or whether prims/verts
* can go through untouched.
* Check if we need any special pipeline stages, or whether
* prims/verts can go through untouched. Don't test for bypass
* clipping or vs modes, this function is just about the primitive
* pipeline stages.
*/
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;
@ -72,6 +66,11 @@ draw_need_pipeline(const struct draw_context *draw)
if (draw->rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
return TRUE;
/* unfilled polygons */
if (draw->rasterizer->fill_cw != PIPE_POLYGON_MODE_FILL ||
draw->rasterizer->fill_ccw != PIPE_POLYGON_MODE_FILL)
return TRUE;
/* polygon offset */
if (draw->rasterizer->offset_cw || draw->rasterizer->offset_ccw)
return TRUE;
@ -84,9 +83,14 @@ draw_need_pipeline(const struct draw_context *draw)
if (draw->rasterizer->light_twoside)
return TRUE;
/* polygon cull */
/* polygon cull - this is difficult - hardware can cull just fine
* most of the time (though sometimes CULL_NEITHER is unsupported.
*
* Generally this isn't a reason to require the pipeline, though.
*
if (draw->rasterizer->cull_mode)
return TRUE;
*/
return FALSE;
}

View file

@ -38,6 +38,8 @@
#include "draw_context.h"
#include "draw_vs.h"
#include "tgsi/util/tgsi_parse.h"
static INLINE unsigned
compute_clipmask(const float *clip, /*const*/ float plane[][4], unsigned nr)
@ -187,6 +189,7 @@ vs_exec_run( struct draw_vertex_shader *shader,
static void
vs_exec_delete( struct draw_vertex_shader *dvs )
{
FREE((void*) dvs->state.tokens);
FREE( dvs );
}
@ -196,11 +199,13 @@ draw_create_vs_exec(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct draw_vertex_shader *vs = CALLOC_STRUCT( draw_vertex_shader );
uint nt = tgsi_num_tokens(state->tokens);
if (vs == NULL)
return NULL;
vs->state = *state;
/* we make a private copy of the tokens */
vs->state.tokens = mem_dup(state->tokens, nt * sizeof(state->tokens[0]));
vs->prepare = vs_exec_prepare;
vs->run = vs_exec_run;
vs->delete = vs_exec_delete;

View file

@ -38,6 +38,8 @@
#include "draw_context.h"
#include "draw_vs.h"
#include "tgsi/util/tgsi_parse.h"
#ifdef MESA_LLVM
#include "gallivm/gallivm.h"
@ -186,6 +188,7 @@ vs_llvm_delete( struct draw_vertex_shader *base )
/* Do something to free compiled shader:
*/
FREE( (void*) shader->base.state.tokens );
FREE( shader );
}
@ -197,12 +200,14 @@ draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_llvm_vertex_shader *vs;
uint nt = tgsi_num_tokens(templ->tokens);
vs = CALLOC_STRUCT( draw_llvm_vertex_shader );
if (vs == NULL)
return NULL;
vs->base.state = templ;
/* we make a private copy of the tokens */
vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.prepare = vs_llvm_prepare;
vs->base.run = vs_llvm_run;
vs->base.delete = vs_llvm_delete;

View file

@ -43,6 +43,7 @@
#include "rtasm/rtasm_x86sse.h"
#include "tgsi/exec/tgsi_sse2.h"
#include "tgsi/util/tgsi_parse.h"
typedef void (XSTDCALL *codegen_function) (
@ -204,6 +205,7 @@ vs_sse_delete( struct draw_vertex_shader *base )
x86_release_func( &shader->sse2_program );
FREE( (void*) shader->base.state.tokens );
FREE( shader );
}
@ -213,6 +215,7 @@ draw_create_vs_sse(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_sse_vertex_shader *vs;
uint nt = tgsi_num_tokens(templ->tokens);
if (!draw->use_sse)
return NULL;
@ -221,7 +224,8 @@ draw_create_vs_sse(struct draw_context *draw,
if (vs == NULL)
return NULL;
vs->base.state = *templ;
/* we make a private copy of the tokens */
vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.prepare = vs_sse_prepare;
vs->base.run = vs_sse_run;
vs->base.delete = vs_sse_delete;

View file

@ -317,3 +317,16 @@ tgsi_parse_token(
}
}
unsigned
tgsi_num_tokens(const struct tgsi_token *tokens)
{
struct tgsi_parse_context ctx;
if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
unsigned len = (ctx.FullHeader.Header.HeaderSize +
ctx.FullHeader.Header.BodySize +
1);
return len;
}
return 0;
}

View file

@ -113,6 +113,10 @@ void
tgsi_parse_token(
struct tgsi_parse_context *ctx );
unsigned
tgsi_num_tokens(const struct tgsi_token *tokens);
#if defined __cplusplus
}
#endif

View file

@ -4,6 +4,7 @@ util = env.ConvenienceLibrary(
target = 'util',
source = [
'p_debug.c',
'p_debug_mem.c',
'p_tile.c',
'p_util.c',
'u_blit.c',

View file

@ -58,7 +58,7 @@ int rpl_snprintf(char *str, size_t size, const char *format, ...);
#endif
void debug_vprintf(const char *format, va_list ap)
void _debug_vprintf(const char *format, va_list ap)
{
#ifdef WIN32
#ifndef WINCE
@ -76,15 +76,7 @@ void debug_vprintf(const char *format, va_list ap)
}
void debug_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
debug_vprintf(format, ap);
va_end(ap);
}
#ifdef DEBUG
void debug_print_blob( const char *name,
const void *blob,
unsigned size )
@ -99,12 +91,10 @@ void debug_print_blob( const char *name,
debug_printf("%d:\t%08x\n", i, ublob[i]);
}
}
#endif
/* TODO: implement a debug_abort that calls EngBugCheckEx on WIN32 */
static INLINE void debug_break(void)
void _debug_break(void)
{
#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
__asm("int3");
@ -117,6 +107,150 @@ static INLINE void debug_break(void)
#endif
}
#ifdef WIN32
static const char *
find(const char *start, const char *end, char c)
{
const char *p;
for(p = start; !end || p != end; ++p) {
if(*p == c)
return p;
if(*p < 32)
break;
}
return NULL;
}
static int
compare(const char *start, const char *end, const char *s)
{
const char *p, *q;
for(p = start, q = s; p != end && *q != '\0'; ++p, ++q) {
if(*p != *q)
return 0;
}
return p == end && *q == '\0';
}
static void
copy(char *dst, const char *start, const char *end, size_t n)
{
const char *p;
char *q;
for(p = start, q = dst, n = n - 1; p != end && n; ++p, ++q, --n)
*q = *p;
*q = '\0';
}
#endif
const char *
debug_get_option(const char *name, const char *dfault)
{
const char *result;
#ifdef WIN32
ULONG_PTR iFile = 0;
const void *pMap = NULL;
const char *sol, *eol, *sep;
static char output[1024];
pMap = EngMapFile(L"\\??\\c:\\gallium.cfg", 0, &iFile);
if(!pMap)
result = dfault;
else {
sol = (const char *)pMap;
while(1) {
/* TODO: handle LF line endings */
eol = find(sol, NULL, '\r');
if(!eol || eol == sol)
break;
sep = find(sol, eol, '=');
if(!sep)
break;
if(compare(sol, sep, name)) {
copy(output, sep + 1, eol, sizeof(output));
result = output;
break;
}
sol = eol + 2;
}
EngUnmapFile(iFile);
}
#else
result = getenv(name);
if(!result)
result = dfault;
#endif
if(result)
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result);
else
debug_printf("%s: %s = (null)\n", __FUNCTION__, name);
return result;
}
boolean
debug_get_bool_option(const char *name, boolean dfault)
{
const char *str = debug_get_option(name, NULL);
boolean result;
if(str == NULL)
result = dfault;
else if(!strcmp(str, "no"))
result = FALSE;
else if(!strcmp(str, "0"))
result = FALSE;
else if(!strcmp(str, "f"))
result = FALSE;
else if(!strcmp(str, "false"))
result = FALSE;
else
result = TRUE;
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
return result;
}
long
debug_get_num_option(const char *name, long dfault)
{
/* FIXME */
return dfault;
}
unsigned long
debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
unsigned long dfault)
{
unsigned long result;
const char *str;
str = debug_get_option(name, NULL);
if(!str)
result = dfault;
else {
result = 0;
while( flags->name ) {
if (!strcmp(str, "all") || strstr(str, flags->name ))
result |= flags->value;
++flags;
}
}
debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
return result;
}
#if defined(WIN32)
ULONG_PTR debug_config_file = 0;
void *mapped_config_file = 0;
@ -126,7 +260,7 @@ enum {
};
/* Check for aborts enabled. */
static unsigned abort_en()
static unsigned abort_en(void)
{
if (!mapped_config_file)
{
@ -149,59 +283,28 @@ static unsigned abort_en()
return ((((char *)mapped_config_file)[0]) - 0x30) & eAssertAbortEn;
}
#else /* WIN32 */
static unsigned abort_en()
static unsigned abort_en(void)
{
return !GETENV("GALLIUM_ABORT_ON_ASSERT");
}
#endif
void debug_assert_fail(const char *expr, const char *file, unsigned line)
void _debug_assert_fail(const char *expr,
const char *file,
unsigned line,
const char *function)
{
debug_printf("%s:%i: Assertion `%s' failed.\n", file, line, expr);
_debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
if (abort_en())
{
debug_break();
} else
{
debug_printf("continuing...\n");
_debug_printf("continuing...\n");
}
}
#define DEBUG_MASK_TABLE_SIZE 256
/**
* Mask hash table.
*
* For now we just take the lower bits of the key, and do no attempt to solve
* collisions. Use a proper hash table when we have dozens of drivers.
*/
static uint32_t debug_mask_table[DEBUG_MASK_TABLE_SIZE];
void debug_mask_set(uint32_t uuid, uint32_t mask)
{
unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1);
debug_mask_table[hash] = mask;
}
uint32_t debug_mask_get(uint32_t uuid)
{
unsigned hash = uuid & (DEBUG_MASK_TABLE_SIZE - 1);
return debug_mask_table[hash];
}
void debug_mask_vprintf(uint32_t uuid, uint32_t what, const char *format, va_list ap)
{
uint32_t mask = debug_mask_get(uuid);
if(mask & what)
debug_vprintf(format, ap);
}
const char *
debug_dump_enum(const struct debug_named_value *names,
unsigned long value)
@ -214,7 +317,7 @@ debug_dump_enum(const struct debug_named_value *names,
++names;
}
snprintf(rest, sizeof(rest), "0x%08x", value);
snprintf(rest, sizeof(rest), "0x%08lx", value);
return rest;
}
@ -247,7 +350,7 @@ debug_dump_flags(const struct debug_named_value *names,
else
first = 0;
snprintf(rest, sizeof(rest), "0x%08x", value);
snprintf(rest, sizeof(rest), "0x%08lx", value);
strncat(output, rest, sizeof(output));
}

View file

@ -0,0 +1,172 @@
/**************************************************************************
*
* 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
* Memory debugging.
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
#ifdef WIN32
#include <windows.h>
#include <winddi.h>
#else
#include <stdio.h>
#include <stdlib.h>
#endif
#include "pipe/p_debug.h"
#include "util/u_double_list.h"
#define DEBUG_MEMORY_MAGIC 0x6e34090aU
#if defined(WIN32) && !defined(WINCE)
#define real_malloc(_size) EngAllocMem(0, _size, 'D3AG')
#define real_free(_ptr) EngFreeMem(_ptr)
#else
#define real_malloc(_size) malloc(_size)
#define real_free(_ptr) free(_ptr)
#endif
struct debug_memory_header
{
struct list_head head;
unsigned long no;
const char *file;
unsigned line;
const char *function;
size_t size;
unsigned magic;
};
static struct list_head list = { &list, &list };
static unsigned long start_no = 0;
static unsigned long end_no = 0;
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size)
{
struct debug_memory_header *hdr;
hdr = real_malloc(sizeof(*hdr) + size);
if(!hdr)
return NULL;
hdr->no = end_no++;
hdr->file = file;
hdr->line = line;
hdr->function = function;
hdr->size = size;
hdr->magic = DEBUG_MEMORY_MAGIC;
LIST_ADDTAIL(&hdr->head, &list);
return (void *)((char *)hdr + sizeof(*hdr));
}
void
debug_free(const char *file, unsigned line, const char *function,
void *ptr)
{
struct debug_memory_header *hdr;
if(!ptr)
return;
hdr = (struct debug_memory_header *)((char *)ptr - sizeof(*hdr));
if(hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
file, line, function,
ptr);
debug_assert(0);
return;
}
LIST_DEL(&hdr->head);
hdr->magic = 0;
real_free(hdr);
}
void *
debug_calloc(const char *file, unsigned line, const char *function,
size_t count, size_t size )
{
void *ptr = debug_malloc( file, line, function, count * size );
if( ptr )
memset( ptr, 0, count * size );
return ptr;
}
void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size )
{
void *new_ptr = NULL;
if (new_size != 0) {
new_ptr = debug_malloc( file, line, function, new_size );
if( new_ptr && old_ptr )
memcpy( new_ptr, old_ptr, old_size );
}
debug_free( file, line, function, old_ptr );
return new_ptr;
}
void
debug_memory_reset(void)
{
start_no = end_no;
}
void
debug_memory_report(void)
{
struct list_head *entry;
entry = list.prev;
for (; entry != &list; entry = entry->prev) {
struct debug_memory_header *hdr;
void *ptr;
hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
ptr = (void *)((char *)hdr + sizeof(*hdr));
if(hdr->no >= start_no)
debug_printf("%s:%u:%s: %u bytes at %p not freed\n",
hdr->file, hdr->line, hdr->function,
hdr->size, ptr);
}
}

View file

@ -719,8 +719,6 @@ util_create_gen_mipmap(struct pipe_context *pipe,
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
ctx->sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
ctx->sampler.normalized_coords = 1;
@ -774,23 +772,23 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
{
void *buf;
ctx->vertices[0][0][0] = 0.0f; /*x*/
ctx->vertices[0][0][1] = 0.0f; /*y*/
ctx->vertices[0][0][0] = -0.5f; /*x*/
ctx->vertices[0][0][1] = -0.5f; /*y*/
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = 0.0f; /*t*/
ctx->vertices[1][0][0] = width; /*x*/
ctx->vertices[1][0][1] = 0.0f; /*y*/
ctx->vertices[1][0][0] = width - 0.5f; /*x*/
ctx->vertices[1][0][1] = -0.5f; /*y*/
ctx->vertices[1][1][0] = 1.0f; /*s*/
ctx->vertices[1][1][1] = 0.0f; /*t*/
ctx->vertices[2][0][0] = width;
ctx->vertices[2][0][1] = height;
ctx->vertices[2][0][0] = width - 0.5f;
ctx->vertices[2][0][1] = height - 0.5f;
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = 1.0f;
ctx->vertices[3][0][0] = 0.0f;
ctx->vertices[3][0][1] = height;
ctx->vertices[3][0][0] = -0.5f;
ctx->vertices[3][0][1] = height - 0.5f;
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
@ -849,11 +847,13 @@ simple_viewport(struct pipe_context *pipe, uint width, uint height)
* \param face which cube face to generate mipmaps for (0 for non-cube maps)
* \param baseLevel the first mipmap level to use as a src
* \param lastLevel the last mipmap level to generate
* \param filter the minification filter used to generate mipmap levels with
* \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
*/
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel)
uint face, uint baseLevel, uint lastLevel, uint filter)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
@ -890,6 +890,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
memset(&fb, 0, sizeof(fb));
fb.num_cbufs = 1;
/* set min/mag to same filter for faster sw speed */
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_img_filter = filter;
/*
* XXX for small mipmap levels, it may be faster to use the software
* fallback path...

View file

@ -50,7 +50,6 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
extern void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_texture *pt,
uint face, uint baseLevel, uint lastLevel);
uint face, uint baseLevel, uint lastLevel, uint filter);
#endif

View file

@ -37,6 +37,12 @@
#include "pipe/p_compiler.h" /* for boolean */
#ifdef __cplusplus
extern "C" {
#endif
enum pipe_format;
struct softpipe_winsys {
@ -60,4 +66,8 @@ struct pipe_screen *
softpipe_create_screen(struct pipe_winsys *);
#ifdef __cplusplus
}
#endif
#endif /* SP_WINSYS_H */

View file

@ -60,43 +60,102 @@ extern "C" {
#endif
void _debug_vprintf(const char *format, va_list ap);
static INLINE void
_debug_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
}
/**
* Print debug messages.
*
* A debug message will be printed regardless of the DEBUG/NDEBUG macros.
*
* The actual channel used to output debug message is platform specific. To
* avoid misformating or truncation, follow these rules of thumb:
* - output whole lines
* - avoid outputing large strings (512 bytes is the current maximum length
* that is guaranteed to be printed in all platforms)
*/
void debug_printf(const char *format, ...);
static INLINE void
debug_printf(const char *format, ...)
{
#ifdef DEBUG
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
#endif
}
/* Dump a blob in hex to the same place that debug_printf sends its
* messages:
#ifdef DEBUG
#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
#else
#define debug_vprintf(_format, _ap) ((void)0)
#endif
/**
* Dump a blob in hex to the same place that debug_printf sends its
* messages.
*/
#ifdef DEBUG
void debug_print_blob( const char *name,
const void *blob,
unsigned size );
#else
#define debug_print_blob(_name, _blob, _size) ((void)0)
#endif
void _debug_break(void);
/**
* @sa debug_printf
* Hard-coded breakpoint.
*/
void debug_vprintf(const char *format, va_list ap);
void debug_assert_fail(const char *expr, const char *file, unsigned line);
/** Assert macro */
#ifdef DEBUG
#define debug_assert(expr) ((expr) ? (void)0 : debug_assert_fail(#expr, __FILE__, __LINE__))
#if (defined(__i386__) || defined(__386__)) && defined(__GNUC__)
#define debug_break() __asm("int3")
#elif (defined(__i386__) || defined(__386__)) && defined(__MSC__)
#define debug_break() _asm {int 3}
#else
#define debug_break() _debug_break()
#endif
#else /* !DEBUG */
#define debug_break() ((void)0)
#endif /* !DEBUG */
long
debug_get_num_option(const char *name, long dfault);
void _debug_assert_fail(const char *expr,
const char *file,
unsigned line,
const char *function);
/**
* Assert macro
*
* Do not expect that the assert call terminates -- errors must be handled
* regardless of assert behavior.
*/
#ifdef DEBUG
#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
#else
#define debug_assert(expr) ((void)0)
#endif
/** Override standard assert macro */
#ifdef assert
#undef assert
#endif
@ -104,78 +163,53 @@ void debug_assert_fail(const char *expr, const char *file, unsigned line);
/**
* Set a channel's debug mask.
*
* uuid is just a random 32 bit integer that uniquely identifies the debugging
* channel.
*
* @note Due to current implementation issues, make sure the lower 8 bits of
* UUID are unique.
* Output the current function name.
*/
void debug_mask_set(uint32_t uuid, uint32_t mask);
uint32_t debug_mask_get(uint32_t uuid);
#ifdef DEBUG
#define debug_checkpoint() \
_debug_printf("%s\n", __FUNCTION__)
#else
#define debug_checkpoint() \
((void)0)
#endif
/**
* Conditional debug output.
*
* This is just a generalization of the debug filtering mechanism used
* throughout Gallium.
*
* You use this function as:
*
* @code
* #define MYDRIVER_UUID 0x12345678 // random 32 bit identifier
*
* static void inline
* mydriver_debug(uint32_t what, const char *format, ...)
* {
* #ifdef DEBUG
* va_list ap;
* va_start(ap, format);
* debug_mask_vprintf(MYDRIVER_UUID, what, format, ap);
* va_end(ap);
* #endif
* }
*
* ...
*
* debug_mask_set(MYDRIVER_UUID,
* MYDRIVER_DEBUG_THIS |
* MYDRIVER_DEBUG_THAT |
* ... );
*
* ...
*
* mydriver_debug(MYDRIVER_DEBUG_THIS,
* "this and this happened\n");
*
* mydriver_debug(MYDRIVER_DEBUG_THAT,
* "that = %f\n", that);
* ...
* @endcode
*
* You can also define several variants of mydriver_debug, with hardcoded what.
* Note that although macros with variable number of arguments would accomplish
* more in less code, they are not portable.
* Output the full source code position.
*/
void debug_mask_vprintf(uint32_t uuid,
uint32_t what,
const char *format,
va_list ap);
#ifdef DEBUG
#define debug_checkpoint_full() \
_debug_printf("%s:%u:%s", __FILE__, __LINE__, __FUNCTION__)
#else
#define debug_checkpoint_full() \
((void)0)
#endif
/**
* Output a warning message. Muted on release version.
*/
#ifdef DEBUG
#define debug_warning(__msg) \
debug_printf("%s:%i:warning: %s\n", __FILE__, __LINE__, (__msg))
_debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg))
#else
#define debug_warning(__msg) \
((void)0)
#endif
/**
* Output an error message. Not muted on release version.
*/
#ifdef DEBUG
#define debug_error(__msg) \
_debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, (__msg))
#else
#define debug_error(__msg) \
_debug_printf("error: %s\n", __msg))
#endif
/**
* Used by debug_dump_enum and debug_dump_flags to describe symbols.
*/
@ -225,6 +259,56 @@ debug_dump_flags(const struct debug_named_value *names,
unsigned long value);
/**
* Get option.
*
* It is an alias for getenv on Linux.
*
* On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
* endings with one option per line as
*
* NAME=value
*
* This file must be terminated with an extra empty line.
*/
const char *
debug_get_option(const char *name, const char *dfault);
boolean
debug_get_bool_option(const char *name, boolean dfault);
long
debug_get_unsigned_option(const char *name, long dfault);
unsigned long
debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
unsigned long dfault);
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size);
void
debug_free(const char *file, unsigned line, const char *function,
void *ptr);
void *
debug_calloc(const char *file, unsigned line, const char *function,
size_t count, size_t size );
void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size );
void
debug_memory_reset(void);
void
debug_memory_report(void);
#ifdef __cplusplus
}
#endif

View file

@ -39,6 +39,22 @@ extern "C" {
#endif
#if defined(WIN32) && defined(DEBUG) /* memory debugging */
#include "p_debug.h"
#define MALLOC( _size ) \
debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size )
#define CALLOC( _count, _size ) \
debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size )
#define FREE( _ptr ) \
debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr )
#define REALLOC( _ptr, _old_size, _size ) \
debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _size )
#define GETENV( X ) NULL
#else
#ifdef WIN32
void * __stdcall
@ -91,10 +107,10 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
void *new_ptr = NULL;
if (new_size != 0) {
unsigned copy_size = old_size < new_size ? old_size : new_size;
new_ptr = MALLOC( new_size );
if( new_ptr && old_ptr ) {
memcpy( new_ptr, old_ptr, old_size );
if (new_ptr && old_ptr && copy_size) {
memcpy( new_ptr, old_ptr, copy_size );
}
}
@ -104,7 +120,7 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
#define GETENV( X ) NULL
#else /* WIN32 */
#else /* !WIN32 */
#define MALLOC( SIZE ) malloc( SIZE )
@ -116,7 +132,8 @@ REALLOC( void *old_ptr, unsigned old_size, unsigned new_size )
#define GETENV( X ) getenv( X )
#endif /* WIN32 */
#endif /* !WIN32 */
#endif /* !DEBUG */
#define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T))
@ -184,7 +201,7 @@ mem_dup(const void *src, uint size)
#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
#define Elements(x) sizeof(x)/sizeof(*(x))
#define Elements(x) (sizeof(x)/sizeof((x)[0]))
#define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER))
/**

View file

@ -56,28 +56,27 @@ update_textures(struct st_context *st)
for (unit = 0; unit < st->ctx->Const.MaxTextureCoordUnits; unit++) {
const GLuint su = fprog->Base.SamplerUnits[unit];
struct gl_texture_object *texObj = st->ctx->Texture.Unit[su]._Current;
struct st_texture_object *stObj = st_texture_object(texObj);
struct pipe_texture *pt;
struct pipe_texture *pt = NULL;
if (texObj) {
GLboolean flush, retval;
if (fprog->Base.SamplersUsed & (1 << su)) {
struct gl_texture_object *texObj = st->ctx->Texture.Unit[su]._Current;
struct st_texture_object *stObj = st_texture_object(texObj);
retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
if (!retval) {
/* out of mem */
continue;
if (texObj) {
GLboolean flush, retval;
retval = st_finalize_texture(st->ctx, st->pipe, texObj, &flush);
if (!retval) {
/* out of mem */
continue;
}
st->state.num_textures = unit + 1;
}
st->state.num_textures = unit + 1;
pt = st_get_stobj_texture(stObj);
}
/* XXX: need to ensure that textures are unbound/removed from
* this table before being deleted, otherwise the pointer
* comparison below could fail.
*/
pt = st_get_stobj_texture(stObj);
pipe_texture_reference(&st->state.sampler_texture[unit], pt);
}

View file

@ -44,6 +44,7 @@
#include "st_atom_constbuf.h"
#include "st_program.h"
#include "st_cb_bitmap.h"
#include "st_cb_program.h"
#include "st_mesa_to_tgsi.h"
#include "st_texture.h"
#include "pipe/p_context.h"
@ -406,7 +407,7 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
assert(height <= maxSize);
cso_save_rasterizer(cso);
//cso_save_viewport(cso);
cso_save_samplers(cso);
/* rasterizer state: just scissor */
{
@ -457,11 +458,9 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
/* restore state */
cso_restore_rasterizer(cso);
cso_restore_samplers(cso);
//cso_restore_viewport(cso);
/* shaders don't go through cso yet */
pipe->bind_fs_state(pipe, st->fp->driver_shader);
pipe->bind_vs_state(pipe, st->vp->driver_shader);
pipe->set_sampler_textures(pipe, ctx->st->state.num_textures,
ctx->st->state.sampler_texture);
}
@ -513,7 +512,13 @@ st_destroy_bitmap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
/* XXX free frag shader state */
if (st->bitmap.combined_prog) {
st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base);
}
if (st->bitmap.program) {
st_delete_program(st->ctx, &st->bitmap.program->Base.Base);
}
if (st->bitmap.vs) {
pipe->delete_vs_state(pipe, st->bitmap.vs);

View file

@ -523,6 +523,7 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
cso_save_rasterizer(cso);
cso_save_viewport(cso);
cso_save_samplers(cso);
/* rasterizer state: just scissor */
{
@ -596,13 +597,11 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
/* restore state */
cso_restore_rasterizer(cso);
cso_restore_viewport(cso);
cso_restore_samplers(cso);
/* shaders don't go through cso yet */
pipe->bind_fs_state(pipe, st->fp->driver_shader);
pipe->bind_vs_state(pipe, st->vp->driver_shader);
cso_set_rasterizer(cso, &st->state.rasterizer);
cso_set_samplers(cso, PIPE_MAX_SAMPLERS,
(const struct pipe_sampler_state **) st->state.sampler_list);
pipe->set_sampler_textures(pipe, ctx->st->state.num_textures,
ctx->st->state.sampler_texture);
}

View file

@ -45,6 +45,7 @@
#include "st_context.h"
#include "st_program.h"
#include "st_atom_shader.h"
#include "st_cb_program.h"
static GLuint SerialNo = 1;
@ -122,8 +123,8 @@ static struct gl_program *st_new_program( GLcontext *ctx,
}
static void st_delete_program( GLcontext *ctx,
struct gl_program *prog )
void
st_delete_program(GLcontext *ctx, struct gl_program *prog)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;

View file

@ -32,5 +32,8 @@
extern void
st_init_program_functions(struct dd_function_table *functions);
extern void
st_delete_program(GLcontext *ctx, struct gl_program *prog);
#endif

View file

@ -265,19 +265,17 @@ guess_and_alloc_texture(struct st_context *st,
{
GLuint firstLevel;
GLuint lastLevel;
GLuint width = stImage->base.Width;
GLuint height = stImage->base.Height;
GLuint depth = stImage->base.Depth;
GLuint width = stImage->base.Width2; /* size w/out border */
GLuint height = stImage->base.Height2;
GLuint depth = stImage->base.Depth2;
GLuint i, comp_byte = 0;
DBG("%s\n", __FUNCTION__);
assert(!stObj->pt);
if (stImage->base.Border)
return;
if (stImage->level > stObj->base.BaseLevel &&
if (stObj->pt &&
stImage->level > stObj->base.BaseLevel &&
(stImage->base.Width == 1 ||
(stObj->base.Target != GL_TEXTURE_1D &&
stImage->base.Height == 1) ||
@ -297,7 +295,8 @@ guess_and_alloc_texture(struct st_context *st,
/* Figure out image dimensions at start level.
*/
for (i = stImage->level; i > firstLevel; i--) {
width <<= 1;
if (width != 1)
width <<= 1;
if (height != 1)
height <<= 1;
if (depth != 1)
@ -1448,9 +1447,9 @@ st_finalize_texture(GLcontext *ctx,
stObj->pt->format !=
st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat) ||
stObj->pt->last_level != stObj->lastLevel ||
stObj->pt->width[0] != firstImage->base.Width ||
stObj->pt->height[0] != firstImage->base.Height ||
stObj->pt->depth[0] != firstImage->base.Depth ||
stObj->pt->width[0] != firstImage->base.Width2 ||
stObj->pt->height[0] != firstImage->base.Height2 ||
stObj->pt->depth[0] != firstImage->base.Depth2 ||
stObj->pt->cpp != cpp ||
stObj->pt->compressed != firstImage->base.IsCompressed)) {
pipe_texture_release(&stObj->pt);
@ -1464,9 +1463,9 @@ st_finalize_texture(GLcontext *ctx,
gl_target_to_pipe(stObj->base.Target),
st_mesa_format_to_pipe_format(firstImage->base.TexFormat->MesaFormat),
stObj->lastLevel,
firstImage->base.Width,
firstImage->base.Height,
firstImage->base.Depth,
firstImage->base.Width2,
firstImage->base.Height2,
firstImage->base.Depth2,
comp_byte);
if (!stObj->pt) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");

View file

@ -42,6 +42,7 @@
#include "st_cb_drawpixels.h"
#include "st_cb_fbo.h"
#include "st_cb_feedback.h"
#include "st_cb_program.h"
#include "st_cb_queryobj.h"
#include "st_cb_rasterpos.h"
#include "st_cb_readpixels.h"

View file

@ -92,7 +92,8 @@ st_render_mipmap(struct st_context *st,
return FALSE;
}
util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel);
util_gen_mipmap(st->gen_mipmap, pt, face, baseLevel, lastLevel,
PIPE_TEX_FILTER_LINEAR);
/* shaders don't go through CSO yet */
if (st->fp)

View file

@ -97,10 +97,6 @@ struct st_vertex_program
};
extern void
st_init_program_functions(struct dd_function_table *functions);
static inline struct st_fragment_program *
st_fragment_program( struct gl_fragment_program *fp )
{