CConnection::CConnection()
: csecurity(0), is(0), os(0), reader_(0), writer_(0),
shared(false),
- state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false)
+ state_(RFBSTATE_UNINITIALISED), useProtocol3_3(false),
+ framebuffer(NULL), decoder(this)
{
security = new SecurityClient();
}
CConnection::~CConnection()
{
+ setFramebuffer(NULL);
if (csecurity) csecurity->destroy();
delete reader_;
reader_ = 0;
os = os_;
}
+void CConnection::setFramebuffer(ModifiablePixelBuffer* fb)
+{
+ if ((framebuffer != NULL) && (fb != NULL)) {
+ Rect rect;
+
+ const rdr::U8* data;
+ int stride;
+
+ const rdr::U8 black[4] = { 0, 0, 0, 0 };
+
+ // Copy still valid area
+
+ rect.setXYWH(0, 0,
+ __rfbmin(fb->width(), framebuffer->width()),
+ __rfbmin(fb->height(), framebuffer->height()));
+ data = framebuffer->getBuffer(framebuffer->getRect(), &stride);
+ fb->imageRect(rect, data, stride);
+
+ // Black out any new areas
+
+ if (fb->width() > framebuffer->width()) {
+ rect.setXYWH(framebuffer->width(), 0,
+ fb->width() - fb->width(),
+ fb->height());
+ fb->fillRect(rect, black);
+ }
+
+ if (fb->height() > framebuffer->height()) {
+ rect.setXYWH(0, framebuffer->height(),
+ fb->width(),
+ fb->height() - framebuffer->height());
+ fb->fillRect(rect, black);
+ }
+ }
+
+ delete framebuffer;
+ framebuffer = fb;
+}
+
void CConnection::initialiseProtocol()
{
state_ = RFBSTATE_PROTOCOL_VERSION;
writer_->writeClientInit(shared);
}
+void CConnection::dataRect(const Rect& r, int encoding)
+{
+ decoder.decodeRect(r, encoding, framebuffer);
+}
+
void CConnection::authSuccess()
{
}
#define __RFB_CCONNECTION_H__
#include <rfb/CMsgHandler.h>
+#include <rfb/DecodeManager.h>
#include <rfb/util.h>
namespace rfb {
// only ever support protocol version 3.3
void setProtocol3_3(bool s) {useProtocol3_3 = s;}
+ // setFramebuffer configures the PixelBuffer that the CConnection
+ // should render all pixel data in to. Note that the CConnection
+ // takes ownership of the PixelBuffer and it must not be deleted by
+ // anyone else. Call setFramebuffer again with NULL or a different
+ // PixelBuffer to delete the previous one.
+ void setFramebuffer(ModifiablePixelBuffer* fb);
+
// initialiseProtocol() should be called once the streams and security
// types are set. Subsequently, processMsg() should be called whenever
// there is data to read on the InStream.
void processMsg();
+ // Methods overridden from CMsgHandler
+
+ virtual void dataRect(const Rect& r, int encoding);
+
+
// Methods to be overridden in a derived class
// getIdVerifier() returns the identity verifier associated with the connection.
void setReader(CMsgReader *r) { reader_ = r; }
void setWriter(CMsgWriter *w) { writer_ = w; }
+ ModifiablePixelBuffer* getFramebuffer() { return framebuffer; }
+
private:
// This is a default implementation of fences that automatically
// responds to requests, stating no support for synchronisation.
CharArray serverName;
bool useProtocol3_3;
+
+ ModifiablePixelBuffer* framebuffer;
+ DecodeManager decoder;
};
}
#endif
ConnParams.cxx
CopyRectDecoder.cxx
Cursor.cxx
+ DecodeManager.cxx
Decoder.cxx
d3des.c
EncodeManager.cxx
--- /dev/null
+/* Copyright 2015 Pierre Ossman for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <rfb/DecodeManager.h>
+#include <rfb/Decoder.h>
+
+#include <rfb/LogWriter.h>
+
+#include <rdr/Exception.h>
+
+using namespace rfb;
+
+static LogWriter vlog("DecodeManager");
+
+DecodeManager::DecodeManager(CConnection *conn) :
+ conn(conn)
+{
+ memset(decoders, 0, sizeof(decoders));
+}
+
+DecodeManager::~DecodeManager()
+{
+ for (size_t i = 0; i < sizeof(decoders)/sizeof(decoders[0]); i++)
+ delete decoders[i];
+}
+
+void DecodeManager::decodeRect(const Rect& r, int encoding,
+ ModifiablePixelBuffer* pb)
+{
+ assert(pb != NULL);
+
+ if (!Decoder::supported(encoding)) {
+ vlog.error("Unknown encoding %d", encoding);
+ throw rdr::Exception("Unknown encoding");
+ }
+
+ if (!decoders[encoding]) {
+ decoders[encoding] = Decoder::createDecoder(encoding, conn);
+ if (!decoders[encoding]) {
+ vlog.error("Unknown encoding %d", encoding);
+ throw rdr::Exception("Unknown encoding");
+ }
+ }
+ decoders[encoding]->readRect(r, pb);
+}
--- /dev/null
+/* Copyright 2015 Pierre Ossman for Cendio AB
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+
+#ifndef __RFB_DECODEMANAGER_H__
+#define __RFB_DECODEMANAGER_H__
+
+#include <rfb/encodings.h>
+
+namespace rfb {
+ class CConnection;
+ class Decoder;
+ class ModifiablePixelBuffer;
+ class Rect;
+
+ class DecodeManager {
+ public:
+ DecodeManager(CConnection *conn);
+ ~DecodeManager();
+
+ void decodeRect(const Rect& r, int encoding,
+ ModifiablePixelBuffer* pb);
+
+ private:
+ CConnection *conn;
+ Decoder *decoders[encodingMax+1];
+ };
+}
+
+#endif
#include <rfb/CConnection.h>
#include <rfb/CMsgReader.h>
-#include <rfb/Decoder.h>
#include <rfb/PixelBuffer.h>
#include <rfb/PixelFormat.h>
virtual void setDesktopSize(int w, int h);
virtual void setPixelFormat(const rfb::PixelFormat& pf);
virtual void setCursor(int, int, const rfb::Point&, void*, void*);
- virtual void dataRect(const rfb::Rect&, int);
+ virtual void framebufferUpdateStart();
+ virtual void framebufferUpdateEnd();
virtual void setColourMapEntries(int, int, rdr::U16*);
virtual void bell();
virtual void serverCutText(const char*, rdr::U32);
protected:
rdr::FileInStream *in;
- rfb::Decoder *decoders[rfb::encodingMax+1];
- rfb::ManagedPixelBuffer pb;
};
CConn::CConn(const char *filename)
{
- int i;
-
cpuTime = 0.0;
in = new rdr::FileInStream(filename);
setStreams(in, NULL);
- memset(decoders, 0, sizeof(decoders));
- for (i = 0;i < rfb::encodingMax;i++) {
- if (!rfb::Decoder::supported(i))
- continue;
-
- decoders[i] = rfb::Decoder::createDecoder(i, this);
- }
-
// Need to skip the initial handshake
setState(RFBSTATE_INITIALISATION);
// That also means that the reader and writer weren't setup
CConn::~CConn()
{
- int i;
-
delete in;
-
- for (i = 0;i < rfb::encodingMax;i++)
- delete decoders[i];
}
void CConn::setDesktopSize(int w, int h)
{
CConnection::setDesktopSize(w, h);
- pb.setSize(cp.width, cp.height);
+ setFramebuffer(new rfb::ManagedPixelBuffer(filePF, cp.width, cp.height));
}
void CConn::setPixelFormat(const rfb::PixelFormat& pf)
{
// Override format
CConnection::setPixelFormat(filePF);
-
- pb.setPF(cp.pf());
}
void CConn::setCursor(int, int, const rfb::Point&, void*, void*)
{
}
-void CConn::dataRect(const rfb::Rect &r, int encoding)
+void CConn::framebufferUpdateStart()
{
- if (!decoders[encoding])
- throw rdr::Exception("Unknown encoding");
-
startCpuCounter();
- decoders[encoding]->readRect(r, &pb);
+}
+
+void CConn::framebufferUpdateEnd()
+{
endCpuCounter();
cpuTime += getCpuCounter();
#include <rfb/CConnection.h>
#include <rfb/CMsgReader.h>
-#include <rfb/Decoder.h>
#include <rfb/UpdateTracker.h>
#include <rfb/EncodeManager.h>
protected:
rdr::FileInStream *in;
- rfb::Decoder *decoders[rfb::encodingMax + 1];
- rfb::ManagedPixelBuffer pb;
rfb::SimpleUpdateTracker updates;
class SConn *sc;
};
CConn::CConn(const char *filename)
{
- int i;
-
decodeTime = 0.0;
encodeTime = 0.0;
in = new rdr::FileInStream(filename);
setStreams(in, NULL);
- memset(decoders, 0, sizeof(decoders));
- for (i = 0; i < rfb::encodingMax; i++) {
- if (!rfb::Decoder::supported(i))
- continue;
-
- decoders[i] = rfb::Decoder::createDecoder(i, this);
- }
-
// Need to skip the initial handshake and ServerInit
setState(RFBSTATE_NORMAL);
// That also means that the reader and writer weren't setup
pf.parse(format);
setPixelFormat(pf);
- pb.setPF((bool)translate ? fbPF : pf);
-
sc = new SConn();
- sc->cp.setPF(pb.getPF());
+ sc->cp.setPF((bool)translate ? fbPF : pf);
sc->setEncodings(sizeof(encodings) / sizeof(*encodings), encodings);
}
CConn::~CConn()
{
- int i;
-
delete sc;
-
delete in;
-
- for (i = 0; i < rfb::encodingMax; i++)
- delete decoders[i];
}
void CConn::getStats(double& ratio, unsigned long long& bytes,
{
CConnection::setDesktopSize(w, h);
- pb.setSize(cp.width, cp.height);
+ setFramebuffer(new rfb::ManagedPixelBuffer(sc->cp.pf(), cp.width, cp.height));
}
void CConn::setCursor(int, int, const rfb::Point&, void*, void*)
void CConn::framebufferUpdateStart()
{
updates.clear();
+ startCpuCounter();
}
void CConn::framebufferUpdateEnd()
{
rfb::UpdateInfo ui;
- rfb::Region clip(pb.getRect());
+ rfb::PixelBuffer* pb = getFramebuffer();
+ rfb::Region clip(pb->getRect());
+
+ endCpuCounter();
+
+ decodeTime += getCpuCounter();
updates.getUpdateInfo(&ui, clip);
startCpuCounter();
- sc->writeUpdate(ui, &pb);
+ sc->writeUpdate(ui, pb);
endCpuCounter();
encodeTime += getCpuCounter();
void CConn::dataRect(const rfb::Rect &r, int encoding)
{
- if (!decoders[encoding])
- throw rdr::Exception("Unknown encoding");
-
- startCpuCounter();
- decoders[encoding]->readRect(r, &pb);
- endCpuCounter();
-
- decodeTime += getCpuCounter();
+ CConnection::dataRect(r, encoding);
if (encoding != rfb::encodingCopyRect) // FIXME
updates.add_changed(rfb::Region(r));
#include <rfb/CMsgWriter.h>
#include <rfb/CSecurity.h>
-#include <rfb/encodings.h>
-#include <rfb/Decoder.h>
#include <rfb/Hostname.h>
#include <rfb/LogWriter.h>
#include <rfb/Security.h>
setShared(::shared);
sock = socket;
- memset(decoders, 0, sizeof(decoders));
-
int encNum = encodingNum(preferredEncoding);
if (encNum != -1)
currentEncoding = encNum;
OptionsDialog::removeCallback(handleOptions);
Fl::remove_timeout(handleUpdateTimeout, this);
- for (size_t i = 0; i < sizeof(decoders)/sizeof(decoders[0]); i++)
- delete decoders[i];
-
if (desktop)
delete desktop;
if (encoding != encodingCopyRect)
lastServerEncoding = encoding;
- if (!Decoder::supported(encoding)) {
- // TRANSLATORS: Refers to a VNC protocol encoding type
- vlog.error(_("Unknown encoding %d"), encoding);
- throw Exception(_("Unknown encoding"));
- }
-
- if (!decoders[encoding]) {
- decoders[encoding] = Decoder::createDecoder(encoding, this);
- if (!decoders[encoding]) {
- vlog.error(_("Unknown encoding %d"), encoding);
- throw Exception(_("Unknown encoding"));
- }
- }
- decoders[encoding]->readRect(r, desktop->getFramebuffer());
+ CConnection::dataRect(r, encoding);
sock->inStream().stopTiming();
}
#include <FL/Fl.H>
#include <rfb/CConnection.h>
-#include <rfb/encodings.h>
-#include <network/Socket.h>
+#include <rdr/FdInStream.h>
-namespace rfb { class Decoder; }
+namespace network { class Socket; }
class DesktopWindow;
bool pendingPFChange;
rfb::PixelFormat pendingPF;
- rfb::Decoder *decoders[rfb::encodingMax+1];
-
int currentEncoding, lastServerEncoding;
bool formatChange;
}
-rfb::ModifiablePixelBuffer* DesktopWindow::getFramebuffer(void)
-{
- return viewport->getFramebuffer();
-}
-
-
// Copy the areas of the framebuffer that have been changed (damaged)
// to the displayed window.
// Updated session title
void setName(const char *name);
- // Return a pointer to the framebuffer for decoders to write into
- rfb::ModifiablePixelBuffer* getFramebuffer(void);
-
// Resize the current framebuffer, but retain the contents
void resizeFramebuffer(int new_w, int new_h);
frameBuffer = createFramebuffer(w, h);
assert(frameBuffer);
+ cc->setFramebuffer(frameBuffer);
contextMenu = new Fl_Menu_Button(0, 0, 0, 0);
// Setting box type to FL_NO_BOX prevents it from trying to draw the
OptionsDialog::removeCallback(handleOptions);
- delete frameBuffer;
-
if (cursor) {
if (!cursor->alloc_array)
delete [] cursor->array;
damage(FL_DAMAGE_USER1, r.tl.x + x(), r.tl.y + y(), r.width(), r.height());
}
-rfb::ModifiablePixelBuffer* Viewport::getFramebuffer(void)
-{
- return frameBuffer;
-}
-
static const char * dotcursor_xpm[] = {
"5 5 2 1",
". c #000000",
void Viewport::resize(int x, int y, int w, int h)
{
- PlatformPixelBuffer* newBuffer;
- rfb::Rect rect;
-
- const rdr::U8* data;
- int stride;
-
- const rdr::U8 black[4] = { 0, 0, 0, 0 };
-
- // FIXME: Resize should probably be a feature of the pixel buffer itself
-
- if ((w == frameBuffer->width()) && (h == frameBuffer->height()))
- goto end;
+ if ((w != frameBuffer->width()) || (h != frameBuffer->height())) {
+ vlog.debug("Resizing framebuffer from %dx%d to %dx%d",
+ frameBuffer->width(), frameBuffer->height(), w, h);
- vlog.debug("Resizing framebuffer from %dx%d to %dx%d",
- frameBuffer->width(), frameBuffer->height(), w, h);
-
- newBuffer = createFramebuffer(w, h);
- assert(newBuffer);
-
- rect.setXYWH(0, 0,
- __rfbmin(newBuffer->width(), frameBuffer->width()),
- __rfbmin(newBuffer->height(), frameBuffer->height()));
- data = frameBuffer->getBuffer(frameBuffer->getRect(), &stride);
- newBuffer->imageRect(rect, data, stride);
-
- // Black out any new areas
-
- if (newBuffer->width() > frameBuffer->width()) {
- rect.setXYWH(frameBuffer->width(), 0,
- newBuffer->width() - frameBuffer->width(),
- newBuffer->height());
- newBuffer->fillRect(rect, black);
+ frameBuffer = createFramebuffer(w, h);
+ assert(frameBuffer);
+ cc->setFramebuffer(frameBuffer);
}
- if (newBuffer->height() > frameBuffer->height()) {
- rect.setXYWH(0, frameBuffer->height(),
- newBuffer->width(),
- newBuffer->height() - frameBuffer->height());
- newBuffer->fillRect(rect, black);
- }
-
- delete frameBuffer;
- frameBuffer = newBuffer;
-
-end:
Fl_Widget::resize(x, y, w, h);
}
// Flush updates to screen
void updateWindow();
- // Return a pointer to the framebuffer for decoders to write into
- rfb::ModifiablePixelBuffer* getFramebuffer(void);
-
// New image for the locally rendered cursor
void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);