http://hi.baidu.com/aokikyon/blog/item/0f8e857eaf285e340dd7da36.htmlhttp://hi.baidu.com/aokikyon/blog/item/906ee2ca3db13f4af31fe740.htmlhttp://hi.baidu.com/aokikyon/blog/item/8ca566439c8b871d9213c647.htmlhttp://www.google.com/codesearch/p?hl=zh-CN#2IXyam9IX44/drivers/video/samsung/s3cfb_fimd4x.c&q=S3C_FB_OSD_SET_INFO&d=0其实就是双BUFFER惹的祸, 其实只要框架和驱动配合好就OK。驱动部分在git://github.com/leshak/i5700-leshak-kernel.git中的driver/video/samsung 中已经实现可以参考。框架部分 参考 http://hi.baidu.com/aokikyon/blog/item/0f8e857eaf285e340dd7da36.html。EGLDisplaySurface分析(3)——for S3C64102010-04-04 20:10//这是较早的一份三星修改的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 nextconst 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_BUFFERreturn 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_BUFFERreturn 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 windowparams->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 areacmm_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 areacmm_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-cacheableif (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 addresscodec_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_DISPLAYEGLDisplaySurface::EGLDisplaySurface() : EGLNativeSurfaceEGLDisplaySurface>(){//构造函数没有变化}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 flipmIndex = 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 nextconst 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{ 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;}EGLDisplaySurface分析(3)——for S3C64102010-04-04 20:10//这是较早的一份三星修改的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) { 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){ 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)//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 nextconst 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) { LOGE("%s::createG2d fail\n", __func__); return NULL; } if(createCmm(m_s3cCmm, fb_info.phy_start_addr, buffer_size) { 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_BUFFERreturn 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) { 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_BUFFERreturn 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 windowparams->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){ 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 areacmm_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 areacmm_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-cacheableif (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 addresscodec_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_DISPLAYEGLDisplaySurface::EGLDisplaySurface() : EGLNativeSurface(){//构造函数没有变化}EGLDisplaySurface::~EGLDisplaySurface(){//析构多了以下内容if(2{ if(ioctl(egl_native_window_t::fd, S3C_FB_OSD_STOP) 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 flipmIndex = 1 - mIndex;mInfo.activate = FB_ACTIVATE_VBL;mInfo.yoffset = mIndex ? mInfo.yres : 0;if (ioctl(egl_native_window_t::fd, FBIOPAN_DISPLAY, &mInfo){ 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){ LOGE("%s::FBIO_WAITFORVSYNC fail(%s)", __func__, strerror(errno)); return 0;}// update the address of the buffer to draw to nextconst 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){ LOGE("%s::S3C_FB_VS_START fail\n", __func__); return -errno;}if(ioctl(fd, S3C_FB_SET_VSYNC_INT){ LOGE("%s::S3C_FB_SET_VSYNC_INT fail\n", __func__); return -errno;}//if(2{ 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) { LOGE("%s::S3C_FB_OSD_SET_INFO error\n", __func__); return -errno; } if (ioctl(fd, S3C_FB_OSD_START) { LOGD("%s::S3C_FB_OSD_START error\n", __func__); return -errno; }}return fd;}