[PATCH 1/5] wined3d: Avoid glBegin() / glEnd() in check_fbo_compat() when possible.

Matteo Bruni mbruni at codeweavers.com
Mon Jul 27 07:29:53 CDT 2015


---
draw_test_quad() should be ready to be used by find_polyoffset_scale(),
although I haven't actually tried.

Those glDelete[Program|Buffers]() in wined3d_caps_gl_ctx_destroy()
aren't strictly necessary since the "caps" GL context isn't shared with
any other.
---
 dlls/wined3d/directx.c         |  27 +++----
 dlls/wined3d/glsl_shader.c     |   4 +-
 dlls/wined3d/utils.c           | 156 ++++++++++++++++++++++++++++++++++-------
 dlls/wined3d/wined3d_private.h |  19 ++++-
 4 files changed, 164 insertions(+), 42 deletions(-)

diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c
index 61c3059..5880799 100644
--- a/dlls/wined3d/directx.c
+++ b/dlls/wined3d/directx.c
@@ -250,19 +250,21 @@ const GLenum magLookup[] =
     GL_NEAREST, GL_NEAREST, GL_LINEAR,
 };
 
-struct wined3d_caps_gl_ctx
-{
-    HDC dc;
-    HWND wnd;
-    HGLRC gl_ctx;
-    HDC restore_dc;
-    HGLRC restore_gl_ctx;
-};
-
 static void wined3d_caps_gl_ctx_destroy(const struct wined3d_caps_gl_ctx *ctx)
 {
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+
     TRACE("Destroying caps GL context.\n");
 
+    /* Both glDeleteProgram and glDeleteBuffers silently ignore 0 IDs but
+     * this function might be called before the relevant function pointers
+     * in gl_info are initialized. */
+    if (ctx->test_program_id || ctx->test_vbo)
+    {
+        GL_EXTCALL(glDeleteProgram(ctx->test_program_id));
+        GL_EXTCALL(glDeleteBuffers(1, &ctx->test_vbo));
+    }
+
     if (!wglMakeCurrent(NULL, NULL))
         ERR("Failed to disable caps GL context.\n");
 
@@ -309,7 +311,7 @@ static BOOL wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_
     return TRUE;
 }
 
-static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx)
+static BOOL wined3d_caps_gl_ctx_create(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx)
 {
     PIXELFORMATDESCRIPTOR pfd;
     int iPixelFormat;
@@ -367,6 +369,7 @@ static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx)
         goto fail;
     }
 
+    ctx->gl_info = &adapter->gl_info;
     return TRUE;
 
 fail:
@@ -5840,7 +5843,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
     TRACE("Allocated LUID %08x:%08x for adapter %p.\n",
             adapter->luid.HighPart, adapter->luid.LowPart, adapter);
 
-    if (!wined3d_caps_gl_ctx_create(&caps_gl_ctx))
+    if (!wined3d_caps_gl_ctx_create(adapter, &caps_gl_ctx))
     {
         ERR("Failed to get a GL context for adapter %p.\n", adapter);
         return FALSE;
@@ -5887,7 +5890,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal)
         return FALSE;
     }
 
-    if (!wined3d_adapter_init_format_info(adapter))
+    if (!wined3d_adapter_init_format_info(adapter, &caps_gl_ctx))
     {
         ERR("Failed to initialize GL format info.\n");
         wined3d_caps_gl_ctx_destroy(&caps_gl_ctx);
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 3c92781..301dc6f 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -333,7 +333,7 @@ static const char *get_info_log_line(const char **ptr)
 }
 
 /* Context activation is done by the caller. */
-static void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
+void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program)
 {
     int length = 0;
     char *log;
@@ -453,7 +453,7 @@ static void shader_glsl_dump_program_source(const struct wined3d_gl_info *gl_inf
 }
 
 /* Context activation is done by the caller. */
-static void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program)
+void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program)
 {
     GLint tmp;
 
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 48f6671..6c871f1 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -1557,13 +1557,133 @@ static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info
     while (gl_info->gl_ops.gl.p_glGetError());
 }
 
+static void draw_test_quad(struct wined3d_caps_gl_ctx *ctx, const struct wined3d_vec3 *geometry,
+        const struct wined3d_color *color)
+{
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
+    static const struct wined3d_vec3 default_geometry[] =
+    {
+        {-1.0f, -1.0f, 0.0f},
+        { 1.0f, -1.0f, 0.0f},
+        {-1.0f,  1.0f, 0.0f},
+        { 1.0f,  1.0f, 0.0f},
+    };
+    static const char vs_core_header[] =
+        "#version 150\n"
+        "in vec4 pos;\n"
+        "in vec4 color;\n"
+        "out vec4 out_color;\n"
+        "\n";
+    static const char vs_legacy_header[] =
+        "#version 120\n"
+        "attribute vec4 pos;\n"
+        "attribute vec4 color;\n"
+        "varying vec4 out_color;\n"
+        "\n";
+    static const char vs_body[] =
+        "void main()\n"
+        "{\n"
+        "    gl_Position = pos;\n"
+        "    out_color = color;\n"
+        "}\n";
+    static const char fs_core[] =
+        "#version 150\n"
+        "in vec4 out_color;\n"
+        "out vec4 fragment_color;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    fragment_color = out_color;\n"
+        "}\n";
+    static const char fs_legacy[] =
+        "#version 120\n"
+        "varying vec4 out_color;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragData[0] = out_color;\n"
+        "}\n";
+    const char *source[2];
+    GLuint vs_id, fs_id;
+    unsigned int i;
+
+    if (!geometry)
+        geometry = default_geometry;
+
+    if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] || !gl_info->supported[ARB_VERTEX_SHADER]
+            || !gl_info->supported[ARB_FRAGMENT_SHADER])
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+        gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
+        gl_info->gl_ops.gl.p_glLoadIdentity();
+
+        gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
+        gl_info->gl_ops.gl.p_glColor4f(color->r, color->g, color->b, color->a);
+        for (i = 0; i < 4; ++i)
+            gl_info->gl_ops.gl.p_glVertex3fv(&geometry[i].x);
+        gl_info->gl_ops.gl.p_glEnd();
+        checkGLcall("Drawing a quad");
+        return;
+    }
+
+    if (!ctx->test_vbo)
+        GL_EXTCALL(glGenBuffers(1, &ctx->test_vbo));
+    GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, ctx->test_vbo));
+    GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(struct wined3d_vec3) * 4, geometry, GL_STREAM_DRAW));
+    GL_EXTCALL(glVertexAttribPointer(0, 3, GL_FLOAT, FALSE, 0, NULL));
+    GL_EXTCALL(glVertexAttrib4f(1, color->r, color->g, color->b, color->a));
+    GL_EXTCALL(glEnableVertexAttribArray(0));
+    GL_EXTCALL(glDisableVertexAttribArray(1));
+
+    if (!ctx->test_program_id)
+    {
+        ctx->test_program_id = GL_EXTCALL(glCreateProgram());
+
+        vs_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
+        source[0] = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? vs_legacy_header : vs_core_header;
+        source[1] = vs_body;
+        GL_EXTCALL(glShaderSource(vs_id, 2, source, NULL));
+        GL_EXTCALL(glAttachShader(ctx->test_program_id, vs_id));
+        GL_EXTCALL(glDeleteShader(vs_id));
+
+        fs_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
+        source[0] = gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? fs_legacy : fs_core;
+        GL_EXTCALL(glShaderSource(fs_id, 1, source, NULL));
+        GL_EXTCALL(glAttachShader(ctx->test_program_id, fs_id));
+        GL_EXTCALL(glDeleteShader(fs_id));
+
+        GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 0, "pos"));
+        GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 1, "color"));
+
+        GL_EXTCALL(glCompileShader(vs_id));
+        print_glsl_info_log(gl_info, vs_id, FALSE);
+        GL_EXTCALL(glCompileShader(fs_id));
+        print_glsl_info_log(gl_info, fs_id, FALSE);
+        GL_EXTCALL(glLinkProgram(ctx->test_program_id));
+        shader_glsl_validate_link(gl_info, ctx->test_program_id);
+    }
+    GL_EXTCALL(glUseProgram(ctx->test_program_id));
+
+    gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+    GL_EXTCALL(glUseProgram(0));
+    GL_EXTCALL(glDisableVertexAttribArray(0));
+    GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
+    checkGLcall("Drawing a quad");
+}
+
 /* Context activation is done by the caller. */
