diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 3dc6ca7c024..8af9e4bb826 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -2352,6 +2352,33 @@ static void context_get_rt_size(const struct wined3d_context *context, SIZE *siz size->cy = wined3d_texture_get_level_height(rt, level); } +void context_enable_clip_distances(struct wined3d_context *context, unsigned int enable_mask) +{ + const struct wined3d_gl_info *gl_info = context->gl_info; + unsigned int clip_distance_count = gl_info->limits.user_clip_distances; + unsigned int i, disable_mask, current_mask; + + disable_mask = ~enable_mask; + enable_mask &= (1u << clip_distance_count) - 1; + disable_mask &= (1u << clip_distance_count) - 1; + current_mask = context->clip_distance_mask; + context->clip_distance_mask = enable_mask; + + enable_mask &= ~current_mask; + for (i = 0; enable_mask; enable_mask >>= 1, ++i) + { + if (enable_mask & 1) + gl_info->gl_ops.gl.p_glEnable(GL_CLIP_DISTANCE0 + i); + } + disable_mask &= current_mask; + for (i = 0; disable_mask; disable_mask >>= 1, ++i) + { + if (disable_mask & 1) + gl_info->gl_ops.gl.p_glDisable(GL_CLIP_DISTANCE0 + i); + } + checkGLcall("toggle clip distances"); +} + /***************************************************************************** * SetupForBlit * @@ -2530,9 +2557,7 @@ static void SetupForBlit(const struct wined3d_device *device, struct wined3d_con context->last_was_rhw = TRUE; context_invalidate_state(context, STATE_VDECL); /* because of last_was_rhw = TRUE */ - for (i = 0; i < gl_info->limits.user_clip_distances; ++i) - gl_info->gl_ops.gl.p_glDisable(GL_CLIP_DISTANCE0 + i); - checkGLcall("disable clip planes"); + context_enable_clip_distances(context, 0); context_invalidate_state(context, STATE_RENDER(WINED3D_RS_CLIPPING)); /* FIXME: Make draw_textured_quad() able to work with a upper left origin. */ diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index ea497fabc6a..f3ec7df1863 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -611,9 +611,7 @@ void state_alpha_test(struct wined3d_context *context, const struct wined3d_stat void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) { - const struct wined3d_gl_info *gl_info = context->gl_info; - unsigned int clipplane_count = gl_info->limits.user_clip_distances; - unsigned int i, enable_mask, disable_mask; + unsigned int enable_mask; if (use_vs(state) && !context->d3d_info->vs_clipping) { @@ -626,7 +624,7 @@ void state_clipping(struct wined3d_context *context, const struct wined3d_state * disables all clip planes because of that - don't do anything here * and keep them disabled. */ if (state->render_states[WINED3D_RS_CLIPPLANEENABLE] && !warned++) - FIXME("Clipping not supported with vertex shaders\n"); + FIXME("Clipping not supported with vertex shaders.\n"); return; } @@ -636,36 +634,12 @@ void state_clipping(struct wined3d_context *context, const struct wined3d_state * need to update the clipping field from ffp_vertex_settings. */ context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX; - /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting - * of already set values - */ - /* If enabling / disabling all * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum? */ - if (state->render_states[WINED3D_RS_CLIPPING]) - { - enable_mask = state->render_states[WINED3D_RS_CLIPPLANEENABLE]; - disable_mask = ~state->render_states[WINED3D_RS_CLIPPLANEENABLE]; - } - else - { - enable_mask = 0; - disable_mask = ~0u; - } - - enable_mask &= (1u << clipplane_count) - 1; - disable_mask &= (1u << clipplane_count) - 1; - - for (i = 0; enable_mask && i < clipplane_count; enable_mask >>= 1, ++i) - if (enable_mask & 1) - gl_info->gl_ops.gl.p_glEnable(GL_CLIP_DISTANCE0 + i); - checkGLcall("clip plane enable"); - - for (i = 0; disable_mask && i < clipplane_count; disable_mask >>= 1, ++i) - if (disable_mask & 1) - gl_info->gl_ops.gl.p_glDisable(GL_CLIP_DISTANCE0 + i); - checkGLcall("clip plane disable"); + enable_mask = state->render_states[WINED3D_RS_CLIPPING] ? + state->render_states[WINED3D_RS_CLIPPLANEENABLE] : 0; + context_enable_clip_distances(context, enable_mask); } static void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id) @@ -4532,22 +4506,19 @@ static void vertexdeclaration(struct wined3d_context *context, const struct wine } else { - if(!context->last_was_vshader) { + if (!context->last_was_vshader) + { static BOOL warned = FALSE; if (!context->d3d_info->vs_clipping) { /* Disable all clip planes to get defined results on all drivers. See comment in the * state_clipping state handler */ - for (i = 0; i < gl_info->limits.user_clip_distances; ++i) - { - gl_info->gl_ops.gl.p_glDisable(GL_CLIP_PLANE0 + i); - checkGLcall("glDisable(GL_CLIP_PLANE0 + i)"); - } + context_enable_clip_distances(context, 0); if (!warned && state->render_states[WINED3D_RS_CLIPPLANEENABLE]) { - FIXME("Clipping not supported with vertex shaders\n"); + FIXME("Clipping not supported with vertex shaders.\n"); warned = TRUE; } } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9fe7fbcd72d..da06ba159f7 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1901,7 +1901,8 @@ struct wined3d_context DWORD transform_feedback_active : 1; DWORD transform_feedback_paused : 1; DWORD shader_update_mask : 6; /* WINED3D_SHADER_TYPE_COUNT, 6 */ - DWORD padding : 17; + DWORD clip_distance_mask : 8; /* MAX_CLIP_DISTANCES, 8 */ + DWORD padding : 9; DWORD constant_update_mask; DWORD numbered_array_mask; GLenum tracking_parm; /* Which source is tracking current colour */ @@ -2146,6 +2147,7 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, stru const struct wined3d_format *ds_format) DECLSPEC_HIDDEN; HGLRC context_create_wgl_attribs(const struct wined3d_gl_info *gl_info, HDC hdc, HGLRC share_ctx) DECLSPEC_HIDDEN; void context_destroy(struct wined3d_device *device, struct wined3d_context *context) DECLSPEC_HIDDEN; +void context_enable_clip_distances(struct wined3d_context *context, unsigned int mask) DECLSPEC_HIDDEN; void context_end_transform_feedback(struct wined3d_context *context) DECLSPEC_HIDDEN; void context_free_fence(struct wined3d_fence *fence) DECLSPEC_HIDDEN; void context_free_occlusion_query(struct wined3d_occlusion_query *query) DECLSPEC_HIDDEN;