mirror of https://github.com/mpv-player/mpv
parent
c0f272fcd1
commit
fd5098a409
|
@ -38,7 +38,6 @@
|
||||||
#include "common/common.h"
|
#include "common/common.h"
|
||||||
#include "w32_common.h"
|
#include "w32_common.h"
|
||||||
#include "sub/osd.h"
|
#include "sub/osd.h"
|
||||||
#include "bitmap_packer.h"
|
|
||||||
|
|
||||||
// shaders generated by fxc.exe from d3d_shader_yuv.hlsl
|
// shaders generated by fxc.exe from d3d_shader_yuv.hlsl
|
||||||
#include "d3d_shader_420p.h"
|
#include "d3d_shader_420p.h"
|
||||||
|
@ -105,7 +104,6 @@ struct osdpart {
|
||||||
struct d3dtex texture;
|
struct d3dtex texture;
|
||||||
int num_vertices;
|
int num_vertices;
|
||||||
vertex_osd *vertices;
|
vertex_osd *vertices;
|
||||||
struct bitmap_packer *packer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum shaders {
|
enum shaders {
|
||||||
|
@ -1215,13 +1213,8 @@ static int preinit(struct vo *vo)
|
||||||
priv->vo = vo;
|
priv->vo = vo;
|
||||||
priv->log = vo->log;
|
priv->log = vo->log;
|
||||||
|
|
||||||
for (int n = 0; n < MAX_OSD_PARTS; n++) {
|
for (int n = 0; n < MAX_OSD_PARTS; n++)
|
||||||
struct osdpart *osd = talloc_ptrtype(priv, osd);
|
priv->osd[n] = talloc_zero(priv, struct osdpart);
|
||||||
*osd = (struct osdpart) {
|
|
||||||
.packer = talloc_zero(osd, struct bitmap_packer),
|
|
||||||
};
|
|
||||||
priv->osd[n] = osd;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->d3d9_dll = LoadLibraryA("d3d9.dll");
|
priv->d3d9_dll = LoadLibraryA("d3d9.dll");
|
||||||
if (!priv->d3d9_dll) {
|
if (!priv->d3d9_dll) {
|
||||||
|
@ -1536,34 +1529,45 @@ error_exit:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static D3DCOLOR ass_to_d3d_color(uint32_t color)
|
||||||
|
{
|
||||||
|
uint32_t r = (color >> 24) & 0xff;
|
||||||
|
uint32_t g = (color >> 16) & 0xff;
|
||||||
|
uint32_t b = (color >> 8) & 0xff;
|
||||||
|
uint32_t a = 0xff - (color & 0xff);
|
||||||
|
return D3DCOLOR_ARGB(a, r, g, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int next_pow2(int v)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < 30; x++) {
|
||||||
|
if ((1 << x) >= v)
|
||||||
|
return 1 << x;
|
||||||
|
}
|
||||||
|
return INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
|
static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
|
||||||
struct sub_bitmaps *imgs)
|
struct sub_bitmaps *imgs)
|
||||||
{
|
{
|
||||||
D3DFORMAT fmt = priv->osd_fmt_table[imgs->format];
|
D3DFORMAT fmt = priv->osd_fmt_table[imgs->format];
|
||||||
|
|
||||||
osd->packer->w_max = priv->max_texture_width;
|
assert(imgs->packed);
|
||||||
osd->packer->h_max = priv->max_texture_height;
|
|
||||||
|
|
||||||
osd->packer->padding = imgs->scaled; // assume 2x2 filter on scaling
|
osd->change_id = imgs->change_id;
|
||||||
int r = packer_pack_from_subbitmaps(osd->packer, imgs);
|
osd->num_vertices = 0;
|
||||||
if (r < 0) {
|
|
||||||
MP_ERR(priv, "OSD bitmaps do not fit on "
|
|
||||||
"a surface with the maximum supported size %dx%d.\n",
|
|
||||||
osd->packer->w_max, osd->packer->h_max);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (osd->packer->w > osd->texture.tex_w
|
if (imgs->packed_w > osd->texture.tex_w
|
||||||
|| osd->packer->h > osd->texture.tex_h
|
|| imgs->packed_h > osd->texture.tex_h
|
||||||
|| osd->format != imgs->format)
|
|| osd->format != imgs->format)
|
||||||
{
|
{
|
||||||
osd->format = imgs->format;
|
osd->format = imgs->format;
|
||||||
|
|
||||||
int new_w = osd->packer->w;
|
int new_w = next_pow2(imgs->packed_w);
|
||||||
int new_h = osd->packer->h;
|
int new_h = next_pow2(imgs->packed_h);
|
||||||
d3d_fix_texture_size(priv, &new_w, &new_h);
|
d3d_fix_texture_size(priv, &new_w, &new_h);
|
||||||
|
|
||||||
MP_DBG(priv, "reallocate OSD surface.\n");
|
MP_DBG(priv, "reallocate OSD surface to %dx%d.\n", new_w, new_h);
|
||||||
|
|
||||||
d3dtex_release(priv, &osd->texture);
|
d3dtex_release(priv, &osd->texture);
|
||||||
d3dtex_allocate(priv, &osd->texture, fmt, new_w, new_h);
|
d3dtex_allocate(priv, &osd->texture, fmt, new_w, new_h);
|
||||||
|
@ -1572,9 +1576,7 @@ static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
|
||||||
return false; // failed to allocate
|
return false; // failed to allocate
|
||||||
}
|
}
|
||||||
|
|
||||||
struct pos bb[2];
|
RECT dirty_rc = { 0, 0, imgs->packed_w, imgs->packed_h };
|
||||||
packer_get_bb(osd->packer, bb);
|
|
||||||
RECT dirty_rc = { bb[0].x, bb[0].y, bb[1].x, bb[1].y };
|
|
||||||
|
|
||||||
D3DLOCKED_RECT locked_rect;
|
D3DLOCKED_RECT locked_rect;
|
||||||
|
|
||||||
|
@ -1586,66 +1588,26 @@ static bool upload_osd(d3d_priv *priv, struct osdpart *osd,
|
||||||
}
|
}
|
||||||
|
|
||||||
int ps = fmt == D3DFMT_A8 ? 1 : 4;
|
int ps = fmt == D3DFMT_A8 ? 1 : 4;
|
||||||
packer_copy_subbitmaps(osd->packer, imgs, locked_rect.pBits, ps,
|
memcpy_pic(locked_rect.pBits, imgs->packed->planes[0], ps * imgs->packed_w,
|
||||||
locked_rect.Pitch);
|
imgs->packed_h, locked_rect.Pitch, imgs->packed->stride[0]);
|
||||||
|
|
||||||
if (FAILED(IDirect3DTexture9_UnlockRect(osd->texture.system, 0))) {
|
if (FAILED(IDirect3DTexture9_UnlockRect(osd->texture.system, 0))) {
|
||||||
MP_ERR(priv, "OSD texture unlock failed.\n");
|
MP_ERR(priv, "OSD texture unlock failed.\n");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return d3dtex_update(priv, &osd->texture);
|
if (!d3dtex_update(priv, &osd->texture))
|
||||||
}
|
return false;
|
||||||
|
|
||||||
static struct osdpart *generate_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
|
// We need 2 primitives per quad which makes 6 vertices.
|
||||||
{
|
osd->num_vertices = imgs->num_parts * 6;
|
||||||
if (imgs->num_parts == 0 || !priv->osd_fmt_table[imgs->format])
|
MP_TARRAY_GROW(osd, osd->vertices, osd->num_vertices);
|
||||||
return NULL;
|
|
||||||
|
|
||||||
struct osdpart *osd = priv->osd[imgs->render_index];
|
|
||||||
|
|
||||||
if (imgs->change_id != osd->change_id) {
|
|
||||||
if (!upload_osd(priv, osd, imgs))
|
|
||||||
osd->packer->count = 0;
|
|
||||||
|
|
||||||
osd->change_id = imgs->change_id;
|
|
||||||
osd->num_vertices = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return osd->packer->count ? osd : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static D3DCOLOR ass_to_d3d_color(uint32_t color)
|
|
||||||
{
|
|
||||||
uint32_t r = (color >> 24) & 0xff;
|
|
||||||
uint32_t g = (color >> 16) & 0xff;
|
|
||||||
uint32_t b = (color >> 8) & 0xff;
|
|
||||||
uint32_t a = 0xff - (color & 0xff);
|
|
||||||
return D3DCOLOR_ARGB(a, r, g, b);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
|
|
||||||
{
|
|
||||||
d3d_priv *priv = ctx;
|
|
||||||
|
|
||||||
struct osdpart *osd = generate_osd(priv, imgs);
|
|
||||||
if (!osd)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (osd->packer->count && !osd->num_vertices) {
|
|
||||||
// We need 2 primitives per quad which makes 6 vertices (we could reduce
|
|
||||||
// the number of vertices by using an indexed vertex array, but it's
|
|
||||||
// probably not worth doing)
|
|
||||||
osd->num_vertices = osd->packer->count * 6;
|
|
||||||
osd->vertices = talloc_realloc(osd, osd->vertices, vertex_osd,
|
|
||||||
osd->num_vertices);
|
|
||||||
|
|
||||||
float tex_w = osd->texture.tex_w;
|
float tex_w = osd->texture.tex_w;
|
||||||
float tex_h = osd->texture.tex_h;
|
float tex_h = osd->texture.tex_h;
|
||||||
|
|
||||||
for (int n = 0; n < osd->packer->count; n++) {
|
for (int n = 0; n < imgs->num_parts; n++) {
|
||||||
struct sub_bitmap *b = &imgs->parts[n];
|
struct sub_bitmap *b = &imgs->parts[n];
|
||||||
struct pos p = osd->packer->result[n];
|
|
||||||
|
|
||||||
D3DCOLOR color = imgs->format == SUBBITMAP_LIBASS
|
D3DCOLOR color = imgs->format == SUBBITMAP_LIBASS
|
||||||
? ass_to_d3d_color(b->libass.color)
|
? ass_to_d3d_color(b->libass.color)
|
||||||
|
@ -1655,10 +1617,10 @@ static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
|
||||||
float y0 = b->y;
|
float y0 = b->y;
|
||||||
float x1 = b->x + b->dw;
|
float x1 = b->x + b->dw;
|
||||||
float y1 = b->y + b->dh;
|
float y1 = b->y + b->dh;
|
||||||
float tx0 = p.x / tex_w;
|
float tx0 = b->src_x / tex_w;
|
||||||
float ty0 = p.y / tex_h;
|
float ty0 = b->src_y / tex_h;
|
||||||
float tx1 = (p.x + b->w) / tex_w;
|
float tx1 = (b->src_x + b->w) / tex_w;
|
||||||
float ty1 = (p.y + b->h) / tex_h;
|
float ty1 = (b->src_y + b->h) / tex_h;
|
||||||
|
|
||||||
vertex_osd *v = &osd->vertices[n * 6];
|
vertex_osd *v = &osd->vertices[n * 6];
|
||||||
v[0] = (vertex_osd) { x0, y0, 0, color, tx0, ty0 };
|
v[0] = (vertex_osd) { x0, y0, 0, color, tx0, ty0 };
|
||||||
|
@ -1668,8 +1630,31 @@ static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
|
||||||
v[4] = v[2];
|
v[4] = v[2];
|
||||||
v[5] = v[1];
|
v[5] = v[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct osdpart *generate_osd(d3d_priv *priv, struct sub_bitmaps *imgs)
|
||||||
|
{
|
||||||
|
if (imgs->num_parts == 0 || !priv->osd_fmt_table[imgs->format])
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
struct osdpart *osd = priv->osd[imgs->render_index];
|
||||||
|
|
||||||
|
if (imgs->change_id != osd->change_id)
|
||||||
|
upload_osd(priv, osd, imgs);
|
||||||
|
|
||||||
|
return osd->num_vertices ? osd : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_osd_cb(void *ctx, struct sub_bitmaps *imgs)
|
||||||
|
{
|
||||||
|
d3d_priv *priv = ctx;
|
||||||
|
|
||||||
|
struct osdpart *osd = generate_osd(priv, imgs);
|
||||||
|
if (!osd)
|
||||||
|
return;
|
||||||
|
|
||||||
d3d_begin_scene(priv);
|
d3d_begin_scene(priv);
|
||||||
|
|
||||||
IDirect3DDevice9_SetRenderState(priv->d3d_device,
|
IDirect3DDevice9_SetRenderState(priv->d3d_device,
|
||||||
|
|
Loading…
Reference in New Issue