📄 overlay_ddraw.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_ddraw.c 615 2006-01-26 16:57:51Z picard $
*
* The Core Pocket Media Player
* Copyright (c) 2004-2005 Gabor Kovacs
*
****************************************************************************/
#include "../common.h"
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#ifndef STRICT
#define STRICT
#endif
#include <windows.h>
#if _MSC_VER > 1000
#pragma warning( push, 3 )
#endif
#include "ddraw.h"
#include "overlay_ddraw.h"
/*
#undef DEBUG_BIN
#undef DEBUG_MSG
#undef DEBUG_MSG1
#undef DEBUG_MSG2
#undef DEBUG_MSG3
#undef DEBUG_MSG4
#undef DEBUG_MSG5
#undef DEBUG_MSG6
#undef DEBUG_MSG7
#define DEBUG_BIN(m,x,p,n) DebugBinary(x,p,n)
#define DEBUG_MSG(m,x) DebugMessage(x)
#define DEBUG_MSG1(m,x,a) DebugMessage(x,a)
#define DEBUG_MSG2(m,x,a,b) DebugMessage(x,a,b)
#define DEBUG_MSG3(m,x,a,b,c) DebugMessage(x,a,b,c)
#define DEBUG_MSG4(m,x,a,b,c,d) DebugMessage(x,a,b,c,d)
#define DEBUG_MSG5(m,x,a,b,c,d,e) DebugMessage(x,a,b,c,d,e)
#define DEBUG_MSG6(m,x,a,b,c,d,e,f) DebugMessage(x,a,b,c,d,e,f)
#define DEBUG_MSG7(m,x,a,b,c,d,e,f,g) DebugMessage(x,a,b,c,d,e,f,g)
*/
static void Desc2Surface( const DDSURFACEDESC* Desc, video* p )
{
memset(p,0,sizeof(video));
p->Width = Desc->dwWidth;
p->Height = Desc->dwHeight;
p->Aspect = ASPECT_ONE;
p->Direction = 0;
if (Desc->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
{
p->Pixel.Flags = PF_FOURCC;
p->Pixel.FourCC = Desc->ddpfPixelFormat.dwFourCC;
}
else
if (Desc->ddpfPixelFormat.dwFlags & DDPF_RGB)
{
p->Pixel.Flags = PF_RGB;
p->Pixel.BitCount = Desc->ddpfPixelFormat.dwRGBBitCount;
p->Pixel.BitMask[0] = Desc->ddpfPixelFormat.dwRBitMask;
p->Pixel.BitMask[1] = Desc->ddpfPixelFormat.dwGBitMask;
p->Pixel.BitMask[2] = Desc->ddpfPixelFormat.dwBBitMask;
}
else
if (Desc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1)
{
p->Pixel.Flags = PF_PALETTE;
p->Pixel.BitCount = 1;
}
else
if (Desc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2)
{
p->Pixel.Flags = PF_PALETTE;
p->Pixel.BitCount = 2;
}
else
if (Desc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
{
p->Pixel.Flags = PF_PALETTE;
p->Pixel.BitCount = 4;
}
else
if (Desc->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
{
p->Pixel.Flags = PF_PALETTE;
p->Pixel.BitCount = 8;
}
}
static bool_t Surface2Desc( const video* p, DDSURFACEDESC* Desc, bool_t PixelFormat )
{
memset(Desc,0,sizeof(DDSURFACEDESC));
Desc->dwSize = sizeof(DDSURFACEDESC);
Desc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT;
Desc->dwWidth = p->Width;
Desc->dwHeight = p->Height;
if (PixelFormat)
{
Desc->dwFlags |= DDSD_PIXELFORMAT;
Desc->ddpfPixelFormat.dwSize = sizeof(Desc->ddpfPixelFormat);
if (p->Pixel.Flags & PF_FOURCC)
{
Desc->ddpfPixelFormat.dwFlags = DDPF_FOURCC;
Desc->ddpfPixelFormat.dwFourCC = p->Pixel.FourCC;
}
else
if (p->Pixel.Flags & PF_RGB)
{
Desc->ddpfPixelFormat.dwFlags = DDPF_RGB;
Desc->ddpfPixelFormat.dwRGBBitCount = p->Pixel.BitCount;
Desc->ddpfPixelFormat.dwRBitMask = p->Pixel.BitMask[0];
Desc->ddpfPixelFormat.dwGBitMask = p->Pixel.BitMask[1];
Desc->ddpfPixelFormat.dwBBitMask = p->Pixel.BitMask[2];
}
else
if (p->Pixel.Flags & PF_PALETTE)
{
switch (p->Pixel.BitCount)
{
case 1: Desc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED1; break;
case 2: Desc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED2; break;
case 4: Desc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED4; break;
case 8: Desc->ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8; break;
}
Desc->ddpfPixelFormat.dwRGBBitCount = p->Pixel.BitCount;
}
else
return 0;
}
return 1;
}
static bool_t ClearBuffer(ddraw* p,LPDIRECTDRAWSURFACE Buffer)
{
bool_t Result = 0;
DDSURFACEDESC Desc;
Desc.dwSize = sizeof(Desc);
TRY_BEGIN
if (IDirectDrawSurface_Lock(Buffer,NULL,&Desc,DDLOCK_WAIT,NULL) == DD_OK)
{
int v,x2,y2,pitch2;
FillInfo(&p->Overlay.Pixel);
v = RGBToFormat(CRGB(0,0,0),&p->Overlay.Pixel);
TRY_BEGIN
if (PlanarYUV(&p->Overlay.Pixel,&x2,&y2,&pitch2) && p->Overlay.Pixel.BitCount==8)
{
uint8_t* i = (uint8_t*)Desc.lpSurface;
FillColor(i,Desc.lPitch,0,0,p->Overlay.Width,p->Overlay.Height,8,v & 255);
i += Desc.lPitch * p->Overlay.Height;
FillColor(i,Desc.lPitch >> pitch2,0,0,p->Overlay.Width >> x2,p->Overlay.Height >> y2,8,(v>>8)&255);
i += (Desc.lPitch >> x2) * (p->Overlay.Height >> y2);
FillColor(i,Desc.lPitch >> pitch2,0,0,p->Overlay.Width >> x2,p->Overlay.Height >> y2,8,(v>>16)&255);
}
else
if (PackedYUV(&p->Overlay.Pixel) && p->Overlay.Pixel.BitCount==16)
FillColor(Desc.lpSurface,Desc.lPitch,0,0,p->Overlay.Width >> 1,p->Overlay.Height,32,v);
else
FillColor(Desc.lpSurface,Desc.lPitch,0,0,p->Overlay.Width,p->Overlay.Height,p->Overlay.Pixel.BitCount,v);
Result = 1;
TRY_END
IDirectDrawSurface_Unlock(Buffer,NULL);
}
TRY_END
return Result;
}
static void ReleaseBuffers(ddraw* p)
{
if (p->DDBackBuffer)
{
IDirectDrawSurface_Release(p->DDBackBuffer);
p->DDBackBuffer = NULL;
}
if (p->DDBuffer)
{
if (p->Mode == MODE_OVERLAY)
IDirectDrawSurface_UpdateOverlay(p->DDBuffer,NULL,p->DDPrimary,NULL,DDOVER_HIDE,NULL);
IDirectDrawSurface_Release(p->DDBuffer);
p->DDBuffer = NULL;
}
}
static bool_t CreateBuffer(ddraw* p,bool_t PixelFormat)
{
DDSURFACEDESC Desc;
p->BufferPixelFormat = PixelFormat;
if (p->DDBackBuffer)
{
IDirectDrawSurface_Release(p->DDBackBuffer);
p->DDBackBuffer = NULL;
}
if (p->DDBuffer)
{
IDirectDrawSurface_Release(p->DDBuffer);
p->DDBuffer = NULL;
}
if (!Surface2Desc(&p->Overlay,&Desc,PixelFormat))
return 0;
Desc.dwFlags |= DDSD_CAPS;
Desc.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY;
if (p->Mode == MODE_OVERLAY)
{
Desc.ddsCaps.dwCaps |= DDSCAPS_OVERLAY;
Desc.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
Desc.dwFlags |= DDSD_BACKBUFFERCOUNT;
Desc.dwBackBufferCount = 1;
}
DEBUG_MSG5(DEBUG_VIDEO,T("DDRAW CreateSurface %08x %dx%d %08x %08x"),Desc.ddsCaps.dwCaps,Desc.dwWidth,Desc.dwHeight,Desc.ddpfPixelFormat.dwFlags,Desc.ddpfPixelFormat.dwFourCC);
if (IDirectDraw_CreateSurface(p->DD,&Desc,&p->DDBuffer,NULL) != DD_OK)
{
if (p->Mode == MODE_OVERLAY)
{
// try without backbuffer...
Desc.ddsCaps.dwCaps &= ~(DDSCAPS_COMPLEX | DDSCAPS_FLIP);
Desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
IDirectDraw_CreateSurface(p->DD,&Desc,&p->DDBuffer,NULL);
}
if (!p->DDBuffer)
{
DEBUG_MSG(DEBUG_VIDEO,T("DDRAW CreateSurface Failed"));
return 0;
}
}
else
if (p->Mode == MODE_OVERLAY)
{
Desc.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
IDirectDrawSurface_GetAttachedSurface(p->DDBuffer,&Desc.ddsCaps,&p->DDBackBuffer);
}
if (IDirectDrawSurface_GetSurfaceDesc(p->DDBuffer,&Desc) == DD_OK)
Desc2Surface(&Desc,&p->Overlay);
DEBUG_MSG(DEBUG_VIDEO,T("DDRAW CreateSurface Ok"));
if (!ClearBuffer(p,p->DDBuffer))
{
ReleaseBuffers(p);
return 0;
}
if (p->DDBackBuffer)
ClearBuffer(p,p->DDBackBuffer);
return 1;
}
static int UpdateOverlay(ddraw* p)
{
p->Src.left = p->OverlayRect.x;
p->Src.top = p->OverlayRect.y;
p->Src.right = p->OverlayRect.x + p->OverlayRect.Width;
p->Src.bottom = p->OverlayRect.y + p->OverlayRect.Height;
p->Dst.left = p->p.DstAlignedRect.x;
p->Dst.top = p->p.DstAlignedRect.y;
p->Dst.right = p->p.DstAlignedRect.x + p->p.DstAlignedRect.Width;
p->Dst.bottom = p->p.DstAlignedRect.y + p->p.DstAlignedRect.Height;
if (p->Mode == MODE_OVERLAY &&
p->OverlayRect.Width>0 && p->OverlayRect.Height>0 &&
p->p.DstAlignedRect.Width>0 && p->p.DstAlignedRect.Height>0)
{
DWORD hResult;
int Flags = 0;
DDOVERLAYFX DDFX;
memset(&DDFX,0,sizeof(DDFX));
DDFX.dwSize = sizeof(DDFX);
if (p->OvlFX.Flags & (BLITFX_ARITHSTRETCH50|BLITFX_ARITHSTRETCHALWAYS))
{
Flags |= DDOVER_DDFX;
DDFX.dwDDFX |= DDOVERFX_ARITHSTRETCHY;
}
if (p->p.Show)
Flags |= DDOVER_SHOW;
else
Flags |= DDOVER_HIDE;
if (p->p.ColorKey != RGB_NULL)
{
Flags |= DDOVER_KEYDEST;
//Flags |= DDOVER_KEYDESTOVERRIDE;
//DDFX.dckDestColorkey.dwColorSpaceLowValue = RGBToFormat(p->p.ColorKey,&p->p.Output.Format.Video.Pixel);
//DDFX.dckDestColorkey.dwColorSpaceHighValue = 0;
}
hResult = IDirectDrawSurface_UpdateOverlay(p->DDBuffer,&p->Src,p->DDPrimary,&p->Dst,Flags,&DDFX);
if (hResult != DD_OK)
DEBUG_MSG1(DEBUG_VIDEO,T("DDRAW UpdateOverlay failed %08x"),hResult);
}
return ERR_NONE;
}
static void GetMode(ddraw *p)
{
DDSURFACEDESC Desc;
memset(&Desc,0,sizeof(DDSURFACEDESC));
Desc.dwSize = sizeof(DDSURFACEDESC);
IDirectDraw_GetDisplayMode(p->DD,&Desc);
Desc2Surface(&Desc,&p->p.Output.Format.Video);
FillInfo(&p->p.Output.Format.Video.Pixel);
}
static int GetAlign(int i)
{
int v=1;
while (v<16 && v<i)
v<<=1;
return v;
}
static int Init(ddraw* p)
{
DDSURFACEDESC Desc;
p->p.ColorKey = RGB_NULL;
if (p->SetupColorKey && IsWindow(Context()->Wnd))
p->p.ColorKey = COLORKEY;
if (p->DDCaps.dwCaps & DDCAPS_OVERLAYSTRETCH)
{
p->MinScale = (p->DDCaps.dwMinOverlayStretch * SCALE_ONE) / 1000;
p->MaxScale = (p->DDCaps.dwMaxOverlayStretch * SCALE_ONE) / 1000;
}
else
{
p->MinScale = SCALE_ONE;
p->MaxScale = SCALE_ONE;
}
if (p->DDCaps.dwCaps & DDCAPS_ALIGNBOUNDARYDEST)
p->DstAlignPos = GetAlign(p->DDCaps.dwAlignBoundaryDest);
else
p->DstAlignPos = 1;
if (p->DDCaps.dwCaps & DDCAPS_ALIGNSIZEDEST)
p->DstAlignSize = GetAlign(p->DDCaps.dwAlignSizeDest);
else
p->DstAlignSize = 1;
GetMode(p);
// get primary surface
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -