新闻  |   论坛  |   博客  |   在线研讨会
S3C2416 2D加速----转载
hong60104 | 2011-09-14 21:01:24    阅读:1891   发布文章
S3C2416 2D加速

 
 最近调试2D一忙就是2周,现在终于忙完了,要将之前的调试信息全部都写下来,可是不大可能的。
 
当然,主要还是要驱动程序和 应用程序结合调试才能达到效果。
最开始一直使用光栅(ROP),希望能达到想要的效果,结果却一直是出现颜色混合。。
 
后来发现自己居然只使用到了FB0。。至于FB1....默认是关闭的;
而2416上的关键色,要求是两个窗口叠加才能出现效果;这个主要是集中在处理OSD的时候,没能开启。汗一个先。。。
 
关于加速显示的测试程序,在网上找到了几篇,比如
 http://apps.hi.baidu.com/share/detail/17513859
虽然貌似不上架,很难使用,但是基本上思路还有的。
根据需要,改成我自己驱动的情况:
 
 
00001: #include <stdlib.h>
00002: #include <stdio.h>
00003: #include <string.h>
00004: #include <unistd.h>
00005: #include <fcntl.h>
00006: #include <sys/ioctl.h>
00007: #include <sys/types.h>
00008: #include <sys/mman.h>
00010: #include <errno.h>
00012: #include <stdint.h> //uint32_t uint8_t
00013: #include "s3c_g2d.h"
00014: #include <linux/fb.h>
00015:
00016: #include <sys/stat.h>
00017: #include <unistd.h>
00018:
00019: #include <sys/time.h>
00020:
00021: #include "def.h"
00022:
00023: /***********************************************************
00024: * Global image file descriptor
00025: ***********************************************************/
00026: int g2d_fd;
00027:
00028: #ifdef FB0_OPERATION
00029: int fb0_fd;
00030: #endif
00031:
00032: int fb1_fd;
00033:
00034: struct fb_fix_screeninfo finfo;
00035: struct fb_var_screeninfo info;
00036:
00037: void printHex(char * p, unsigned char * data, int len)
00038: {
00039:     int i;
00040:     if(p)
00041:     {
00042:         printf("|%s|:[addr=%p][len=%d]:/n",p,data,len);
00043:     }
00044:     len = len>128 ? 128: len;
00045:     for(i=0;i<len;i++)
00046:     {
00047:         printf("%02x,",data[i]);
00048:         if((i+1)%16 ==0)
00049:         printf("/n");
00050:     }
00051:     printf("|%s|/n/n",p);
00052: }
00053:
00054: /*********************************************
00055: * file operaton
00056: **********************************************/
00057: int open_file_image(char* file_name,int * file_fd,int * file_len)
00058: {
00059:     int rv;
00060:     struct stat buf;
00061:
00062:     rv = stat (file_name,&buf);
00063:     if(rv != 0 || buf.st_size < 1)
00064:     {
00065:        perror("stat");
00066:     return -1;
00067:     }
00068:
00069:     *file_len = buf.st_size;
00070:
00071:     *file_fd = open(file_name,O_RDWR);
00072:     if((*file_fd) < 0)
00073:     {
00074:         perror("fopen");
00075:         return -1;
00076:     }
00078:     return 0;
00079: } ? end open_file_image ?
00080:
00081:
00082: void fb_info()
00083: {
00084:     printf("using (fd=%d)/n"
00085:     "id = %s/n"
00086:     "xres = %d px/n"
00087:     "yres = %d px/n"
00088:     "xres_virtual = %d px/n"
00089:     "yres_virtual = %d px/n"
00090:     "bpp = %d/n"
00091:     "r = %2u:%u/n"
00092:     "g = %2u:%u/n"
00093:     "b = %2u:%u/n"
00094:     "smem_start = 0x%lx/n",
00095:     fb1_fd ,
00096:     finfo .id,
00097:     info .xres,
00098:     info .yres,
00099:     info .xres_virtual,
00100:     info .yres_virtual,
00101:     info .bits_per_pixel,
00102:     info .red.offset, info .red.length,
00103:     info .green.offset, info .green.length,
00104:     info .blue.offset, info .blue.length,
00105:     finfo .smem_start
00107:     );
00108:
00109: } ? end fb_info ?
00110:
00111: /*********************************************************
00112: * g2d & fb init & mmap
00113: **********************************************************/
00114: unsigned int g2d_fb_init()
00115: {
00116:     s3c_color_key_info_t ckey;
00117:     s3c_color_val_info_t cvalue;
00118:     // s3c_win_info_t osd; //set for win0,win1, SET_OSD_INFO
00119:
00120:     int rv;
00121:
00122: ////////////////////////////////////////////////////////////////////////////////////
00123:
00124:     g2d_fd = open(S3C_G2D_DEV_NAME, O_RDWR);//open g2d
00125:     if(g2d_fd <0)
00126:     {
00127:         perror("open S3C_G2D_DEV_NAME:");
00128:         return -1;
00129:     }
00130:
00131: #ifdef G2D_CUSTOMED
00132: /*************************************************************
00133: * G2D: color key and alpha
00134: *************************************************************/
00135: // G2D_NO_ALPHA = 0,
00136: // G2D_PLANE_ALPHA,//fixed..
00137: // G2D_PIXEL_ALPHA // with fallback to plane alpha
00138:     rv = ioctl(g2d_fd , S3C_G2D_SET_BLENDING, G2D_PIXEL_ALPHA);//光栅 先于 S3C_G2D_SET_RASTER_OP
00139:     if (rv != 0)
00140:     {
00141:        DBG("S3C_G2D_SET_BLENDING failed rv = %d, %s /n",rv, strerror(errno));
00142:        return -2;
00143:     }
00144:
00145:
00146: //alpha = (ALPHA+1) / 256, blended: ALPHA_REG = 0xf
00147: //win 1 透明度 //max 0xff
00148:     rv = ioctl(g2d_fd , S3C_G2D_SET_ALPHA_VAL, 0xf);
00149:     if (rv != 0)
00150:     {
00151:        DBG("set color key info error rv = %d, %s /n",rv, strerror(errno));
00152:        return rv;
00153:     }
00154:
00155: // #define G2D_ROP_SRC_ONLY (0xf0)
00156: // #define G2D_ROP_3RD_OPRND_ONLY (0xaa) //make the screen black
00157: // #define G2D_ROP_DST_ONLY (0xcc) //nothing.
00158: // #define G2D_ROP_SRC_OR_DST (0xfc) //覆盖 以前的画面
00159: // #define G2D_ROP_SRC_OR_3RD_OPRND (0xfa) // same as G2D_ROP_SRC_ONLY
00160: // #define G2D_ROP_SRC_AND_DST (0xc0) //覆盖 以前的画面,但是更透明
00161: // #define G2D_ROP_SRC_AND_3RD_OPRND (0xa0) //黑屏
00162: // #define G2D_ROP_SRC_XOR_3RD_OPRND (0x5a) // same as G2D_ROP_SRC_ONLY
00163: // #define G2D_ROP_DST_OR_3RD_OPRND (0xee) // nothing ?? same as G2D_ROP_SRC_ONLY ?
00163: ?
00164:
00165: //G2D_ROP_SRC_OR_DST
00166: //G2D_ROP_SRC_AND_DST
00167:
00168:     rv = ioctl(g2d_fd , S3C_G2D_SET_RASTER_OP, G2D_ROP_SRC_ONLY);//rop
00169:     if (rv != 0)
00170:     {
00171:        DBG("S3C_G2D_SET_RASTER_OP failed rv = %d, %s /n",rv, strerror(errno));
00172:        return -2;
00173:     }
00174:     #ifdef G2D_SET_TRANSFORM_90
00175:     rv = ioctl(g2d_fd , S3C_G2D_SET_TRANSFORM, G2D_ROT_90);
00176:     if (rv != 0)
00177:     {
00178:        DBG("g2d TRANSFORM error rv = %d, %s /n",rv, strerror(errno));
00179:        return -1;
00180:     }
00181: #endif //G2D_SET_TRANSFORM_90
00182:
00183: #endif //G2D_CUSTOMED
00184:
00185: ////////////////////////////////////////////////////////////////////////////////////
00186:
00187:
00188: #ifdef FB0_OPERATION
00189: /*************************************************
00190: * fb0 info
00191: *************************************************/
00192:     fb0_fd = open(S3C_FB0_DEV_NAME, O_RDWR);//open fb0
00193:     if(fb0_fd <0)
00194:     {
00195:        DBG("open framebuffer device %s /n", strerror(errno));
00196:        return -1;
00197:     }
00198: #endif //FB0_OPERATION
00199:
00200: ////////////////////////////////////////////////////////////////////////////////////
00201:
00202: /*************************************************
00203: * fb1 info
00204: *************************************************/
00205:     fb1_fd = open(S3C_FB1_DEV_NAME, O_RDWR);//open fb1
00206:     if(fb1_fd <0)
00207:     {
00208:         DBG("open framebuffer device %s /n", strerror(errno));
00209:         return -1;
00210:     }
00211:     rv = ioctl(fb1_fd , FBIOGET_FSCREENINFO, &finfo );
00212:     if (rv != 0)
00213:     {
00214:         DBG("%s get fix info error rv = %d, %s /n",__FUNCTION__,rv, strerror(errno));
00215:         return -1;
00216:     }
00217:     rv = ioctl(fb1_fd , FBIOGET_VSCREENINFO, &info );
00218:     if (rv != 0)
00219:     {
00220:         DBG("get var info error rv = %d, %s /n",rv, strerror(errno));
00221:         return -1;
00222:     }
00223:
00224: #ifdef FB1_CUSTOMED
00225: /*************************************************
00226: * OSD for fb1
00227: *************************************************/
00228:
00229:     rv = ioctl(fb1_fd , SET_OSD_START);
00230:     if (rv != 0)
00231:     {
00232:         DBG("set OSD Start error rv = %d, %s /n",rv, strerror(errno));
00233:         return rv;
00234:     }
00235:
00236:
00237: /***********************************************************
00238: * configure the color key to black and bg display
00239: ************************************************************/
00240:
00241: /**
00242: * set the blending mode and alpha1_R/G/B
00243: */
00244:     //0 Plane Blending & 1 Pixel Blending & chroma(color) key
00245:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA_MODE, 1);//Pixel Blending & chroma(color) key
00246:     if (rv != 0)
00247:     {
00248:         DBG("set color alpha mode error rv = %d, %s /n",rv, strerror(errno));
00249:         return rv;
00250:     }
00251:
00252:     //color for win 1
00253:     cvalue.colval_red = 0;
00254:     cvalue.colval_green = 0;
00255:     cvalue.colval_blue = 0;
00256:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA0_VALUE, &cvalue);
00256:     //Pixel Blending & chroma(color) key
00257:     if (rv != 0)
00258:     {
00259:        DBG("set color alpha mode error rv = %d, %s /n",rv, strerror(errno));
00260:        return rv;
00261:     }
00262:
00263:     //color for win 0
00264:     cvalue.colval_red = 0xf;
00265:     cvalue.colval_green = 0xf;
00266:     cvalue.colval_blue = 0xf;
00267:     rv = ioctl(fb1_fd , SET_COLOR_ALPHA1_VALUE, &cvalue);
00267:     //Pixel Blending & chroma(color) key
00268:     if (rv != 0)
00269:     {
00270:         DBG("set color alpha mode error rv = %d, %s /n",rv, strerror(errno));
00271:         return rv;
00272:     }
00273:
00274:     // direction = 0 means win1 is breen compared with color value
00275:     ckey.direction = COLOR_KEY_DIR_FG_DISPLAY;
00275:     //COLOR_KEY_DIR_BG_DISPLAY COLOR_KEY_DIR_FG_DISPLAY
00276:     //each bit is set to 0 means that each bit in colval is been compared
00277:     ckey.compkey_red = 0;
00278:     ckey.compkey_green = 0;
00279:     ckey.compkey_blue = 0;
00280:     //set color key info to be compared in color value
00281:     rv = ioctl(fb1_fd , SET_COLOR_KEY_INFO, &ckey);
00282:     if (rv != 0)
00283:     {
00284:        DBG("set color key info error rv = %d, %s /n",rv, strerror(errno));
00285:        return rv;
00286:     }
00287:
00288:     cvalue.colval_red = 0;
00289:     cvalue.colval_green = 0;
00290:     cvalue.colval_blue = 0;
00291:     //set color value
00292:     rv = ioctl(fb1_fd , SET_COLOR_KEY_COLVAL, &cvalue);
00293:     if (rv != 0)
00294:     {
00295:         DBG("set color key value error rv = %d, %s /n",rv, strerror(errno));
00296:         return rv;
00297:     }
00298:
00299:
00300:     //没用?????????????????????????????????????????????//
00301:     //start color key KEYEN_F[25] Color Key Chroma Key( 浓度 色度 ) Enable control
00302:     rv = ioctl(fb1_fd , SET_COLOR_KEY_START);
00303:     if (rv != 0)
00304:     {
00305:         DBG("set color key value error rv = %d, %s /n",rv, strerror(errno));
00306:         return rv;
00307:     }
00308:
00309:
00310:     //start alpha of color key KEYBLEN D [26]=1:alpha value selected by
00311:     // non-key area: alpha0_r/g/b
00312:     // key area : alpha1_r/g/b
00313:     rv = ioctl(fb1_fd , SET_COLOR_KEY_ALPHA_START);
00314:     if (rv != 0)
00315:     {
00316:     DBG("set color key value error rv = %d, %s /n",rv, strerror(errno));
00317:     return rv;
00318:     }
00319:
00320:     #endif //FB1_CUSTOMED
00321:
00322:     return 0;
00323: } ? end g2d_fb_init ?
00324:
00325:
00326: /*********************************************
00327: * g2d implement
00328: **********************************************/
00329: int s3c_g2d_copy_buffer(struct s3c_g2d_req * req, unsigned long buffer_base, unsigned
00329: long fb_base/*,
00330: int x, int y, int w, int h*/)
00331: {
00332:     int rv;
00333:     memset(req, 0, sizeof(struct s3c_g2d_req));
00334:
00335:
00336:     req->src.w = SOURCE_WIDTH;
00337:     req->src.h = SOURCE_HEIGHT;
00338:     req->src.offs = 0;
00339:     req->src.base = buffer_base;
00340:     req->src.fmt = SOURCE_FMT;
00341:
00342:     req->src.l = 0;
00343:     req->src.t = 0;
00344:     req->src.r = req->src.w;
00345:     req->src.b = req->src.h;
00346:
00347:     req->dst.w = DEST_WIDTH;
00348:     req->dst.h = DEST_HEIGHT;
00349:     req->dst.offs = 0;
00350:     req->dst.base = fb_base;
00351:     req->dst.fmt = DST_FMT;
00352:
00353:     req->dst.l = DST_LEFT_X;
00354:     req->dst.t = DST_TOP_Y;
00355:
00356:     req->dst.r = DST_RIGHT_X;
00357:     req->dst.b = DST_DOWN_Y;
00358:
00359:     rv = ioctl(g2d_fd , S3C_G2D_BITBLT, req);
00360:     if (rv != 0)
00361:     {
00362:         DBG("S3C_G2D_BITBLT failed = %d", -errno);
00363:         return -2;
00364:     }
00365:     // DBG("src base:0xx%u dst:base:0x%x/n",req->src.base,req->dst.base);
00366:     return 0;
00367: } ? end s3c_g2d_copy_buffer ?
00368:
00369: int main(int argc, char *argv[])
00370: {
00371:     u32 fb_phy;
00372:     struct s3c_g2d_req params;
00373:     int file_len,frame=0,rv,image_fd,times = 10;
00374:
00375:     struct timeval start,end;
00376:     double timeuse;
00377:     void * pmem_base /*, *fb_mem_map */;
00378:     char * file_name = YUV_FILE;
00379:
00380:     if(argc >= 2)
00381:     {
00382:         file_name = argv[1];
00383:         if(argc >= 3)
00384:         times = atoi(argv[2]);
00385:        DBG("Request Play times %d /n",times);
00386:     }
00387:
00388: /* get framebuffer phyaddr */
00389:     if(g2d_fb_init() != 0)
00390:        return -3;
00391:     fb_phy = finfo .smem_start;
00392:
00393: /* get pmem source addr */
00394:     pmem_base = mmap(NULL, G2D_SFR_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, g2d_fd , 0);
00395:     if(pmem_base == MAP_FAILED)
00396:     {
00397:        perror("mmap");
00398:        return -1;
00399:     }
00400:     memset(pmem_base,0, G2D_SFR_SIZE);
00401:
00402:     DBG("pmem_base = %p/n",pmem_base);
00403:
00404:
00405:     /* get image file */
00406:     rv = open_file_image(file_name,&image_fd,&file_len);
00407:     if(rv < 0)
00408:     {
00409:         return rv;
00410:     }
00411:
00412:     DBG("File[%s], size[%d], Frame[%d]/n",file_name,file_len,file_len/G2D_SFR_SIZE);
00413:
00414:     sleep(1);
00415:
00416:
00417:     gettimeofday(&start, NULL);
00418:     while(1)
00419:     {
00420:     /* Start: read the content of the image file to the mem */
00421:         rv = read(image_fd,pmem_base,G2D_SFR_SIZE);
00422:         if(rv > 0)
00423:         {
00424:
00425:             rv = s3c_g2d_copy_buffer(&params, (unsigned long)pmem_base, fb_phy);
00426:             if(rv)
00427:            break;
00428:        }
00429:        else
00430:         {
00431:            if(--times <= 0)
00432:            break;
00433:            lseek(image_fd,0,SEEK_SET);//seek to begin
00434:        }
00435:         frame++;
00436:     // DBG("times=%d, frame=%d/n",times,frame);
00437:     usleep(50000);
00438:     } ? end while 1 ?
00439:     gettimeofday(&end, NULL);
00440:     timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
00441:     timeuse/=1000;
00442:
00443:     DBG("Total Frame[%d], Total Time[%2.1f] ms,Time Pre Frame[%2.1f] ms/n",frame,timeuse,timeuse/frame);
00444:
00445:
00446:     //fb_info();
00447:
00448:     // printHex(file_name, pmem_base,128);
00449:     close(image_fd);
00450:     munmap(pmem_base,G2D_SFR_SIZE);
00451:
00452:
00453:     close(g2d_fd );
00454:     #ifdef FB0_OPERATION
00455:     close(fb0_fd );
00456:     #endif
00457:     close(fb1_fd );
00458:     return 0;
00459:} ? end main ?
00460:
 
