Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1152971
  • 博文数量: 222
  • 博客积分: 5262
  • 博客等级: 大校
  • 技术积分: 3028
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-22 19:10
文章分类

全部博文(222)

文章存档

2012年(2)

2011年(192)

2010年(28)

分类: 嵌入式

2011-01-05 19:38:31

//这是较早的一份三星修改的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;
}

阅读(2851) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~