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 <axel.davy@ens.fr>
This commit is contained in:
Axel Davy
2016-10-15 13:52:04 +02:00
parent 1b24d5e1f5
commit f72d8719eb
3 changed files with 160 additions and 141 deletions
+1 -129
View File
@@ -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 = &rect;
}
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;
}
+155 -11
View File
@@ -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 = &rect;
}
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] =
+4 -1
View File
@@ -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 *,