[vlc-devel] [PATCH] Direct2D video output module

Laurent Aimar fenrir at elivagar.org
Sun Jul 25 13:19:16 CEST 2010


Hi,

On Fri, Jul 23, 2010 at 10:46:33AM +0300, David Kaplan wrote:
> Adds support for the D2D API on Win7/Vista SP2 with Platform Update
> Requires d2d1 contrib headers
> diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
> index e023ef4..125fd65 100644
> --- a/modules/video_output/msw/common.h
> +++ b/modules/video_output/msw/common.h
> @@ -157,6 +157,15 @@ struct vout_display_sys_t
>      vout_display_opengl_t vgl;
>  #endif
>  
> +#ifdef MODULE_NAME_IS_direct2d
> +    HINSTANCE              d2_dll;            /* handle of the opened d2d1 dll */
> +    FLOAT                  d2_dpi_x;                                  /* DPI x */
> +    FLOAT                  d2_dpi_y;                                  /* DPI y */
 It seems that it is not needed to store d2_dpi_x/d2_dpi_y  into the private
context.
> +    ID2D1Factory           *d2_factory;                         /* D2D factory */
> +    ID2D1HwndRenderTarget  *d2_render_target;          /* D2D rendering target */
> +    ID2D1Bitmap            *d2_bitmap;                            /* D2 bitmap */
> +#endif

> diff --git a/modules/video_output/msw/direct2d.c b/modules/video_output/msw/direct2d.c
> new file mode 100644
> index 0000000..880c240
> --- /dev/null
> +++ b/modules/video_output/msw/direct2d.c
> @@ -0,0 +1,422 @@
> +/*****************************************************************************
> + * direct2d.c : Direct2D video output plugin for vlc (Win7/Vista SP2 PF Update)
> + *****************************************************************************
> + * Copyright (C) 2010 VideoLAN and AUTHORS
> + * $Id$
> + *
> + * Author: David Kaplan <david at 2of1.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
> + *****************************************************************************/
> +
> +/*****************************************************************************
> + * Preamble
> + *****************************************************************************/
> +
> +#ifdef HAVE_CONFIG_H
> +# include "config.h"
> +#endif
> +#include <assert.h>
> +
> +#include <vlc_common.h>
> +#include <vlc_plugin.h>
> +#include <vlc_playlist.h>
> +#include <vlc_vout_display.h>
> +
> +#include <windows.h>
> +#include <commctrl.h>
> +
> +#include <d2d1.h>
> +
> +#include "common.h"
> +
> +#include <initguid.h>
> +#undef GUID_EXT
> +#define GUID_EXT
> +DEFINE_GUID(IID_ID2D1Factory, 0x6152247, 0x6f50, 0x465a, 0x92, 0x45, 0x11, 0x8b, 0xfd, 0x3b, 0x60, 0x7);
> +
> +#ifndef WS_NONAVDONEBUTTON
> +#   define WS_NONAVDONEBUTTON 0
> +#endif
 Is it needed ?
> +
> +/*****************************************************************************
> + * Module descriptor
> + *****************************************************************************/
> +static int  Open (vlc_object_t *);
> +static void Close(vlc_object_t *);
> +
> +#define D2D_HELP N_("Video output for Windows 7/Windows Vista with Platform update")
> +
> +vlc_module_begin ()
> +    set_category(CAT_VIDEO)
> +    set_subcategory(SUBCAT_VIDEO_VOUT)
> +    set_help(D2D_HELP)
> +    set_shortname("Direct2D")
> +    set_description(N_("Direct2D video output"))
> +    set_capability("vout display", 10)
 I wonder what its priority should be. If it is better/faster than gdi (and
it should be when d2d support is present), I think it should have a priority
a bit higher.

> +    add_shortcut("direct2d")
> +    set_callbacks(Open, Close)
> +vlc_module_end ()

