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

Stefan Dösinger stefandoesinger at gmail.com
Thu Feb 13 07:13:45 CST 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Looks good to me.

Am 2014-02-13 13:05, schrieb Martin Storsjo:
> --- Fixed the final style issues and added comments about who 
> activates the GL context. --- dlls/wined3d/arb_program_shader.c |
> 204 +++++++++++++++++++++++++------------- 1 file changed, 134
> insertions(+), 70 deletions(-)
> 
> diff --git a/dlls/wined3d/arb_program_shader.c
> b/dlls/wined3d/arb_program_shader.c index 93a6e31..a273eac 100644 
> --- a/dlls/wined3d/arb_program_shader.c +++
> b/dlls/wined3d/arb_program_shader.c @@ -6768,22 +6768,74 @@ const
> struct fragment_pipeline arbfp_fragment_pipeline = { 
> arbfp_fragmentstate_template, };
> 
> -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 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 +{ +    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; +} + +/* Context activation is done by the caller. */ 
> +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 +6845,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); @@ -7196,12 +7239,14 @@ static BOOL
> gen_nv12_read(struct wined3d_shader_buffer *buffer, GLenum
> textype, return TRUE; }
> 
> +/* Context activation is done by the caller. */ static GLuint
> gen_p8_shader(struct arbfp_blit_priv *priv, const struct
> wined3d_gl_info *gl_info, GLenum textype) { GLenum shader; struct
> wined3d_shader_buffer buffer; GLint pos; +    struct
> arbfp_blit_desc *desc;
> 
> /* Shader header */ if (!shader_buffer_init(&buffer)) @@ -7249,14
> +7294,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 +7363,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
> +7494,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 +7531,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,39 +7553,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; - -        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); +        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 = gen_p8_shader(priv,
> gl_info, textype); +                break;
> 
> -            upload_palette(surface, context); -            break; 
> +            default: +                shader =
> gen_yuv_shader(priv, gl_info, fixup, textype); +
> break; +        }
> 
> -        default: +        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); +    if (fixup == COMPLEX_FIXUP_P8) +
> upload_palette(surface, context);
> 
> gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB); 
> checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
> 

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.22 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJS/MUJAAoJEN0/YqbEcdMwJDEQAIEBkWRt2YIly+I+2jO2Y2al
MxewjsCeQRf2uFnn4QIVNSfBOrjx6tq5d4aaj0pMlW2O98nXpVJWrHH5suqdX3IP
F57tC6bLkucvwuutKFn+h5JohkHw7mjiPjDMYV2H2Lml3Yy0CXDfpSUJsREfTXgl
YefKfzxIjckRV/u64kCTOxXCjkeI1LakEWIs8zL8QKXHSUIQtUHfN5uNynbhSnNq
SU7+d3B/p/ZFvdOpT6HyhXHyGmx584CcmDTIz9tj6JG0oWmHE6dLZoIrgR/f32iH
M0SYfxFEpRhv26a3NFEx98VAHTarZKkMTrcu6QQIgZ0RiC1jpSOvidk98sIK7dbr
T+ynOho0GaZt5ZC0pvc1w6GPw7sf040Oz2JcSqIxDX+S5JjqG7PsMvJSYcziY8xJ
eBrYgpO/Db5DVyOHfEuFbcS6fyLcO9P9hi2VvhQx2TR9q2XQEMklMamo+OTGng5t
cx61mfvCLUF/BsQBteW/SAIHaUGfKgUOgmPIJpucssVbULVXnxI1op1PcczvT6JP
xqaG+GiXzuDMulcQR+gnYz7oWnMWj2AA+bPVrTKUhZTbEupUgG9j8CsxeJ678tlk
bBKK1p/3UBz1+oc7Qo+Yu6mBVSjPSxwczxmErWe+L7K1kP2L8vtqYg06CSTPH8t7
Y6kf6yuWGIbyapYMcuAO
=jA/i
-----END PGP SIGNATURE-----



More information about the wine-devel mailing list