Commit 8ab205ad authored by Sam Hocevar's avatar Sam Hocevar

* ./modules/video_output/wingdi.c: implemented offscreen rendering with

    fast blit (well at least it was considered "fast" back in the times of
    Windows 3.1). Default is 8bpp because that's what my iPaq does (no
    palette support yet though), 16bpp can be chosen at compile time and
    works perfectly in the emulator.
parent 515e0f2b
......@@ -2,7 +2,7 @@
* wingdi.c : Win32 / WinCE GDI video output plugin for vlc
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: wingdi.c,v 1.1 2002/11/21 13:53:32 sam Exp $
* $Id: wingdi.c,v 1.2 2002/11/22 15:19:47 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
......@@ -30,7 +30,11 @@
#include <vlc/vlc.h>
#include <vlc/vout.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define MAX_DIRECTBUFFERS 10
#define DEFAULT_BPP 8
/*****************************************************************************
* Local prototypes
......@@ -43,6 +47,29 @@ static void End ( vout_thread_t * );
static int Manage ( vout_thread_t * );
static void Render ( vout_thread_t *, picture_t * );
static void Display ( vout_thread_t *, picture_t * );
static void SetPalette( vout_thread_t *, u16 *, u16 *, u16 * );
static void EventThread ( vlc_object_t * );
static long FAR PASCAL WndProc ( HWND, UINT, WPARAM, LPARAM );
static void InitOffscreen ( vout_thread_t * );
/*****************************************************************************
* Private structure
*****************************************************************************/
struct vout_sys_t
{
/* The event thread */
vlc_object_t * p_event;
/* Our video output window */
HWND window;
/* Our offscreen bitmap and its framebuffer */
HDC off_dc;
HBITMAP off_bitmap;
BITMAPINFO bitmapinfo;
uint8_t * p_buffer;
};
/*****************************************************************************
* Module descriptor
......@@ -59,6 +86,24 @@ vlc_module_end();
static int OpenVideo ( vlc_object_t *p_this )
{
vout_thread_t * p_vout = (vout_thread_t *)p_this;
vlc_value_t val;
p_vout->p_sys = malloc( sizeof(vout_sys_t) );
if( !p_vout->p_sys )
{
return VLC_ENOMEM;
}
p_vout->p_sys->p_event = vlc_object_create( p_vout, VLC_OBJECT_GENERIC );
if( !p_vout->p_sys->p_event )
{
free( p_vout->p_sys );
return VLC_ENOMEM;
}
var_Create( p_vout->p_sys->p_event, "p_vout", VLC_VAR_ADDRESS );
val.p_address = (void *)p_vout;
var_Set( p_vout->p_sys->p_event, "p_vout", val );
p_vout->pf_init = Init;
p_vout->pf_end = End;
......@@ -74,7 +119,11 @@ static int OpenVideo ( vlc_object_t *p_this )
*****************************************************************************/
static void CloseVideo ( vlc_object_t *p_this )
{
;
vout_thread_t * p_vout = (vout_thread_t *)p_this;
var_Destroy( p_vout->p_sys->p_event, "p_vout" );
vlc_object_destroy( p_vout->p_sys->p_event );
free( p_vout->p_sys );
}
/*****************************************************************************
......@@ -85,13 +134,25 @@ static int Init( vout_thread_t *p_vout )
int i_index;
picture_t *p_pic;
if( vlc_thread_create( p_vout->p_sys->p_event, "GDI Event Thread",
EventThread, 0, 1 ) )
{
msg_Err( p_vout, "cannot spawn EventThread" );
return VLC_ETHREAD;
}
I_OUTPUTPICTURES = 0;
/* Initialize the output structure */
p_vout->output.i_chroma = VLC_FOURCC('R','V','1','6');
p_vout->output.i_rmask = 0xf800;
p_vout->output.i_gmask = 0x07e0;
/* Initialize the output structure - we can use either 8 or 15bpp */
#if DEFAULT_BPP == 8
p_vout->output.i_chroma = VLC_FOURCC('R','G','B','2');
p_vout->output.pf_setpalette = SetPalette;
#else
p_vout->output.i_chroma = VLC_FOURCC('R','V','1','5');
p_vout->output.i_rmask = 0x7c00;
p_vout->output.i_gmask = 0x03e0;
p_vout->output.i_bmask = 0x001f;
#endif
p_vout->output.i_width = p_vout->render.i_width;
p_vout->output.i_height = p_vout->render.i_height;
p_vout->output.i_aspect = p_vout->render.i_aspect;
......@@ -150,6 +211,10 @@ static void End( vout_thread_t *p_vout )
i_index--;
free( PP_OUTPUTPICTURE[ i_index ]->p_data_orig );
}
p_vout->p_sys->p_event->b_die = VLC_TRUE;
PostMessage( p_vout->p_sys->window, WM_NULL, 0, 0 );
vlc_thread_join( p_vout->p_sys->p_event );
}
/*****************************************************************************
......@@ -177,5 +242,178 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
/* No need to do anything, the fake direct buffers stay as they are */
HDC hdc;
int y;
hdc = GetDC( p_vout->p_sys->window );
SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
/* Stupid GDI is upside-down */
for( y = p_pic->p->i_lines ; y-- ; )
{
memcpy( p_vout->p_sys->p_buffer
+ p_pic->p->i_pitch * (p_pic->p->i_lines-y),
p_pic->p->p_pixels + p_pic->p->i_pitch * y,
p_pic->p->i_pitch );
}
BitBlt( hdc, 0, 0, p_vout->output.i_width, p_vout->output.i_height,
p_vout->p_sys->off_dc, 0, 0, SRCCOPY );
ReleaseDC( p_vout->p_sys->window, hdc );
}
/*****************************************************************************
* SetPalette: sets an 8 bpp palette
*****************************************************************************/
static void SetPalette( vout_thread_t *p_vout, u16 *red, u16 *green, u16 *blue )
{
msg_Err( p_vout, "FIXME: SetPalette unimplemented" );
}
/*****************************************************************************
* EventThread: Event handling thread
*****************************************************************************/
static void EventThread ( vlc_object_t *p_event )
{
vout_thread_t * p_vout;
vlc_value_t val;
HINSTANCE instance;
WNDCLASS wc;
MSG msg;
var_Get( p_event, "p_vout", &val );
p_vout = (vout_thread_t *)val.p_address;
instance = GetModuleHandle( NULL );
/* Register window class */
memset( &wc, 0, sizeof(wc) );
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC)WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instance;
wc.hIcon = 0;
wc.hCursor = 0;
wc.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
wc.lpszMenuName = 0;
wc.lpszClassName = L"VOUT";
RegisterClass( &wc );
/* Create output window */
p_vout->p_sys->window =
CreateWindow( L"VOUT", L"Video Output",
WS_VISIBLE | WS_SIZEBOX | WS_CAPTION,
CW_USEDEFAULT, CW_USEDEFAULT,
p_vout->render.i_width,
p_vout->render.i_height + 10,
NULL, NULL, instance, (LPVOID)p_vout );
/* Display our window */
ShowWindow( p_vout->p_sys->window, SW_SHOWNORMAL );
UpdateWindow( p_vout->p_sys->window );
vlc_thread_ready( p_event );
while( !p_event->b_die
&& GetMessage( &msg, p_vout->p_sys->window, 0, 0 ) )
{
if( p_event->b_die )
{
break;
}
DispatchMessage( &msg );
}
DestroyWindow( p_vout->p_sys->window );
}
/*****************************************************************************
* Message handler for the main window
*****************************************************************************/
static long FAR PASCAL WndProc ( HWND hWnd, UINT message,
WPARAM wParam, LPARAM lParam )
{
/* Caution: this only works */
vout_thread_t *p_vout;
if( message == WM_CREATE )
{
/* Store p_vout for future use */
p_vout = (vout_thread_t *)((CREATESTRUCT *)lParam)->lpCreateParams;
SetWindowLong( hWnd, GWL_USERDATA, (LONG)p_vout );
}
else
{
p_vout = (vout_thread_t *)GetWindowLong( hWnd, GWL_USERDATA );
}
switch( message )
{
case WM_LBUTTONDOWN:
break;
case WM_MOUSEMOVE:
break;
case WM_LBUTTONUP:
break;
case WM_CREATE:
InitOffscreen( p_vout );
break;
case WM_DESTROY:
DeleteDC( p_vout->p_sys->off_dc );
DeleteObject( p_vout->p_sys->off_bitmap );
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
/*****************************************************************************
* InitOffscreen: initialize an offscreen bitmap for direct buffer operations.
*****************************************************************************/
static void InitOffscreen( vout_thread_t *p_vout )
{
BITMAPINFOHEADER *p_header = &p_vout->p_sys->bitmapinfo.bmiHeader;
HDC window_dc;
window_dc = GetDC( p_vout->p_sys->window );
p_header->biSize = sizeof( BITMAPINFOHEADER );
p_header->biPlanes = 1;
p_header->biCompression = BI_RGB;
#if DEFAULT_BPP == 8
p_header->biBitCount = 8;
p_header->biSizeImage =
p_vout->render.i_height * p_vout->render.i_width;
#else
p_header->biBitCount = 16;
p_header->biSizeImage =
p_vout->render.i_height * p_vout->render.i_width * 2;
#endif
p_header->biWidth = p_vout->render.i_width;
p_header->biHeight = p_vout->render.i_height;
p_header->biClrImportant = 0;
p_header->biClrUsed = 0;
p_header->biXPelsPerMeter = 0;
p_header->biYPelsPerMeter = 0;
p_vout->p_sys->off_bitmap =
CreateDIBSection( window_dc, (BITMAPINFO *)p_header, DIB_RGB_COLORS,
(void**)&p_vout->p_sys->p_buffer, NULL, 0 );
p_vout->p_sys->off_dc = CreateCompatibleDC( window_dc );
SelectObject( p_vout->p_sys->off_dc, p_vout->p_sys->off_bitmap );
ReleaseDC( 0, window_dc );
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment