wined3d: Send texture binding updates through the command stream.
This commit is contained in:
parent
d61b14371a
commit
052a863010
|
@ -36,6 +36,7 @@ enum wined3d_cs_op
|
|||
WINED3D_CS_OP_SET_STREAM_SOURCE,
|
||||
WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ,
|
||||
WINED3D_CS_OP_SET_INDEX_BUFFER,
|
||||
WINED3D_CS_OP_SET_TEXTURE,
|
||||
};
|
||||
|
||||
struct wined3d_cs_present
|
||||
|
@ -125,6 +126,13 @@ struct wined3d_cs_set_index_buffer
|
|||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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) =
|
||||
{
|
||||
/* 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_FREQ */ wined3d_cs_exec_set_stream_source_freq,
|
||||
/* 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)
|
||||
|
|
|
@ -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,
|
||||
UINT stage, struct wined3d_texture *texture)
|
||||
{
|
||||
const struct wined3d_d3d_info *d3d_info = &device->adapter->d3d_info;
|
||||
struct wined3d_texture *prev;
|
||||
|
||||
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);
|
||||
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)
|
||||
{
|
||||
LONG bind_count = InterlockedIncrement(&texture->resource.bind_count);
|
||||
|
||||
wined3d_texture_incref(texture);
|
||||
|
||||
if (!prev || texture->target != prev->target)
|
||||
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 (!device->recording)
|
||||
wined3d_cs_emit_set_texture(device->cs, stage, texture);
|
||||
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);
|
||||
}
|
||||
|
||||
device_invalidate_state(device, STATE_SAMPLER(stage));
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
void wined3d_cs_emit_set_stream_source_freq(struct wined3d_cs *cs, UINT stream_idx,
|
||||
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,
|
||||
struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
|
||||
void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in New Issue