[PATCH 2/5] wined3d: Introduce a get_projection_matrix() function.

Matteo Bruni mbruni at codeweavers.com
Fri Mar 20 07:50:53 CDT 2015


Notice that I'm using floats instead of doubles in the new function,
mostly to be able to use struct wined3d_matrix and multiply_matrix().
At a rough estimate the precision should still be good enough.
I'm still computing the offsets in double precision in the transformed
vertices case to be totally safe. The explicit casts there are for MSVC
which (IIRC) throws warnings for that kind of implicit precision loss
assignments otherwise.
---
 dlls/wined3d/state.c           | 68 +++---------------------------------------
 dlls/wined3d/utils.c           | 64 +++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/wined3d_private.h |  2 ++
 3 files changed, 70 insertions(+), 64 deletions(-)

diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 774e6dd..9a40876 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4052,74 +4052,14 @@ static void transform_view(struct wined3d_context *context, const struct wined3d
 void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = context->gl_info;
+    struct wined3d_matrix projection;
 
     gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
     checkGLcall("glMatrixMode(GL_PROJECTION)");
 
-    /* There are a couple of additional things we have to take into account
-     * here besides the projection transformation itself:
-     *   - We need to flip along the y-axis in case of offscreen rendering.
-     *   - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
-     *   - D3D coordinates refer to pixel centers while GL coordinates refer
-     *     to pixel corners.
-     *   - D3D has a top-left filling convention. We need to maintain this
-     *     even after the y-flip mentioned above.
-     * In order to handle the last two points, we translate by
-     * (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
-     * translating slightly less than half a pixel. We want the difference to
-     * be large enough that it doesn't get lost due to rounding inside the
-     * driver, but small enough to prevent it from interfering with any
-     * anti-aliasing. */
-
-    if (context->last_was_rhw)
-    {
-        /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
-        double x = state->viewport.x;
-        double y = state->viewport.y;
-        double w = state->viewport.width;
-        double h = state->viewport.height;
-        double x_scale = 2.0 / w;
-        double x_offset = ((63.0 / 64.0) - (2.0 * x) - w) / w;
-        double y_scale = context->render_offscreen ? 2.0 / h : 2.0 / -h;
-        double y_offset = context->render_offscreen
-                ? ((63.0 / 64.0) - (2.0 * y) - h) / h
-                : ((63.0 / 64.0) - (2.0 * y) - h) / -h;
-        enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
-                state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
-        double z_scale = zenable ? 2.0f : 0.0f;
-        double z_offset = zenable ? -1.0f : 0.0f;
-        const GLdouble projection[] =
-        {
-             x_scale,      0.0,  0.0,      0.0,
-                 0.0,  y_scale,  0.0,      0.0,
-                 0.0,      0.0,  z_scale,  0.0,
-            x_offset, y_offset,  z_offset, 1.0,
-        };
-
-        gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
-        checkGLcall("glLoadMatrixd");
-    }
-    else
-    {
-        double y_scale = context->render_offscreen ? -1.0 : 1.0;
-        double x_offset = (63.0 / 64.0) / state->viewport.width;
-        double y_offset = context->render_offscreen
-                ? (63.0 / 64.0) / state->viewport.height
-                : -(63.0 / 64.0) / state->viewport.height;
-        const GLdouble projection[] =
-        {
-                 1.0,      0.0,  0.0, 0.0,
-                 0.0,  y_scale,  0.0, 0.0,
-                 0.0,      0.0,  2.0, 0.0,
-            x_offset, y_offset, -1.0, 1.0,
-        };
-
-        gl_info->gl_ops.gl.p_glLoadMatrixd(projection);
-        checkGLcall("glLoadMatrixd");
-
-        gl_info->gl_ops.gl.p_glMultMatrixf(&state->transforms[WINED3D_TS_PROJECTION]._11);
-        checkGLcall("glLoadMatrixf");
-    }
+    get_projection_matrix(context, state, &projection);
+    gl_info->gl_ops.gl.p_glLoadMatrixf(&projection._11);
+    checkGLcall("glLoadMatrixf");
 }
 
 /* This should match any arrays loaded in load_vertex_data.
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index a43029c..4452f7c 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -3138,6 +3138,70 @@ void get_modelview_matrix(const struct wined3d_context *context, const struct wi
         multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]);
 }
 
+void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct wined3d_matrix *mat)
+{
+    /* There are a couple of additional things we have to take into account
+     * here besides the projection transformation itself:
+     *   - We need to flip along the y-axis in case of offscreen rendering.
+     *   - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
+     *   - D3D coordinates refer to pixel centers while GL coordinates refer
+     *     to pixel corners.
+     *   - D3D has a top-left filling convention. We need to maintain this
+     *     even after the y-flip mentioned above.
+     * In order to handle the last two points, we translate by
+     * (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
+     * translating slightly less than half a pixel. We want the difference to
+     * be large enough that it doesn't get lost due to rounding inside the
+     * driver, but small enough to prevent it from interfering with any
+     * anti-aliasing. */
+
+    if (context->last_was_rhw)
+    {
+        /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
+        float x = state->viewport.x;
+        float y = state->viewport.y;
+        float w = state->viewport.width;
+        float h = state->viewport.height;
+        float x_scale = 2.0f / w;
+        float x_offset = (float)((63.0 / 64.0 - (2.0 * x) - w) / w);
+        float y_scale = context->render_offscreen ? 2.0f / h : 2.0f / -h;
+        float y_offset = (float)(context->render_offscreen
+                ? (63.0 / 64.0 - (2.0 * y) - h) / h
+                : (63.0 / 64.0 - (2.0 * y) - h) / -h);
+        enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
+                state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
+        float z_scale = zenable ? 2.0f : 0.0f;
+        float z_offset = zenable ? -1.0f : 0.0f;
+        const struct wined3d_matrix projection =
+        {
+             x_scale,     0.0f,      0.0f, 0.0f,
+                0.0f,  y_scale,      0.0f, 0.0f,
+                0.0f,     0.0f,   z_scale, 0.0f,
+            x_offset, y_offset,  z_offset, 1.0f,
+        };
+
+        *mat = projection;
+    }
+    else
+    {
+        float y_scale = context->render_offscreen ? -1.0f : 1.0f;
+        float x_offset = 63.0f / 64.0f * (1.0f / state->viewport.width);
+        float y_offset = context->render_offscreen
+                ? 63.0f / 64.0f * (1.0f / state->viewport.height)
+                : -63.0f / 64.0f * (1.0f / state->viewport.height);
+        const struct wined3d_matrix projection =
+        {
+                1.0f,     0.0f,  0.0f, 0.0f,
+                0.0f,  y_scale,  0.0f, 0.0f,
+                0.0f,     0.0f,  2.0f, 0.0f,
+            x_offset, y_offset, -1.0f, 1.0f,
+        };
+
+        multiply_matrix(mat, &projection, &state->transforms[WINED3D_TS_PROJECTION]);
+    }
+}
+
 /* Setup this textures matrix according to the texture flags. */
 /* Context activation is done by the caller (state handler). */
 void set_texture_matrix(const struct wined3d_gl_info *gl_info, const struct wined3d_matrix *matrix, DWORD flags,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index d8fc453..eca6bdb 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -3037,6 +3037,8 @@ static inline BOOL shader_constant_is_local(const struct wined3d_shader *shader,
 void get_identity_matrix(struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
 void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
         struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
+void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
+        struct wined3d_matrix *mat) DECLSPEC_HIDDEN;
 
 /* Using additional shader constants (uniforms in GLSL / program environment
  * or local parameters in ARB) is costly:
-- 
2.0.5




More information about the wine-patches mailing list