📄 qgfxlinuxfb_qws.cpp
字号:
bbits=vinfo.blue.length; if(rbits==0 && gbits==0 && bbits==0) { // cyber2000 driver bug hack rbits=3; gbits=3; bbits=2; } break; case 15: rbits=5; gbits=5; bbits=5; break; case 16: rbits=5; gbits=6; bbits=5; break; case 24: case 32: rbits=gbits=bbits=8; break; } cmap.len=1<<QMAX(rbits,QMAX(gbits,bbits)); cmap.red=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.green=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.blue=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.transp=(unsigned short int *) malloc(sizeof(unsigned short int)*256); for( unsigned int i = 0x0; i < cmap.len; i++ ) { cmap.red[i] = i*65535/((1<<rbits)-1); cmap.green[i] = i*65535/((1<<gbits)-1); cmap.blue[i] = i*65535/((1<<bbits)-1); cmap.transp[i] = 0; } ioctl(fd,FBIOPUTCMAP,&cmap); free(cmap.red); free(cmap.green); free(cmap.blue); free(cmap.transp); } canaccel=useOffscreen(); if(mapsize-size<16384) { canaccel=false; } if(canaccel) { // Figure out position of offscreen memory // Set up pool entries pointer table and 64-bit align it unsigned int pos=(unsigned int)data; int psize; psize=size; psize+=4096; psize+=8; psize&=~0x7; pos+=psize; entryp=((int *)pos); lowest=((unsigned int *)pos)+1; // These keep track of accelerator state optype=((int *)pos)+2; lastop=((int *)pos)+3; pos+=(sizeof(int))*4; entries=(QPoolEntry *)pos; *entryp=0; *lowest=mapsize; } else { optype = &dummy_optype; lastop = &dummy_lastop; } *optype=0; *lastop=0; initted=true; return true;}/* The offscreen memory manager's list of entries is stored at the bottom of the offscreen memory area and consistes of a series of QPoolEntry's, each of which keep track of a block of allocated memory. Unallocated memory is implicitly indicated by the gap between blocks indicated by QPoolEntry's. The memory manager looks through any unallocated memory before the end of currently-allocated memory to see if a new block will fit in the gap; if it doesn't it allocated it from the end of currently-allocated memory. Memory is allocated from the top of the framebuffer downwards; if it hits the list of entries then offscreen memory is full and further allocations are made from main RAM (and hence unaccelerated). Allocated memory can be seen as a sort of upside-down stack; lowest keeps track of the bottom of the stack.*/void QLinuxFbScreen::delete_entry(int pos){ if(pos>*entryp || pos<0) { qDebug("Attempt to delete odd pos! %d %d",pos,*entryp); return; } QPoolEntry * qpe=&entries[pos]; if(qpe->start<=*lowest && pos>0) { // Lowest goes up again *lowest=(entries[pos-1].start); } (*entryp)--; if(pos==*entryp) { return; } int size=(*entryp)-pos; size++; memmove(&entries[pos],&entries[pos+1],size*sizeof(QPoolEntry));}void QLinuxFbScreen::insert_entry(int pos,int start,int end){ if(pos>*entryp) { qDebug("Attempt to insert odd pos! %d %d",pos,*entryp); return; } if(pos==*entryp) { entries[pos].start=start; entries[pos].end=end; (*entryp)++; return; } (*entryp)++; int size=(*entryp)-pos; size++; memmove(&entries[pos+1],&entries[pos],size*sizeof(QPoolEntry)); entries[pos].start=start; entries[pos].end=end;}/*! Requests a block of offscreen graphics card memory from the memory manager; it will be aligned at pixmapOffsetAlignment(). If no memory is free 0 will be returned, otherwise a pointer to the data within the framebuffer. QScreen::onCard can be used to retrieve a byte offset from the start of graphics card memory from this pointer. The display is locked while memory is allocated and unallocated in order to preserve the memory pool's integrity, so cache and uncache should not be called if the screen is locked. \amount is the amount of memory to allocate, \a optim gives the optimization level (same values as QPixmap::Optimization).*/uchar * QLinuxFbScreen::cache(int amount, int optim){ if(!canaccel || entryp==0 || optim == int(QPixmap::NoOptim) ) { return 0; } qt_fbdpy->grab(); int align=pixmapOffsetAlignment(); int hold=(*entryp-1); for(int loopc=0;loopc<hold;loopc++) { int freestart=entries[loopc+1].end; int freeend=entries[loopc].start; if(freestart!=freeend) { while(freestart % align) { freestart++; } int len=freeend-freestart; if(len>amount) { insert_entry(loopc+1,freestart,freestart+amount); if(freestart % align) { qDebug("Wah, freed-block return unaligned %x",freestart); } qt_fbdpy->ungrab(); return data+freestart; } } } // No free blocks in already-taken memory; get some more // if we can int stackend=(*entryp)*sizeof(QPoolEntry); int startp=size+(sizeof(int)*2)+stackend; int newlowest=(*lowest)-amount; if(newlowest % align) { newlowest-=align; while(newlowest % align) { newlowest++; } } if(startp>=newlowest) { //qDebug("No more memory, %d %d %d %d",startp,stackend, //*lowest,amount); //canaccel=false; qt_fbdpy->ungrab(); return 0; } insert_entry(*entryp,newlowest,*lowest); *lowest=newlowest; if(newlowest % align) { //qDebug("Wah, new return is unaligned %x",newlowest); } qt_fbdpy->ungrab(); return data+newlowest;}/*!\fn void QLinuxFbScreen::uncache(uchar * c)Delete a block of memory allocated from graphics card memory.*/void QLinuxFbScreen::uncache(uchar * c){ qt_fbdpy->grab(); unsigned long pos=(unsigned long)c; pos-=((unsigned long)data); unsigned int hold=(*entryp); for(unsigned int loopc=0;loopc<hold;loopc++) { if(entries[loopc].start==pos) { delete_entry(loopc); qt_fbdpy->ungrab(); return; } } qt_fbdpy->ungrab(); qDebug("Attempt to delete unknown offset %ld",pos);}/*!\fn void QLinuxFbScreen::shutdownDevice()This is called by the Qt/Embedded server when it shuts down, and shouldbe inherited if you need to do any card-specific shutting down.The default version hides the screen cursor and reenables the blinking cursorand screen blanking.*/void QLinuxFbScreen::shutdownDevice(){ // Set back the original mode#ifndef QT_NO_QWS_CURSOR qt_screencursor->hide();#endif // Causing crashes. Not needed. //setMode(startupw,startuph,startupd);/* if ( startupd == 8 ) { ioctl(fd,FBIOPUTCMAP,startcmap); free(startcmap->red); free(startcmap->green); free(startcmap->blue); free(startcmap->transp); delete startcmap; startcmap = 0; }*/ // Blankin' screen, blinkin' cursor! const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; writeTerm(termctl,sizeof(termctl));}/*!\fn void QLinuxFbScreen::set(unsigned int i,unsigned int r,unsigned int g,unsigned int b)In paletted graphics modes, this sets color index i to the specified RGBvalue.*/void QLinuxFbScreen::set(unsigned int i,unsigned int r,unsigned int g,unsigned int b){ fb_cmap cmap; cmap.start=i; cmap.len=1; cmap.red=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.green=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.blue=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.transp=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.red[0]=r << 8; cmap.green[0]=g << 8; cmap.blue[0]=b << 8; cmap.transp[0]=0; ioctl(fd,FBIOPUTCMAP,&cmap); free(cmap.red); free(cmap.green); free(cmap.blue); free(cmap.transp); screenclut[i] = qRgb( r, g, b );}/*!\fn void QLinuxFbScreen::setMode(int nw,int nh,int nd)Sets the framebuffer to a new resolution and bit depth. After doing thisany currently-existing gfx's will be invalid and the screen should becompletely redrawn. In a multiple-process Embedded Qt situation you willneed to signal all other applications to also setMode() to the same modeand redraw.*/void QLinuxFbScreen::setMode(int nw,int nh,int nd){ fb_fix_screeninfo finfo; fb_var_screeninfo vinfo; if (ioctl(fd, FBIOGET_FSCREENINFO, &finfo)) { perror("reading /dev/fb0"); qFatal("Error reading fixed information"); } if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) { qFatal("Error reading variable information in mode change"); } vinfo.xres=nw; vinfo.yres=nh; vinfo.bits_per_pixel=nd; if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo)) { qFatal("Error writing variable information in mode change"); } if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo)) { qFatal("Error reading changed variable information in mode change"); } w=vinfo.xres; h=vinfo.yres; d=vinfo.bits_per_pixel; lstep=finfo.line_length; size=h*lstep;}// save the state of the graphics card// This is needed so that e.g. we can restore the palette when switching// between linux virtual consoles./*!\fn void QLinuxFbScreen::save()This doesn't do anything; accelerated drivers may wish to reimplementit to save graphics cards registers. It's called by the Qt/Embedded serverwhen the virtual console is switched.*/void QLinuxFbScreen::save(){ // nothing to do.}/*!\fn void QLinuxFbScreen::restore()This is called when the virtual console is switched back to Qt/Embeddedand restores the palette.*/// restore the state of the graphics card.void QLinuxFbScreen::restore(){ if (( d == 8 ) || ( d == 4 )) { fb_cmap cmap; cmap.start=0; cmap.len=screencols; cmap.red=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.green=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.blue=(unsigned short int *) malloc(sizeof(unsigned short int)*256); cmap.transp=(unsigned short int *) malloc(sizeof(unsigned short int)*256); for ( int loopc = 0; loopc < screencols; loopc++ ) { cmap.red[loopc] = qRed( screenclut[loopc] ) << 8; cmap.green[loopc] = qGreen( screenclut[loopc] ) << 8; cmap.blue[loopc] = qBlue( screenclut[loopc] ) << 8; cmap.transp[loopc] = 0; } ioctl(fd,FBIOPUTCMAP,&cmap); free(cmap.red); free(cmap.green); free(cmap.blue); free(cmap.transp); }}void QLinuxFbScreen::blank(bool on){#if defined(QT_QWS_IPAQ) if ( on ) system("apm -suspend");#else// Some old kernel versions don't have this. These defines should go// away eventually#if defined(FBIOBLANK)#if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING) ioctl(fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING);#else ioctl(fd, FBIOBLANK, on ? 1 : 0);#endif#endif#endif}extern "C" QScreen * qt_get_screen_linuxfb(int display_id){ return new QLinuxFbScreen( display_id );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -