📄 pg_graphics.cpp
字号:
/*****************************************************************************
******************************************************************************
** **
** Copyright (c) 2005-2006 Videon Central, Inc. **
** All rights reserved. **
** **
** The computer program contained herein contains proprietary information **
** which is the property of Videon Central, Inc. The program may be used **
** and/or copied only with the written permission of Videon Central, Inc. **
** or in accordance with the terms and conditions stipulated in the **
** agreement/contract under which the programs have been supplied. **
** **
******************************************************************************
*****************************************************************************/
/**
* @file pg_graphics.cpp
*
* $Revision: 1.4 $
*
* PG graphics drawing routines
*
*/
#include "pg_api.h"
#include "pg_defs.h"
#include "pg_util.h"
#include "pg_graphics.h"
#include "directfb.h"
#ifdef DMALLOC
#include "dmalloc.h"
#endif
#define DEBUG_PG_GRAPHICS DBG_ERROR
#define DBG_ON(x) (DEBUG_PG_GRAPHICS >= x)
DFBRegion gPGFlipRegion;
DFBRectangle PGCleanupList[PG_MAX_ODS]; /* our list of objects to clean on screen */
ULONG gPGImageIndex = 0;
/* externs */
extern PALETTE PGPalettes[PG_MAX_PALETTES];
extern OBJECT_DEFINITION_SEGMENT PGObjList[PG_MAX_ODS];
extern PGINFO PGInfo;
extern PGSTATS PGStats;
/* local prototypes */
void PGAddToCleanupList(int X, int Y, int Width, int Height);
/**
* PGGraphicsSetPalette - update the palette for the currently displayed surface
*
* @param PALETTE *Pal - The palette to set on DirectFB
*
* @return PG_STATUS
*/
PG_STATUS PGGraphicsSetPalette(PALETTE *Pal)
{
if (NULL == Pal)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PG: Invalid palette\n"));
return PG_STATUS_ERROR;
}
if (NULL == Pal->DFBPal)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PG: Invalid DFB palette\n"));
return PG_STATUS_ERROR;
}
/* set the palette for the primary surface */
if (Pal->DFBPal->SetEntries(Pal->DFBPal, Pal->Colors, PG_MAX_PALETTE_COLORS, 0) != DFB_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGGraphicsSetPalette(): Failed to set palette entries\n"));
return PG_STATUS_ERROR;
}
/* set palette for primary surface */
if (DFB_OK != PGInfo.DFBInfo.PrimarySurface->SetPalette(PGInfo.DFBInfo.PrimarySurface, Pal->DFBPal))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("Failed to set palette\n"));
return PG_STATUS_ERROR;
}
return PG_STATUS_SUCCESS;
}
/**
* PGGraphicsDrawCompObj - draw the given composition object on screen, cropped images also
*
* @param COMPOSITION_OBJECT *CompObj - The Composition object to draw
* @param PALETTE *Pal - The palette used to convert RLE to ARGB
*
* @return PG_STATUS
*/
PG_STATUS PGGraphicsDrawCompObj(COMPOSITION_OBJECT *CompObj)
{
OBJECT_DEFINITION_SEGMENT *Img=NULL;
USHORT DrawX, DrawY, DrawW, DrawH;
USHORT ScreenMaxX, ScreenMaxY;
DFBResult Result;
int imgsize;
#ifdef ALLOW_PG_PROFILING
ULONG TickStart = 0;
#endif
DBGPRINT(DBG_ON(DBG_TRACE), ("PGGraphicsDrawCompObj: Draw Object %d\n", CompObj->ObjectIDRef));
/* grab the object from the list */
Img = &PGObjList[CompObj->ObjectIDRef];
if (0 == Img->InUse)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGGraphicsDrawCompObj(): Could not render object it is not available in PGRender, id %d\n", CompObj->ObjectIDRef));
return PG_STATUS_ERROR;
}
/* we need to create a new surface */
imgsize = Img->ObjData.Width * Img->ObjData.Height;
if ((0 == imgsize) || (imgsize > 1920 * 1080))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGGraphicsDrawCompObj(): ERROR imgsize is zero or too large\n"));
return PG_STATUS_ERROR;
}
/* make sure the image is at least 8 pixels wide (spec) */
if ((Img->ObjData.Width < 8) || (Img->ObjData.Height < 8))
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGGraphicsDrawCompObj(): Do not draw image, too small w=%d h=%d\n", Img->ObjData.Width, Img->ObjData.Height));
goto errout;
}
/* load drawing params, if we are drawing half width cut all x coords in half */
if (PGInfo.CoordsHalfWidth == 0)
{
DrawX = CompObj->XPosition;
DrawY = CompObj->YPosition;
DrawW = Img->ObjData.Width;
DrawH = Img->ObjData.Height;
ScreenMaxX = MAX_GRFX_WIDTH;
ScreenMaxY = MAX_GRFX_HEIGHT;
}
else
{
DrawX = CompObj->XPosition/2;
DrawY = CompObj->YPosition;
DrawW = (Img->ObjData.Width+1)/2;
DrawH = Img->ObjData.Height;
ScreenMaxX = MAX_GRFX_WIDTH/2;
ScreenMaxY = MAX_GRFX_HEIGHT;
}
/* see if the image is cropped */
if (!CompObj->CroppedFlag)
{
/* check that we do not go outside screen space */
if ((DrawX <= ScreenMaxX) && (DrawY <= ScreenMaxY) &&
((DrawX + DrawW) <= ScreenMaxX) && ((DrawY + DrawH) <= ScreenMaxY))
{
/* image is not cropped */
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
TickStart = OS_GetTicks();
}
#endif
Result = PGInfo.DFBInfo.PrimarySurface->Blit(PGInfo.DFBInfo.PrimarySurface, Img->SurfaceLUT8, NULL, DrawX, DrawY);
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalBlitTicks += OS_GetTicks() - TickStart;
}
#endif
if (Result == DFB_OK)
{
PGAddToCleanupList(DrawX, DrawY, DrawW, DrawH);
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PG Blit Failed object %d\n", CompObj->ObjectIDRef));
}
}
}
else
{
/* img is cropped */
DFBRectangle Rect;
if (PGInfo.CoordsHalfWidth == 0)
{
Rect.x = CompObj->Rect.X;
Rect.y = CompObj->Rect.Y;
Rect.w = CompObj->Rect.Width;
Rect.h = CompObj->Rect.Height;
}
else
{
Rect.x = CompObj->Rect.X/2;
Rect.y = CompObj->Rect.Y;
Rect.w = (CompObj->Rect.Width+1)/2;
Rect.h = CompObj->Rect.Height;
}
if ((DrawX <= ScreenMaxX) && (DrawY <= ScreenMaxY) &&
((DrawX + Rect.w) <= ScreenMaxX) && ((DrawY + Rect.h) <= ScreenMaxY))
{
/* draw the image */
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
TickStart = OS_GetTicks();
}
#endif
Result = PGInfo.DFBInfo.PrimarySurface->Blit(PGInfo.DFBInfo.PrimarySurface, Img->SurfaceLUT8, &Rect, DrawX, DrawY);
#ifdef ALLOW_PG_PROFILING
if (1 == PGStats.Profiling)
{
PGStats.PGTotalBlitTicks += OS_GetTicks() - TickStart;
}
#endif
if (Result == DFB_OK)
{
PGAddToCleanupList(DrawX, DrawY, DrawW, DrawH);
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PG Blit Failed object %d\n", CompObj->ObjectIDRef));
}
}
else
{
DBGPRINT(DBG_ON(DBG_ERROR), ("IGGraphicsDrawCompObj(): image tried to draw out of bounds %d %d %d %d\n",
DrawX, DrawY, DrawX + Rect.w, DrawY + Rect.h));
}
}
return PG_STATUS_SUCCESS;
errout:
return PG_STATUS_ERROR;
}
/**
* PGAddToCleanupList - add an image to the cleanup list, this list will be cleared using the
* clear color when it is time for a display blank
*
* @param int Height - height of the image
* @param int Width - width of the image
* @param int X - starting x coord
* @param int Y - starting y coord
*
* @return PG_STATUS
*/
void PGAddToCleanupList(int X, int Y, int Width, int Height)
{
/* loop looking for a match */
for (ULONG i=0; i<gPGImageIndex; i++)
{
/* see if we match inputs */
if ((PGCleanupList[i].h == Height) &&
(PGCleanupList[i].w == Width) &&
(PGCleanupList[i].x == X) &&
(PGCleanupList[i].y == Y))
{
/* input matches one in the list, don't add */
return;
}
}
/* if we didn't find a match in the list, we got here, so add it */
PGCleanupList[gPGImageIndex].h = Height;
PGCleanupList[gPGImageIndex].w = Width;
PGCleanupList[gPGImageIndex].x = X;
PGCleanupList[gPGImageIndex].y = Y;
/* stretch the flipping region to fit the new coords */
if (X < gPGFlipRegion.x1)
{
gPGFlipRegion.x1 = X;
}
if (Y < gPGFlipRegion.y1)
{
gPGFlipRegion.y1 = Y;
}
if (X+Width > gPGFlipRegion.x2)
{
gPGFlipRegion.x2 = X+Width;
}
if (Y+Height > gPGFlipRegion.y2)
{
gPGFlipRegion.y2 = Y+Height;
}
gPGImageIndex++;
}
/**
* PGGraphicsSetPaletteColors - update the palette for the currently displayed surface
*
* @param DFBPaletteDescription PalDesc - the description of the palette
* @param PALETTE *Pal - The palette to set on DirectFB
*
* @return PG_STATUS
*/
PG_STATUS PGGraphicsSetPaletteColors(int PaletteNumber, BYTE *DataPtr, int NumEntries, BYTE fClearPalette, PG_COLOR_SPACE ColorSpace)
{
BYTE PaletteEntryID;
int i;
PALETTE *CurPal = &PGPalettes[PaletteNumber];
/* if we are not in EPOCH_NORMAL, fclearpalette will be 1, if normal we are just doing an update
don't clear the palette */
if (fClearPalette)
{
memset(CurPal->Colors, 0, sizeof(DFBColor) * PG_MAX_PALETTE_COLORS);
}
/* pal_ptr here points to the first byte which is palette_entry_id (we use it as the palette_color) */
ULONG Color;
BYTE *ClrBytes = (BYTE *)&Color;
/* fill in the palette colors in the correct PaletteEntryID positions in the palette */
for (i=0; i<NumEntries; i++)
{
PaletteEntryID = *DataPtr; /* this is the palette_entry_id */
DataPtr++;
if (ColorSpace == REC_709)
{
/* convert all colors to ARGB */
Color = MakeARGBfromYCrCb709(*DataPtr++, // y
*DataPtr++, //cr
*DataPtr++, //cb
*DataPtr++); //t
}
else
{
/* convert all colors to ARGB */
Color = MakeARGBfromYCrCb601(*DataPtr++, // y
*DataPtr++, //cr
*DataPtr++, //cb
*DataPtr++); //t
}
/* Pal*/
CurPal->Colors[PaletteEntryID].a = ClrBytes[0];
CurPal->Colors[PaletteEntryID].r = ClrBytes[1];
CurPal->Colors[PaletteEntryID].g = ClrBytes[2];
CurPal->Colors[PaletteEntryID].b = ClrBytes[3];
}
return PG_STATUS_SUCCESS;
}
/**
* PGGraphicsCreateAllPalettes - create all the pg palettes
*
* @return PG_STATUS
*/
PG_STATUS PGGraphicsCreateAllPalettes()
{
DFBPaletteDescription PalDesc;
PALETTE *CurPal;
/* loop and create all the dfb palettes but with clear as their colors */
for (int i=0; i<PG_MAX_PALETTES; i++)
{
CurPal = &PGPalettes[i];
for (int j=0; j<PG_MAX_PALETTE_COLORS; j++)
{
CurPal->Colors[j].a = 0;
CurPal->Colors[j].r = 0;
CurPal->Colors[j].g = 0;
CurPal->Colors[j].b = 0;
}
/* setup the description */
PalDesc.flags = (DFBPaletteDescriptionFlags) (DPDESC_SIZE | DPDESC_ENTRIES);
PalDesc.size = PG_MAX_PALETTE_COLORS;
PalDesc.entries = CurPal->Colors;
/* call create palette with the entries we give here */
if (PGInfo.DFBInfo.pDFBHandle->CreatePalette(PGInfo.DFBInfo.pDFBHandle, &PalDesc, &CurPal->DFBPal) != DFB_OK)
{
DBGPRINT(DBG_ON(DBG_ERROR), ("PGGraphicsCreateAllPalettes(): Failed to create DFB Palette\n"));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -