llvmpipe: Fork softpipe for experimentation with llvm.

This commit is contained in:
José Fonseca 2009-07-26 23:44:38 +01:00
parent 1814d6b49c
commit 946f432a08
57 changed files with 11082 additions and 2 deletions

View file

@ -32,7 +32,7 @@ import common
default_statetrackers = 'mesa'
if common.default_platform in ('linux', 'freebsd', 'darwin'):
default_drivers = 'softpipe,failover,i915simple,trace,identity'
default_drivers = 'softpipe,failover,i915simple,trace,identity,llvmpipe'
default_winsys = 'xlib'
elif common.default_platform in ('winddk',):
default_drivers = 'softpipe,i915simple,trace,identity'
@ -46,7 +46,7 @@ common.AddOptions(opts)
opts.Add(ListVariable('statetrackers', 'state trackers to build', default_statetrackers,
['mesa', 'python', 'xorg']))
opts.Add(ListVariable('drivers', 'pipe drivers to build', default_drivers,
['softpipe', 'failover', 'i915simple', 'i965simple', 'cell', 'trace', 'r300', 'identity']))
['softpipe', 'failover', 'i915simple', 'i965simple', 'cell', 'trace', 'r300', 'identity', 'llvmpipe']))
opts.Add(ListVariable('winsys', 'winsys drivers to build', default_winsys,
['xlib', 'intel', 'gdi', 'radeon']))

View file

@ -0,0 +1,44 @@
TOP = ../../../..
include $(TOP)/configs/current
LIBNAME = llvmpipe
C_SOURCES = \
lp_fs_exec.c \
lp_fs_sse.c \
lp_fs_llvm.c \
lp_clear.c \
lp_flush.c \
lp_query.c \
lp_context.c \
lp_draw_arrays.c \
lp_prim_setup.c \
lp_prim_vbuf.c \
lp_quad_pipe.c \
lp_quad_alpha_test.c \
lp_quad_blend.c \
lp_quad_colormask.c \
lp_quad_coverage.c \
lp_quad_depth_test.c \
lp_quad_earlyz.c \
lp_quad_fs.c \
lp_quad_occlusion.c \
lp_quad_output.c \
lp_quad_stencil.c \
lp_quad_stipple.c \
lp_screen.c \
lp_setup.c \
lp_state_blend.c \
lp_state_clip.c \
lp_state_derived.c \
lp_state_fs.c \
lp_state_sampler.c \
lp_state_rasterizer.c \
lp_state_surface.c \
lp_state_vertex.c \
lp_texture.c \
lp_tex_sample.c \
lp_tile_cache.c \
lp_surface.c
include ../../Makefile.template

View file

@ -0,0 +1,46 @@
Import('*')
env = env.Clone()
llvmpipe = env.ConvenienceLibrary(
target = 'llvmpipe',
source = [
'lp_fs_exec.c',
'lp_fs_sse.c',
'lp_fs_llvm.c',
'lp_clear.c',
'lp_context.c',
'lp_draw_arrays.c',
'lp_flush.c',
'lp_prim_setup.c',
'lp_prim_vbuf.c',
'lp_setup.c',
'lp_quad_alpha_test.c',
'lp_quad_blend.c',
'lp_quad_pipe.c',
'lp_quad_colormask.c',
'lp_quad_coverage.c',
'lp_quad_depth_test.c',
'lp_quad_earlyz.c',
'lp_quad_fs.c',
'lp_quad_occlusion.c',
'lp_quad_output.c',
'lp_quad_stencil.c',
'lp_quad_stipple.c',
'lp_query.c',
'lp_screen.c',
'lp_state_blend.c',
'lp_state_clip.c',
'lp_state_derived.c',
'lp_state_fs.c',
'lp_state_rasterizer.c',
'lp_state_sampler.c',
'lp_state_surface.c',
'lp_state_vertex.c',
'lp_surface.c',
'lp_tex_sample.c',
'lp_texture.c',
'lp_tile_cache.c',
])
Export('softpipe')

View file

@ -0,0 +1,89 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009 VMware, Inc. 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:
* Brian Paul
* Michel Dänzer
*/
#include "pipe/p_defines.h"
#include "util/u_pack_color.h"
#include "lp_clear.h"
#include "lp_context.h"
#include "lp_surface.h"
#include "lp_state.h"
#include "lp_tile_cache.h"
/**
* Clear the given buffers to the specified values.
* No masking, no scissor (clear entire buffer).
*/
void
llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
double depth, unsigned stencil)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
unsigned cv;
uint i;
if (llvmpipe->no_rast)
return;
#if 0
llvmpipe_update_derived(llvmpipe); /* not needed?? */
#endif
if (buffers & PIPE_CLEAR_COLOR) {
for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
struct pipe_surface *ps = llvmpipe->framebuffer.cbufs[i];
util_pack_color(rgba, ps->format, &cv);
lp_tile_cache_clear(llvmpipe->cbuf_cache[i], rgba, cv);
#if !TILE_CLEAR_OPTIMIZATION
/* non-cached surface */
pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
#endif
}
}
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
static const float zero[4] = { 0.0F, 0.0F, 0.0F, 0.0F };
struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
cv = util_pack_z_stencil(ps->format, depth, stencil);
lp_tile_cache_clear(llvmpipe->zsbuf_cache, zero, cv);
#if !TILE_CLEAR_OPTIMIZATION
/* non-cached surface */
pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv);
#endif
}
}

View file

@ -0,0 +1,43 @@
/**************************************************************************
*
* 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:
* Brian Paul
*/
#ifndef SP_CLEAR_H
#define SP_CLEAR_H
#include "pipe/p_state.h"
struct pipe_context;
extern void
llvmpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
double depth, unsigned stencil);
#endif /* SP_CLEAR_H */

View file

@ -0,0 +1,317 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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 "util/u_math.h"
#include "util/u_memory.h"
#include "lp_clear.h"
#include "lp_context.h"
#include "lp_flush.h"
#include "lp_prim_setup.h"
#include "lp_prim_vbuf.h"
#include "lp_state.h"
#include "lp_surface.h"
#include "lp_tile_cache.h"
#include "lp_texture.h"
#include "lp_winsys.h"
#include "lp_query.h"
/**
* Map any drawing surfaces which aren't already mapped
*/
void
llvmpipe_map_transfers(struct llvmpipe_context *lp)
{
unsigned i;
for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
lp_tile_cache_map_transfers(lp->cbuf_cache[i]);
}
lp_tile_cache_map_transfers(lp->zsbuf_cache);
}
/**
* Unmap any mapped drawing surfaces
*/
void
llvmpipe_unmap_transfers(struct llvmpipe_context *lp)
{
uint i;
for (i = 0; i < lp->framebuffer.nr_cbufs; i++)
lp_flush_tile_cache(lp, lp->cbuf_cache[i]);
lp_flush_tile_cache(lp, lp->zsbuf_cache);
for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
lp_tile_cache_unmap_transfers(lp->cbuf_cache[i]);
}
lp_tile_cache_unmap_transfers(lp->zsbuf_cache);
}
static void llvmpipe_destroy( struct pipe_context *pipe )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
uint i;
if (llvmpipe->draw)
draw_destroy( llvmpipe->draw );
for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
llvmpipe->quad[i].polygon_stipple->destroy( llvmpipe->quad[i].polygon_stipple );
llvmpipe->quad[i].earlyz->destroy( llvmpipe->quad[i].earlyz );
llvmpipe->quad[i].shade->destroy( llvmpipe->quad[i].shade );
llvmpipe->quad[i].alpha_test->destroy( llvmpipe->quad[i].alpha_test );
llvmpipe->quad[i].depth_test->destroy( llvmpipe->quad[i].depth_test );
llvmpipe->quad[i].stencil_test->destroy( llvmpipe->quad[i].stencil_test );
llvmpipe->quad[i].occlusion->destroy( llvmpipe->quad[i].occlusion );
llvmpipe->quad[i].coverage->destroy( llvmpipe->quad[i].coverage );
llvmpipe->quad[i].blend->destroy( llvmpipe->quad[i].blend );
llvmpipe->quad[i].colormask->destroy( llvmpipe->quad[i].colormask );
llvmpipe->quad[i].output->destroy( llvmpipe->quad[i].output );
}
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
lp_destroy_tile_cache(llvmpipe->cbuf_cache[i]);
lp_destroy_tile_cache(llvmpipe->zsbuf_cache);
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
lp_destroy_tile_cache(llvmpipe->tex_cache[i]);
for (i = 0; i < Elements(llvmpipe->constants); i++) {
if (llvmpipe->constants[i].buffer) {
pipe_buffer_reference(&llvmpipe->constants[i].buffer, NULL);
}
}
FREE( llvmpipe );
}
static unsigned int
llvmpipe_is_texture_referenced( struct pipe_context *pipe,
struct pipe_texture *texture,
unsigned face, unsigned level)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
unsigned i;
if(llvmpipe->dirty_render_cache) {
for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
if(llvmpipe->framebuffer.cbufs[i] &&
llvmpipe->framebuffer.cbufs[i]->texture == texture)
return PIPE_REFERENCED_FOR_WRITE;
}
if(llvmpipe->framebuffer.zsbuf &&
llvmpipe->framebuffer.zsbuf->texture == texture)
return PIPE_REFERENCED_FOR_WRITE;
}
/* FIXME: we also need to do the same for the texture cache */
return PIPE_UNREFERENCED;
}
static unsigned int
llvmpipe_is_buffer_referenced( struct pipe_context *pipe,
struct pipe_buffer *buf)
{
return PIPE_UNREFERENCED;
}
struct pipe_context *
llvmpipe_create( struct pipe_screen *screen )
{
struct llvmpipe_context *llvmpipe = CALLOC_STRUCT(llvmpipe_context);
uint i;
util_init_math();
#ifdef PIPE_ARCH_X86
llvmpipe->use_sse = !debug_get_bool_option( "GALLIUM_NOSSE", FALSE );
#else
llvmpipe->use_sse = FALSE;
#endif
llvmpipe->dump_fs = debug_get_bool_option( "GALLIUM_DUMP_FS", FALSE );
llvmpipe->pipe.winsys = screen->winsys;
llvmpipe->pipe.screen = screen;
llvmpipe->pipe.destroy = llvmpipe_destroy;
/* state setters */
llvmpipe->pipe.create_blend_state = llvmpipe_create_blend_state;
llvmpipe->pipe.bind_blend_state = llvmpipe_bind_blend_state;
llvmpipe->pipe.delete_blend_state = llvmpipe_delete_blend_state;
llvmpipe->pipe.create_sampler_state = llvmpipe_create_sampler_state;
llvmpipe->pipe.bind_sampler_states = llvmpipe_bind_sampler_states;
llvmpipe->pipe.delete_sampler_state = llvmpipe_delete_sampler_state;
llvmpipe->pipe.create_depth_stencil_alpha_state = llvmpipe_create_depth_stencil_state;
llvmpipe->pipe.bind_depth_stencil_alpha_state = llvmpipe_bind_depth_stencil_state;
llvmpipe->pipe.delete_depth_stencil_alpha_state = llvmpipe_delete_depth_stencil_state;
llvmpipe->pipe.create_rasterizer_state = llvmpipe_create_rasterizer_state;
llvmpipe->pipe.bind_rasterizer_state = llvmpipe_bind_rasterizer_state;
llvmpipe->pipe.delete_rasterizer_state = llvmpipe_delete_rasterizer_state;
llvmpipe->pipe.create_fs_state = llvmpipe_create_fs_state;
llvmpipe->pipe.bind_fs_state = llvmpipe_bind_fs_state;
llvmpipe->pipe.delete_fs_state = llvmpipe_delete_fs_state;
llvmpipe->pipe.create_vs_state = llvmpipe_create_vs_state;
llvmpipe->pipe.bind_vs_state = llvmpipe_bind_vs_state;
llvmpipe->pipe.delete_vs_state = llvmpipe_delete_vs_state;
llvmpipe->pipe.set_blend_color = llvmpipe_set_blend_color;
llvmpipe->pipe.set_clip_state = llvmpipe_set_clip_state;
llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
llvmpipe->pipe.set_framebuffer_state = llvmpipe_set_framebuffer_state;
llvmpipe->pipe.set_polygon_stipple = llvmpipe_set_polygon_stipple;
llvmpipe->pipe.set_scissor_state = llvmpipe_set_scissor_state;
llvmpipe->pipe.set_sampler_textures = llvmpipe_set_sampler_textures;
llvmpipe->pipe.set_viewport_state = llvmpipe_set_viewport_state;
llvmpipe->pipe.set_vertex_buffers = llvmpipe_set_vertex_buffers;
llvmpipe->pipe.set_vertex_elements = llvmpipe_set_vertex_elements;
llvmpipe->pipe.draw_arrays = llvmpipe_draw_arrays;
llvmpipe->pipe.draw_elements = llvmpipe_draw_elements;
llvmpipe->pipe.draw_range_elements = llvmpipe_draw_range_elements;
llvmpipe->pipe.set_edgeflags = llvmpipe_set_edgeflags;
llvmpipe->pipe.clear = llvmpipe_clear;
llvmpipe->pipe.flush = llvmpipe_flush;
llvmpipe->pipe.is_texture_referenced = llvmpipe_is_texture_referenced;
llvmpipe->pipe.is_buffer_referenced = llvmpipe_is_buffer_referenced;
llvmpipe_init_query_funcs( llvmpipe );
llvmpipe_init_texture_funcs( llvmpipe );
/*
* Alloc caches for accessing drawing surfaces and textures.
* Must be before quad stage setup!
*/
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
llvmpipe->cbuf_cache[i] = lp_create_tile_cache( screen );
llvmpipe->zsbuf_cache = lp_create_tile_cache( screen );
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
llvmpipe->tex_cache[i] = lp_create_tile_cache( screen );
/* setup quad rendering stages */
for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
llvmpipe->quad[i].polygon_stipple = lp_quad_polygon_stipple_stage(llvmpipe);
llvmpipe->quad[i].earlyz = lp_quad_earlyz_stage(llvmpipe);
llvmpipe->quad[i].shade = lp_quad_shade_stage(llvmpipe);
llvmpipe->quad[i].alpha_test = lp_quad_alpha_test_stage(llvmpipe);
llvmpipe->quad[i].depth_test = lp_quad_depth_test_stage(llvmpipe);
llvmpipe->quad[i].stencil_test = lp_quad_stencil_test_stage(llvmpipe);
llvmpipe->quad[i].occlusion = lp_quad_occlusion_stage(llvmpipe);
llvmpipe->quad[i].coverage = lp_quad_coverage_stage(llvmpipe);
llvmpipe->quad[i].blend = lp_quad_blend_stage(llvmpipe);
llvmpipe->quad[i].colormask = lp_quad_colormask_stage(llvmpipe);
llvmpipe->quad[i].output = lp_quad_output_stage(llvmpipe);
}
/* vertex shader samplers */
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
llvmpipe->tgsi.vert_samplers[i].base.get_samples = lp_get_samples_vertex;
llvmpipe->tgsi.vert_samplers[i].unit = i;
llvmpipe->tgsi.vert_samplers[i].lp = llvmpipe;
llvmpipe->tgsi.vert_samplers[i].cache = llvmpipe->tex_cache[i];
llvmpipe->tgsi.vert_samplers_list[i] = &llvmpipe->tgsi.vert_samplers[i];
}
/* fragment shader samplers */
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
llvmpipe->tgsi.frag_samplers[i].base.get_samples = lp_get_samples_fragment;
llvmpipe->tgsi.frag_samplers[i].unit = i;
llvmpipe->tgsi.frag_samplers[i].lp = llvmpipe;
llvmpipe->tgsi.frag_samplers[i].cache = llvmpipe->tex_cache[i];
llvmpipe->tgsi.frag_samplers_list[i] = &llvmpipe->tgsi.frag_samplers[i];
}
/*
* Create drawing context and plug our rendering stage into it.
*/
llvmpipe->draw = draw_create();
if (!llvmpipe->draw)
goto fail;
draw_texture_samplers(llvmpipe->draw,
PIPE_MAX_SAMPLERS,
(struct tgsi_sampler **)
llvmpipe->tgsi.vert_samplers_list);
llvmpipe->setup = lp_draw_render_stage(llvmpipe);
if (!llvmpipe->setup)
goto fail;
if (debug_get_bool_option( "SP_NO_RAST", FALSE ))
llvmpipe->no_rast = TRUE;
if (debug_get_bool_option( "SP_NO_VBUF", FALSE )) {
/* Deprecated path -- vbuf is the intended interface to the draw module:
*/
draw_set_rasterize_stage(llvmpipe->draw, llvmpipe->setup);
}
else {
lp_init_vbuf(llvmpipe);
}
/* plug in AA line/point stages */
draw_install_aaline_stage(llvmpipe->draw, &llvmpipe->pipe);
draw_install_aapoint_stage(llvmpipe->draw, &llvmpipe->pipe);
#if USE_DRAW_STAGE_PSTIPPLE
/* Do polygon stipple w/ texture map + frag prog? */
draw_install_pstipple_stage(llvmpipe->draw, &llvmpipe->pipe);
#endif
lp_init_surface_functions(llvmpipe);
return &llvmpipe->pipe;
fail:
llvmpipe_destroy(&llvmpipe->pipe);
return NULL;
}

View file

@ -0,0 +1,168 @@
/**************************************************************************
*
* 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_CONTEXT_H
#define SP_CONTEXT_H
#include "pipe/p_context.h"
#include "draw/draw_vertex.h"
#include "lp_quad_pipe.h"
#include "lp_tex_sample.h"
/**
* This is a temporary variable for testing draw-stage polygon stipple.
* If zero, do stipple in lp_quad_stipple.c
*/
#define USE_DRAW_STAGE_PSTIPPLE 1
/* Number of threads working on individual quads.
* Setting to 1 disables this feature.
*/
#define SP_NUM_QUAD_THREADS 1
struct llvmpipe_vbuf_render;
struct draw_context;
struct draw_stage;
struct llvmpipe_tile_cache;
struct lp_fragment_shader;
struct lp_vertex_shader;
struct llvmpipe_context {
struct pipe_context pipe; /**< base class */
/** Constant state objects */
const struct pipe_blend_state *blend;
const struct pipe_sampler_state *sampler[PIPE_MAX_SAMPLERS];
const struct pipe_depth_stencil_alpha_state *depth_stencil;
const struct pipe_rasterizer_state *rasterizer;
const struct lp_fragment_shader *fs;
const struct lp_vertex_shader *vs;
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_clip_state clip;
struct pipe_constant_buffer constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
struct pipe_texture *texture[PIPE_MAX_SAMPLERS];
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
unsigned num_samplers;
unsigned num_textures;
unsigned num_vertex_elements;
unsigned num_vertex_buffers;
unsigned dirty; /**< Mask of SP_NEW_x flags */
/* Counter for occlusion queries. Note this supports overlapping
* queries.
*/
uint64_t occlusion_count;
unsigned active_query_count;
/** Mapped vertex buffers */
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
/** Mapped constant buffers */
void *mapped_constants[PIPE_SHADER_TYPES];
/** Vertex format */
struct vertex_info vertex_info;
struct vertex_info vertex_info_vbuf;
/** Which vertex shader output slot contains point size */
int psize_slot;
unsigned reduced_api_prim; /**< PIPE_PRIM_POINTS, _LINES or _TRIANGLES */
/** Derived from scissor and surface bounds: */
struct pipe_scissor_state cliprect;
unsigned line_stipple_counter;
/** Software quad rendering pipeline */
struct {
struct quad_stage *polygon_stipple;
struct quad_stage *earlyz;
struct quad_stage *shade;
struct quad_stage *alpha_test;
struct quad_stage *stencil_test;
struct quad_stage *depth_test;
struct quad_stage *occlusion;
struct quad_stage *coverage;
struct quad_stage *blend;
struct quad_stage *colormask;
struct quad_stage *output;
struct quad_stage *first; /**< points to one of the above stages */
} quad[SP_NUM_QUAD_THREADS];
/** TGSI exec things */
struct {
struct lp_shader_sampler vert_samplers[PIPE_MAX_SAMPLERS];
struct lp_shader_sampler *vert_samplers_list[PIPE_MAX_SAMPLERS];
struct lp_shader_sampler frag_samplers[PIPE_MAX_SAMPLERS];
struct lp_shader_sampler *frag_samplers_list[PIPE_MAX_SAMPLERS];
} tgsi;
/** The primitive drawing context */
struct draw_context *draw;
struct draw_stage *setup;
struct draw_stage *vbuf;
struct llvmpipe_vbuf_render *vbuf_render;
boolean dirty_render_cache;
struct llvmpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
struct llvmpipe_tile_cache *zsbuf_cache;
struct llvmpipe_tile_cache *tex_cache[PIPE_MAX_SAMPLERS];
unsigned use_sse : 1;
unsigned dump_fs : 1;
unsigned no_rast : 1;
};
static INLINE struct llvmpipe_context *
llvmpipe_context( struct pipe_context *pipe )
{
return (struct llvmpipe_context *)pipe;
}
#endif /* SP_CONTEXT_H */

View file

@ -0,0 +1,194 @@
/**************************************************************************
*
* 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:
* Brian Paul
* Keith Whitwell
*/
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "pipe/internal/p_winsys_screen.h"
#include "pipe/p_inlines.h"
#include "util/u_prim.h"
#include "lp_context.h"
#include "lp_state.h"
#include "draw/draw_context.h"
static void
llvmpipe_map_constant_buffers(struct llvmpipe_context *lp)
{
struct pipe_winsys *ws = lp->pipe.winsys;
uint i, size;
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
if (lp->constants[i].buffer && lp->constants[i].buffer->size)
lp->mapped_constants[i] = ws->buffer_map(ws, lp->constants[i].buffer,
PIPE_BUFFER_USAGE_CPU_READ);
}
if (lp->constants[PIPE_SHADER_VERTEX].buffer)
size = lp->constants[PIPE_SHADER_VERTEX].buffer->size;
else
size = 0;
draw_set_mapped_constant_buffer(lp->draw,
lp->mapped_constants[PIPE_SHADER_VERTEX],
size);
}
static void
llvmpipe_unmap_constant_buffers(struct llvmpipe_context *lp)
{
struct pipe_winsys *ws = lp->pipe.winsys;
uint i;
/* really need to flush all prims since the vert/frag shaders const buffers
* are going away now.
*/
draw_flush(lp->draw);
draw_set_mapped_constant_buffer(lp->draw, NULL, 0);
for (i = 0; i < 2; i++) {
if (lp->constants[i].buffer && lp->constants[i].buffer->size)
ws->buffer_unmap(ws, lp->constants[i].buffer);
lp->mapped_constants[i] = NULL;
}
}
boolean
llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count)
{
return llvmpipe_draw_elements(pipe, NULL, 0, mode, start, count);
}
/**
* Draw vertex arrays, with optional indexing.
* Basically, map the vertex buffers (and drawing surfaces), then hand off
* the drawing to the 'draw' module.
*/
boolean
llvmpipe_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned mode, unsigned start, unsigned count)
{
struct llvmpipe_context *lp = llvmpipe_context(pipe);
struct draw_context *draw = lp->draw;
unsigned i;
lp->reduced_api_prim = u_reduced_prim(mode);
if (lp->dirty)
llvmpipe_update_derived( lp );
llvmpipe_map_transfers(lp);
llvmpipe_map_constant_buffers(lp);
/*
* Map vertex buffers
*/
for (i = 0; i < lp->num_vertex_buffers; i++) {
void *buf
= pipe_buffer_map(pipe->screen,
lp->vertex_buffer[i].buffer,
PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_vertex_buffer(draw, i, buf);
}
/* Map index buffer, if present */
if (indexBuffer) {
void *mapped_indexes
= pipe_buffer_map(pipe->screen, indexBuffer,
PIPE_BUFFER_USAGE_CPU_READ);
draw_set_mapped_element_buffer_range(draw, indexSize,
min_index,
max_index,
mapped_indexes);
}
else {
/* no index/element buffer */
draw_set_mapped_element_buffer_range(draw, 0, start,
start + count - 1, NULL);
}
/* draw! */
draw_arrays(draw, mode, start, count);
/*
* unmap vertex/index buffers - will cause draw module to flush
*/
for (i = 0; i < lp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL);
pipe_buffer_unmap(pipe->screen, lp->vertex_buffer[i].buffer);
}
if (indexBuffer) {
draw_set_mapped_element_buffer(draw, 0, NULL);
pipe_buffer_unmap(pipe->screen, indexBuffer);
}
/* Note: leave drawing surfaces mapped */
llvmpipe_unmap_constant_buffers(lp);
lp->dirty_render_cache = TRUE;
return TRUE;
}
boolean
llvmpipe_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned mode, unsigned start, unsigned count)
{
return llvmpipe_draw_range_elements( pipe, indexBuffer,
indexSize,
0, 0xffffffff,
mode, start, count );
}
void
llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags)
{
struct llvmpipe_context *lp = llvmpipe_context(pipe);
draw_set_edgeflags(lp->draw, edgeflags);
}

View file

@ -0,0 +1,94 @@
/**************************************************************************
*
* 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 "pipe/p_defines.h"
#include "draw/draw_context.h"
#include "lp_flush.h"
#include "lp_context.h"
#include "lp_surface.h"
#include "lp_state.h"
#include "lp_tile_cache.h"
#include "lp_winsys.h"
void
llvmpipe_flush( struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
uint i;
draw_flush(llvmpipe->draw);
if (flags & PIPE_FLUSH_TEXTURE_CACHE) {
for (i = 0; i < llvmpipe->num_textures; i++) {
lp_flush_tile_cache(llvmpipe, llvmpipe->tex_cache[i]);
}
}
if (flags & PIPE_FLUSH_RENDER_CACHE) {
for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++)
if (llvmpipe->cbuf_cache[i])
lp_flush_tile_cache(llvmpipe, llvmpipe->cbuf_cache[i]);
if (llvmpipe->zsbuf_cache)
lp_flush_tile_cache(llvmpipe, llvmpipe->zsbuf_cache);
/* Need this call for hardware buffers before swapbuffers.
*
* there should probably be another/different flush-type function
* that's called before swapbuffers because we don't always want
* to unmap surfaces when flushing.
*/
llvmpipe_unmap_transfers(llvmpipe);
llvmpipe->dirty_render_cache = FALSE;
}
/* Enable to dump BMPs of the color/depth buffers each frame */
#if 0
if(flags & PIPE_FLUSH_FRAME) {
static unsigned frame_no = 1;
static char filename[256];
util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(filename, llvmpipe->framebuffer.cbufs[0]);
util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(filename, llvmpipe->framebuffer.zsbuf);
++frame_no;
}
#endif
if (fence)
*fence = NULL;
}

View file

@ -0,0 +1,37 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_FLUSH_H
#define SP_FLUSH_H
struct pipe_context;
struct pipe_fence_handle;
void llvmpipe_flush(struct pipe_context *pipe, unsigned flags,
struct pipe_fence_handle **fence);
#endif

View file

@ -0,0 +1,54 @@
/**************************************************************************
*
* 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_FS_H
#define SP_FS_H
struct lp_fragment_shader *
llvmpipe_create_fs_exec(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ);
struct lp_fragment_shader *
llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ);
struct lp_fragment_shader *
llvmpipe_create_fs_llvm(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ);
struct tgsi_interp_coef;
struct tgsi_exec_vector;
void lp_setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos);
#endif

View file

@ -0,0 +1,162 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Execute fragment shader using the TGSI interpreter.
*/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_fs.h"
#include "lp_quad.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_parse.h"
/**
* Subclass of lp_fragment_shader
*/
struct lp_exec_fragment_shader
{
struct lp_fragment_shader base;
/* No other members for now */
};
/** cast wrapper */
static INLINE struct lp_exec_fragment_shader *
lp_exec_fragment_shader(const struct lp_fragment_shader *base)
{
return (struct lp_exec_fragment_shader *) base;
}
/**
* Compute quad X,Y,Z,W for the four fragments in a quad.
*
* This should really be part of the compiled shader.
*/
void
lp_setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos)
{
uint chan;
/* do X */
quadpos->xyzw[0].f[0] = x;
quadpos->xyzw[0].f[1] = x + 1;
quadpos->xyzw[0].f[2] = x;
quadpos->xyzw[0].f[3] = x + 1;
/* do Y */
quadpos->xyzw[1].f[0] = y;
quadpos->xyzw[1].f[1] = y;
quadpos->xyzw[1].f[2] = y + 1;
quadpos->xyzw[1].f[3] = y + 1;
/* do Z and W for all fragments in the quad */
for (chan = 2; chan < 4; chan++) {
const float dadx = coef->dadx[chan];
const float dady = coef->dady[chan];
const float a0 = coef->a0[chan] + dadx * x + dady * y;
quadpos->xyzw[chan].f[0] = a0;
quadpos->xyzw[chan].f[1] = a0 + dadx;
quadpos->xyzw[chan].f[2] = a0 + dady;
quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
}
}
static void
exec_prepare( const struct lp_fragment_shader *base,
struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers )
{
/*
* Bind tokens/shader to the interpreter's machine state.
* Avoid redundant binding.
*/
if (machine->Tokens != base->shader.tokens) {
tgsi_exec_machine_bind_shader( machine,
base->shader.tokens,
PIPE_MAX_SAMPLERS,
samplers );
}
}
/* TODO: hide the machine struct in here somewhere, remove from this
* interface:
*/
static unsigned
exec_run( const struct lp_fragment_shader *base,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
/* Compute X, Y, Z, W vals for this quad */
lp_setup_pos_vector(quad->posCoef,
(float)quad->input.x0, (float)quad->input.y0,
&machine->QuadPos);
return tgsi_exec_machine_run( machine );
}
static void
exec_delete( struct lp_fragment_shader *base )
{
FREE((void *) base->shader.tokens);
FREE(base);
}
struct lp_fragment_shader *
llvmpipe_create_fs_exec(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ)
{
struct lp_exec_fragment_shader *shader;
/* Decide whether we'll be codegenerating this shader and if so do
* that now.
*/
shader = CALLOC_STRUCT(lp_exec_fragment_shader);
if (!shader)
return NULL;
/* we need to keep a local copy of the tokens */
shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
shader->base.prepare = exec_prepare;
shader->base.run = exec_run;
shader->base.delete = exec_delete;
return &shader->base;
}

View file

@ -0,0 +1,205 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Execute fragment shader using LLVM code generation.
* Authors:
* Zack Rusin
*/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_fs.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_sse2.h"
#if 0
/**
* Subclass of lp_fragment_shader
*/
struct lp_llvm_fragment_shader
{
struct lp_fragment_shader base;
struct gallivm_prog *llvm_prog;
};
static void
shade_quad_llvm(struct quad_stage *qs,
struct quad_header *quad)
{
struct quad_shade_stage *qss = quad_shade_stage(qs);
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
float dests[4][16][4] ALIGN16_ATTRIB;
float inputs[4][16][4] ALIGN16_ATTRIB;
const float fx = (float) quad->x0;
const float fy = (float) quad->y0;
struct gallivm_prog *llvm = qss->llvm_prog;
inputs[0][0][0] = fx;
inputs[1][0][0] = fx + 1.0f;
inputs[2][0][0] = fx;
inputs[3][0][0] = fx + 1.0f;
inputs[0][0][1] = fy;
inputs[1][0][1] = fy;
inputs[2][0][1] = fy + 1.0f;
inputs[3][0][1] = fy + 1.0f;
gallivm_prog_inputs_interpolate(llvm, inputs, quad->coef);
#if DLLVM
debug_printf("MASK = %d\n", quad->mask);
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 2; ++j) {
debug_printf("IN(%d,%d) [%f %f %f %f]\n", i, j,
inputs[i][j][0], inputs[i][j][1], inputs[i][j][2], inputs[i][j][3]);
}
}
#endif
quad->mask &=
gallivm_fragment_shader_exec(llvm, fx, fy, dests, inputs,
llvmpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
qss->samplers);
#if DLLVM
debug_printf("OUT LLVM = 1[%f %f %f %f], 2[%f %f %f %f]\n",
dests[0][0][0], dests[0][0][1], dests[0][0][2], dests[0][0][3],
dests[0][1][0], dests[0][1][1], dests[0][1][2], dests[0][1][3]);
#endif
/* store result color */
if (qss->colorOutSlot >= 0) {
unsigned i;
/* XXX need to handle multiple color outputs someday */
allvmrt(qss->stage.llvmpipe->fs->info.output_semantic_name[qss->colorOutSlot]
== TGSI_SEMANTIC_COLOR);
for (i = 0; i < QUAD_SIZE; ++i) {
quad->outputs.color[0][0][i] = dests[i][qss->colorOutSlot][0];
quad->outputs.color[0][1][i] = dests[i][qss->colorOutSlot][1];
quad->outputs.color[0][2][i] = dests[i][qss->colorOutSlot][2];
quad->outputs.color[0][3][i] = dests[i][qss->colorOutSlot][3];
}
}
#if DLLVM
for (int i = 0; i < QUAD_SIZE; ++i) {
debug_printf("QLLVM%d(%d) [%f, %f, %f, %f]\n", i, qss->colorOutSlot,
quad->outputs.color[0][0][i],
quad->outputs.color[0][1][i],
quad->outputs.color[0][2][i],
quad->outputs.color[0][3][i]);
}
#endif
/* store result Z */
if (qss->depthOutSlot >= 0) {
/* output[slot] is new Z */
uint i;
for (i = 0; i < 4; i++) {
quad->outputs.depth[i] = dests[i][0][2];
}
}
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] = inputs[i][0][2];
}
}
#if DLLVM
debug_printf("D [%f, %f, %f, %f] mask = %d\n",
quad->outputs.depth[0],
quad->outputs.depth[1],
quad->outputs.depth[2],
quad->outputs.depth[3], quad->mask);
#endif
/* shader may cull fragments */
if( quad->mask ) {
qs->next->run( qs->next, quad );
}
}
unsigned
run_llvm_fs( const struct lp_fragment_shader *base,
struct foo *machine )
{
}
void
delete_llvm_fs( struct lp_fragment_shader *base )
{
FREE(base);
}
struct lp_fragment_shader *
llvmpipe_create_fs_llvm(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ)
{
struct lp_llvm_fragment_shader *shader = NULL;
/* LLVM fragment shaders currently disabled:
*/
state = CALLOC_STRUCT(lp_llvm_shader_state);
if (!state)
return NULL;
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);
if (shader) {
shader->base.run = run_llvm_fs;
shader->base.delete = delete_llvm_fs;
}
return shader;
}
#else
struct lp_fragment_shader *
llvmpipe_create_fs_llvm(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ)
{
return NULL;
}
#endif

View file

@ -0,0 +1,169 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Execute fragment shader using runtime SSE code generation.
*/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_fs.h"
#include "lp_quad.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_sse2.h"
#if defined(PIPE_ARCH_X86)
#include "rtasm/rtasm_x86sse.h"
/**
* Subclass of lp_fragment_shader
*/
struct lp_sse_fragment_shader
{
struct lp_fragment_shader base;
struct x86_function sse2_program;
tgsi_sse2_fs_function func;
float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
};
/** cast wrapper */
static INLINE struct lp_sse_fragment_shader *
lp_sse_fragment_shader(const struct lp_fragment_shader *base)
{
return (struct lp_sse_fragment_shader *) base;
}
static void
fs_sse_prepare( const struct lp_fragment_shader *base,
struct tgsi_exec_machine *machine,
struct tgsi_sampler **samplers )
{
machine->Samplers = samplers;
}
/* TODO: codegenerate the whole run function, skip this wrapper.
* TODO: break dependency on tgsi_exec_machine struct
* TODO: push Position calculation into the generated shader
* TODO: process >1 quad at a time
*/
static unsigned
fs_sse_run( const struct lp_fragment_shader *base,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
struct lp_sse_fragment_shader *shader = lp_sse_fragment_shader(base);
/* Compute X, Y, Z, W vals for this quad -- place in temp[0] for now */
lp_setup_pos_vector(quad->posCoef,
(float)quad->input.x0, (float)quad->input.y0,
machine->Temps);
/* init kill mask */
tgsi_set_kill_mask(machine, 0x0);
tgsi_set_exec_mask(machine, 1, 1, 1, 1);
shader->func( machine,
machine->Consts,
(const float (*)[4])shader->immediates,
machine->InterpCoefs
// , &machine->QuadPos
);
return ~(machine->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0]);
}
static void
fs_sse_delete( struct lp_fragment_shader *base )
{
struct lp_sse_fragment_shader *shader = lp_sse_fragment_shader(base);
x86_release_func( &shader->sse2_program );
FREE(shader);
}
struct lp_fragment_shader *
llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ)
{
struct lp_sse_fragment_shader *shader;
if (!llvmpipe->use_sse)
return NULL;
shader = CALLOC_STRUCT(lp_sse_fragment_shader);
if (!shader)
return NULL;
x86_init_func( &shader->sse2_program );
if (!tgsi_emit_sse2( templ->tokens, &shader->sse2_program,
shader->immediates, FALSE )) {
FREE(shader);
return NULL;
}
shader->func = (tgsi_sse2_fs_function) x86_get_func( &shader->sse2_program );
if (!shader->func) {
x86_release_func( &shader->sse2_program );
FREE(shader);
return NULL;
}
shader->base.shader.tokens = NULL; /* don't hold reference to templ->tokens */
shader->base.prepare = fs_sse_prepare;
shader->base.run = fs_sse_run;
shader->base.delete = fs_sse_delete;
return &shader->base;
}
#else
/* Maybe put this variant in the header file.
*/
struct lp_fragment_shader *
llvmpipe_create_fs_sse(struct llvmpipe_context *llvmpipe,
const struct pipe_shader_state *templ)
{
return NULL;
}
#endif

