[PATCHv2 2/3] wined3d: Use an rbtree for storing shaders for texture format conversion/blitting

Martin Storsjo martin at martin.st
Wed Feb 12 14:05:39 CST 2014


---
Using explicit comparisons of the two fields instead of memcmp()
of a struct for the key comparison, sharing code for error
paths using goto, and fixed the accidentally removed line for P8
conversion.
---
 dlls/wined3d/arb_program_shader.c | 192 +++++++++++++++++++++++++-------------
 1 file changed, 126 insertions(+), 66 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 93a6e31..4e7477f 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -6768,22 +6768,72 @@ const struct fragment_pipeline arbfp_fragment_pipeline = {
     arbfp_fragmentstate_template,
 };
 
+struct arbfp_blit_type
+{
+    enum complex_fixup fixup;
+    GLenum textype;
+};
+
+struct arbfp_blit_desc
+{
+    GLenum shader;
+    struct arbfp_blit_type type;
+    struct wine_rb_entry entry;
+};
+
 struct arbfp_blit_priv {
-    GLenum yuy2_rect_shader, yuy2_2d_shader;
-    GLenum uyvy_rect_shader, uyvy_2d_shader;
-    GLenum yv12_rect_shader, yv12_2d_shader;
-    GLenum nv12_rect_shader, nv12_2d_shader;
-    GLenum p8_rect_shader, p8_2d_shader;
+    struct wine_rb_tree shaders;
     GLuint palette_texture;
 };
 
+static int arbfp_blit_type_compare(const void *key, const struct wine_rb_entry *entry)
+{
+    const struct arbfp_blit_type *ka = key;
+    const struct arbfp_blit_type *kb = &WINE_RB_ENTRY_VALUE(entry, const struct arbfp_blit_desc, entry)->type;
+
+    if (ka->fixup != kb->fixup)
+        return ka->fixup < kb->fixup ? -1 : 1;
+    if (ka->textype != kb->textype)
+        return ka->textype < kb->textype ? -1 : 1;
+    return 0;
+}
+
+static void arbfp_free_blit_shader(struct wine_rb_entry *entry, void *context)
+{
+    const struct wined3d_gl_info *gl_info = context;
+    struct arbfp_blit_desc *entry_arb = WINE_RB_ENTRY_VALUE(entry, struct arbfp_blit_desc, entry);
+
+    GL_EXTCALL(glDeleteProgramsARB(1, &entry_arb->shader));
+    checkGLcall("glDeleteProgramsARB(1, &entry_arb->shader)");
+    HeapFree(GetProcessHeap(), 0, entry_arb);
+}
+
+const struct wine_rb_functions wined3d_arbfp_blit_rb_functions =
+{
+    wined3d_rb_alloc,
+    wined3d_rb_realloc,
+    wined3d_rb_free,
+    arbfp_blit_type_compare,
+};
+
 static HRESULT arbfp_blit_alloc(struct wined3d_device *device)
 {
+    struct arbfp_blit_priv *priv;
     device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv));
     if(!device->blit_priv) {
         ERR("Out of memory\n");
         return E_OUTOFMEMORY;
     }
+    priv = device->blit_priv;
+
+    if (wine_rb_init(&priv->shaders, &wined3d_arbfp_blit_rb_functions) == -1)
+    {
+        ERR("Failed to initialize rbtree.\n");
+        HeapFree(GetProcessHeap(), 0, device->blit_priv);
+        device->blit_priv = NULL;
+        return E_OUTOFMEMORY;
+    }
+
     return WINED3D_OK;
 }
 
@@ -6793,17 +6843,8 @@ static void arbfp_blit_free(struct wined3d_device *device)
     const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
     struct arbfp_blit_priv *priv = device->blit_priv;
 
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_rect_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_rect_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->uyvy_2d_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_rect_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->yv12_2d_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->nv12_rect_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->nv12_2d_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_rect_shader));
-    GL_EXTCALL(glDeleteProgramsARB(1, &priv->p8_2d_shader));
-    checkGLcall("Delete yuv and p8 programs");
+    wine_rb_destroy(&priv->shaders, arbfp_free_blit_shader, &device->adapter->gl_info);
+    checkGLcall("Delete blit programs");
 
     if (priv->palette_texture)
         gl_info->gl_ops.gl.p_glDeleteTextures(1, &priv->palette_texture);
@@ -7202,6 +7243,7 @@ static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
     GLenum shader;
     struct wined3d_shader_buffer buffer;
     GLint pos;
+    struct arbfp_blit_desc *desc;
 
     /* Shader header */
     if (!shader_buffer_init(&buffer))
@@ -7249,14 +7291,34 @@ static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
         shader_arb_dump_program_source(buffer.buffer);
     }
 
-    if (textype == GL_TEXTURE_RECTANGLE_ARB)
-        priv->p8_rect_shader = shader;
-    else
-        priv->p8_2d_shader = shader;
-
     shader_buffer_free(&buffer);
 