> +/**
> + * Performs set up of ID2D1Bitmap memory ready for blitting
> + */
> +static void Prepare(vout_display_t *vd, picture_t *picture)
> +{
> +    vout_display_sys_t *sys = vd->sys;
> +
> +    if (sys->d2_render_target && sys->d2_bitmap)
> +    {
 Bad { placement.

> +        /* This seems unnecessary
> +        D2D1_RECT_U r_src = {
> +            sys->rect_src_clipped.left,
> +            sys->rect_src_clipped.top,
> +            sys->rect_src_clipped.right,
> +            sys->rect_src_clipped.bottom
> +        };
> +        */
 Have you tested with crop(yes), zoom, auto-scale, aspect ratio, and various
combination of them? (All in the Video menu).
> +
> +        HRESULT hr = ID2D1Bitmap_CopyFromMemory(sys->d2_bitmap,
> +                                                NULL /*&r_src*/,
> +                                                picture->p[0].p_pixels,
> +                                                picture->p[0].i_pitch);
 About our previous discussion, it seems that pitch != width * 4 is fine.
 From msdn:
 "pitch
  UINT32
  The stride, or pitch, of the source bitmap stored in srcData. The stride
  is the byte count of a scanline (one row of pixels in memory). The stride
  can be computed from the following formula:
  pixel width * bytes per pixel + memory padding."

> +        if (hr != S_OK)
> +            msg_Err(vd, "Failed to copy bitmap memory (hr = 0x%x)!",
> +                    (unsigned)hr);
> +
> +#ifndef NDEBUG
> +        /*msg_Dbg(vd, "Bitmap dbg: target = %p, pitch = %d, bitmap = %p",
> +                sys->d2_render_target, pitch, sys->d2_bitmap);*/
> +#endif
> +    }
> +}
> +
> +/**
> + * Blits a scaled picture_t to the render target
> + */
> +static void Display(vout_display_t *vd, picture_t *picture)
> +{
> +    vout_display_sys_t *sys = vd->sys;
> +
> +    D2D1_RECT_F r_dest = {
> +        sys->rect_dest.left,
> +        sys->rect_dest.top,
> +        sys->rect_dest.right,
> +        sys->rect_dest.bottom
> +    };
> +
> +    if (sys->d2_render_target && sys->d2_bitmap) {
> +        ID2D1HwndRenderTarget_BeginDraw(sys->d2_render_target);
> +
> +        ID2D1HwndRenderTarget_DrawBitmap(sys->d2_render_target,
> +                                         sys->d2_bitmap,
> +                                         &r_dest,
> +                                         1.0f,
> +                                         D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
> +                                         NULL);
> +
> +        ID2D1HwndRenderTarget_EndDraw(sys->d2_render_target, NULL, NULL);
 From msdn I see
"Your application should create render targets once and hold onto them for the
 life of the application or until the render target's EndDraw method returns the
 D2DERR_RECREATE_TARGET error. When you receive this error, you need to recreate
 the render target (and any resources it created)."

 So it seems that you need to check for EndDraw error code and recreate the
resources when needed. You can see how d3d does it.

> +    }
> +
> +    picture_Release(picture);
> +
> +    CommonDisplay(vd);
> +}
> +
> + /**
> +  * Control event handler
> +  */
> +static int Control(vout_display_t *vd, int query, va_list args)
> +{
> +    return CommonControl(vd, query, args);
> +}
> +
> +/**
> + * Handles surface management
> + * ID2D1RenderTargets cannot be resized and must be recreated
> + */
> +static void Manage(vout_display_t *vd)
> +{
> +    vout_display_sys_t *sys = vd->sys;
> +
> +    CommonManage(vd);
> +
> +    if (sys->changes & DX_POSITION_CHANGE) {
> +        D2D_ResizeRenderTarget(vd);
> +        sys->changes &= ~DX_POSITION_CHANGE;
> +    }
> +}
> +
> +/**
> + * Creates a ID2D1HwndRenderTarget and associated ID2D1Bitmap
> + */
> +static int D2D_CreateRenderTarget(vout_display_t *vd)
> +{
> +    vout_display_sys_t *sys = vd->sys;
> +
> +    sys->d2_render_target = NULL;
> +
> +    D2D1_PIXEL_FORMAT pf = {
> +        DXGI_FORMAT_B8G8R8A8_UNORM,
> +        D2D1_ALPHA_MODE_IGNORE
> +    };
 As you now only require RGB32, is it possible to set a correct RGB mask
in Open() ?

> +
> +    D2D1_RENDER_TARGET_PROPERTIES rtp = {
> +        D2D1_RENDER_TARGET_TYPE_DEFAULT,
> +        pf,
> +        0,
> +        0,
> +        D2D1_RENDER_TARGET_USAGE_NONE,
> +        D2D1_FEATURE_LEVEL_DEFAULT
> +    };
> +
> +    D2D1_SIZE_U size = {
> +        sys->rect_dest.right - sys->rect_dest.left,
> +        sys->rect_dest.bottom - sys->rect_dest.top
> +    };
> +
> +    D2D1_HWND_RENDER_TARGET_PROPERTIES hrtp = {
> +        sys->hvideownd,
> +        size,
> +        D2D1_PRESENT_OPTIONS_IMMEDIATELY /* this might need fiddling */
> +    };
> +

Regards,

-- 
fenrir




More information about the vlc-devel mailing list