wined3d: Introduce "context_apply_state()" to setup a context for a specific usage.

This commit is contained in:
Henri Verbeet 2009-12-27 19:57:21 +01:00 committed by Alexandre Julliard
parent f30999f193
commit 9295de9b84
1 changed files with 75 additions and 73 deletions

View File

@ -2105,65 +2105,11 @@ void context_set_draw_buffer(struct wined3d_context *context, GLenum buffer)
context->draw_buffer_dirty = TRUE;
}
/*****************************************************************************
* context_acquire
*
* Finds a rendering context and drawable matching the device and render
* target for the current thread, activates them and puts them into the
* requested state.
*
* Params:
* This: Device to activate the context for
* target: Requested render target
* usage: Prepares the context for blitting, drawing or other actions
*
*****************************************************************************/
struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurface *target, enum ContextUsage usage)
/* Context activation is done by the caller. */
static void context_apply_state(struct wined3d_context *context, IWineD3DDeviceImpl *device, enum ContextUsage usage)
{
struct wined3d_context *current_context = context_get_current();
DWORD tid = GetCurrentThreadId();
DWORD i, dirtyState, idx;
BYTE shift;
const struct StateEntry *StateTable = This->StateTable;
const struct wined3d_gl_info *gl_info;
struct wined3d_context *context;
TRACE("(%p): Selecting context for render target %p, thread %d\n", This, target, tid);
context = FindContext(This, target, tid);
context_enter(context);
if (!context->valid) return context;
gl_info = context->gl_info;
/* Activate the opengl context */
if (context != current_context)
{
if (!context_set_current(context)) ERR("Failed to activate the new context.\n");
else This->frag_pipe->enable_extension((IWineD3DDevice *)This, !context->last_was_blit);
if (context->vshader_const_dirty)
{
memset(context->vshader_const_dirty, 1,
sizeof(*context->vshader_const_dirty) * This->d3d_vshader_constantF);
This->highest_dirty_vs_const = This->d3d_vshader_constantF;
}
if (context->pshader_const_dirty)
{
memset(context->pshader_const_dirty, 1,
sizeof(*context->pshader_const_dirty) * This->d3d_pshader_constantF);
This->highest_dirty_ps_const = This->d3d_pshader_constantF;
}
}
else if (context->restore_ctx)
{
if (!pwglMakeCurrent(context->hdc, context->glCtx))
{
DWORD err = GetLastError();
ERR("Failed to make GL context %p current on device context %p, last error %#x.\n",
context->hdc, context->glCtx, err);
}
}
const struct StateEntry *state_table = device->StateTable;
unsigned int i;
switch (usage) {
case CTXUSAGE_CLEAR:
@ -2186,7 +2132,7 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurfac
FIXME("Activating for CTXUSAGE_BLIT for an offscreen target with ORM_FBO. This should be avoided.\n");
ENTER_GL();
context_bind_fbo(context, GL_FRAMEBUFFER, &context->dst_fbo);
context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, target);
context_attach_surface_fbo(context, GL_FRAMEBUFFER, 0, context->current_rt);
context_attach_depth_stencil_fbo(context, GL_FRAMEBUFFER, NULL, FALSE);
LEAVE_GL();
} else {
@ -2215,7 +2161,7 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurfac
case CTXUSAGE_CLEAR:
if(context->last_was_blit) {
This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE);
device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE);
}
/* Blending and clearing should be orthogonal, but tests on the nvidia driver show that disabling
@ -2224,32 +2170,33 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurfac
ENTER_GL();
glDisable(GL_BLEND);
LEAVE_GL();
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), StateTable);
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_ALPHABLENDENABLE), state_table);
ENTER_GL();
glEnable(GL_SCISSOR_TEST);
checkGLcall("glEnable GL_SCISSOR_TEST");
LEAVE_GL();
context->last_was_blit = FALSE;
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), StateTable);
Context_MarkStateDirty(context, STATE_SCISSORRECT, StateTable);
Context_MarkStateDirty(context, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE), state_table);
Context_MarkStateDirty(context, STATE_SCISSORRECT, state_table);
break;
case CTXUSAGE_DRAWPRIM:
/* This needs all dirty states applied */
if(context->last_was_blit) {
This->frag_pipe->enable_extension((IWineD3DDevice *) This, TRUE);
device->frag_pipe->enable_extension((IWineD3DDevice *)device, TRUE);
}
IWineD3DDeviceImpl_FindTexUnitMap(This);
IWineD3DDeviceImpl_FindTexUnitMap(device);
ENTER_GL();
for(i=0; i < context->numDirtyEntries; i++) {
dirtyState = context->dirtyArray[i];
idx = dirtyState >> 5;
shift = dirtyState & 0x1f;
for (i = 0; i < context->numDirtyEntries; ++i)
{
DWORD rep = context->dirtyArray[i];
DWORD idx = rep >> 5;
BYTE shift = rep & 0x1f;
context->isStateDirty[idx] &= ~(1 << shift);
StateTable[dirtyState].apply(dirtyState, This->stateBlock, context);
state_table[rep].apply(rep, device->stateBlock, context);
}
LEAVE_GL();
context->numDirtyEntries = 0; /* This makes the whole list clean */
@ -2257,14 +2204,69 @@ struct wined3d_context *context_acquire(IWineD3DDeviceImpl *This, IWineD3DSurfac
break;
case CTXUSAGE_BLIT:
SetupForBlit(This, context,
((IWineD3DSurfaceImpl *)target)->currentDesc.Width,
((IWineD3DSurfaceImpl *)target)->currentDesc.Height);
SetupForBlit(device, context,
((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Width,
((IWineD3DSurfaceImpl *)context->current_rt)->currentDesc.Height);
break;
default:
FIXME("Unexpected context usage requested\n");
}
}
/*****************************************************************************
* context_acquire
*
* Finds a rendering context and drawable matching the device and render
* target for the current thread, activates them and puts them into the
* requested state.
*
* Params:
* This: Device to activate the context for
* target: Requested render target
* usage: Prepares the context for blitting, drawing or other actions
*
*****************************************************************************/
struct wined3d_context *context_acquire(IWineD3DDeviceImpl *device, IWineD3DSurface *target, enum ContextUsage usage)
{
struct wined3d_context *current_context = context_get_current();
struct wined3d_context *context;
TRACE("device %p, target %p, usage %#x.\n", device, target, usage);
context = FindContext(device, target, GetCurrentThreadId());
context_enter(context);
if (!context->valid) return context;
if (context != current_context)
{
if (!context_set_current(context)) ERR("Failed to activate the new context.\n");
else device->frag_pipe->enable_extension((IWineD3DDevice *)device, !context->last_was_blit);
if (context->vshader_const_dirty)
{
memset(context->vshader_const_dirty, 1,
sizeof(*context->vshader_const_dirty) * device->d3d_vshader_constantF);
device->highest_dirty_vs_const = device->d3d_vshader_constantF;
}
if (context->pshader_const_dirty)
{
memset(context->pshader_const_dirty, 1,
sizeof(*context->pshader_const_dirty) * device->d3d_pshader_constantF);
device->highest_dirty_ps_const = device->d3d_pshader_constantF;
}
}
else if (context->restore_ctx)
{
if (!pwglMakeCurrent(context->hdc, context->glCtx))
{
DWORD err = GetLastError();
ERR("Failed to make GL context %p current on device context %p, last error %#x.\n",
context->hdc, context->glCtx, err);
}
}
context_apply_state(context, device, usage);
return context;
}