+    desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));
+    if (!desc)
+    {
+        ERR("Out of memory\n");
+        goto err_out;
+    }
+
+    desc->type.textype = textype;
+    desc->type.fixup = COMPLEX_FIXUP_P8;
+    desc->shader = shader;
+    if (wine_rb_put(&priv->shaders, &desc->type, &desc->entry) == -1)
+    {
+        ERR("Out of memory\n");
+        goto err_out;
+    }
+
     return shader;
+
+err_out:
+    GL_EXTCALL(glDeleteProgramsARB(1, &shader));
+    checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader))");
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0));
+    checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0)");
+    if (desc)
+        HeapFree(GetProcessHeap(), 0, desc);
+    return 0;
 }
 
 /* Context activation is done by the caller. */
@@ -7298,6 +7360,7 @@ static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_
     struct wined3d_shader_buffer buffer;
     char luminance_component;
     GLint pos;
+    struct arbfp_blit_desc *desc;
 
     /* Shader header */
     if (!shader_buffer_init(&buffer))
@@ -7428,34 +7491,32 @@ static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_
 
     shader_buffer_free(&buffer);
 
-    switch (yuv_fixup)
+    desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));
+    if (!desc)
     {
-        case COMPLEX_FIXUP_YUY2:
-            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yuy2_rect_shader = shader;
-            else priv->yuy2_2d_shader = shader;
-            break;
-
-        case COMPLEX_FIXUP_UYVY:
-            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->uyvy_rect_shader = shader;
-            else priv->uyvy_2d_shader = shader;
-            break;
-
-        case COMPLEX_FIXUP_YV12:
-            if (textype == GL_TEXTURE_RECTANGLE_ARB) priv->yv12_rect_shader = shader;
-            else priv->yv12_2d_shader = shader;
-            break;
+        ERR("Out of memory\n");
+        goto err_out;
+    }
 
-        case COMPLEX_FIXUP_NV12:
-            if (textype == GL_TEXTURE_RECTANGLE_ARB)
-                priv->nv12_rect_shader = shader;
-            else
-                priv->nv12_2d_shader = shader;
-            break;
-        default:
-            ERR("Unsupported complex fixup: %d\n", yuv_fixup);
+    desc->type.textype = textype;
+    desc->type.fixup = yuv_fixup;
+    desc->shader = shader;
+    if (wine_rb_put(&priv->shaders, &desc->type, &desc->entry) == -1)
+    {
+        ERR("Out of memory\n");
+        goto err_out;
     }
 
     return shader;
+
+err_out:
+    GL_EXTCALL(glDeleteProgramsARB(1, &shader));
+    checkGLcall("GL_EXTCALL(glDeleteProgramsARB(1, &shader))");
+    GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0));
+    checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, 0)");
+    if (desc)
+        HeapFree(GetProcessHeap(), 0, desc);
+    return 0;
 }
 
 /* Context activation is done by the caller. */
@@ -7467,6 +7528,8 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
     enum complex_fixup fixup;
     const struct wined3d_gl_info *gl_info = context->gl_info;
     GLenum textype = surface->container->target;
+    struct wine_rb_entry *entry;
+    struct arbfp_blit_type type;
 
     if (surface->flags & SFLAG_CONVERTED)
     {
@@ -7487,40 +7550,37 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
 
     fixup = get_complex_fixup(surface->resource.format->color_fixup);
 
-    switch(fixup)
+    type.fixup = fixup;
+    type.textype = textype;
+    entry = wine_rb_get(&priv->shaders, &type);
+    if (entry)
     {
-        case COMPLEX_FIXUP_YUY2:
-            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yuy2_rect_shader : priv->yuy2_2d_shader;
-            break;
-
-        case COMPLEX_FIXUP_UYVY:
-            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->uyvy_rect_shader : priv->uyvy_2d_shader;
-            break;
-
-        case COMPLEX_FIXUP_YV12:
-            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yv12_rect_shader : priv->yv12_2d_shader;
-            break;
-
-        case COMPLEX_FIXUP_NV12:
-            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->nv12_rect_shader : priv->nv12_2d_shader;
-            break;
-
+        struct arbfp_blit_desc *desc = WINE_RB_ENTRY_VALUE(entry, struct arbfp_blit_desc, entry);
+        shader = desc->shader;
+    }
+    else
+    {
+        switch(fixup)
+        {
         case COMPLEX_FIXUP_P8:
-            shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->p8_rect_shader : priv->p8_2d_shader;
-            if (!shader) shader = gen_p8_shader(priv, gl_info, textype);
-
+            shader = gen_p8_shader(priv, gl_info, textype);
             upload_palette(surface, context);
             break;
 
         default:
+            shader = gen_yuv_shader(priv, gl_info, fixup, textype);
+            break;
+        }
+
+        if (!shader)
+        {
             FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup);
             gl_info->gl_ops.gl.p_glEnable(textype);
             checkGLcall("glEnable(textype)");
             return E_NOTIMPL;
+        }
     }
 
-    if (!shader) shader = gen_yuv_shader(priv, gl_info, fixup, textype);
-
     gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
     checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
     GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
-- 
1.8.3.4 (Apple Git-47)




More information about the wine-patches mailing list