diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 212881a9b71..4c42fa284cb 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -941,7 +941,6 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_RSSetState(ID3D11DeviceCon if (!(rasterizer_state_impl = unsafe_impl_from_ID3D11RasterizerState(rasterizer_state))) { wined3d_device_set_rasterizer_state(device->wined3d_device, NULL); - wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_FILLMODE, WINED3D_FILL_SOLID); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_CULLMODE, WINED3D_CULL_BACK); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_SLOPESCALEDEPTHBIAS, 0); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_DEPTHBIAS, 0); @@ -955,7 +954,6 @@ static void STDMETHODCALLTYPE d3d11_immediate_context_RSSetState(ID3D11DeviceCon wined3d_device_set_rasterizer_state(device->wined3d_device, rasterizer_state_impl->wined3d_state); desc = &rasterizer_state_impl->desc; - wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_FILLMODE, desc->FillMode); wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_CULLMODE, desc->CullMode); scale_bias.f = desc->SlopeScaledDepthBias; const_bias.f = desc->DepthBias; diff --git a/dlls/d3d11/state.c b/dlls/d3d11/state.c index 92b75f8e1fb..d63a1bc699c 100644 --- a/dlls/d3d11/state.c +++ b/dlls/d3d11/state.c @@ -1076,6 +1076,7 @@ static HRESULT d3d_rasterizer_state_init(struct d3d_rasterizer_state *state, str return E_FAIL; } + wined3d_desc.fill_mode = desc->FillMode; wined3d_desc.front_ccw = desc->FrontCounterClockwise; wined3d_desc.depth_clip = desc->DepthClipEnable; wined3d_desc.depth_bias_clamp = desc->DepthBiasClamp; diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index cdb3202ac18..69ff7dd0cd9 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -521,6 +521,13 @@ static void device_leftover_sampler(struct wine_rb_entry *entry, void *context) ERR("Leftover sampler %p.\n", sampler); } +static void device_free_rasterizer_state(struct wine_rb_entry *entry, void *context) +{ + struct wined3d_rasterizer_state *state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry); + + wined3d_rasterizer_state_decref(state); +} + void wined3d_device_cleanup(struct wined3d_device *device) { unsigned int i; @@ -529,6 +536,7 @@ void wined3d_device_cleanup(struct wined3d_device *device) wined3d_device_uninit_3d(device); wined3d_blend_state_decref(device->blend_state_atoc_enabled); + wine_rb_destroy(&device->rasterizer_states, device_free_rasterizer_state, NULL); wined3d_cs_destroy(device->cs); @@ -3477,11 +3485,11 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, const struct wined3d_stateblock_state *state = &stateblock->stateblock_state; const struct wined3d_saved_states *changed = &stateblock->changed; const unsigned int word_bit_count = sizeof(DWORD) * CHAR_BIT; + BOOL set_blend_state, set_rasterizer_state = FALSE; struct wined3d_blend_state *blend_state; unsigned int i, j, start, idx; struct wined3d_color colour; struct wined3d_range range; - BOOL set_blend_state; DWORD map, stage; TRACE("device %p, stateblock %p.\n", device, stateblock); @@ -3578,17 +3586,53 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, { j = wined3d_bit_scan(&map); idx = i * word_bit_count + j; - if (idx != WINED3D_RS_BLENDFACTOR) - { - wined3d_device_set_render_state(device, idx, state->rs[idx]); - continue; - } - if (!set_blend_state) + switch (idx) { - blend_state = wined3d_device_get_blend_state(device, &colour); - wined3d_color_from_d3dcolor(&colour, state->rs[idx]); - wined3d_device_set_blend_state(device, blend_state, &colour); + case WINED3D_RS_BLENDFACTOR: + if (!set_blend_state) + { + blend_state = wined3d_device_get_blend_state(device, &colour); + wined3d_color_from_d3dcolor(&colour, state->rs[idx]); + wined3d_device_set_blend_state(device, blend_state, &colour); + } + break; + + case WINED3D_RS_FILLMODE: + set_rasterizer_state = TRUE; + break; + + default: + wined3d_device_set_render_state(device, idx, state->rs[idx]); + break; + } + } + } + + if (set_rasterizer_state) + { + struct wined3d_rasterizer_state *rasterizer_state; + struct wined3d_rasterizer_state_desc desc; + struct wine_rb_entry *entry; + + desc.fill_mode = state->rs[WINED3D_RS_FILLMODE]; + desc.front_ccw = FALSE; + desc.depth_bias_clamp = 0.0f; + desc.depth_clip = TRUE; + + if ((entry = wine_rb_get(&device->rasterizer_states, &desc))) + { + rasterizer_state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry); + wined3d_device_set_rasterizer_state(device, rasterizer_state); + } + else if (SUCCEEDED(wined3d_rasterizer_state_create(device, &desc, NULL, + &wined3d_null_parent_ops, &rasterizer_state))) + { + wined3d_device_set_rasterizer_state(device, rasterizer_state); + if (wine_rb_put(&device->rasterizer_states, &desc, &rasterizer_state->entry) == -1) + { + ERR("Failed to insert rasterizer state.\n"); + wined3d_rasterizer_state_decref(rasterizer_state); } } } @@ -5392,6 +5436,13 @@ static int wined3d_sampler_compare(const void *key, const struct wine_rb_entry * return memcmp(&sampler->desc, key, sizeof(sampler->desc)); } +static int wined3d_rasterizer_state_compare(const void *key, const struct wine_rb_entry *entry) +{ + const struct wined3d_rasterizer_state *state = WINE_RB_ENTRY_VALUE(entry, struct wined3d_rasterizer_state, entry); + + return memcmp(&state->desc, key, sizeof(state->desc)); +} + static BOOL wined3d_select_feature_level(const struct wined3d_adapter *adapter, const enum wined3d_feature_level *levels, unsigned int level_count, enum wined3d_feature_level *selected_level) @@ -5452,6 +5503,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined fragment_pipeline = adapter->fragment_pipe; wine_rb_init(&device->samplers, wined3d_sampler_compare); + wine_rb_init(&device->rasterizer_states, wined3d_rasterizer_state_compare); if (vertex_pipeline->vp_states && fragment_pipeline->states && FAILED(hr = compile_state_table(device->state_table, device->multistate_funcs, @@ -5460,6 +5512,7 @@ HRESULT wined3d_device_init(struct wined3d_device *device, struct wined3d *wined { ERR("Failed to compile state table, hr %#x.\n", hr); wine_rb_destroy(&device->samplers, NULL, NULL); + wine_rb_destroy(&device->rasterizer_states, NULL, NULL); wined3d_decref(device->wined3d); return hr; } @@ -5496,6 +5549,7 @@ err: heap_free(device->multistate_funcs[i]); } wine_rb_destroy(&device->samplers, NULL, NULL); + wine_rb_destroy(&device->rasterizer_states, NULL, NULL); wined3d_decref(device->wined3d); return hr; } diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index a4d88e1bfc1..388116bc666 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -171,10 +171,9 @@ void state_nop(struct wined3d_context *context, const struct wined3d_state *stat TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state_id)); } -static void state_fillmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) +static void fillmode(const struct wined3d_rasterizer_state *r, const struct wined3d_gl_info *gl_info) { - const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info; - enum wined3d_fill_mode mode = state->render_states[WINED3D_RS_FILLMODE]; + enum wined3d_fill_mode mode = r ? r->desc.fill_mode : WINED3D_FILL_SOLID; switch (mode) { @@ -4324,9 +4323,10 @@ static void depth_clip(const struct wined3d_rasterizer_state *r, const struct wi static void rasterizer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info; + const struct wined3d_rasterizer_state *r = state->rasterizer_state; GLenum mode; - mode = state->rasterizer_state && state->rasterizer_state->desc.front_ccw ? GL_CCW : GL_CW; + mode = r && r->desc.front_ccw ? GL_CCW : GL_CW; if (context->render_offscreen) mode = (mode == GL_CW) ? GL_CCW : GL_CW; @@ -4334,21 +4334,24 @@ static void rasterizer(struct wined3d_context *context, const struct wined3d_sta checkGLcall("glFrontFace"); if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_DEPTHBIAS))) state_depthbias(context, state, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); - depth_clip(state->rasterizer_state, gl_info); + fillmode(r, gl_info); + depth_clip(r, gl_info); } static void rasterizer_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info; + const struct wined3d_rasterizer_state *r = state->rasterizer_state; GLenum mode; - mode = state->rasterizer_state && state->rasterizer_state->desc.front_ccw ? GL_CCW : GL_CW; + mode = r && r->desc.front_ccw ? GL_CCW : GL_CW; gl_info->gl_ops.gl.p_glFrontFace(mode); checkGLcall("glFrontFace"); if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_DEPTHBIAS))) state_depthbias(context, state, STATE_RENDER(WINED3D_RS_DEPTHBIAS)); - depth_clip(state->rasterizer_state, gl_info); + fillmode(r, gl_info); + depth_clip(r, gl_info); } static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4588,7 +4591,6 @@ const struct wined3d_state_entry_template misc_state_template[] = { STATE_RENDER(WINED3D_RS_ZENABLE), { STATE_RENDER(WINED3D_RS_ZENABLE), state_zenable }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_WRAPU), { STATE_RENDER(WINED3D_RS_WRAPU), state_wrapu }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_WRAPV), { STATE_RENDER(WINED3D_RS_WRAPV), state_wrapv }, WINED3D_GL_EXT_NONE }, - { STATE_RENDER(WINED3D_RS_FILLMODE), { STATE_RENDER(WINED3D_RS_FILLMODE), state_fillmode }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_LINEPATTERN), { STATE_RENDER(WINED3D_RS_LINEPATTERN), state_linepattern }, WINED3D_GL_LEGACY_CONTEXT }, { STATE_RENDER(WINED3D_RS_LINEPATTERN), { STATE_RENDER(WINED3D_RS_LINEPATTERN), state_linepattern_w }, WINED3D_GL_EXT_NONE }, { STATE_RENDER(WINED3D_RS_MONOENABLE), { STATE_RENDER(WINED3D_RS_MONOENABLE), state_monoenable }, WINED3D_GL_EXT_NONE }, @@ -5426,6 +5428,7 @@ static void validate_state_table(struct wined3d_state_entry *state_table) { { 1, 1}, { 3, 3}, + { 8, 8}, { 17, 18}, { 21, 21}, { 42, 45}, diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 23540295bb4..db4660cf586 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -3155,6 +3155,7 @@ struct wined3d_rasterizer_state const struct wined3d_parent_ops *parent_ops; struct wined3d_device *device; + struct wine_rb_entry entry; }; struct wined3d_stream_output @@ -3293,7 +3294,7 @@ struct wined3d_device struct list resources; /* a linked list to track resources created by the device */ struct list shaders; /* a linked list to track shaders (pixel and vertex) */ - struct wine_rb_tree samplers; + struct wine_rb_tree samplers, rasterizer_states; /* Render Target Support */ struct wined3d_fb_state fb; diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index cb8f19981aa..2370ca469f0 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2033,6 +2033,7 @@ struct wined3d_blend_state_desc struct wined3d_rasterizer_state_desc { + enum wined3d_fill_mode fill_mode; BOOL front_ccw; float depth_bias_clamp; BOOL depth_clip;