From dfe5e84e74b184748c48cf07d58c79c2c5685a2d Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Sun, 18 Jan 2015 11:05:34 +0100 Subject: [PATCH] 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 Signed-off-by: Axel Davy --- src/gallium/state_trackers/nine/nine_state.c | 46 ++++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index 1e533354d64..02fef9a381d 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -44,7 +44,10 @@ update_framebuffer(struct NineDevice9 *device) struct nine_state *state = &device->state; struct pipe_framebuffer_state *fb = &device->state.fb; 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; @@ -53,19 +56,31 @@ update_framebuffer(struct NineDevice9 *device) state->rt_mask = 0x0; 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) { - 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); state->rt_mask |= 1 << i; 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)) { assert(rt->texture == D3DRTYPE_TEXTURE || 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); - 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 { fb->zsbuf = NULL; } -- 2.30.2