Matteo Bruni : wined3d: Introduce a get_projection_matrix() function.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Mar 23 10:03:19 CDT 2015


Module: wine
Branch: master
Commit: 2d270f31c67f1e7f93917bde3ba18936d384195a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=2d270f31c67f1e7f93917bde3ba18936d384195a

Author: Matteo Bruni <mbruni at codeweavers.com>
Date:   Fri Mar 20 13:50:53 2015 +0100

wined3d: Introduce a get_projection_matrix() function.

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.

---

 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 98df60c..bd4f2e2 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:




More information about the wine-cvs mailing list