Browse Source

If the client and server are using identical pixel formats, then perform Tight decoding directly into the viewer's back buffer, rather than going through the slow fillRect/imageRect routines.


git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4757 3789f03b-4d11-0410-bbf8-ca57d06f2519
tags/v1.1.90
DRC 12 years ago
parent
commit
33c15e3a3a

+ 1
- 0
common/rfb/CMakeLists.txt View File

@@ -23,6 +23,7 @@ set(RFB_SOURCES
HextileDecoder.cxx
HextileEncoder.cxx
JpegCompressor.cxx
JpegDecompressor.cxx
KeyRemapper.cxx
LogWriter.cxx
Logger.cxx

+ 6
- 0
common/rfb/CMsgHandler.h View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009 Pierre Ossman for Cendio AB
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,6 +69,11 @@ namespace rfb {
virtual void imageRect(const Rect& r, void* pixels) = 0;
virtual void copyRect(const Rect& r, int srcX, int srcY) = 0;

virtual rdr::U8* getRawPixelsRW(const Rect& r, int* stride) = 0;
virtual void releaseRawPixels(const Rect& r) = 0;

virtual const PixelFormat &getPreferredPF(void) = 0;

ConnParams cp;
};
}

+ 55
- 0
common/rfb/PixelFormat.cxx View File

@@ -225,6 +225,61 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
}


void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src,
int w, int pitch, int h, ColourMap* cm) const
{
if (is888()) {
// Optimised common case
int rindex, gindex, bindex;

if (bigEndian) {
rindex = (24 - redShift)/8;
gindex = (24 - greenShift)/8;
bindex = (24 - blueShift)/8;
} else {
rindex = redShift/8;
gindex = greenShift/8;
bindex = blueShift/8;
}

int dstPad = pitch - w * 4;
while (h > 0) {
rdr::U8 *dstEndOfRow = (rdr::U8 *)dst + w * 4;
while (dst < dstEndOfRow) {
dst[rindex] = *(src++);
dst[gindex] = *(src++);
dst[bindex] = *(src++);
dst += 4;
}
dst += dstPad;
h--;
}
} else {
// Generic code
Pixel p;
rdr::U8 r, g, b;
int pixelSize = bpp/8;

int dstPad = pitch - w * pixelSize;
while (h > 0) {
rdr::U8 *dstEndOfRow = (rdr::U8 *)dst + w * pixelSize;
while (dst < dstEndOfRow) {
r = *(src++);
g = *(src++);
b = *(src++);

p = pixelFromRGB(r, g, b, cm);

bufferFromPixel(dst, p);
dst += pixelSize;
}
dst += dstPad;
h--;
}
}
}


