Commit d321959d authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Move FBO application into a state handler.

parent 1aa85c96
......@@ -2161,79 +2161,96 @@ BOOL context_apply_clear_state(struct wined3d_context *context, struct wined3d_d
return TRUE;
}
/* Context activation is done by the caller. */
BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device)
static inline DWORD find_draw_buffers_mask(struct wined3d_context *context, struct wined3d_device *device)
{
const struct StateEntry *state_table = device->StateTable;
const struct wined3d_fb_state *fb = &device->fb;
struct wined3d_shader *ps = device->stateBlock->state.pixel_shader;
struct wined3d_surface **rts = device->fb.render_targets;
DWORD rt_mask, rt_mask_bits;
unsigned int i;
DWORD rt_mask;
if (!context_validate_rt_config(context->gl_info->limits.buffers,
fb->render_targets, fb->depth_stencil))
return FALSE;
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return context_generate_rt_mask_no_fbo(device, rts[0]);
else if (!context->render_offscreen) return context_generate_rt_mask_from_surface(rts[0]);
/* Preload resources before FBO setup. Texture preload in particular may
* result in changes to the current FBO, due to using e.g. FBO blits for
* updating a resource location. */
device_update_tex_unit_map(device);
device_preload_textures(device);
if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
device_update_stream_info(device, context->gl_info);
rt_mask = ps ? ps->reg_maps.rt_mask : 1;
rt_mask &= device->valid_rt_mask;
rt_mask_bits = rt_mask;
i = 0;
while (rt_mask_bits)
{
rt_mask_bits &= ~(1 << i);
if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
rt_mask &= ~(1 << i);
i++;
}
return rt_mask;
}
/* GL locking and context activation are done by the caller */
void context_state_fb(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context)
{
struct wined3d_device *device = stateblock->device;
const struct wined3d_fb_state *fb = &device->fb;
DWORD rt_mask = find_draw_buffers_mask(context, device);
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{
context_validate_onscreen_formats(device, context, fb->depth_stencil);
if (!context->render_offscreen)
{
ENTER_GL();
context_apply_fbo_state(context, GL_FRAMEBUFFER, NULL, NULL, SFLAG_INDRAWABLE);
LEAVE_GL();
rt_mask = context_generate_rt_mask_from_surface(fb->render_targets[0]);
}
else
{
const struct wined3d_shader *ps = device->stateBlock->state.pixel_shader;
DWORD rt_mask_bits;
struct wined3d_surface **rts = fb->render_targets;
ENTER_GL();
context_apply_fbo_state(context, GL_FRAMEBUFFER, fb->render_targets, fb->depth_stencil, SFLAG_INTEXTURE);
glReadBuffer(GL_NONE);
checkGLcall("glReadBuffer");
LEAVE_GL();
rt_mask = ps ? ps->reg_maps.rt_mask : 1;
rt_mask &= device->valid_rt_mask;
rt_mask_bits = rt_mask;
i = 0;
while (rt_mask_bits)
{
rt_mask_bits &= ~(1 << i);
if (!rts[i] || rts[i]->resource.format->id == WINED3DFMT_NULL)
rt_mask &= ~(1 << i);
i++;
}
}
}
else
{
rt_mask = context_generate_rt_mask_no_fbo(device, fb->render_targets[0]);
}
ENTER_GL();
if (context->draw_buffers_mask != rt_mask)
{
context_apply_draw_buffers(context, rt_mask);
context->draw_buffers_mask = rt_mask;
}
}
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
/* GL locking and context activation are done by the caller */
void context_state_drawbuf(DWORD state, struct wined3d_stateblock *stateblock, struct wined3d_context *context)
{
DWORD rt_mask;
struct wined3d_device *device = stateblock->device;
if (isStateDirty(context, STATE_FRAMEBUFFER)) return;
rt_mask = find_draw_buffers_mask(context, device);
if (context->draw_buffers_mask != rt_mask)
{
context_check_fbo_status(context, GL_FRAMEBUFFER);
context_apply_draw_buffers(context, rt_mask);
context->draw_buffers_mask = rt_mask;
}
}
/* Context activation is done by the caller. */
BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_device *device)
{
const struct StateEntry *state_table = device->StateTable;
const struct wined3d_fb_state *fb = &device->fb;
unsigned int i;
if (!context_validate_rt_config(context->gl_info->limits.buffers,
fb->render_targets, fb->depth_stencil))
return FALSE;
/* Preload resources before FBO setup. Texture preload in particular may
* result in changes to the current FBO, due to using e.g. FBO blits for
* updating a resource location. */
device_update_tex_unit_map(device);
device_preload_textures(device);
if (isStateDirty(context, STATE_VDECL) || isStateDirty(context, STATE_STREAMSRC))
device_update_stream_info(device, context->gl_info);
ENTER_GL();
if (context->last_was_blit)
{
device->frag_pipe->enable_extension(TRUE);
......@@ -2247,6 +2264,15 @@ BOOL context_apply_draw_state(struct wined3d_context *context, struct wined3d_de
context->isStateDirty[idx] &= ~(1 << shift);
state_table[rep].apply(rep, device->stateBlock, context);
}
/* FIXME */
state_table[STATE_FRAMEBUFFER].apply(STATE_FRAMEBUFFER, device->stateBlock, context);
if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
{
context_check_fbo_status(context, GL_FRAMEBUFFER);
}
LEAVE_GL();
context->numDirtyEntries = 0; /* This makes the whole list clean */
context->last_was_blit = FALSE;
......
......@@ -5098,6 +5098,8 @@ const struct StateEntryTemplate misc_state_template[] = {
{ STATE_SAMPLER(19), /* Vertex sampler 3 */ { STATE_SAMPLER(19), sampler }, WINED3D_GL_EXT_NONE },
{ STATE_BASEVERTEXINDEX, { STATE_BASEVERTEXINDEX, state_nop, }, ARB_DRAW_ELEMENTS_BASE_VERTEX },
{ STATE_BASEVERTEXINDEX, { STATE_STREAMSRC, NULL, }, WINED3D_GL_EXT_NONE },
{ STATE_FRAMEBUFFER, { STATE_FRAMEBUFFER, context_state_fb }, WINED3D_GL_EXT_NONE },
{ STATE_PIXELSHADER, { STATE_PIXELSHADER, context_state_drawbuf},WINED3D_GL_EXT_NONE },
{0 /* Terminate */, { 0, 0 }, WINED3D_GL_EXT_NONE },
};
......@@ -5761,6 +5763,7 @@ static void validate_state_table(struct StateEntry *state_table)
STATE_FRONTFACE,
STATE_POINTSPRITECOORDORIGIN,
STATE_BASEVERTEXINDEX,
STATE_FRAMEBUFFER
};
unsigned int i, current;
......
......@@ -2249,6 +2249,8 @@ const char *debug_d3dstate(DWORD state)
return "STATE_POINTSPRITECOORDORIGIN";
if (STATE_IS_BASEVERTEXINDEX(state))
return "STATE_BASEVERTEXINDEX";
if (STATE_IS_FRAMEBUFFER(state))
return "STATE_FRAMEBUFFER";
return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
}
......
......@@ -998,7 +998,10 @@ extern glMultiTexCoordFunc multi_texcoord_funcs[WINED3D_FFP_EMIT_COUNT] DECLSPEC
#define STATE_BASEVERTEXINDEX (STATE_POINTSPRITECOORDORIGIN + 1)
#define STATE_IS_BASEVERTEXINDEX(a) ((a) == STATE_BASEVERTEXINDEX)
#define STATE_HIGHEST (STATE_BASEVERTEXINDEX)
#define STATE_FRAMEBUFFER (STATE_BASEVERTEXINDEX + 1)
#define STATE_IS_FRAMEBUFFER(a) ((a) == STATE_FRAMEBUFFER)
#define STATE_HIGHEST (STATE_FRAMEBUFFER)
enum fogsource {
FOGSOURCE_FFP,
......@@ -1243,6 +1246,10 @@ void context_resource_unloaded(const struct wined3d_device *device,
BOOL context_set_current(struct wined3d_context *ctx) DECLSPEC_HIDDEN;
void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer) DECLSPEC_HIDDEN;
void context_set_tls_idx(DWORD idx) DECLSPEC_HIDDEN;
void context_state_drawbuf(DWORD state, struct wined3d_stateblock *stateblock,
struct wined3d_context *context) DECLSPEC_HIDDEN;
void context_state_fb(DWORD state, struct wined3d_stateblock *stateblock,
struct wined3d_context *context) DECLSPEC_HIDDEN;
void context_surface_update(struct wined3d_context *context, const struct wined3d_surface *surface) DECLSPEC_HIDDEN;
/*****************************************************************************
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment