ISA: Make the decode function part of the ISA's decoder.
[gem5.git] / src / base / vnc / vncserver.cc
index 8936fa67b542c15e8c93b4d1ff8448bd3765f550..3f0393104c69c70098bf9daec4abb5c0eb989b82 100644 (file)
  * Implementiation of a VNC server
  */
 
-#include <cstdio>
-
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <sys/termios.h>
-#include <errno.h>
+#include <sys/types.h>
+#include <fcntl.h>
 #include <poll.h>
 #include <unistd.h>
 
+#include <cerrno>
+#include <cstdio>
+
+#include "base/vnc/vncserver.hh"
 #include "base/atomicio.hh"
+#include "base/bitmap.hh"
 #include "base/misc.hh"
+#include "base/output.hh"
 #include "base/socket.hh"
 #include "base/trace.hh"
-#include "base/vnc/vncserver.hh"
+#include "debug/VNC.hh"
 #include "sim/byteswap.hh"
+#include "sim/core.hh"
 
 using namespace std;
 
@@ -97,14 +104,14 @@ VncServer::VncServer(const Params *p)
     : SimObject(p), listenEvent(NULL), dataEvent(NULL), number(p->number),
       dataFd(-1), _videoWidth(1), _videoHeight(1), clientRfb(0), keyboard(NULL),
       mouse(NULL), sendUpdate(false), videoMode(VideoConvert::UnknownMode),
-      vc(NULL)
+      vc(NULL), captureEnabled(p->frame_capture), captureCurrentFrame(0),
+      captureLastHash(0), captureBitmap(0)
 {
     if (p->port)
         listen(p->port);
 
     curState = WaitForProtocolVersion;
 
-
     // currently we only support this one pixel format
     // unpacked 32bit rgb (rgb888 + 8 bits of nothing/alpha)
     // keep it around for telling the client and making
@@ -120,6 +127,14 @@ VncServer::VncServer(const Params *p)
     pixelFormat.greenshift = 8;
     pixelFormat.blueshift = 0;
 
+    if (captureEnabled) {
+        // remove existing frame output directory if it exists, then create a
+        //   clean empty directory
+        const string FRAME_OUTPUT_SUBDIR = "frames_" + name();
+        simout.remove(FRAME_OUTPUT_SUBDIR, true);
+        captureOutputDirectory = simout.createSubdirectory(
+                                FRAME_OUTPUT_SUBDIR);
+    }
 
     DPRINTF(VNC, "Vnc server created at port %d\n", p->port);
 }
@@ -232,21 +247,21 @@ VncServer::data()
             setEncodings();
             break;
           case ClientFrameBufferUpdate:
-             requestFbUpdate();
-             break;
+            requestFbUpdate();
+            break;
           case ClientKeyEvent:
-             recvKeyboardInput();
-             break;
+            recvKeyboardInput();
+            break;
           case ClientPointerEvent:
-             recvPointerInput();
-             break;
+            recvPointerInput();
+            break;
           case ClientCutText:
-             recvCutText();
-             break;
+            recvCutText();
+            break;
           default:
-             panic("Unimplemented message type recv from client: %d\n",
-                     message_type);
-             break;
+            panic("Unimplemented message type recv from client: %d\n",
+                  message_type);
+            break;
         }
         break;
       default:
@@ -685,6 +700,16 @@ VncServer::setFrameBufferParams(VideoConvert::Mode mode, int width, int height)
         vc = new VideoConvert(mode, VideoConvert::rgb8888, videoWidth(),
                 videoHeight());
 
+        if (captureEnabled) {
+            // create bitmap of the frame with new attributes
+            if (captureBitmap)
+                delete captureBitmap;
+
+            assert(clientRfb);
+            captureBitmap = new Bitmap(videoMode, width, height, clientRfb);
+            assert(captureBitmap);
+        }
+
         if (dataFd > 0 && clientRfb && curState == NormalPhase) {
             if (supportsResizeEnc)
                 sendFrameBufferResized();
@@ -701,3 +726,29 @@ VncServerParams::create()
 {
     return new VncServer(this);
 }
+
+void
+VncServer::captureFrameBuffer()
+{
+    assert(captureBitmap);
+
+    // skip identical frames
+    uint64_t new_hash = captureBitmap->getHash();
+    if (captureLastHash == new_hash)
+        return;
+    captureLastHash = new_hash;
+
+    // get the filename for the current frame
+    char frameFilenameBuffer[64];
+    snprintf(frameFilenameBuffer, 64, "fb.%06d.%lld.bmp.gz",
+            captureCurrentFrame, static_cast<long long int>(curTick()));
+    const string frameFilename(frameFilenameBuffer);
+
+    // create the compressed framebuffer file
+    ostream *fb_out = simout.create(captureOutputDirectory + frameFilename,
+                    true);
+    captureBitmap->write(fb_out);
+    simout.close(fb_out);
+
+    ++captureCurrentFrame;
+}