-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Everything is ok with me as long as we accept at least initial implementation, which is coded reasonably good. I want to understand what's going on and improve on top of it. I think that it's better to have at least the subtitles showing on the screen compared to nothing. Later we can always improve Jim's work if it needs to be improved.
So - Jim, you've almost cleared your code. When the patch is accepted, I will begin to ask questions how to make everything work good :) _______________________________________________ MPlayer-dev-eng mailing list MPlayer-dev-eng@mplayerhq.hu https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
Hi, I hope this is OK now. 1) I've moved back to a memset 0, and used D3DRS_SRCBLEND, D3DBLEND_ONE D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA as the source/dest filters 2) moved to use a triangle strip rather than a fan 3) took the comments about the setup of the blending, but I think it's clearer to do this stuff together. It should have very little cost (some api overhead) as most drivers will detect when you are trying to set the same state as the previous value. 4) Should have all the random spaces removed to match what was cleaned in svn this afternoon. 5) the vertex_t casting has been changed, the pointer is now a vertex_t, but the reason it didn't make any difference is that I now have to cast to (void *) in two places. That should be it (I hope) P.S. Are you using a tool of some sort to spot tab->space etc formatting issues in the patch? (or just your eyes) Jim -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkkwKSkACgkQhrNWoHjgI1Di0gCgm6DyZC4KERXOWcAG1gVP969v /qEAoJMNCEUBIzB12nm02QpUGgspdo1r =7fHQ -----END PGP SIGNATURE----- Index: libvo/vo_direct3d.c =================================================================== --- libvo/vo_direct3d.c (revision 28047) +++ libvo/vo_direct3d.c (working copy) @@ -30,6 +30,7 @@ #include "aspect.h" #include "w32_common.h" #include "libavutil/common.h" +#include "sub.h" static const vo_info_t info = { @@ -71,8 +72,15 @@ IDirect3DSurface9 *d3d_surface; /**< Offscreen Direct3D Surface. MPlayer renders inside it. Uses colorspace priv->movie_src_fmt */ + IDirect3DTexture9 *d3d_texture_osd; /**< Direct3D Texture. Uses RGBA */ + IDirect3DTexture9 *d3d_texture_system; /**< Direct3D Texture. System memory + cannot lock a normal texture. Uses RGBA */ IDirect3DSurface9 *d3d_backbuf; /**< Video card's back buffer (used to display next frame) */ + IDirect3DVertexBuffer9 *d3d_quad_vb; /**< Vertex buffer that contains the texture + coordinates for the quad. */ + int is_osd_populated; /**< 1 = OSD texture has something to display, + 0 = OSD texture is clear */ } *priv; typedef struct { @@ -100,6 +108,23 @@ #define DISPLAY_FORMAT_TABLE_ENTRIES (sizeof(fmt_table) / sizeof(fmt_table[0])) +#define D3DFVF_MY_VERTEX ( D3DFVF_XYZ | D3DFVF_TEX1 ) + +#define OSD_TEXTURE_SIZE 1024 /* as this is a texture, it can be + a different size than the movie */ + +typedef struct vertex_s { + float x, y, z; /* Position of vertex in 3D space */ + float tu, tv; /* Texture coordinates */ +} vertex_t; + +vertex_t osd_quad_vb[] = { + {-1.0f, 1.0f, 0.0f, 0, 0 }, + { 1.0f, 1.0f, 0.0f, 1, 0 }, + {-1.0f,-1.0f, 0.0f, 0, 1 }, + { 1.0f,-1.0f, 0.0f, 1, 1 } +}; + /**************************************************************************** * * * * @@ -185,6 +210,22 @@ priv->d3d_surface = NULL; } + /* kill the VB and the texture */ + if (priv->d3d_texture_osd != NULL) { + IDirect3DTexture9_Release(priv->d3d_texture_osd); + priv->d3d_texture_osd = NULL; + } + + if (priv->d3d_texture_system != NULL) { + IDirect3DTexture9_Release(priv->d3d_texture_system); + priv->d3d_texture_system = NULL; + } + + if (priv->d3d_quad_vb != NULL) { + IDirect3DVertexBuffer9_Release(priv->d3d_quad_vb); + priv->d3d_quad_vb = NULL; + } + if (priv->d3d_device != NULL) { IDirect3DDevice9_Release(priv->d3d_device); priv->d3d_device = NULL; @@ -206,6 +247,8 @@ { D3DPRESENT_PARAMETERS present_params; D3DDISPLAYMODE disp_mode; + vertex_t *vertices = NULL; + float aspect; mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d><INFO>reconfigure_d3d called \n"); @@ -267,6 +310,68 @@ return 0; } + /* create OSD */ + if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, + OSD_TEXTURE_SIZE, + OSD_TEXTURE_SIZE, + 1, + D3DUSAGE_DYNAMIC, + D3DFMT_A8L8, + D3DPOOL_SYSTEMMEM, + &priv->d3d_texture_system, + NULL))) { + mp_msg(MSGT_VO,MSGL_ERR, + "<vo_direct3d><INFO>IDirect3DDevice9_CreateTexture Failed (d3d_texture_system).\n"); + return 0; + } + + if (FAILED(IDirect3DDevice9_CreateTexture(priv->d3d_device, + OSD_TEXTURE_SIZE, + OSD_TEXTURE_SIZE, + 1, + D3DUSAGE_DYNAMIC, + D3DFMT_A8L8, + D3DPOOL_DEFAULT, + &priv->d3d_texture_osd, + NULL))) { + mp_msg(MSGT_VO,MSGL_ERR, + "<vo_direct3d><INFO>IDirect3DDevice9_CreateTexture Failed (d3d_texture_osd).\n"); + return 0; + } + + if (FAILED(IDirect3DDevice9_CreateVertexBuffer(priv->d3d_device, + sizeof(osd_quad_vb), + 0, + D3DFVF_MY_VERTEX, + D3DPOOL_DEFAULT, + &priv->d3d_quad_vb, + NULL))) { + mp_msg(MSGT_VO,MSGL_ERR, + "<vo_direct3d><INFO>IDirect3DDevice9_CreateVertexBuffer Failed (d3d_quad_vb).\n"); + return 0; + } + + if (FAILED(IDirect3DVertexBuffer9_Lock(priv->d3d_quad_vb, + 0, sizeof(osd_quad_vb), + (void *)&vertices, + 0))) { + mp_msg(MSGT_VO,MSGL_ERR, + "<vo_direct3d><INFO>IDirect3DVertexBuffer9_Lock Failed.\n"); + return 0; + } + + memcpy((void *)vertices, osd_quad_vb, sizeof(osd_quad_vb)); + aspect = (float)priv->src_width / priv->src_height; + /* populate the v texture coordinate */ + vertices[2].tv = + vertices[3].tv = ((1.0f / OSD_TEXTURE_SIZE) * (OSD_TEXTURE_SIZE / aspect)); + + if (FAILED(IDirect3DVertexBuffer9_Unlock(priv->d3d_quad_vb))) { + mp_msg(MSGT_VO,MSGL_ERR, + "<vo_direct3d><INFO>IDirect3DVertexBuffer9_Unlock Failed.\n"); + return 0; + } + if (FAILED(IDirect3DDevice9_GetBackBuffer(priv->d3d_device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &(priv->d3d_backbuf)))) { @@ -389,7 +494,7 @@ mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>Accepted image format: %s\n", vo_format_name(fmt_table[i].mplayer_fmt)); return (VFCAP_CSP_SUPPORTED | VFCAP_CSP_SUPPORTED_BY_HW - /*| VFCAP_OSD*/ | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN); + | VFCAP_OSD | VFCAP_HWSCALE_UP | VFCAP_HWSCALE_DOWN); } } @@ -573,13 +678,6 @@ } } -/** @brief libvo Callback: Draw OSD/Subtitles, - * @return N/A - */ -static void draw_osd(void) -{ -} - /** @brief libvo Callback: Uninitializes all pointers and closes * all D3D related stuff, * @return N/A @@ -676,3 +774,130 @@ mp_msg(MSGT_VO, MSGL_V, "<vo_direct3d>draw_frame called\n"); return VO_FALSE; } + +/** @brief Maps MPlayer alpha to D3D + * 0x0 -> transparent and discarded by alpha test + * 0x0 -> 0xFF to become opaque + * other alpha values are inverted +1 (2 = -2) + * These values are then inverted again with + the texture filter D3DBLEND_INVSRCALPHA + */ +void vo_draw_alpha_l8a8(int w,int h, unsigned char* src, unsigned char *srca, + int srcstride, unsigned char* dstbase,int dststride) +{ + int y; + for (y = 0; y < h; y++) { + unsigned short *dst = (unsigned short*)dstbase; + int x; + for (x = 0; x < w; x++) { + dst[x] = (-srca[x] << 8) | src[x]; + } + src += srcstride; + srca += srcstride; + dstbase += dststride; + } +} + +/** @brief Callback function to render the OSD to the texture + */ +static void draw_alpha(int x0, int y0, int w, int h, unsigned char *src, + unsigned char *srca, int stride) +{ + D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order + to copy MPlayer's frame inside it.*/ + + if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, + &locked_rect, NULL, 0))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>IDirect3DTexture9_LockRect failure.\n"); + return; + } + + vo_draw_alpha_l8a8(w,h,src,srca,stride, + (void *)((unsigned int)locked_rect.pBits+locked_rect.Pitch*y0+2*x0), locked_rect.Pitch); + + /* this unlock is used for both slice_draw path and D3DRenderFrame path */ + if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>IDirect3DTexture9_UnlockRect failure.\n"); + return; + } + + priv->is_osd_populated = 1; +} + +/** @brief libvo Callback: Draw OSD/Subtitles, + * @return N/A + */ +static void draw_osd(void) +{ + /* calculate a width and height based on the OSD_TEXTURE_SIZE */ + float aspect = (float)priv->src_width / priv->src_height; + unsigned int calc_height = ((unsigned int)(OSD_TEXTURE_SIZE / aspect)); + + if (vo_osd_changed(0)) { + D3DLOCKED_RECT locked_rect; /**< Offscreen surface we lock in order + to copy MPlayer's frame inside it.*/ + + /* clear the OSD */ + if (FAILED(IDirect3DTexture9_LockRect(priv->d3d_texture_system, 0, + &locked_rect, NULL, 0))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>IDirect3DTexture9_LockRect failure.\n"); + return; + } + + memset(locked_rect.pBits, 0, (locked_rect.Pitch * OSD_TEXTURE_SIZE)); + + /* this unlock is used for both slice_draw path and D3DRenderFrame path */ + if (FAILED(IDirect3DTexture9_UnlockRect(priv->d3d_texture_system, 0))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>IDirect3DTexture9_UnlockRect failure.\n"); + return; + } + + priv->is_osd_populated = 0; + + vo_draw_text(OSD_TEXTURE_SIZE, calc_height, draw_alpha); + + if (FAILED(IDirect3DDevice9_UpdateTexture(priv->d3d_device, + (IDirect3DBaseTexture9 *)priv->d3d_texture_system, + (IDirect3DBaseTexture9 *)priv->d3d_texture_osd))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>IDirect3DDevice9_UpdateTexture failure.\n"); + return; + } + } + + + /* update OSD */ + + if (priv->is_osd_populated) { + if (FAILED(IDirect3DDevice9_BeginScene(priv->d3d_device))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>BeginScene failed\n"); + return; + } + /* turn on alpha test */ + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_SRCBLEND, D3DBLEND_ONE); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, TRUE); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAFUNC, D3DCMP_GREATER); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHAREF, (DWORD)0x0); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, TRUE); + + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_LIGHTING, FALSE); + + IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + IDirect3DDevice9_SetSamplerState(priv->d3d_device, 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + /* need to use a texture here */ + IDirect3DDevice9_SetTexture(priv->d3d_device, 0, (IDirect3DBaseTexture9 *)priv->d3d_texture_osd); + IDirect3DDevice9_SetStreamSource(priv->d3d_device, 0, priv->d3d_quad_vb, 0, sizeof(vertex_t)); + IDirect3DDevice9_SetFVF(priv->d3d_device, D3DFVF_MY_VERTEX); + IDirect3DDevice9_DrawPrimitive(priv->d3d_device, D3DPT_TRIANGLESTRIP, 0, 2); + + /* turn off alpha test */ + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHATESTENABLE, FALSE); + IDirect3DDevice9_SetRenderState(priv->d3d_device, D3DRS_ALPHABLENDENABLE, FALSE); + + if (FAILED(IDirect3DDevice9_EndScene(priv->d3d_device))) { + mp_msg(MSGT_VO,MSGL_ERR,"<vo_direct3d>EndScene failed\n"); + return; + } + } +}