免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1482 | 回复: 0
打印 上一主题 下一主题

EGLDisplaySurface分析(3)——for S3C6410 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-01-05 19:38 |只看该作者 |倒序浏览

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

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP