Thread: [Okvm-cvs] okvm/server V4LDesktop.cpp,1.4,1.5 V4LDesktop.h,1.3,1.4
Status: Pre-Alpha
Brought to you by:
david-m
|
From: David M. <da...@us...> - 2006-05-28 12:09:31
|
Update of /cvsroot/okvm/okvm/server In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv31717/server Modified Files: V4LDesktop.cpp V4LDesktop.h Log Message: The goal is to have some number of controlled devices, and have the screen split into an appropriately sized table and display a miniturised version of them all. If they are being controlled by the OKVM card, then it would cycle through, updating each for 5 seconds then moving on to the next. This patch is after some optimisations, dropping it to ~10%CPU for 7.8 fps. I have a fourth patch close which improves performance to 8 fps at ~8% CPU. With the montage patches, you start off in full screen mode, showing only 1 of 4 screens. Left clicking takes you to the montage. Right clicking takes you to the montage and starts cycling through the 4 screens. When in montage mode, left clicking a screen only updates that screen. Right clicking starts the cycle. Double clicking on a screen takes you to full screen mode again. The + and - keys add or remove screens. Scott Burns <sb...@ii...> Index: V4LDesktop.h =================================================================== RCS file: /cvsroot/okvm/okvm/server/V4LDesktop.h,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** V4LDesktop.h 24 May 2006 06:57:07 -0000 1.3 --- V4LDesktop.h 28 May 2006 12:09:26 -0000 1.4 *************** *** 45,48 **** --- 45,50 ---- virtual void lookup(int index, int* r, int* g, int* b); virtual void poll(); + void montageImage( void * dest, void * src, int sector ); + void copyPixelFragment( unsigned char * dest, int dbpp, unsigned char * src, int sbpp, int strength ); protected: *************** *** 55,62 **** private: int fd; ! int width; ! int height; ! int palette; ! void* framebuffer; }; --- 57,85 ---- private: int fd; ! ! // The following are used for the video source ! int width; ! int height; ! int palette; ! int depth; ! void * framebuffer; ! ! // The following are the equivalents for the montage bugger ! int mwidth; ! int mheight; ! int mpalette; ! int mdepth; ! void * mbuffer; ! ! int buttons; ! struct timeval buttonTime; ! int element; ! int frames; ! ! enum { ! FULL_SCREEN, ! MONTAGE_SINGLE, ! MONTAGE_SCAN, ! } montageMode; }; Index: V4LDesktop.cpp =================================================================== RCS file: /cvsroot/okvm/okvm/server/V4LDesktop.cpp,v retrieving revision 1.4 retrieving revision 1.5 diff -C2 -d -r1.4 -r1.5 *** V4LDesktop.cpp 28 May 2006 11:53:07 -0000 1.4 --- V4LDesktop.cpp 28 May 2006 12:09:26 -0000 1.5 *************** *** 27,30 **** --- 27,31 ---- #include <errno.h> #include <unistd.h> + #include <math.h> #include <string> *************** *** 127,138 **** --- 128,142 ---- // 16bpp, rgb565 pf = PixelFormat(16, 16, false, true, 31, 63, 31, 11, 5, 0); + depth = 2; break; case VIDEO_PALETTE_RGB24: // 24bpp, RGB24 pf = PixelFormat(24, 24, false, true, 255, 255, 255, 0, 8, 16); + depth = 3; break; case VIDEO_PALETTE_RGB32: // 32bpp, ARGB24 pf = PixelFormat(32, 24, false, true, 255, 255, 255, 0, 8, 16); + depth = 4; break; } *************** *** 140,143 **** --- 144,165 ---- (rdr::U8 *) framebuffer, 0); + buttons = 0; + buttonTime.tv_sec = 0; + buttonTime.tv_usec = 0; + element = 0; + frames = 4; + montageMode = FULL_SCREEN; + + mdepth = 3; + mwidth = 400; + mheight = 300; + mpalette = VIDEO_PALETTE_RGB24; + + mbuffer = malloc( mdepth * mwidth * mheight ); + if( mbuffer == NULL ) { + throw rdr::SystemException("Failed to allocate montage buffer", + errno); + } + memset( mbuffer, 0xff, mdepth * mwidth * mheight ); } *************** *** 159,163 **** { server = s; ! server->setPixelBuffer(pb); } --- 181,195 ---- { server = s; ! if( montageMode == FULL_SCREEN ) { ! delete pb; ! pb = new FullFramePixelBuffer(pf, width, height, ! (rdr::U8 *) framebuffer, 0); ! server->setPixelBuffer(pb); ! } else { ! delete pb; ! pb = new FullFramePixelBuffer(pf, mwidth, mheight, ! (rdr::U8 *) mbuffer, 0); ! server->setPixelBuffer(pb); ! } } *************** *** 166,174 **** --- 198,294 ---- V4LDesktop::pointerEvent(const Point& pos, rdr::U8 buttonMask) { + int frameWidth = (int)ceil( sqrt( frames * 1.0 ) ); + int elementHeight = mheight / frameWidth; + int elementWidth = mwidth / frameWidth; + int clickElement = 0; + int leftClick = 0; + int doubleClick = 0; + int rightClick = 0; + #ifdef notyet vlog.info("pointerEvent pos=%d,%d buttons=0x%x", pos.x, pos.y, buttonMask); #endif + + clickElement = (pos.y / elementHeight) * frameWidth; + clickElement += pos.x / elementWidth; + + if( buttonMask & 0x01 ) { + buttons |= 0x01; + } else if( buttons & 0x01 ) { + struct timeval rightNow; + leftClick = true; + buttons &= ~(0x01); + gettimeofday( &rightNow, NULL ); + switch( rightNow.tv_sec - buttonTime.tv_sec ) { + case 0: + doubleClick = true; + break; + case 1: + if( rightNow.tv_usec < buttonTime.tv_sec ) + doubleClick = true; + break; + } + buttonTime = rightNow; + } + if( buttonMask & 0x04 ) { + buttons |= 0x04; + } else if( buttons & 0x04 ) { + rightClick = true; + buttons &= ~(0x04); + } + + switch( montageMode ) { + case MONTAGE_SCAN: + // Left click, stop scan, change target + if( leftClick && !doubleClick ) { + element = clickElement; + montageMode = MONTAGE_SINGLE; + } + break; + case MONTAGE_SINGLE: + // Second left click, change target + if( doubleClick && ( clickElement == element ) ) { + montageMode = FULL_SCREEN; + delete pb; + pb = new FullFramePixelBuffer(pf, width, height, + (rdr::U8 *) framebuffer, 0); + server->setPixelBuffer(pb); + } else if( leftClick ) { + element = clickElement; + } + + // right click, return to scan + if( rightClick ) { + montageMode = MONTAGE_SCAN; + element = clickElement; + } + break; + case FULL_SCREEN: + // left click, return to single + if( leftClick && !doubleClick ) { + montageMode = MONTAGE_SINGLE; + memset( mbuffer, 0xff, mdepth * mwidth * mheight ); + buttonTime.tv_sec = 0; + delete pb; + pb = new FullFramePixelBuffer(pf, mwidth, mheight, + (rdr::U8 *) mbuffer, 0); + server->setPixelBuffer(pb); + } + // right click, return to scan + if( rightClick ) { + montageMode = MONTAGE_SCAN; + delete pb; + pb = new FullFramePixelBuffer(pf, mwidth, mheight, + (rdr::U8 *) mbuffer, 0); + server->setPixelBuffer(pb); + } + // Make sure we don't doubleclick + break; + } + mouse->mouseEvent(pos.x, pos.y, buttonMask); + + } *************** *** 178,181 **** --- 298,313 ---- vlog.info("keyEvent 0x%x (%s)", key, down ? "down" : "up"); keyboard->keyboardEvent(key, down); + if( !down ) { + switch( key ) { + case 0xffab: + frames++; + memset( mbuffer, 0xff, mdepth * mwidth * mheight ); + break; + case 0xffad: + frames--; + memset( mbuffer, 0xff, mdepth * mwidth * mheight ); + break; + } + } } *************** *** 187,192 **** --- 319,490 ---- void + V4LDesktop::copyPixelFragment( unsigned char * dest, int dbpp, unsigned char * src, int sbpp, int strength ) + { + int pixel; + unsigned char * sp; + + // Convert to 32bpp + switch( sbpp ) { + case 2: + pixel = *src; + pixel = (pixel << 8) & 0x00ff00; + pixel += *(src + 1) & 0x00ff; + pixel = ( ( pixel & 0x00f800 ) << 5 ) | + ( ( pixel & 0x0007e0 ) << 3 ) | + ( ( pixel & 0x00001f ) ); + break; + case 4: + pixel = *((int *)src); + case 3: + pixel = *src; + pixel = (pixel << 8) & 0x00ff00; + pixel += *(src + 1) & 0x00ff; + pixel = (pixel << 8) & 0x00ffff00; + pixel += *(src + 2) & 0x00ff; + break; + } + + // scale image + sp = (unsigned char *)&pixel; + sp[0] = (unsigned char)( ( sp[0] * strength ) >> 16 ) & 0x00ff; + sp[1] = (unsigned char)( ( sp[1] * strength ) >> 16 ) & 0x00ff; + sp[2] = (unsigned char)( ( sp[2] * strength ) >> 16 ) & 0x00ff; + sp[3] = (unsigned char)( ( sp[3] * strength ) >> 16 ) & 0x00ff; + + // convert to dest bpp and save + switch( dbpp ) { + case 2: + *dest += ( sp[1] & 0x00f8 ) | ( ( sp[2] >> 3 ) & 0x0007 ); + *(dest+1) += ( sp[3] & 0x001f ) | ( ( sp[2] << 5 ) & 0x00e0 ); + break; + case 3: + *dest += sp[2]; + *(dest+1) += sp[1]; + *(dest+2) += sp[0]; + break; + case 4: + *dest += sp[3]; + *(dest+1) += sp[2]; + *(dest+2) += sp[1]; + *(dest+3) += sp[0]; + break; + } + + } + + void + V4LDesktop::montageImage( void * dest, void * src, int sector ) + { + int lineLength; // number of pixels wide the element is + int frameWidth; // Number of elements wide + int lineHeight; // number of pixels high the element is + int remWidth; // remainder pixels per element + int remHeight; // remainder pixels per element + int borderW; // + int borderH; // + int row; // row the element is in, zero based + int col; // col the element is in, zero based + unsigned char * cp; + unsigned char * tp; + unsigned char * sp; + unsigned char portion; + unsigned int a, b, c, d; + int horizScale; + int vertScale; + int horizWeight; + int vertWeight; + int type; + + if( sector >= frames ) return; + if( sector < 0 ) return; + + frameWidth = (int)ceil( sqrt( frames * 1.0 ) ); + lineLength = ( mwidth / frameWidth ); + lineHeight = ( mheight / frameWidth ); + + row = sector / frameWidth; + col = sector % frameWidth; + + remWidth = width % frameWidth; + remHeight = height % frameWidth; + + horizScale = (width << 8) / lineLength; + vertScale = (height << 8) / lineHeight; + + // Blank out the target area. + cp = (unsigned char *)dest; + // Offset to start of element + cp += row * lineHeight * mwidth * mdepth; + cp += col * lineLength * mdepth; + for( int i = 0;i < lineHeight;i++ ) { + memset( cp, 0, lineLength * mdepth ); + cp += mwidth * mdepth; + } + + // For each source pixel + // figure out type 1, 2, 3 or 4 + // figure out dest pixel(s) + // for type 2-4 figure out percentage in each pixel + sp = (unsigned char *)src; + tp = (unsigned char *)dest; + tp += row * lineHeight * mwidth * mdepth; + tp += col * lineLength * mdepth; + + for( int j=0;j< (height);j++) { + for( int i=0;i < (width);i++) { + // Okay, We have a source pixel. This pixel may be completely + // contained inside a destination pixel. It may be apportioned + // either horizontally or vertically (or both) over more than + // one pixel. + + // Calc start and end dest pixel horizontally + a = ( i << 16 ) / horizScale; + b = ( (i + 1) << 16 ) / horizScale; + // Calc start and end pixel vertically + c = ( j << 16 ) / vertScale; + d = ( (j + 1) << 16 ) / vertScale; + + // one horizontal line of pixels at a time + for( row = (c >> 8);row <= (d >> 8);row++ ) { + // what is my value assigned to this line? + if( (c & 0x00ff00) == (d & 0x00ff00 ) ) { + vertWeight = d-c; + } else if( ( row << 8 ) < c ) { + vertWeight = 0x00ff - ( c & 0x00ff); + } else if( row >= ( d >> 8 ) ) { + vertWeight = d & 0x00ff; + } else { + vertWeight = 0x00ff; + } + + // one pixel in the line at a time + for( col = (a >> 8);col <= (b >> 8);col++ ) { + // what is my value in this pixel? + if( (a & 0x00ff00) == (b & 0x00ff00 )) { + horizWeight = b-a; + } else if( ( col << 8 ) < a ) { + horizWeight = 0x00ff - ( a & 0x00ff ); + } else if( col >= ( b >> 8 ) ) { + horizWeight = b & 0x00ff; + } else { + horizWeight = 0x00ff; + } + + cp = tp + (col * mdepth) + (row * mwidth * mdepth); + copyPixelFragment( cp, mdepth, sp, depth, horizWeight * vertWeight ); + } + } + sp += depth; + } + } + + } + + + + void V4LDesktop::poll() { + static long timestamp = 0; if (server == NULL || !server->clientsReadyForUpdate()) { return; *************** *** 196,199 **** --- 494,498 ---- // Check for a size change in the video // + //SB check for pallette change struct video_window vw; v4lioctl(fd, VIDIOCGWIN, &vw); *************** *** 208,215 **** pb = new FullFramePixelBuffer(pf, width, height, (rdr::U8 *) framebuffer, 0); ! server->setPixelBuffer(pb); mouse->syncCursor = true; } struct video_mmap vm = { 0 }; vm.frame = 0; --- 507,527 ---- pb = new FullFramePixelBuffer(pf, width, height, (rdr::U8 *) framebuffer, 0); ! ! if( montageMode == FULL_SCREEN ) { ! server->setPixelBuffer(pb); ! } mouse->syncCursor = true; } + if( montageMode == MONTAGE_SCAN ) + if( !(time(NULL) % 5) && time(NULL) != timestamp) { + element = (element + 1)%frames; + timestamp = time(NULL); + } + + if( montageMode != FULL_SCREEN ) { + montageImage( mbuffer, framebuffer, element ); + } + struct video_mmap vm = { 0 }; vm.frame = 0; *************** *** 247,248 **** --- 559,574 ---- return rc; } + + + // SBSBSB Limitations to overcome: + // stock resolution + // stock multiplier ( type 2, 3, 4 ) + // stock depth + // no third buffer for changed image + // only work with 24bpp (untested) + // limited update on montage + // properly implemented changes + // double click delay + // reduction or no-change scaling + // arbitrary screen size + // not 4:3 ratios |