summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKeith Whitwell <[email protected]>2010-01-10 17:22:09 +0000
committerKeith Whitwell <[email protected]>2010-01-10 17:22:09 +0000
commitc1a04416023e24621e4992caf593e8dfe8d7a2fc (patch)
tree954303fe263279379063ff418f87418f62c205ec /src
parentf4321fbd961a0a891c7f40b16efc61aa791e03a9 (diff)
llvmpipe: initial mrt support
Non-mrt apps work, and the code looks correct, but not many mrt test apps handy atm...
Diffstat (limited to 'src')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_flush.c7
-rw-r--r--src/gallium/drivers/llvmpipe/lp_jit.h2
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast.c215
-rw-r--r--src/gallium/drivers/llvmpipe/lp_rast_priv.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c18
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state.h6
-rw-r--r--src/gallium/drivers/llvmpipe/lp_state_fs.c114
7 files changed, 225 insertions, 143 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_flush.c b/src/gallium/drivers/llvmpipe/lp_flush.c
index 9405150c4f7..16fb00092e6 100644
--- a/src/gallium/drivers/llvmpipe/lp_flush.c
+++ b/src/gallium/drivers/llvmpipe/lp_flush.c
@@ -77,8 +77,11 @@ llvmpipe_flush( struct pipe_context *pipe,
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]);
+ unsigned i;
+ for (i = 0; i < llvmpipe->framebuffer.nr_cbufs) {
+ util_snprintf(filename, sizeof(filename), "cbuf%u_%u.bmp", i, frame_no);
+ debug_dump_surface_bmp(filename, llvmpipe->framebuffer.cbufs[i]);
+ }
util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(filename, llvmpipe->framebuffer.zsbuf);
++frame_no;
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 1a6e939aa24..3b316914b02 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -108,7 +108,7 @@ typedef void
const void *a0,
const void *dadx,
const void *dady,
- void *color,
+ uint8_t **color,
void *depth,
const int32_t c1,
const int32_t c2,
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 6535e693089..38c27b90e35 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -53,6 +53,7 @@ lp_rast_begin( struct lp_rasterizer *rast,
{
struct pipe_screen *screen = rast->screen;
struct pipe_surface *cbuf, *zsbuf;
+ int i;
LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
@@ -64,24 +65,27 @@ lp_rast_begin( struct lp_rasterizer *rast,
rast->check_for_clipped_tiles = (fb->width % TILE_SIZE != 0 ||
fb->height % TILE_SIZE != 0);
- /* XXX support multiple color buffers here */
- cbuf = rast->state.fb.cbufs[0];
- if (cbuf) {
- rast->cbuf_transfer = screen->get_tex_transfer(rast->screen,
- cbuf->texture,
- cbuf->face,
- cbuf->level,
- cbuf->zslice,
- PIPE_TRANSFER_READ_WRITE,
- 0, 0,
- fb->width, fb->height);
- if (!rast->cbuf_transfer)
- return FALSE;
-
- rast->cbuf_map = screen->transfer_map(rast->screen,
- rast->cbuf_transfer);
- if (!rast->cbuf_map)
- return FALSE;
+
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+ cbuf = rast->state.fb.cbufs[i];
+ if (cbuf) {
+ rast->cbuf_transfer[i] = screen->get_tex_transfer(rast->screen,
+ cbuf->texture,
+ cbuf->face,
+ cbuf->level,
+ cbuf->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0,
+ cbuf->width,
+ cbuf->height);
+ if (!rast->cbuf_transfer[i])
+ goto fail;
+
+ rast->cbuf_map[i] = screen->transfer_map(rast->screen,
+ rast->cbuf_transfer[i]);
+ if (!rast->cbuf_map[i])
+ goto fail;
+ }
}
zsbuf = rast->state.fb.zsbuf;
@@ -93,17 +97,23 @@ lp_rast_begin( struct lp_rasterizer *rast,
zsbuf->zslice,
PIPE_TRANSFER_READ_WRITE,
0, 0,
- fb->width, fb->height);
+ zsbuf->width,
+ zsbuf->height);
if (!rast->zsbuf_transfer)
- return FALSE;
+ goto fail;
rast->zsbuf_map = screen->transfer_map(rast->screen,
rast->zsbuf_transfer);
if (!rast->zsbuf_map)
- return FALSE;
+ goto fail;
}
return TRUE;
+
+fail:
+ /* Unmap and release transfers?
+ */
+ return FALSE;
}
@@ -115,22 +125,26 @@ static void
lp_rast_end( struct lp_rasterizer *rast )
{
struct pipe_screen *screen = rast->screen;
+ unsigned i;
- if (rast->cbuf_map)
- screen->transfer_unmap(screen, rast->cbuf_transfer);
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+ if (rast->cbuf_map[i])
+ screen->transfer_unmap(screen, rast->cbuf_transfer[i]);
+
+ if (rast->cbuf_transfer[i])
+ screen->tex_transfer_destroy(rast->cbuf_transfer[i]);
+
+ rast->cbuf_transfer[i] = NULL;
+ rast->cbuf_map[i] = NULL;
+ }
if (rast->zsbuf_map)
screen->transfer_unmap(screen, rast->zsbuf_transfer);
- if (rast->cbuf_transfer)
- screen->tex_transfer_destroy(rast->cbuf_transfer);
-
if (rast->zsbuf_transfer)
screen->tex_transfer_destroy(rast->zsbuf_transfer);
- rast->cbuf_transfer = NULL;
rast->zsbuf_transfer = NULL;
- rast->cbuf_map = NULL;
rast->zsbuf_map = NULL;
}
@@ -161,8 +175,9 @@ void lp_rast_clear_color( struct lp_rasterizer *rast,
const union lp_rast_cmd_arg arg )
{
const uint8_t *clear_color = arg.clear_color;
- uint8_t *color_tile = rast->tasks[thread_index].tile.color;
-
+ uint8_t **color_tile = rast->tasks[thread_index].tile.color;
+ unsigned i;
+
LP_DBG(DEBUG_RAST, "%s 0x%x,0x%x,0x%x,0x%x\n", __FUNCTION__,
clear_color[0],
clear_color[1],
@@ -172,14 +187,17 @@ void lp_rast_clear_color( struct lp_rasterizer *rast,
if (clear_color[0] == clear_color[1] &&
clear_color[1] == clear_color[2] &&
clear_color[2] == clear_color[3]) {
- memset(color_tile, clear_color[0], TILE_SIZE * TILE_SIZE * 4);
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+ memset(color_tile[i], clear_color[0], TILE_SIZE * TILE_SIZE * 4);
+ }
}
else {
unsigned x, y, chan;
- for (y = 0; y < TILE_SIZE; y++)
- for (x = 0; x < TILE_SIZE; x++)
- for (chan = 0; chan < 4; ++chan)
- TILE_PIXEL(color_tile, x, y, chan) = clear_color[chan];
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++)
+ for (y = 0; y < TILE_SIZE; y++)
+ for (x = 0; x < TILE_SIZE; x++)
+ for (chan = 0; chan < 4; ++chan)
+ TILE_PIXEL(color_tile[i], x, y, chan) = clear_color[chan];
}
}
@@ -214,28 +232,40 @@ void lp_rast_load_color( struct lp_rasterizer *rast,
struct lp_rasterizer_task *task = &rast->tasks[thread_index];
const unsigned x = task->x;
const unsigned y = task->y;
- int w = TILE_SIZE;
- int h = TILE_SIZE;
+ unsigned i;
LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y);
- if (x + w > rast->state.fb.width)
- w -= x + w - rast->state.fb.width;
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+ struct pipe_transfer *transfer = rast->cbuf_transfer[i];
+ int w = TILE_SIZE;
+ int h = TILE_SIZE;
- if (y + h > rast->state.fb.height)
- h -= y + h - rast->state.fb.height;
+ if (x >= transfer->width)
+ continue;
- assert(w >= 0);
- assert(h >= 0);
- assert(w <= TILE_SIZE);
- assert(h <= TILE_SIZE);
-
- lp_tile_read_4ub(rast->cbuf_transfer->texture->format,
- rast->tasks[thread_index].tile.color,
- rast->cbuf_map,
- rast->cbuf_transfer->stride,
- x, y,
- w, h);
+ if (y >= transfer->height)
+ continue;
+ /* XXX: require tile-size aligned render target dimensions:
+ */
+ if (x + w > transfer->width)
+ w -= x + w - transfer->width;
+
+ if (y + h > transfer->height)
+ h -= y + h - transfer->height;
+
+ assert(w >= 0);
+ assert(h >= 0);
+ assert(w <= TILE_SIZE);
+ assert(h <= TILE_SIZE);
+
+ lp_tile_read_4ub(transfer->texture->format,
+ rast->tasks[thread_index].tile.color[i],
+ rast->cbuf_map[i],
+ transfer->stride,
+ x, y,
+ w, h);
+ }
}
@@ -313,8 +343,9 @@ void lp_rast_shade_quads( struct lp_rasterizer *rast,
{
const struct lp_rast_state *state = rast->tasks[thread_index].current_state;
struct lp_rast_tile *tile = &rast->tasks[thread_index].tile;
- void *color;
+ uint8_t *color[PIPE_MAX_COLOR_BUFS];
void *depth;
+ unsigned i;
unsigned ix, iy;
int block_offset;
@@ -336,14 +367,17 @@ void lp_rast_shade_quads( struct lp_rasterizer *rast,
block_offset = ((iy/4)*(16*16) + (ix/4)*16);
/* color buffer */
- color = tile->color + 4 * block_offset;
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++)
+ color[i] = tile->color[i] + 4 * block_offset;
/* depth buffer */
depth = tile->depth + block_offset;
+
+
#ifdef DEBUG
- assert(lp_check_alignment(depth, 16));
- assert(lp_check_alignment(color, 16));
+ assert(lp_check_alignment(tile->depth, 16));
+ assert(lp_check_alignment(tile->color[0], 16));
assert(lp_check_alignment(state->jit_context.blend_color, 16));
assert(lp_check_alignment(inputs->step[0], 16));
@@ -360,8 +394,7 @@ void lp_rast_shade_quads( struct lp_rasterizer *rast,
color,
depth,
c1, c2, c3,
- inputs->step[0], inputs->step[1], inputs->step[2]
- );
+ inputs->step[0], inputs->step[1], inputs->step[2]);
}
@@ -377,29 +410,42 @@ static void lp_rast_store_color( struct lp_rasterizer *rast,
{
const unsigned x = rast->tasks[thread_index].x;
const unsigned y = rast->tasks[thread_index].y;
- int w = TILE_SIZE;
- int h = TILE_SIZE;
-
- if (x + w > rast->state.fb.width)
- w -= x + w - rast->state.fb.width;
+ unsigned i;
- if (y + h > rast->state.fb.height)
- h -= y + h - rast->state.fb.height;
+ for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+ struct pipe_transfer *transfer = rast->cbuf_transfer[i];
+ int w = TILE_SIZE;
+ int h = TILE_SIZE;
- assert(w >= 0);
- assert(h >= 0);
- assert(w <= TILE_SIZE);
- assert(h <= TILE_SIZE);
+ if (x >= transfer->width)
+ continue;
- LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__,
- thread_index, x, y, w, h);
+ if (y >= transfer->height)
+ continue;
- lp_tile_write_4ub(rast->cbuf_transfer->texture->format,
- rast->tasks[thread_index].tile.color,
- rast->cbuf_map,
- rast->cbuf_transfer->stride,
- x, y,
- w, h);
+ /* XXX: require tile-size aligned render target dimensions:
+ */
+ if (x + w > transfer->width)
+ w -= x + w - transfer->width;
+
+ if (y + h > transfer->height)
+ h -= y + h - transfer->height;
+
+ assert(w >= 0);
+ assert(h >= 0);
+ assert(w <= TILE_SIZE);
+ assert(h <= TILE_SIZE);
+
+ LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__,
+ thread_index, x, y, w, h);
+
+ lp_tile_write_4ub(transfer->texture->format,
+ rast->tasks[thread_index].tile.color[i],
+ rast->cbuf_map[i],
+ transfer->stride,
+ x, y,
+ w, h);
+ }
}
@@ -600,7 +646,7 @@ lp_rasterize_scene( struct lp_rasterizer *rast,
/* no threading */
lp_rast_begin( rast, fb,
- fb->cbufs[0]!= NULL,
+ fb->nr_cbufs != 0, /* always write color if cbufs present */
fb->zsbuf != NULL && write_depth );
lp_scene_bin_iter_begin( scene );
@@ -667,7 +713,7 @@ thread_func( void *init_data )
write_depth = rast->curr_scene->write_depth;
lp_rast_begin( rast, fb,
- fb->cbufs[0] != NULL,
+ fb->nr_cbufs != 0,
fb->zsbuf != NULL && write_depth );
}
@@ -738,7 +784,7 @@ struct lp_rasterizer *
lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
{
struct lp_rasterizer *rast;
- unsigned i;
+ unsigned i, cbuf;
rast = CALLOC_STRUCT(lp_rasterizer);
if(!rast)
@@ -750,7 +796,9 @@ lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
rast->full_scenes = lp_scene_queue_create();
for (i = 0; i < Elements(rast->tasks); i++) {
- rast->tasks[i].tile.color = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
+ for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ )
+ rast->tasks[i].tile.color[cbuf] = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
+
rast->tasks[i].tile.depth = align_malloc( TILE_SIZE*TILE_SIZE*4, 16 );
rast->tasks[i].rast = rast;
rast->tasks[i].thread_index = i;
@@ -769,13 +817,14 @@ lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
*/
void lp_rast_destroy( struct lp_rasterizer *rast )
{
- unsigned i;
+ unsigned i, cbuf;
util_unreference_framebuffer_state(&rast->state.fb);
for (i = 0; i < Elements(rast->tasks); i++) {
align_free(rast->tasks[i].tile.depth);
- align_free(rast->tasks[i].tile.color);
+ for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ )
+ align_free(rast->tasks[i].tile.color[cbuf]);
}
/* for synchronizing rasterization threads */
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index cd72d7e69d8..5afdeab049c 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -46,7 +46,7 @@ struct lp_rasterizer;
*/
struct lp_rast_tile
{
- uint8_t *color;
+ uint8_t *color[PIPE_MAX_COLOR_BUFS];
uint32_t *depth;
};
@@ -87,9 +87,9 @@ struct lp_rasterizer
/* Framebuffer stuff
*/
struct pipe_screen *screen;
- struct pipe_transfer *cbuf_transfer;
+ struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
struct pipe_transfer *zsbuf_transfer;
- void *cbuf_map;
+ void *cbuf_map[PIPE_MAX_COLOR_BUFS];
void *zsbuf_map;
struct {
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 5cdcf4ecc98..74f3054864c 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -155,26 +155,26 @@ begin_binning( struct setup_context *setup )
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
- if (setup->fb.cbufs[0]) {
+ if (setup->fb.nr_cbufs) {
if (setup->clear.flags & PIPE_CLEAR_COLOR)
lp_scene_bin_everywhere( scene,
- lp_rast_clear_color,
- setup->clear.color );
+ lp_rast_clear_color,
+ setup->clear.color );
else
lp_scene_bin_everywhere( scene,
- lp_rast_load_color,
- lp_rast_arg_null() );
+ lp_rast_load_color,
+ lp_rast_arg_null() );
}
if (setup->fb.zsbuf) {
if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL)
lp_scene_bin_everywhere( scene,
- lp_rast_clear_zstencil,
- setup->clear.zstencil );
+ lp_rast_clear_zstencil,
+ setup->clear.zstencil );
else
lp_scene_bin_everywhere( scene,
- lp_rast_load_zstencil,
- lp_rast_arg_null() );
+ lp_rast_load_zstencil,
+ lp_rast_arg_null() );
}
LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__);
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 25d13536741..cb240cb6e55 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -67,10 +67,16 @@ struct lp_fragment_shader;
struct lp_fragment_shader_variant_key
{
enum pipe_format zsbuf_format;
+ unsigned nr_cbufs;
+
struct pipe_depth_state depth;
struct pipe_alpha_state alpha;
struct pipe_blend_state blend;
+ struct {
+ ubyte colormask;
+ } cbuf_blend[PIPE_MAX_COLOR_BUFS];
+
struct lp_sampler_static_state sampler[PIPE_MAX_SAMPLERS];
};
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 293535387ab..01912d6ea2d 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -327,7 +327,7 @@ generate_fs(struct llvmpipe_context *lp,
const struct lp_build_interp_soa_context *interp,
struct lp_build_sampler_soa *sampler,
LLVMValueRef *pmask,
- LLVMValueRef *color,
+ LLVMValueRef (*color)[4],
LLVMValueRef depth_ptr,
LLVMValueRef c0,
LLVMValueRef c1,
@@ -348,6 +348,7 @@ generate_fs(struct llvmpipe_context *lp,
boolean early_depth_test;
unsigned attrib;
unsigned chan;
+ unsigned cbuf;
assert(i < 4);
@@ -364,9 +365,11 @@ generate_fs(struct llvmpipe_context *lp,
lp_build_flow_scope_begin(flow);
/* Declare the color and z variables */
- for(chan = 0; chan < NUM_CHANNELS; ++chan) {
- color[chan] = LLVMGetUndef(vec_type);
- lp_build_flow_scope_declare(flow, &color[chan]);
+ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ color[cbuf][chan] = LLVMGetUndef(vec_type);
+ lp_build_flow_scope_declare(flow, &color[cbuf][chan]);
+ }
}
lp_build_flow_scope_declare(flow, &z);
@@ -407,6 +410,7 @@ generate_fs(struct llvmpipe_context *lp,
/* Alpha test */
/* XXX: should the alpha reference value be passed separately? */
+ /* XXX: should only test the final assignment to alpha */
if(cbuf == 0 && chan == 3) {
LLVMValueRef alpha = outputs[attrib][chan];
LLVMValueRef alpha_ref_value;
@@ -416,9 +420,7 @@ generate_fs(struct llvmpipe_context *lp,
&mask, alpha, alpha_ref_value);
}
- if(cbuf == 0)
- color[chan] = outputs[attrib][chan];
-
+ color[cbuf][chan] = outputs[attrib][chan];
break;
}
@@ -539,7 +541,7 @@ generate_fragment(struct llvmpipe_context *lp,
LLVMValueRef a0_ptr;
LLVMValueRef dadx_ptr;
LLVMValueRef dady_ptr;
- LLVMValueRef color_ptr;
+ LLVMValueRef color_ptr_ptr;
LLVMValueRef depth_ptr;
LLVMValueRef c0, c1, c2, step0_ptr, step1_ptr, step2_ptr;
LLVMBasicBlockRef block;
@@ -549,12 +551,13 @@ generate_fragment(struct llvmpipe_context *lp,
struct lp_build_sampler_soa *sampler;
struct lp_build_interp_soa_context interp;
LLVMValueRef fs_mask[LP_MAX_VECTOR_LENGTH];
- LLVMValueRef fs_out_color[NUM_CHANNELS][LP_MAX_VECTOR_LENGTH];
+ LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][LP_MAX_VECTOR_LENGTH];
LLVMValueRef blend_mask;
LLVMValueRef blend_in_color[NUM_CHANNELS];
unsigned num_fs;
unsigned i;
unsigned chan;
+ unsigned cbuf;
if (LP_DEBUG & DEBUG_JIT) {
tgsi_dump(shader->base.tokens, 0);
@@ -651,7 +654,7 @@ generate_fragment(struct llvmpipe_context *lp,
arg_types[3] = LLVMPointerType(fs_elem_type, 0); /* a0 */
arg_types[4] = LLVMPointerType(fs_elem_type, 0); /* dadx */
arg_types[5] = LLVMPointerType(fs_elem_type, 0); /* dady */
- arg_types[6] = LLVMPointerType(blend_vec_type, 0); /* color */
+ arg_types[6] = LLVMPointerType(LLVMPointerType(blend_vec_type, 0), 0); /* color */
arg_types[7] = LLVMPointerType(fs_int_vec_type, 0); /* depth */
arg_types[8] = LLVMInt32Type(); /* c0 */
arg_types[9] = LLVMInt32Type(); /* c1 */
@@ -667,6 +670,10 @@ generate_fragment(struct llvmpipe_context *lp,
variant->function = LLVMAddFunction(screen->module, "shader", func_type);
LLVMSetFunctionCallConv(variant->function, LLVMCCallConv);
+
+ /* XXX: need to propagate noalias down into color param now we are
+ * passing a pointer-to-pointer?
+ */
for(i = 0; i < Elements(arg_types); ++i)
if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute);
@@ -677,7 +684,7 @@ generate_fragment(struct llvmpipe_context *lp,
a0_ptr = LLVMGetParam(variant->function, 3);
dadx_ptr = LLVMGetParam(variant->function, 4);
dady_ptr = LLVMGetParam(variant->function, 5);
- color_ptr = LLVMGetParam(variant->function, 6);
+ color_ptr_ptr = LLVMGetParam(variant->function, 6);
depth_ptr = LLVMGetParam(variant->function, 7);
c0 = LLVMGetParam(variant->function, 8);
c1 = LLVMGetParam(variant->function, 9);
@@ -692,7 +699,7 @@ generate_fragment(struct llvmpipe_context *lp,
lp_build_name(a0_ptr, "a0");
lp_build_name(dadx_ptr, "dadx");
lp_build_name(dady_ptr, "dady");
- lp_build_name(color_ptr, "color");
+ lp_build_name(color_ptr_ptr, "color_ptr");
lp_build_name(depth_ptr, "depth");
lp_build_name(c0, "c0");
lp_build_name(c1, "c1");
@@ -721,8 +728,9 @@ generate_fragment(struct llvmpipe_context *lp,
/* loop over quads in the block */
for(i = 0; i < num_fs; ++i) {
LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, 0);
- LLVMValueRef out_color[NUM_CHANNELS];
+ LLVMValueRef out_color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS];
LLVMValueRef depth_ptr_i;
+ int cbuf;
if(i != 0)
lp_build_interp_soa_update(&interp, i);
@@ -742,40 +750,50 @@ generate_fragment(struct llvmpipe_context *lp,
c0, c1, c2,
step0_ptr, step1_ptr, step2_ptr);
- for(chan = 0; chan < NUM_CHANNELS; ++chan)
- fs_out_color[chan][i] = out_color[chan];
+ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++)
+ for(chan = 0; chan < NUM_CHANNELS; ++chan)
+ fs_out_color[cbuf][chan][i] = out_color[cbuf][chan];
}
sampler->destroy(sampler);
- /*
- * Convert the fs's output color and mask to fit to the blending type.
+ /* Loop over color outputs / color buffers to do blending.
*/
+ for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
+ LLVMValueRef color_ptr;
+ LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), cbuf, 0);
- for(chan = 0; chan < NUM_CHANNELS; ++chan) {
- lp_build_conv(builder, fs_type, blend_type,
- fs_out_color[chan], num_fs,
- &blend_in_color[chan], 1);
- lp_build_name(blend_in_color[chan], "color.%c", "rgba"[chan]);
+ /*
+ * Convert the fs's output color and mask to fit to the blending type.
+ */
+ for(chan = 0; chan < NUM_CHANNELS; ++chan) {
+ lp_build_conv(builder, fs_type, blend_type,
+ fs_out_color[cbuf][chan], num_fs,
+ &blend_in_color[chan], 1);
+ lp_build_name(blend_in_color[chan], "color%d.%c", cbuf, "rgba"[chan]);
+ }
+ lp_build_conv_mask(builder, fs_type, blend_type,
+ fs_mask, num_fs,
+ &blend_mask, 1);
+
+ color_ptr = LLVMBuildLoad(builder,
+ LLVMBuildGEP(builder, color_ptr_ptr, &index, 1, ""),
+ "");
+ lp_build_name(color_ptr, "color_ptr%d", cbuf);
+
+ /*
+ * Blending.
+ */
+ generate_blend(&key->blend,
+ builder,
+ blend_type,
+ context_ptr,
+ blend_mask,
+ blend_in_color,
+ color_ptr);
}
- lp_build_conv_mask(builder, fs_type, blend_type,
- fs_mask, num_fs,
- &blend_mask, 1);
-
- /*
- * Blending.
- */
-
- generate_blend(&key->blend,
- builder,
- blend_type,
- context_ptr,
- blend_mask,
- blend_in_color,
- color_ptr);
-
LLVMBuildRetVoid(builder);
LLVMDisposeBuilder(builder);
@@ -940,21 +958,27 @@ make_variant_key(struct llvmpipe_context *lp,
key->alpha.func = lp->depth_stencil->alpha.func;
/* alpha.ref_value is passed in jit_context */
- if(lp->framebuffer.cbufs[0]) {
+ if (lp->framebuffer.nr_cbufs) {
+ memcpy(&key->blend, lp->blend, sizeof key->blend);
+ }
+
+ key->nr_cbufs = lp->framebuffer.nr_cbufs;
+ for (i = 0; i < lp->framebuffer.nr_cbufs; i++) {
const struct util_format_description *format_desc;
unsigned chan;
- memcpy(&key->blend, lp->blend, sizeof key->blend);
-
- format_desc = util_format_description(lp->framebuffer.cbufs[0]->format);
+ format_desc = util_format_description(lp->framebuffer.cbufs[i]->format);
assert(format_desc->layout == UTIL_FORMAT_COLORSPACE_RGB ||
format_desc->layout == UTIL_FORMAT_COLORSPACE_SRGB);
- /* mask out color channels not present in the color buffer */
+ /* mask out color channels not present in the color buffer.
+ * Should be simple to incorporate per-cbuf writemasks:
+ */
for(chan = 0; chan < 4; ++chan) {
enum util_format_swizzle swizzle = format_desc->swizzle[chan];
- if(swizzle > 4)
- key->blend.colormask &= ~(1 << chan);
+
+ if(swizzle <= UTIL_FORMAT_SWIZZLE_W)
+ key->cbuf_blend[i].colormask |= (1 << chan);
}
}