偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1747)
分类: LINUX
2010-09-15 11:06:41
|
//这是较早的一份三星修改的6410代码,以适应其寄存器。
//这里列出的代码是改动较大的部分
//怀疑实现时用了None PAGE FLIP,即copy2VirtualDoubleBuffer的硬件加速方法
uint32_t EGLDisplaySurface::swapBuffers()//swapbuffers并没有用到copybit
{
/* If we can't do the page_flip, just copy the back buffer to the front */
if (!(mFlags & PAGE_FLIP))
{
int dev_index = getIndexOfFB(mFb[1].format);
if(copy2VirtualDoubleBuffer(dev_index) < 0)//diff 这儿要注意,如果没有PAGE FLIP,不是直接拷贝,而是调用该函数
{
LOGE("%s::copy2VirtualDoubleBuffer fail\n", __func__);
return -errno;
}
return 0;
}
// do the actual flip
mIndex = 1 - mIndex;
mInfo.activate = FB_ACTIVATE_VBL;
mInfo.yoffset = mIndex ? mInfo.yres : 0;
#if 0
//diff这儿注意,不去调用FBIOPUT_VSCREENINFO,因为这个操作会重写显示寄存器,导致屏幕闪烁
if (ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo) == -1)
{
LOGE("FBIOPUT_VSCREENINFO failed");
return 0;
}
#else
// added by sy82.yoon - remove blinking window on S3C6410(2009.04.21)
/*diff 注意,使用FBIOPAN_DISPLAY ,需要测试这种方法是否能够正常work
*fb_pan_display()
*s3cfb_pan_display()
*s3cfb_set_buffer_address()
*writel(start_addr, ctrl->regs + S3C_VIDADDR_START0(id));Window 0’s buffer start address register, buffer 0
*just only rewrite few regs
*/
if (ioctl(egl_native_window_t::fd, FBIOPAN_DISPLAY, &mInfo) < 0)
{
LOGE("%s::FBIOPAN_DISPLAY fail(%s)", __func__, strerror(errno));
return 0;
}
unsigned int crtc = 0;
if(ioctl(egl_native_window_t::fd, FBIO_WAITFORVSYNC, &crtc) < 0) {
//s3cfb_wait_for_vsync->wait_event_interruptible_timeout
LOGE("%s::FBIO_WAITFORVSYNC fail(%s)", __func__, strerror(errno));
return 0;
}
#endif
//update the address of the buffer to draw to next
const GGLSurface& buffer = mFb[1 - mIndex];
egl_native_window_t::offset = intptr_t(buffer.data) - egl_native_window_t::base;
mPageFlipCount++;
// We don't support screen-size changes for now
return 0;
}
status_t EGLDisplaySurface::mapFrameBuffer()
{
//... ...省略
if (flags & PAGE_FLIP)//有PAGE_FLIP
{
unsigned int frame_size = finfo.line_length*info.yres;
offscreen[1] = (uint8_t*)buffer + frame_size;
m_FbPhysAddr[1] = finfo.smem_start + frame_size;
}
else//使用VirtualDoubleBuffer 要调用CMM(Codec Memory Management))这个硬件
{
offscreen[1] = createVirtualDoubleBuffer(info.xres_virtual, info.yres_virtual, info.bits_per_pixel,
finfo.smem_len,
fd, dev_index, ggl_color_format);
#ifdef HW_VIRTUAL_BUFFER
{
m_FbPhysAddr[1] = m_s3cCmm->phys_addr;
}
#endif // HW_VIRTUAL_BUFFER
if (offscreen[1] == 0)
{
LOGE("%s::createVirtualDoubleBuffer fail\n", __func__);
munmap(buffer, finfo.smem_len);
return NO_MEMORY;
}
memset(offscreen[1], 0, finfo.smem_len);
}
}
// ----------------------------------------------------------------------------
// s3c6410
// 以下是为s3c6410添加的代码
// ----------------------------------------------------------------------------
unsigned char * EGLDisplaySurface::createVirtualDoubleBuffer(int width, int height, int bpp,
unsigned int buffer_size,
int fb_fd, int fb_index,
int ggl_color_format)
{
//... ...省略
#ifdef HW_VIRTUAL_BUFFER
{
s3c_fb_next_info_t fb_info;
int g2d_colorformat = convertFormatGGL2G2d(ggl_color_format);//将GGL转换为G2d模式
if(createG2d(m_s3cG2d, g2d_colorformat) < 0)//createG2d
{
LOGE("%s::createG2d fail\n", __func__);
return NULL;
}
if(createCmm(m_s3cCmm, fb_info.phy_start_addr, buffer_size) < 0)//createCmm
{
LOGE("%s::createCmm fail\n", __func__);
return NULL;
}
virtual_buffer = m_s3cCmm->virt_addr;
}
#else
{
virtual_buffer = (uint8_t*)malloc(buffer_size);
}
#endif // HW_VIRTUAL_BUFFER
return virtual_buffer;
}
int EGLDisplaySurface::destroyVirtualDoubleBuffer(int fb_index)
{
//卸载函数
}
int EGLDisplaySurface::copy2VirtualDoubleBuffer(int fb_index)
{
#ifdef HW_VIRTUAL_BUFFER
{
if(doG2D(m_s3cG2d, m_s3cCmm->phys_addr, m_s3cCmm->phys_addr_dst,//也可以用g2d加速方法
mInfo.xres, mInfo.yres) < 0)
{
LOGE("%s::doG2D fail\n", __func__);
return -1;
}
}
#else
{
memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);//这是android的默认模式
}
#endif // HW_VIRTUAL_BUFFER
return 0;
}
// ----------------------------------------------------------------------------
#ifdef HW_VIRTUAL_BUFFER
// ----------------------------------------------------------------------------
// s3c-g2d创建函数
int EGLDisplaySurface::createG2d(s3c_g2d_t * s3c_g2d, int color_format)
{
#define S3C_G2D_DEV_NAME "/dev/s3c-g2d"
s3c_g2d->dev_fd = open(S3C_G2D_DEV_NAME, O_RDWR);
s3c_g2d_params *params = &s3c_g2d->params;
params->bpp_src = (G2D_COLOR_SPACE)color_format;
params->bpp_dst = (G2D_COLOR_SPACE)color_format;
params->alpha_mode = 0;
params->alpha_val = 0;
params->color_key_mode = 0;
params->color_key_val = 0;
return 0;
}
int EGLDisplaySurface::destroyG2d(s3c_g2d_t *s3c_g2d)
{
close(s3c_g2d->dev_fd);
s3c_g2d->dev_fd = 0;
return 0;
}
//g2d真正的操作函数,2D引擎负责搬运,CMM负责管理内存
int EGLDisplaySurface::doG2D(s3c_g2d_t * s3c_g2d, unsigned int src_addr, unsigned int dst_addr, u32 width, u32 height)
{
s3c_g2d_params *params = &s3c_g2d->params;
params->src_base_addr = src_addr;//源地址
params->src_full_width = width;
params->src_full_height = height;
params->src_start_x = 0;
params->src_start_y = 0;
params->src_work_width = width-1;
params->src_work_height = height-1;
params->dst_base_addr = dst_addr;//目的地址
params->dst_full_width = width;
params->dst_full_height = height;
params->dst_start_x = 0;
params->dst_start_y = 0;
params->dst_work_width = width-1;
params->dst_work_height = height-1;
//initialize clipping window
params->cw_x1 = 0;
params->cw_y1 = 0;
params->cw_x2 = width-1;
params->cw_y2 = height-1;
if(ioctl(s3c_g2d->dev_fd, S3C_G2D_ROTATOR_0, params) < 0)//其实g2D只有一个S3C_G2D_ROTATOR_0函数
{
LOGE("%s::S3C_G2D_ROTATOR fail\n", __func__);
return -1;
}
return 0;
}
// ----------------------------------------------------------------------------
// s3c-cmm Codec Memory Management 创建函数
int EGLDisplaySurface::createCmm (s3c_cmm_t * s3c_cmm, unsigned int phys_addr_dst, unsigned int size)
{
CODEC_GET_PHY_ADDR_ARG codec_get_phy_addr_arg;
unsigned char * cmm_cached_addr;
unsigned char * cmm_non_cached_addr;
#define CMM_DEVICE_DEV_NAME "/dev/s3c-cmm"
s3c_cmm->dev_fd = open(CMM_DEVICE_DEV_NAME, O_RDWR | O_NDELAY);
// Mapping cacheable memory area
cmm_cached_addr = (unsigned char *)mmap(0, CODEC_CACHED_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, s3c_cmm->dev_fd, 0);
// Mapping non-cacheable memory area
cmm_non_cached_addr = (unsigned char *)mmap(0,
CODEC_NON_CACHED_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
s3c_cmm->dev_fd, CODEC_CACHED_MEM_SIZE);
s3c_cmm->alloc_arg.buffSize = size;
s3c_cmm->alloc_arg.cached_mapped_addr = (unsigned int)cmm_cached_addr;
s3c_cmm->alloc_arg.non_cached_mapped_addr = (unsigned int)cmm_non_cached_addr;
s3c_cmm->alloc_arg.cacheFlag = 1; // 1: cacheable, 0: non-cacheable
if (ioctl(s3c_cmm->dev_fd, IOCTL_CODEC_MEM_ALLOC, &s3c_cmm->alloc_arg) == 0)
{
LOGE("IOCTL_CODEC_MEM_ALLOC fail \n");
return -1;
}
CODEC_CACHE_FLUSH_ARG codec_cache_flush_arg;
codec_cache_flush_arg.u_addr = s3c_cmm->alloc_arg.out_addr;
codec_cache_flush_arg.size = s3c_cmm->alloc_arg.buffSize;
ioctl(s3c_cmm->dev_fd, IOCTL_CODEC_CACHE_FLUSH, &codec_cache_flush_arg);
// Get physical address
codec_get_phy_addr_arg.u_addr = s3c_cmm->alloc_arg.out_addr;
ioctl(s3c_cmm->dev_fd, IOCTL_CODEC_GET_PHY_ADDR, &codec_get_phy_addr_arg);
s3c_cmm->virt_addr = (unsigned char*)codec_get_phy_addr_arg.u_addr;
s3c_cmm->phys_addr = (unsigned int)codec_get_phy_addr_arg.p_addr;
s3c_cmm->phys_addr_dst = phys_addr_dst;
return 0;
}
int EGLDisplaySurface::destroyCmm(s3c_cmm_t * s3c_cmm)
{
codec_mem_free_arg.u_addr = s3c_cmm->alloc_arg.out_addr;
ioctl(s3c_cmm->dev_fd, IOCTL_CODEC_MEM_FREE, codec_mem_free_arg);
}
#endif // HW_VIRTUAL_BUFFER
============================================================================
//这是另外一份三星修改的6410代码
//同样列出的代码是改动较大的部分
//已经没有copy2VirtualDoubleBuffer硬件加速方法,swapbuffer使用PAN_DISPLAY
EGLDisplaySurface::EGLDisplaySurface()
: EGLNativeSurface
{
//构造函数没有变化
}
EGLDisplaySurface::~EGLDisplaySurface()
{
//析构多了以下内容
if(2 <= DEFAULT_FB_NUM)
{
if(ioctl(egl_native_window_t::fd, S3C_FB_OSD_STOP) < 0)
LOGE("%s::S3C_FB_OSD_SET_INFO error\n", __func__);
}
}
uint32_t EGLDisplaySurface::swapBuffers()
{
//swapbuffer函数主要是将ioctl(egl_native_window_t::fd, FBIOPUT_VSCREENINFO, &mInfo)
//修改为ioctl(egl_native_window_t::fd, FBIOPAN_DISPLAY, &mInfo)
//nocite!我测试时会报错!
/* If we can't do the page_flip, just copy the back buffer to the front */
if (!(mFlags & PAGE_FLIP))
{
memcpy(mFb[0].data, mFb[1].data, mInfo.xres*mInfo.yres*2);
return 0;
}
// do the actual flip
mIndex = 1 - mIndex;
mInfo.activate = FB_ACTIVATE_VBL;
mInfo.yoffset = mIndex ? mInfo.yres : 0;
if (ioctl(egl_native_window_t::fd, FBIOPAN_DISPLAY, &mInfo) < 0)
{
LOGE("%s::FBIOPAN_DISPLAY fail(%s)", __func__, strerror(errno));
return 0;
}
unsigned int crtc = 0;
if(ioctl(egl_native_window_t::fd, FBIO_WAITFORVSYNC, &crtc) < 0)
{
LOGE("%s::FBIO_WAITFORVSYNC fail(%s)", __func__, strerror(errno));
return 0;
}
// update the address of the buffer to draw to next
const GGLSurface& buffer = mFb[1 - mIndex];
egl_native_window_t::offset = intptr_t(buffer.data) - egl_native_window_t::base;
mPageFlipCount++;
// We don't support screen-size changes for now
return 0;
}
status_t EGLDisplaySurface::mapFrameBuffer()
{
char const * const device_template[] = {
"/dev/graphics/fb%u",
"/dev/fb%u",
0 };
int fd = -1;
int i=0;
char name[64];
int ggl_color_format = GGL_PIXEL_FORMAT_RGB_565;
int dev_index = DEFAULT_FB_NUM;
//初始化时多了一些OSD内容
if(ioctl(fd, S3C_FB_VS_START) < 0)
{
LOGE("%s::S3C_FB_VS_START fail\n", __func__);
return -errno;
}
if(ioctl(fd, S3C_FB_SET_VSYNC_INT) < 0)
{
LOGE("%s::S3C_FB_SET_VSYNC_INT fail\n", __func__);
return -errno;
}
//if(2 <= DEFAULT_FB_NUM)
{
s3c_win_info_t s3c_win_info;
s3c_win_info.left_x = 0;
s3c_win_info.top_y = 0;
s3c_win_info.width = info.xres;
s3c_win_info.height = info.yres;
s3c_win_info.bpp = info.bits_per_pixel;
if (ioctl(fd, S3C_FB_OSD_SET_INFO, &s3c_win_info) < 0)
{
LOGE("%s::S3C_FB_OSD_SET_INFO error\n", __func__);
return -errno;
}
if (ioctl(fd, S3C_FB_OSD_START) < 0)
{
LOGD("%s::S3C_FB_OSD_START error\n", __func__);
return -errno;
}
}
return fd;
}