View file

@ -0,0 +1,190 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* \brief A draw stage that drives our triangle setup routines from
* within the draw pipeline. One of two ways to drive setup, the
* other being in lp_prim_vbuf.c.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul
*/
#include "lp_context.h"
#include "lp_setup.h"
#include "lp_state.h"
#include "lp_prim_setup.h"
#include "draw/draw_pipe.h"
#include "draw/draw_vertex.h"
#include "util/u_memory.h"
/**
* Triangle setup info (derived from draw_stage).
* Also used for line drawing (taking some liberties).
*/
struct setup_stage {
struct draw_stage stage; /**< This must be first (base class) */
struct setup_context *setup;
};
/**
* Basically a cast wrapper.
*/
static INLINE struct setup_stage *setup_stage( struct draw_stage *stage )
{
return (struct setup_stage *)stage;
}
typedef const float (*cptrf4)[4];
static void
do_tri(struct draw_stage *stage, struct prim_header *prim)
{
struct setup_stage *setup = setup_stage( stage );
setup_tri( setup->setup,
(cptrf4)prim->v[0]->data,
(cptrf4)prim->v[1]->data,
(cptrf4)prim->v[2]->data );
}
static void
do_line(struct draw_stage *stage, struct prim_header *prim)
{
struct setup_stage *setup = setup_stage( stage );
setup_line( setup->setup,
(cptrf4)prim->v[0]->data,
(cptrf4)prim->v[1]->data );
}
static void
do_point(struct draw_stage *stage, struct prim_header *prim)
{
struct setup_stage *setup = setup_stage( stage );
setup_point( setup->setup,
(cptrf4)prim->v[0]->data );
}
static void setup_begin( struct draw_stage *stage )
{
struct setup_stage *setup = setup_stage(stage);
setup_prepare( setup->setup );
stage->point = do_point;
stage->line = do_line;
stage->tri = do_tri;
}
static void setup_first_point( struct draw_stage *stage,
struct prim_header *header )
{
setup_begin(stage);
stage->point( stage, header );
}
static void setup_first_line( struct draw_stage *stage,
struct prim_header *header )
{
setup_begin(stage);
stage->line( stage, header );
}
static void setup_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
setup_begin(stage);
stage->tri( stage, header );
}
static void setup_flush( struct draw_stage *stage,
unsigned flags )
{
stage->point = setup_first_point;
stage->line = setup_first_line;
stage->tri = setup_first_tri;
}
static void reset_stipple_counter( struct draw_stage *stage )
{
}
static void render_destroy( struct draw_stage *stage )
{
struct setup_stage *ssetup = setup_stage(stage);
setup_destroy_context(ssetup->setup);
FREE( stage );
}
/**
* Create a new primitive setup/render stage.
*/
struct draw_stage *lp_draw_render_stage( struct llvmpipe_context *llvmpipe )
{
struct setup_stage *sstage = CALLOC_STRUCT(setup_stage);
sstage->setup = setup_create_context(llvmpipe);
sstage->stage.draw = llvmpipe->draw;
sstage->stage.point = setup_first_point;
sstage->stage.line = setup_first_line;
sstage->stage.tri = setup_first_tri;
sstage->stage.flush = setup_flush;
sstage->stage.reset_stipple_counter = reset_stipple_counter;
sstage->stage.destroy = render_destroy;
return (struct draw_stage *)sstage;
}
struct setup_context *
lp_draw_setup_context( struct draw_stage *stage )
{
struct setup_stage *ssetup = setup_stage(stage);
return ssetup->setup;
}
void
lp_draw_flush( struct draw_stage *stage )
{
stage->flush( stage, 0 );
}

View file

@ -0,0 +1,85 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_PRIM_SETUP_H
#define SP_PRIM_SETUP_H
/**
* vbuf is a special stage to gather the stream of triangles, lines, points
* together and reconstruct vertex buffers for hardware upload.
*
* First attempt, work in progress.
*
* TODO:
* - separate out vertex buffer building and primitive emit, ie >1 draw per vb.
* - tell vbuf stage how to build hw vertices directly
* - pass vbuf stage a buffer pointer for direct emit to agp/vram.
*
*
*
* 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.
*/
struct draw_stage;
struct llvmpipe_context;
typedef void (*vbuf_draw_func)( struct pipe_context *pipe,
unsigned prim,
const ushort *elements,
unsigned nr_elements,
const void *vertex_buffer,
unsigned nr_vertices );
extern struct draw_stage *
lp_draw_render_stage( struct llvmpipe_context *llvmpipe );
extern struct setup_context *
lp_draw_setup_context( struct draw_stage * );
extern void
lp_draw_flush( struct draw_stage * );
extern struct draw_stage *
lp_draw_vbuf_stage( struct draw_context *draw_context,
struct pipe_context *pipe,
vbuf_draw_func draw );
#endif /* SP_PRIM_SETUP_H */

View file

@ -0,0 +1,585 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Interface between 'draw' module's output and the llvmpipe rasterizer/setup
* code. When the 'draw' module has finished filling a vertex buffer, the
* draw_arrays() functions below will be called. Loop over the vertices and
* call the point/line/tri setup functions.
*
* Authors
* Brian Paul
*/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_prim_vbuf.h"
#include "lp_prim_setup.h"
#include "lp_setup.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "util/u_memory.h"
#define SP_MAX_VBUF_INDEXES 1024
#define SP_MAX_VBUF_SIZE 4096
typedef const float (*cptrf4)[4];
/**
* Subclass of vbuf_render.
*/
struct llvmpipe_vbuf_render
{
struct vbuf_render base;
struct llvmpipe_context *llvmpipe;
uint prim;
uint vertex_size;
uint nr_vertices;
uint vertex_buffer_size;
void *vertex_buffer;
};
/** cast wrapper */
static struct llvmpipe_vbuf_render *
llvmpipe_vbuf_render(struct vbuf_render *vbr)
{
return (struct llvmpipe_vbuf_render *) vbr;
}
static const struct vertex_info *
lp_vbuf_get_vertex_info(struct vbuf_render *vbr)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
return llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
}
static boolean
lp_vbuf_allocate_vertices(struct vbuf_render *vbr,
ushort vertex_size, ushort nr_vertices)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
unsigned size = vertex_size * nr_vertices;
if (cvbr->vertex_buffer_size < size) {
align_free(cvbr->vertex_buffer);
cvbr->vertex_buffer = align_malloc(size, 16);
cvbr->vertex_buffer_size = size;
}
cvbr->vertex_size = vertex_size;
cvbr->nr_vertices = nr_vertices;
return cvbr->vertex_buffer != NULL;
}
static void
lp_vbuf_release_vertices(struct vbuf_render *vbr)
{
#if 0
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
const struct vertex_info *info =
llvmpipe_get_vbuf_vertex_info(cvbr->llvmpipe);
const float *vtx = (const float *) cvbr->vertex_buffer;
uint i, j;
debug_printf("%s (vtx_size = %u, vtx_used = %u)\n",
__FUNCTION__, cvbr->vertex_size, cvbr->nr_vertices);
for (i = 0; i < cvbr->nr_vertices; i++) {
for (j = 0; j < info->num_attribs; j++) {
uint k;
switch (info->attrib[j].emit) {
case EMIT_4F: k = 4; break;
case EMIT_3F: k = 3; break;
case EMIT_2F: k = 2; break;
case EMIT_1F: k = 1; break;
default: assert(0);
}
debug_printf("Vert %u attr %u: ", i, j);
while (k-- > 0) {
debug_printf("%g ", vtx[0]);
vtx++;
}
debug_printf("\n");
}
}
}
#endif
/* keep the old allocation for next time */
}
static void *
lp_vbuf_map_vertices(struct vbuf_render *vbr)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
return cvbr->vertex_buffer;
}
static void
lp_vbuf_unmap_vertices(struct vbuf_render *vbr,
ushort min_index,
ushort max_index )
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
/* do nothing */
}
static boolean
lp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
/* XXX: break this dependency - make setup_context live under
* llvmpipe, rename the old "setup" draw stage to something else.
*/
struct setup_context *setup_ctx = lp_draw_setup_context(cvbr->llvmpipe->setup);
setup_prepare( setup_ctx );
cvbr->prim = prim;
return TRUE;
}
static INLINE cptrf4 get_vert( const void *vertex_buffer,
int index,
int stride )
{
return (cptrf4)((char *)vertex_buffer + index * stride);
}
/**
* draw elements / indexed primitives
*/
static void
lp_vbuf_draw(struct vbuf_render *vbr, const ushort *indices, uint nr)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer = cvbr->vertex_buffer;
unsigned i;
/* XXX: break this dependency - make setup_context live under
* llvmpipe, rename the old "setup" draw stage to something else.
*/
struct draw_stage *setup = llvmpipe->setup;
struct setup_context *setup_ctx = lp_draw_setup_context(setup);
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
setup_point( setup_ctx,
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
setup_line( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
setup_line( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
setup_line( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
if (nr) {
setup_line( setup_ctx,
get_vert(vertex_buffer, indices[nr-1], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
break;
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
for (i = 2; i < nr; i += 1) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-(i&1)], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
case PIPE_PRIM_TRIANGLE_FAN:
for (i = 2; i < nr; i += 1) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
case PIPE_PRIM_QUADS:
for (i = 3; i < nr; i += 4) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
case PIPE_PRIM_QUAD_STRIP:
for (i = 3; i < nr; i += 2) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride));
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color. Note that the first polygon vertex is passed as
* the last triangle vertex here.
* flatshade_first state makes no difference.
*/
for (i = 2; i < nr; i += 1) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
break;
default:
assert(0);
}
/* XXX: why are we calling this??? If we had to call something, it
* would be a function in lp_setup.c:
*/
lp_draw_flush( setup );
}
/**
* 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
lp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
struct llvmpipe_context *llvmpipe = cvbr->llvmpipe;
const unsigned stride = llvmpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer =
(void *) get_vert(cvbr->vertex_buffer, start, stride);
unsigned i;
/* XXX: break this dependency - make setup_context live under
* llvmpipe, rename the old "setup" draw stage to something else.
*/
struct draw_stage *setup = llvmpipe->setup;
struct setup_context *setup_ctx = lp_draw_setup_context(setup);
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
setup_point( setup_ctx,
get_vert(vertex_buffer, i-0, stride) );
}
break;
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
setup_line( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
setup_line( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
setup_line( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
if (nr) {
setup_line( setup_ctx,
get_vert(vertex_buffer, nr-1, stride),
get_vert(vertex_buffer, 0, stride) );
}
break;
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-2, stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
case PIPE_PRIM_TRIANGLE_STRIP:
for (i = 2; i < nr; i++) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i+(i&1)-1, stride),
get_vert(vertex_buffer, i-(i&1), stride),
get_vert(vertex_buffer, i-2, stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i+(i&1)-2, stride),
get_vert(vertex_buffer, i-(i&1)-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
case PIPE_PRIM_TRIANGLE_FAN:
for (i = 2; i < nr; i += 1) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
case PIPE_PRIM_QUADS:
for (i = 3; i < nr; i += 4) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
case PIPE_PRIM_QUAD_STRIP:
for (i = 3; i < nr; i += 2) {
if (llvmpipe->rasterizer->flatshade_first) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride) );
}
else {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color. Note that the first polygon vertex is passed as
* the last triangle vertex here.
* flatshade_first state makes no difference.
*/
for (i = 2; i < nr; i += 1) {
setup_tri( setup_ctx,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride) );
}
break;
default:
assert(0);
}
}
static void
lp_vbuf_destroy(struct vbuf_render *vbr)
{
struct llvmpipe_vbuf_render *cvbr = llvmpipe_vbuf_render(vbr);
cvbr->llvmpipe->vbuf_render = NULL;
FREE(cvbr);
}
/**
* Initialize the post-transform vertex buffer information for the given
* context.
*/
void
lp_init_vbuf(struct llvmpipe_context *lp)
{
assert(lp->draw);
lp->vbuf_render = CALLOC_STRUCT(llvmpipe_vbuf_render);
lp->vbuf_render->base.max_indices = SP_MAX_VBUF_INDEXES;
lp->vbuf_render->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
lp->vbuf_render->base.get_vertex_info = lp_vbuf_get_vertex_info;
lp->vbuf_render->base.allocate_vertices = lp_vbuf_allocate_vertices;
lp->vbuf_render->base.map_vertices = lp_vbuf_map_vertices;
lp->vbuf_render->base.unmap_vertices = lp_vbuf_unmap_vertices;
lp->vbuf_render->base.set_primitive = lp_vbuf_set_primitive;
lp->vbuf_render->base.draw = lp_vbuf_draw;
lp->vbuf_render->base.draw_arrays = lp_vbuf_draw_arrays;
lp->vbuf_render->base.release_vertices = lp_vbuf_release_vertices;
lp->vbuf_render->base.destroy = lp_vbuf_destroy;
lp->vbuf_render->llvmpipe = lp;
lp->vbuf = draw_vbuf_stage(lp->draw, &lp->vbuf_render->base);
draw_set_rasterize_stage(lp->draw, lp->vbuf);
draw_set_render(lp->draw, &lp->vbuf_render->base);
}

View file

@ -0,0 +1,38 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_VBUF_H
#define SP_VBUF_H
struct llvmpipe_context;
extern void
lp_init_vbuf(struct llvmpipe_context *llvmpipe);
#endif /* SP_VBUF_H */

View file

@ -0,0 +1,106 @@
/**************************************************************************
*
* 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_QUAD_H
#define SP_QUAD_H
#include "pipe/p_state.h"
#include "tgsi/tgsi_exec.h"
#define QUAD_PRIM_POINT 1
#define QUAD_PRIM_LINE 2
#define QUAD_PRIM_TRI 3
/* The rasterizer generates 2x2 quads of fragment and feeds them to
* the current fp_machine (see below).
* Remember that Y=0=top with Y increasing down the window.
*/
#define QUAD_TOP_LEFT 0
#define QUAD_TOP_RIGHT 1
#define QUAD_BOTTOM_LEFT 2
#define QUAD_BOTTOM_RIGHT 3
#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
#define MASK_ALL 0xf
/**
* Quad stage inputs (pos, coverage, front/back face, etc)
*/
struct quad_header_input
{
int x0, y0; /**< quad window pos, always even */
float coverage[QUAD_SIZE]; /**< fragment coverage for antialiasing */
unsigned facing:1; /**< Front (0) or back (1) facing? */
unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */
};
/**
* Quad stage inputs/outputs.
*/
struct quad_header_inout
{
unsigned mask:4;
};
/**
* Quad stage outputs (color & depth).
*/
struct quad_header_output
{
/** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
float color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE];
float depth[QUAD_SIZE];
};
/**
* Encodes everything we need to know about a 2x2 pixel block. Uses
* "Channel-Serial" or "SoA" layout.
*/
struct quad_header {
struct quad_header_input input;
struct quad_header_inout inout;
struct quad_header_output output;
const struct tgsi_interp_coef *coef;
const struct tgsi_interp_coef *posCoef;
unsigned nr_attrs;
};
#endif /* SP_QUAD_H */

View file

@ -0,0 +1,108 @@
/**
* quad alpha test
*/
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_quad_pipe.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
static void
alpha_test_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
const float ref = llvmpipe->depth_stencil->alpha.ref_value;
unsigned passMask = 0x0, j;
const uint cbuf = 0; /* only output[0].alpha is tested */
const float *aaaa = quad->output.color[cbuf][3];
switch (llvmpipe->depth_stencil->alpha.func) {
case PIPE_FUNC_NEVER:
break;
case PIPE_FUNC_LESS:
/*
* If mask were an array [4] we could do this SIMD-style:
* passMask = (quad->outputs.color[0][3] <= vec4(ref));
*/
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] < ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] == ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] <= ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] > ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] != ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (aaaa[j] >= ref) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_ALWAYS:
passMask = MASK_ALL;
break;
default:
assert(0);
}
quad->inout.mask &= passMask;
if (quad->inout.mask)
qs->next->run(qs->next, quad);
}
static void alpha_test_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void alpha_test_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *
lp_quad_alpha_test_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = alpha_test_begin;
stage->run = alpha_test_quad;
stage->destroy = alpha_test_destroy;
return stage;
}

View file

