summaryrefslogtreecommitdiff
path: root/src/video_out/video_out_directx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_out/video_out_directx.c')
-rw-r--r--src/video_out/video_out_directx.c203
1 files changed, 131 insertions, 72 deletions
diff --git a/src/video_out/video_out_directx.c b/src/video_out/video_out_directx.c
index 11ee709e1..8cb72238a 100644
--- a/src/video_out/video_out_directx.c
+++ b/src/video_out/video_out_directx.c
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2005 the xine project
- *
+ *
* This file is part of xine, a unix video player.
- *
+ *
* xine 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.
- *
+ *
* xine 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, USA
@@ -21,6 +21,10 @@
* by Matthew Grooms <elon@altavista.com>
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
typedef unsigned char boolean;
#include <windows.h>
@@ -55,21 +59,33 @@ typedef unsigned char boolean;
* the linking stage.
*****************************************************************************/
#if 1
-static const GUID IID_IDirectDraw = {
+static const GUID xine_IID_IDirectDraw = {
0x6C14DB80,0xA733,0x11CE,{0xA5,0x21,0x00,0x20,0xAF,0x0B,0xE5,0x60}
};
+#ifdef IID_IDirectDraw
+# undef IID_IDirectDraw
+#endif
+#define IID_IDirectDraw xine_IID_IDirectDraw
#endif
#if 0
static const GUID IID_IDirectDraw2 = {
0xB3A6F3E0,0x2B43,0x11CF,{0xA2,0xDE,0x00,0xAA,0x00,0xB9,0x33,0x56}
};
+#ifdef IID_IDirectDraw2
+# undef IID_IDirectDraw2
+#endif
+#define IID_IDirectDraw2 xine_IID_IDirectDraw2
#endif
#if 0
static const GUID IID_IDirectDraw4 = {
0x9C59509A,0x39BD,0x11D1,{0x8C,0x4A,0x00,0xC0,0x4F,0xD9,0x30,0xC5}
};
+#ifdef IID_IDirectDraw4
+# undef IID_IDirectDraw4
+#endif
+#define IID_IDirectDraw4 xine_IID_IDirectDraw4
#endif
/* -----------------------------------------
@@ -102,7 +118,7 @@ typedef struct {
LPDIRECTDRAW ddobj; /* direct draw object */
LPDIRECTDRAWSURFACE primary; /* primary dd surface */
- LPDIRECTDRAWSURFACE secondary; /* secondary dd surface */
+ LPDIRECTDRAWSURFACE secondary; /* secondary dd surface */
LPDIRECTDRAWCLIPPER ddclipper; /* dd clipper object */
uint8_t * contents; /* secondary contents */
win32_frame_t *current; /* current frame */
@@ -117,7 +133,8 @@ typedef struct {
yuv2rgb_t *yuv2rgb; /* used for format conversion */
int mode; /* rgb mode */
int bytespp; /* rgb bits per pixel */
-
+ DDPIXELFORMAT primary_pixel_format;
+ DDSURFACEDESC ddsd; /* set by Lock(), used during display_frame */
alphablend_t alphablend_extra_data;
} win32_driver_t;
@@ -134,7 +151,7 @@ typedef struct {
*
* ----------------------------------------- */
-/* Display formatted error message in
+/* Display formatted error message in
* popup message box.*/
static void Error( HWND hwnd, LPSTR szfmt, ... )
@@ -152,7 +169,7 @@ static void UpdateRect( win32_visual_t * win32_visual )
{
if( win32_visual->FullScreen )
{
- SetRect( &win32_visual->WndRect, 0, 0,
+ SetRect( &win32_visual->WndRect, 0, 0,
GetSystemMetrics( SM_CXSCREEN ),
GetSystemMetrics( SM_CYSCREEN ) );
}
@@ -164,12 +181,12 @@ static void UpdateRect( win32_visual_t * win32_visual )
}
}
-/* Create our direct draw object, primary
+/* Create our direct draw object, primary
* surface and clipper object.
*
- * NOTE : The primary surface is more or
+ * NOTE : The primary surface is more or
* less a viewport into the parent desktop
- * window and will always have a pixel format
+ * window and will always have a pixel format
* identical to the current display mode. */
static boolean CreatePrimary( win32_driver_t * win32_driver )
@@ -259,7 +276,7 @@ static boolean CreatePrimary( win32_driver_t * win32_driver )
}
/* Create our secondary ( off screen ) buffer.
- * The optimal secondary buffer is a h/w
+ * The optimal secondary buffer is a h/w
* overlay with the same pixel format as the
* xine frame type. However, since this is
* not always supported by the host h/w,
@@ -310,7 +327,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he
/* the requested format is XINE_IMGFMT_YV12 */
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
@@ -326,7 +343,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he
/* the requested format is XINE_IMGFMT_YUY2 */
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd.ddpfPixelFormat.dwYUVBitCount = 16;
@@ -343,7 +360,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he
/* the requested format is IMGFMT_RGB */
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
- ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OVERLAY;
ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsd.ddpfPixelFormat.dwYUVBitCount = 24;
@@ -354,7 +371,7 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he
lprintf("CreateSecondary() - act_format = (RGB) %d\n", IMGFMT_RGB);
win32_driver->act_format = IMGFMT_RGB;
- }
+ }
#endif /* RGB_SUPPORT */
lprintf("CreateSecondary() - IDirectDraw_CreateSurface()\n");
@@ -367,8 +384,9 @@ static boolean CreateSecondary( win32_driver_t * win32_driver, int width, int he
lprintf("CreateSecondary() - Falling back to back buffer same as primary\n");
lprintf("CreateSecondary() - act_format = (NATIVE) %d\n", IMGFMT_NATIVE);
- ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
+ ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
+ ddsd.ddpfPixelFormat = win32_driver->primary_pixel_format;
win32_driver->act_format = IMGFMT_NATIVE;
if( IDirectDraw_CreateSurface( win32_driver->ddobj, &ddsd, &win32_driver->secondary, 0 ) == DD_OK )
@@ -405,7 +423,7 @@ static void Destroy( win32_driver_t * win32_driver )
IDirectDraw_Release( win32_driver->ddobj );
_x_alphablend_free(&win32_driver->alphablend_extra_data);
-
+
free( win32_driver );
}
@@ -430,6 +448,10 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver )
return 0;
}
+ /* store pixel format for CreateSecondary */
+
+ win32_driver->primary_pixel_format = ddpf;
+
/* TODO : support paletized video modes */
if( ( ddpf.dwFlags & DDPF_PALETTEINDEXED1 ) ||
@@ -478,13 +500,15 @@ static boolean CheckPixelFormat( win32_driver_t * win32_driver )
win32_driver->mode = MODE_15_BGR;
}
+ lprintf("win32 mode: %u\n", win32_driver->mode);
return TRUE;
}
+#if 0
/* Create a Direct draw surface from
* a bitmap resource..
*
- * NOTE : This is not really useful
+ * NOTE : This is not really useful
* anymore since the xine logo code is
* being pushed to the backend. */
@@ -523,7 +547,7 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc
Error( 0, "CreateSurface ( bitmap ) : could not create dd surface" );
return 0;
}
-
+
/* get a handle to our surface dc,
* create a compat dc and load
* our bitmap into the compat dc */
@@ -546,8 +570,9 @@ static LPDIRECTDRAWSURFACE CreateBMP( win32_driver_t * win32_driver, int resourc
return bmp_surf;
}
+#endif
-/* Merge overlay with the current primary
+/* Merge overlay with the current primary
* surface. This funtion is only used when
* a h/w overlay of the current frame type
* is supported. */
@@ -558,7 +583,7 @@ static boolean Overlay( LPDIRECTDRAWSURFACE src_surface, RECT * src_rect,
{
DWORD dw_color_key;
DDPIXELFORMAT ddpf;
- DDOVERLAYFX ddofx;
+ DDOVERLAYFX ddofx;
int flags;
HRESULT result;
@@ -755,23 +780,22 @@ static boolean DisplayFrame( win32_driver_t * win32_driver )
/* Lock our back buffer to update its contents. */
-static void * Lock( void * surface )
+static void * Lock( win32_driver_t * win32_driver, void * surface )
{
LPDIRECTDRAWSURFACE lock_surface = ( LPDIRECTDRAWSURFACE ) surface;
- DDSURFACEDESC ddsd;
HRESULT result;
if( !surface )
return 0;
- memset( &ddsd, 0, sizeof( ddsd ) );
- ddsd.dwSize = sizeof( ddsd );
+ memset( &win32_driver->ddsd, 0, sizeof( win32_driver->ddsd ) );
+ win32_driver->ddsd.dwSize = sizeof( win32_driver->ddsd );
- result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
+ result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
if( result == DDERR_SURFACELOST )
{
IDirectDrawSurface_Restore( lock_surface );
- result = IDirectDrawSurface_Lock( lock_surface, 0, &ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
+ result = IDirectDrawSurface_Lock( lock_surface, 0, &win32_driver->ddsd, DDLOCK_WAIT | DDLOCK_NOSYSLOCK, 0 );
if( result != DD_OK )
return 0;
@@ -786,7 +810,7 @@ static void * Lock( void * surface )
}
}
- return ddsd.lpSurface;
+ return win32_driver->ddsd.lpSurface;
}
/* Unlock our back buffer to prepair for display. */
@@ -863,7 +887,7 @@ static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver )
{
win32_frame_t *win32_frame;
- win32_frame = ( win32_frame_t * ) xine_xmalloc( sizeof( win32_frame_t ) );
+ win32_frame = calloc(1, sizeof(win32_frame_t));
if (!win32_frame)
return NULL;
@@ -879,7 +903,7 @@ static vo_frame_t * win32_alloc_frame( vo_driver_t * vo_driver )
}
-static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_frame, uint32_t width,
+static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_frame, uint32_t width,
uint32_t height, double ratio, int format, int flags )
{
win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver;
@@ -929,7 +953,7 @@ static void win32_update_frame_format( vo_driver_t * vo_driver, vo_frame_t * vo_
#endif
else
{
- xprintf (win32_driver->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (win32_driver->xine, XINE_VERBOSITY_DEBUG,
"vo_out_directx : !!! unsupported image format %04x !!!\n", format );
exit (1);
}
@@ -946,8 +970,6 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame
{
win32_driver_t *win32_driver = ( win32_driver_t * ) vo_driver;
win32_frame_t *win32_frame = ( win32_frame_t * ) vo_frame;
- int offset;
- int size;
/* if the required width, height or format has changed
@@ -966,7 +988,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame
/* lock our surface to update its contents */
- win32_driver->contents = Lock( win32_driver->secondary );
+ win32_driver->contents = Lock( win32_driver, win32_driver->secondary );
/* surface unavailable, skip frame render */
@@ -993,13 +1015,13 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame
#if NEW_YUV
win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb,
win32_driver->width, win32_driver->height,
- win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1],
+ win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1],
win32_driver->width, win32_driver->height,
win32_driver->width * win32_driver->bytespp);
#else
yuv2rgb_setup( win32_driver->yuv2rgb,
win32_driver->width, win32_driver->height,
- win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1],
+ win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[1],
win32_driver->width, win32_driver->height,
win32_driver->width * win32_driver->bytespp );
@@ -1019,7 +1041,7 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame
#if NEW_YUV
win32_driver->yuv2rgb->configure( win32_driver->yuv2rgb,
win32_driver->width, win32_driver->height,
- win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2,
+ win32_frame->vo_frame.pitches[0], win32_frame->vo_frame.pitches[0] / 2,
win32_driver->width, win32_driver->height,
win32_driver->width * win32_driver->bytespp );
#else
@@ -1051,37 +1073,47 @@ static void win32_display_frame( vo_driver_t * vo_driver, vo_frame_t * vo_frame
/* the actual format is identical to our
* stream format. we just need to copy it */
- switch(win32_frame->format)
+ int line;
+ uint8_t * src;
+ vo_frame_t * frame = vo_frame;
+ uint8_t * dst = (uint8_t *)win32_driver->contents;
+
+ switch(win32_frame->format)
{
- case XINE_IMGFMT_YV12:
- {
- vo_frame_t *frame;
- uint8_t *img;
-
- frame = vo_frame;
- img = (uint8_t *)win32_driver->contents;
-
- offset = 0;
- size = frame->pitches[0] * frame->height;
- xine_fast_memcpy( img+offset, frame->base[0], size);
-
- offset += size;
- size = frame->pitches[2]* frame->height / 2;
- xine_fast_memcpy( img+offset, frame->base[2], size);
-
- offset += size;
- size = frame->pitches[1] * frame->height / 2;
- xine_fast_memcpy( img+offset, frame->base[1], size);
- }
+ case XINE_IMGFMT_YV12:
+ src = frame->base[0];
+ for (line = 0; line < frame->height ; line++){
+ xine_fast_memcpy( dst, src, frame->width);
+ src += vo_frame->pitches[0];
+ dst += win32_driver->ddsd.lPitch;
+ }
+
+ src = frame->base[2];
+ for (line = 0; line < frame->height/2 ; line++){
+ xine_fast_memcpy( dst, src, frame->width/2);
+ src += vo_frame->pitches[2];
+ dst += win32_driver->ddsd.lPitch/2;
+ }
+
+ src = frame->base[1];
+ for (line = 0; line < frame->height/2 ; line++){
+ xine_fast_memcpy( dst, src, frame->width/2);
+ src += vo_frame->pitches[1];
+ dst += win32_driver->ddsd.lPitch/2;
+ }
break;
+
case XINE_IMGFMT_YUY2:
- xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2);
- break;
default:
- xine_fast_memcpy( win32_driver->contents, win32_frame->vo_frame.base[0], win32_frame->vo_frame.pitches[0] * win32_frame->vo_frame.height * 2);
+ src = frame->base[0];
+ for (line = 0; line < frame->height ; line++){
+ xine_fast_memcpy( dst, src, frame->width*2);
+ src += vo_frame->pitches[0];
+ dst += win32_driver->ddsd.lPitch;
+ }
break;
}
- }
+ }
/* unlock the surface */
@@ -1143,11 +1175,38 @@ static int win32_gui_data_exchange( vo_driver_t * vo_driver, int data_type, void
switch( data_type )
{
+
case GUI_WIN32_MOVED_OR_RESIZED:
UpdateRect( win32_driver->win32_visual );
DisplayFrame( win32_driver );
break;
+ case XINE_GUI_SEND_DRAWABLE_CHANGED:
+ {
+ HRESULT result;
+ HWND newWndHnd = (HWND) data;
+
+ /* set cooperative level */
+ result = IDirectDraw_SetCooperativeLevel( win32_driver->ddobj, newWndHnd, DDSCL_NORMAL );
+ if( result != DD_OK )
+ {
+ Error( 0, "SetCooperativeLevel : error 0x%lx", result );
+ return 0;
+ }
+ /* associate our clipper with new window */
+ result = IDirectDrawClipper_SetHWnd( win32_driver->ddclipper, 0, newWndHnd );
+ if( result != DD_OK )
+ {
+ Error( 0, "ddclipper->SetHWnd : error 0x%lx", result );
+ return 0;
+ }
+ /* store our objects in our visual struct */
+ win32_driver->win32_visual->WndHnd = newWndHnd;
+ /* update video area and redraw current frame */
+ UpdateRect( win32_driver->win32_visual );
+ DisplayFrame( win32_driver );
+ break;
}
+ }
return 0;
}
@@ -1158,15 +1217,15 @@ static int win32_redraw_needed(vo_driver_t* this_gen)
int ret = 0;
/* TC - May need to revisit this! */
-#ifdef TC
+#ifdef TC
win32_driver_t *win32_driver = (win32_driver_t *) this_gen;
if( _x_vo_scale_redraw_needed( &win32_driver->sc ) ) {
- win32_gui_data_exchange(this_gen, GUI_WIN32_MOVED_OR_RESIZED, 0);
+ win32_gui_data_exchange(this_gen, GUI_WIN32_MOVED_OR_RESIZED, 0);
ret = 1;
}
#endif
-
+
return ret;
}
@@ -1183,11 +1242,11 @@ static vo_driver_t *open_plugin (video_driver_class_t *class_gen, const void *wi
/*vo_driver_t *init_video_out_plugin( config_values_t * config, void * win32_visual )*/
{
directx_class_t *class = (directx_class_t *)class_gen;
- win32_driver_t *win32_driver = ( win32_driver_t * ) xine_xmalloc ( sizeof( win32_driver_t ) );
+ win32_driver_t *win32_driver = calloc(1, sizeof(win32_driver_t));
_x_alphablend_init(&win32_driver->alphablend_extra_data, class->xine);
-
+
win32_driver->xine = class->xine;
/* Make sure that the DirectX drivers are available and present! */
@@ -1249,7 +1308,7 @@ static void *init_class (xine_t *xine, void *visual_gen) {
/*
* from this point on, nothing should go wrong anymore
*/
- directx = (directx_class_t *) xine_xmalloc (sizeof (directx_class_t));
+ directx = calloc(1, sizeof (directx_class_t));
directx->driver_class.open_plugin = open_plugin;
directx->driver_class.get_identifier = get_identifier;
@@ -1258,7 +1317,7 @@ static void *init_class (xine_t *xine, void *visual_gen) {
directx->xine = xine;
directx->config = xine->config;
-
+
return directx;
}