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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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] =
|
||||
|
||||
@@ -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 *,
|
||||
|
||||
Reference in New Issue
Block a user