i915: Add support for HW rendering with no color draw buffer.

This is useful for shadow map generation.  Tested with glsl-bug-22603,
which rendered the depth textures with fallbacks before.

Acked-by: Chad Versace <chad@chad-versace.us>
This commit is contained in:
Eric Anholt 2011-07-12 10:20:53 -07:00
parent debf751aea
commit af9548d335

View file

@ -318,7 +318,8 @@ i915_emit_state(struct intel_context *intel)
aper_array[aper_count++] = intel->batch.bo;
if (dirty & I915_UPLOAD_BUFFERS) {
aper_array[aper_count++] = state->draw_region->buffer;
if (state->draw_region)
aper_array[aper_count++] = state->draw_region->buffer;
if (state->depth_region)
aper_array[aper_count++] = state->depth_region->buffer;
}
@ -388,23 +389,27 @@ i915_emit_state(struct intel_context *intel)
if (INTEL_DEBUG & DEBUG_STATE)
fprintf(stderr, "I915_UPLOAD_BUFFERS:\n");
count = 14;
count = 17;
if (state->Buffer[I915_DESTREG_DRAWRECT0] != MI_NOOP)
count++;
if (state->depth_region)
count += 3;
BEGIN_BATCH(count);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_CBUFADDR1]);
OUT_RELOC(state->draw_region->buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
if (state->draw_region) {
OUT_RELOC(state->draw_region->buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
} else {
OUT_BATCH(0);
}
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
if (state->depth_region) {
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR0]);
OUT_BATCH(state->Buffer[I915_DESTREG_DBUFADDR1]);
OUT_RELOC(state->depth_region->buffer,
I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0);
} else {
OUT_BATCH(0);
}
OUT_BATCH(state->Buffer[I915_DESTREG_DV0]);
@ -532,6 +537,12 @@ i915_set_buf_info_for_region(uint32_t *state, struct intel_region *region,
if (region->tiling == I915_TILING_Y)
state[1] |= BUF_3D_TILE_WALK_Y;
}
} else {
/* Fill in a default pitch, since 0 is invalid. We'll be
* setting the buffer offset to 0 and not referencing the
* buffer, so the pitch could really be any valid value.
*/
state[1] |= BUF_3D_PITCH(4096);
}
}
@ -596,6 +607,8 @@ i915_set_draw_region(struct intel_context *intel,
LOD_PRECLAMP_OGL | TEX_DEFAULT_COLOR_OGL);
if (irb != NULL) {
value |= i915_render_target_format_for_mesa_format[irb->Base.Format];
} else {
value |= DV_PF_8888;
}
/* This isn't quite safe, thus being hidden behind an option. When changing
@ -670,6 +683,20 @@ i915_set_draw_region(struct intel_context *intel,
I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
}
static void
i915_update_color_write_enable(struct i915_context *i915, bool enable)
{
uint32_t dw = i915->state.Ctx[I915_CTXREG_LIS6];
if (enable)
dw |= S6_COLOR_WRITE_ENABLE;
else
dw &= ~S6_COLOR_WRITE_ENABLE;
if (dw != i915->state.Ctx[I915_CTXREG_LIS6]) {
I915_STATECHANGE(i915, I915_UPLOAD_CTX);
i915->state.Ctx[I915_CTXREG_LIS6] = dw;
}
}
/**
* Update the hardware state for drawing into a window or framebuffer object.
*
@ -683,9 +710,10 @@ i915_set_draw_region(struct intel_context *intel,
static void
i915_update_draw_buffer(struct intel_context *intel)
{
struct i915_context *i915 = (struct i915_context *)intel;
struct gl_context *ctx = &intel->ctx;
struct gl_framebuffer *fb = ctx->DrawBuffer;
struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
struct intel_region *colorRegion = NULL, *depthRegion = NULL;
struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
bool fb_has_hiz = intel_framebuffer_has_hiz(fb);
@ -717,49 +745,19 @@ i915_update_draw_buffer(struct intel_context *intel)
/* How many color buffers are we drawing into?
*
* If there are zero buffers or the buffer is too big, don't configure any
* regions for hardware drawing. We'll fallback to software below. Not
* having regions set makes some of the software fallback paths faster.
* If there is more than one drawbuffer (GL_FRONT_AND_BACK), or the
* drawbuffers are too big, we have to fallback to software.
*/
if ((fb->Width > ctx->Const.MaxRenderbufferSize)
|| (fb->Height > ctx->Const.MaxRenderbufferSize)
|| (fb->_NumColorDrawBuffers == 0)) {
/* writing to 0 */
colorRegions[0] = NULL;
}
else if (fb->_NumColorDrawBuffers > 1) {
int i;
struct intel_renderbuffer *irb;
for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
colorRegions[i] = irb ? irb->region : NULL;
}
}
else {
/* Get the intel_renderbuffer for the single colorbuffer we're drawing
* into.
*/
if (fb->Name == 0) {
/* drawing to window system buffer */
if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT)
colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
else
colorRegions[0] = intel_get_rb_region(fb, BUFFER_BACK_LEFT);
}
else {
/* drawing to user-created FBO */
struct intel_renderbuffer *irb;
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
}
}
if (!colorRegions[0]) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
}
else {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
|| (fb->Height > ctx->Const.MaxRenderbufferSize)) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, true);
} else if (fb->_NumColorDrawBuffers > 1) {
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, true);
} else {
struct intel_renderbuffer *irb;
irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
colorRegion = irb ? irb->region : NULL;
FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, false);
}
/* Check for depth fallback. */
@ -801,7 +799,9 @@ i915_update_draw_buffer(struct intel_context *intel)
ctx->Driver.Enable(ctx, GL_DEPTH_TEST, ctx->Depth.Test);
ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled);
intel->vtbl.set_draw_region(intel, colorRegions, depthRegion,
i915_update_color_write_enable(i915, colorRegion != NULL);
intel->vtbl.set_draw_region(intel, &colorRegion, depthRegion,
fb->_NumColorDrawBuffers);
intel->NewGLState |= _NEW_BUFFERS;