📄 qscreenlinuxfb_qws.cpp
字号:
malloc(sizeof(unsigned short int)*screencols); startcmap.green=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); startcmap.blue=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); startcmap.transp=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) { perror("QLinuxFbScreen::connect"); qWarning("Error reading palette from framebuffer, using default palette"); createPalette(startcmap, vinfo, finfo); } int bits_used = 0; for(loopc=0;loopc<screencols;loopc++) { screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8, startcmap.green[loopc] >> 8, startcmap.blue[loopc] >> 8); bits_used |= startcmap.red[loopc] | startcmap.green[loopc] | startcmap.blue[loopc]; } // WORKAROUND: Some framebuffer drivers only return 8 bit // color values, so we need to not bit shift them.. if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) { for(loopc=0;loopc<screencols;loopc++) { screenclut[loopc] = qRgb(startcmap.red[loopc], startcmap.green[loopc], startcmap.blue[loopc]); } qWarning("8 bits cmap returned due to faulty FB driver, colors corrected"); } free(startcmap.red); free(startcmap.green); free(startcmap.blue); free(startcmap.transp); } else { screencols=0; } return true;}/*! \reimp This unmaps the framebuffer. \sa connect()*/void QLinuxFbScreen::disconnect(){ data -= dataoffset; if (data) munmap((char*)data,mapsize); close(d_ptr->fd);}// #define DEBUG_VINFOvoid QLinuxFbScreen::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo){ if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; cmap.start=0; cmap.len=screencols; cmap.red=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); cmap.green=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); cmap.blue=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); cmap.transp=(unsigned short int *) malloc(sizeof(unsigned short int)*screencols); if (screencols==16) { if (finfo.type == FB_TYPE_PACKED_PIXELS) { // We'll setup a grayscale cmap for 4bpp linear int val = 0; for (int idx = 0; idx < 16; ++idx, val += 17) { cmap.red[idx] = (val<<8)|val; cmap.green[idx] = (val<<8)|val; cmap.blue[idx] = (val<<8)|val; screenclut[idx]=qRgb(val, val, val); } } else { // Default 16 colour palette // Green is now trolltech green so certain images look nicer // black d_gray l_gray white red green blue cyan magenta yellow unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 }; unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F }; unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 }; for (int idx = 0; idx < 16; ++idx) { cmap.red[idx] = ((reds[idx]) << 8)|reds[idx]; cmap.green[idx] = ((greens[idx]) << 8)|greens[idx]; cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx]; cmap.transp[idx] = 0; screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]); } } } else { if (grayscale) { // Build grayscale palette int i; for(i=0;i<screencols;++i) { int bval = screencols == 256 ? i : (i << 4); ushort val = (bval << 8) | bval; cmap.red[i] = val; cmap.green[i] = val; cmap.blue[i] = val; cmap.transp[i] = 0; screenclut[i] = qRgb(bval,bval,bval); } } else { // 6x6x6 216 color cube int idx = 0; for(int ir = 0x0; ir <= 0xff; ir+=0x33) { for(int ig = 0x0; ig <= 0xff; ig+=0x33) { for(int ib = 0x0; ib <= 0xff; ib+=0x33) { cmap.red[idx] = (ir << 8)|ir; cmap.green[idx] = (ig << 8)|ig; cmap.blue[idx] = (ib << 8)|ib; cmap.transp[idx] = 0; screenclut[idx]=qRgb(ir, ig, ib); ++idx; } } } // Fill in rest with 0 for (int loopc=0; loopc<40; ++loopc) { screenclut[idx]=0; ++idx; } screencols=idx; } } } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) { cmap.start=0; int rbits=0,gbits=0,bbits=0; switch (vinfo.bits_per_pixel) { case 8: rbits=vinfo.red.length; gbits=vinfo.green.length; 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 18: case 19: rbits=6; gbits=6; bbits=6; break; case 24: case 32: rbits=gbits=bbits=8; break; } screencols=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; } }}/*! \reimp This is called by the \l {Qtopia Core} server at startup time. It turns off console blinking, sets up the color palette, enables write combining on the framebuffer and initialises the off-screen memory manager.*/bool QLinuxFbScreen::initDevice(){ d_ptr->openTty(); // Grab current mode so we can reset it fb_var_screeninfo vinfo; fb_fix_screeninfo finfo; //####################### // Shut up Valgrind memset(&vinfo, 0, sizeof(vinfo)); memset(&finfo, 0, sizeof(finfo)); //####################### if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { perror("QLinuxFbScreen::initDevice"); qFatal("Error reading variable information in card init"); return false; }#ifdef DEBUG_VINFO qDebug("Greyscale %d",vinfo.grayscale); qDebug("Nonstd %d",vinfo.nonstd); qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length, vinfo.red.msb_right); qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length, vinfo.green.msb_right); qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length, vinfo.blue.msb_right); qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length, vinfo.transp.msb_right);#endif d_ptr->startupw=vinfo.xres; d_ptr->startuph=vinfo.yres; d_ptr->startupd=vinfo.bits_per_pixel; grayscale = vinfo.grayscale; if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { perror("QLinuxFbScreen::initDevice"); qCritical("Error reading fixed information in card init"); // It's not an /error/ as such, though definitely a bad sign // so we return true return true; }#ifdef __i386__ // Now init mtrr if(!::getenv("QWS_NOMTRR")) { int mfd=open("/proc/mtrr",O_WRONLY,0); // MTRR entry goes away when file is closed - i.e. // hopefully when QWS is killed if(mfd != -1) { mtrr_sentry sentry; sentry.base=(unsigned long int)finfo.smem_start; //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start); // Size needs to be in 4k chunks, but that's not always // what we get thanks to graphics card registers. Write combining // these is Not Good, so we write combine what we can // (which is not much - 4 megs on an 8 meg card, it seems) unsigned int size=finfo.smem_len; size=size >> 22; size=size << 22; sentry.size=size; sentry.type=MTRR_TYPE_WRCOMB; if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) { //printf("Couldn't add mtrr entry for %lx %lx, %s\n", //sentry.base,sentry.size,strerror(errno)); } } }#endif if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR)) { fb_cmap cmap; createPalette(cmap, vinfo, finfo); if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) { perror("QLinuxFbScreen::initDevice"); qWarning("Error writing palette to framebuffer"); } free(cmap.red); free(cmap.green); free(cmap.blue); free(cmap.transp); } canaccel=useOffscreen(); if(mapsize-size<16384) { canaccel=false; } if(canaccel) { setupOffScreen(); *entryp=0; *lowest=mapsize; insert_entry(*entryp,*lowest,*lowest); // dummy entry to mark start } shared->fifocount=0; shared->buffer_offset=0xffffffff; // 0 would be a sensible offset (screen) shared->linestep=0; shared->cliptop=0xffffffff; shared->clipleft=0xffffffff; shared->clipright=0xffffffff; shared->clipbottom=0xffffffff; shared->rop=0xffffffff;#ifdef QT_QWS_DEPTH_GENERIC if (pixelFormat() == QImage::Format_Invalid && screencols == 0 && d_ptr->doGenericColors) { qt_set_generic_blit(this, vinfo.bits_per_pixel, vinfo.red.length, vinfo.green.length, vinfo.blue.length, vinfo.transp.length, vinfo.red.offset, vinfo.green.offset, vinfo.blue.offset, vinfo.transp.offset); }#endif#ifndef QT_NO_QWS_CURSOR QScreenCursor::initSoftwareCursor();#endif 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; }#ifdef DEBUG_CACHE qDebug("Remove entry: %d", pos);#endif QPoolEntry *qpe = &entries[pos]; if (qpe->start <= *lowest) { // Lowest goes up again *lowest = entries[pos-1].start;#ifdef DEBUG_CACHE qDebug(" moved lowest to %d", *lowest);#endif } (*entryp)--; if (pos == *entryp) return; int size = (*entryp)-pos; 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; }#ifdef DEBUG_CACHE qDebug("Insert entry: %d, %d -> %d", pos, start, end);#endif if (start < (int)*lowest) { *lowest = start;#ifdef DEBUG_CACHE qDebug(" moved lowest to %d", *lowest);#endif } if (pos==*entryp) { entries[pos].start=start; entries[pos].end=end; entries[pos].clientId=qws_client_id; (*entryp)++; return; } int size=(*entryp)-pos; memmove(&entries[pos+1],&entries[pos],size*sizeof(QPoolEntry)); entries[pos].start=start; entries[pos].end=end; entries[pos].clientId=qws_client_id; (*entryp)++;}/*! \fn uchar * QLinuxFbScreen::cache(int amount) Requests the specified \a amount of offscreen graphics card memory from the memory manager, and returns a pointer to the data within the framebuffer (or 0 if there is no free memory). Note that the display is locked while memory is allocated in order to preserve the memory pool's integrity. Use the QScreen::onCard() function to retrieve an offset (in bytes) from the start of graphics card memory for the returned pointer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -