Gets rid of a loooot of code and complexity. Colour map clients are still supported through an automatically generated map, but we lose the ability to develop a client or server that uses colour maps internally.tags/v1.3.90
@@ -1,96 +0,0 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. 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 | |||
* 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. | |||
*/ | |||
// | |||
// ColourCube - structure to represent a colour cube. The colour cube consists | |||
// of its dimensions (nRed x nGreen x nBlue) and a table mapping an (r,g,b) | |||
// triple to a pixel value. | |||
// | |||
// A colour cube is used in two cases. The first is internally in a viewer | |||
// when it cannot use a trueColour format, nor can it have exclusive access to | |||
// a writable colour map. This is most notably the case for an X viewer | |||
// wishing to use a PseudoColor X server's default colormap. | |||
// | |||
// The second use is on the server side when a client has asked for a colour | |||
// map and the server is trueColour. Instead of setting an uneven trueColour | |||
// format like bgr233, it can set the client's colour map up with a 6x6x6 | |||
// colour cube. For this use the colour cube table has a null mapping, which | |||
// makes it easy to perform the reverse lookup operation from pixel value to | |||
// r,g,b values. | |||
#ifndef __RFB_COLOURCUBE_H__ | |||
#define __RFB_COLOURCUBE_H__ | |||
#include <rfb/Pixel.h> | |||
#include <rfb/ColourMap.h> | |||
namespace rfb { | |||
class ColourCube : public ColourMap { | |||
public: | |||
ColourCube(int nr, int ng, int nb, Pixel* table_=0) | |||
: nRed(nr), nGreen(ng), nBlue(nb), table(table_), deleteTable(false) | |||
{ | |||
if (!table) { | |||
table = new Pixel[size()]; | |||
deleteTable = true; | |||
// set a null mapping by default | |||
for (int i = 0; i < size(); i++) | |||
table[i] = i; | |||
} | |||
} | |||
ColourCube() : deleteTable(false) {} | |||
virtual ~ColourCube() { | |||
if (deleteTable) delete [] table; | |||
} | |||
void set(int r, int g, int b, Pixel p) { | |||
table[(r * nGreen + g) * nBlue + b] = p; | |||
} | |||
Pixel lookup(int r, int g, int b) const { | |||
return table[(r * nGreen + g) * nBlue + b]; | |||
} | |||
int size() const { return nRed*nGreen*nBlue; } | |||
int redMult() const { return nGreen*nBlue; } | |||
int greenMult() const { return nBlue; } | |||
int blueMult() const { return 1; } | |||
// ColourMap lookup() method. Note that this only works when the table has | |||
// the default null mapping. | |||
virtual void lookup(int i, int* r, int* g, int* b) { | |||
if (i >= size()) return; | |||
*b = i % nBlue; | |||
i /= nBlue; | |||
*g = i % nGreen; | |||
*r = i / nGreen; | |||
*r = (*r * 65535 + (nRed-1) / 2) / (nRed-1); | |||
*g = (*g * 65535 + (nGreen-1) / 2) / (nGreen-1); | |||
*b = (*b * 65535 + (nBlue-1) / 2) / (nBlue-1); | |||
} | |||
int nRed; | |||
int nGreen; | |||
int nBlue; | |||
Pixel* table; | |||
bool deleteTable; | |||
}; | |||
} | |||
#endif |
@@ -1,51 +0,0 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. | |||
* Copyright 2011 Pierre Ossman <ossman@cendio.se> 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_COLOURMAP_H__ | |||
#define __RFB_COLOURMAP_H__ | |||
namespace rfb { | |||
struct Colour { | |||
Colour() : r(0), g(0), b(0) {} | |||
Colour(int r_, int g_, int b_) : r(r_), g(g_), b(b_) {} | |||
int r, g, b; | |||
bool operator==(const Colour& c) const {return c.r == r && c.g == g && c.b == b;} | |||
bool operator!=(const Colour& c) const {return !(c == *this);} | |||
}; | |||
class ColourMap { | |||
public: | |||
virtual void lookup(int index, int* r, int* g, int* b)=0; | |||
virtual ~ColourMap() {} | |||
}; | |||
class SimpleColourMap : public ColourMap { | |||
public: | |||
SimpleColourMap(int size = 256) { table = new Colour[size]; }; | |||
virtual ~SimpleColourMap() { delete [] table; }; | |||
void lookup(int index, int* r, int* g, int* b) | |||
{ *r = table[index].r; *g = table[index].g; *b = table[index].b; }; | |||
void set(int index, int r, int g, int b) | |||
{ table[index].r = r; table[index].g = g; table[index].b = b; }; | |||
protected: | |||
Colour *table; | |||
}; | |||
} | |||
#endif |
@@ -33,16 +33,15 @@ static LogWriter vlog("PixelBuffer"); | |||
// -=- Generic pixel buffer class | |||
PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h, ColourMap* cm) | |||
: format(pf), width_(w), height_(h), colourmap(cm) {} | |||
PixelBuffer::PixelBuffer() : width_(0), height_(0), colourmap(0) {} | |||
PixelBuffer::PixelBuffer(const PixelFormat& pf, int w, int h) | |||
: format(pf), width_(w), height_(h) {} | |||
PixelBuffer::PixelBuffer() : width_(0), height_(0) {} | |||
PixelBuffer::~PixelBuffer() {} | |||
void PixelBuffer::setPF(const PixelFormat &pf) {format = pf;} | |||
const PixelFormat& PixelBuffer::getPF() const {return format;} | |||
ColourMap* PixelBuffer::getColourMap() const {return colourmap;} | |||
void | |||
@@ -117,8 +116,8 @@ static void fillRect32(U8 *buf, int stride, const Rect& r, Pixel pix) | |||
FullFramePixelBuffer::FullFramePixelBuffer(const PixelFormat& pf, int w, int h, | |||
rdr::U8* data_, ColourMap* cm) | |||
: PixelBuffer(pf, w, h, cm), data(data_) | |||
rdr::U8* data_) | |||
: PixelBuffer(pf, w, h), data(data_) | |||
{ | |||
// Called again to configure the fill function | |||
setPF(pf); | |||
@@ -314,20 +313,19 @@ void FullFramePixelBuffer::copyRect(const Rect &rect, const Point &move_by_delta | |||
// Automatically allocates enough space for the specified format & area | |||
ManagedPixelBuffer::ManagedPixelBuffer() | |||
: datasize(0), own_colourmap(false) | |||
: datasize(0) | |||
{ | |||
checkDataSize(); | |||
}; | |||
ManagedPixelBuffer::ManagedPixelBuffer(const PixelFormat& pf, int w, int h) | |||
: FullFramePixelBuffer(pf, w, h, 0, 0), datasize(0), own_colourmap(false) | |||
: FullFramePixelBuffer(pf, w, h, 0), datasize(0) | |||
{ | |||
checkDataSize(); | |||
}; | |||
ManagedPixelBuffer::~ManagedPixelBuffer() { | |||
if (data) delete [] data; | |||
if (colourmap && own_colourmap) delete colourmap; | |||
}; | |||
@@ -341,13 +339,6 @@ ManagedPixelBuffer::setSize(int w, int h) { | |||
}; | |||
void | |||
ManagedPixelBuffer::setColourMap(ColourMap* cm, bool own_cm) { | |||
if (colourmap && own_colourmap) delete colourmap; | |||
colourmap = cm; | |||
own_colourmap = own_cm; | |||
} | |||
inline void | |||
ManagedPixelBuffer::checkDataSize() { | |||
unsigned long new_datasize = width_ * height_ * (format.bpp/8); |
@@ -26,7 +26,6 @@ | |||
#include <rfb/ImageGetter.h> | |||
#include <rfb/PixelFormat.h> | |||
#include <rfb/ColourMap.h> | |||
#include <rfb/Rect.h> | |||
#include <rfb/Pixel.h> | |||
@@ -36,7 +35,7 @@ namespace rfb { | |||
class PixelBuffer : public ImageGetter { | |||
public: | |||
PixelBuffer(const PixelFormat& pf, int width, int height, ColourMap* cm); | |||
PixelBuffer(const PixelFormat& pf, int width, int height); | |||
virtual ~PixelBuffer(); | |||
/////////////////////////////////////////////// | |||
@@ -49,7 +48,6 @@ namespace rfb { | |||
virtual void setPF(const PixelFormat &pf); | |||
public: | |||
virtual const PixelFormat &getPF() const; | |||
virtual ColourMap* getColourMap() const; | |||
// Get width, height and number of pixels | |||
int width() const { return width_; } | |||
@@ -91,7 +89,6 @@ namespace rfb { | |||
PixelBuffer(); | |||
PixelFormat format; | |||
int width_, height_; | |||
ColourMap* colourmap; | |||
}; | |||
// FullFramePixelBuffer | |||
@@ -99,7 +96,7 @@ namespace rfb { | |||
class FullFramePixelBuffer : public PixelBuffer { | |||
public: | |||
FullFramePixelBuffer(const PixelFormat& pf, int width, int height, | |||
rdr::U8* data_, ColourMap* cm); | |||
rdr::U8* data_); | |||
virtual ~FullFramePixelBuffer(); | |||
protected: | |||
@@ -160,15 +157,11 @@ namespace rfb { | |||
virtual void setPF(const PixelFormat &pf); | |||
virtual void setSize(int w, int h); | |||
// Assign a colour map to the buffer | |||
virtual void setColourMap(ColourMap* cm, bool own_cm); | |||
// Return the total number of bytes of pixel data in the buffer | |||
int dataLen() const { return width_ * height_ * (format.bpp/8); } | |||
protected: | |||
unsigned long datasize; | |||
bool own_colourmap; | |||
void checkDataSize(); | |||
}; | |||
@@ -53,16 +53,51 @@ PixelFormat::PixelFormat() | |||
bool PixelFormat::equal(const PixelFormat& other) const | |||
{ | |||
return (bpp == other.bpp && | |||
depth == other.depth && | |||
(bigEndian == other.bigEndian || bpp == 8) && | |||
trueColour == other.trueColour && | |||
(!trueColour || (redMax == other.redMax && | |||
greenMax == other.greenMax && | |||
blueMax == other.blueMax && | |||
redShift == other.redShift && | |||
greenShift == other.greenShift && | |||
blueShift == other.blueShift))); | |||
if (bpp != other.bpp || depth != other.depth) | |||
return false; | |||
if (redMax != other.redMax) | |||
return false; | |||
if (greenMax != other.greenMax) | |||
return false; | |||
if (blueMax != other.blueMax) | |||
return false; | |||
// Endianness requires more care to determine compatibility | |||
if (bigEndian == other.bigEndian || bpp == 8) { | |||
if (redShift != other.redShift) | |||
return false; | |||
if (greenShift != other.greenShift) | |||
return false; | |||
if (blueShift != other.blueShift) | |||
return false; | |||
} else { | |||
// Has to be the same byte for each channel | |||
if (redShift/8 != (3 - other.redShift/8)) | |||
return false; | |||
if (greenShift/8 != (3 - other.greenShift/8)) | |||
return false; | |||
if (blueShift/8 != (3 - other.blueShift/8)) | |||
return false; | |||
// And the same bit offset within the byte | |||
if (redShift%8 != other.redShift%8) | |||
return false; | |||
if (greenShift%8 != other.greenShift%8) | |||
return false; | |||
if (blueShift%8 != other.blueShift%8) | |||
return false; | |||
// And not cross a byte boundary | |||
if (redShift/8 != (redShift + redBits - 1)/8) | |||
return false; | |||
if (greenShift/8 != (greenShift + greenBits - 1)/8) | |||
return false; | |||
if (blueShift/8 != (blueShift + blueBits - 1)/8) | |||
return false; | |||
} | |||
return true; | |||
} | |||
void PixelFormat::read(rdr::InStream* is) | |||
@@ -79,6 +114,18 @@ void PixelFormat::read(rdr::InStream* is) | |||
blueShift = is->readU8(); | |||
is->skip(3); | |||
// We have no real support for colour maps. If the client | |||
// wants one, then we force a 8-bit true colour format and | |||
// pretend it's a colour map. | |||
if (!trueColour) { | |||
redMax = 7; | |||
greenMax = 7; | |||
blueMax = 3; | |||
redShift = 0; | |||
greenShift = 3; | |||
blueShift = 6; | |||
} | |||
if (!isSane()) | |||
throw Exception("invalid pixel format"); | |||
@@ -132,14 +179,13 @@ bool PixelFormat::isLittleEndian(void) const | |||
} | |||
void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, | |||
int pixels, ColourMap* cm) const | |||
void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const | |||
{ | |||
bufferFromRGB(dst, src, pixels, pixels, 1, cm); | |||
bufferFromRGB(dst, src, pixels, pixels, 1); | |||
} | |||
void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, | |||
int w, int stride, int h, ColourMap* cm) const | |||
int w, int stride, int h) const | |||
{ | |||
if (is888()) { | |||
// Optimised common case | |||
@@ -188,7 +234,7 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, | |||
g = *(src++); | |||
b = *(src++); | |||
p = pixelFromRGB(r, g, b, cm); | |||
p = pixelFromRGB(r, g, b); | |||
bufferFromPixel(dst, p); | |||
dst += bpp/8; | |||
@@ -199,26 +245,14 @@ void PixelFormat::bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, | |||
} | |||
void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, Colour* rgb) const | |||
{ | |||
rdr::U16 r, g, b; | |||
rgbFromPixel(p, cm, &r, &g, &b); | |||
rgb->r = r; | |||
rgb->g = g; | |||
rgb->b = b; | |||
} | |||
void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm) const | |||
void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const | |||
{ | |||
rgbFromBuffer(dst, src, pixels, pixels, 1, cm); | |||
rgbFromBuffer(dst, src, pixels, pixels, 1); | |||
} | |||
void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, | |||
int w, int stride, int h, ColourMap* cm) const | |||
int w, int stride, int h) const | |||
{ | |||
if (is888()) { | |||
// Optimised common case | |||
@@ -260,7 +294,7 @@ void PixelFormat::rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, | |||
p = pixelFromBuffer(src); | |||
rgbFromPixel(p, cm, &r, &g, &b); | |||
rgbFromPixel(p, &r, &g, &b); | |||
*(dst++) = r; | |||
*(dst++) = g; | |||
@@ -449,36 +483,34 @@ bool PixelFormat::isSane(void) | |||
if (!trueColour && (depth != 8)) | |||
return false; | |||
if (trueColour) { | |||
if ((redMax & (redMax + 1)) != 0) | |||
return false; | |||
if ((greenMax & (greenMax + 1)) != 0) | |||
return false; | |||
if ((blueMax & (blueMax + 1)) != 0) | |||
return false; | |||
if ((redMax & (redMax + 1)) != 0) | |||
return false; | |||
if ((greenMax & (greenMax + 1)) != 0) | |||
return false; | |||
if ((blueMax & (blueMax + 1)) != 0) | |||
return false; | |||
/* | |||
* We don't allow individual channels > 8 bits in order to keep our | |||
* conversions simple. | |||
*/ | |||
if (redMax >= (1 << 8)) | |||
return false; | |||
if (greenMax >= (1 << 8)) | |||
return false; | |||
if (blueMax >= (1 << 8)) | |||
return false; | |||
/* | |||
* We don't allow individual channels > 8 bits in order to keep our | |||
* conversions simple. | |||
*/ | |||
if (redMax >= (1 << 8)) | |||
return false; | |||
if (greenMax >= (1 << 8)) | |||
return false; | |||
if (blueMax >= (1 << 8)) | |||
return false; | |||
totalBits = bits(redMax) + bits(greenMax) + bits(blueMax); | |||
if (totalBits > bpp) | |||
return false; | |||
totalBits = bits(redMax) + bits(greenMax) + bits(blueMax); | |||
if (totalBits > bpp) | |||
return false; | |||
if (((redMax << redShift) & (greenMax << greenShift)) != 0) | |||
return false; | |||
if (((redMax << redShift) & (blueMax << blueShift)) != 0) | |||
return false; | |||
if (((greenMax << greenShift) & (blueMax << blueShift)) != 0) | |||
return false; | |||
} | |||
if (((redMax << redShift) & (greenMax << greenShift)) != 0) | |||
return false; | |||
if (((redMax << redShift) & (blueMax << blueShift)) != 0) | |||
return false; | |||
if (((greenMax << greenShift) & (blueMax << blueShift)) != 0) | |||
return false; | |||
return true; | |||
} |
@@ -35,7 +35,6 @@ | |||
#define __RFB_PIXELFORMAT_H__ | |||
#include <rfb/Pixel.h> | |||
#include <rfb/ColourMap.h> | |||
namespace rdr { class InStream; class OutStream; } | |||
@@ -44,9 +43,12 @@ namespace rfb { | |||
class PixelFormat { | |||
public: | |||
PixelFormat(int b, int d, bool e, bool t, | |||
int rm=0, int gm=0, int bm=0, int rs=0, int gs=0, int bs=0); | |||
int rm, int gm, int bm, int rs, int gs, int bs); | |||
PixelFormat(); | |||
// Checks if the formats have identical buffer representation. | |||
// They might still have different pixel representation, endianness | |||
// or true colour state. | |||
bool equal(const PixelFormat& other) const; | |||
void read(rdr::InStream* is); | |||
@@ -59,20 +61,19 @@ namespace rfb { | |||
inline Pixel pixelFromBuffer(const rdr::U8* buffer) const; | |||
inline void bufferFromPixel(rdr::U8* buffer, Pixel pixel) const; | |||
inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm=0) const; | |||
inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm=0) const; | |||
inline Pixel pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const; | |||
inline Pixel pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) 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 stride, | |||
int h, ColourMap* cm=0) const; | |||
void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, int pixels) const; | |||
void bufferFromRGB(rdr::U8 *dst, const rdr::U8* src, | |||
int w, int stride, int h) 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; | |||
inline void rgbFromPixel(Pixel pix, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const; | |||
inline void rgbFromPixel(Pixel pix, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const; | |||
inline void rgbFromPixel(Pixel pix, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const; | |||
void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels, ColourMap* cm=0) const; | |||
void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int w, int stride, | |||
int h, ColourMap* cm=0) const; | |||
void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, int pixels) const; | |||
void rgbFromBuffer(rdr::U8* dst, const rdr::U8* src, | |||
int w, int stride, int h) const; | |||
void print(char* str, int len) const; | |||
bool parse(const char* str); | |||
@@ -84,6 +85,9 @@ namespace rfb { | |||
public: | |||
int bpp; | |||
int depth; | |||
// This only tracks if the client thinks it is in colour map mode. | |||
// In practice we are always in true colour mode. | |||
bool trueColour; | |||
// FIXME: These should be protected, but we need to fix TransImageGetter first. |
@@ -75,131 +75,81 @@ inline void PixelFormat::bufferFromPixel(rdr::U8* buffer, Pixel p) const | |||
} | |||
inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue, ColourMap* cm) const | |||
inline Pixel PixelFormat::pixelFromRGB(rdr::U16 red, rdr::U16 green, rdr::U16 blue) const | |||
{ | |||
if (trueColour) { | |||
Pixel p; | |||
/* We don't need to mask since we shift out unwanted bits */ | |||
p = ((Pixel)red >> (16 - redBits)) << redShift; | |||
p |= ((Pixel)green >> (16 - greenBits)) << greenShift; | |||
p |= ((Pixel)blue >> (16 - blueBits)) << blueShift; | |||
} else if (cm) { | |||
// Try to find the closest pixel by Cartesian distance | |||
int colours = 1 << depth; | |||
int diff = 256 * 256 * 4; | |||
int col = 0; | |||
for (int i=0; i<colours; i++) { | |||
int r, g, b; | |||
cm->lookup(i, &r, &g, &b); | |||
int rd = (r-red) >> 8; | |||
int gd = (g-green) >> 8; | |||
int bd = (b-blue) >> 8; | |||
int d = rd*rd + gd*gd + bd*bd; | |||
if (d < diff) { | |||
col = i; | |||
diff = d; | |||
} | |||
} | |||
return col; | |||
} else { | |||
// XXX just return 0 for colour map? | |||
return 0; | |||
} | |||
Pixel p; | |||
/* We don't need to mask since we shift out unwanted bits */ | |||
p = ((Pixel)red >> (16 - redBits)) << redShift; | |||
p |= ((Pixel)green >> (16 - greenBits)) << greenShift; | |||
p |= ((Pixel)blue >> (16 - blueBits)) << blueShift; | |||
return p; | |||
} | |||
inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue, ColourMap* cm) const | |||
inline Pixel PixelFormat::pixelFromRGB(rdr::U8 red, rdr::U8 green, rdr::U8 blue) const | |||
{ | |||
if (trueColour) { | |||
Pixel p; | |||
Pixel p; | |||
p = ((Pixel)red >> (8 - redBits)) << redShift; | |||
p |= ((Pixel)green >> (8 - greenBits)) << greenShift; | |||
p |= ((Pixel)blue >> (8 - blueBits)) << blueShift; | |||
p = ((Pixel)red >> (8 - redBits)) << redShift; | |||
p |= ((Pixel)green >> (8 - greenBits)) << greenShift; | |||
p |= ((Pixel)blue >> (8 - blueBits)) << blueShift; | |||
return p; | |||
} else { | |||
return pixelFromRGB((rdr::U16)(red << 8 | red), | |||
(rdr::U16)(green << 8 | green), | |||
(rdr::U16)(blue << 8 | blue), cm); | |||
} | |||
return p; | |||
} | |||
inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const | |||
inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U16 *r, rdr::U16 *g, rdr::U16 *b) const | |||
{ | |||
if (trueColour) { | |||
int mb, rb, gb, bb; | |||
/* Bit replication is much cheaper than multiplication and division */ | |||
mb = minBits; | |||
rb = redBits; | |||
gb = greenBits; | |||
bb = blueBits; | |||
*r = (p >> redShift) << (16 - rb); | |||
*g = (p >> greenShift) << (16 - gb); | |||
*b = (p >> blueShift) << (16 - bb); | |||
while (mb < 16) { | |||
*r = *r | (*r >> rb); | |||
*g = *g | (*g >> gb); | |||
*b = *b | (*b >> bb); | |||
mb <<= 1; | |||
rb <<= 1; | |||
gb <<= 1; | |||
bb <<= 1; | |||
} | |||
} else if (cm) { | |||
int ir, ig, ib; | |||
cm->lookup(p, &ir, &ig, &ib); | |||
*r = ir; | |||
*g = ig; | |||
*b = ib; | |||
} else { | |||
// XXX just return 0 for colour map? | |||
*r = 0; | |||
*g = 0; | |||
*b = 0; | |||
int mb, rb, gb, bb; | |||
/* Bit replication is much cheaper than multiplication and division */ | |||
mb = minBits; | |||
rb = redBits; | |||
gb = greenBits; | |||
bb = blueBits; | |||
*r = (p >> redShift) << (16 - rb); | |||
*g = (p >> greenShift) << (16 - gb); | |||
*b = (p >> blueShift) << (16 - bb); | |||
while (mb < 16) { | |||
*r = *r | (*r >> rb); | |||
*g = *g | (*g >> gb); | |||
*b = *b | (*b >> bb); | |||
mb <<= 1; | |||
rb <<= 1; | |||
gb <<= 1; | |||
bb <<= 1; | |||
} | |||
} | |||
inline void PixelFormat::rgbFromPixel(Pixel p, ColourMap* cm, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const | |||
inline void PixelFormat::rgbFromPixel(Pixel p, rdr::U8 *r, rdr::U8 *g, rdr::U8 *b) const | |||
{ | |||
if (trueColour) { | |||
int mb, rb, gb, bb; | |||
/* Bit replication is much cheaper than multiplication and division */ | |||
mb = minBits; | |||
rb = redBits; | |||
gb = greenBits; | |||
bb = blueBits; | |||
*r = (p >> redShift) << (8 - rb); | |||
*g = (p >> greenShift) << (8 - gb); | |||
*b = (p >> blueShift) << (8 - bb); | |||
while (mb < 8) { | |||
*r = *r | (*r >> rb); | |||
*g = *g | (*g >> gb); | |||
*b = *b | (*b >> bb); | |||
mb <<= 1; | |||
rb <<= 1; | |||
gb <<= 1; | |||
bb <<= 1; | |||
} | |||
} else { | |||
rdr::U16 r2, g2, b2; | |||
rgbFromPixel(p, cm, &r2, &g2, &b2); | |||
*r = r2 >> 8; | |||
*g = g2 >> 8; | |||
*b = b2 >> 8; | |||
int mb, rb, gb, bb; | |||
/* Bit replication is much cheaper than multiplication and division */ | |||
mb = minBits; | |||
rb = redBits; | |||
gb = greenBits; | |||
bb = blueBits; | |||
*r = (p >> redShift) << (8 - rb); | |||
*g = (p >> greenShift) << (8 - gb); | |||
*b = (p >> blueShift) << (8 - bb); | |||
while (mb < 8) { | |||
*r = *r | (*r >> rb); | |||
*g = *g | (*g >> gb); | |||
*b = *b | (*b >> bb); | |||
mb <<= 1; | |||
rb <<= 1; | |||
gb <<= 1; | |||
bb <<= 1; | |||
} | |||
} | |||
@@ -22,10 +22,7 @@ | |||
#include <string.h> | |||
#include <rfb/PixelFormat.h> | |||
#include <rfb/Exception.h> | |||
#include <rfb/ColourMap.h> | |||
#include <rfb/TrueColourMap.h> | |||
#include <rfb/PixelBuffer.h> | |||
#include <rfb/ColourCube.h> | |||
#include <rfb/PixelTransformer.h> | |||
using namespace rfb; | |||
@@ -100,50 +97,23 @@ static transFnType transRGBFns[][3] = { | |||
{ transRGB16to8, transRGB16to16, transRGB16to32 }, | |||
{ transRGB32to8, transRGB32to16, transRGB32to32 } | |||
}; | |||
static transFnType transRGBCubeFns[][3] = { | |||
{ transRGBCube16to8, transRGBCube16to16, transRGBCube16to32 }, | |||
{ transRGBCube32to8, transRGBCube32to16, transRGBCube32to32 } | |||
}; | |||
// Table initialisation functions. | |||
typedef void (*initCMtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourMap* cm, const PixelFormat& outPF); | |||
typedef void (*initTCtoTCFnType)(rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF); | |||
typedef void (*initCMtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourMap* cm, ColourCube* cube); | |||
typedef void (*initTCtoCubeFnType)(rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourCube* cube); | |||
typedef void (*initFnType)(rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF); | |||
static initCMtoTCFnType initSimpleCMtoTCFns[] = { | |||
initSimpleCMtoTC8, initSimpleCMtoTC16, initSimpleCMtoTC32 | |||
static initFnType initSimpleFns[] = { | |||
initSimple8, initSimple16, initSimple32 | |||
}; | |||
static initTCtoTCFnType initSimpleTCtoTCFns[] = { | |||
initSimpleTCtoTC8, initSimpleTCtoTC16, initSimpleTCtoTC32 | |||
}; | |||
static initCMtoCubeFnType initSimpleCMtoCubeFns[] = { | |||
initSimpleCMtoCube8, initSimpleCMtoCube16, initSimpleCMtoCube32 | |||
}; | |||
static initTCtoCubeFnType initSimpleTCtoCubeFns[] = { | |||
initSimpleTCtoCube8, initSimpleTCtoCube16, initSimpleTCtoCube32 | |||
}; | |||
static initTCtoTCFnType initRGBTCtoTCFns[] = { | |||
initRGBTCtoTC8, initRGBTCtoTC16, initRGBTCtoTC32 | |||
}; | |||
static initTCtoCubeFnType initRGBTCtoCubeFns[] = { | |||
initRGBTCtoCube8, initRGBTCtoCube16, initRGBTCtoCube32 | |||
static initFnType initRGBFns[] = { | |||
initRGB8, initRGB16, initRGB32 | |||
}; | |||
PixelTransformer::PixelTransformer(bool econ) | |||
: economic(econ), cmCallback(0), cube(0), table(0), transFn(0) | |||
: economic(econ), table(0), transFn(0) | |||
{ | |||
} | |||
@@ -152,17 +122,11 @@ PixelTransformer::~PixelTransformer() | |||
delete [] table; | |||
} | |||
void PixelTransformer::init(const PixelFormat& inPF_, ColourMap* inCM_, | |||
const PixelFormat& outPF_, ColourCube* cube_, | |||
setCMFnType cmCallback_, void *cbData_) | |||
void PixelTransformer::init(const PixelFormat& inPF_, | |||
const PixelFormat& outPF_) | |||
{ | |||
inPF = inPF_; | |||
inCM = inCM_; | |||
outPF = outPF_; | |||
cube = cube_; | |||
cmCallback = cmCallback_; | |||
cbData = cbData_; | |||
if (table) | |||
delete [] table; | |||
@@ -175,79 +139,17 @@ void PixelTransformer::init(const PixelFormat& inPF_, ColourMap* inCM_, | |||
if ((outPF.bpp != 8) && (outPF.bpp != 16) && (outPF.bpp != 32)) | |||
throw Exception("PixelTransformer: bpp out not 8, 16 or 32"); | |||
if (!outPF.trueColour) { | |||
if (outPF.bpp != 8) | |||
throw Exception("PixelTransformer: outPF has color map but not 8bpp"); | |||
if (!inPF.trueColour) { | |||
if (inPF.bpp != 8) | |||
throw Exception("PixelTransformer: inPF has colorMap but not 8bpp"); | |||
if (!inCM) | |||
throw Exception("PixelTransformer: inPF has colorMap but no colour map specified"); | |||
// CM to CM/Cube | |||
if (cube) { | |||
transFn = transSimpleFns[0][0]; | |||
(*initSimpleCMtoCubeFns[0]) (&table, inPF, inCM, cube); | |||
} else { | |||
transFn = noTransFn; | |||
setColourMapEntries(0, 256); | |||
} | |||
return; | |||
} | |||
// TC to CM/Cube | |||
ColourCube defaultCube(6,6,6); | |||
if (!cube) cube = &defaultCube; | |||
if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) { | |||
transFn = transRGBCubeFns[inPF.bpp/32][0]; | |||
(*initRGBTCtoCubeFns[0]) (&table, inPF, cube); | |||
} else { | |||
transFn = transSimpleFns[inPF.bpp/16][0]; | |||
(*initSimpleTCtoCubeFns[0]) (&table, inPF, cube); | |||
} | |||
if (cube != &defaultCube) | |||
return; | |||
if (!cmCallback) | |||
throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided"); | |||
cmCallback(0, 216, cube, cbData); | |||
cube = 0; | |||
return; | |||
} | |||
if (inPF.equal(outPF)) { | |||
transFn = noTransFn; | |||
return; | |||
} | |||
if (!inPF.trueColour) { | |||
// CM to TC | |||
if (inPF.bpp != 8) | |||
throw Exception("PixelTransformer: inPF has colorMap but not 8bpp"); | |||
if (!inCM) | |||
throw Exception("PixelTransformer: inPF has colorMap but no colour map specified"); | |||
transFn = transSimpleFns[0][outPF.bpp/16]; | |||
(*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF); | |||
return; | |||
} | |||
// TC to TC | |||
if ((inPF.bpp > 16) || (economic && (inPF.bpp == 16))) { | |||
transFn = transRGBFns[inPF.bpp/32][outPF.bpp/16]; | |||
(*initRGBTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF); | |||
(*initRGBFns[outPF.bpp/16]) (&table, inPF, outPF); | |||
} else { | |||
transFn = transSimpleFns[inPF.bpp/16][outPF.bpp/16]; | |||
(*initSimpleTCtoTCFns[outPF.bpp/16]) (&table, inPF, outPF); | |||
(*initSimpleFns[outPF.bpp/16]) (&table, inPF, outPF); | |||
} | |||
} | |||
@@ -256,39 +158,11 @@ const PixelFormat &PixelTransformer::getInPF() const | |||
return inPF; | |||
} | |||
const ColourMap *PixelTransformer::getInColourMap() const | |||
{ | |||
return inCM; | |||
} | |||
const PixelFormat &PixelTransformer::getOutPF() const | |||
{ | |||
return outPF; | |||
} | |||
const ColourCube *PixelTransformer::getOutColourCube() const | |||
{ | |||
return cube; | |||
} | |||
void PixelTransformer::setColourMapEntries(int firstCol, int nCols) | |||
{ | |||
if (nCols == 0) | |||
nCols = (1 << inPF.depth) - firstCol; | |||
if (inPF.trueColour) return; // shouldn't be called in this case | |||
if (outPF.trueColour) { | |||
(*initSimpleCMtoTCFns[outPF.bpp/16]) (&table, inPF, inCM, outPF); | |||
} else if (cube) { | |||
(*initSimpleCMtoCubeFns[outPF.bpp/16]) (&table, inPF, inCM, cube); | |||
} else { | |||
if (!cmCallback) | |||
throw Exception("PixelTransformer: Neither colour map callback nor colour cube provided"); | |||
cmCallback(firstCol, nCols, inCM, cbData); | |||
} | |||
} | |||
void PixelTransformer::translatePixels(const void* inPtr, void* outPtr, | |||
int nPixels) const | |||
{ |
@@ -33,11 +33,7 @@ namespace rfb { | |||
int outStride, int width, int height); | |||
class SMsgWriter; | |||
class ColourMap; | |||
class PixelBuffer; | |||
class ColourCube; | |||
typedef void (*setCMFnType)(int firstColour, int nColours, ColourMap* cm, void* data); | |||
class PixelTransformer { | |||
public: | |||
@@ -47,32 +43,12 @@ namespace rfb { | |||
// init() is called to initialise the translation tables. The inPF and | |||
// inCM arguments give the source format details, outPF gives the | |||
// target pixel format. If the target has a colour map, then the you | |||
// must specify either a colour map callback or a colour cube to indicate | |||
// how the target colour map should be handled. If both are specified | |||
// then the cube will be used. | |||
// target pixel format. | |||
void init(const PixelFormat& inPF, ColourMap* inCM, | |||
const PixelFormat& outPF, ColourCube* cube = NULL, | |||
setCMFnType cmCallback = NULL, void *cbData = NULL); | |||
void init(const PixelFormat& inPF, const PixelFormat& outPF); | |||
const PixelFormat &getInPF() const; | |||
const ColourMap *getInColourMap() const; | |||
const PixelFormat &getOutPF() const; | |||
const ColourCube *getOutColourCube() const; | |||
// setColourMapEntries() is called when the colour map specified to init() | |||
// has changed. firstColour and nColours specify which part of the | |||
// colour map has changed. If nColours is 0, this means the rest of the | |||
// colour map. If the target also has a colour map, then the callback or | |||
// cube specified to init() will be used. If the target is true colour | |||
// then instead we update the internal translation table - in this case | |||
// the caller should also make sure that the target surface receives an | |||
// update of the relevant parts (the simplest thing to do is just update | |||
// the whole framebuffer, though it is possible to be smarter than this). | |||
void setColourMapEntries(int firstColour, int nColours); | |||
// translatePixels() translates the given number of pixels from inPtr, | |||
// putting it into the buffer pointed to by outPtr. The pixels at inPtr | |||
@@ -91,12 +67,7 @@ namespace rfb { | |||
bool economic; | |||
PixelFormat inPF; | |||
ColourMap* inCM; | |||
PixelFormat outPF; | |||
setCMFnType cmCallback; | |||
void *cbData; | |||
ColourCube* cube; | |||
rdr::U8* table; | |||
transFnType transFn; |
@@ -306,10 +306,6 @@ void SConnection::approveConnection(bool accept, const char* reason) | |||
} | |||
} | |||
void SConnection::setInitialColourMap() | |||
{ | |||
} | |||
void SConnection::clientInit(bool shared) | |||
{ | |||
writer_->writeServerInit(); | |||
@@ -320,6 +316,8 @@ void SConnection::setPixelFormat(const PixelFormat& pf) | |||
{ | |||
SMsgHandler::setPixelFormat(pf); | |||
readyForSetColourMapEntries = true; | |||
if (!pf.trueColour) | |||
writeFakeColourMap(); | |||
} | |||
void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental) | |||
@@ -327,7 +325,7 @@ void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental) | |||
if (!readyForSetColourMapEntries) { | |||
readyForSetColourMapEntries = true; | |||
if (!cp.pf().trueColour) { | |||
setInitialColourMap(); | |||
writeFakeColourMap(); | |||
} | |||
} | |||
} | |||
@@ -347,3 +345,14 @@ void SConnection::enableContinuousUpdates(bool enable, | |||
int x, int y, int w, int h) | |||
{ | |||
} | |||
void SConnection::writeFakeColourMap(void) | |||
{ | |||
int i; | |||
rdr::U16 red[256], green[256], blue[256]; | |||
for (i = 0;i < 256;i++) | |||
cp.pf().rgbFromPixel(i, &red[i], &green[i], &blue[i]); | |||
writer()->writeSetColourMapEntries(0, 256, red, green, blue); | |||
} |
@@ -102,11 +102,6 @@ namespace rfb { | |||
// SConnection::framebufferUpdateRequest(). | |||
virtual void framebufferUpdateRequest(const Rect& r, bool incremental); | |||
// setInitialColourMap() is called when the client needs an initial | |||
// SetColourMapEntries message. In fact this only happens when the client | |||
// accepts the server's default pixel format and it uses a colour map. | |||
virtual void setInitialColourMap(); | |||
// fence() is called when we get a fence request or response. By default | |||
// it responds directly to requests (stating it doesn't support any | |||
// synchronisation) and drops responses. Override to implement more proper | |||
@@ -180,6 +175,7 @@ namespace rfb { | |||
protected: | |||
void setState(stateEnum s) { state_ = s; } | |||
void writeFakeColourMap(void); | |||
bool readyForSetColourMapEntries; | |||
@@ -23,7 +23,6 @@ | |||
#include <rfb/msgTypes.h> | |||
#include <rfb/fenceTypes.h> | |||
#include <rfb/Exception.h> | |||
#include <rfb/ColourMap.h> | |||
#include <rfb/ConnParams.h> | |||
#include <rfb/UpdateTracker.h> | |||
#include <rfb/Encoder.h> | |||
@@ -76,18 +75,18 @@ void SMsgWriter::writeServerInit() | |||
} | |||
void SMsgWriter::writeSetColourMapEntries(int firstColour, int nColours, | |||
ColourMap* cm) | |||
const rdr::U16 red[], | |||
const rdr::U16 green[], | |||
const rdr::U16 blue[]) | |||
{ | |||
startMsg(msgTypeSetColourMapEntries); | |||
os->pad(1); | |||
os->writeU16(firstColour); | |||
os->writeU16(nColours); | |||
for (int i = firstColour; i < firstColour+nColours; i++) { | |||
int r, g, b; | |||
cm->lookup(i, &r, &g, &b); | |||
os->writeU16(r); | |||
os->writeU16(g); | |||
os->writeU16(b); | |||
os->writeU16(red[i]); | |||
os->writeU16(green[i]); | |||
os->writeU16(blue[i]); | |||
} | |||
endMsg(); | |||
} |
@@ -33,7 +33,6 @@ namespace rfb { | |||
class ConnParams; | |||
class TransImageGetter; | |||
class ColourMap; | |||
class Region; | |||
class UpdateInfo; | |||
class Encoder; | |||
@@ -56,10 +55,11 @@ namespace rfb { | |||
// Methods to write normal protocol messages | |||
// writeSetColourMapEntries() writes a setColourMapEntries message, using | |||
// the given ColourMap object to lookup the RGB values of the given range | |||
// of colours. | |||
// the given colour entries. | |||
void writeSetColourMapEntries(int firstColour, int nColours, | |||
ColourMap* cm); | |||
const rdr::U16 red[], | |||
const rdr::U16 green[], | |||
const rdr::U16 blue[]); | |||
// writeBell() and writeServerCutText() do the obvious thing. | |||
void writeBell(); |
@@ -338,9 +338,9 @@ void TightEncoder::writeRect(const Rect& _r, TransImageGetter* _ig) | |||
if (checkSolidTile(sr, &colorValue, false)) { | |||
if (jpegSubsampling == subsampleGray && jpegQuality != -1) { | |||
Colour rgb; | |||
serverpf.rgbFromPixel(colorValue, NULL, &rgb); | |||
rdr::U32 lum = ((257 * rgb.r) + (504 * rgb.g) + (98 * rgb.b) | |||
rdr::U16 r, g, b; | |||
serverpf.rgbFromPixel(colorValue, &r, &g, &b); | |||
rdr::U32 lum = ((257 * r) + (504 * g) + (98 * b) | |||
+ 16500) / 1000; | |||
colorValue = lum + (lum << 8) + (lum << 16); | |||
} |
@@ -24,10 +24,7 @@ | |||
#include <rfb/Exception.h> | |||
#include <rfb/ConnParams.h> | |||
#include <rfb/SMsgWriter.h> | |||
#include <rfb/ColourMap.h> | |||
#include <rfb/TrueColourMap.h> | |||
#include <rfb/PixelBuffer.h> | |||
#include <rfb/ColourCube.h> | |||
#include <rfb/TransImageGetter.h> | |||
using namespace rfb; | |||
@@ -42,18 +39,12 @@ TransImageGetter::~TransImageGetter() | |||
} | |||
void TransImageGetter::init(PixelBuffer* pb_, const PixelFormat& out, | |||
SMsgWriter* writer_, ColourCube* cube_) | |||
SMsgWriter* writer_) | |||
{ | |||
pb = pb_; | |||
writer = writer_; | |||
PixelTransformer::init(pb->getPF(), pb->getColourMap(), out, cube_, | |||
cmCallback, this); | |||
} | |||
void TransImageGetter::setColourMapEntries(int firstCol, int nCols) | |||
{ | |||
PixelTransformer::setColourMapEntries(firstCol, nCols); | |||
PixelTransformer::init(pb->getPF(), out); | |||
} | |||
const rdr::U8 *TransImageGetter::getRawBufferR(const Rect &r, int *stride) | |||
@@ -74,15 +65,3 @@ void TransImageGetter::getImage(void* outPtr, const Rect& r, int outStride) | |||
translateRect((void*)inPtr, inStride, Rect(0, 0, r.width(), r.height()), | |||
outPtr, outStride, Point(0, 0)); | |||
} | |||
void TransImageGetter::cmCallback(int firstColour, int nColours, | |||
ColourMap* cm, void* data) | |||
{ | |||
TransImageGetter *self; | |||
assert(data); | |||
self = (TransImageGetter*)data; | |||
if (self->writer) | |||
self->writer->writeSetColourMapEntries(firstColour, nColours, cm); | |||
} |
@@ -32,9 +32,7 @@ | |||
namespace rfb { | |||
class SMsgWriter; | |||
class ColourMap; | |||
class PixelBuffer; | |||
class ColourCube; | |||
class TransImageGetter : public ImageGetter, | |||
public PixelTransformer { | |||
@@ -45,25 +43,9 @@ namespace rfb { | |||
// init() is called to initialise the translation tables. The PixelBuffer | |||
// argument gives the source data and format details, outPF gives the | |||
// client's pixel format. If the client has a colour map, then the writer | |||
// argument is used to send a SetColourMapEntries message to the client. | |||
// client's pixel format. | |||
void init(PixelBuffer* pb, const PixelFormat& outPF, SMsgWriter* writer=0, | |||
ColourCube* cube=0); | |||
// setColourMapEntries() is called when the PixelBuffer has a colour map | |||
// which has changed. firstColour and nColours specify which part of the | |||
// colour map has changed. If nColours is 0, this means the rest of the | |||
// colour map. The PixelBuffer previously passed to init() must have a | |||
// valid ColourMap object. If the client also has a colour map, then the | |||
// writer argument is used to send a SetColourMapEntries message to the | |||
// client. If the client is true colour then instead we update the | |||
// internal translation table - in this case the caller should also make | |||
// sure that the client receives an update of the relevant parts of the | |||
// framebuffer (the simplest thing to do is just update the whole | |||
// framebuffer, though it is possible to be smarter than this). | |||
void setColourMapEntries(int firstColour, int nColours); | |||
void init(PixelBuffer* pb, const PixelFormat& outPF, SMsgWriter* writer=0); | |||
// getImage() gets the given rectangle of data from the PixelBuffer, | |||
// translates it into the client's pixel format and puts it in the buffer | |||
@@ -89,10 +71,6 @@ namespace rfb { | |||
// the rectangle given to getImage(). | |||
void setOffset(const Point& offset_) { offset = offset_; } | |||
private: | |||
static void cmCallback(int firstColour, int nColours, | |||
ColourMap* cm, void* data); | |||
private: | |||
bool economic; | |||
PixelBuffer* pb; | |||
@@ -100,7 +78,6 @@ namespace rfb { | |||
SMsgWriter* writer; | |||
rdr::U8* table; | |||
transFnType transFn; | |||
ColourCube* cube; | |||
Point offset; | |||
}; | |||
} |
@@ -1,41 +0,0 @@ | |||
/* Copyright (C) 2002-2005 RealVNC Ltd. 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 | |||
* 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_TRUECOLOURMAP_H__ | |||
#define __RFB_TRUECOLOURMAP_H__ | |||
#include <rfb/ColourMap.h> | |||
namespace rfb { | |||
class TrueColourMap : public ColourMap { | |||
public: | |||
TrueColourMap(const PixelFormat& pf_) : pf(pf_) {} | |||
virtual void lookup(int i, int* r, int* g, int* b) | |||
{ | |||
rdr::U16 _r, _g, _b; | |||
pf.rgbFromPixel(i, NULL, &_r, &_g, &_b); | |||
*r = _r; | |||
*g = _g; | |||
*b = _b; | |||
} | |||
private: | |||
PixelFormat pf; | |||
}; | |||
} | |||
#endif |
@@ -253,15 +253,6 @@ void VNCSConnectionST::screenLayoutChangeOrClose(rdr::U16 reason) | |||
} | |||
} | |||
void VNCSConnectionST::setColourMapEntriesOrClose(int firstColour,int nColours) | |||
{ | |||
try { | |||
setColourMapEntries(firstColour, nColours); | |||
} catch(rdr::Exception& e) { | |||
close(e.str()); | |||
} | |||
} | |||
void VNCSConnectionST::bellOrClose() | |||
{ | |||
try { | |||
@@ -625,11 +616,6 @@ void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height, | |||
writeFramebufferUpdate(); | |||
} | |||
void VNCSConnectionST::setInitialColourMap() | |||
{ | |||
setColourMapEntries(0, 0); | |||
} | |||
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[]) | |||
{ | |||
if (flags & fenceFlagRequest) { | |||
@@ -1151,21 +1137,6 @@ void VNCSConnectionST::screenLayoutChange(rdr::U16 reason) | |||
writeFramebufferUpdate(); | |||
} | |||
void VNCSConnectionST::setColourMapEntries(int firstColour, int nColours) | |||
{ | |||
if (!readyForSetColourMapEntries) | |||
return; | |||
if (server->pb->getPF().trueColour) | |||
return; | |||
image_getter.setColourMapEntries(firstColour, nColours); | |||
if (cp.pf().trueColour) { | |||
updates.add_changed(server->pb->getRect()); | |||
writeFramebufferUpdate(); | |||
} | |||
} | |||
// setCursor() is called whenever the cursor has changed shape or pixel format. | |||
// If the client supports local cursor then it will arrange for the cursor to |
@@ -71,7 +71,6 @@ namespace rfb { | |||
// Wrappers to make these methods "safe" for VNCServerST. | |||
void writeFramebufferUpdateOrClose(); | |||
void screenLayoutChangeOrClose(rdr::U16 reason); | |||
void setColourMapEntriesOrClose(int firstColour, int nColours); | |||
void setCursorOrClose(); | |||
void bellOrClose(); | |||
void serverCutTextOrClose(const char *str, int len); | |||
@@ -138,7 +137,6 @@ namespace rfb { | |||
virtual void framebufferUpdateRequest(const Rect& r, bool incremental); | |||
virtual void setDesktopSize(int fb_width, int fb_height, | |||
const ScreenSet& layout); | |||
virtual void setInitialColourMap(); | |||
virtual void fence(rdr::U32 flags, unsigned len, const char data[]); | |||
virtual void enableContinuousUpdates(bool enable, | |||
int x, int y, int w, int h); | |||
@@ -173,7 +171,6 @@ namespace rfb { | |||
void writeRenderedCursorRect(); | |||
void screenLayoutChange(rdr::U16 reason); | |||
void setColourMapEntries(int firstColour, int nColours); | |||
void setCursor(); | |||
void setDesktopName(const char *name); | |||
void setSocketTimeouts(); |
@@ -52,12 +52,6 @@ namespace rfb { | |||
// getPixelBuffer() returns a pointer to the PixelBuffer object. | |||
virtual PixelBuffer* getPixelBuffer() const = 0; | |||
// setColourMapEntries() tells the server that some entries in the colour | |||
// map have changed. The server will retrieve them via the PixelBuffer's | |||
// ColourMap object. This may result in protocol messages being sent. | |||
// If nColours is 0, this means the rest of the colour map. | |||
virtual void setColourMapEntries(int firstColour=0, int nColours=0) = 0; | |||
// serverCutText() tells the server that the cut text has changed. This | |||
// will normally be sent to all clients. | |||
virtual void serverCutText(const char* str, int len) = 0; |
@@ -359,15 +359,6 @@ void VNCServerST::setScreenLayout(const ScreenSet& layout) | |||
} | |||
} | |||
void VNCServerST::setColourMapEntries(int firstColour, int nColours) | |||
{ | |||
std::list<VNCSConnectionST*>::iterator ci, ci_next; | |||
for (ci = clients.begin(); ci != clients.end(); ci = ci_next) { | |||
ci_next = ci; ci_next++; | |||
(*ci)->setColourMapEntriesOrClose(firstColour, nColours); | |||
} | |||
} | |||
void VNCServerST::bell() | |||
{ | |||
std::list<VNCSConnectionST*>::iterator ci, ci_next; |
@@ -88,7 +88,6 @@ namespace rfb { | |||
virtual void setPixelBuffer(PixelBuffer* pb); | |||
virtual void setScreenLayout(const ScreenSet& layout); | |||
virtual PixelBuffer* getPixelBuffer() const { return pb; } | |||
virtual void setColourMapEntries(int firstColour=0, int nColours=0); | |||
virtual void serverCutText(const char* str, int len); | |||
virtual void add_changed(const Region ®ion); | |||
virtual void add_copied(const Region &dest, const Point &delta); |
@@ -73,7 +73,7 @@ void TIGHT_DECODE (const Rect& r) | |||
if (cutZeros) { | |||
rdr::U8 bytebuf[3]; | |||
is->readBytes(bytebuf, 3); | |||
serverpf.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)&pix, bytebuf, 1); | |||
} else { | |||
pix = is->READ_PIXEL(); | |||
} | |||
@@ -107,7 +107,7 @@ void TIGHT_DECODE (const Rect& r) | |||
if (cutZeros) { | |||
rdr::U8 tightPalette[256 * 3]; | |||
is->readBytes(tightPalette, palSize * 3); | |||
serverpf.bufferFromRGB((rdr::U8*)palette, tightPalette, palSize, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)palette, tightPalette, palSize); | |||
} else { | |||
is->readBytes(palette, palSize * sizeof(PIXEL_T)); | |||
} | |||
@@ -175,7 +175,7 @@ void TIGHT_DECODE (const Rect& r) | |||
int w = r.width(); | |||
if (cutZeros) { | |||
while (h > 0) { | |||
serverpf.bufferFromRGB((rdr::U8*)ptr, srcPtr, w, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)ptr, srcPtr, w); | |||
ptr += stride; | |||
srcPtr += w * 3; | |||
h--; | |||
@@ -284,7 +284,7 @@ TightDecoder::FilterGradient24(rdr::U8 *netbuf, PIXEL_T* buf, int stride, | |||
pix[c] = netbuf[y*rectWidth*3+c] + prevRow[c]; | |||
thisRow[c] = pix[c]; | |||
} | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1); | |||
/* Remaining pixels of a row */ | |||
for (x = 1; x < rectWidth; x++) { | |||
@@ -298,7 +298,7 @@ TightDecoder::FilterGradient24(rdr::U8 *netbuf, PIXEL_T* buf, int stride, | |||
pix[c] = netbuf[(y*rectWidth+x)*3+c] + est[c]; | |||
thisRow[x*3+c] = pix[c]; | |||
} | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1); | |||
} | |||
memcpy(prevRow, thisRow, sizeof(prevRow)); | |||
@@ -324,13 +324,13 @@ FILTER_GRADIENT(rdr::U8 *netbuf, PIXEL_T* buf, int stride, const Rect& r) | |||
for (y = 0; y < rectHeight; y++) { | |||
/* First pixel in a row */ | |||
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1, NULL); | |||
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth], 1); | |||
for (c = 0; c < 3; c++) | |||
pix[c] += prevRow[c]; | |||
memcpy(thisRow, pix, sizeof(pix)); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride], pix, 1); | |||
/* Remaining pixels of a row */ | |||
for (x = 1; x < rectWidth; x++) { | |||
@@ -343,13 +343,13 @@ FILTER_GRADIENT(rdr::U8 *netbuf, PIXEL_T* buf, int stride, const Rect& r) | |||
} | |||
} | |||
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1, NULL); | |||
serverpf.rgbFromBuffer(pix, (rdr::U8*)&netbuf[y*rectWidth+x], 1); | |||
for (c = 0; c < 3; c++) | |||
pix[c] += est[c]; | |||
memcpy(&thisRow[x*3], pix, sizeof(pix)); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1, NULL); | |||
serverpf.bufferFromRGB((rdr::U8*)&buf[y*stride+x], pix, 1); | |||
} | |||
memcpy(prevRow, thisRow, sizeof(prevRow)); |
@@ -99,7 +99,7 @@ unsigned int PACK_PIXELS (PIXEL_T *buf, unsigned int count) | |||
rdr::U8 *dst = (rdr::U8 *)buf; | |||
for (unsigned int i = 0; i < count; i++) { | |||
pix = *buf++; | |||
clientpf.rgbFromBuffer(dst, (rdr::U8*)&pix, 1, NULL); | |||
clientpf.rgbFromBuffer(dst, (rdr::U8*)&pix, 1); | |||
dst += 3; | |||
} | |||
return count * 3; |
@@ -46,12 +46,8 @@ namespace rfb { | |||
#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT) | |||
#define SWAPOUT CONCAT2E(SWAP,BPPOUT) | |||
#define initSimpleCMtoTCOUT CONCAT2E(initSimpleCMtoTC,BPPOUT) | |||
#define initSimpleTCtoTCOUT CONCAT2E(initSimpleTCtoTC,BPPOUT) | |||
#define initSimpleCMtoCubeOUT CONCAT2E(initSimpleCMtoCube,BPPOUT) | |||
#define initSimpleTCtoCubeOUT CONCAT2E(initSimpleTCtoCube,BPPOUT) | |||
#define initRGBTCtoTCOUT CONCAT2E(initRGBTCtoTC,BPPOUT) | |||
#define initRGBTCtoCubeOUT CONCAT2E(initRGBTCtoCube,BPPOUT) | |||
#define initSimpleOUT CONCAT2E(initSimple,BPPOUT) | |||
#define initRGBOUT CONCAT2E(initRGB,BPPOUT) | |||
#define initOneRGBTableOUT CONCAT2E(initOneRGBTable,BPPOUT) | |||
#define initOneRGBCubeTableOUT CONCAT2E(initOneRGBCubeTable,BPPOUT) | |||
@@ -61,34 +57,8 @@ namespace rfb { | |||
static bool nativeBigEndian = *(rdr::U8*)(&endianTest) != 1; | |||
#endif | |||
void initSimpleCMtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourMap* cm, const PixelFormat& outPF) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
int size = 1 << inPF.bpp; | |||
delete [] *tablep; | |||
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)]; | |||
OUTPIXEL* table = (OUTPIXEL*)*tablep; | |||
for (int i = 0; i < size; i++) { | |||
int r,g,b; | |||
cm->lookup(i,&r,&g,&b); | |||
table[i] = ((((r * outPF.redMax + 32767) / 65535) << outPF.redShift) | | |||
(((g * outPF.greenMax + 32767) / 65535) << outPF.greenShift) | | |||
(((b * outPF.blueMax + 32767) / 65535) << outPF.blueShift)); | |||
#if (BPPOUT != 8) | |||
if (outPF.bigEndian != nativeBigEndian) | |||
table[i] = SWAPOUT (table[i]); | |||
#endif | |||
} | |||
} | |||
void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF) | |||
void initSimpleOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
@@ -118,55 +88,8 @@ void initSimpleTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
} | |||
} | |||
void initSimpleCMtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourMap* cm, ColourCube* cube) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
int size = 1 << inPF.bpp; | |||
delete [] *tablep; | |||
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)]; | |||
OUTPIXEL* table = (OUTPIXEL*)*tablep; | |||
for (int i = 0; i < size; i++) { | |||
int r,g,b; | |||
cm->lookup(i,&r,&g,&b); | |||
r = (r * (cube->nRed-1) + 32767) / 65535; | |||
g = (g * (cube->nGreen-1) + 32767) / 65535; | |||
b = (b * (cube->nBlue-1) + 32767) / 65535; | |||
table[i] = cube->lookup(r, g, b); | |||
} | |||
} | |||
void initSimpleTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourCube* cube) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
int size = 1 << inPF.bpp; | |||
delete [] *tablep; | |||
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)]; | |||
OUTPIXEL* table = (OUTPIXEL*)*tablep; | |||
for (int i = 0; i < size; i++) { | |||
int r = (i >> inPF.redShift) & inPF.redMax; | |||
int g = (i >> inPF.greenShift) & inPF.greenMax; | |||
int b = (i >> inPF.blueShift) & inPF.blueMax; | |||
r = (r * (cube->nRed-1) + inPF.redMax/2) / inPF.redMax; | |||
g = (g * (cube->nGreen-1) + inPF.greenMax/2) / inPF.greenMax; | |||
b = (b * (cube->nBlue-1) + inPF.blueMax/2) / inPF.blueMax; | |||
table[i] = cube->lookup(r, g, b); | |||
} | |||
} | |||
void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax, | |||
int outShift, bool swap) | |||
static void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax, | |||
int outShift, bool swap) | |||
{ | |||
int size = inMax + 1; | |||
@@ -179,8 +102,8 @@ void initOneRGBTableOUT (OUTPIXEL* table, int inMax, int outMax, | |||
} | |||
} | |||
void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF) | |||
void initRGBOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
const PixelFormat& outPF) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
@@ -205,50 +128,8 @@ void initRGBTCtoTCOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
} | |||
void initOneRGBCubeTableOUT (OUTPIXEL* table, int inMax, int outMax, | |||
int outMult) | |||
{ | |||
int size = inMax + 1; | |||
for (int i = 0; i < size; i++) { | |||
table[i] = ((i * outMax + inMax / 2) / inMax) * outMult; | |||
} | |||
} | |||
void initRGBTCtoCubeOUT (rdr::U8** tablep, const PixelFormat& inPF, | |||
ColourCube* cube) | |||
{ | |||
if (inPF.bpp != 8 && inPF.bigEndian != nativeBigEndian) | |||
throw Exception("Internal error: inPF is not native endian"); | |||
int size = inPF.redMax + inPF.greenMax + inPF.blueMax + 3 + cube->size(); | |||
delete [] *tablep; | |||
*tablep = new rdr::U8[size * sizeof(OUTPIXEL)]; | |||
OUTPIXEL* redTable = (OUTPIXEL*)*tablep; | |||
OUTPIXEL* greenTable = redTable + inPF.redMax + 1; | |||
OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1; | |||
OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1; | |||
initOneRGBCubeTableOUT (redTable, inPF.redMax, cube->nRed-1, | |||
cube->redMult()); | |||
initOneRGBCubeTableOUT (greenTable, inPF.greenMax, cube->nGreen-1, | |||
cube->greenMult()); | |||
initOneRGBCubeTableOUT (blueTable, inPF.blueMax, cube->nBlue-1, | |||
cube->blueMult()); | |||
for (int i = 0; i < cube->size(); i++) { | |||
cubeTable[i] = cube->table[i]; | |||
} | |||
} | |||
#undef OUTPIXEL | |||
#undef initSimpleCMtoTCOUT | |||
#undef initSimpleTCtoTCOUT | |||
#undef initSimpleCMtoCubeOUT | |||
#undef initSimpleTCtoCubeOUT | |||
#undef initRGBTCtoTCOUT | |||
#undef initRGBTCtoCubeOUT | |||
#undef initSimpleOUT | |||
#undef initRGBOUT | |||
#undef initOneRGBTableOUT | |||
#undef initOneRGBCubeTableOUT | |||
} |
@@ -42,7 +42,6 @@ | |||
#define OUTPIXEL rdr::CONCAT2E(U,BPPOUT) | |||
#define transSimpleINtoOUT CONCAT4E(transSimple,BPPIN,to,BPPOUT) | |||
#define transRGBINtoOUT CONCAT4E(transRGB,BPPIN,to,BPPOUT) | |||
#define transRGBCubeINtoOUT CONCAT4E(transRGBCube,BPPIN,to,BPPOUT) | |||
#if (BPPIN <= 16) | |||
@@ -111,41 +110,9 @@ void transRGBINtoOUT (void* table, | |||
} | |||
} | |||
// transRGBCubeINtoOUT is similar to transRGBINtoOUT but also looks up the | |||
// colour cube index in a fourth table to yield a pixel value. | |||
void transRGBCubeINtoOUT (void* table, | |||
const PixelFormat& inPF, const void* inPtr, int inStride, | |||
const PixelFormat& outPF, void* outPtr, | |||
int outStride, int width, int height) | |||
{ | |||
OUTPIXEL* redTable = (OUTPIXEL*)table; | |||
OUTPIXEL* greenTable = redTable + inPF.redMax + 1; | |||
OUTPIXEL* blueTable = greenTable + inPF.greenMax + 1; | |||
OUTPIXEL* cubeTable = blueTable + inPF.blueMax + 1; | |||
INPIXEL* ip = (INPIXEL*)inPtr; | |||
OUTPIXEL* op = (OUTPIXEL*)outPtr; | |||
int inExtra = inStride - width; | |||
int outExtra = outStride - width; | |||
while (height > 0) { | |||
OUTPIXEL* opEndOfRow = op + width; | |||
while (op < opEndOfRow) { | |||
*op++ = cubeTable[(redTable [(*ip >> inPF.redShift) & inPF.redMax] + | |||
greenTable[(*ip >> inPF.greenShift) & inPF.greenMax] + | |||
blueTable [(*ip >> inPF.blueShift) & inPF.blueMax])]; | |||
ip++; | |||
} | |||
ip += inExtra; | |||
op += outExtra; | |||
height--; | |||
} | |||
} | |||
#endif | |||
#undef INPIXEL | |||
#undef OUTPIXEL | |||
#undef transSimpleINtoOUT | |||
#undef transRGBINtoOUT | |||
#undef transRGBCubeINtoOUT |
@@ -101,7 +101,7 @@ static void doTests(rfb::PixelFormat &dstpf, rfb::PixelFormat &srcpf) | |||
if (srcpf.isLittleEndian()) { | |||
delete pt; | |||
pt = new rfb::PixelTransformer; | |||
pt->init(srcpf, NULL, dstpf); | |||
pt->init(srcpf, dstpf); | |||
} | |||
printf("%s,%s", srcb, dstb); |
@@ -29,7 +29,7 @@ | |||
using namespace rfb; | |||
XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, | |||
const Rect &rect, ColourMap* cm) | |||
const Rect &rect) | |||
: FullFramePixelBuffer(), | |||
m_poller(0), | |||
m_dpy(dpy), | |||
@@ -54,7 +54,6 @@ XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory, | |||
width_ = rect.width(); | |||
height_ = rect.height(); | |||
data = (rdr::U8 *)m_image->xim->data; | |||
colourmap = cm; | |||
// Calculate the distance in pixels between two subsequent scan | |||
// lines of the framebuffer. This may differ from image width. |
@@ -37,8 +37,7 @@ using namespace rfb; | |||
class XPixelBuffer : public FullFramePixelBuffer | |||
{ | |||
public: | |||
XPixelBuffer(Display *dpy, ImageFactory &factory, | |||
const Rect &rect, ColourMap* cm); | |||
XPixelBuffer(Display *dpy, ImageFactory &factory, const Rect &rect); | |||
virtual ~XPixelBuffer(); | |||
// Provide access to the underlying Image object. |
@@ -135,7 +135,7 @@ private: | |||
}; | |||
class XDesktop : public SDesktop, public ColourMap, public TXGlobalEventHandler | |||
class XDesktop : public SDesktop, public TXGlobalEventHandler | |||
{ | |||
public: | |||
XDesktop(Display* dpy_, Geometry *geometry_) | |||
@@ -199,7 +199,7 @@ public: | |||
ImageFactory factory((bool)useShm, (bool)useOverlay); | |||
// Create pixel buffer and provide it to the server object. | |||
pb = new XPixelBuffer(dpy, factory, geometry->getRect(), this); | |||
pb = new XPixelBuffer(dpy, factory, geometry->getRect()); | |||
vlog.info("Allocated %s", pb->getImage()->classDesc()); | |||
server = (VNCServerST *)vs; | |||
@@ -269,20 +269,6 @@ public: | |||
return Point(pb->width(), pb->height()); | |||
} | |||
// -=- ColourMap callbacks | |||
virtual void lookup(int index, int* r, int* g, int* b) { | |||
XColor xc; | |||
xc.pixel = index; | |||
if (index < DisplayCells(dpy,DefaultScreen(dpy))) { | |||
XQueryColor(dpy, DefaultColormap(dpy,DefaultScreen(dpy)), &xc); | |||
} else { | |||
xc.red = xc.green = xc.blue = 0; | |||
} | |||
*r = xc.red; | |||
*g = xc.green; | |||
*b = xc.blue; | |||
} | |||
// -=- TXGlobalEventHandler interface | |||
virtual bool handleGlobalEvent(XEvent* ev) { |
@@ -51,7 +51,6 @@ extern "C" { | |||
extern char *display; | |||
#include "colormapst.h" | |||
#ifdef RANDR | |||
#include "randrstr.h" | |||
#endif | |||
@@ -143,14 +142,11 @@ XserverDesktop::XserverDesktop(ScreenPtr pScreen_, | |||
: pScreen(pScreen_), | |||
server(0), httpServer(0), | |||
listener(listener_), httpListener(httpListener_), | |||
cmap(0), deferredUpdateTimerSet(false), | |||
deferredUpdateTimerSet(false), | |||
grabbing(false), ignoreHooks_(false), directFbptr(true), | |||
queryConnectId(0) | |||
{ | |||
format = pf; | |||
colourmap = this; | |||
serverReset(pScreen); | |||
server = new VNCServerST(name, this); | |||
setFramebuffer(pScreen->width, pScreen->height, fbptr, stride); | |||
@@ -171,24 +167,6 @@ XserverDesktop::~XserverDesktop() | |||
delete server; | |||
} | |||
void XserverDesktop::serverReset(ScreenPtr pScreen_) | |||
{ | |||
pScreen = pScreen_; | |||
int i; | |||
pointer retval; | |||
#if XORG >= 17 | |||
#define dixLookupResource dixLookupResourceByType | |||
#endif | |||
i = dixLookupResource(&retval, pScreen->defColormap, RT_COLORMAP, NullClient, | |||
DixReadAccess); | |||
/* Handle suspicious conditions */ | |||
assert(i == Success); | |||
cmap = (ColormapPtr) retval; | |||
} | |||
void XserverDesktop::blockUpdates() | |||
{ | |||
server->blockUpdates(); | |||
@@ -379,44 +357,6 @@ XserverDesktop::queryConnection(network::Socket* sock, | |||
return rfb::VNCServerST::PENDING; | |||
} | |||
void XserverDesktop::setColormap(ColormapPtr cmap_) | |||
{ | |||
if (cmap != cmap_) { | |||
cmap = cmap_; | |||
setColourMapEntries(0, 0); | |||
} | |||
} | |||
void XserverDesktop::setColourMapEntries(ColormapPtr pColormap, int ndef, | |||
xColorItem* pdef) | |||
{ | |||
if (cmap != pColormap || ndef <= 0) return; | |||
unsigned int first = pdef[0].pixel; | |||
unsigned int n = 1; | |||
for (int i = 1; i < ndef; i++) { | |||
if (first + n == pdef[i].pixel) { | |||
n++; | |||
} else { | |||
setColourMapEntries(first, n); | |||
first = pdef[i].pixel; | |||
n = 1; | |||
} | |||
} | |||
setColourMapEntries(first, n); | |||
} | |||
void XserverDesktop::setColourMapEntries(int firstColour, int nColours) | |||
{ | |||
try { | |||
server->setColourMapEntries(firstColour, nColours); | |||
} catch (rdr::Exception& e) { | |||
vlog.error("XserverDesktop::setColourMapEntries: %s",e.str()); | |||
} | |||
} | |||
void XserverDesktop::bell() | |||
{ | |||
server->bell(); | |||
@@ -469,7 +409,7 @@ void XserverDesktop::setCursor(CursorPtr cursor) | |||
rgb[1] = (*in >> 8) & 0xff; | |||
rgb[2] = (*in >> 0) & 0xff; | |||
getPF().bufferFromRGB(out, rgb, 1, this); | |||
getPF().bufferFromRGB(out, rgb, 1); | |||
if (((*in >> 24) & 0xff) > 127) | |||
cursorMask[y * rfbMaskBytesPerRow + x/8] |= 0x80>>(x%8); | |||
@@ -480,42 +420,42 @@ void XserverDesktop::setCursor(CursorPtr cursor) | |||
} | |||
} else { | |||
#endif | |||
xColorItem fg, bg; | |||
fg.red = cursor->foreRed; | |||
fg.green = cursor->foreGreen; | |||
fg.blue = cursor->foreBlue; | |||
FakeAllocColor(cmap, &fg); | |||
bg.red = cursor->backRed; | |||
bg.green = cursor->backGreen; | |||
bg.blue = cursor->backBlue; | |||
FakeAllocColor(cmap, &bg); | |||
FakeFreeColor(cmap, fg.pixel); | |||
FakeFreeColor(cmap, bg.pixel); | |||
rdr::U8 rgb[3]; | |||
rdr::U8 fg[4], bg[4]; | |||
rdr::U8* buffer; | |||
rgb[0] = cursor->foreRed; | |||
rgb[1] = cursor->foreGreen; | |||
rgb[2] = cursor->foreBlue; | |||
getPF().bufferFromRGB(fg, rgb, 1); | |||
rgb[0] = cursor->backRed; | |||
rgb[1] = cursor->backGreen; | |||
rgb[2] = cursor->backBlue; | |||
getPF().bufferFromRGB(bg, rgb, 1); | |||
int xMaskBytesPerRow = BitmapBytePad(w); | |||
buffer = cursorData; | |||
for (int y = 0; y < h; y++) { | |||
for (int x = 0; x < w; x++) { | |||
rdr::U8 *pixel; | |||
int byte = y * xMaskBytesPerRow + x / 8; | |||
#if (BITMAP_BIT_ORDER == MSBFirst) | |||
int bit = 7 - x % 8; | |||
#else | |||
int bit = x % 8; | |||
#endif | |||
switch (getPF().bpp) { | |||
case 8: | |||
((rdr::U8*)cursorData)[y * w + x] | |||
= (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; | |||
break; | |||
case 16: | |||
((rdr::U16*)cursorData)[y * w + x] | |||
= (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; | |||
break; | |||
case 32: | |||
((rdr::U32*)cursorData)[y * w + x] | |||
= (cursor->bits->source[byte] & (1 << bit)) ? fg.pixel : bg.pixel; | |||
break; | |||
} | |||
if (cursor->bits->source[byte] & (1 << bit)) | |||
pixel = fg; | |||
else | |||
pixel = bg; | |||
memcpy(buffer, pixel, getPF().bpp/8); | |||
buffer += getPF().bpp/8; | |||
} | |||
} | |||
@@ -1109,28 +1049,6 @@ int XserverDesktop::getStride() const | |||
return stride_; | |||
} | |||
void XserverDesktop::lookup(int index, int* r, int* g, int* b) | |||
{ | |||
if ((cmap->c_class | DynamicClass) == DirectColor) { | |||
VisualPtr v = cmap->pVisual; | |||
*r = cmap->red [(index & v->redMask ) >> v->offsetRed ].co.local.red; | |||
*g = cmap->green[(index & v->greenMask) >> v->offsetGreen].co.local.green; | |||
*b = cmap->blue [(index & v->blueMask ) >> v->offsetBlue ].co.local.blue; | |||
} else { | |||
EntryPtr pent; | |||
pent = (EntryPtr)&cmap->red[index]; | |||
if (pent->fShared) { | |||
*r = pent->co.shco.red->color; | |||
*g = pent->co.shco.green->color; | |||
*b = pent->co.shco.blue->color; | |||
} else { | |||
*r = pent->co.local.red; | |||
*g = pent->co.local.green; | |||
*b = pent->co.local.blue; | |||
} | |||
} | |||
} | |||
void XserverDesktop::keyEvent(rdr::U32 keysym, bool down) | |||
{ | |||
if (down) |
@@ -54,7 +54,7 @@ namespace rfb { | |||
namespace network { class TcpListener; class Socket; } | |||
class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, | |||
public rfb::ColourMap, public rdr::Substitutor, | |||
public rdr::Substitutor, | |||
public rfb::VNCServerST::QueryConnectionHandler { | |||
public: | |||
@@ -65,13 +65,10 @@ public: | |||
virtual ~XserverDesktop(); | |||
// methods called from X server code | |||
void serverReset(ScreenPtr pScreen); | |||
void blockUpdates(); | |||
void unblockUpdates(); | |||
void setFramebuffer(int w, int h, void* fbptr, int stride); | |||
void refreshScreenLayout(); | |||
void setColormap(ColormapPtr cmap); | |||
void setColourMapEntries(ColormapPtr pColormap, int ndef, xColorItem* pdef); | |||
void bell(); | |||
void serverCutText(const char* str, int len); | |||
void setDesktopName(const char* name); | |||
@@ -114,9 +111,6 @@ public: | |||
virtual void grabRegion(const rfb::Region& r); | |||
virtual int getStride() const; | |||
// rfb::ColourMap callbacks | |||
virtual void lookup(int index, int* r, int* g, int* b); | |||
// rdr::Substitutor callback | |||
virtual char* substitute(const char* varName); | |||
@@ -126,7 +120,6 @@ public: | |||
char** reason); | |||
private: | |||
void setColourMapEntries(int firstColour, int nColours); | |||
rfb::ScreenSet computeScreenLayout(); | |||
#ifdef RANDR | |||
RRModePtr findRandRMode(RROutputPtr output, int width, int height); | |||
@@ -138,7 +131,6 @@ private: | |||
rfb::HTTPServer* httpServer; | |||
network::TcpListener* listener; | |||
network::TcpListener* httpListener; | |||
ColormapPtr cmap; | |||
int stride_; | |||
bool deferredUpdateTimerSet; | |||
bool grabbing; |
@@ -168,8 +168,10 @@ static PixelFormat vncGetPixelFormat(ScreenPtr pScreen) | |||
trueColour = (vis->c_class == TrueColor); | |||
if (!trueColour && bpp != 8) | |||
throw rfb::Exception("X server uses unsupported visual"); | |||
if (!trueColour) { | |||
fprintf(stderr,"pseudocolour not supported"); | |||
abort(); | |||
} | |||
redShift = ffs(vis->redMask) - 1; | |||
greenShift = ffs(vis->greenMask) - 1; | |||
@@ -266,9 +268,6 @@ void vncExtensionInit() | |||
desktop[scr]->addClient(sock, false); | |||
vlog.info("added inetd sock"); | |||
} | |||
} else { | |||
desktop[scr]->serverReset(screenInfo.screens[scr]); | |||
} | |||
vncHooksInit(screenInfo.screens[scr], desktop[scr]); |
@@ -75,8 +75,6 @@ typedef struct { | |||
#if XORG < 110 | |||
RestoreAreasProcPtr RestoreAreas; | |||
#endif | |||
InstallColormapProcPtr InstallColormap; | |||
StoreColorsProcPtr StoreColors; | |||
DisplayCursorProcPtr DisplayCursor; | |||
ScreenBlockHandlerProcPtr BlockHandler; | |||
#ifdef RENDER | |||
@@ -132,9 +130,6 @@ static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, | |||
#if XORG < 110 | |||
static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed); | |||
#endif | |||
static void vncHooksInstallColormap(ColormapPtr pColormap); | |||
static void vncHooksStoreColors(ColormapPtr pColormap, int ndef, | |||
xColorItem* pdef); | |||
static Bool vncHooksDisplayCursor( | |||
#if XORG >= 16 | |||
DeviceIntPtr pDev, | |||
@@ -289,8 +284,6 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop) | |||
#if XORG < 110 | |||
vncHooksScreen->RestoreAreas = pScreen->RestoreAreas; | |||
#endif | |||
vncHooksScreen->InstallColormap = pScreen->InstallColormap; | |||
vncHooksScreen->StoreColors = pScreen->StoreColors; | |||
vncHooksScreen->DisplayCursor = pScreen->DisplayCursor; | |||
vncHooksScreen->BlockHandler = pScreen->BlockHandler; | |||
#ifdef RENDER | |||
@@ -318,8 +311,6 @@ Bool vncHooksInit(ScreenPtr pScreen, XserverDesktop* desktop) | |||
#if XORG < 110 | |||
pScreen->RestoreAreas = vncHooksRestoreAreas; | |||
#endif | |||
pScreen->InstallColormap = vncHooksInstallColormap; | |||
pScreen->StoreColors = vncHooksStoreColors; | |||
pScreen->DisplayCursor = vncHooksDisplayCursor; | |||
pScreen->BlockHandler = vncHooksBlockHandler; | |||
#ifdef RENDER | |||
@@ -381,8 +372,6 @@ static Bool vncHooksCloseScreen(ScreenPtr pScreen_) | |||
#if XORG < 110 | |||
pScreen->RestoreAreas = vncHooksScreen->RestoreAreas; | |||
#endif | |||
pScreen->InstallColormap = vncHooksScreen->InstallColormap; | |||
pScreen->StoreColors = vncHooksScreen->StoreColors; | |||
pScreen->DisplayCursor = vncHooksScreen->DisplayCursor; | |||
pScreen->BlockHandler = vncHooksScreen->BlockHandler; | |||
#ifdef RENDER | |||
@@ -512,33 +501,6 @@ static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr pRegion) | |||
} | |||
#endif | |||
// InstallColormap - get the new colormap | |||
static void vncHooksInstallColormap(ColormapPtr pColormap) | |||
{ | |||
SCREEN_UNWRAP(pColormap->pScreen, InstallColormap); | |||
(*pScreen->InstallColormap) (pColormap); | |||
vncHooksScreen->desktop->setColormap(pColormap); | |||
SCREEN_REWRAP(InstallColormap); | |||
} | |||
// StoreColors - get the colormap changes | |||
static void vncHooksStoreColors(ColormapPtr pColormap, int ndef, | |||
xColorItem* pdef) | |||
{ | |||
SCREEN_UNWRAP(pColormap->pScreen, StoreColors); | |||
(*pScreen->StoreColors) (pColormap, ndef, pdef); | |||
vncHooksScreen->desktop->setColourMapEntries(pColormap, ndef, pdef); | |||
SCREEN_REWRAP(StoreColors); | |||
} | |||
// DisplayCursor - get the cursor shape | |||
static Bool vncHooksDisplayCursor( |
@@ -65,8 +65,9 @@ static const PixelFormat verylowColourPF(8, 3,false, true, | |||
// 64 colours (2 bits per component) | |||
static const PixelFormat lowColourPF(8, 6, false, true, | |||
3, 3, 3, 4, 2, 0); | |||
// 256 colours (palette) | |||
static const PixelFormat mediumColourPF(8, 8, false, false); | |||
// 256 colours (2-3 bits per component) | |||
static const PixelFormat mediumColourPF(8, 8, false, true, | |||
7, 7, 3, 5, 2, 0); | |||
CConn::CConn(const char* vncServerName, network::Socket* socket=NULL) | |||
: serverHost(0), serverPort(0), desktop(NULL), | |||
@@ -342,7 +343,7 @@ void CConn::framebufferUpdateEnd() | |||
void CConn::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs) | |||
{ | |||
desktop->setColourMapEntries(firstColour, nColours, rgbs); | |||
vlog.error("Invalid SetColourMapEntries from server!"); | |||
} | |||
void CConn::bell() |
@@ -216,12 +216,6 @@ void DesktopWindow::setName(const char *name) | |||
} | |||
void DesktopWindow::setColourMapEntries(int firstColour, int nColours, | |||
rdr::U16* rgbs) | |||
{ | |||
viewport->setColourMapEntries(firstColour, nColours, rgbs); | |||
} | |||
void DesktopWindow::fillRect(const rfb::Rect& r, rfb::Pixel pix) { | |||
viewport->fillRect(r, pix); | |||
} |
@@ -50,8 +50,6 @@ public: | |||
// Methods forwarded from CConn | |||
void setName(const char *name); | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void fillRect(const rfb::Rect& r, rfb::Pixel pix); | |||
void imageRect(const rfb::Rect& r, void* pixels); | |||
void copyRect(const rfb::Rect& r, int srcX, int srcY); |
@@ -87,7 +87,7 @@ enum { ID_EXIT, ID_FULLSCREEN, ID_RESIZE, | |||
Viewport::Viewport(int w, int h, const rfb::PixelFormat& serverPF, CConn* cc_) | |||
: Fl_Widget(0, 0, w, h), cc(cc_), frameBuffer(NULL), pixelTrans(NULL), | |||
colourMapChange(false), lastPointerPos(0, 0), lastButtonMask(0), | |||
lastPointerPos(0, 0), lastButtonMask(0), | |||
cursor(NULL), menuCtrlKey(false), menuAltKey(false) | |||
{ | |||
// FLTK STR #2599 must be fixed for proper dead keys support | |||
@@ -183,11 +183,11 @@ void Viewport::setServerPF(const rfb::PixelFormat& pf) | |||
PixelFormat fake_pf(pf.bpp, pf.depth, nativeBigEndian, pf.trueColour, | |||
pf.redMax, pf.greenMax, pf.blueMax, | |||
pf.redShift, pf.greenShift, pf.blueShift); | |||
pixelTrans->init(fake_pf, &colourMap, getPreferredPF()); | |||
pixelTrans->init(fake_pf, getPreferredPF()); | |||
return; | |||
} | |||
pixelTrans->init(pf, &colourMap, getPreferredPF()); | |||
pixelTrans->init(pf, getPreferredPF()); | |||
} | |||
@@ -197,21 +197,6 @@ const rfb::PixelFormat &Viewport::getPreferredPF() | |||
} | |||
// setColourMapEntries() changes some of the entries in the colourmap. | |||
// We don't actually act on these changes until we need to. This is | |||
// because recalculating the internal translation table can be expensive. | |||
// This also solves the issue of silly servers sending colour maps in | |||
// multiple pieces. | |||
void Viewport::setColourMapEntries(int firstColour, int nColours, | |||
rdr::U16* rgbs) | |||
{ | |||
for (int i = 0; i < nColours; i++) | |||
colourMap.set(firstColour+i, rgbs[i*3], rgbs[i*3+1], rgbs[i*3+2]); | |||
colourMapChange = true; | |||
} | |||
// Copy the areas of the framebuffer that have been changed (damaged) | |||
// to the displayed window. | |||
@@ -230,8 +215,6 @@ void Viewport::updateWindow() | |||
void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) { | |||
if (pixelTrans) { | |||
rfb::Pixel pix2; | |||
if (colourMapChange) | |||
commitColourMap(); | |||
pixelTrans->translatePixels(&pix, &pix2, 1); | |||
pix = pix2; | |||
} | |||
@@ -242,8 +225,6 @@ void Viewport::fillRect(const rfb::Rect& r, rfb::Pixel pix) { | |||
void Viewport::imageRect(const rfb::Rect& r, void* pixels) { | |||
if (pixelTrans) { | |||
if (colourMapChange) | |||
commitColourMap(); | |||
pixelTrans->translateRect(pixels, r.width(), | |||
rfb::Rect(0, 0, r.width(), r.height()), | |||
frameBuffer->data, frameBuffer->getStride(), | |||
@@ -327,7 +308,7 @@ void Viewport::setCursor(int width, int height, const Point& hotspot, | |||
m_width = (width+7)/8; | |||
for (int y = 0;y < height;y++) { | |||
for (int x = 0;x < width;x++) { | |||
pf->rgbFromBuffer(o, i, 1, &colourMap); | |||
pf->rgbFromBuffer(o, i, 1); | |||
if (m[(m_width*y)+(x/8)] & 0x80>>(x%8)) | |||
o[3] = 255; | |||
@@ -529,19 +510,6 @@ void Viewport::handleUpdateTimeout(void *data) | |||
} | |||
void Viewport::commitColourMap() | |||
{ | |||
if (pixelTrans == NULL) | |||
return; | |||
if (!colourMapChange) | |||
return; | |||
colourMapChange = false; | |||
pixelTrans->setColourMapEntries(0, 0); | |||
} | |||
void Viewport::handleClipboardChange(int source, void *data) | |||
{ | |||
Viewport *self = (Viewport *)data; |
@@ -26,7 +26,6 @@ | |||
#include <rfb/Region.h> | |||
#include <rfb/Pixel.h> | |||
#include <rfb/ColourMap.h> | |||
class Fl_Menu_Button; | |||
class Fl_RGB_Image; | |||
@@ -52,8 +51,6 @@ public: | |||
// Methods forwarded from CConn | |||
void setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs); | |||
void fillRect(const rfb::Rect& r, rfb::Pixel pix); | |||
void imageRect(const rfb::Rect& r, void* pixels); | |||
void copyRect(const rfb::Rect& r, int srcX, int srcY); | |||
@@ -77,8 +74,6 @@ private: | |||
static void handleUpdateTimeout(void *data); | |||
void commitColourMap(); | |||
static void handleClipboardChange(int source, void *data); | |||
void handlePointerEvent(const rfb::Point& pos, int buttonMask); | |||
@@ -98,11 +93,7 @@ private: | |||
CConn* cc; | |||
PlatformPixelBuffer* frameBuffer; | |||
rfb::PixelTransformer *pixelTrans; | |||
rfb::SimpleColourMap colourMap; | |||
bool colourMapChange; | |||
rfb::Region damage; | |||
rfb::Point lastPointerPos; |
@@ -40,7 +40,7 @@ static rfb::LogWriter vlog("PlatformPixelBuffer"); | |||
PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) : | |||
FullFramePixelBuffer(rfb::PixelFormat(32, 24, false, true, | |||
255, 255, 255, 16, 8, 0), | |||
width, height, NULL, NULL), | |||
width, height, NULL), | |||
bitmap(NULL) | |||
{ | |||
BITMAPINFOHEADER bih; |
@@ -94,7 +94,7 @@ static PixelFormat display_pf() | |||
} | |||
PlatformPixelBuffer::PlatformPixelBuffer(int width, int height) : | |||
FullFramePixelBuffer(display_pf(), width, height, NULL, NULL), | |||
FullFramePixelBuffer(display_pf(), width, height, NULL), | |||
shminfo(NULL), xim(NULL) | |||
{ | |||
// Might not be open at this point |
@@ -31,13 +31,11 @@ static LogWriter vlog("DIBSectionBuffer"); | |||
DIBSectionBuffer::DIBSectionBuffer(HWND window_) | |||
: bitmap(0), window(window_), device(0) { | |||
memset(&format, 0, sizeof(format)); | |||
memset(palette, 0, sizeof(palette)); | |||
} | |||
DIBSectionBuffer::DIBSectionBuffer(HDC device_) | |||
: bitmap(0), window(0), device(device_) { | |||
memset(&format, 0, sizeof(format)); | |||
memset(palette, 0, sizeof(palette)); | |||
} | |||
DIBSectionBuffer::~DIBSectionBuffer() { | |||
@@ -51,19 +49,10 @@ void DIBSectionBuffer::setPF(const PixelFormat& pf) { | |||
vlog.debug("pixel format unchanged by setPF()"); | |||
return; | |||
} | |||
if (!pf.trueColour) | |||
throw rfb::Exception("palette format not supported"); | |||
format = pf; | |||
recreateBuffer(); | |||
if ((pf.bpp <= 8) && pf.trueColour) { | |||
vlog.info("creating %d-bit TrueColour palette", pf.depth); | |||
for (int i=0; i < (1<<(pf.depth)); i++) { | |||
rdr::U16 r, g, b; | |||
pf.rgbFromPixel(i, NULL, &r, &g, &b); | |||
palette[i].r = r; | |||
palette[i].g = g; | |||
palette[i].b = b; | |||
} | |||
refreshPalette(); | |||
} | |||
} | |||
void DIBSectionBuffer::setSize(int w, int h) { | |||
@@ -77,20 +66,6 @@ void DIBSectionBuffer::setSize(int w, int h) { | |||
} | |||
// * copyPaletteToDIB MUST NEVER be called on a truecolour DIB! * | |||
void copyPaletteToDIB(Colour palette[256], HDC wndDC, HBITMAP dib) { | |||
BitmapDC dibDC(wndDC, dib); | |||
RGBQUAD rgb[256]; | |||
for (unsigned int i=0;i<256;i++) { | |||
rgb[i].rgbRed = palette[i].r >> 8; | |||
rgb[i].rgbGreen = palette[i].g >> 8; | |||
rgb[i].rgbBlue = palette[i].b >> 8; | |||
} | |||
if (!SetDIBColorTable(dibDC, 0, 256, (RGBQUAD*) rgb)) | |||
throw rdr::SystemException("unable to SetDIBColorTable", GetLastError()); | |||
} | |||
inline void initMaxAndShift(DWORD mask, int* max, int* shift) { | |||
for ((*shift) = 0; (mask & 1) == 0; (*shift)++) mask >>= 1; | |||
(*max) = (rdr::U16)mask; | |||
@@ -103,9 +78,7 @@ void DIBSectionBuffer::recreateBuffer() { | |||
if (width_ && height_ && (format.depth != 0)) { | |||
BitmapInfo bi; | |||
memset(&bi, 0, sizeof(bi)); | |||
// *** wrong? | |||
UINT iUsage = format.trueColour ? DIB_RGB_COLORS : DIB_PAL_COLORS; | |||
// *** | |||
UINT iUsage = DIB_RGB_COLORS; | |||
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); | |||
bi.bmiHeader.biBitCount = format.bpp; | |||
bi.bmiHeader.biSizeImage = (format.bpp / 8) * width_ * height_; | |||
@@ -140,15 +113,11 @@ void DIBSectionBuffer::recreateBuffer() { | |||
// Copy the contents across | |||
if (device) { | |||
if (format.bpp <= 8) | |||
copyPaletteToDIB(palette, device, new_bitmap); | |||
BitmapDC src_dev(device, bitmap); | |||
BitmapDC dest_dev(device, new_bitmap); | |||
BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY); | |||
} else { | |||
WindowDC wndDC(window); | |||
if (format.bpp <= 8) | |||
copyPaletteToDIB(palette, wndDC, new_bitmap); | |||
BitmapDC src_dev(wndDC, bitmap); | |||
BitmapDC dest_dev(wndDC, new_bitmap); | |||
BitBlt(dest_dev, 0, 0, width_, height_, src_dev, 0, 0, SRCCOPY); | |||
@@ -164,7 +133,6 @@ void DIBSectionBuffer::recreateBuffer() { | |||
if (new_bitmap) { | |||
int bpp, depth; | |||
bool trueColour; | |||
int redMax, greenMax, blueMax; | |||
int redShift, greenShift, blueShift; | |||
@@ -189,46 +157,24 @@ void DIBSectionBuffer::recreateBuffer() { | |||
// Calculate the PixelFormat for the DIB | |||
bpp = depth = ds.dsBm.bmBitsPixel; | |||
trueColour = format.trueColour || format.bpp > 8; | |||
if (trueColour) { | |||
// Get the truecolour format used by the DIBSection | |||
initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift); | |||
initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift); | |||
initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift); | |||
// Calculate the effective depth | |||
depth = 0; | |||
Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2]; | |||
while (bits) { | |||
depth++; | |||
bits = bits >> 1; | |||
} | |||
if (depth > bpp) | |||
throw Exception("Bad DIBSection format (depth exceeds bpp)"); | |||
// Get the truecolour format used by the DIBSection | |||
initMaxAndShift(ds.dsBitfields[0], &redMax, &redShift); | |||
initMaxAndShift(ds.dsBitfields[1], &greenMax, &greenShift); | |||
initMaxAndShift(ds.dsBitfields[2], &blueMax, &blueShift); | |||
// Calculate the effective depth | |||
depth = 0; | |||
Pixel bits = ds.dsBitfields[0] | ds.dsBitfields[1] | ds.dsBitfields[2]; | |||
while (bits) { | |||
depth++; | |||
bits = bits >> 1; | |||
} | |||
if (depth > bpp) | |||
throw Exception("Bad DIBSection format (depth exceeds bpp)"); | |||
format = PixelFormat(bpp, depth, false, trueColour, | |||
format = PixelFormat(bpp, depth, false, true, | |||
redMax, greenMax, blueMax, | |||
redShift, greenShift, blueShift); | |||
if (!trueColour) { | |||
// Set the DIBSection's palette | |||
refreshPalette(); | |||
} | |||
} | |||
} | |||
void DIBSectionBuffer::refreshPalette() { | |||
if (format.bpp > 8) { | |||
vlog.error("refresh palette called for truecolor DIB"); | |||
return; | |||
} | |||
vlog.debug("refreshing palette"); | |||
if (device) | |||
copyPaletteToDIB(palette, device, bitmap); | |||
else | |||
copyPaletteToDIB(palette, WindowDC(window), bitmap); | |||
} | |||
@@ -28,7 +28,6 @@ | |||
#include <windows.h> | |||
#include <rfb/PixelBuffer.h> | |||
#include <rfb/Region.h> | |||
#include <rfb/ColourMap.h> | |||
#include <rfb/Exception.h> | |||
namespace rfb { | |||
@@ -39,7 +38,7 @@ namespace rfb { | |||
// -=- DIBSectionBuffer | |||
// | |||
class DIBSectionBuffer : public FullFramePixelBuffer, ColourMap { | |||
class DIBSectionBuffer : public FullFramePixelBuffer { | |||
public: | |||
DIBSectionBuffer(HWND window); | |||
DIBSectionBuffer(HDC device); | |||
@@ -50,29 +49,11 @@ namespace rfb { | |||
virtual int getStride() const {return stride;} | |||
virtual ColourMap* getColourMap() const {return (ColourMap*)this;} | |||
// - ColourMap interface | |||
virtual void lookup(int index, int* r, int *g, int* b) { | |||
*r = palette[index].r; | |||
*g = palette[index].g; | |||
*b = palette[index].b; | |||
} | |||
// Custom colourmap interface | |||
void setColour(int index, int r, int g, int b) { | |||
palette[index].r = r; | |||
palette[index].g = g; | |||
palette[index].b = b; | |||
} | |||
void refreshPalette(); | |||
// *** virtual void copyRect(const Rect &dest, const Point &move_by_delta); | |||
public: | |||
HBITMAP bitmap; | |||
protected: | |||
void recreateBuffer(); | |||
Colour palette[256]; | |||
int stride; | |||
HWND window; | |||
HDC device; |
@@ -79,10 +79,6 @@ DeviceFrameBuffer::DeviceFrameBuffer(HDC deviceContext, const Rect& wRect) | |||
// Configure the cursor buffer | |||
cursorBm.setPF(format); | |||
// Set up a palette if required | |||
if (!format.trueColour) | |||
updateColourMap(); | |||
} | |||
DeviceFrameBuffer::~DeviceFrameBuffer() { | |||
@@ -134,37 +130,6 @@ DeviceFrameBuffer::grabRegion(const Region &rgn) { | |||
} | |||
void copyDevicePaletteToDIB(HDC dc, DIBSectionBuffer* dib) { | |||
// - Fetch the system palette for the framebuffer | |||
PALETTEENTRY syspalette[256]; | |||
UINT entries = ::GetSystemPaletteEntries(dc, 0, 256, syspalette); | |||
if (entries == 0) { | |||
vlog.info("resorting to standard 16 color palette"); | |||
for (unsigned int i=0;i<256;i++) { | |||
int v = (i%16) >= 8 ? 127 : 255; | |||
syspalette[i].peRed = i & 1 ? v : 0; | |||
syspalette[i].peGreen = i & 2 ? v : 0; | |||
syspalette[i].peBlue = i & 4 ? v : 0; | |||
} | |||
} else { | |||
vlog.info("framebuffer has %u palette entries", entries); | |||
} | |||
// - Update the bitmap's stored copy of the palette | |||
for (unsigned int i=0;i<256;i++) { | |||
int r, g, b; | |||
r = (syspalette[i].peRed << 8) + 0x80; | |||
g = (syspalette[i].peGreen << 8) + 0x80; | |||
b = (syspalette[i].peBlue << 8) + 0x80; | |||
dib->setColour(i, r, g, b); | |||
} | |||
// - Update the DIB section to use the palette | |||
dib->refreshPalette(); | |||
} | |||
void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) | |||
{ | |||
// - If hCursor is null then there is no cursor - clear the old one | |||
@@ -211,10 +176,6 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) | |||
// Configure the cursor bitmap | |||
cursorBm.setSize(cursor.width(), cursor.height()); | |||
// Copy the palette into it if required | |||
if (format.bpp <= 8) | |||
copyDevicePaletteToDIB(device, &cursorBm); | |||
// Draw the cursor into the bitmap | |||
BitmapDC dc(device, cursorBm.bitmap); | |||
if (!DrawIconEx(dc, 0, 0, hCursor, 0, 0, 0, NULL, DI_NORMAL | DI_COMPAT)) | |||
@@ -231,7 +192,7 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) | |||
bool doOutline = false; | |||
if (!iconInfo.hbmColor) { | |||
Pixel xorColour = format.pixelFromRGB((rdr::U16)0, (rdr::U16)0, (rdr::U16)0, cursorBm.getColourMap()); | |||
Pixel xorColour = format.pixelFromRGB((rdr::U16)0, (rdr::U16)0, (rdr::U16)0); | |||
for (int y = 0; y < cursor.height(); y++) { | |||
for (int x = 0; x < cursor.width(); x++) { | |||
int byte = y * maskInfo.bmWidthBytes + x / 8; | |||
@@ -269,7 +230,7 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) | |||
if (doOutline) { | |||
vlog.debug("drawing cursor outline!"); | |||
memcpy(cursor.data, cursorBm.data, cursor.dataLen()); | |||
cursor.drawOutline(format.pixelFromRGB((rdr::U16)0xffff, (rdr::U16)0xffff, (rdr::U16)0xffff, cursorBm.getColourMap())); | |||
cursor.drawOutline(format.pixelFromRGB((rdr::U16)0xffff, (rdr::U16)0xffff, (rdr::U16)0xffff)); | |||
memcpy(cursorBm.data, cursor.data, cursor.dataLen()); | |||
} | |||
@@ -279,10 +240,3 @@ void DeviceFrameBuffer::setCursor(HCURSOR hCursor, VNCServer* server) | |||
vlog.error("%s", e.str()); | |||
} | |||
} | |||
void | |||
DeviceFrameBuffer::updateColourMap() { | |||
if (!format.trueColour) | |||
copyDevicePaletteToDIB(device, this); | |||
} |
@@ -79,7 +79,6 @@ namespace rfb { | |||
// - DeviceFrameBuffer specific methods | |||
void setCursor(HCURSOR c, VNCServer* server); | |||
void updateColourMap(); | |||
// Set whether grabRect should ignore errors or throw exceptions | |||
// Only set this if you are sure you'll capture the errors some other way! |
@@ -350,12 +350,6 @@ SDisplay::notifyDisplayEvent(WMMonitor::Notifier::DisplayEventType evt) { | |||
vlog.debug("desktop format changed"); | |||
recreatePixelBuffer(); | |||
break; | |||
case WMMonitor::Notifier::DisplayColourMapChanged: | |||
vlog.debug("desktop colormap changed"); | |||
pb->updateColourMap(); | |||
if (server) | |||
server->setColourMapEntries(); | |||
break; | |||
default: | |||
vlog.error("unknown display event received"); | |||
} |
@@ -45,12 +45,6 @@ WMMonitor::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) { | |||
notifier->notifyDisplayEvent(Notifier::DisplaySizeChanged); | |||
notifier->notifyDisplayEvent(Notifier::DisplayPixelFormatChanged); | |||
} | |||
break; | |||
case WM_SYSCOLORCHANGE: | |||
case WM_PALETTECHANGED: | |||
if (notifier) { | |||
notifier->notifyDisplayEvent(Notifier::DisplayColourMapChanged); | |||
} | |||
break; | |||
}; | |||
return MsgWindow::processMessage(msg, wParam, lParam); |
@@ -44,7 +44,7 @@ namespace rfb { | |||
class Notifier { | |||
public: | |||
typedef enum {DisplaySizeChanged, DisplayColourMapChanged, | |||
typedef enum {DisplaySizeChanged, | |||
DisplayPixelFormatChanged} DisplayEventType; | |||
virtual void notifyDisplayEvent(DisplayEventType evt) = 0; | |||
}; |