@ -0,0 +1,777 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* quad blending
* \author Brian Paul
*/
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_tile_cache.h"
#include "lp_quad_pipe.h"
#define VEC4_COPY(DST, SRC) \
do { \
DST[0] = SRC[0]; \
DST[1] = SRC[1]; \
DST[2] = SRC[2]; \
DST[3] = SRC[3]; \
} while(0)
#define VEC4_SCALAR(DST, SRC) \
do { \
DST[0] = SRC; \
DST[1] = SRC; \
DST[2] = SRC; \
DST[3] = SRC; \
} while(0)
#define VEC4_ADD(R, A, B) \
do { \
R[0] = A[0] + B[0]; \
R[1] = A[1] + B[1]; \
R[2] = A[2] + B[2]; \
R[3] = A[3] + B[3]; \
} while (0)
#define VEC4_SUB(R, A, B) \
do { \
R[0] = A[0] - B[0]; \
R[1] = A[1] - B[1]; \
R[2] = A[2] - B[2]; \
R[3] = A[3] - B[3]; \
} while (0)
/** Add and limit result to ceiling of 1.0 */
#define VEC4_ADD_SAT(R, A, B) \
do { \
R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
} while (0)
/** Subtract and limit result to floor of 0.0 */
#define VEC4_SUB_SAT(R, A, B) \
do { \
R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
} while (0)
#define VEC4_MUL(R, A, B) \
do { \
R[0] = A[0] * B[0]; \
R[1] = A[1] * B[1]; \
R[2] = A[2] * B[2]; \
R[3] = A[3] * B[3]; \
} while (0)
#define VEC4_MIN(R, A, B) \
do { \
R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
} while (0)
#define VEC4_MAX(R, A, B) \
do { \
R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
} while (0)
static void
logicop_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
uint cbuf;
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
float dest[4][QUAD_SIZE];
ubyte src[4][4], dst[4][4], res[4][4];
uint *src4 = (uint *) src;
uint *dst4 = (uint *) dst;
uint *res4 = (uint *) res;
struct llvmpipe_cached_tile *
tile = lp_get_cached_tile(llvmpipe,
llvmpipe->cbuf_cache[cbuf],
quad->input.x0, quad->input.y0);
float (*quadColor)[4] = quad->output.color[cbuf];
uint i, j;
/* get/swizzle dest colors */
for (j = 0; j < QUAD_SIZE; j++) {
int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
/* convert to ubyte */
for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
}
switch (llvmpipe->blend->logicop_func) {
case PIPE_LOGICOP_CLEAR:
for (j = 0; j < 4; j++)
res4[j] = 0;
break;
case PIPE_LOGICOP_NOR:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] | dst4[j]);
break;
case PIPE_LOGICOP_AND_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] & dst4[j];
break;
case PIPE_LOGICOP_COPY_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j];
break;
case PIPE_LOGICOP_AND_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & ~dst4[j];
break;
case PIPE_LOGICOP_INVERT:
for (j = 0; j < 4; j++)
res4[j] = ~dst4[j];
break;
case PIPE_LOGICOP_XOR:
for (j = 0; j < 4; j++)
res4[j] = dst4[j] ^ src4[j];
break;
case PIPE_LOGICOP_NAND:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] & dst4[j]);
break;
case PIPE_LOGICOP_AND:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & dst4[j];
break;
case PIPE_LOGICOP_EQUIV:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] ^ dst4[j]);
break;
case PIPE_LOGICOP_NOOP:
for (j = 0; j < 4; j++)
res4[j] = dst4[j];
break;
case PIPE_LOGICOP_OR_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] | dst4[j];
break;
case PIPE_LOGICOP_COPY:
for (j = 0; j < 4; j++)
res4[j] = src4[j];
break;
case PIPE_LOGICOP_OR_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | ~dst4[j];
break;
case PIPE_LOGICOP_OR:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | dst4[j];
break;
case PIPE_LOGICOP_SET:
for (j = 0; j < 4; j++)
res4[j] = ~0;
break;
default:
assert(0);
}
for (j = 0; j < 4; j++) {
quadColor[j][0] = ubyte_to_float(res[j][0]);
quadColor[j][1] = ubyte_to_float(res[j][1]);
quadColor[j][2] = ubyte_to_float(res[j][2]);
quadColor[j][3] = ubyte_to_float(res[j][3]);
}
}
/* pass quad to next stage */
qs->next->run(qs->next, quad);
}
static void
blend_quad(struct quad_stage *qs, struct quad_header *quad)
{
static const float zero[4] = { 0, 0, 0, 0 };
static const float one[4] = { 1, 1, 1, 1 };
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
uint cbuf;
if (llvmpipe->blend->logicop_enable) {
logicop_quad(qs, quad);
return;
}
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
float source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
struct llvmpipe_cached_tile *tile
= lp_get_cached_tile(llvmpipe,
llvmpipe->cbuf_cache[cbuf],
quad->input.x0, quad->input.y0);
float (*quadColor)[4] = quad->output.color[cbuf];
uint i, j;
/* get/swizzle dest colors */
for (j = 0; j < QUAD_SIZE; j++) {
int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
/*
* Compute src/first term RGB
*/
switch (llvmpipe->blend->rgb_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[0], quadColor[0]); /* R */
VEC4_COPY(source[1], quadColor[1]); /* G */
VEC4_COPY(source[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
{
const float *alpha = dest[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(source[0], quadColor[0], temp); /* R */
VEC4_MUL(source[1], quadColor[1], temp); /* G */
VEC4_MUL(source[2], quadColor[2], temp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, llvmpipe->blend_color.color[0]); /* R */
VEC4_MUL(source[0], quadColor[0], comp); /* R */
VEC4_SCALAR(comp, llvmpipe->blend_color.color[1]); /* G */
VEC4_MUL(source[1], quadColor[1], comp); /* G */
VEC4_SCALAR(comp, llvmpipe->blend_color.color[2]); /* B */
VEC4_MUL(source[2], quadColor[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float alpha[4];
VEC4_SCALAR(alpha, llvmpipe->blend_color.color[3]);
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
assert(0); /* to do */
break;
case PIPE_BLENDFACTOR_SRC1_ALPHA:
assert(0); /* to do */
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[0], zero); /* R */
VEC4_COPY(source[1], zero); /* G */
VEC4_COPY(source[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, dest[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, dest[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[0]);
VEC4_MUL(source[0], quadColor[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[1]);
VEC4_MUL(source[1], quadColor[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[2]);
VEC4_MUL(source[2], quadColor[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_alpha[4];
VEC4_SCALAR(inv_alpha, 1.0f - llvmpipe->blend_color.color[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
assert(0); /* to do */
break;
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
assert(0); /* to do */
break;
default:
assert(0);
}
/*
* Compute src/first term A
*/
switch (llvmpipe->blend->alpha_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* multiply alpha by 1.0 */
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, llvmpipe->blend_color.color[3]); /* A */
VEC4_MUL(source[3], quadColor[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
/* A */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[3]);
VEC4_MUL(source[3], quadColor[3], inv_comp);
}
break;
default:
assert(0);
}
/*
* Compute dest/second term RGB
*/
switch (llvmpipe->blend->rgb_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* dest = dest * 1 NO-OP, leave dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
assert(0); /* illegal */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, llvmpipe->blend_color.color[0]); /* R */
VEC4_MUL(dest[0], dest[0], comp); /* R */
VEC4_SCALAR(comp, llvmpipe->blend_color.color[1]); /* G */
VEC4_MUL(dest[1], dest[1], comp); /* G */
VEC4_SCALAR(comp, llvmpipe->blend_color.color[2]); /* B */
VEC4_MUL(dest[2], dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, llvmpipe->blend_color.color[3]); /* A */
VEC4_MUL(dest[0], dest[0], comp); /* R */
VEC4_MUL(dest[1], dest[1], comp); /* G */
VEC4_MUL(dest[2], dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(dest[0], zero); /* R */
VEC4_COPY(dest[1], zero); /* G */
VEC4_COPY(dest[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
case PIPE_BLENDFACTOR_SRC1_ALPHA:
/* XXX what are these? */
assert(0);
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[0], inv_comp, dest[0]); /* R */
VEC4_MUL(dest[1], inv_comp, dest[1]); /* G */
VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[0]); /* R */
VEC4_MUL(dest[0], dest[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, dest[1]); /* G */
VEC4_MUL(dest[1], dest[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, dest[2]); /* B */
VEC4_MUL(dest[2], dest[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[0]);
VEC4_MUL(dest[0], dest[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[1]);
VEC4_MUL(dest[1], dest[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[2]);
VEC4_MUL(dest[2], dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[3]);
VEC4_MUL(dest[0], dest[0], inv_comp);
VEC4_MUL(dest[1], dest[1], inv_comp);
VEC4_MUL(dest[2], dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
/* XXX what are these? */
assert(0);
break;
default:
assert(0);
}
/*
* Compute dest/second term A
*/
switch (llvmpipe->blend->alpha_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* dest = dest * 1 NO-OP, leave dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
assert(0); /* illegal */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, llvmpipe->blend_color.color[3]); /* A */
VEC4_MUL(dest[3], dest[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(dest[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[3]); /* A */
VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - llvmpipe->blend_color.color[3]);
VEC4_MUL(dest[3], dest[3], inv_comp);
}
break;
default:
assert(0);
}
/*
* Combine RGB terms
*/
switch (llvmpipe->blend->rgb_func) {
case PIPE_BLEND_ADD:
VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */
VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */
VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */
VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */
VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
break;
default:
assert(0);
}
/*
* Combine A terms
*/
switch (llvmpipe->blend->alpha_func) {
case PIPE_BLEND_ADD:
VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
break;
default:
assert(0);
}
} /* cbuf loop */
/* pass blended quad to next stage */
qs->next->run(qs->next, quad);
}
static void blend_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void blend_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_blend_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = blend_begin;
stage->run = blend_quad;
stage->destroy = blend_destroy;
return stage;
}

View file

@ -0,0 +1,74 @@
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_quad_pipe.h"
/**
* Loop over colorbuffers, passing quad to next stage each time.
*/
static void
cbuf_loop_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
float tmp[PIPE_MAX_COLOR_BUFS][4][QUAD_SIZE];
unsigned i;
assert(sizeof(quad->outputs.color) == sizeof(tmp));
assert(llvmpipe->framebuffer.nr_cbufs <= PIPE_MAX_COLOR_BUFS);
/* make copy of original colors since they can get modified
* by blending and masking.
* XXX we won't have to do this if the fragment program actually emits
* N separate colors and we're drawing to N color buffers (MRT).
* But if we emitted one color and glDrawBuffer(GL_FRONT_AND_BACK) is
* in effect, we need to save/restore colors like this.
*/
memcpy(tmp, quad->outputs.color, sizeof(tmp));
for (i = 0; i < llvmpipe->framebuffer.nr_cbufs; i++) {
/* set current cbuffer */
#if 0 /* obsolete & going away */
llvmpipe->current_cbuf = i;
#endif
/* pass blended quad to next stage */
qs->next->run(qs->next, quad);
/* restore quad's colors for next buffer */
memcpy(quad->outputs.color, tmp, sizeof(tmp));
}
}
static void cbuf_loop_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void cbuf_loop_destroy(struct quad_stage *qs)
{
FREE( qs );
}
/**
* Create the colorbuffer loop stage.
* This is used to implement multiple render targets and GL_FRONT_AND_BACK
* rendering.
*/
struct quad_stage *lp_quad_bufloop_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = cbuf_loop_begin;
stage->run = cbuf_loop_quad;
stage->destroy = cbuf_loop_destroy;
return stage;
}

View file

@ -0,0 +1,116 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* \brief quad colormask stage
* \author Brian Paul
*/
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_quad_pipe.h"
#include "lp_tile_cache.h"
/**
* XXX colormask could be rolled into blending...
*/
static void
colormask_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
uint cbuf;
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
float dest[4][QUAD_SIZE];
struct llvmpipe_cached_tile *tile
= lp_get_cached_tile(llvmpipe,
llvmpipe->cbuf_cache[cbuf],
quad->input.x0, quad->input.y0);
float (*quadColor)[4] = quad->output.color[cbuf];
uint i, j;
/* get/swizzle dest colors */
for (j = 0; j < QUAD_SIZE; j++) {
int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
/* R */
if (!(llvmpipe->blend->colormask & PIPE_MASK_R))
COPY_4V(quadColor[0], dest[0]);
/* G */
if (!(llvmpipe->blend->colormask & PIPE_MASK_G))
COPY_4V(quadColor[1], dest[1]);
/* B */
if (!(llvmpipe->blend->colormask & PIPE_MASK_B))
COPY_4V(quadColor[2], dest[2]);
/* A */
if (!(llvmpipe->blend->colormask & PIPE_MASK_A))
COPY_4V(quadColor[3], dest[3]);
}
/* pass quad to next stage */
qs->next->run(qs->next, quad);
}
static void colormask_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void colormask_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_colormask_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = colormask_begin;
stage->run = colormask_quad;
stage->destroy = colormask_destroy;
return stage;
}

View file

@ -0,0 +1,94 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* \brief Apply AA coverage to quad alpha valus
* \author Brian Paul
*/
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_quad_pipe.h"
/**
* Multiply quad's alpha values by the fragment coverage.
*/
static void
coverage_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
const uint prim = quad->input.prim;
if ((llvmpipe->rasterizer->poly_smooth && prim == QUAD_PRIM_TRI) ||
(llvmpipe->rasterizer->line_smooth && prim == QUAD_PRIM_LINE) ||
(llvmpipe->rasterizer->point_smooth && prim == QUAD_PRIM_POINT)) {
uint cbuf;
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
float (*quadColor)[4] = quad->output.color[cbuf];
unsigned j;
for (j = 0; j < QUAD_SIZE; j++) {
assert(quad->input.coverage[j] >= 0.0);
assert(quad->input.coverage[j] <= 1.0);
quadColor[3][j] *= quad->input.coverage[j];
}
}
}
qs->next->run(qs->next, quad);
}
static void coverage_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void coverage_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_coverage_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = coverage_begin;
stage->run = coverage_quad;
stage->destroy = coverage_destroy;
return stage;
}

View file

@ -0,0 +1,290 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* \brief Quad depth testing
*/
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_quad_pipe.h"
#include "lp_tile_cache.h"
/**
* Do depth testing for a quad.
* Not static since it's used by the stencil code.
*/
/*
* To increase efficiency, we should probably have multiple versions
* of this function that are specifically for Z16, Z32 and FP Z buffers.
* Try to effectively do that with codegen...
*/
void
lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
const enum pipe_format format = ps->format;
unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */
unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */
unsigned zmask = 0;
unsigned j;
struct llvmpipe_cached_tile *tile
= lp_get_cached_tile(llvmpipe, llvmpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
assert(ps); /* shouldn't get here if there's no zbuffer */
/*
* Convert quad's float depth values to int depth values (qzzzz).
* If the Z buffer stores integer values, we _have_ to do the depth
* compares with integers (not floats). Otherwise, the float->int->float
* conversion of Z values (which isn't an identity function) will cause
* Z-fighting errors.
*
* Also, get the zbuffer values (bzzzz) from the cached tile.
*/
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
{
float scale = 65535.0;
for (j = 0; j < QUAD_SIZE; j++) {
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
bzzzz[j] = tile->data.depth16[y][x];
}
}
break;
case PIPE_FORMAT_Z32_UNORM:
{
double scale = (double) (uint) ~0UL;
for (j = 0; j < QUAD_SIZE; j++) {
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
bzzzz[j] = tile->data.depth32[y][x];
}
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
/* fall-through */
case PIPE_FORMAT_S8Z24_UNORM:
{
float scale = (float) ((1 << 24) - 1);
for (j = 0; j < QUAD_SIZE; j++) {
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
}
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
/* fall-through */
case PIPE_FORMAT_Z24S8_UNORM:
{
float scale = (float) ((1 << 24) - 1);
for (j = 0; j < QUAD_SIZE; j++) {
qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
bzzzz[j] = tile->data.depth32[y][x] >> 8;
}
}
break;
default:
assert(0);
}
switch (llvmpipe->depth_stencil->depth.func) {
case PIPE_FUNC_NEVER:
/* zmask = 0 */
break;
case PIPE_FUNC_LESS:
/* Note this is pretty much a single sse or cell instruction.
* Like this: quad->mask &= (quad->outputs.depth < zzzz);
*/
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] < bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] == bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] <= bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] > bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] != bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (qzzzz[j] >= bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_ALWAYS:
zmask = MASK_ALL;
break;
default:
assert(0);
}
quad->inout.mask &= zmask;
if (llvmpipe->depth_stencil->depth.writemask) {
/* This is also efficient with sse / spe instructions:
*/
for (j = 0; j < QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
bzzzz[j] = qzzzz[j];
}
}
/* put updated Z values back into cached tile */
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth16[y][x] = (ushort) bzzzz[j];
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
/* fall-through */
/* (yes, this falls through to a different case than above) */
case PIPE_FORMAT_Z32_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = bzzzz[j];
}
break;
case PIPE_FORMAT_S8Z24_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
uint s8z24 = tile->data.depth32[y][x];
s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
tile->data.depth32[y][x] = s8z24;
}
break;
case PIPE_FORMAT_Z24S8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
uint z24s8 = tile->data.depth32[y][x];
z24s8 = (z24s8 & 0xff) | (bzzzz[j] << 8);
tile->data.depth32[y][x] = z24s8;
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = bzzzz[j] << 8;
}
break;
default:
assert(0);
}
}
}
static void
depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
{
lp_depth_test_quad(qs, quad);
if (quad->inout.mask)
qs->next->run(qs->next, quad);
}
static void depth_test_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void depth_test_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_depth_test_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = depth_test_begin;
stage->run = depth_test_quad;
stage->destroy = depth_test_destroy;
return stage;
}

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.
*
**************************************************************************/
/**
* \brief Quad early-z testing
*/
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "lp_quad.h"
#include "lp_quad_pipe.h"
/**
* All this stage does is compute the quad's Z values (which is normally
* done by the shading stage).
* The next stage will do the actual depth test.
*/
static void
earlyz_quad(
struct quad_stage *qs,
struct quad_header *quad )
{
const float fx = (float) quad->input.x0;
const float fy = (float) quad->input.y0;
const float dzdx = quad->posCoef->dadx[2];
const float dzdy = quad->posCoef->dady[2];
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
quad->output.depth[0] = z0;
quad->output.depth[1] = z0 + dzdx;
quad->output.depth[2] = z0 + dzdy;
quad->output.depth[3] = z0 + dzdx + dzdy;
qs->next->run( qs->next, quad );
}
static void
earlyz_begin(
struct quad_stage *qs )
{
qs->next->begin( qs->next );
}
static void
earlyz_destroy(
struct quad_stage *qs )
{
FREE( qs );
}
struct quad_stage *
lp_quad_earlyz_stage(
struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT( quad_stage );
stage->llvmpipe = llvmpipe;
stage->begin = earlyz_begin;
stage->run = earlyz_quad;
stage->destroy = earlyz_destroy;
return stage;
}

View file

@ -0,0 +1,192 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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 "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "lp_context.h"
#include "lp_state.h"
#include "lp_quad.h"
#include "lp_quad_pipe.h"
#include "lp_texture.h"
#include "lp_tex_sample.h"
struct quad_shade_stage
{
struct quad_stage stage; /**< base class */
struct tgsi_exec_machine *machine;
struct tgsi_exec_vector *inputs, *outputs;
};
/** 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 llvmpipe_context *llvmpipe = qs->llvmpipe;
struct tgsi_exec_machine *machine = qss->machine;
boolean z_written;
/* Consts do not require 16 byte alignment. */
machine->Consts = llvmpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
machine->InterpCoefs = quad->coef;
/* run shader */
quad->inout.mask &= llvmpipe->fs->run( llvmpipe->fs, machine, quad );
/* store outputs */
z_written = FALSE;
{
const ubyte *sem_name = llvmpipe->fs->info.output_semantic_name;
const ubyte *sem_index = llvmpipe->fs->info.output_semantic_index;
const uint n = qss->stage.llvmpipe->fs->info.num_outputs;
uint i;
for (i = 0; i < n; i++) {
switch (sem_name[i]) {
case TGSI_SEMANTIC_COLOR:
{
uint cbuf = sem_index[i];
memcpy(quad->output.color[cbuf],
&machine->Outputs[i].xyzw[0].f[0],
sizeof(quad->output.color[0]) );
}
break;
case TGSI_SEMANTIC_POSITION:
{
uint j;
for (j = 0; j < 4; j++) {
quad->output.depth[j] = machine->Outputs[0].xyzw[2].f[j];
}
z_written = TRUE;
}
break;
}
}
}
if (!z_written) {
/* compute Z values now, as in the quad earlyz stage */
/* XXX we should really only do this if the earlyz stage is not used */
const float fx = (float) quad->input.x0;
const float fy = (float) quad->input.y0;
const float dzdx = quad->posCoef->dadx[2];
const float dzdy = quad->posCoef->dady[2];
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
quad->output.depth[0] = z0;
quad->output.depth[1] = z0 + dzdx;
quad->output.depth[2] = z0 + dzdy;
quad->output.depth[3] = z0 + dzdx + dzdy;
}
/* shader may cull fragments */
if (quad->inout.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 llvmpipe_context *llvmpipe = qs->llvmpipe;
llvmpipe->fs->prepare( llvmpipe->fs,
qss->machine,
(struct tgsi_sampler **)
llvmpipe->tgsi.frag_samplers_list );
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_destroy(qss->machine);
FREE( qs );
}
struct quad_stage *
lp_quad_shade_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
if (!qss)
goto fail;
qss->stage.llvmpipe = llvmpipe;
qss->stage.begin = shade_begin;
qss->stage.run = shade_quad;
qss->stage.destroy = shade_destroy;
qss->machine = tgsi_exec_machine_create();
if (!qss->machine)
goto fail;
return &qss->stage;
fail:
if (qss && qss->machine)
tgsi_exec_machine_destroy(qss->machine);
FREE(qss);
return NULL;
}

