321 lines
8.0 KiB
C
321 lines
8.0 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*
|
||
|
* $Id: overlay_gdi.c 543 2006-01-07 22:06:24Z picard $
|
||
|
*
|
||
|
* The Core Pocket Media Player
|
||
|
* Copyright (c) 2004-2005 Gabor Kovacs
|
||
|
*
|
||
|
****************************************************************************/
|
||
|
|
||
|
#include "../common.h"
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
|
||
|
//#define BLITTEST
|
||
|
|
||
|
#define WIN32_LEAN_AND_MEAN
|
||
|
#ifndef STRICT
|
||
|
#define STRICT
|
||
|
#endif
|
||
|
#include <windows.h>
|
||
|
|
||
|
typedef struct gdi
|
||
|
{
|
||
|
overlay p;
|
||
|
int DIBSection;
|
||
|
HBITMAP Bitmap;
|
||
|
HGDIOBJ Bitmap0; //bitmap returned by selectobject
|
||
|
HDC DC2;
|
||
|
video Overlay;
|
||
|
rect OverlayRect;
|
||
|
planes Planes;
|
||
|
|
||
|
#ifdef BLITTEST
|
||
|
void* Soft2;
|
||
|
planes Planes2;
|
||
|
#endif
|
||
|
|
||
|
} gdi;
|
||
|
|
||
|
static int AllocBitmap(gdi* p)
|
||
|
{
|
||
|
#ifndef BLITTEST
|
||
|
int OldFlags = p->Overlay.Pixel.Flags;
|
||
|
#endif
|
||
|
p->p.Dirty = 1;
|
||
|
|
||
|
if (p->DIBSection)
|
||
|
{
|
||
|
int i;
|
||
|
struct
|
||
|
{
|
||
|
BITMAPINFOHEADER Head;
|
||
|
int BitMask[3];
|
||
|
} Info;
|
||
|
HDC DC = GetDC(NULL);
|
||
|
|
||
|
memset(&Info,0,sizeof(Info));
|
||
|
Info.Head.biSize = sizeof(Info.Head);
|
||
|
Info.Head.biWidth = p->Overlay.Width;
|
||
|
Info.Head.biHeight = -p->Overlay.Height;
|
||
|
Info.Head.biPlanes = 1;
|
||
|
Info.Head.biBitCount = (WORD)p->Overlay.Pixel.BitCount;
|
||
|
Info.Head.biCompression = (p->Overlay.Pixel.BitCount==16 || p->Overlay.Pixel.BitCount==32) ? BI_BITFIELDS:BI_RGB;
|
||
|
Info.Head.biSizeImage = (p->Overlay.Width * p->Overlay.Height * p->Overlay.Pixel.BitCount) >> 3;
|
||
|
for (i=0;i<3;++i)
|
||
|
Info.BitMask[i] = p->Overlay.Pixel.BitMask[i];
|
||
|
|
||
|
p->Bitmap = CreateDIBSection(DC,(BITMAPINFO*)&Info,DIB_RGB_COLORS,&p->Planes[0],NULL,0);
|
||
|
|
||
|
if (p->Bitmap)
|
||
|
p->Bitmap0 = SelectObject(p->DC2,p->Bitmap);
|
||
|
|
||
|
ReleaseDC(NULL,DC);
|
||
|
}
|
||
|
else
|
||
|
p->Planes[0] = Alloc16(p->Overlay.Pitch * p->Overlay.Height);
|
||
|
|
||
|
if (((uintptr_t)p->Planes[0] & 15) || (p->Overlay.Pitch & 15))
|
||
|
p->Overlay.Pixel.Flags &= ~PF_16ALIGNED;
|
||
|
else
|
||
|
p->Overlay.Pixel.Flags |= PF_16ALIGNED;
|
||
|
|
||
|
#ifndef BLITTEST
|
||
|
if (OldFlags != p->Overlay.Pixel.Flags)
|
||
|
{
|
||
|
BlitRelease(p->p.Soft);
|
||
|
p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->p.FX,&p->p.Caps);
|
||
|
BlitAlign(p->p.Soft, &p->OverlayRect, &p->p.SrcAlignedRect);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return p->Planes[0] != NULL;
|
||
|
}
|
||
|
|
||
|
static void FreeBitmap(gdi* p)
|
||
|
{
|
||
|
if (p->Bitmap)
|
||
|
{
|
||
|
SelectObject(p->DC2,p->Bitmap0);
|
||
|
DeleteObject(p->Bitmap);
|
||
|
p->Bitmap = 0;
|
||
|
}
|
||
|
|
||
|
if (p->Planes[0])
|
||
|
{
|
||
|
if (!p->DIBSection)
|
||
|
Free16(p->Planes[0]);
|
||
|
|
||
|
p->Planes[0] = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void Done(gdi* p)
|
||
|
{
|
||
|
FreeBitmap(p);
|
||
|
|
||
|
if (p->DC2)
|
||
|
{
|
||
|
DeleteDC(p->DC2);
|
||
|
p->DC2 = 0;
|
||
|
}
|
||
|
|
||
|
#ifdef BLITTEST
|
||
|
SurfaceFree(p->Planes2);
|
||
|
BlitRelease(p->Soft2);
|
||
|
p->Soft2 = NULL;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static int Init(gdi* p)
|
||
|
{
|
||
|
HDC DC;
|
||
|
QueryDesktop(&p->p.Output.Format.Video);
|
||
|
|
||
|
p->Planes[0] = NULL;
|
||
|
|
||
|
p->Overlay.Width = 0;
|
||
|
p->Overlay.Height = 0;
|
||
|
p->Overlay.Direction = 0;
|
||
|
p->Overlay.Aspect = ASPECT_ONE;
|
||
|
p->Overlay.Pixel = p->p.Output.Format.Video.Pixel;
|
||
|
if (p->Overlay.Pixel.BitCount==24)
|
||
|
DefaultRGB(&p->Overlay.Pixel,24,8,8,8,0,0,0); //BI_BITFIELDS not supported for 24bpp
|
||
|
p->Overlay.Pixel.Flags |= PF_16ALIGNED; // assume it will be aligned
|
||
|
|
||
|
p->DIBSection = (p->Overlay.Pixel.Flags & PF_RGB) != 0;
|
||
|
p->Bitmap = 0;
|
||
|
p->Bitmap0 = 0;
|
||
|
|
||
|
DC = GetDC(NULL);
|
||
|
p->DC2 = CreateCompatibleDC(DC);
|
||
|
ReleaseDC(NULL,DC);
|
||
|
|
||
|
p->p.ClearFX = BLITFX_ONLYDIFF;
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
static int Reset(gdi* p)
|
||
|
{
|
||
|
Done(p);
|
||
|
Init(p);
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
static int Update(gdi* p)
|
||
|
{
|
||
|
rect OldGUI = p->p.GUIAlignedRect;
|
||
|
rect Old = p->p.DstAlignedRect;
|
||
|
|
||
|
int OldWidth = p->Overlay.Width;
|
||
|
int OldHeight = p->Overlay.Height;
|
||
|
|
||
|
VirtToPhy(&p->p.Viewport,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
|
||
|
VirtToPhy(NULL,&p->p.SrcAlignedRect,&p->p.Input.Format.Video);
|
||
|
|
||
|
AnyAlign(&p->p.DstAlignedRect, &p->p.SrcAlignedRect, &p->p.FX, 2, 2, 1, SCALE_ONE*1024 );
|
||
|
|
||
|
PhyToVirt(&p->p.DstAlignedRect,&p->p.GUIAlignedRect,&p->p.Output.Format.Video);
|
||
|
|
||
|
p->Overlay.Width = ALIGN16(p->p.GUIAlignedRect.Width); // we need PF_16ALIGNED for pitch
|
||
|
p->Overlay.Height = p->p.GUIAlignedRect.Height;
|
||
|
p->Overlay.Pitch = (p->Overlay.Width * p->Overlay.Pixel.BitCount) >> 3;
|
||
|
p->Overlay.Pitch = (p->Overlay.Pitch+1) & ~1; //word aligned (it doesn't mater anymore, Width is aligned)
|
||
|
|
||
|
p->OverlayRect.x = p->OverlayRect.y = 0;
|
||
|
p->OverlayRect.Width = p->p.GUIAlignedRect.Width;
|
||
|
p->OverlayRect.Height = p->p.GUIAlignedRect.Height;
|
||
|
|
||
|
#ifdef BLITTEST
|
||
|
{
|
||
|
rect TestAlignedRect = p->OverlayRect;
|
||
|
packetformat TestFormat = {0};
|
||
|
TestFormat.Type = PACKET_VIDEO;
|
||
|
TestFormat.Format.Video = p->Overlay;
|
||
|
TestFormat.Format.Video.Pixel.Flags &= (PF_PALETTE|PF_RGB);
|
||
|
//TestFormat.Format.Video.Pixel.Flags |= PF_FOURCC;
|
||
|
//TestFormat.Format.Video.Pixel.FourCC = FOURCC_Y422;
|
||
|
//PacketFormatDefault(&TestFormat);
|
||
|
DefaultRGB(&TestFormat.Format.Video.Pixel,32,8,8,8,0,0,0);
|
||
|
DefaultPitch(&TestFormat.Format.Video);
|
||
|
|
||
|
SurfaceFree(p->Planes2);
|
||
|
SurfaceAlloc(p->Planes2,&TestFormat.Format.Video);
|
||
|
|
||
|
BlitRelease(p->Soft2);
|
||
|
p->Soft2 = BlitCreate(&TestFormat.Format.Video,&p->p.Input.Format.Video,&p->p.FX,&p->p.Caps);
|
||
|
BlitAlign(p->Soft2,&TestAlignedRect, &p->p.SrcAlignedRect);
|
||
|
|
||
|
BlitRelease(p->p.Soft);
|
||
|
p->p.Soft = BlitCreate(&p->Overlay,&TestFormat.Format.Video,NULL,NULL);
|
||
|
BlitAlign(p->p.Soft,&p->OverlayRect, &TestAlignedRect);
|
||
|
}
|
||
|
#else
|
||
|
BlitRelease(p->p.Soft);
|
||
|
p->p.Soft = BlitCreate(&p->Overlay,&p->p.Input.Format.Video,&p->p.FX,&p->p.Caps);
|
||
|
BlitAlign(p->p.Soft, &p->OverlayRect, &p->p.SrcAlignedRect);
|
||
|
#endif
|
||
|
|
||
|
p->p.GUIAlignedRect.x += p->OverlayRect.x;
|
||
|
p->p.GUIAlignedRect.y += p->OverlayRect.y;
|
||
|
p->p.GUIAlignedRect.Width = p->OverlayRect.Width;
|
||
|
p->p.GUIAlignedRect.Height = p->OverlayRect.Height;
|
||
|
|
||
|
VirtToPhy(&p->p.GUIAlignedRect,&p->p.DstAlignedRect,&p->p.Output.Format.Video);
|
||
|
|
||
|
if (OldWidth != p->Overlay.Width || OldHeight != p->Overlay.Height)
|
||
|
FreeBitmap(p);
|
||
|
|
||
|
if (p->p.Show && !EqRect(&Old,&p->p.DstAlignedRect))
|
||
|
{
|
||
|
WinInvalidate(&OldGUI,0);
|
||
|
WinInvalidate(&p->p.Viewport,1);
|
||
|
WinValidate(&p->p.GUIAlignedRect);
|
||
|
}
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
static int Blit(gdi* p, const constplanes Data, const constplanes DataLast )
|
||
|
{
|
||
|
HDC DC;
|
||
|
|
||
|
if (!p->Planes[0] && !AllocBitmap(p))
|
||
|
return ERR_OUT_OF_MEMORY;
|
||
|
|
||
|
#ifdef BLITTEST
|
||
|
BlitImage(p->Soft2,p->Planes2,Data,DataLast,-1,-1);
|
||
|
BlitImage(p->p.Soft,p->Planes,p->Planes2,NULL,-1,-1);
|
||
|
#else
|
||
|
BlitImage(p->p.Soft,p->Planes,Data,DataLast,-1,-1);
|
||
|
#endif
|
||
|
|
||
|
if (!p->DIBSection)
|
||
|
{
|
||
|
if (p->Bitmap)
|
||
|
{
|
||
|
SelectObject(p->DC2,p->Bitmap0);
|
||
|
DeleteObject(p->Bitmap);
|
||
|
}
|
||
|
|
||
|
p->Bitmap = CreateBitmap( p->Overlay.Width, p->Overlay.Height, 1,
|
||
|
p->Overlay.Pixel.BitCount, (char*)p->Planes[0]);
|
||
|
|
||
|
if (!p->Bitmap)
|
||
|
return ERR_OUT_OF_MEMORY;
|
||
|
|
||
|
p->Bitmap0 = SelectObject(p->DC2,p->Bitmap);
|
||
|
}
|
||
|
|
||
|
DC = GetDC(NULL);
|
||
|
BitBlt(DC,p->p.GUIAlignedRect.x,p->p.GUIAlignedRect.y,
|
||
|
p->OverlayRect.Width,p->OverlayRect.Height,p->DC2,p->OverlayRect.x,p->OverlayRect.y,SRCCOPY);
|
||
|
ReleaseDC(NULL,DC);
|
||
|
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
static int Create(gdi* p)
|
||
|
{
|
||
|
p->p.Init = Init;
|
||
|
p->p.Done = Done;
|
||
|
p->p.Blit = Blit;
|
||
|
p->p.Update = Update;
|
||
|
p->p.Reset = Reset;
|
||
|
return ERR_NONE;
|
||
|
}
|
||
|
|
||
|
static const nodedef GDI =
|
||
|
{
|
||
|
sizeof(gdi)|CF_GLOBAL,
|
||
|
GDI_ID,
|
||
|
OVERLAY_CLASS,
|
||
|
PRI_DEFAULT,
|
||
|
(nodecreate)Create,
|
||
|
};
|
||
|
|
||
|
void OverlayGDI_Init()
|
||
|
{
|
||
|
NodeRegisterClass(&GDI);
|
||
|
}
|
||
|
|
||
|
void OverlayGDI_Done()
|
||
|
{
|
||
|
NodeUnRegisterClass(GDI_ID);
|
||
|
}
|
||
|
|
||
|
#endif
|