Martin Storsjo : wined3d: Use an rbtree for storing shaders for texture format conversion/blitting.
Alexandre Julliard
julliard at winehq.org
Mon Feb 17 13:45:16 CST 2014
Module: wine
Branch: master
Commit: 12755257898e72cf47798b467a5467fef56eed9e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=12755257898e72cf47798b467a5467fef56eed9e
Author: Martin Storsjo <martin at martin.st>
Date: Mon Feb 17 14:46:01 2014 +0200
wined3d: Use an rbtree for storing shaders for texture format conversion/blitting.
---
dlls/wined3d/arb_program_shader.c | 183 ++++++++++++++++++++++---------------
1 file changed, 107 insertions(+), 76 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 93a6e31..d7e9ef7 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_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)
{
- device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv));
- if(!device->blit_priv) {
- ERR("Out of memory\n");
+ struct arbfp_blit_priv *priv;
+
+ if (!(priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*priv))))
+ return E_OUTOFMEMORY;
+
+ if (wine_rb_init(&priv->shaders, &wined3d_arbfp_blit_rb_functions) == -1)
+ {
+ ERR("Failed to initialize rbtree.\n");
+ HeapFree(GetProcessHeap(), 0, priv);
return E_OUTOFMEMORY;
}
+
+ device->blit_priv = priv;
+
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);
@@ -7196,6 +7237,7 @@ 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)
{
@@ -7249,11 +7291,6 @@ 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);
return shader;
@@ -7428,33 +7465,6 @@ static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_
shader_buffer_free(&buffer);
- switch (yuv_fixup)
- {
- 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;
-
- 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);
- }
-
return shader;
}
@@ -7467,6 +7477,9 @@ 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;
+ struct arbfp_blit_desc *desc;
if (surface->flags & SFLAG_CONVERTED)
{
@@ -7487,39 +7500,57 @@ 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);
+ 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;
+ }
+
+ desc = HeapAlloc(GetProcessHeap(), 0, sizeof(*desc));
+ if (!desc)
+ goto err_out;
+
+ desc->type.textype = textype;
+ desc->type.fixup = fixup;
+ desc->shader = shader;
+ if (wine_rb_put(&priv->shaders, &desc->type, &desc->entry) == -1)
+ {
+err_out:
+ ERR("Out of memory\n");
+ 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)");
+ HeapFree(GetProcessHeap(), 0, desc);
+ return E_OUTOFMEMORY;
+ }
}
- 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)");
More information about the wine-cvs
mailing list