static void
i830_set_draw_region(struct intel_context *intel,
- struct intel_region *color_region,
- struct intel_region *depth_region)
+ struct intel_region *color_regions[],
+ struct intel_region *depth_region,
+ GLuint num_regions)
{
struct i830_context *i830 = i830_context(&intel->ctx);
- i830_state_draw_region(intel, &i830->state, color_region, depth_region);
+ i830_state_draw_region(intel, &i830->state, color_regions[0], depth_region);
}
#if 0
static void
i915_set_draw_region(struct intel_context *intel,
- struct intel_region *color_region,
- struct intel_region *depth_region)
+ struct intel_region *color_regions[],
+ struct intel_region *depth_region,
+ GLuint num_regions)
{
struct i915_context *i915 = i915_context(&intel->ctx);
- i915_state_draw_region(intel, &i915->state, color_region, depth_region);
+ i915_state_draw_region(intel, &i915->state, color_regions[0], depth_region);
}
#define BRW_MAX_TEX_UNIT 8
-#define BRW_WM_MAX_SURF BRW_MAX_TEX_UNIT + 1
+#define BRW_WM_MAX_SURF BRW_MAX_TEX_UNIT + MAX_DRAW_BUFFERS
enum brw_cache_id {
BRW_CC_VP,
struct brw_tracked_state **atoms;
GLuint nr_atoms;
-
- struct intel_region *draw_region;
+ GLuint nr_draw_regions;
+ struct intel_region *draw_regions[MAX_DRAW_BUFFERS];
struct intel_region *depth_region;
} state;
struct gl_buffer_object *vbo;
struct intel_region *saved_draw_region;
+ GLuint saved_nr_draw_regions;
struct intel_region *saved_depth_region;
GLuint restore_draw_buffers[MAX_DRAW_BUFFERS];
return GL_TRUE;
}
- /* _NEW_BUFFERS
- */
- /* We can only handle a single draw buffer at the moment, and only as the
- * first color buffer.
- */
- if (fb->_NumColorDrawBuffers > 1) {
- DBG("FALLBACK: multiple color draw buffers\n");
- return GL_TRUE;
- }
-
/* _NEW_RENDERMODE
*
* XXX: need to save/restore RenderMode in metaops state, or
struct brw_context *brw = brw_context(&intel->ctx);
if (!brw->metaops.saved_draw_region) {
- brw->metaops.saved_draw_region = brw->state.draw_region;
+ brw->metaops.saved_draw_region = brw->state.draw_regions[0];
+ brw->metaops.saved_nr_draw_regions = brw->state.nr_draw_regions;
brw->metaops.saved_depth_region = brw->state.depth_region;
}
- brw->state.draw_region = draw_region;
+ brw->state.draw_regions[0] = draw_region;
+ brw->state.nr_draw_regions = 1;
brw->state.depth_region = depth_region;
if (intel->frame_buffer_texobj != NULL)
/* This works without adjusting refcounts. Fix later?
*/
- brw->metaops.saved_draw_region = brw->state.draw_region;
+ brw->metaops.saved_draw_region = brw->state.draw_regions[0];
+ brw->metaops.saved_nr_draw_regions = brw->state.nr_draw_regions;
brw->metaops.saved_depth_region = brw->state.depth_region;
brw->metaops.active = 1;
ctx->FragmentProgram.Current = brw->metaops.restore_fp;
- brw->state.draw_region = brw->metaops.saved_draw_region;
+ brw->state.draw_regions[0] = brw->metaops.saved_draw_region;
+ brw->state.nr_draw_regions = brw->metaops.saved_nr_draw_regions;
brw->state.depth_region = brw->metaops.saved_depth_region;
brw->metaops.saved_draw_region = NULL;
brw->metaops.saved_depth_region = NULL;
/* called from intelDrawBuffer()
*/
static void brw_set_draw_region( struct intel_context *intel,
- struct intel_region *draw_region,
- struct intel_region *depth_region)
+ struct intel_region *draw_regions[],
+ struct intel_region *depth_region,
+ GLuint num_regions)
{
struct brw_context *brw = brw_context(&intel->ctx);
-
+ int i;
if (brw->state.depth_region != depth_region)
brw->state.dirty.brw |= BRW_NEW_DEPTH_BUFFER;
-
- intel_region_release(&brw->state.draw_region);
+ for (i = 0; i < brw->state.nr_draw_regions; i++)
+ intel_region_release(&brw->state.draw_regions[i]);
intel_region_release(&brw->state.depth_region);
- intel_region_reference(&brw->state.draw_region, draw_region);
+ for (i = 0; i < num_regions; i++)
+ intel_region_reference(&brw->state.draw_regions[i], draw_regions[i]);
intel_region_reference(&brw->state.depth_region, depth_region);
+ brw->state.nr_draw_regions = num_regions;
}
c->fp = fp;
c->env_param = brw->intel.ctx.FragmentProgram.Parameters;
+ brw_init_compile(brw, &c->func);
if (brw_wm_is_glsl(&c->fp->program)) {
brw_wm_glsl_emit(brw, c);
} else {
*/
c->grf_limit = BRW_WM_MAX_GRF/2;
- /* This is where we start emitting gen4 code:
- */
- brw_init_compile(brw, &c->func);
-
brw_wm_pass2(c);
c->prog_data.total_grf = c->max_wm_grf;
GLuint writemask:4;
GLuint tex_unit:4; /* texture unit for TEX, TXD, TXP instructions */
GLuint tex_idx:3; /* TEXTURE_1D,2D,3D,CUBE,RECT_INDEX source target */
+ GLuint eot:1; /* End of thread indicator for FB_WRITE*/
+ GLuint target:10; /* target binding table index for FB_WRITE*/
};
retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
- inst->tex_unit + 1, /* surface */
+ inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
inst->tex_unit, /* sampler */
inst->writemask,
(shadow ?
retype(vec16(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(c->payload.depth[0].hw_reg, BRW_REGISTER_TYPE_UW),
- inst->tex_unit + 1, /* surface */
+ inst->tex_unit + MAX_DRAW_BUFFERS, /* surface */
inst->tex_unit, /* sampler */
inst->writemask,
BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
static void fire_fb_write( struct brw_wm_compile *c,
GLuint base_reg,
- GLuint nr )
+ GLuint nr,
+ GLuint target,
+ GLuint eot )
{
struct brw_compile *p = &c->func;
retype(vec16(brw_null_reg()), BRW_REGISTER_TYPE_UW),
base_reg,
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
- 0, /* render surface always 0 */
+ target,
nr,
0,
- 1);
+ eot);
}
static void emit_aa( struct brw_wm_compile *c,
static void emit_fb_write( struct brw_wm_compile *c,
struct brw_reg *arg0,
struct brw_reg *arg1,
- struct brw_reg *arg2)
+ struct brw_reg *arg2,
+ GLuint target,
+ GLuint eot)
{
struct brw_compile *p = &c->func;
GLuint nr = 2;
if (c->key.aa_dest_stencil_reg)
emit_aa(c, arg1, 2);
- fire_fb_write(c, 0, nr);
+ fire_fb_write(c, 0, nr, target, eot);
}
else {
struct brw_reg v1_null_ud = vec1(retype(brw_null_reg(), BRW_REGISTER_TYPE_UD));
jmp = brw_JMPI(p, ip, ip, brw_imm_w(0));
{
emit_aa(c, arg1, 2);
- fire_fb_write(c, 0, nr);
+ fire_fb_write(c, 0, nr, target, eot);
/* note - thread killed in subroutine */
}
brw_land_fwd_jump(p, jmp);
/* ELSE: Shuffle up one register to fill in the hole left for AA:
*/
- fire_fb_write(c, 1, nr-1);
+ fire_fb_write(c, 1, nr-1, target, eot);
}
}
break;
case WM_FB_WRITE:
- emit_fb_write(c, args[0], args[1], args[2]);
+ emit_fb_write(c, args[0], args[1], args[2], inst->target, inst->eot);
break;
/* Straightforward arithmetic:
struct prog_src_register outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_COLR);
struct prog_src_register payload_r0_depth = src_reg(PROGRAM_PAYLOAD, PAYLOAD_DEPTH);
struct prog_src_register outdepth = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DEPR);
+ GLuint i;
- emit_op(c,
- WM_FB_WRITE,
- dst_mask(dst_undef(),0),
- 0, 0, 0,
- outcolor,
- payload_r0_depth,
- outdepth);
+ struct prog_instruction *inst;
+ struct brw_context *brw = c->func.brw;
+
+ /* inst->Sampler is not used by backend,
+ use it for fb write target and eot */
+
+ inst = emit_op(c, WM_FB_WRITE, dst_mask(dst_undef(),0),
+ 0, 0, 0, outcolor, payload_r0_depth, outdepth);
+ inst->Sampler = (brw->state.nr_draw_regions > 1 ? 0: 1)|(0<<1);
+
+ if (brw->state.nr_draw_regions > 1) {
+ for (i = 0 ; i < brw->state.nr_draw_regions; i++) {
+ outcolor = src_reg(PROGRAM_OUTPUT, FRAG_RESULT_DATA0 + i);
+ inst = emit_op(c,
+ WM_FB_WRITE, dst_mask(dst_undef(),0), 0, 0, 0,
+ outcolor, payload_r0_depth, outdepth);
+ inst->Sampler = ((i == brw->state.nr_draw_regions - 1) ? 1: 0);
+ inst->Sampler |= (i<<1);
+ }
+ }
}
static void fire_fb_write( struct brw_wm_compile *c,
GLuint base_reg,
- GLuint nr )
+ GLuint nr,
+ GLuint target,
+ GLuint eot)
{
struct brw_compile *p = &c->func;
-
/* Pass through control information:
*/
/* mov (8) m1.0<1>:ud r1.0<8;8,1>:ud { Align1 NoMask } */
retype(vec8(brw_null_reg()), BRW_REGISTER_TYPE_UW),
base_reg,
retype(brw_vec8_grf(0, 0), BRW_REGISTER_TYPE_UW),
- 0, /* render surface always 0 */
+ target,
nr,
0,
- 1);
+ eot);
}
static void emit_fb_write(struct brw_wm_compile *c,
struct brw_compile *p = &c->func;
int nr = 2;
int channel;
- struct brw_reg src0;//, src1, src2, dst;
+ GLuint target, eot;
+ struct brw_reg src0;
/* Reserve a space for AA - may not be needed:
*/
nr += 2;
}
-
- fire_fb_write(c, 0, nr);
+ target = inst->Sampler >> 1;
+ eot = inst->Sampler & 1;
+ fire_fb_write(c, 0, nr, target, eot);
}
static void emit_pixel_w( struct brw_wm_compile *c,
retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(payload_reg, BRW_REGISTER_TYPE_UW),
- inst->TexSrcUnit + 1, /* surface */
+ inst->TexSrcUnit + MAX_DRAW_BUFFERS, /* surface */
inst->TexSrcUnit, /* sampler */
inst->DstReg.WriteMask,
BRW_SAMPLER_MESSAGE_SIMD16_SAMPLE_BIAS,
retype(vec8(dst[0]), BRW_REGISTER_TYPE_UW),
1,
retype(payload_reg, BRW_REGISTER_TYPE_UW),
- inst->TexSrcUnit + 1, /* surface */
+ inst->TexSrcUnit + MAX_DRAW_BUFFERS, /* surface */
inst->TexSrcUnit, /* sampler */
inst->DstReg.WriteMask,
BRW_SAMPLER_MESSAGE_SIMD8_SAMPLE,
}
static void brw_wm_emit_glsl(struct brw_context *brw, struct brw_wm_compile *c)
-
{
#define MAX_IFSN 32
#define MAX_LOOP_DEPTH 32
struct brw_compile *p = &c->func;
struct brw_indirect stack_index = brw_indirect(0, 0);
- brw_init_compile(brw, &c->func);
c->reg_index = 0;
prealloc_reg(c);
brw_set_compression_control(p, BRW_COMPRESSION_NONE);
out->saturate = (inst->SaturateMode != SATURATE_OFF);
out->tex_unit = inst->TexSrcUnit;
out->tex_idx = inst->TexSrcTarget;
+ out->eot = inst->Sampler & 1;
+ out->target = inst->Sampler>>1;
/* Args:
*/
key.depth = firstImage->Depth;
key.tiled = intelObj->mt->region->tiled;
- dri_bo_unreference(brw->wm.surf_bo[unit + 1]);
- brw->wm.surf_bo[unit + 1] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
+ dri_bo_unreference(brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS]);
+ brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
&key, sizeof(key),
&key.bo, 1,
NULL);
- if (brw->wm.surf_bo[unit + 1] == NULL)
- brw->wm.surf_bo[unit + 1] = brw_create_texture_surface(brw, &key);
+ if (brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] == NULL)
+ brw->wm.surf_bo[unit + MAX_DRAW_BUFFERS] = brw_create_texture_surface(brw, &key);
}
/**
*/
static void
brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
- unsigned int unit)
+ unsigned int unit, GLboolean cached)
{
dri_bo *region_bo = NULL;
GLboolean tiled, color_blend;
} key;
- memset(&key, 0, sizeof(key));
-
if (region != NULL) {
region_bo = region->buffer;
key.height = 1;
key.cpp = 4;
}
-
memcpy(key.color_mask, brw->attribs.Color->ColorMask,
sizeof(key.color_mask));
key.color_blend = (!brw->attribs.Color->_LogicOpEnabled &&
brw->attribs.Color->BlendEnabled);
dri_bo_unreference(brw->wm.surf_bo[unit]);
- brw->wm.surf_bo[unit] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
- &key, sizeof(key),
- ®ion_bo, 1,
- NULL);
+ brw->wm.surf_bo[unit] = NULL;
+ if (cached)
+ brw->wm.surf_bo[unit] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
+ &key, sizeof(key),
+ ®ion_bo, 1,
+ NULL);
+
if (brw->wm.surf_bo[unit] == NULL) {
struct brw_surface_state surf;
/* Key size will never match key size for textures, so we're safe. */
brw->wm.surf_bo[unit] = brw_upload_cache(&brw->cache, BRW_SS_SURFACE,
- &key, sizeof(key),
+ &key, sizeof(key),
®ion_bo, 1,
&surf, sizeof(surf),
NULL, NULL);
-
if (region_bo != NULL) {
dri_emit_reloc(brw->wm.surf_bo[unit],
DRM_BO_FLAG_MEM_TT |
NULL);
if (bind_bo == NULL) {
- GLuint data_size = brw->wm.nr_surfaces * 4;
+ GLuint data_size = brw->wm.nr_surfaces * sizeof(GLuint);
uint32_t *data = malloc(data_size);
int i;
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE,
0,
- i * 4,
+ i * sizeof(GLuint),
brw->wm.surf_bo[i]);
}
}
GLcontext *ctx = &brw->intel.ctx;
struct intel_context *intel = &brw->intel;
GLuint i;
+ if (brw->state.nr_draw_regions > 1) {
+ for (i = 0; i < brw->state.nr_draw_regions; i++)
+ brw_update_region_surface(brw, brw->state.draw_regions[i], i,
+ GL_FALSE);
+ }else
+ brw_update_region_surface(brw, brw->state.draw_regions[0], 0, GL_TRUE);
- brw_update_region_surface(brw, brw->state.draw_region, 0);
- brw->wm.nr_surfaces = 1;
+ brw->wm.nr_surfaces = MAX_DRAW_BUFFERS;
for (i = 0; i < BRW_MAX_TEX_UNIT; i++) {
struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[i];
if(texUnit->_ReallyEnabled &&
texUnit->_Current == intel->frame_buffer_texobj)
{
- dri_bo_unreference(brw->wm.surf_bo[i+1]);
- brw->wm.surf_bo[i+1] = brw->wm.surf_bo[0];
- dri_bo_reference(brw->wm.surf_bo[i+1]);
- brw->wm.nr_surfaces = i+2;
+ dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = brw->wm.surf_bo[0];
+ dri_bo_reference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
} else if (texUnit->_ReallyEnabled) {
brw_update_texture_surface(ctx, i);
- brw->wm.nr_surfaces = i+2;
+ brw->wm.nr_surfaces = i + MAX_DRAW_BUFFERS + 1;
} else {
- dri_bo_unreference(brw->wm.surf_bo[i+1]);
- brw->wm.surf_bo[i+1] = NULL;
+ dri_bo_unreference(brw->wm.surf_bo[i+MAX_DRAW_BUFFERS]);
+ brw->wm.surf_bo[i+MAX_DRAW_BUFFERS] = NULL;
}
}
default:
intelSetFrontClipRects(intel);
}
+
}
if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
{
struct intel_context *intel = intel_context(ctx);
- struct intel_region *colorRegion, *depthRegion = NULL;
+ struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
int front = 0; /* drawing to front color buffer? */
/*
* How many color buffers are we drawing into?
*/
- if (fb->_NumColorDrawBuffers != 1) {
- /* writing to 0 or 2 or 4 color buffers */
- /*_mesa_debug(ctx, "Software rendering\n");*/
+ if (fb->_NumColorDrawBuffers == 0) {
+ /* writing to 0 */
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
- colorRegion = NULL;
+ colorRegions[0] = NULL;
if (fb->Name != 0)
intelSetRenderbufferClipRects(intel);
+ } else if (fb->_NumColorDrawBuffers > 1) {
+ int i;
+ struct intel_renderbuffer *irb;
+ FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
+
+ if (fb->Name != 0)
+ intelSetRenderbufferClipRects(intel);
+ for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
+ colorRegions[i] = (irb && irb->region) ? irb->region : NULL;
+ }
}
else {
/* draw to exactly one color buffer */
/* drawing to window system buffer */
if (front) {
intelSetFrontClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
+ colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
}
else {
intelSetBackClipRects(intel);
- colorRegion = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
+ colorRegions[0]= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
}
}
else {
struct intel_renderbuffer *irb;
intelSetRenderbufferClipRects(intel);
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
- colorRegion = (irb && irb->region) ? irb->region : NULL;
+ colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
}
}
else
ctx->NewState |= _NEW_POLYGON;
- if (!colorRegion) {
+ if (!colorRegions[0]) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
}
else {
ctx->NewState |= _NEW_DEPTH;
}
- intel->vtbl.set_draw_region(intel, colorRegion, depthRegion);
+ intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
+ fb->_NumColorDrawBuffers);
/* update viewport since it depends on window size */
if (ctx->Driver.Viewport) {
void (*render_start) (struct intel_context * intel);
void (*render_prevalidate) (struct intel_context * intel);
void (*set_draw_region) (struct intel_context * intel,
- struct intel_region * draw_region,
- struct intel_region * depth_region);
+ struct intel_region * draw_regions[],
+ struct intel_region * depth_region,
+ GLuint num_regions);
GLuint (*flush_cmd) (void);
void (*emit_flush) (struct intel_context *intel, GLuint unused);