wined3d: Implement color keying in arbfp_blit.
This commit is contained in:
parent
439076d591
commit
2d56694445
|
@ -6825,7 +6825,8 @@ struct arbfp_blit_type
|
|||
{
|
||||
enum complex_fixup fixup : 4;
|
||||
enum wined3d_gl_resource_type res_type : 3;
|
||||
DWORD padding : 25;
|
||||
DWORD use_color_key : 1;
|
||||
DWORD padding : 24;
|
||||
};
|
||||
|
||||
struct arbfp_blit_desc
|
||||
|
@ -6836,6 +6837,7 @@ struct arbfp_blit_desc
|
|||
};
|
||||
|
||||
#define ARBFP_BLIT_PARAM_SIZE 0
|
||||
#define ARBFP_BLIT_PARAM_COLOR_KEY 1
|
||||
|
||||
struct arbfp_blit_priv
|
||||
{
|
||||
|
@ -7287,6 +7289,11 @@ static GLuint gen_p8_shader(struct arbfp_blit_priv *priv,
|
|||
GLint pos;
|
||||
const char *tex_target = arbfp_texture_target(type->res_type);
|
||||
|
||||
/* This should not happen because we only use this conversion for
|
||||
* present blits which don't use color keying. */
|
||||
if (type->use_color_key)
|
||||
FIXME("Implement P8 color keying.\n");
|
||||
|
||||
/* Shader header */
|
||||
if (!shader_buffer_init(&buffer))
|
||||
{
|
||||
|
@ -7382,6 +7389,9 @@ static GLuint gen_yuv_shader(struct arbfp_blit_priv *priv, const struct wined3d_
|
|||
char luminance_component;
|
||||
GLint pos;
|
||||
|
||||
if (type->use_color_key)
|
||||
FIXME("Implement YUV color keying.\n");
|
||||
|
||||
/* Shader header */
|
||||
if (!shader_buffer_init(&buffer))
|
||||
{
|
||||
|
@ -7539,7 +7549,24 @@ static GLuint arbfp_gen_plain_shader(struct arbfp_blit_priv *priv,
|
|||
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader));
|
||||
|
||||
shader_addline(&buffer, "!!ARBfp1.0\n");
|
||||
|
||||
if (type->use_color_key)
|
||||
{
|
||||
shader_addline(&buffer, "TEMP color;\n");
|
||||
shader_addline(&buffer, "TEMP compare;\n");
|
||||
shader_addline(&buffer, "PARAM color_key = program.local[%u];\n", ARBFP_BLIT_PARAM_COLOR_KEY);
|
||||
shader_addline(&buffer, "TEX color, fragment.texcoord[0], texture[0], %s;\n", tex_target);
|
||||
shader_addline(&buffer, "SGE compare.r, color.a, color_key.a;\n");
|
||||
shader_addline(&buffer, "SGE compare.g, -color.a, -color_key.a;\n");
|
||||
shader_addline(&buffer, "MUL compare, compare.r, -compare.g;\n");
|
||||
shader_addline(&buffer, "KIL compare;\n");
|
||||
shader_addline(&buffer, "MOV result.color, color;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
shader_addline(&buffer, "TEX result.color, fragment.texcoord[0], texture[0], %s;\n", tex_target);
|
||||
}
|
||||
|
||||
shader_addline(&buffer, "END\n");
|
||||
|
||||
GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
|
||||
|
@ -7560,7 +7587,8 @@ static GLuint arbfp_gen_plain_shader(struct arbfp_blit_priv *priv,
|
|||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
|
||||
static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface,
|
||||
const struct wined3d_color_key *color_key)
|
||||
{
|
||||
GLenum shader;
|
||||
float size[4] = {(float) surface->pow2Width, (float) surface->pow2Height, 1.0f, 1.0f};
|
||||
|
@ -7571,6 +7599,7 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
|
|||
struct wine_rb_entry *entry;
|
||||
struct arbfp_blit_type type;
|
||||
struct arbfp_blit_desc *desc;
|
||||
float float_color_key[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
|
||||
if (is_complex_fixup(surface->resource.format->color_fixup))
|
||||
fixup = get_complex_fixup(surface->resource.format->color_fixup);
|
||||
|
@ -7604,7 +7633,7 @@ static HRESULT arbfp_blit_set(void *blit_priv, struct wined3d_context *context,
|
|||
type.res_type = WINED3D_GL_RES_TYPE_TEX_2D;
|
||||
}
|
||||
type.fixup = fixup;
|
||||
type.padding = 0;
|
||||
type.use_color_key = !!color_key;
|
||||
|
||||
entry = wine_rb_get(&priv->shaders, &type);
|
||||
if (entry)
|
||||
|
@ -7668,6 +7697,14 @@ err_out:
|
|||
checkGLcall("glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, shader)");
|
||||
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARBFP_BLIT_PARAM_SIZE, size));
|
||||
checkGLcall("glProgramLocalParameter4fvARB");
|
||||
if (type.use_color_key)
|
||||
{
|
||||
if (surface->resource.format->id == WINED3DFMT_P8_UINT)
|
||||
float_color_key[3] = color_key->color_space_low_value / 255.0f;
|
||||
|
||||
GL_EXTCALL(glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, ARBFP_BLIT_PARAM_COLOR_KEY, float_color_key));
|
||||
checkGLcall("glProgramLocalParameter4fvARB");
|
||||
}
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
@ -7688,8 +7725,13 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum win
|
|||
if (!gl_info->supported[ARB_FRAGMENT_PROGRAM])
|
||||
return FALSE;
|
||||
|
||||
if (blit_op != WINED3D_BLIT_OP_COLOR_BLIT)
|
||||
switch (blit_op)
|
||||
{
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT:
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
|
||||
break;
|
||||
|
||||
default:
|
||||
TRACE("Unsupported blit_op=%d\n", blit_op);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -7742,11 +7784,16 @@ static BOOL arbfp_blit_supported(const struct wined3d_gl_info *gl_info, enum win
|
|||
|
||||
HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
|
||||
struct wined3d_surface *src_surface, const RECT *src_rect_in,
|
||||
struct wined3d_surface *dst_surface, const RECT *dst_rect_in)
|
||||
struct wined3d_surface *dst_surface, const RECT *dst_rect_in,
|
||||
const struct wined3d_color_key *color_key)
|
||||
{
|
||||
struct wined3d_context *context;
|
||||
RECT src_rect = *src_rect_in;
|
||||
RECT dst_rect = *dst_rect_in;
|
||||
struct wined3d_color_key old_color_key = src_surface->container->async.src_blt_color_key;
|
||||
DWORD old_color_key_flags = src_surface->container->async.color_key_flags;
|
||||
|
||||
wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT, color_key);
|
||||
|
||||
/* Activate the destination context, set it up for blitting */
|
||||
context = context_acquire(device, dst_surface);
|
||||
|
@ -7775,7 +7822,7 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
|
|||
if (!wined3d_resource_is_offscreen(&dst_surface->container->resource))
|
||||
surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
|
||||
|
||||
arbfp_blit_set(device->blit_priv, context, src_surface);
|
||||
arbfp_blit_set(device->blit_priv, context, src_surface, color_key);
|
||||
|
||||
/* Draw a textured quad */
|
||||
draw_textured_quad(src_surface, context, &src_rect, &dst_rect, filter);
|
||||
|
@ -7793,6 +7840,9 @@ HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
|
|||
surface_validate_location(dst_surface, dst_surface->container->resource.draw_binding);
|
||||
surface_invalidate_location(dst_surface, ~dst_surface->container->resource.draw_binding);
|
||||
|
||||
wined3d_texture_set_color_key(src_surface->container, WINED3D_CKEY_SRC_BLT,
|
||||
(old_color_key_flags & WINED3D_CKEY_SRC_BLT) ? &old_color_key : NULL);
|
||||
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -3398,7 +3398,7 @@ static void surface_blt_to_drawable(const struct wined3d_device *device,
|
|||
if (!wined3d_resource_is_offscreen(&dst_surface->container->resource))
|
||||
surface_translate_drawable_coords(dst_surface, context->win_handle, &dst_rect);
|
||||
|
||||
device->blitter->set_shader(device->blit_priv, context, src_surface);
|
||||
device->blitter->set_shader(device->blit_priv, context, src_surface, NULL);
|
||||
|
||||
if (alpha_test)
|
||||
{
|
||||
|
@ -4290,7 +4290,8 @@ static HRESULT ffp_blit_alloc(struct wined3d_device *device) { return WINED3D_OK
|
|||
static void ffp_blit_free(struct wined3d_device *device) { }
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static HRESULT ffp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
|
||||
static HRESULT ffp_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface,
|
||||
const struct wined3d_color_key *color_key)
|
||||
{
|
||||
const struct wined3d_gl_info *gl_info = context->gl_info;
|
||||
|
||||
|
@ -4324,6 +4325,7 @@ static BOOL ffp_blit_supported(const struct wined3d_gl_info *gl_info, enum wined
|
|||
switch (blit_op)
|
||||
{
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT:
|
||||
case WINED3D_BLIT_OP_COLOR_BLIT_CKEY:
|
||||
if (src_pool == WINED3D_POOL_SYSTEM_MEM || dst_pool == WINED3D_POOL_SYSTEM_MEM)
|
||||
return FALSE;
|
||||
|
||||
|
@ -4434,7 +4436,8 @@ static void cpu_blit_free(struct wined3d_device *device)
|
|||
}
|
||||
|
||||
/* Context activation is done by the caller. */
|
||||
static HRESULT cpu_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface)
|
||||
static HRESULT cpu_blit_set(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface,
|
||||
const struct wined3d_color_key *color_key)
|
||||
{
|
||||
return WINED3D_OK;
|
||||
}
|
||||
|
@ -5078,6 +5081,8 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
|
|||
|
||||
static const DWORD simple_blit = WINEDDBLT_ASYNC
|
||||
| WINEDDBLT_COLORFILL
|
||||
| WINEDDBLT_KEYSRC
|
||||
| WINEDDBLT_KEYSRCOVERRIDE
|
||||
| WINEDDBLT_WAIT
|
||||
| WINEDDBLT_DEPTHFILL
|
||||
| WINEDDBLT_DONOTWAIT;
|
||||
|
@ -5290,12 +5295,24 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
|
|||
}
|
||||
else
|
||||
{
|
||||
TRACE("Color blit.\n");
|
||||
enum wined3d_blit_op blit_op = WINED3D_BLIT_OP_COLOR_BLIT;
|
||||
const struct wined3d_color_key *color_key = NULL;
|
||||
|
||||
/* Upload */
|
||||
if ((src_surface->locations & WINED3D_LOCATION_SYSMEM)
|
||||
TRACE("Color blit.\n");
|
||||
if (flags & WINEDDBLT_KEYSRCOVERRIDE)
|
||||
{
|
||||
color_key = &fx->ddckSrcColorkey;
|
||||
blit_op = WINED3D_BLIT_OP_COLOR_BLIT_CKEY;
|
||||
}
|
||||
else if (flags & WINEDDBLT_KEYSRC)
|
||||
{
|
||||
color_key = &src_surface->container->async.src_blt_color_key;
|
||||
blit_op = WINED3D_BLIT_OP_COLOR_BLIT_CKEY;
|
||||
}
|
||||
else if ((src_surface->locations & WINED3D_LOCATION_SYSMEM)
|
||||
&& !(dst_surface->locations & WINED3D_LOCATION_SYSMEM))
|
||||
{
|
||||
/* Upload */
|
||||
if (scale)
|
||||
TRACE("Not doing upload because of scaling.\n");
|
||||
else if (convert)
|
||||
|
@ -5312,17 +5329,16 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (dst_swapchain && dst_swapchain->back_buffers
|
||||
&& dst_surface->container == dst_swapchain->front_buffer
|
||||
&& src_surface->container == dst_swapchain->back_buffers[0])
|
||||
{
|
||||
/* Use present for back -> front blits. The idea behind this is
|
||||
* that present is potentially faster than a blit, in particular
|
||||
* when FBO blits aren't available. Some ddraw applications like
|
||||
* Half-Life and Prince of Persia 3D use Blt() from the backbuffer
|
||||
* to the frontbuffer instead of doing a Flip(). D3D8 and D3D9
|
||||
* applications can't blit directly to the frontbuffer. */
|
||||
if (dst_swapchain && dst_swapchain->back_buffers
|
||||
&& dst_surface->container == dst_swapchain->front_buffer
|
||||
&& src_surface->container == dst_swapchain->back_buffers[0])
|
||||
{
|
||||
enum wined3d_swap_effect swap_effect = dst_swapchain->desc.swap_effect;
|
||||
|
||||
TRACE("Using present for backbuffer -> frontbuffer blit.\n");
|
||||
|
@ -5336,7 +5352,7 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
if (fbo_blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
||||
if (fbo_blit_supported(&device->adapter->gl_info, blit_op,
|
||||
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
||||
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
||||
{
|
||||
|
@ -5351,13 +5367,14 @@ HRESULT CDECL wined3d_surface_blt(struct wined3d_surface *dst_surface, const REC
|
|||
return WINED3D_OK;
|
||||
}
|
||||
|
||||
if (arbfp_blit.blit_supported(&device->adapter->gl_info, WINED3D_BLIT_OP_COLOR_BLIT,
|
||||
if (arbfp_blit.blit_supported(&device->adapter->gl_info, blit_op,
|
||||
&src_rect, src_surface->resource.usage, src_surface->resource.pool, src_surface->resource.format,
|
||||
&dst_rect, dst_surface->resource.usage, dst_surface->resource.pool, dst_surface->resource.format))
|
||||
{
|
||||
TRACE("Using arbfp blit.\n");
|
||||
|
||||
if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect, dst_surface, &dst_rect)))
|
||||
if (SUCCEEDED(arbfp_blit_surface(device, filter, src_surface, &src_rect,
|
||||
dst_surface, &dst_rect, color_key)))
|
||||
return WINED3D_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -367,7 +367,7 @@ static void swapchain_blit(const struct wined3d_swapchain *swapchain,
|
|||
|
||||
/* Set up the texture. The surface is not in a wined3d_texture
|
||||
* container, so there are no D3D texture settings to dirtify. */
|
||||
device->blitter->set_shader(device->blit_priv, context2, backbuffer);
|
||||
device->blitter->set_shader(device->blit_priv, context2, backbuffer, NULL);
|
||||
gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter);
|
||||
gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, gl_filter);
|
||||
|
||||
|
|
|
@ -1323,6 +1323,7 @@ HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_
|
|||
enum wined3d_blit_op
|
||||
{
|
||||
WINED3D_BLIT_OP_COLOR_BLIT,
|
||||
WINED3D_BLIT_OP_COLOR_BLIT_CKEY,
|
||||
WINED3D_BLIT_OP_COLOR_FILL,
|
||||
WINED3D_BLIT_OP_DEPTH_FILL,
|
||||
WINED3D_BLIT_OP_DEPTH_BLIT,
|
||||
|
@ -1334,7 +1335,8 @@ struct blit_shader
|
|||
{
|
||||
HRESULT (*alloc_private)(struct wined3d_device *device);
|
||||
void (*free_private)(struct wined3d_device *device);
|
||||
HRESULT (*set_shader)(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface);
|
||||
HRESULT (*set_shader)(void *blit_priv, struct wined3d_context *context, const struct wined3d_surface *surface,
|
||||
const struct wined3d_color_key *color_key);
|
||||
void (*unset_shader)(const struct wined3d_gl_info *gl_info);
|
||||
BOOL (*blit_supported)(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
|
||||
const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
|
||||
|
@ -1357,7 +1359,8 @@ const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *g
|
|||
/* Temporary blit_shader helper functions */
|
||||
HRESULT arbfp_blit_surface(struct wined3d_device *device, DWORD filter,
|
||||
struct wined3d_surface *src_surface, const RECT *src_rect,
|
||||
struct wined3d_surface *dst_surface, const RECT *dst_rect) DECLSPEC_HIDDEN;
|
||||
struct wined3d_surface *dst_surface, const RECT *dst_rect,
|
||||
const struct wined3d_color_key *color_key) DECLSPEC_HIDDEN;
|
||||
|
||||
struct wined3d_context *context_acquire(const struct wined3d_device *device,
|
||||
struct wined3d_surface *target) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Reference in New Issue