View file

@ -0,0 +1,85 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* \brief Quad occlusion counter stage
* \author Brian Paul
*/
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_quad_pipe.h"
static unsigned count_bits( unsigned val )
{
unsigned i;
for (i = 0; val ; val >>= 1)
i += (val & 1);
return i;
}
static void
occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
llvmpipe->occlusion_count += count_bits(quad->inout.mask);
qs->next->run(qs->next, quad);
}
static void occlusion_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void occlusion_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_occlusion_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = occlusion_begin;
stage->run = occlusion_count_quad;
stage->destroy = occlusion_destroy;
return stage;
}

View file

@ -0,0 +1,103 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_quad_pipe.h"
#include "lp_tile_cache.h"
/**
* Last step of quad processing: write quad colors to the framebuffer,
* taking mask into account.
*/
static void
output_quad(struct quad_stage *qs, struct quad_header *quad)
{
/* in-tile pos: */
const int itx = quad->input.x0 % TILE_SIZE;
const int ity = quad->input.y0 % TILE_SIZE;
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
uint cbuf;
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < llvmpipe->framebuffer.nr_cbufs; cbuf++) {
struct llvmpipe_cached_tile *tile
= lp_get_cached_tile(llvmpipe,
llvmpipe->cbuf_cache[cbuf],
quad->input.x0, quad->input.y0);
float (*quadColor)[4] = quad->output.color[cbuf];
int i, j;
/* get/swizzle dest colors */
for (j = 0; j < QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
if (0) {
debug_printf("lp write pixel %d,%d: %g, %g, %g\n",
quad->input.x0 + x,
quad->input.y0 + y,
quadColor[0][j],
quadColor[1][j],
quadColor[2][j]);
}
}
}
}
}
static void output_begin(struct quad_stage *qs)
{
assert(qs->next == NULL);
}
static void output_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_output_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = output_begin;
stage->run = output_quad;
stage->destroy = output_destroy;
return stage;
}

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.
*
**************************************************************************/
#include "lp_context.h"
#include "lp_state.h"
#include "pipe/p_shader_tokens.h"
static void
lp_push_quad_first(
struct llvmpipe_context *lp,
struct quad_stage *quad,
uint i )
{
quad->next = lp->quad[i].first;
lp->quad[i].first = quad;
}
static void
lp_build_depth_stencil(
struct llvmpipe_context *lp,
uint i )
{
if (lp->depth_stencil->stencil[0].enabled ||
lp->depth_stencil->stencil[1].enabled) {
lp_push_quad_first( lp, lp->quad[i].stencil_test, i );
}
else if (lp->depth_stencil->depth.enabled &&
lp->framebuffer.zsbuf) {
lp_push_quad_first( lp, lp->quad[i].depth_test, i );
}
}
void
lp_build_quad_pipeline(struct llvmpipe_context *lp)
{
uint i;
boolean early_depth_test =
lp->depth_stencil->depth.enabled &&
lp->framebuffer.zsbuf &&
!lp->depth_stencil->alpha.enabled &&
!lp->fs->info.uses_kill &&
!lp->fs->info.writes_z;
/* build up the pipeline in reverse order... */
for (i = 0; i < SP_NUM_QUAD_THREADS; i++) {
lp->quad[i].first = lp->quad[i].output;
if (lp->blend->colormask != 0xf) {
lp_push_quad_first( lp, lp->quad[i].colormask, i );
}
if (lp->blend->blend_enable ||
lp->blend->logicop_enable) {
lp_push_quad_first( lp, lp->quad[i].blend, i );
}
if (lp->active_query_count) {
lp_push_quad_first( lp, lp->quad[i].occlusion, i );
}
if (lp->rasterizer->poly_smooth ||
lp->rasterizer->line_smooth ||
lp->rasterizer->point_smooth) {
lp_push_quad_first( lp, lp->quad[i].coverage, i );
}
if (!early_depth_test) {
lp_build_depth_stencil( lp, i );
}
if (lp->depth_stencil->alpha.enabled) {
lp_push_quad_first( lp, lp->quad[i].alpha_test, i );
}
/* XXX always enable shader? */
if (1) {
lp_push_quad_first( lp, lp->quad[i].shade, i );
}
if (early_depth_test) {
lp_build_depth_stencil( lp, i );
lp_push_quad_first( lp, lp->quad[i].earlyz, i );
}
#if !USE_DRAW_STAGE_PSTIPPLE
if (lp->rasterizer->poly_stipple_enable) {
lp_push_quad_first( lp, lp->quad[i].polygon_stipple, i );
}
#endif
}
}

View file

@ -0,0 +1,74 @@
/**************************************************************************
*
* 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_QUAD_PIPE_H
#define SP_QUAD_PIPE_H
struct llvmpipe_context;
struct quad_header;
/**
* Fragment processing is performed on 2x2 blocks of pixels called "quads".
* Quad processing is performed with a pipeline of stages represented by
* this type.
*/
struct quad_stage {
struct llvmpipe_context *llvmpipe;
struct quad_stage *next;
void (*begin)(struct quad_stage *qs);
/** the stage action */
void (*run)(struct quad_stage *qs, struct quad_header *quad);
void (*destroy)(struct quad_stage *qs);
};
struct quad_stage *lp_quad_polygon_stipple_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_earlyz_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_shade_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_alpha_test_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_stencil_test_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_depth_test_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_occlusion_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_coverage_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_blend_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_colormask_stage( struct llvmpipe_context *llvmpipe );
struct quad_stage *lp_quad_output_stage( struct llvmpipe_context *llvmpipe );
void lp_build_quad_pipeline(struct llvmpipe_context *lp);
void lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
#endif /* SP_QUAD_PIPE_H */

View file

@ -0,0 +1,352 @@
/**
* \brief Quad stencil testing
*/
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_surface.h"
#include "lp_tile_cache.h"
#include "lp_quad_pipe.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
/** Only 8-bit stencil supported */
#define STENCIL_MAX 0xff
/**
* Do the basic stencil test (compare stencil buffer values against the
* reference value.
*
* \param stencilVals the stencil values from the stencil buffer
* \param func the stencil func (PIPE_FUNC_x)
* \param ref the stencil reference value
* \param valMask the stencil value mask indicating which bits of the stencil
* values and ref value are to be used.
* \return mask indicating which pixels passed the stencil test
*/
static unsigned
do_stencil_test(const ubyte stencilVals[QUAD_SIZE], unsigned func,
unsigned ref, unsigned valMask)
{
unsigned passMask = 0x0;
unsigned j;
ref &= valMask;
switch (func) {
case PIPE_FUNC_NEVER:
/* passMask = 0x0 */
break;
case PIPE_FUNC_LESS:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref < (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref == (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref <= (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref > (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref != (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < QUAD_SIZE; j++) {
if (ref >= (stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_ALWAYS:
passMask = MASK_ALL;
break;
default:
assert(0);
}
return passMask;
}
/**
* Apply the stencil operator to stencil values.
*
* \param stencilVals the stencil buffer values (read and written)
* \param mask indicates which pixels to update
* \param op the stencil operator (PIPE_STENCIL_OP_x)
* \param ref the stencil reference value
* \param wrtMask writemask controlling which bits are changed in the
* stencil values
*/
static void
apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
{
unsigned j;
ubyte newstencil[QUAD_SIZE];
for (j = 0; j < QUAD_SIZE; j++) {
newstencil[j] = stencilVals[j];
}
switch (op) {
case PIPE_STENCIL_OP_KEEP:
/* no-op */
break;
case PIPE_STENCIL_OP_ZERO:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = 0;
}
}
break;
case PIPE_STENCIL_OP_REPLACE:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = ref;
}
}
break;
case PIPE_STENCIL_OP_INCR:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (stencilVals[j] < STENCIL_MAX) {
newstencil[j] = stencilVals[j] + 1;
}
}
}
break;
case PIPE_STENCIL_OP_DECR:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (stencilVals[j] > 0) {
newstencil[j] = stencilVals[j] - 1;
}
}
}
break;
case PIPE_STENCIL_OP_INCR_WRAP:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = stencilVals[j] + 1;
}
}
break;
case PIPE_STENCIL_OP_DECR_WRAP:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = stencilVals[j] - 1;
}
}
break;
case PIPE_STENCIL_OP_INVERT:
for (j = 0; j < QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = ~stencilVals[j];
}
}
break;
default:
assert(0);
}
/*
* update the stencil values
*/
if (wrtMask != STENCIL_MAX) {
/* apply bit-wise stencil buffer writemask */
for (j = 0; j < QUAD_SIZE; j++) {
stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
}
}
else {
for (j = 0; j < QUAD_SIZE; j++) {
stencilVals[j] = newstencil[j];
}
}
}
/**
* Do stencil (and depth) testing. Stenciling depends on the outcome of
* depth testing.
*/
static void
stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
unsigned func, zFailOp, zPassOp, failOp;
ubyte ref, wrtMask, valMask;
ubyte stencilVals[QUAD_SIZE];
struct llvmpipe_cached_tile *tile
= lp_get_cached_tile(llvmpipe, llvmpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
uint j;
uint face = quad->input.facing;
if (!llvmpipe->depth_stencil->stencil[1].enabled) {
/* single-sided stencil test, use front (face=0) state */
face = 0;
}
/* choose front or back face function, operator, etc */
/* XXX we could do these initializations once per primitive */
func = llvmpipe->depth_stencil->stencil[face].func;
failOp = llvmpipe->depth_stencil->stencil[face].fail_op;
zFailOp = llvmpipe->depth_stencil->stencil[face].zfail_op;
zPassOp = llvmpipe->depth_stencil->stencil[face].zpass_op;
ref = llvmpipe->depth_stencil->stencil[face].ref_value;
wrtMask = llvmpipe->depth_stencil->stencil[face].writemask;
valMask = llvmpipe->depth_stencil->stencil[face].valuemask;
assert(ps); /* shouldn't get here if there's no stencil buffer */
/* get stencil values from cached tile */
switch (ps->format) {
case PIPE_FORMAT_S8Z24_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
stencilVals[j] = tile->data.depth32[y][x] >> 24;
}
break;
case PIPE_FORMAT_Z24S8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
stencilVals[j] = tile->data.depth32[y][x] & 0xff;
}
break;
case PIPE_FORMAT_S8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
stencilVals[j] = tile->data.stencil8[y][x];
}
break;
default:
assert(0);
}
/* do the stencil test first */
{
unsigned passMask, failMask;
passMask = do_stencil_test(stencilVals, func, ref, valMask);
failMask = quad->inout.mask & ~passMask;
quad->inout.mask &= passMask;
if (failOp != PIPE_STENCIL_OP_KEEP) {
apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
}
}
if (quad->inout.mask) {
/* now the pixels that passed the stencil test are depth tested */
if (llvmpipe->depth_stencil->depth.enabled) {
const unsigned origMask = quad->inout.mask;
lp_depth_test_quad(qs, quad); /* quad->mask is updated */
/* update stencil buffer values according to z pass/fail result */
if (zFailOp != PIPE_STENCIL_OP_KEEP) {
const unsigned failMask = origMask & ~quad->inout.mask;
apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
}
if (zPassOp != PIPE_STENCIL_OP_KEEP) {
const unsigned passMask = origMask & quad->inout.mask;
apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
}
}
else {
/* no depth test, apply Zpass operator to stencil buffer values */
apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask);
}
}
/* put new stencil values into cached tile */
switch (ps->format) {
case PIPE_FORMAT_S8Z24_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
uint s8z24 = tile->data.depth32[y][x];
s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
tile->data.depth32[y][x] = s8z24;
}
break;
case PIPE_FORMAT_Z24S8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
uint z24s8 = tile->data.depth32[y][x];
z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
tile->data.depth32[y][x] = z24s8;
}
break;
case PIPE_FORMAT_S8_UNORM:
for (j = 0; j < QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.stencil8[y][x] = stencilVals[j];
}
break;
default:
assert(0);
}
if (quad->inout.mask)
qs->next->run(qs->next, quad);
}
static void stencil_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void stencil_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *lp_quad_stencil_test_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = stencil_begin;
stage->run = stencil_test_quad;
stage->destroy = stencil_destroy;
return stage;
}

View file

@ -0,0 +1,77 @@
/**
* quad polygon stipple stage
*/
#include "lp_context.h"
#include "lp_quad.h"
#include "lp_quad_pipe.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
/**
* Apply polygon stipple to quads produced by triangle rasterization
*/
static void
stipple_quad(struct quad_stage *qs, struct quad_header *quad)
{
static const uint bit31 = 1 << 31;
static const uint bit30 = 1 << 30;
if (quad->input.prim == QUAD_PRIM_TRI) {
struct llvmpipe_context *llvmpipe = qs->llvmpipe;
/* need to invert Y to index into OpenGL's stipple pattern */
const int col0 = quad->input.x0 % 32;
const int y0 = quad->input.y0;
const int y1 = y0 + 1;
const uint stipple0 = llvmpipe->poly_stipple.stipple[y0 % 32];
const uint stipple1 = llvmpipe->poly_stipple.stipple[y1 % 32];
/* turn off quad mask bits that fail the stipple test */
if ((stipple0 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_LEFT;
if ((stipple0 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_RIGHT;
if ((stipple1 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_LEFT;
if ((stipple1 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
if (!quad->inout.mask) {
/* all fragments failed stipple test, end of quad pipeline */
return;
}
}
qs->next->run(qs->next, quad);
}
static void stipple_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
static void stipple_destroy(struct quad_stage *qs)
{
FREE( qs );
}
struct quad_stage *
lp_quad_polygon_stipple_stage( struct llvmpipe_context *llvmpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
stage->llvmpipe = llvmpipe;
stage->begin = stipple_begin;
stage->run = stipple_quad;
stage->destroy = stipple_destroy;
return stage;
}

View file

@ -0,0 +1,111 @@
/**************************************************************************
*
* 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 "util/u_memory.h"
#include "lp_context.h"
#include "lp_query.h"
#include "lp_state.h"
struct llvmpipe_query {
uint64_t start;
uint64_t end;
};
static struct llvmpipe_query *llvmpipe_query( struct pipe_query *p )
{
return (struct llvmpipe_query *)p;
}
static struct pipe_query *
llvmpipe_create_query(struct pipe_context *pipe,
unsigned type)
{
assert(type == PIPE_QUERY_OCCLUSION_COUNTER);
return (struct pipe_query *)CALLOC_STRUCT( llvmpipe_query );
}
static void
llvmpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
FREE(q);
}
static void
llvmpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
struct llvmpipe_query *sq = llvmpipe_query(q);
sq->start = llvmpipe->occlusion_count;
llvmpipe->active_query_count++;
llvmpipe->dirty |= SP_NEW_QUERY;
}
static void
llvmpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe );
struct llvmpipe_query *sq = llvmpipe_query(q);
llvmpipe->active_query_count--;
sq->end = llvmpipe->occlusion_count;
llvmpipe->dirty |= SP_NEW_QUERY;
}
static boolean
llvmpipe_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
uint64_t *result )
{
struct llvmpipe_query *sq = llvmpipe_query(q);
*result = sq->end - sq->start;
return TRUE;
}
void llvmpipe_init_query_funcs(struct llvmpipe_context *llvmpipe )
{
llvmpipe->pipe.create_query = llvmpipe_create_query;
llvmpipe->pipe.destroy_query = llvmpipe_destroy_query;
llvmpipe->pipe.begin_query = llvmpipe_begin_query;
llvmpipe->pipe.end_query = llvmpipe_end_query;
llvmpipe->pipe.get_query_result = llvmpipe_get_query_result;
}

View file

@ -0,0 +1,39 @@
/**************************************************************************
*
* 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
*/
#ifndef SP_QUERY_H
#define SP_QUERY_H
struct llvmpipe_context;
extern void llvmpipe_init_query_funcs(struct llvmpipe_context * );
#endif /* SP_QUERY_H */

View file

@ -0,0 +1,190 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
#include "util/u_memory.h"
#include "util/u_simple_screen.h"
#include "pipe/internal/p_winsys_screen.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "lp_texture.h"
#include "lp_winsys.h"
#include "lp_screen.h"
static const char *
llvmpipe_get_vendor(struct pipe_screen *screen)
{
return "Tungsten Graphics, Inc.";
}
static const char *
llvmpipe_get_name(struct pipe_screen *screen)
{
return "llvmpipe";
}
static int
llvmpipe_get_param(struct pipe_screen *screen, int param)
{
switch (param) {
case PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS:
return PIPE_MAX_SAMPLERS;
case PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS:
return PIPE_MAX_SAMPLERS;
case PIPE_CAP_NPOT_TEXTURES:
return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
return 1;
case PIPE_CAP_GLSL:
return 1;
case PIPE_CAP_S3TC:
return 0;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 0;
case PIPE_CAP_POINT_SPRITE:
return 1;
case PIPE_CAP_MAX_RENDER_TARGETS:
return PIPE_MAX_COLOR_BUFS;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_REPEAT:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return 13; /* max 4Kx4K */
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return 8; /* max 128x128x128 */
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return 13; /* max 4Kx4K */
case PIPE_CAP_TGSI_CONT_SUPPORTED:
return 1;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
return 1;
default:
return 0;
}
}
static float
llvmpipe_get_paramf(struct pipe_screen *screen, int param)
{
switch (param) {
case PIPE_CAP_MAX_LINE_WIDTH:
/* fall-through */
case PIPE_CAP_MAX_LINE_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAP_MAX_POINT_WIDTH:
/* fall-through */
case PIPE_CAP_MAX_POINT_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAP_MAX_TEXTURE_ANISOTROPY:
return 16.0; /* not actually signficant at this time */
case PIPE_CAP_MAX_TEXTURE_LOD_BIAS:
return 16.0; /* arbitrary */
default:
return 0;
}
}
/**
* Query format support for creating a texture, drawing surface, etc.
* \param format the format to test
* \param type one of PIPE_TEXTURE, PIPE_SURFACE
*/
static boolean
llvmpipe_is_format_supported( struct pipe_screen *screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned tex_usage,
unsigned geom_flags )
{
assert(target == PIPE_TEXTURE_1D ||
target == PIPE_TEXTURE_2D ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE);
switch(format) {
case PIPE_FORMAT_DXT1_RGB:
case PIPE_FORMAT_DXT1_RGBA:
case PIPE_FORMAT_DXT3_RGBA:
case PIPE_FORMAT_DXT5_RGBA:
return FALSE;
default:
return TRUE;
}
}
static void
llvmpipe_destroy_screen( struct pipe_screen *screen )
{
struct pipe_winsys *winsys = screen->winsys;
if(winsys->destroy)
winsys->destroy(winsys);
FREE(screen);
}
/**
* Create a new pipe_screen object
* Note: we're not presently subclassing pipe_screen (no llvmpipe_screen).
*/
struct pipe_screen *
llvmpipe_create_screen(struct pipe_winsys *winsys)
{
struct llvmpipe_screen *screen = CALLOC_STRUCT(llvmpipe_screen);
if (!screen)
return NULL;
screen->base.winsys = winsys;
screen->base.destroy = llvmpipe_destroy_screen;
screen->base.get_name = llvmpipe_get_name;
screen->base.get_vendor = llvmpipe_get_vendor;
screen->base.get_param = llvmpipe_get_param;
screen->base.get_paramf = llvmpipe_get_paramf;
screen->base.is_format_supported = llvmpipe_is_format_supported;
llvmpipe_init_screen_texture_funcs(&screen->base);
u_simple_screen_init(&screen->base);
return &screen->base;
}

View file

@ -0,0 +1,58 @@
/**************************************************************************
*
* 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_SCREEN_H
#define SP_SCREEN_H
#include "pipe/p_screen.h"
#include "pipe/p_defines.h"
struct llvmpipe_screen {
struct pipe_screen base;
/* Increments whenever textures are modified. Contexts can track
* this.
*/
unsigned timestamp;
};
static INLINE struct llvmpipe_screen *
llvmpipe_screen( struct pipe_screen *pipe )
{
return (struct llvmpipe_screen *)pipe;
}
#endif /* SP_SCREEN_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,53 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_SETUP_H
#define SP_SETUP_H
struct setup_context;
struct llvmpipe_context;
void
setup_tri( struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4] );
void
setup_line(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4]);
void
setup_point( struct setup_context *setup,
const float (*v0)[4] );
struct setup_context *setup_create_context( struct llvmpipe_context *llvmpipe );
void setup_prepare( struct setup_context *setup );
void setup_destroy_context( struct setup_context *setup );
#endif

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>
*/
#ifndef SP_STATE_H
#define SP_STATE_H
#include "pipe/p_state.h"
#include "tgsi/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;
struct vertex_info;
/**
* 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 lp_fragment_shader {
struct pipe_shader_state shader;
struct tgsi_shader_info info;
void (*prepare)( const struct lp_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 lp_fragment_shader *shader,
struct tgsi_exec_machine *machine,
struct quad_header *quad );
void (*delete)( struct lp_fragment_shader * );
};
/** Subclass of pipe_shader_state */
struct lp_vertex_shader {
struct pipe_shader_state shader;
struct draw_vertex_shader *draw_data;
};
void *
llvmpipe_create_blend_state(struct pipe_context *,
const struct pipe_blend_state *);
void llvmpipe_bind_blend_state(struct pipe_context *,
void *);
void llvmpipe_delete_blend_state(struct pipe_context *,
void *);
void *
llvmpipe_create_sampler_state(struct pipe_context *,
const struct pipe_sampler_state *);
void llvmpipe_bind_sampler_states(struct pipe_context *, unsigned, void **);
void llvmpipe_delete_sampler_state(struct pipe_context *, void *);
void *
llvmpipe_create_depth_stencil_state(struct pipe_context *,
const struct pipe_depth_stencil_alpha_state *);
void llvmpipe_bind_depth_stencil_state(struct pipe_context *, void *);
void llvmpipe_delete_depth_stencil_state(struct pipe_context *, void *);
void *
llvmpipe_create_rasterizer_state(struct pipe_context *,
const struct pipe_rasterizer_state *);
void llvmpipe_bind_rasterizer_state(struct pipe_context *, void *);
void llvmpipe_delete_rasterizer_state(struct pipe_context *, void *);
void llvmpipe_set_framebuffer_state( struct pipe_context *,
const struct pipe_framebuffer_state * );
void llvmpipe_set_blend_color( struct pipe_context *pipe,
const struct pipe_blend_color *blend_color );
void llvmpipe_set_clip_state( struct pipe_context *,
const struct pipe_clip_state * );
void llvmpipe_set_constant_buffer(struct pipe_context *,
uint shader, uint index,
const struct pipe_constant_buffer *buf);
void *llvmpipe_create_fs_state(struct pipe_context *,
const struct pipe_shader_state *);
void llvmpipe_bind_fs_state(struct pipe_context *, void *);
void llvmpipe_delete_fs_state(struct pipe_context *, void *);
void *llvmpipe_create_vs_state(struct pipe_context *,
const struct pipe_shader_state *);
void llvmpipe_bind_vs_state(struct pipe_context *, void *);
void llvmpipe_delete_vs_state(struct pipe_context *, void *);
void llvmpipe_set_polygon_stipple( struct pipe_context *,
const struct pipe_poly_stipple * );
void llvmpipe_set_scissor_state( struct pipe_context *,
const struct pipe_scissor_state * );
void llvmpipe_set_sampler_textures( struct pipe_context *,
unsigned num,
struct pipe_texture ** );
void llvmpipe_set_viewport_state( struct pipe_context *,
const struct pipe_viewport_state * );
void llvmpipe_set_vertex_elements(struct pipe_context *,
unsigned count,
const struct pipe_vertex_element *);
void llvmpipe_set_vertex_buffers(struct pipe_context *,
unsigned count,
const struct pipe_vertex_buffer *);
void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe );
boolean llvmpipe_draw_arrays(struct pipe_context *pipe, unsigned mode,
unsigned start, unsigned count);
boolean llvmpipe_draw_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned mode, unsigned start, unsigned count);
boolean
llvmpipe_draw_range_elements(struct pipe_context *pipe,
struct pipe_buffer *indexBuffer,
unsigned indexSize,
unsigned min_index,
unsigned max_index,
unsigned mode, unsigned start, unsigned count);
void
llvmpipe_set_edgeflags(struct pipe_context *pipe, const unsigned *edgeflags);
void
llvmpipe_map_transfers(struct llvmpipe_context *lp);
void
llvmpipe_unmap_transfers(struct llvmpipe_context *lp);
void
llvmpipe_map_texture_surfaces(struct llvmpipe_context *lp);
void
llvmpipe_unmap_texture_surfaces(struct llvmpipe_context *lp);
struct vertex_info *
llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe);
struct vertex_info *
llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe);
#endif

View file

@ -0,0 +1,98 @@
/**************************************************************************
*
* 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 "util/u_memory.h"
#include "lp_context.h"
#include "lp_state.h"
void *
llvmpipe_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *blend)
{
return mem_dup(blend, sizeof(*blend));
}
void llvmpipe_bind_blend_state( struct pipe_context *pipe,
void *blend )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->blend = (const struct pipe_blend_state *)blend;
llvmpipe->dirty |= SP_NEW_BLEND;
}
void llvmpipe_delete_blend_state(struct pipe_context *pipe,
void *blend)
{
FREE( blend );
}
void llvmpipe_set_blend_color( struct pipe_context *pipe,
const struct pipe_blend_color *blend_color )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->blend_color = *blend_color;
llvmpipe->dirty |= SP_NEW_BLEND;
}
/** XXX move someday? Or consolidate all these simple state setters
* into one file.
*/
void *
llvmpipe_create_depth_stencil_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *depth_stencil)
{
return mem_dup(depth_stencil, sizeof(*depth_stencil));
}
void
llvmpipe_bind_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->depth_stencil = (const struct pipe_depth_stencil_alpha_state *)depth_stencil;
llvmpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
}
void
llvmpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
{
FREE( depth );
}

View file

@ -0,0 +1,79 @@
/**************************************************************************
*
* 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 "lp_context.h"
#include "lp_state.h"
#include "draw/draw_context.h"
void llvmpipe_set_clip_state( struct pipe_context *pipe,
const struct pipe_clip_state *clip )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
/* pass the clip state to the draw module */
draw_set_clip_state(llvmpipe->draw, clip);
}
void llvmpipe_set_viewport_state( struct pipe_context *pipe,
const struct pipe_viewport_state *viewport )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
/* pass the viewport info to the draw module */
draw_set_viewport_state(llvmpipe->draw, viewport);
llvmpipe->viewport = *viewport; /* struct copy */
llvmpipe->dirty |= SP_NEW_VIEWPORT;
}
void llvmpipe_set_scissor_state( struct pipe_context *pipe,
const struct pipe_scissor_state *scissor )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
draw_flush(llvmpipe->draw);
llvmpipe->scissor = *scissor; /* struct copy */
llvmpipe->dirty |= SP_NEW_SCISSOR;
}
void llvmpipe_set_polygon_stipple( struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple )
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
draw_flush(llvmpipe->draw);
llvmpipe->poly_stipple = *stipple; /* struct copy */
llvmpipe->dirty |= SP_NEW_STIPPLE;
}

View file

@ -0,0 +1,211 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "draw/draw_private.h"
#include "lp_context.h"
#include "lp_state.h"
/**
* Mark the current vertex layout as "invalid".
* We'll validate the vertex layout later, when we start to actually
* render a point or line or tri.
*/
static void
invalidate_vertex_layout(struct llvmpipe_context *llvmpipe)
{
llvmpipe->vertex_info.num_attribs = 0;
}
/**
* The vertex info describes how to convert the post-transformed vertices
* (simple float[][4]) used by the 'draw' module into vertices for
* rasterization.
*
* This function validates the vertex layout and returns a pointer to a
* vertex_info object.
*/
struct vertex_info *
llvmpipe_get_vertex_info(struct llvmpipe_context *llvmpipe)
{
struct vertex_info *vinfo = &llvmpipe->vertex_info;
if (vinfo->num_attribs == 0) {
/* compute vertex layout now */
const struct lp_fragment_shader *lpfs = llvmpipe->fs;
const enum interp_mode colorInterp
= llvmpipe->rasterizer->flatshade ? INTERP_CONSTANT : INTERP_LINEAR;
uint i;
if (llvmpipe->vbuf) {
/* if using the post-transform vertex buffer, tell draw_vbuf to
* simply emit the whole post-xform vertex as-is:
*/
struct vertex_info *vinfo_vbuf = &llvmpipe->vertex_info_vbuf;
const uint num = draw_num_vs_outputs(llvmpipe->draw);
uint i;
/* No longer any need to try and emit draw vertex_header info.
*/
vinfo_vbuf->num_attribs = 0;
for (i = 0; i < num; i++) {
draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
}
draw_compute_vertex_size(vinfo_vbuf);
}
/*
* Loop over fragment shader inputs, searching for the matching output
* from the vertex shader.
*/
vinfo->num_attribs = 0;
for (i = 0; i < lpfs->info.num_inputs; i++) {
int src;
switch (lpfs->info.input_semantic_name[i]) {
case TGSI_SEMANTIC_POSITION:
src = draw_find_vs_output(llvmpipe->draw,
TGSI_SEMANTIC_POSITION, 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_POS, src);
break;
case TGSI_SEMANTIC_COLOR:
src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_COLOR,
lpfs->info.input_semantic_index[i]);
draw_emit_vertex_attr(vinfo, EMIT_4F, colorInterp, src);
break;
case TGSI_SEMANTIC_FOG:
src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_FOG, 0);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
break;
case TGSI_SEMANTIC_GENERIC:
case TGSI_SEMANTIC_FACE:
/* this includes texcoords and varying vars */
src = draw_find_vs_output(llvmpipe->draw, TGSI_SEMANTIC_GENERIC,
lpfs->info.input_semantic_index[i]);
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_PERSPECTIVE, src);
break;
default:
assert(0);
}
}
llvmpipe->psize_slot = draw_find_vs_output(llvmpipe->draw,
TGSI_SEMANTIC_PSIZE, 0);
if (llvmpipe->psize_slot > 0) {
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
llvmpipe->psize_slot);
}
draw_compute_vertex_size(vinfo);
}
return vinfo;
}
/**
* Called from vbuf module.
*
* Note that there's actually two different vertex layouts in llvmpipe.
*
* The normal one is computed in llvmpipe_get_vertex_info() above and is
* used by the point/line/tri "setup" code.
*
* The other one (this one) is only used by the vbuf module (which is
* not normally used by default but used in testing). For the vbuf module,
* we basically want to pass-through the draw module's vertex layout as-is.
* When the llvmpipe vbuf code begins drawing, the normal vertex layout
* will come into play again.
*/
struct vertex_info *
llvmpipe_get_vbuf_vertex_info(struct llvmpipe_context *llvmpipe)
{
(void) llvmpipe_get_vertex_info(llvmpipe);
return &llvmpipe->vertex_info_vbuf;
}
/**
* Recompute cliprect from scissor bounds, scissor enable and surface size.
*/
static void
compute_cliprect(struct llvmpipe_context *lp)
{
uint surfWidth = lp->framebuffer.width;
uint surfHeight = lp->framebuffer.height;
if (lp->rasterizer->scissor) {
/* clip to scissor rect */
lp->cliprect.minx = MAX2(lp->scissor.minx, 0);
lp->cliprect.miny = MAX2(lp->scissor.miny, 0);
lp->cliprect.maxx = MIN2(lp->scissor.maxx, surfWidth);
lp->cliprect.maxy = MIN2(lp->scissor.maxy, surfHeight);
}
else {
/* clip to surface bounds */
lp->cliprect.minx = 0;
lp->cliprect.miny = 0;
lp->cliprect.maxx = surfWidth;
lp->cliprect.maxy = surfHeight;
}
}
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
{
if (llvmpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS |
SP_NEW_VS))
invalidate_vertex_layout( llvmpipe );
if (llvmpipe->dirty & (SP_NEW_SCISSOR |
SP_NEW_DEPTH_STENCIL_ALPHA |
SP_NEW_FRAMEBUFFER))
compute_cliprect(llvmpipe);
if (llvmpipe->dirty & (SP_NEW_BLEND |
SP_NEW_DEPTH_STENCIL_ALPHA |
SP_NEW_FRAMEBUFFER |
SP_NEW_RASTERIZER |
SP_NEW_FS |
SP_NEW_QUERY))
lp_build_quad_pipeline(llvmpipe);
llvmpipe->dirty = 0;
}

View file

@ -0,0 +1,169 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_fs.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "pipe/internal/p_winsys_screen.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_parse.h"
void *
llvmpipe_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_fragment_shader *state;
/* debug */
if (llvmpipe->dump_fs)
tgsi_dump(templ->tokens, 0);
/* codegen */
state = llvmpipe_create_fs_llvm( llvmpipe, templ );
if (!state) {
state = llvmpipe_create_fs_sse( llvmpipe, templ );
if (!state) {
state = llvmpipe_create_fs_exec( llvmpipe, templ );
}
}
assert(state);
/* get/save the summary info for this shader */
tgsi_scan_shader(templ->tokens, &state->info);
return state;
}
void
llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->fs = (struct lp_fragment_shader *) fs;
llvmpipe->dirty |= SP_NEW_FS;
}
void
llvmpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct lp_fragment_shader *state = fs;
assert(fs != llvmpipe_context(pipe)->fs);
state->delete( state );
}
void *
llvmpipe_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_vertex_shader *state;
state = CALLOC_STRUCT(lp_vertex_shader);
if (state == NULL )
goto fail;
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
state->draw_data = draw_create_vertex_shader(llvmpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
return state;
fail:
if (state) {
FREE( (void *)state->shader.tokens );
FREE( state->draw_data );
FREE( state );
}
return NULL;
}
void
llvmpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->vs = (const struct lp_vertex_shader *)vs;
draw_bind_vertex_shader(llvmpipe->draw,
(llvmpipe->vs ? llvmpipe->vs->draw_data : NULL));
llvmpipe->dirty |= SP_NEW_VS;
}
void
llvmpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_vertex_shader *state =
(struct lp_vertex_shader *)vs;
draw_delete_vertex_shader(llvmpipe->draw, state->draw_data);
FREE( state );
}
void
llvmpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
const struct pipe_constant_buffer *buf)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
assert(shader < PIPE_SHADER_TYPES);
assert(index == 0);
/* note: reference counting */
pipe_buffer_reference(&llvmpipe->constants[shader].buffer,
buf ? buf->buffer : NULL);
llvmpipe->dirty |= SP_NEW_CONSTANTS;
}

