wined3d: Send texture binding updates through the command stream.

This commit is contained in:
Henri Verbeet 2013-10-03 08:54:13 +02:00 committed by Alexandre Julliard
parent d61b14371a
commit 052a863010
3 changed files with 81 additions and 61 deletions

View File

@ -36,6 +36,7 @@ enum wined3d_cs_op
WINED3D_CS_OP_SET_STREAM_SOURCE, WINED3D_CS_OP_SET_STREAM_SOURCE,
WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ, WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ,
WINED3D_CS_OP_SET_INDEX_BUFFER, WINED3D_CS_OP_SET_INDEX_BUFFER,
WINED3D_CS_OP_SET_TEXTURE,
}; };
struct wined3d_cs_present struct wined3d_cs_present
@ -125,6 +126,13 @@ struct wined3d_cs_set_index_buffer
enum wined3d_format_id format_id; enum wined3d_format_id format_id;
}; };
struct wined3d_cs_set_texture
{
enum wined3d_cs_op opcode;
UINT stage;
struct wined3d_texture *texture;
};
static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data) static void wined3d_cs_exec_present(struct wined3d_cs *cs, const void *data)
{ {
const struct wined3d_cs_present *op = data; const struct wined3d_cs_present *op = data;
@ -427,6 +435,75 @@ void wined3d_cs_emit_set_index_buffer(struct wined3d_cs *cs, struct wined3d_buff
cs->ops->submit(cs); cs->ops->submit(cs);
} }
static void wined3d_cs_exec_set_texture(struct wined3d_cs *cs, const void *data)
{
const struct wined3d_d3d_info *d3d_info = &cs->device->adapter->d3d_info;
const struct wined3d_cs_set_texture *op = data;
struct wined3d_texture *prev;
prev = cs->state.textures[op->stage];
cs->state.textures[op->stage] = op->texture;
if (op->texture)
{
if (InterlockedIncrement(&op->texture->resource.bind_count) == 1)
op->texture->sampler = op->stage;
if (!prev || op->texture->target != prev->target)
device_invalidate_state(cs->device, STATE_PIXELSHADER);
if (!prev && op->stage < d3d_info->limits.ffp_blend_stages)
{
/* The source arguments for color and alpha ops have different
* meanings when a NULL texture is bound, so the COLOR_OP and
* ALPHA_OP have to be dirtified. */
device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
}
}
if (prev)
{
if (InterlockedDecrement(&prev->resource.bind_count) && prev->sampler == op->stage)
{
unsigned int i;
/* Search for other stages the texture is bound to. Shouldn't
* happen if applications bind textures to a single stage only. */
TRACE("Searching for other stages the texture is bound to.\n");
for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
{
if (cs->state.textures[i] == prev)
{
TRACE("Texture is also bound to stage %u.\n", i);
prev->sampler = i;
break;
}
}
}
if (!op->texture && op->stage < d3d_info->limits.ffp_blend_stages)
{
device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_COLOR_OP));
device_invalidate_state(cs->device, STATE_TEXTURESTAGE(op->stage, WINED3D_TSS_ALPHA_OP));
}
}
device_invalidate_state(cs->device, STATE_SAMPLER(op->stage));
}
void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture)
{
struct wined3d_cs_set_texture *op;
op = cs->ops->require_space(cs, sizeof(*op));
op->opcode = WINED3D_CS_OP_SET_TEXTURE;
op->stage = stage;
op->texture = texture;
cs->ops->submit(cs);
}
static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) = static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
{ {
/* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present, /* WINED3D_CS_OP_PRESENT */ wined3d_cs_exec_present,
@ -440,6 +517,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
/* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source,
/* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq,
/* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer,
/* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture,
}; };
static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size) static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)

View File

@ -3164,7 +3164,6 @@ DWORD CDECL wined3d_device_get_texture_stage_state(const struct wined3d_device *
HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device, HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
UINT stage, struct wined3d_texture *texture) UINT stage, struct wined3d_texture *texture)
{ {
const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
struct wined3d_texture *prev; struct wined3d_texture *prev;
TRACE("device %p, stage %u, texture %p.\n", device, stage, texture); TRACE("device %p, stage %u, texture %p.\n", device, stage, texture);
@ -3200,70 +3199,12 @@ HRESULT CDECL wined3d_device_set_texture(struct wined3d_device *device,
TRACE("Setting new texture to %p.\n", texture); TRACE("Setting new texture to %p.\n", texture);
device->update_state->textures[stage] = texture; device->update_state->textures[stage] = texture;
if (device->recording)
{
TRACE("Recording... not performing anything\n");
if (texture) wined3d_texture_incref(texture);
if (prev) wined3d_texture_decref(prev);
return WINED3D_OK;
}
if (texture) if (texture)
{
LONG bind_count = InterlockedIncrement(&texture->resource.bind_count);
wined3d_texture_incref(texture); wined3d_texture_incref(texture);
if (!device->recording)
if (!prev || texture->target != prev->target) wined3d_cs_emit_set_texture(device->cs, stage, texture);
device_invalidate_state(device, STATE_PIXELSHADER);
if (!prev && stage < d3d_info->limits.ffp_blend_stages)
{
/* The source arguments for color and alpha ops have different
* meanings when a NULL texture is bound, so the COLOR_OP and
* ALPHA_OP have to be dirtified. */
device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_COLOR_OP));
device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_ALPHA_OP));
}
if (bind_count == 1)
texture->sampler = stage;
}
if (prev) if (prev)
{
LONG bind_count = InterlockedDecrement(&prev->resource.bind_count);
if (!texture && stage < d3d_info->limits.ffp_blend_stages)
{
device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_COLOR_OP));
device_invalidate_state(device, STATE_TEXTURESTAGE(stage, WINED3D_TSS_ALPHA_OP));
}
if (bind_count && prev->sampler == stage)
{
unsigned int i;
/* Search for other stages the texture is bound to. Shouldn't
* happen if applications bind textures to a single stage only. */
TRACE("Searching for other stages the texture is bound to.\n");
for (i = 0; i < MAX_COMBINED_SAMPLERS; ++i)
{
if (device->update_state->textures[i] == prev)
{
TRACE("Texture is also bound to stage %u.\n", i);
prev->sampler = i;
break;
}
}
}
wined3d_texture_decref(prev); wined3d_texture_decref(prev);
}
device_invalidate_state(device, STATE_SAMPLER(stage));
return WINED3D_OK; return WINED3D_OK;
} }

View File

@ -2496,6 +2496,7 @@ void wined3d_cs_emit_set_stream_source(struct wined3d_cs *cs, UINT stream_idx,
struct wined3d_buffer *buffer, UINT offset, UINT stride) DECLSPEC_HIDDEN; struct wined3d_buffer *buffer, UINT offset, UINT stride) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx, void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx,
UINT frequency, UINT flags) DECLSPEC_HIDDEN; UINT frequency, UINT flags) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined3d_texture *texture) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs, void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN; struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN; void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;