最终测试的效果,当然要 上传一张啦。。
 
 
 
横着的条纹是win0, 竖着的条文是win1,COLVAL是黑色
 
win0是显示整屏幕,win1只有1/2屏幕,也可想成是win0旋转+缩放后得到的。
 
 
参考网站:
http://lxr.post-tech.com/source/drivers/media/video/samsung/g2d/?v=linux-2.6.29-eclair
http://apps.hi.baidu.com/share/detail/17513887
http://blogold.chinaunix.net/u3/111323/showart_2200014.html
http://apps.hi.baidu.com/share/detail/17513859
 
下面是常见问题的总结:
 
 
19:43:35
请问你的测试代码里面 SOURCE_FMT 与 DST_FMT 颜色模式 是什么?
19:43:45
6410手册里面讲的太不清楚,有几个寄存器的设置他就没讲清楚甚至没讲!
    1、DST_BASE_ADDR和SRC_BASE_ADDR要设置物理地址。不能是内核的虚拟地址或者应用程序中的地址。对于FB,要使用 dma_alloc_writecombine 第三个参数返回的物理地址 fbi->fix.smem_start。
19:56:26
怎么要设置成物理地址啊?
19:56:56
目的地址是framebuff 地址 而源地址怎么设置啊?
典当七秒的魚 08:55:36
是 颜色模式。
DST_FMT 是你驱动里使用的格式。像rgb565等。
 SOURCE_FMT 是你要显示的(在内存里)image的格式。