View file

@ -0,0 +1,62 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_state.h"
#include "draw/draw_context.h"
void *
llvmpipe_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *rast)
{
return mem_dup(rast, sizeof(*rast));
}
void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe,
void *setup)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
/* pass-through to draw module */
draw_set_rasterizer_state(llvmpipe->draw, setup);
llvmpipe->rasterizer = (struct pipe_rasterizer_state *)setup;
llvmpipe->dirty |= SP_NEW_RASTERIZER;
}
void llvmpipe_delete_rasterizer_state(struct pipe_context *pipe,
void *rasterizer)
{
FREE( rasterizer );
}

View file

@ -0,0 +1,117 @@
/**************************************************************************
*
* 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:
* Brian Paul
*/
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "lp_context.h"
#include "lp_context.h"
#include "lp_state.h"
#include "lp_texture.h"
#include "lp_tile_cache.h"
#include "draw/draw_context.h"
void *
llvmpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
return mem_dup(sampler, sizeof(*sampler));
}
void
llvmpipe_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
unsigned i;
assert(num <= PIPE_MAX_SAMPLERS);
/* Check for no-op */
if (num == llvmpipe->num_samplers &&
!memcmp(llvmpipe->sampler, sampler, num * sizeof(void *)))
return;
draw_flush(llvmpipe->draw);
for (i = 0; i < num; ++i)
llvmpipe->sampler[i] = sampler[i];
for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
llvmpipe->sampler[i] = NULL;
llvmpipe->num_samplers = num;
llvmpipe->dirty |= SP_NEW_SAMPLER;
}
void
llvmpipe_set_sampler_textures(struct pipe_context *pipe,
unsigned num, struct pipe_texture **texture)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
uint i;
assert(num <= PIPE_MAX_SAMPLERS);
/* Check for no-op */
if (num == llvmpipe->num_textures &&
!memcmp(llvmpipe->texture, texture, num * sizeof(struct pipe_texture *)))
return;
draw_flush(llvmpipe->draw);
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
struct pipe_texture *tex = i < num ? texture[i] : NULL;
pipe_texture_reference(&llvmpipe->texture[i], tex);
lp_tile_cache_set_texture(pipe, llvmpipe->tex_cache[i], tex);
}
llvmpipe->num_textures = num;
llvmpipe->dirty |= SP_NEW_TEXTURE;
}
void
llvmpipe_delete_sampler_state(struct pipe_context *pipe,
void *sampler)
{
FREE( sampler );
}

View file

@ -0,0 +1,129 @@
/**************************************************************************
*
* 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 "lp_context.h"
#include "lp_state.h"
#include "lp_surface.h"
#include "lp_tile_cache.h"
#include "draw/draw_context.h"
/**
* XXX this might get moved someday
* Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
* Here, we flush the old surfaces and update the tile cache to point to the new
* surfaces.
*/
void
llvmpipe_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct llvmpipe_context *lp = llvmpipe_context(pipe);
uint i;
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
/* check if changing cbuf */
if (lp->framebuffer.cbufs[i] != fb->cbufs[i]) {
/* flush old */
lp_flush_tile_cache(lp, lp->cbuf_cache[i]);
/* assign new */
lp->framebuffer.cbufs[i] = fb->cbufs[i];
/* update cache */
lp_tile_cache_set_surface(lp->cbuf_cache[i], fb->cbufs[i]);
}
}
lp->framebuffer.nr_cbufs = fb->nr_cbufs;
/* zbuf changing? */
if (lp->framebuffer.zsbuf != fb->zsbuf) {
/* flush old */
lp_flush_tile_cache(lp, lp->zsbuf_cache);
/* assign new */
lp->framebuffer.zsbuf = fb->zsbuf;
/* update cache */
lp_tile_cache_set_surface(lp->zsbuf_cache, fb->zsbuf);
}
#if 0
/* XXX combined depth/stencil here */
/* sbuf changing? */
if (lp->framebuffer.sbuf != fb->sbuf) {
/* flush old */
lp_flush_tile_cache(lp, lp->sbuf_cache_sep);
/* assign new */
lp->framebuffer.sbuf = fb->sbuf;
/* update cache */
if (fb->sbuf != fb->zbuf) {
/* separate stencil buf */
lp->sbuf_cache = lp->sbuf_cache_sep;
lp_tile_cache_set_surface(lp->sbuf_cache, fb->sbuf);
}
else {
/* combined depth/stencil */
lp->sbuf_cache = lp->zbuf_cache;
lp_tile_cache_set_surface(lp->sbuf_cache, fb->sbuf);
}
}
#endif
/* Tell draw module how deep the Z/depth buffer is */
{
int depth_bits;
double mrd;
if (lp->framebuffer.zsbuf) {
depth_bits = pf_get_component_bits(lp->framebuffer.zsbuf->format,
PIPE_FORMAT_COMP_Z);
}
else {
depth_bits = 0;
}
if (depth_bits > 16) {
mrd = 0.0000001;
}
else {
mrd = 0.00002;
}
draw_set_mrd(lp->draw, mrd);
}
lp->framebuffer.width = fb->width;
lp->framebuffer.height = fb->height;
lp->dirty |= SP_NEW_FRAMEBUFFER;
}

View file

@ -0,0 +1,73 @@
/**************************************************************************
*
* 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 "lp_context.h"
#include "lp_state.h"
#include "lp_surface.h"
#include "draw/draw_context.h"
void
llvmpipe_set_vertex_elements(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *attribs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
assert(count <= PIPE_MAX_ATTRIBS);
memcpy(llvmpipe->vertex_element, attribs,
count * sizeof(struct pipe_vertex_element));
llvmpipe->num_vertex_elements = count;
llvmpipe->dirty |= SP_NEW_VERTEX;
draw_set_vertex_elements(llvmpipe->draw, count, attribs);
}
void
llvmpipe_set_vertex_buffers(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_buffer *buffers)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
assert(count <= PIPE_MAX_ATTRIBS);
memcpy(llvmpipe->vertex_buffer, buffers, count * sizeof(buffers[0]));
llvmpipe->num_vertex_buffers = count;
llvmpipe->dirty |= SP_NEW_VERTEX;
draw_set_vertex_buffers(llvmpipe->draw, count, buffers);
}

View file

@ -0,0 +1,50 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "util/u_rect.h"
#include "lp_context.h"
#include "lp_surface.h"
static void
lp_surface_copy(struct pipe_context *pipe,
struct pipe_surface *dest, unsigned destx, unsigned desty,
struct pipe_surface *src, unsigned srcx, unsigned srcy,
unsigned width, unsigned height)
{
util_surface_copy(pipe, FALSE,
dest, destx, desty,
src, srcx, srcy,
width, height);
}
void
lp_init_surface_functions(struct llvmpipe_context *lp)
{
lp->pipe.surface_copy = lp_surface_copy;
lp->pipe.surface_fill = util_surface_fill;
}

View file

@ -0,0 +1,42 @@
/**************************************************************************
*
* 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_SURFACE_H
#define SP_SURFACE_H
struct llvmpipe_context;
extern void
lp_init_surface_functions(struct llvmpipe_context *lp);
#endif /* SP_SURFACE_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,73 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_TEX_SAMPLE_H
#define SP_TEX_SAMPLE_H
#include "tgsi/tgsi_exec.h"
/**
* Subclass of tgsi_sampler
*/
struct lp_shader_sampler
{
struct tgsi_sampler base; /**< base class */
uint unit;
struct llvmpipe_context *lp;
struct llvmpipe_tile_cache *cache;
};
static INLINE const struct lp_shader_sampler *
lp_shader_sampler(const struct tgsi_sampler *sampler)
{
return (const struct lp_shader_sampler *) sampler;
}
extern void
lp_get_samples_fragment(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float lodbias,
float rgba[NUM_CHANNELS][QUAD_SIZE]);
extern void
lp_get_samples_vertex(struct tgsi_sampler *tgsi_sampler,
const float s[QUAD_SIZE],
const float t[QUAD_SIZE],
const float p[QUAD_SIZE],
float lodbias,
float rgba[NUM_CHANNELS][QUAD_SIZE]);
#endif /* SP_TEX_SAMPLE_H */

View file

@ -0,0 +1,421 @@
/**************************************************************************
*
* 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/internal/p_winsys_screen.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "lp_context.h"
#include "lp_state.h"
#include "lp_texture.h"
#include "lp_tile_cache.h"
#include "lp_screen.h"
#include "lp_winsys.h"
/* Simple, maximally packed layout.
*/
static unsigned minify( unsigned d )
{
return MAX2(1, d>>1);
}
/* Conventional allocation path for non-display textures:
*/
static boolean
llvmpipe_texture_layout(struct pipe_screen *screen,
struct llvmpipe_texture * lpt)
{
struct pipe_texture *pt = &lpt->base;
unsigned level;
unsigned width = pt->width[0];
unsigned height = pt->height[0];
unsigned depth = pt->depth[0];
unsigned buffer_size = 0;
for (level = 0; level <= pt->last_level; level++) {
pt->width[level] = width;
pt->height[level] = height;
pt->depth[level] = depth;
pt->nblocksx[level] = pf_get_nblocksx(&pt->block, width);
pt->nblocksy[level] = pf_get_nblocksy(&pt->block, height);
lpt->stride[level] = pt->nblocksx[level]*pt->block.size;
lpt->level_offset[level] = buffer_size;
buffer_size += (pt->nblocksy[level] *
((pt->target == PIPE_TEXTURE_CUBE) ? 6 : depth) *
lpt->stride[level]);
width = minify(width);
height = minify(height);
depth = minify(depth);
}
lpt->buffer = screen->buffer_create(screen, 32,
PIPE_BUFFER_USAGE_PIXEL,
buffer_size);
return lpt->buffer != NULL;
}
static boolean
llvmpipe_displaytarget_layout(struct pipe_screen *screen,
struct llvmpipe_texture * lpt)
{
unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE |
PIPE_BUFFER_USAGE_GPU_READ_WRITE);
lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
lpt->buffer = screen->surface_buffer_create( screen,
lpt->base.width[0],
lpt->base.height[0],
lpt->base.format,
usage,
&lpt->stride[0]);
return lpt->buffer != NULL;
}
static struct pipe_texture *
llvmpipe_texture_create(struct pipe_screen *screen,
const struct pipe_texture *templat)
{
struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
if (!lpt)
return NULL;
lpt->base = *templat;
pipe_reference_init(&lpt->base.reference, 1);
lpt->base.screen = screen;
if (lpt->base.tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if (!llvmpipe_displaytarget_layout(screen, lpt))
goto fail;
}
else {
if (!llvmpipe_texture_layout(screen, lpt))
goto fail;
}
return &lpt->base;
fail:
FREE(lpt);
return NULL;
}
static struct pipe_texture *
llvmpipe_texture_blanket(struct pipe_screen * screen,
const struct pipe_texture *base,
const unsigned *stride,
struct pipe_buffer *buffer)
{
struct llvmpipe_texture *lpt;
assert(screen);
/* Only supports one type */
if (base->target != PIPE_TEXTURE_2D ||
base->last_level != 0 ||
base->depth[0] != 1) {
return NULL;
}
lpt = CALLOC_STRUCT(llvmpipe_texture);
if (!lpt)
return NULL;
lpt->base = *base;
pipe_reference_init(&lpt->base.reference, 1);
lpt->base.screen = screen;
lpt->base.nblocksx[0] = pf_get_nblocksx(&lpt->base.block, lpt->base.width[0]);
lpt->base.nblocksy[0] = pf_get_nblocksy(&lpt->base.block, lpt->base.height[0]);
lpt->stride[0] = stride[0];
pipe_buffer_reference(&lpt->buffer, buffer);
return &lpt->base;
}
static void
llvmpipe_texture_destroy(struct pipe_texture *pt)
{
struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
pipe_buffer_reference(&lpt->buffer, NULL);
FREE(lpt);
}
static struct pipe_surface *
llvmpipe_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
unsigned face, unsigned level, unsigned zslice,
unsigned usage)
{
struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
struct pipe_surface *ps;
assert(level <= pt->last_level);
ps = CALLOC_STRUCT(pipe_surface);
if (ps) {
pipe_reference_init(&ps->reference, 1);
pipe_texture_reference(&ps->texture, pt);
ps->format = pt->format;
ps->width = pt->width[level];
ps->height = pt->height[level];
ps->offset = lpt->level_offset[level];
ps->usage = usage;
/* Because we are llvmpipe, anything that the state tracker
* thought was going to be done with the GPU will actually get
* done with the CPU. Let's adjust the flags to take that into
* account.
*/
if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) {
/* GPU_WRITE means "render" and that can involve reads (blending) */
ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ;
}
if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ)
ps->usage |= PIPE_BUFFER_USAGE_CPU_READ;
if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE |
PIPE_BUFFER_USAGE_GPU_WRITE)) {
/* Mark the surface as dirty. The tile cache will look for this. */
lpt->modified = TRUE;
}
ps->face = face;
ps->level = level;
ps->zslice = zslice;
if (pt->target == PIPE_TEXTURE_CUBE) {
ps->offset += face * pt->nblocksy[level] * lpt->stride[level];
}
else if (pt->target == PIPE_TEXTURE_3D) {
ps->offset += zslice * pt->nblocksy[level] * lpt->stride[level];
}
else {
assert(face == 0);
assert(zslice == 0);
}
}
return ps;
}
static void
llvmpipe_tex_surface_destroy(struct pipe_surface *surf)
{
/* Effectively do the texture_update work here - if texture images
* needed post-processing to put them into hardware layout, this is
* where it would happen. For llvmpipe, nothing to do.
*/
assert(surf->texture);
pipe_texture_reference(&surf->texture, NULL);
FREE(surf);
}
static struct pipe_transfer *
llvmpipe_get_tex_transfer(struct pipe_screen *screen,
struct pipe_texture *texture,
unsigned face, unsigned level, unsigned zslice,
enum pipe_transfer_usage usage,
unsigned x, unsigned y, unsigned w, unsigned h)
{
struct llvmpipe_texture *lptex = llvmpipe_texture(texture);
struct llvmpipe_transfer *lpt;
assert(texture);
assert(level <= texture->last_level);
lpt = CALLOC_STRUCT(llvmpipe_transfer);
if (lpt) {
struct pipe_transfer *pt = &lpt->base;
pipe_texture_reference(&pt->texture, texture);
pt->format = texture->format;
pt->block = texture->block;
pt->x = x;
pt->y = y;
pt->width = w;
pt->height = h;
pt->nblocksx = texture->nblocksx[level];
pt->nblocksy = texture->nblocksy[level];
pt->stride = lptex->stride[level];
pt->usage = usage;
pt->face = face;
pt->level = level;
pt->zslice = zslice;
lpt->offset = lptex->level_offset[level];
if (texture->target == PIPE_TEXTURE_CUBE) {
lpt->offset += face * pt->nblocksy * pt->stride;
}
else if (texture->target == PIPE_TEXTURE_3D) {
lpt->offset += zslice * pt->nblocksy * pt->stride;
}
else {
assert(face == 0);
assert(zslice == 0);
}
return pt;
}
return NULL;
}
static void
llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer)
{
/* Effectively do the texture_update work here - if texture images
* needed post-processing to put them into hardware layout, this is
* where it would happen. For llvmpipe, nothing to do.
*/
assert (transfer->texture);
pipe_texture_reference(&transfer->texture, NULL);
FREE(transfer);
}
static void *
llvmpipe_transfer_map( struct pipe_screen *screen,
struct pipe_transfer *transfer )
{
ubyte *map, *xfer_map;
struct llvmpipe_texture *lpt;
unsigned flags = 0;
assert(transfer->texture);
lpt = llvmpipe_texture(transfer->texture);
if (transfer->usage != PIPE_TRANSFER_READ) {
flags |= PIPE_BUFFER_USAGE_CPU_WRITE;
}
if (transfer->usage != PIPE_TRANSFER_WRITE) {
flags |= PIPE_BUFFER_USAGE_CPU_READ;
}
map = pipe_buffer_map(screen, lpt->buffer, flags);
if (map == NULL)
return NULL;
/* May want to different things here depending on read/write nature
* of the map:
*/
if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ)
{
/* Do something to notify sharing contexts of a texture change.
* In llvmpipe, that would mean flushing the texture cache.
*/
llvmpipe_screen(screen)->timestamp++;
}
xfer_map = map + llvmpipe_transfer(transfer)->offset +
transfer->y / transfer->block.height * transfer->stride +
transfer->x / transfer->block.width * transfer->block.size;
/*printf("map = %p xfer map = %p\n", map, xfer_map);*/
return xfer_map;
}
static void
llvmpipe_transfer_unmap(struct pipe_screen *screen,
struct pipe_transfer *transfer)
{
struct llvmpipe_texture *lpt;
assert(transfer->texture);
lpt = llvmpipe_texture(transfer->texture);
pipe_buffer_unmap( screen, lpt->buffer );
}
void
llvmpipe_init_texture_funcs(struct llvmpipe_context *lp)
{
}
void
llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = llvmpipe_texture_create;
screen->texture_blanket = llvmpipe_texture_blanket;
screen->texture_destroy = llvmpipe_texture_destroy;
screen->get_tex_surface = llvmpipe_get_tex_surface;
screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
screen->get_tex_transfer = llvmpipe_get_tex_transfer;
screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy;
screen->transfer_map = llvmpipe_transfer_map;
screen->transfer_unmap = llvmpipe_transfer_unmap;
}
boolean
llvmpipe_get_texture_buffer( struct pipe_texture *texture,
struct pipe_buffer **buf,
unsigned *stride )
{
struct llvmpipe_texture *tex = (struct llvmpipe_texture *)texture;
if (!tex)
return FALSE;
pipe_buffer_reference(buf, tex->buffer);
if (stride)
*stride = tex->stride[0];
return TRUE;
}

