diff options
Diffstat (limited to 'src/video_out/video_out_directx.c')
-rw-r--r-- | src/video_out/video_out_directx.c | 203 |
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; } |