wined3d: Use an rbtree for storing shaders for texture format conversion/blitting.
This commit is contained in:
parent
171529106b
commit
1275525789
|
@ -6768,22 +6768,72 @@ const struct fragment_pipeline arbfp_fragment_pipeline = {
|
||||||
arbfp_fragmentstate_template,
|
arbfp_fragmentstate_template,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct arbfp_blit_priv {
|
struct arbfp_blit_type
|
||||||
GLenum yuy2_rect_shader, yuy2_2d_shader;
|
{
|
||||||
GLenum uyvy_rect_shader, uyvy_2d_shader;
|
enum complex_fixup fixup;
|
||||||
GLenum yv12_rect_shader, yv12_2d_shader;
|
GLenum textype;
|
||||||
GLenum nv12_rect_shader, nv12_2d_shader;
|
};
|
||||||
GLenum p8_rect_shader, p8_2d_shader;
|
|
||||||
|
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;
|
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)
|
static HRESULT arbfp_blit_alloc(struct wined3d_device *device)
|
||||||
{
|
{
|
||||||
device->blit_priv = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(struct arbfp_blit_priv));
|
struct arbfp_blit_priv *priv;
|
||||||
if(!device->blit_priv) {
|
|
||||||
ERR("Out of memory\n");
|
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;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
device->blit_priv = priv;
|
||||||
|
|
||||||
return WINED3D_OK;
|
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;
|
const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
|
||||||
struct arbfp_blit_priv *priv = device->blit_priv;
|
struct arbfp_blit_priv *priv = device->blit_priv;
|
||||||
|
|
||||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_rect_shader));
|
wine_rb_destroy(&priv->shaders, arbfp_free_blit_shader, &device->adapter->gl_info);
|
||||||
GL_EXTCALL(glDeleteProgramsARB(1, &priv->yuy2_2d_shader));
|
checkGLcall("Delete blit programs");
|
||||||
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");
|
|
||||||
|
|
||||||
if (priv->palette_texture)
|
if (priv->palette_texture)
|
||||||
gl_info->gl_ops.gl.p_glDeleteTextures(1, &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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Context activation is done by the caller. */
|
||||||
static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
|
static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
|
||||||
const struct wined3d_gl_info *gl_info, GLenum textype)
|
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);
|
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);
|
shader_buffer_free(&buffer);
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
|
@ -7428,33 +7465,6 @@ static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_
|
||||||
|
|
||||||
shader_buffer_free(&buffer);
|
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;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7467,6 +7477,9 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
|
||||||
enum complex_fixup fixup;
|
enum complex_fixup fixup;
|
||||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||||
GLenum textype = surface->container->target;
|
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)
|
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);
|
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:
|
desc = WINE_RB_ENTRY_VALUE(entry, struct arbfp_blit_desc, entry);
|
||||||
shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->yuy2_rect_shader : priv->yuy2_2d_shader;
|
shader = desc->shader;
|
||||||
break;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (fixup)
|
||||||
|
{
|
||||||
|
case COMPLEX_FIXUP_P8:
|
||||||
|
shader = gen_p8_shader(priv, gl_info, textype);
|
||||||
|
break;
|
||||||
|
|
||||||
case COMPLEX_FIXUP_UYVY:
|
default:
|
||||||
shader = textype == GL_TEXTURE_RECTANGLE_ARB ? priv->uyvy_rect_shader : priv->uyvy_2d_shader;
|
shader = gen_yuv_shader(priv, gl_info, fixup, textype);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case COMPLEX_FIXUP_YV12:
|
if (!shader)
|
||||||
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);
|
|
||||||
|
|
||||||
upload_palette(surface, context);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup);
|
FIXME("Unsupported complex fixup %#x, not setting a shader\n", fixup);
|
||||||
gl_info->gl_ops.gl.p_glEnable(textype);
|
gl_info->gl_ops.gl.p_glEnable(textype);
|
||||||
checkGLcall("glEnable(textype)");
|
checkGLcall("glEnable(textype)");
|
||||||
return E_NOTIMPL;
|
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);
|
gl_info->gl_ops.gl.p_glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
|
checkGLcall("glEnable(GL_FRAGMENT_PROGRAM_ARB)");
|
||||||
|
|
Loading…
Reference in New Issue