View file

@ -0,0 +1,83 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_TEXTURE_H
#define SP_TEXTURE_H
#include "pipe/p_state.h"
struct pipe_context;
struct pipe_screen;
struct llvmpipe_context;
struct llvmpipe_texture
{
struct pipe_texture base;
unsigned long level_offset[PIPE_MAX_TEXTURE_LEVELS];
unsigned stride[PIPE_MAX_TEXTURE_LEVELS];
/* The data is held here:
*/
struct pipe_buffer *buffer;
boolean modified;
};
struct llvmpipe_transfer
{
struct pipe_transfer base;
unsigned long offset;
};
/** cast wrappers */
static INLINE struct llvmpipe_texture *
llvmpipe_texture(struct pipe_texture *pt)
{
return (struct llvmpipe_texture *) pt;
}
static INLINE struct llvmpipe_transfer *
llvmpipe_transfer(struct pipe_transfer *pt)
{
return (struct llvmpipe_transfer *) pt;
}
extern void
llvmpipe_init_texture_funcs( struct llvmpipe_context *llvmpipe );
extern void
llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen);
#endif /* SP_TEXTURE */

View file

@ -0,0 +1,626 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/**
* Texture tile caching.
*
* Author:
* Brian Paul
*/
#include "pipe/p_inlines.h"
#include "util/u_memory.h"
#include "util/u_tile.h"
#include "lp_context.h"
#include "lp_surface.h"
#include "lp_texture.h"
#include "lp_tile_cache.h"
#define NUM_ENTRIES 50
/** XXX move these */
#define MAX_WIDTH 2048
#define MAX_HEIGHT 2048
struct llvmpipe_tile_cache
{
struct pipe_screen *screen;
struct pipe_surface *surface; /**< the surface we're caching */
struct pipe_transfer *transfer;
void *transfer_map;
struct pipe_texture *texture; /**< if caching a texture */
struct llvmpipe_cached_tile entries[NUM_ENTRIES];
uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
float clear_color[4]; /**< for color bufs */
uint clear_val; /**< for z+stencil, or packed color clear value */
boolean depth_stencil; /**< Is the surface a depth/stencil format? */
struct pipe_transfer *tex_trans;
void *tex_trans_map;
int tex_face, tex_level, tex_z;
struct llvmpipe_cached_tile tile; /**< scratch tile for clears */
};
/**
* Return the position in the cache for the tile that contains win pos (x,y).
* We currently use a direct mapped cache so this is like a hack key.
* At some point we should investige something more sophisticated, like
* a LRU replacement policy.
*/
#define CACHE_POS(x, y) \
(((x) / TILE_SIZE + ((y) / TILE_SIZE) * 5) % NUM_ENTRIES)
/**
* Is the tile at (x,y) in cleared state?
*/
static INLINE uint
is_clear_flag_set(const uint *bitvec, int x, int y)
{
int pos, bit;
x /= TILE_SIZE;
y /= TILE_SIZE;
pos = y * (MAX_WIDTH / TILE_SIZE) + x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bit = bitvec[pos / 32] & (1 << (pos & 31));
return bit;
}
/**
* Mark the tile at (x,y) as not cleared.
*/
static INLINE void
clear_clear_flag(uint *bitvec, int x, int y)
{
int pos;
x /= TILE_SIZE;
y /= TILE_SIZE;
pos = y * (MAX_WIDTH / TILE_SIZE) + x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bitvec[pos / 32] &= ~(1 << (pos & 31));
}
struct llvmpipe_tile_cache *
lp_create_tile_cache( struct pipe_screen *screen )
{
struct llvmpipe_tile_cache *tc;
uint pos;
tc = CALLOC_STRUCT( llvmpipe_tile_cache );
if (tc) {
tc->screen = screen;
for (pos = 0; pos < NUM_ENTRIES; pos++) {
tc->entries[pos].x =
tc->entries[pos].y = -1;
}
}
return tc;
}
void
lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc)
{
struct pipe_screen *screen;
uint pos;
for (pos = 0; pos < NUM_ENTRIES; pos++) {
/*assert(tc->entries[pos].x < 0);*/
}
if (tc->transfer) {
screen = tc->transfer->texture->screen;
screen->tex_transfer_destroy(tc->transfer);
}
if (tc->tex_trans) {
screen = tc->tex_trans->texture->screen;
screen->tex_transfer_destroy(tc->tex_trans);
}
FREE( tc );
}
/**
* Specify the surface to cache.
*/
void
lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc,
struct pipe_surface *ps)
{
assert(!tc->texture);
if (tc->transfer) {
struct pipe_screen *screen = tc->transfer->texture->screen;
if (ps == tc->surface)
return;
if (tc->transfer_map) {
screen->transfer_unmap(screen, tc->transfer);
tc->transfer_map = NULL;
}
screen->tex_transfer_destroy(tc->transfer);
tc->transfer = NULL;
}
tc->surface = ps;
if (ps) {
struct pipe_screen *screen = ps->texture->screen;
tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
ps->level, ps->zslice,
PIPE_TRANSFER_READ_WRITE,
0, 0, ps->width, ps->height);
tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
ps->format == PIPE_FORMAT_X8Z24_UNORM ||
ps->format == PIPE_FORMAT_Z24S8_UNORM ||
ps->format == PIPE_FORMAT_Z24X8_UNORM ||
ps->format == PIPE_FORMAT_Z16_UNORM ||
ps->format == PIPE_FORMAT_Z32_UNORM ||
ps->format == PIPE_FORMAT_S8_UNORM);
}
}
/**
* Return the transfer being cached.
*/
struct pipe_surface *
lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc)
{
return tc->surface;
}
void
lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc)
{
if (tc->transfer && !tc->transfer_map)
tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
if (tc->tex_trans && !tc->tex_trans_map)
tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
}
void
lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc)
{
if (tc->transfer_map) {
tc->screen->transfer_unmap(tc->screen, tc->transfer);
tc->transfer_map = NULL;
}
if (tc->tex_trans_map) {
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
tc->tex_trans_map = NULL;
}
}
/**
* Specify the texture to cache.
*/
void
lp_tile_cache_set_texture(struct pipe_context *pipe,
struct llvmpipe_tile_cache *tc,
struct pipe_texture *texture)
{
uint i;
assert(!tc->transfer);
pipe_texture_reference(&tc->texture, texture);
if (tc->tex_trans) {
struct pipe_screen *screen = tc->tex_trans->texture->screen;
if (tc->tex_trans_map) {
screen->transfer_unmap(screen, tc->tex_trans);
tc->tex_trans_map = NULL;
}
screen->tex_transfer_destroy(tc->tex_trans);
tc->tex_trans = NULL;
}
/* mark as entries as invalid/empty */
/* XXX we should try to avoid this when the teximage hasn't changed */
for (i = 0; i < NUM_ENTRIES; i++) {
tc->entries[i].x = -1;
}
tc->tex_face = -1; /* any invalid value here */
}
/**
* Set pixels in a tile to the given clear color/value, float.
*/
static void
clear_tile_rgba(struct llvmpipe_cached_tile *tile,
enum pipe_format format,
const float clear_value[4])
{
if (clear_value[0] == 0.0 &&
clear_value[1] == 0.0 &&
clear_value[2] == 0.0 &&
clear_value[3] == 0.0) {
memset(tile->data.color, 0, sizeof(tile->data.color));
}
else {
uint i, j;
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.color[i][j][0] = clear_value[0];
tile->data.color[i][j][1] = clear_value[1];
tile->data.color[i][j][2] = clear_value[2];
tile->data.color[i][j][3] = clear_value[3];
}
}
}
}
/**
* Set a tile to a solid value/color.
*/
static void
clear_tile(struct llvmpipe_cached_tile *tile,
enum pipe_format format,
uint clear_value)
{
uint i, j;
switch (pf_get_size(format)) {
case 1:
memset(tile->data.any, 0, TILE_SIZE * TILE_SIZE);
break;
case 2:
if (clear_value == 0) {
memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth16[i][j] = (ushort) clear_value;
}
}
}
break;
case 4:
if (clear_value == 0) {
memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.color32[i][j] = clear_value;
}
}
}
break;
default:
assert(0);
}
}
/**
* Actually clear the tiles which were flagged as being in a clear state.
*/
static void
lp_tile_cache_flush_clear(struct pipe_context *pipe,
struct llvmpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
const uint w = tc->transfer->width;
const uint h = tc->transfer->height;
uint x, y;
uint numCleared = 0;
/* clear the scratch tile to the clear value */
clear_tile(&tc->tile, pt->format, tc->clear_val);
/* push the tile to all positions marked as clear */
for (y = 0; y < h; y += TILE_SIZE) {
for (x = 0; x < w; x += TILE_SIZE) {
if (is_clear_flag_set(tc->clear_flags, x, y)) {
pipe_put_tile_raw(pt,
x, y, TILE_SIZE, TILE_SIZE,
tc->tile.data.color32, 0/*STRIDE*/);
/* do this? */
clear_clear_flag(tc->clear_flags, x, y);
numCleared++;
}
}
}
#if 0
debug_printf("num cleared: %u\n", numCleared);
#endif
}
/**
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
lp_flush_tile_cache(struct llvmpipe_context *llvmpipe,
struct llvmpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
int inuse = 0, pos;
if (pt) {
/* caching a drawing transfer */
for (pos = 0; pos < NUM_ENTRIES; pos++) {
struct llvmpipe_cached_tile *tile = tc->entries + pos;
if (tile->x >= 0) {
if (tc->depth_stencil) {
pipe_put_tile_raw(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
pipe_put_tile_rgba(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
(float *) tile->data.color);
}
tile->x = tile->y = -1; /* mark as empty */
inuse++;
}
}
#if TILE_CLEAR_OPTIMIZATION
lp_tile_cache_flush_clear(&llvmpipe->pipe, tc);
#endif
}
else if (tc->texture) {
/* caching a texture, mark all entries as empty */
for (pos = 0; pos < NUM_ENTRIES; pos++) {
tc->entries[pos].x = -1;
}
tc->tex_face = -1;
}
#if 0
debug_printf("flushed tiles in use: %d\n", inuse);
#endif
}
/**
* Get a tile from the cache.
* \param x, y position of tile, in pixels
*/
struct llvmpipe_cached_tile *
lp_get_cached_tile(struct llvmpipe_context *llvmpipe,
struct llvmpipe_tile_cache *tc, int x, int y)
{
struct pipe_transfer *pt = tc->transfer;
/* tile pos in framebuffer: */
const int tile_x = x & ~(TILE_SIZE - 1);
const int tile_y = y & ~(TILE_SIZE - 1);
/* cache pos/entry: */
const int pos = CACHE_POS(x, y);
struct llvmpipe_cached_tile *tile = tc->entries + pos;
if (tile_x != tile->x ||
tile_y != tile->y) {
if (tile->x != -1) {
/* put dirty tile back in framebuffer */
if (tc->depth_stencil) {
pipe_put_tile_raw(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
pipe_put_tile_rgba(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
(float *) tile->data.color);
}
}
tile->x = tile_x;
tile->y = tile_y;
if (is_clear_flag_set(tc->clear_flags, x, y)) {
/* don't get tile from framebuffer, just clear it */
if (tc->depth_stencil) {
clear_tile(tile, pt->format, tc->clear_val);
}
else {
clear_tile_rgba(tile, pt->format, tc->clear_color);
}
clear_clear_flag(tc->clear_flags, x, y);
}
else {
/* get new tile data from transfer */
if (tc->depth_stencil) {
pipe_get_tile_raw(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
pipe_get_tile_rgba(pt,
tile->x, tile->y, TILE_SIZE, TILE_SIZE,
(float *) tile->data.color);
}
}
}
return tile;
}
/**
* Given the texture face, level, zslice, x and y values, compute
* the cache entry position/index where we'd hope to find the
* cached texture tile.
* This is basically a direct-map cache.
* XXX There's probably lots of ways in which we can improve this.
*/
static INLINE uint
tex_cache_pos(int x, int y, int z, int face, int level)
{
uint entry = x + y * 9 + z * 3 + face + level * 7;
return entry % NUM_ENTRIES;
}
/**
* Similar to lp_get_cached_tile() but for textures.
* Tiles are read-only and indexed with more params.
*/
const struct llvmpipe_cached_tile *
lp_get_cached_tile_tex(struct llvmpipe_context *lp,
struct llvmpipe_tile_cache *tc, int x, int y, int z,
int face, int level)
{
struct pipe_screen *screen = lp->pipe.screen;
/* tile pos in framebuffer: */
const int tile_x = x & ~(TILE_SIZE - 1);
const int tile_y = y & ~(TILE_SIZE - 1);
/* cache pos/entry: */
const uint pos = tex_cache_pos(x / TILE_SIZE, y / TILE_SIZE, z,
face, level);
struct llvmpipe_cached_tile *tile = tc->entries + pos;
if (tc->texture) {
struct llvmpipe_texture *lpt = llvmpipe_texture(tc->texture);
if (lpt->modified) {
/* texture was modified, invalidate all cached tiles */
uint p;
for (p = 0; p < NUM_ENTRIES; p++) {
tile = tc->entries + p;
tile->x = -1;
}
lpt->modified = FALSE;
}
}
if (tile_x != tile->x ||
tile_y != tile->y ||
z != tile->z ||
face != tile->face ||
level != tile->level) {
/* cache miss */
#if 0
printf("miss at %u x=%d y=%d z=%d face=%d level=%d\n", pos,
x/TILE_SIZE, y/TILE_SIZE, z, face, level);
#endif
/* check if we need to get a new transfer */
if (!tc->tex_trans ||
tc->tex_face != face ||
tc->tex_level != level ||
tc->tex_z != z) {
/* get new transfer (view into texture) */
if (tc->tex_trans) {
if (tc->tex_trans_map) {
tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
tc->tex_trans_map = NULL;
}
screen->tex_transfer_destroy(tc->tex_trans);
tc->tex_trans = NULL;
}
tc->tex_trans = screen->get_tex_transfer(screen, tc->texture, face, level, z,
PIPE_TRANSFER_READ, 0, 0,
tc->texture->width[level],
tc->texture->height[level]);
tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
tc->tex_face = face;
tc->tex_level = level;
tc->tex_z = z;
}
/* get tile from the transfer (view into texture) */
pipe_get_tile_rgba(tc->tex_trans,
tile_x, tile_y, TILE_SIZE, TILE_SIZE,
(float *) tile->data.color);
tile->x = tile_x;
tile->y = tile_y;
tile->z = z;
tile->face = face;
tile->level = level;
}
return tile;
}
/**
* When a whole surface is being cleared to a value we can avoid
* fetching tiles above.
* Save the color and set a 'clearflag' for each tile of the screen.
*/
void
lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba,
uint clearValue)
{
uint pos;
tc->clear_color[0] = rgba[0];
tc->clear_color[1] = rgba[1];
tc->clear_color[2] = rgba[2];
tc->clear_color[3] = rgba[3];
tc->clear_val = clearValue;
#if TILE_CLEAR_OPTIMIZATION
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
#else
/* disable the optimization */
memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
#endif
for (pos = 0; pos < NUM_ENTRIES; pos++) {
struct llvmpipe_cached_tile *tile = tc->entries + pos;
tile->x = tile->y = -1;
}
}

View file

@ -0,0 +1,106 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_TILE_CACHE_H
#define SP_TILE_CACHE_H
#define TILE_CLEAR_OPTIMIZATION 1
#include "pipe/p_compiler.h"
struct llvmpipe_context;
struct llvmpipe_tile_cache;
/**
* Cache tile size (width and height). This needs to be a power of two.
*/
#define TILE_SIZE 64
struct llvmpipe_cached_tile
{
int x, y; /**< pos of tile in window coords */
int z, face, level; /**< Extra texture indexes */
union {
float color[TILE_SIZE][TILE_SIZE][4];
uint color32[TILE_SIZE][TILE_SIZE];
uint depth32[TILE_SIZE][TILE_SIZE];
ushort depth16[TILE_SIZE][TILE_SIZE];
ubyte stencil8[TILE_SIZE][TILE_SIZE];
ubyte any[1];
} data;
};
extern struct llvmpipe_tile_cache *
lp_create_tile_cache( struct pipe_screen *screen );
extern void
lp_destroy_tile_cache(struct llvmpipe_tile_cache *tc);
extern void
lp_tile_cache_set_surface(struct llvmpipe_tile_cache *tc,
struct pipe_surface *lps);
extern struct pipe_surface *
lp_tile_cache_get_surface(struct llvmpipe_tile_cache *tc);
extern void
lp_tile_cache_map_transfers(struct llvmpipe_tile_cache *tc);
extern void
lp_tile_cache_unmap_transfers(struct llvmpipe_tile_cache *tc);
extern void
lp_tile_cache_set_texture(struct pipe_context *pipe,
struct llvmpipe_tile_cache *tc,
struct pipe_texture *texture);
extern void
lp_flush_tile_cache(struct llvmpipe_context *llvmpipe,
struct llvmpipe_tile_cache *tc);
extern void
lp_tile_cache_clear(struct llvmpipe_tile_cache *tc, const float *rgba,
uint clearValue);
extern struct llvmpipe_cached_tile *
lp_get_cached_tile(struct llvmpipe_context *llvmpipe,
struct llvmpipe_tile_cache *tc, int x, int y);
extern const struct llvmpipe_cached_tile *
lp_get_cached_tile_tex(struct llvmpipe_context *llvmpipe,
struct llvmpipe_tile_cache *tc, int x, int y, int z,
int face, int level);
#endif /* SP_TILE_CACHE_H */

View file

@ -0,0 +1,65 @@
/**************************************************************************
*
* 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.
*
**************************************************************************/
/* This is the interface that llvmpipe requires any window system
* hosting it to implement. This is the only include file in llvmpipe
* which is public.
*/
#ifndef SP_WINSYS_H
#define SP_WINSYS_H
#ifdef __cplusplus
extern "C" {
#endif
struct pipe_screen;
struct pipe_winsys;
struct pipe_context;
struct pipe_context *llvmpipe_create( struct pipe_screen * );
struct pipe_screen *
llvmpipe_create_screen(struct pipe_winsys *);
boolean
llvmpipe_get_texture_buffer( struct pipe_texture *texture,
struct pipe_buffer **buf,
unsigned *stride );
#ifdef __cplusplus
}
#endif
#endif /* SP_WINSYS_H */