-static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
+static void check_fbo_compat(struct wined3d_caps_gl_ctx *ctx, struct wined3d_format *format)
 {
     /* Check if the default internal format is supported as a frame buffer
      * target, otherwise fall back to the render target internal.
      *
      * Try to stick to the standard format if possible, this limits precision differences. */
+    static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 1.0f};
+    static const struct wined3d_color half_transparent_red = {1.0f, 0.0f, 0.0f, 0.5f};
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
     GLenum status, rt_internal = format->rtInternal;
     GLuint object, color_rb;
     enum wined3d_gl_resource_type type;
@@ -1697,32 +1817,13 @@ static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined
                     gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
                 else
                     gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
-                gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
-                gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
-                gl_info->gl_ops.gl.p_glLoadIdentity();
-                gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
-                gl_info->gl_ops.gl.p_glLoadIdentity();
-
                 gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
-                /* Draw a full-black quad */
-                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-                gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glEnd();
+                draw_test_quad(ctx, NULL, &black);
 
                 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
-                /* Draw a half-transparent red quad */
-                gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
-                gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
-                gl_info->gl_ops.gl.p_glEnd();
+
+                draw_test_quad(ctx, NULL, &half_transparent_red);
 
                 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
 
@@ -1868,8 +1969,9 @@ static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_fo
 }
 
 /* Context activation is done by the caller. */
-static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
+static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx)
 {
+    const struct wined3d_gl_info *gl_info = ctx->gl_info;
     unsigned int i, type;
     GLuint fbo;
 
@@ -2002,7 +2104,7 @@ static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
         {
             TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
-            check_fbo_compat(gl_info, format);
+            check_fbo_compat(ctx, format);
         }
         else
         {
@@ -2582,7 +2684,7 @@ BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info)
 }
 
 /* Context activation is done by the caller. */
-BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter)
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx)
 {
     struct wined3d_gl_info *gl_info = &adapter->gl_info;
 
@@ -2593,7 +2695,7 @@ BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter)
     if (!init_format_vertex_info(gl_info)) goto fail;
 
     apply_format_fixups(adapter, gl_info);
-    init_format_fbo_compat_info(gl_info);
+    init_format_fbo_compat_info(ctx);
     init_format_filter_info(gl_info, adapter->driver_info.vendor);
 
     return TRUE;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 8dd9e80..27dacb8 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1794,7 +1794,21 @@ struct wined3d_adapter
     const struct blit_shader *blitter;
 };
 
-BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter) DECLSPEC_HIDDEN;
+struct wined3d_caps_gl_ctx
+{
+    HDC dc;
+    HWND wnd;
+    HGLRC gl_ctx;
+    HDC restore_dc;
+    HGLRC restore_gl_ctx;
+
+    const struct wined3d_gl_info *gl_info;
+    GLuint test_vbo;
+    GLuint test_program_id;
+};
+
+BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter,
+        struct wined3d_caps_gl_ctx *ctx) DECLSPEC_HIDDEN;
 UINT64 adapter_adjust_memory(struct wined3d_adapter *adapter, INT64 amount) DECLSPEC_HIDDEN;
 
 BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info) DECLSPEC_HIDDEN;
@@ -3103,6 +3117,9 @@ struct ps_np2fixup_info {
     WORD              num_consts;
 };
 
+void print_glsl_info_log(const struct wined3d_gl_info *gl_info, GLuint id, BOOL program) DECLSPEC_HIDDEN;
+void shader_glsl_validate_link(const struct wined3d_gl_info *gl_info, GLuint program) DECLSPEC_HIDDEN;
+
 struct wined3d_palette
 {
     LONG ref;
-- 
2.3.6




More information about the wine-patches mailing list