void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, Colour* rgb) const
{
rdr::U16 r, g, b;

+ 2
- 0
common/rfb/PixelFormat.h View File

@@ -53,6 +53,8 @@ namespace rfb {
Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const;

void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const;
void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int w, int pitch,
int h, ColourMap* cm=0) const;

void rgbFromPixel(Pixel pix, ColourMap* cm, Colour* rgb) const;
inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const;

+ 18
- 82
common/rfb/TightDecoder.cxx View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright 2004-2005 Cendio AB.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -19,19 +20,11 @@
#include <rfb/CMsgReader.h>
#include <rfb/CMsgHandler.h>
#include <rfb/TightDecoder.h>
#include <stdio.h> /* jpeglib.h needs FILE */
extern "C" {
#include <jpeglib.h>
}

using namespace rfb;

#define TIGHT_MAX_WIDTH 2048

static void JpegSetSrcManager(j_decompress_ptr cinfo, char *compressedData,
int compressedLen);
static bool jpegError;

#define EXTRA_ARGS CMsgHandler* handler
#define FILL_RECT(r, p) handler->fillRect(r, p)
#define IMAGE_RECT(r, p) handler->imageRect(r, p)
@@ -60,82 +53,25 @@ TightDecoder::~TightDecoder()

void TightDecoder::readRect(const Rect& r, CMsgHandler* handler)
{
rdr::InStream* is = reader->getInStream();
/* Uncompressed RGB24 JPEG data, before translated, can be up to 3
times larger, if VNC bpp is 8. */
rdr::U8* buf = reader->getImageBuf(r.area()*3);
switch (reader->bpp()) {
is = reader->getInStream();
this->handler = handler;
clientpf = handler->getPreferredPF();
serverpf = handler->cp.pf();

if (clientpf.equal(serverpf)) {
/* Decode directly into the framebuffer (fast path) */
directDecode = true;
} else {
/* Decode into an intermediate buffer and use pixel translation */
directDecode = false;
}

switch (serverpf.bpp) {
case 8:
tightDecode8 (r, is, zis, (rdr::U8*) buf, handler); break;
tightDecode8 (r); break;
case 16:
tightDecode16(r, is, zis, (rdr::U16*)buf, handler); break;
tightDecode16(r); break;
case 32:
tightDecode32(r, is, zis, (rdr::U32*)buf, handler); break;
tightDecode32(r); break;
}
}


//
// A "Source manager" for the JPEG library.
//

static struct jpeg_source_mgr jpegSrcManager;
static JOCTET *jpegBufferPtr;
static size_t jpegBufferLen;

static void JpegInitSource(j_decompress_ptr cinfo);
static boolean JpegFillInputBuffer(j_decompress_ptr cinfo);
static void JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
static void JpegTermSource(j_decompress_ptr cinfo);

static void
JpegInitSource(j_decompress_ptr cinfo)
{
jpegError = false;
}

static boolean
JpegFillInputBuffer(j_decompress_ptr cinfo)
{
jpegError = true;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;
jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;

return TRUE;
}

static void
JpegSkipInputData(j_decompress_ptr cinfo, long num_bytes)
{
if (num_bytes < 0 || (size_t)num_bytes > jpegSrcManager.bytes_in_buffer) {
jpegError = true;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;
jpegSrcManager.next_input_byte = (JOCTET *)jpegBufferPtr;
} else {
jpegSrcManager.next_input_byte += (size_t) num_bytes;
jpegSrcManager.bytes_in_buffer -= (size_t) num_bytes;
}
}

static void
JpegTermSource(j_decompress_ptr cinfo)
{
/* No work necessary here. */
}

static void
JpegSetSrcManager(j_decompress_ptr cinfo, char *compressedData, int compressedLen)
{
jpegBufferPtr = (JOCTET *)compressedData;
jpegBufferLen = (size_t)compressedLen;

jpegSrcManager.init_source = JpegInitSource;
jpegSrcManager.fill_input_buffer = JpegFillInputBuffer;
jpegSrcManager.skip_input_data = JpegSkipInputData;
jpegSrcManager.resync_to_restart = jpeg_resync_to_restart;
jpegSrcManager.term_source = JpegTermSource;
jpegSrcManager.next_input_byte = jpegBufferPtr;
jpegSrcManager.bytes_in_buffer = jpegBufferLen;

cinfo->src = &jpegSrcManager;
}

+ 32
- 0
common/rfb/TightDecoder.h View File

@@ -1,4 +1,5 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,18 +21,49 @@

#include <rdr/ZlibInStream.h>
#include <rfb/Decoder.h>
#include <rfb/JpegDecompressor.h>

namespace rfb {

class TightDecoder : public Decoder {

public:
static Decoder* create(CMsgReader* reader);
virtual void readRect(const Rect& r, CMsgHandler* handler);
virtual ~TightDecoder();

private:
void tightDecode8(const Rect& r);
void tightDecode16(const Rect& r);
void tightDecode32(const Rect& r);

void DecompressJpegRect8(const Rect& r);
void DecompressJpegRect16(const Rect& r);
void DecompressJpegRect32(const Rect& r);

void FilterGradient8(rdr::InStream* is, rdr::U8* buf, int stride,
const Rect& r, int dataSize);
void FilterGradient16(rdr::InStream* is, rdr::U16* buf, int stride,
const Rect& r, int dataSize);
void FilterGradient24(rdr::InStream* is, rdr::U32* buf, int stride,
const Rect& r, int dataSize);
void FilterGradient32(rdr::InStream* is, rdr::U32* buf, int stride,
const Rect& r, int dataSize);

void directFillRect8(const Rect& r, Pixel pix);
void directFillRect16(const Rect& r, Pixel pix);
void directFillRect32(const Rect& r, Pixel pix);

TightDecoder(CMsgReader* reader);

CMsgReader* reader;
CMsgHandler* handler;
rdr::InStream* is;
rdr::ZlibInStream zis[4];
JpegDecompressor jd;
PixelFormat clientpf;
PixelFormat serverpf;
bool directDecode;
};

// Compression control

+ 118
- 158
common/rfb/tightDecode.h View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2000-2003 Constantin Kaplinsky. All Rights Reserved.
* Copyright 2004-2005 Cendio AB.
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,32 +43,20 @@ namespace rfb {

#define PIXEL_T rdr::CONCAT2E(U,BPP)
#define READ_PIXEL CONCAT2E(readOpaque,BPP)
#define TIGHT_DECODE CONCAT2E(tightDecode,BPP)
#define TIGHT_DECODE TightDecoder::CONCAT2E(tightDecode,BPP)
#define DECOMPRESS_JPEG_RECT TightDecoder::CONCAT2E(DecompressJpegRect,BPP)
#define FILTER_GRADIENT TightDecoder::CONCAT2E(FilterGradient,BPP)
#define DIRECT_FILL_RECT TightDecoder::CONCAT2E(directFillRect,BPP)

#define TIGHT_MIN_TO_COMPRESS 12
static bool DecompressJpegRect(const Rect& r, rdr::InStream* is,
PIXEL_T* buf, CMsgHandler* handler);
static void FilterGradient(const Rect& r, rdr::InStream* is, int dataSize,
PIXEL_T* buf, CMsgHandler* handler);
#if BPP == 32
static void FilterGradient24(const Rect& r, rdr::InStream* is, int dataSize,
PIXEL_T* buf, CMsgHandler* handler);
#endif

// Main function implementing Tight decoder

void TIGHT_DECODE (const Rect& r, rdr::InStream* is,
rdr::ZlibInStream zis[], PIXEL_T* buf
#ifdef EXTRA_ARGS
, EXTRA_ARGS
#endif
)
void TIGHT_DECODE (const Rect& r)
{
rdr::U8 *bytebuf = (rdr::U8*) buf;
bool cutZeros = false;
const rfb::PixelFormat& myFormat = handler->cp.pf();
#if BPP == 32
if (myFormat.is888()) {
if (serverpf.is888()) {
cutZeros = true;
}
#endif
@@ -86,18 +75,20 @@ void TIGHT_DECODE (const Rect& r, rdr::InStream* is,
if (comp_ctl == rfbTightFill) {
PIXEL_T pix;
if (cutZeros) {
rdr::U8 bytebuf[3];
is->readBytes(bytebuf, 3);
myFormat.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1, NULL);
} else {
pix = is->READ_PIXEL();
}
FILL_RECT(r, pix);
if (directDecode) DIRECT_FILL_RECT(r, pix);
else FILL_RECT(r, pix);
return;
}

// "JPEG" compression type.
if (comp_ctl == rfbTightJpeg) {
DecompressJpegRect(r, is, buf, handler);
DECOMPRESS_JPEG_RECT(r);
return;
}

@@ -122,11 +113,11 @@ void TIGHT_DECODE (const Rect& r, rdr::InStream* is,
rdr::U8 elem[3];
for (int i = 0;i < palSize;i++) {
is->readBytes(elem, 3);
myFormat.bufferFromRGB((rdr::U8*)&palette[i], elem, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&palette[i], elem, 1, NULL);
}
} else {
for (int i = 0; i < palSize; i++)
palette[i] = is->READ_PIXEL();
for (int i = 0; i < palSize; i++)
palette[i] = is->READ_PIXEL();
}
break;
case rfbTightFilterGradient:
@@ -161,78 +152,93 @@ void TIGHT_DECODE (const Rect& r, rdr::InStream* is,
input = &zis[streamId];
}

PIXEL_T *buf;
int stride = r.width();
if (directDecode) buf = (PIXEL_T *)handler->getRawPixelsRW(r, &stride);
else buf = (PIXEL_T *)reader->getImageBuf(r.area());

if (palSize == 0) {
// Truecolor data
if (useGradient) {
#if BPP == 32
if (cutZeros) {
FilterGradient24(r, input, dataSize, buf, handler);
FilterGradient24(input, buf, stride, r, dataSize);
} else
#endif
{
FilterGradient(r, input, dataSize, buf, handler);
}
{
FILTER_GRADIENT(input, buf, stride, r, dataSize);
}
} else {
// Copy
int h = r.height();
PIXEL_T *ptr = buf;
if (cutZeros) {
int w = r.width(), pad = stride - w;
rdr::U8 elem[3];
for (int i = 0;i < r.area();i++) {
input->readBytes(elem, 3);
myFormat.bufferFromRGB((rdr::U8*)&buf[i], elem, 1, NULL);
while (h > 0) {
PIXEL_T *endOfRow = ptr + w;
while (ptr < endOfRow) {
input->readBytes(elem, 3);
serverpf.bufferFromRGB((rdr::U8*)ptr++, elem, 1, NULL);
}
ptr += pad;
h--;
}
} else {
input->readBytes(buf, dataSize);
while (h > 0) {
input->readBytes(ptr, rowSize);
ptr += stride;
h--;
}
}
}
} else {
int x, y, b;
// Indexed color
int x, h = r.height(), w = r.width(), b, pad = stride - w;
PIXEL_T *ptr = buf;
rdr::U8 bits;
if (palSize <= 2) {
// 2-color palette
for (y = 0; y < r.height(); y++) {
for (x = 0; x < r.width() / 8; x++) {
while (h > 0) {
for (x = 0; x < w / 8; x++) {
bits = input->readU8();
for (b = 7; b >= 0; b--) {
*ptr++ = palette[bits >> b & 1];
}
}
}
if (r.width() % 8 != 0) {
if (w % 8 != 0) {
bits = input->readU8();
for (b = 7; b >= 8 - r.width() % 8; b--) {
for (b = 7; b >= 8 - w % 8; b--) {
*ptr++ = palette[bits >> b & 1];
}
}
ptr += pad;
h--;
}
} else {
// 256-color palette
for (y = 0; y < r.height(); y++) {
for (x = 0; x < r.width(); x++) {
while (h > 0) {
PIXEL_T *endOfRow = ptr + w;
while (ptr < endOfRow) {
*ptr++ = palette[input->readU8()];
}
}
ptr += pad;
h--;
}
}
}

IMAGE_RECT(r, buf);
if (directDecode) handler->releaseRawPixels(r);
else IMAGE_RECT(r, buf);

if (streamId != -1) {
zis[streamId].reset();
}
}

static bool
DecompressJpegRect(const Rect& r, rdr::InStream* is,
PIXEL_T* buf, CMsgHandler* handler)
void
DECOMPRESS_JPEG_RECT(const Rect& r)
{
struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
int w = r.width();
int h = r.height();
int pixelsize;
rdr::U8 *dstBuf = NULL;
bool dstBufIsTemp = false;
const rfb::PixelFormat& pf = handler->cp.pf();

// Read length
int compressedLen = is->readCompactLength();
if (compressedLen <= 0) {
@@ -246,97 +252,21 @@ DecompressJpegRect(const Rect& r, rdr::InStream* is,
}
is->readBytes(netbuf, compressedLen);

// Set up JPEG decompression
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_decompress(&cinfo);
JpegSetSrcManager(&cinfo, (char*)netbuf, compressedLen);
jpeg_read_header(&cinfo, TRUE);
// We always use direct decoding with JPEG images
int stride;
rdr::U8 *buf = handler->getRawPixelsRW(r, &stride);
jd.decompress(netbuf, compressedLen, buf, stride * clientpf.bpp / 8, r,
clientpf);
handler->releaseRawPixels(r);

cinfo.out_color_space = JCS_RGB;
pixelsize = 3;

#ifdef JCS_EXTENSIONS
// Try to have libjpeg output directly to our native format
if (pf.is888()) {
int redShift, greenShift, blueShift;

if(pf.bigEndian) {
redShift = 24 - pf.redShift;
greenShift = 24 - pf.greenShift;
blueShift = 24 - pf.blueShift;
} else {
redShift = pf.redShift;
greenShift = pf.greenShift;
blueShift = pf.blueShift;
}

// libjpeg can only handle some "standard" formats
if(redShift == 0 && greenShift == 8 && blueShift == 16)
cinfo.out_color_space = JCS_EXT_RGBX;
if(redShift == 16 && greenShift == 8 && blueShift == 0)
cinfo.out_color_space = JCS_EXT_BGRX;
if(redShift == 24 && greenShift == 16 && blueShift == 8)
cinfo.out_color_space = JCS_EXT_XBGR;
if(redShift == 8 && greenShift == 16 && blueShift == 24)
cinfo.out_color_space = JCS_EXT_XRGB;

if (cinfo.out_color_space != JCS_RGB) {
dstBuf = (rdr::U8 *)buf;
pixelsize = 4;
}
}
#endif

if (cinfo.out_color_space == JCS_RGB) {
dstBuf = new rdr::U8[w * h * pixelsize];
dstBufIsTemp = true;
}

JSAMPROW *rowPointer = new JSAMPROW[h];
for (int dy = 0; dy < h; dy++)
rowPointer[dy] = (JSAMPROW)(&dstBuf[dy * w * pixelsize]);

jpeg_start_decompress(&cinfo);
if (cinfo.output_width != (unsigned)r.width() || cinfo.output_height != (unsigned)r.height() ||
cinfo.output_components != pixelsize) {
jpeg_destroy_decompress(&cinfo);
throw Exception("Tight Encoding: Wrong JPEG data received.\n");
}

// Decompress
const rfb::PixelFormat& myFormat = handler->cp.pf();
while (cinfo.output_scanline < cinfo.output_height) {
jpeg_read_scanlines(&cinfo, &rowPointer[cinfo.output_scanline],
cinfo.output_height - cinfo.output_scanline);
if (jpegError) {
break;
}
}

delete [] rowPointer;

if (cinfo.out_color_space == JCS_RGB)
myFormat.bufferFromRGB((rdr::U8*)buf, dstBuf, w * h);

IMAGE_RECT(r, buf);

if (!jpegError) {
jpeg_finish_decompress(&cinfo);
}

jpeg_destroy_decompress(&cinfo);

if (dstBufIsTemp) delete [] dstBuf;
delete [] netbuf;

return !jpegError;
}

#if BPP == 32

static void
FilterGradient24(const Rect& r, rdr::InStream* is, int dataSize,
PIXEL_T* buf, CMsgHandler* handler)
void
TightDecoder::FilterGradient24(rdr::InStream* is, PIXEL_T* buf, int stride,
const Rect& r, int dataSize)
{
int x, y, c;
static rdr::U8 prevRow[TIGHT_MAX_WIDTH*3];
@@ -354,7 +284,6 @@ FilterGradient24(const Rect& r, rdr::InStream* is, int dataSize,
is->readBytes(netbuf, dataSize);

// Set up shortcut variables
const rfb::PixelFormat& myFormat = handler->cp.pf();
int rectHeight = r.height();
int rectWidth = r.width();

@@ -364,21 +293,21 @@ FilterGradient24(const Rect& r, rdr::InStream* is, int dataSize,
pix[c] = netbuf[y*rectWidth*3+c] + prevRow[c];
thisRow[c] = pix[c];
}
myFormat.bufferFromRGB((rdr::U8*)&buf[y*rectWidth], pix, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL);

/* Remaining pixels of a row */
for (x = 1; x < rectWidth; x++) {
for (c = 0; c < 3; c++) {
est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
if (est[c] > 0xff) {
est[c] = 0xff;
} else if (est[c] < 0) {
est[c] = 0;
}
pix[c] = netbuf[(y*rectWidth+x)*3+c] + est[c];
thisRow[x*3+c] = pix[c];
est[c] = prevRow[x*3+c] + pix[c] - prevRow[(x-1)*3+c];
if (est[c] > 0xff) {
est[c] = 0xff;
} else if (est[c] < 0) {
est[c] = 0;
}
pix[c] = netbuf[(y*rectWidth+x)*3+c] + est[c];
thisRow[x*3+c] = pix[c];
}
myFormat.bufferFromRGB((rdr::U8*)&buf[y*rectWidth+x], pix, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL);
}

memcpy(prevRow, thisRow, sizeof(prevRow));
@@ -389,9 +318,9 @@ FilterGradient24(const Rect& r, rdr::InStream* is, int dataSize,

#endif

static void
FilterGradient(const Rect& r, rdr::InStream* is, int dataSize,
PIXEL_T* buf, CMsgHandler* handler)
void
FILTER_GRADIENT(rdr::InStream* is, PIXEL_T* buf, int stride, const Rect& r,
int dataSize)
{
int x, y, c;
static rdr::U8 prevRow[TIGHT_MAX_WIDTH*sizeof(PIXEL_T)];
@@ -409,19 +338,18 @@ FilterGradient(const Rect& r, rdr::InStream* is, int dataSize,
is->readBytes(netbuf, dataSize);

// Set up shortcut variables
const rfb::PixelFormat& myFormat = handler->cp.pf();
int rectHeight = r.height();
int rectWidth = r.width();

for (y = 0; y < rectHeight; y++) {
/* First pixel in a row */
myFormat.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1, NULL);
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1, NULL);
for (c = 0; c < 3; c++)
pix[c] += prevRow[c];

memcpy(thisRow, pix, sizeof(pix));

myFormat.bufferFromRGB((rdr::U8*)&buf[y*rectWidth], pix, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL);

/* Remaining pixels of a row */
for (x = 1; x < rectWidth; x++) {
@@ -434,13 +362,13 @@ FilterGradient(const Rect& r, rdr::InStream* is, int dataSize,
}
}

myFormat.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1, NULL);
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1, NULL);
for (c = 0; c < 3; c++)
pix[c] += est[c];

memcpy(&thisRow[x*3], pix, sizeof(pix));

myFormat.bufferFromRGB((rdr::U8*)&buf[y*rectWidth+x], pix, 1, NULL);
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL);
}

memcpy(prevRow, thisRow, sizeof(prevRow));
@@ -449,7 +377,39 @@ FilterGradient(const Rect& r, rdr::InStream* is, int dataSize,
delete [] netbuf;
}

void
DIRECT_FILL_RECT(const Rect& r, Pixel pix) {

int stride;
PIXEL_T *buf = (PIXEL_T *)handler->getRawPixelsRW(r, &stride);

int w = r.width(), h = r.height();
PIXEL_T *ptr = buf;
#if BPP != 8
int pad = stride - w;
#endif

while (h > 0) {
#if BPP == 8
memset(ptr, pix, w);
ptr += stride;
#else
PIXEL_T *endOfRow = ptr + w;
while (ptr < endOfRow) {
*ptr++ = pix;
}
ptr += pad;
#endif
h--;
}

handler->releaseRawPixels(r);
}

#undef TIGHT_MIN_TO_COMPRESS
#undef DIRECT_FILL_RECT
#undef FILTER_GRADIENT
#undef DECOMPRESS_JPEG_RECT
#undef TIGHT_DECODE
#undef READ_PIXEL
#undef PIXEL_T

+ 9
- 0
vncviewer/CConn.cxx View File

@@ -1,5 +1,6 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
* Copyright 2009-2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
* Copyright (C) 2011 D. R. Commander. All Rights Reserved.
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -411,6 +412,14 @@ void CConn::setCursor(int width, int height, const Point& hotspot,
desktop->setCursor(width, height, hotspot, data, mask);
}

rdr::U8* CConn::getRawPixelsRW(const rfb::Rect& r, int* stride) {
return desktop->getPixelsRW(r, stride);
}
void CConn::releaseRawPixels(const rfb::Rect& r) {
desktop->damageRect(r);
}


////////////////////// Internal methods //////////////////////

void CConn::resizeFramebuffer()

+ 5
- 0
vncviewer/CConn.h View File

@@ -67,6 +67,11 @@ public:
void imageRect(const rfb::Rect& r, void* p);
void copyRect(const rfb::Rect& r, int sx, int sy);

rdr::U8* getRawPixelsRW(const rfb::Rect& r, int* stride);
void releaseRawPixels(const rfb::Rect& r);

const rfb::PixelFormat &getPreferredPF() { return fullColourPF; }

void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);


+ 7
- 0
vncviewer/DesktopWindow.h View File

@@ -61,6 +61,13 @@ public:
viewport->copyRect(r, srcX, srcY);
}

rdr::U8* getPixelsRW(const rfb::Rect& r, int* stride) {
return viewport->getPixelsRW(r, stride);
}
void damageRect(const rfb::Rect& r) {
viewport->damageRect(r);
}

void resizeFramebuffer(int new_w, int new_h);

void setCursor(int width, int height, const rfb::Point& hotspot,

+ 10
- 6
vncviewer/Viewport.h View File

@@ -97,6 +97,16 @@ public:
damageRect(r);
}

rdr::U8* getPixelsRW(const rfb::Rect& r, int* stride) {
return frameBuffer->getPixelsRW(r, stride);
}

void damageRect(const rfb::Rect& r) {
damage.assign_union(rfb::Region(r));
if (!Fl::has_timeout(handleUpdateTimeout, this))
Fl::add_timeout(0.500, handleUpdateTimeout, this);
};

void setCursor(int width, int height, const rfb::Point& hotspot,
void* data, void* mask);

@@ -110,12 +120,6 @@ public:

private:

void damageRect(const rfb::Rect& r) {
damage.assign_union(rfb::Region(r));
if (!Fl::has_timeout(handleUpdateTimeout, this))
Fl::add_timeout(0.500, handleUpdateTimeout, this);
};

static void handleUpdateTimeout(void *data);

void commitColourMap();

Loading…
Cancel
Save