st/nine: Implement fallback behaviour when rts and ds don't match

This seems to be the behaviour on Win. Previous behaviour led
to different issues depending on the driver.

Reviewed-by: Tiziano Bacocco <tizbac2@gmail.com>
Signed-off-by: Axel Davy <axel.davy@ens.fr>
This commit is contained in:
Axel Davy
2015-01-18 11:05:34 +01:00
parent 8b901e3011
commit dfe5e84e74

View File

@@ -44,7 +44,10 @@ update_framebuffer(struct NineDevice9 *device)
struct nine_state *state = &device->state; struct nine_state *state = &device->state;
struct pipe_framebuffer_state *fb = &device->state.fb; struct pipe_framebuffer_state *fb = &device->state.fb;
unsigned i; unsigned i;
unsigned w = 0, h = 0; /* no surface can have width or height 0 */ struct NineSurface9 *rt0 = state->rt[0];
unsigned w = rt0->desc.Width;
unsigned h = rt0->desc.Height;
D3DMULTISAMPLE_TYPE nr_samples = rt0->desc.MultiSampleType;
const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; const int sRGB = state->rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0;
@@ -53,19 +56,31 @@ update_framebuffer(struct NineDevice9 *device)
state->rt_mask = 0x0; state->rt_mask = 0x0;
fb->nr_cbufs = 0; fb->nr_cbufs = 0;
/* all render targets must have the same size and the depth buffer must be
* bigger. Multisample has to match, according to spec. But some apps do
* things wrong there, and no error is returned. The behaviour they get
* apparently is that depth buffer is disabled if it doesn't match.
* Surely the same for render targets. */
/* Special case: D3DFMT_NULL is used to bound no real render target,
* but render to depth buffer. We have to not take into account the render
* target info. TODO: know what should happen when there are several render targers
* and the first one is D3DFMT_NULL */
if (rt0->desc.Format == D3DFMT_NULL && state->ds) {
w = state->ds->desc.Width;
h = state->ds->desc.Height;
nr_samples = state->ds->desc.MultiSampleType;
}
for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) {
if (state->rt[i] && state->rt[i]->desc.Format != D3DFMT_NULL) { struct NineSurface9 *rt = state->rt[i];
struct NineSurface9 *rt = state->rt[i];
if (rt && rt->desc.Format != D3DFMT_NULL && rt->desc.Width == w &&
rt->desc.Height == h && rt->desc.MultiSampleType == nr_samples) {
fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB); fb->cbufs[i] = NineSurface9_GetSurface(rt, sRGB);
state->rt_mask |= 1 << i; state->rt_mask |= 1 << i;
fb->nr_cbufs = i + 1; fb->nr_cbufs = i + 1;
if (w) {
w = MIN2(w, rt->desc.Width);
h = MIN2(h, rt->desc.Height);
} else {
w = rt->desc.Width;
h = rt->desc.Height;
}
if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) { if (unlikely(rt->desc.Usage & D3DUSAGE_AUTOGENMIPMAP)) {
assert(rt->texture == D3DRTYPE_TEXTURE || assert(rt->texture == D3DRTYPE_TEXTURE ||
rt->texture == D3DRTYPE_CUBETEXTURE); rt->texture == D3DRTYPE_CUBETEXTURE);
@@ -79,15 +94,10 @@ update_framebuffer(struct NineDevice9 *device)
} }
} }
if (state->ds) { if (state->ds && state->ds->desc.Width >= w &&
state->ds->desc.Height >= h &&
state->ds->desc.MultiSampleType == nr_samples) {
fb->zsbuf = NineSurface9_GetSurface(state->ds, 0); fb->zsbuf = NineSurface9_GetSurface(state->ds, 0);
if (w) {
w = MIN2(w, state->ds->desc.Width);
h = MIN2(h, state->ds->desc.Height);
} else {
w = state->ds->desc.Width;
h = state->ds->desc.Height;
}
} else { } else {
fb->zsbuf = NULL; fb->zsbuf = NULL;
} }