wined3d: Implement P8 blits in the GLSL blitter.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
38ed82edab
commit
a46e47f8d0
|
@ -12267,6 +12267,7 @@ struct wined3d_glsl_blitter
|
|||
struct wined3d_blitter blitter;
|
||||
struct wined3d_string_buffer_list string_buffers;
|
||||
struct wine_rb_tree programs;
|
||||
GLuint palette_texture;
|
||||
};
|
||||
|
||||
static int glsl_blitter_args_compare(const void *key, const struct wine_rb_entry *entry)
|
||||
|
@ -12292,6 +12293,7 @@ static void glsl_free_blitter_program(struct wine_rb_entry *entry, void *ctx)
|
|||
/* Context activation is done by the caller. */
|
||||
static void glsl_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d_context *context)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct wined3d_glsl_blitter *glsl_blitter;
|
||||
struct wined3d_blitter *next;
|
||||
|
||||
|
@ -12300,12 +12302,44 @@ static void glsl_blitter_destroy(struct wined3d_blitter *blitter, struct wined3d
|
|||
|
||||
glsl_blitter = CONTAINING_RECORD(blitter, struct wined3d_glsl_blitter, blitter);
|
||||
|
||||
if (glsl_blitter->palette_texture)
|
||||
gl_info->gl_ops.gl.p_glDeleteTextures(1, &glsl_blitter->palette_texture);
|
||||
|
||||
wine_rb_destroy(&glsl_blitter->programs, glsl_free_blitter_program, context);
|
||||
string_buffer_list_cleanup(&glsl_blitter->string_buffers);
|
||||
|
||||
heap_free(glsl_blitter);
|
||||
}
|
||||
|
||||
static void glsl_blitter_generate_p8_shader(struct wined3d_string_buffer *buffer,
|
||||
const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
|
||||
const char *output, const char *tex_type, const char *swizzle)
|
||||
{
|
||||
shader_addline(buffer, "uniform sampler1D sampler_palette;\n");
|
||||
shader_addline(buffer, "\nvoid main()\n{\n");
|
||||
/* The alpha-component contains the palette index. */
|
||||
shader_addline(buffer, " float index = texture%s(sampler, out_texcoord.%s).w;\n",
|
||||
needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
|
||||
/* Scale the index by 255/256 and add a bias of 0.5 in order to sample in
|
||||
* the middle. */
|
||||
shader_addline(buffer, " index = (index * 255.0 + 0.5) / 256.0;\n");
|
||||
shader_addline(buffer, " %s = texture%s(sampler_palette, index);\n",
|
||||
output, needs_legacy_glsl_syntax(gl_info) ? "1D" : "");
|
||||
shader_addline(buffer, "}\n");
|
||||
}
|
||||
|
||||
static void glsl_blitter_generate_plain_shader(struct wined3d_string_buffer *buffer,
|
||||
const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args,
|
||||
const char *output, const char *tex_type, const char *swizzle)
|
||||
{
|
||||
shader_addline(buffer, "\nvoid main()\n{\n");
|
||||
shader_addline(buffer, " %s = texture%s(sampler, out_texcoord.%s);\n",
|
||||
output, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
|
||||
shader_glsl_color_correction_ext(buffer, output, WINED3DSP_WRITEMASK_ALL, args->fixup);
|
||||
shader_addline(buffer, "}\n");
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter,
|
||||
const struct wined3d_gl_info *gl_info, const struct glsl_blitter_args *args)
|
||||
{
|
||||
|
@ -12328,14 +12362,12 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter
|
|||
" gl_Position = vec4(pos, 0.0, 1.0);\n"
|
||||
" out_texcoord = texcoord;\n"
|
||||
"}\n";
|
||||
static const char fshader_header[] =
|
||||
"\n"
|
||||
"void main()\n"
|
||||
"{\n";
|
||||
struct wined3d_string_buffer *buffer, *string;
|
||||
enum complex_fixup complex_fixup = get_complex_fixup(args->fixup);
|
||||
struct wined3d_string_buffer *buffer, *output;
|
||||
GLuint program, vshader_id, fshader_id;
|
||||
const char *tex_type, *swizzle, *ptr;
|
||||
unsigned int i;
|
||||
GLint loc;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(texture_data); ++i)
|
||||
{
|
||||
|
@ -12377,14 +12409,15 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter
|
|||
if (!needs_legacy_glsl_syntax(gl_info))
|
||||
shader_addline(buffer, "out vec4 ps_out[1];\n");
|
||||
|
||||
shader_addline(buffer, fshader_header);
|
||||
string = string_buffer_get(&blitter->string_buffers);
|
||||
string_buffer_sprintf(string, "%s[0]", get_fragment_output(gl_info));
|
||||
shader_addline(buffer, " %s = texture%s(sampler, out_texcoord.%s);\n",
|
||||
string->buffer, needs_legacy_glsl_syntax(gl_info) ? tex_type : "", swizzle);
|
||||
shader_glsl_color_correction_ext(buffer, string->buffer, WINED3DSP_WRITEMASK_ALL, args->fixup);
|
||||
string_buffer_release(&blitter->string_buffers, string);
|
||||
shader_addline(buffer, "}\n");
|
||||
output = string_buffer_get(&blitter->string_buffers);
|
||||
string_buffer_sprintf(output, "%s[0]", get_fragment_output(gl_info));
|
||||
|
||||
if (complex_fixup == COMPLEX_FIXUP_P8)
|
||||
glsl_blitter_generate_p8_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle);
|
||||
else
|
||||
glsl_blitter_generate_plain_shader(buffer, gl_info, args, output->buffer, tex_type, swizzle);
|
||||
|
||||
string_buffer_release(&blitter->string_buffers, output);
|
||||
|
||||
ptr = buffer->buffer;
|
||||
GL_EXTCALL(glShaderSource(fshader_id, 1, &ptr, NULL));
|
||||
|
@ -12404,15 +12437,61 @@ static GLuint glsl_blitter_generate_program(struct wined3d_glsl_blitter *blitter
|
|||
print_glsl_info_log(gl_info, fshader_id, FALSE);
|
||||
GL_EXTCALL(glLinkProgram(program));
|
||||
shader_glsl_validate_link(gl_info, program);
|
||||
|
||||
GL_EXTCALL(glUseProgram(program));
|
||||
loc = GL_EXTCALL(glGetUniformLocation(program, "sampler"));
|
||||
GL_EXTCALL(glUniform1i(loc, 0));
|
||||
if (complex_fixup == COMPLEX_FIXUP_P8)
|
||||
{
|
||||
loc = GL_EXTCALL(glGetUniformLocation(program, "sampler_palette"));
|
||||
GL_EXTCALL(glUniform1i(loc, 1));
|
||||
}
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static GLuint glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
|
||||
static void glsl_blitter_upload_palette(struct wined3d_glsl_blitter *blitter,
|
||||
struct wined3d_context *context, const struct wined3d_texture *texture)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
const struct wined3d_palette *palette;
|
||||
|
||||
palette = texture->swapchain ? texture->swapchain->palette : NULL;
|
||||
|
||||
if (!blitter->palette_texture)
|
||||
gl_info->gl_ops.gl.p_glGenTextures(1, &blitter->palette_texture);
|
||||
|
||||
context_active_texture(context, gl_info, 1);
|
||||
gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, blitter->palette_texture);
|
||||
gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
|
||||
if (palette)
|
||||
{
|
||||
gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 256, 0, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, palette->colors);
|
||||
}
|
||||
else
|
||||
{
|
||||
static const DWORD black;
|
||||
|
||||
FIXME("P8 texture loaded without a palette.\n");
|
||||
gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 1, 0, GL_BGRA,
|
||||
GL_UNSIGNED_INT_8_8_8_8_REV, &black);
|
||||
}
|
||||
|
||||
context_active_texture(context, gl_info, 0);
|
||||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static struct glsl_blitter_program *glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
|
||||
struct wined3d_context *context, const struct wined3d_texture *texture)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct glsl_blitter_program *program;
|
||||
enum complex_fixup complex_fixup;
|
||||
struct glsl_blitter_args args;
|
||||
struct wine_rb_entry *entry;
|
||||
|
||||
|
@ -12420,22 +12499,20 @@ static GLuint glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
|
|||
args.texture_type = texture->target;
|
||||
args.fixup = texture->resource.format->color_fixup;
|
||||
|
||||
if (is_complex_fixup(args.fixup))
|
||||
complex_fixup = get_complex_fixup(args.fixup);
|
||||
if (complex_fixup && complex_fixup != COMPLEX_FIXUP_P8)
|
||||
{
|
||||
FIXME("Complex fixups not supported.\n");
|
||||
return 0;
|
||||
FIXME("Complex fixup %#x not supported.\n", complex_fixup);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((entry = wine_rb_get(&blitter->programs, &args)))
|
||||
{
|
||||
program = WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry);
|
||||
return program->id;
|
||||
}
|
||||
return WINE_RB_ENTRY_VALUE(entry, struct glsl_blitter_program, entry);
|
||||
|
||||
if (!(program = heap_alloc(sizeof(*program))))
|
||||
{
|
||||
ERR("Failed to allocate blitter program memory.\n");
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
program->args = args;
|
||||
|
@ -12443,7 +12520,7 @@ static GLuint glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
|
|||
{
|
||||
WARN("Failed to generate blitter program.\n");
|
||||
heap_free(program);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wine_rb_put(&blitter->programs, &program->args, &program->entry) == -1)
|
||||
|
@ -12451,10 +12528,10 @@ static GLuint glsl_blitter_get_program(struct wined3d_glsl_blitter *blitter,
|
|||
ERR("Failed to store blitter program.\n");
|
||||
GL_EXTCALL(glDeleteProgram(program->id));
|
||||
heap_free(program);
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return program->id;
|
||||
return program;
|
||||
}
|
||||
|
||||
static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wined3d_context *context,
|
||||
|
@ -12465,6 +12542,7 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
|
|||
const struct wined3d_resource *dst_resource = &dst_texture->resource;
|
||||
const struct wined3d_format *src_format = src_resource->format;
|
||||
const struct wined3d_format *dst_format = dst_resource->format;
|
||||
enum complex_fixup complex_fixup = COMPLEX_FIXUP_NONE;
|
||||
BOOL decompress;
|
||||
|
||||
if (blit_op == WINED3D_BLIT_OP_RAW_BLIT && dst_format->id == src_format->id)
|
||||
|
@ -12506,11 +12584,16 @@ static BOOL glsl_blitter_supported(enum wined3d_blit_op blit_op, const struct wi
|
|||
|
||||
if (is_complex_fixup(src_format->color_fixup))
|
||||
{
|
||||
TRACE("Complex source fixups are not supported.\n");
|
||||
complex_fixup = get_complex_fixup(src_format->color_fixup);
|
||||
if (complex_fixup != COMPLEX_FIXUP_P8)
|
||||
{
|
||||
TRACE("Complex source fixup %#x not supported.\n", complex_fixup);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_identity_fixup(dst_format->color_fixup))
|
||||
if (!is_identity_fixup(dst_format->color_fixup)
|
||||
&& (dst_format->id != src_format->id || dst_location != WINED3D_LOCATION_DRAWABLE))
|
||||
{
|
||||
TRACE("Destination fixups are not supported.\n");
|
||||
return FALSE;
|
||||
|
@ -12530,9 +12613,9 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
struct wined3d_texture *staging_texture = NULL;
|
||||
struct wined3d_glsl_blitter *glsl_blitter;
|
||||
struct glsl_blitter_program *program;
|
||||
struct wined3d_blitter *next;
|
||||
unsigned int src_level;
|
||||
GLuint program_id;
|
||||
RECT s, d;
|
||||
|
||||
TRACE("blitter %p, op %#x, context %p, src_texture %p, src_sub_resource_idx %u, src_location %s, src_rect %s, "
|
||||
|
@ -12644,12 +12727,14 @@ static DWORD glsl_blitter_blit(struct wined3d_blitter *blitter, enum wined3d_bli
|
|||
context_invalidate_state(context, STATE_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
if (!(program_id = glsl_blitter_get_program(glsl_blitter, context, src_texture)))
|
||||
if (!(program = glsl_blitter_get_program(glsl_blitter, context, src_texture)))
|
||||
{
|
||||
ERR("Failed to get blitter program.\n");
|
||||
return dst_location;
|
||||
}
|
||||
GL_EXTCALL(glUseProgram(program_id));
|
||||
GL_EXTCALL(glUseProgram(program->id));
|
||||
if (get_complex_fixup(program->args.fixup) == COMPLEX_FIXUP_P8)
|
||||
glsl_blitter_upload_palette(glsl_blitter, context, src_texture);
|
||||
context_draw_shaded_quad(context, src_texture, src_sub_resource_idx, src_rect, dst_rect, filter);
|
||||
GL_EXTCALL(glUseProgram(0));
|
||||
|
||||
|
@ -12703,5 +12788,6 @@ void wined3d_glsl_blitter_create(struct wined3d_blitter **next, const struct win
|
|||
blitter->blitter.next = *next;
|
||||
string_buffer_list_init(&blitter->string_buffers);
|
||||
wine_rb_init(&blitter->programs, glsl_blitter_args_compare);
|
||||
blitter->palette_texture = 0;
|
||||
*next = &blitter->blitter;
|
||||
}
|
||||
|
|
|
@ -3285,7 +3285,7 @@ static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_
|
|||
0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE);
|
||||
}
|
||||
|
||||
if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
|
||||
if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER])
|
||||
{
|
||||
idx = get_format_idx(WINED3DFMT_P8_UINT);
|
||||
gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
|
||||
|
|
Loading…
Reference in New Issue