至于硬件支持哪几种 可转换的,你要看看数据手册了。
典当七秒的魚 08:57:37
硬件能处理的只有物理地址吧。我想。
因为你写进去的到下面寄存器的
DST_BASE_ADDR和SRC_BASE_ADDR
只能是物理 地址吧。。。这个地址是硬件能去访问的。
硬件的搬运负责吧原地址SRC_BASE_ADDR的数据 经过6步转换后,显示在DST_BASE_ADDR里面。
典当七秒的魚 08:58:45
我想着就是为何要用物理地址的原因。
你能找到 这个说明真的相当不错了
我当时可是在这里郁闷了好几天。。
因为 一直将虚拟地址写到 源地址。。
操作完成后一直黑屏 。。
09:09:59
就是这个帖子啊
http://blog.chinaunix.net/u3/111323/showart_2200014.html
09:10:24
那src_base 物理地址是怎么确定的呢?
典当七秒的魚 09:15:54
我是这样做的
在初始化的时候就分配好可用的,共享的内存。和显存差不多大, 主要用于 应用层 放src Image
驱动记录这个地址,并将其转换得到物理地址,用于src_base(其实,应用层会再次将此地址对应的虚拟地址写入,而驱动层将会舍弃此地址,因为是虚拟地址嘛),将虚拟地址传给应用层,应用层使用这个地址将src image写到这里地址(应用层能操作的就只能是虚拟地址,并且和内核层的不同。),因此对应的物理地址 的内容也相应的被应用填充了。
09:17:21
完全明白了 非常感谢
09:18:17
注:因为不知道如何将用户空间的虚拟地址转换为物理地址,只好在内核里面alloc了一块buffer s3c_g2d_userFB,每次都要用copy_from_user把图片先拷贝到s3c_g2d_userFB,再由2D搬到屏幕。
大概测试过一下,一张800*600的图片 copy_from_user 用了大概 4ms。2D搬到屏幕上用了大概5~6ms。还是想把copy_from_user给剩了!
09:18:39
这是刚才那个帖子里面提到的 方法估计和你一样的
典当七秒的魚 09:18:46
一样
典当七秒的魚 09:19:12
每次都要用copy_from_user把图片先拷贝到s3c_g2d_userFB 这个不用 。
 
~BOBO 09:27:22
昨晚我也尝试把mmap 返回的虚拟地址在内核空间转换成物理地址也是不行我想说的是在内核空间分配的buff(虚拟地址)与 mmap 映射返回到用户空间的虚拟地址有何不同如果相同的话昨晚的尝试就应该是成功的谢谢
典当七秒的魚 09:31:40
参与讨论
登录后参与讨论
当你觉得为时已晚的时候,恰恰是最早的时候!
推荐文章
最近访客