📄 linux_fb_surf.cpp
字号:
/* ***** BEGIN LICENSE BLOCK *****
* Version: RCSL 1.0/RPSL 1.0
*
* Portions Copyright (c) 1995-2003 RealNetworks, Inc. All Rights Reserved.
*
* The contents of this file, and the files included with this file, are
* subject to the current version of the RealNetworks Public Source License
* Version 1.0 (the "RPSL") available at
* http://www.helixcommunity.org/content/rpsl unless you have licensed
* the file under the RealNetworks Community Source License Version 1.0
* (the "RCSL") available at http://www.helixcommunity.org/content/rcsl,
* in which case the RCSL will apply. You may also obtain the license terms
* directly from RealNetworks. You may not use this file except in
* compliance with the RPSL or, if you have a valid RCSL with RealNetworks
* applicable to this file, the RCSL. Please see the applicable RPSL or
* RCSL for the rights, obligations and limitations governing use of the
* contents of the file.
*
* This file is part of the Helix DNA Technology. RealNetworks is the
* developer of the Original Code and owns the copyrights in the portions
* it created.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* Technology Compatibility Kit Test Suite(s) Location:
* http://www.helixcommunity.org/content/tck
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */
#include "minisite.h"
#include "hxvsurf.h"
#include "coloracc.h"
#include "minisurf.h"
#include "platform/unix/linux_fb_surf.h"
#include "minifmt.h"
//#include <unistd.h>
#include <fcntl.h>
#include <linux/fb.h>
//#include <linux/kd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
//#include <sys/time.h>
//#include <sys/types.h>
//#include <sys/select.h>
static CFmtObj ImageHelper;
CLinuxFrameBufferSurface::CLinuxFrameBufferSurface(IUnknown* pContext,
CMiniBaseSite* pSite)
: CMiniBaseSurface(pContext, pSite)
, m_nScreenNumber(0)
, m_unDepth(0)
, m_nBitsPerPixel(0)
, m_nCompositionSize(0)
, m_pCompositionSurface(NULL)
, m_frameBufferFD(-1)
, m_pFrameBuffer(0)
{}
CLinuxFrameBufferSurface::~CLinuxFrameBufferSurface()
{
if (m_frameBufferFD != -1)
{
m_pFrameBuffer = 0;
close(m_frameBufferFD);
m_frameBufferFD = -1;
}
HX_FREE(m_pCompositionSurface);
m_nCompositionSize = 0;
m_nCompositionPitch = 0;
memset(&m_surfaceSize, 0, sizeof( m_surfaceSize ) );
}
HX_RESULT CLinuxFrameBufferSurface::_CreateDestBuffer(int cidIn,
int nWidth,
int nHeight,
int& nCount)
{
HX_RESULT res = HXR_OK;
HX_ASSERT( m_pSite );
//HX_ASSERT( m_unDepth );
//For now, we just support 1 format
HX_ASSERT( cidIn == CID_I420 );
//Get the size of this site.
m_pSite->GetSize(m_surfaceSize);
//Malloc the room to hold the actual bits.
HXBitmapInfo bmiTemp;
ImageHelper.MakeBitmap( &bmiTemp,
sizeof(bmiTemp),
GetDstCID(),
m_surfaceSize.cx,
m_surfaceSize.cy,
NULL,
0);
m_nCompositionPitch = ImageHelper.GetBitmapPitch(&bmiTemp);
int imageSize = bmiTemp.bmiHeader.biSizeImage;
res = _ResizeVideoBuffer(imageSize);
HX_ASSERT( ImageHelper.GetBitmapColor(&bmiTemp) == GetDstCID() );
if (!m_pFrameBuffer)
{
res = _OpenFrameBuffer();
}
return res;
}
HX_RESULT CLinuxFrameBufferSurface::_LockDestBuffer(UCHAR** ppDestPtr,
LONG32* pnDestPitch,
int& cid,
REF(HXxSize) srcSize,
int nIndex)
{
*ppDestPtr = m_pCompositionSurface;
*pnDestPitch = m_nCompositionPitch;
cid = GetDstCID();
return HXR_OK;
}
HX_RESULT CLinuxFrameBufferSurface::_TransferToDestBuffer(UCHAR* pSrcBuffer,
HXBitmapInfoHeader* pBitmapInfo,
HXxRect* prSrcRect,
HXxRect* prDstRect,
UCHAR* pDstBuffer,
LONG32 nDstPitch)
{
HX_RESULT res = HXR_OK;
int nCidIn = ImageHelper.GetBitmapColor( (HXBitmapInfo*)pBitmapInfo );
//This minisite, as written, is just doing a blind I420->RGB32
//color convert. Feel free to add whatever you want...
HX_ASSERT( nCidIn == CID_I420 );
if( nCidIn == CID_I420 )
{
//This calls the m_fpColorConverter init'ed in the base class.
res = CMiniBaseSurface::_TransferToDestBuffer(pSrcBuffer,
pBitmapInfo,
prSrcRect,
prDstRect,
pDstBuffer,
nDstPitch);
}
return res;
}
HX_RESULT CLinuxFrameBufferSurface::_UnlockDestBuffer(UCHAR* pSurfPtr, int nIndex=0)
{
return HXR_OK;
}
HX_RESULT CLinuxFrameBufferSurface::_RenderDestBuffer(HXxRect* prSrcRect,
HXxRect* prDestRect,
int nIndex)
{
HX_RESULT res = HXR_FAILED;
int imgWidth = prDestRect->right - prDestRect->left;
int imgHeight = prDestRect->bottom - prDestRect->top;
if (m_pFrameBuffer)
{
#ifdef HELIX_FEATURE_CC_RGB32out
UINT32* pSrc = (UINT32*)m_pCompositionSurface;
#elif defined(HELIX_FEATURE_CC_RGB565out)
UINT16* pSrc = (UINT16*)m_pCompositionSurface;
#endif
UINT16* pDest = m_pFrameBuffer;
int srcDelta = 0;
int dstDelta = 0;
// Compute how much of the image we want to copy
int lines = (imgHeight < m_fbHeight) ? imgHeight : m_fbHeight;
int copyWidth = imgWidth;
if (imgWidth < m_fbWidth)
{
dstDelta = m_fbWidth - imgWidth;
}
else if (imgWidth > m_fbWidth)
{
srcDelta = imgWidth - m_fbWidth;
copyWidth = m_fbWidth;
}
// Center image
int left = (m_fbWidth / 2) - (copyWidth / 2);
int top = (m_fbHeight / 2) - (lines / 2);
pDest += top * m_fbWidth + left;
int i = 0;
for (int y = 0; y < lines; y++)
{
for (int x = 0; x < copyWidth; x++)
{
#ifdef HELIX_FEATURE_CC_RGB32out
// We need to convert RGB32 -> RGB565
UINT32 src = *pSrc++;
UINT32 dst = (((src & 0x00f80000) >> 8) |
((src & 0x0000fc00) >> 5) |
((src & 0x000000f8) >> 3));
*pDest++ = (UINT16)dst;
#elif defined(HELIX_FEATURE_CC_RGB565out)
*pDest++ = *pSrc++;
#endif
}
pSrc += srcDelta;
pDest += dstDelta;
}
res = HXR_OK;
}
return res;
}
HX_RESULT CLinuxFrameBufferSurface::_DestroyDestBuffer(int cid, int nCount)
{
HX_FREE(m_pCompositionSurface);
m_nCompositionSize = 0;
m_nCompositionPitch = 0;
memset(&m_surfaceSize, 0, sizeof( m_surfaceSize ) );
return HXR_OK;
}
int CLinuxFrameBufferSurface::GetDstCID(int nIndex)
{
//Right now the mini site just always outputs in RGB32.
#ifdef HELIX_FEATURE_CC_RGB32out
return CID_RGB32;
#elif defined(HELIX_FEATURE_CC_RGB565out)
return CID_RGB565;
#endif
}
HX_RESULT CLinuxFrameBufferSurface::_ResizeVideoBuffer( INT32 nSize)
{
HX_RESULT retVal=HXR_OK;
//XXXgfw. Trade off here. We can use lots of mem if we just return and
//the user has scaled the image up very much and then goes back down.
//If we don't just return we can do tons and tons of mallocs. Maybe we
//should add a timed callback to reclaim some of this mem after a few
//seconds.
if(nSize <= m_nCompositionSize)
return retVal;
if(m_pCompositionSurface == NULL)
{
m_pCompositionSurface = (UCHAR*) malloc(nSize);
}
else
{
m_pCompositionSurface = (UCHAR*) realloc(m_pCompositionSurface, nSize);
}
if( m_pCompositionSurface )
{
m_nCompositionSize = nSize;
}
else
{
HX_ASSERT("We can't alloc the composition surface." == NULL );
m_nCompositionSize = 0;
}
return retVal;
}
HX_RESULT CLinuxFrameBufferSurface::_OpenFrameBuffer()
{
HX_RESULT res = HXR_FAILED;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
/* Open the file for reading and writing */
m_frameBufferFD = open("/dev/fb0", O_RDWR);
if (m_frameBufferFD == -1)
{
printf("Error: cannot open framebuffer device.\n");
}
else if (ioctl(m_frameBufferFD, FBIOGET_FSCREENINFO, &finfo))
{
printf("Error reading fixed information.\n");
}
else if (ioctl(m_frameBufferFD, FBIOGET_VSCREENINFO, &vinfo))
{
printf("Error reading variable information.\n");
}
else
{
printf("xres:%i , yres:%i , BBP:%i\n ",
vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
m_fbWidth = vinfo.xres;
m_fbHeight = vinfo.yres;
int screen_size = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
/* Map the device to memory */
m_pFrameBuffer = (UINT16*)mmap(0, screen_size,
PROT_READ | PROT_WRITE, MAP_SHARED,
m_frameBufferFD, 0);
if ((int)m_pFrameBuffer == -1)
{
printf("Error: failed to map framebuffer device to memory.\n");
}
else
{
res = HXR_OK;
}
}
return res;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -