From f72d8719ebecce0937087a56eec24a51bea9e27a Mon Sep 17 00:00:00 2001 From: Axel Davy Date: Sat, 15 Oct 2016 13:52:04 +0200 Subject: [PATCH] st/nine: Move core of device clear to nine_state Part of the refactor to move all gallium calls to nine_state.c, and have all internal states required for those calls in nine_context. Signed-off-by: Axel Davy --- src/gallium/state_trackers/nine/device9.c | 130 +-------------- src/gallium/state_trackers/nine/nine_state.c | 166 +++++++++++++++++-- src/gallium/state_trackers/nine/nine_state.h | 5 +- 3 files changed, 160 insertions(+), 141 deletions(-) diff --git a/src/gallium/state_trackers/nine/device9.c b/src/gallium/state_trackers/nine/device9.c index be1e7dc866e..7e6d3b35148 100644 --- a/src/gallium/state_trackers/nine/device9.c +++ b/src/gallium/state_trackers/nine/device9.c @@ -1927,16 +1927,7 @@ NineDevice9_Clear( struct NineDevice9 *This, float Z, DWORD Stencil ) { - const int sRGB = This->state.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; - struct pipe_surface *cbuf, *zsbuf; - struct pipe_context *pipe = This->pipe; struct NineSurface9 *zsbuf_surf = This->state.ds; - struct NineSurface9 *rt; - unsigned bufs = 0; - unsigned r, i; - union pipe_color_union rgba; - unsigned rt_mask = 0; - D3DRECT rect; DBG("This=%p Count=%u pRects=%p Flags=%x Color=%08x Z=%f Stencil=%x\n", This, Count, pRects, Flags, Color, Z, Stencil); @@ -1957,126 +1948,7 @@ NineDevice9_Clear( struct NineDevice9 *This, Count = 0; #endif - nine_update_state_framebuffer_clear(This); - - if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; - /* Ignore Z buffer if not bound */ - if (This->context.pipe.fb.zsbuf != NULL) { - if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; - if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; - } - if (!bufs) - return D3D_OK; - d3dcolor_to_pipe_color_union(&rgba, Color); - - rect.x1 = This->state.viewport.X; - rect.y1 = This->state.viewport.Y; - rect.x2 = This->state.viewport.Width + rect.x1; - rect.y2 = This->state.viewport.Height + rect.y1; - - /* Both rectangles apply, which is weird, but that's D3D9. */ - if (This->state.rs[D3DRS_SCISSORTESTENABLE]) { - rect.x1 = MAX2(rect.x1, This->state.scissor.minx); - rect.y1 = MAX2(rect.y1, This->state.scissor.miny); - rect.x2 = MIN2(rect.x2, This->state.scissor.maxx); - rect.y2 = MIN2(rect.y2, This->state.scissor.maxy); - } - - if (Count) { - /* Maybe apps like to specify a large rect ? */ - if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && - pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { - DBG("First rect covers viewport.\n"); - Count = 0; - pRects = NULL; - } - } - - if (rect.x1 >= This->context.pipe.fb.width || rect.y1 >= This->context.pipe.fb.height) - return D3D_OK; - - for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { - if (This->state.rt[i] && This->state.rt[i]->desc.Format != D3DFMT_NULL) - rt_mask |= 1 << i; - } - - /* fast path, clears everything at once */ - if (!Count && - (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == This->context.rt_mask)) && - rect.x1 == 0 && rect.y1 == 0 && - /* Case we clear only render target. Check clear region vs rt. */ - ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && - rect.x2 >= This->context.pipe.fb.width && - rect.y2 >= This->context.pipe.fb.height) || - /* Case we clear depth buffer (and eventually rt too). - * depth buffer size is always >= rt size. Compare to clear region */ - ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && - rect.x2 >= zsbuf_surf->desc.Width && - rect.y2 >= zsbuf_surf->desc.Height))) { - DBG("Clear fast path\n"); - pipe->clear(pipe, bufs, &rgba, Z, Stencil); - return D3D_OK; - } - - if (!Count) { - Count = 1; - pRects = ▭ - } - - for (i = 0; i < This->caps.NumSimultaneousRTs; ++i) { - rt = This->state.rt[i]; - if (!rt || rt->desc.Format == D3DFMT_NULL || - !(bufs & PIPE_CLEAR_COLOR)) - continue; /* save space, compiler should hoist this */ - cbuf = NineSurface9_GetSurface(rt, sRGB); - for (r = 0; r < Count; ++r) { - /* Don't trust users to pass these in the right order. */ - unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); - unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); - unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); - unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); -#ifndef NINE_LAX - /* Drop negative rectangles (like wine expects). */ - if (pRects[r].x1 > pRects[r].x2) continue; - if (pRects[r].y1 > pRects[r].y2) continue; -#endif - - x1 = MAX2(x1, rect.x1); - y1 = MAX2(y1, rect.y1); - x2 = MIN3(x2, rect.x2, rt->desc.Width); - y2 = MIN3(y2, rect.y2, rt->desc.Height); - - DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); - pipe->clear_render_target(pipe, cbuf, &rgba, - x1, y1, x2 - x1, y2 - y1, false); - } - } - if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL)) - return D3D_OK; - - bufs &= PIPE_CLEAR_DEPTHSTENCIL; - - for (r = 0; r < Count; ++r) { - unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); - unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); - unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); - unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); -#ifndef NINE_LAX - /* Drop negative rectangles. */ - if (pRects[r].x1 > pRects[r].x2) continue; - if (pRects[r].y1 > pRects[r].y2) continue; -#endif - - x1 = MIN2(x1, rect.x1); - y1 = MIN2(y1, rect.y1); - x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width); - y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height); - - zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0); - assert(zsbuf); - pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil, - x1, y1, x2 - x1, y2 - y1, false); - } + nine_context_clear_fb(This, Count, pRects, Flags, Color, Z, Stencil); return D3D_OK; } diff --git a/src/gallium/state_trackers/nine/nine_state.c b/src/gallium/state_trackers/nine/nine_state.c index aabe1805e34..46b301d8c00 100644 --- a/src/gallium/state_trackers/nine/nine_state.c +++ b/src/gallium/state_trackers/nine/nine_state.c @@ -1006,17 +1006,6 @@ update_managed_buffers(struct NineDevice9 *device) } } -void -nine_update_state_framebuffer_clear(struct NineDevice9 *device) -{ - struct nine_state *state = &device->state; - - validate_textures(device); - - if (state->changed.group & NINE_STATE_FB) - update_framebuffer(device, TRUE); -} - boolean nine_update_state(struct NineDevice9 *device) { @@ -1132,6 +1121,161 @@ nine_update_state(struct NineDevice9 *device) return TRUE; } +static void +nine_update_state_framebuffer_clear(struct NineDevice9 *device) +{ + struct nine_state *state = &device->state; + + validate_textures(device); + + if (state->changed.group & NINE_STATE_FB) + update_framebuffer(device, TRUE); +} + +/* Checks were already done before the call */ +void +nine_context_clear_fb(struct NineDevice9 *device, + DWORD Count, + const D3DRECT *pRects, + DWORD Flags, + D3DCOLOR Color, + float Z, + DWORD Stencil) +{ + const int sRGB = device->state.rs[D3DRS_SRGBWRITEENABLE] ? 1 : 0; + struct pipe_surface *cbuf, *zsbuf; + struct pipe_context *pipe = device->pipe; + struct NineSurface9 *zsbuf_surf = device->state.ds; + struct NineSurface9 *rt; + unsigned bufs = 0; + unsigned r, i; + union pipe_color_union rgba; + unsigned rt_mask = 0; + D3DRECT rect; + + nine_update_state_framebuffer_clear(device); + + if (Flags & D3DCLEAR_TARGET) bufs |= PIPE_CLEAR_COLOR; + /* Ignore Z buffer if not bound */ + if (device->context.pipe.fb.zsbuf != NULL) { + if (Flags & D3DCLEAR_ZBUFFER) bufs |= PIPE_CLEAR_DEPTH; + if (Flags & D3DCLEAR_STENCIL) bufs |= PIPE_CLEAR_STENCIL; + } + if (!bufs) + return; + d3dcolor_to_pipe_color_union(&rgba, Color); + + rect.x1 = device->state.viewport.X; + rect.y1 = device->state.viewport.Y; + rect.x2 = device->state.viewport.Width + rect.x1; + rect.y2 = device->state.viewport.Height + rect.y1; + + /* Both rectangles apply, which is weird, but that's D3D9. */ + if (device->state.rs[D3DRS_SCISSORTESTENABLE]) { + rect.x1 = MAX2(rect.x1, device->state.scissor.minx); + rect.y1 = MAX2(rect.y1, device->state.scissor.miny); + rect.x2 = MIN2(rect.x2, device->state.scissor.maxx); + rect.y2 = MIN2(rect.y2, device->state.scissor.maxy); + } + + if (Count) { + /* Maybe apps like to specify a large rect ? */ + if (pRects[0].x1 <= rect.x1 && pRects[0].x2 >= rect.x2 && + pRects[0].y1 <= rect.y1 && pRects[0].y2 >= rect.y2) { + DBG("First rect covers viewport.\n"); + Count = 0; + pRects = NULL; + } + } + + if (rect.x1 >= device->context.pipe.fb.width || rect.y1 >= device->context.pipe.fb.height) + return; + + for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { + if (device->state.rt[i] && device->state.rt[i]->desc.Format != D3DFMT_NULL) + rt_mask |= 1 << i; + } + + /* fast path, clears everything at once */ + if (!Count && + (!(bufs & PIPE_CLEAR_COLOR) || (rt_mask == device->context.rt_mask)) && + rect.x1 == 0 && rect.y1 == 0 && + /* Case we clear only render target. Check clear region vs rt. */ + ((!(bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && + rect.x2 >= device->context.pipe.fb.width && + rect.y2 >= device->context.pipe.fb.height) || + /* Case we clear depth buffer (and eventually rt too). + * depth buffer size is always >= rt size. Compare to clear region */ + ((bufs & (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)) && + rect.x2 >= zsbuf_surf->desc.Width && + rect.y2 >= zsbuf_surf->desc.Height))) { + DBG("Clear fast path\n"); + pipe->clear(pipe, bufs, &rgba, Z, Stencil); + return; + } + + if (!Count) { + Count = 1; + pRects = ▭ + } + + for (i = 0; i < device->caps.NumSimultaneousRTs; ++i) { + rt = device->state.rt[i]; + if (!rt || rt->desc.Format == D3DFMT_NULL || + !(bufs & PIPE_CLEAR_COLOR)) + continue; /* save space, compiler should hoist this */ + cbuf = NineSurface9_GetSurface(rt, sRGB); + for (r = 0; r < Count; ++r) { + /* Don't trust users to pass these in the right order. */ + unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); + unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); + unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); + unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); +#ifndef NINE_LAX + /* Drop negative rectangles (like wine expects). */ + if (pRects[r].x1 > pRects[r].x2) continue; + if (pRects[r].y1 > pRects[r].y2) continue; +#endif + + x1 = MAX2(x1, rect.x1); + y1 = MAX2(y1, rect.y1); + x2 = MIN3(x2, rect.x2, rt->desc.Width); + y2 = MIN3(y2, rect.y2, rt->desc.Height); + + DBG("Clearing (%u..%u)x(%u..%u)\n", x1, x2, y1, y2); + pipe->clear_render_target(pipe, cbuf, &rgba, + x1, y1, x2 - x1, y2 - y1, false); + } + } + if (!(bufs & PIPE_CLEAR_DEPTHSTENCIL)) + return; + + bufs &= PIPE_CLEAR_DEPTHSTENCIL; + + for (r = 0; r < Count; ++r) { + unsigned x1 = MIN2(pRects[r].x1, pRects[r].x2); + unsigned y1 = MIN2(pRects[r].y1, pRects[r].y2); + unsigned x2 = MAX2(pRects[r].x1, pRects[r].x2); + unsigned y2 = MAX2(pRects[r].y1, pRects[r].y2); +#ifndef NINE_LAX + /* Drop negative rectangles. */ + if (pRects[r].x1 > pRects[r].x2) continue; + if (pRects[r].y1 > pRects[r].y2) continue; +#endif + + x1 = MIN2(x1, rect.x1); + y1 = MIN2(y1, rect.y1); + x2 = MIN3(x2, rect.x2, zsbuf_surf->desc.Width); + y2 = MIN3(y2, rect.y2, zsbuf_surf->desc.Height); + + zsbuf = NineSurface9_GetSurface(zsbuf_surf, 0); + assert(zsbuf); + pipe->clear_depth_stencil(pipe, zsbuf, bufs, Z, Stencil, + x1, y1, x2 - x1, y2 - y1, false); + } + return; +} + /* State defaults */ static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] = diff --git a/src/gallium/state_trackers/nine/nine_state.h b/src/gallium/state_trackers/nine/nine_state.h index 885ea6b0ae9..bb1064a213f 100644 --- a/src/gallium/state_trackers/nine/nine_state.h +++ b/src/gallium/state_trackers/nine/nine_state.h @@ -266,8 +266,11 @@ extern const uint32_t nine_render_states_vertex[(NINED3DRS_COUNT + 31) / 32]; struct NineDevice9; -void nine_update_state_framebuffer_clear(struct NineDevice9 *); boolean nine_update_state(struct NineDevice9 *); +void +nine_context_clear_fb(struct NineDevice9 *device, DWORD Count, + const D3DRECT *pRects, DWORD Flags, + D3DCOLOR Color, float Z, DWORD Stencil); void nine_state_restore_non_cso(struct NineDevice9 *device); void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *, -- 2.30.2