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.
+++ /dev/null
-/* 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
+++ /dev/null
-/* 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
// -=- 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
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);
// 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;
};
};
-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);
#include <rfb/ImageGetter.h>
#include <rfb/PixelFormat.h>
-#include <rfb/ColourMap.h>
#include <rfb/Rect.h>
#include <rfb/Pixel.h>
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();
///////////////////////////////////////////////
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_; }
PixelBuffer();
PixelFormat format;
int width_, height_;
- ColourMap* colourmap;
};
// FullFramePixelBuffer
class FullFramePixelBuffer : public PixelBuffer {
public:
FullFramePixelBuffer(const PixelFormat& pf, int width, int height,
- rdr::U8* data_, ColourMap* cm);
+ rdr::U8* data_);
virtual ~FullFramePixelBuffer();
protected:
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();
};
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)
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");
}
-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
g = *(src++);
b = *(src++);
- p = pixelFromRGB(r, g, b, cm);
+ p = pixelFromRGB(r, g, b);
bufferFromPixel(dst, p);
dst += bpp/8;
}
-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
p = pixelFromBuffer(src);
- rgbFromPixel(p, cm, &r, &g, &b);
+ rgbFromPixel(p, &r, &g, &b);
*(dst++) = r;
*(dst++) = g;
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;
}
#define __RFB_PIXELFORMAT_H__
#include <rfb/Pixel.h>
-#include <rfb/ColourMap.h>
namespace rdr { class InStream; class OutStream; }
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);
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);
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.
}
-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;
}
}
#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;
{ 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)
{
}
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;
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);
}
}
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
{
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:
// 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
bool economic;
PixelFormat inPF;
- ColourMap* inCM;
-
PixelFormat outPF;
- setCMFnType cmCallback;
- void *cbData;
- ColourCube* cube;
rdr::U8* table;
transFnType transFn;
}
}
-void SConnection::setInitialColourMap()
-{
-}
-
void SConnection::clientInit(bool shared)
{
writer_->writeServerInit();
{
SMsgHandler::setPixelFormat(pf);
readyForSetColourMapEntries = true;
+ if (!pf.trueColour)
+ writeFakeColourMap();
}
void SConnection::framebufferUpdateRequest(const Rect& r, bool incremental)
if (!readyForSetColourMapEntries) {
readyForSetColourMapEntries = true;
if (!cp.pf().trueColour) {
- setInitialColourMap();
+ writeFakeColourMap();
}
}
}
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);
+}
// 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
protected:
void setState(stateEnum s) { state_ = s; }
+ void writeFakeColourMap(void);
bool readyForSetColourMapEntries;
#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>
}
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();
}
class ConnParams;
class TransImageGetter;
- class ColourMap;
class Region;
class UpdateInfo;
class Encoder;
// 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();
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);
}
#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;
}
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)
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);
-}
namespace rfb {
class SMsgWriter;
- class ColourMap;
class PixelBuffer;
- class ColourCube;
class TransImageGetter : public ImageGetter,
public PixelTransformer {
// 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
// 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;
SMsgWriter* writer;
rdr::U8* table;
transFnType transFn;
- ColourCube* cube;
Point offset;
};
}
+++ /dev/null
-/* 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
}
}
-void VNCSConnectionST::setColourMapEntriesOrClose(int firstColour,int nColours)
-{
- try {
- setColourMapEntries(firstColour, nColours);
- } catch(rdr::Exception& e) {
- close(e.str());
- }
-}
-
void VNCSConnectionST::bellOrClose()
{
try {
writeFramebufferUpdate();
}
-void VNCSConnectionST::setInitialColourMap()
-{
- setColourMapEntries(0, 0);
-}
-
void VNCSConnectionST::fence(rdr::U32 flags, unsigned len, const char data[])
{
if (flags & fenceFlagRequest) {
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
// 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);
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);
void writeRenderedCursorRect();
void screenLayoutChange(rdr::U16 reason);
- void setColourMapEntries(int firstColour, int nColours);
void setCursor();
void setDesktopName(const char *name);
void setSocketTimeouts();
// 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;
}
}
-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;
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);
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();
}
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));
}
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--;
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++) {
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));
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++) {
}
}
- 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));
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;
#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)
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");
}
}
-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;
}
}
-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");
}
-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
}
#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)
}
}
-// 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
if (srcpf.isLittleEndian()) {
delete pt;
pt = new rfb::PixelTransformer;
- pt->init(srcpf, NULL, dstpf);
+ pt->init(srcpf, dstpf);
}
printf("%s,%s", srcb, dstb);
using namespace rfb;
XPixelBuffer::XPixelBuffer(Display *dpy, ImageFactory &factory,
- const Rect &rect, ColourMap* cm)
+ const Rect &rect)
: FullFramePixelBuffer(),
m_poller(0),
m_dpy(dpy),
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.
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.
};
-class XDesktop : public SDesktop, public ColourMap, public TXGlobalEventHandler
+class XDesktop : public SDesktop, public TXGlobalEventHandler
{
public:
XDesktop(Display* dpy_, Geometry *geometry_)
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;
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) {
extern char *display;
-#include "colormapst.h"
#ifdef RANDR
#include "randrstr.h"
#endif
: 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);
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();
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();
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);
}
} 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;
}
}
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)
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:
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);
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);
char** reason);
private:
- void setColourMapEntries(int firstColour, int nColours);
rfb::ScreenSet computeScreenLayout();
#ifdef RANDR
RRModePtr findRandRMode(RROutputPtr output, int width, int height);
rfb::HTTPServer* httpServer;
network::TcpListener* listener;
network::TcpListener* httpListener;
- ColormapPtr cmap;
int stride_;
bool deferredUpdateTimerSet;
bool grabbing;
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;
desktop[scr]->addClient(sock, false);
vlog.info("added inetd sock");
}
-
- } else {
- desktop[scr]->serverReset(screenInfo.screens[scr]);
}
vncHooksInit(screenInfo.screens[scr], desktop[scr]);
#if XORG < 110
RestoreAreasProcPtr RestoreAreas;
#endif
- InstallColormapProcPtr InstallColormap;
- StoreColorsProcPtr StoreColors;
DisplayCursorProcPtr DisplayCursor;
ScreenBlockHandlerProcPtr BlockHandler;
#ifdef RENDER
#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,
#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
#if XORG < 110
pScreen->RestoreAreas = vncHooksRestoreAreas;
#endif
- pScreen->InstallColormap = vncHooksInstallColormap;
- pScreen->StoreColors = vncHooksStoreColors;
pScreen->DisplayCursor = vncHooksDisplayCursor;
pScreen->BlockHandler = vncHooksBlockHandler;
#ifdef RENDER
#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
}
#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(
// 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),
void CConn::setColourMapEntries(int firstColour, int nColours, rdr::U16* rgbs)
{
- desktop->setColourMapEntries(firstColour, nColours, rgbs);
+ vlog.error("Invalid SetColourMapEntries from server!");
}
void CConn::bell()
}
-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);
}
// 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);
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
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());
}
}
-// 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.
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;
}
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(),
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;
}
-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;
#include <rfb/Region.h>
#include <rfb/Pixel.h>
-#include <rfb/ColourMap.h>
class Fl_Menu_Button;
class Fl_RGB_Image;
// 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);
static void handleUpdateTimeout(void *data);
- void commitColourMap();
-
static void handleClipboardChange(int source, void *data);
void handlePointerEvent(const rfb::Point& pos, int buttonMask);
CConn* cc;
PlatformPixelBuffer* frameBuffer;
-
rfb::PixelTransformer *pixelTrans;
- rfb::SimpleColourMap colourMap;
- bool colourMapChange;
-
rfb::Region damage;
rfb::Point lastPointerPos;
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;
}
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
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() {
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) {
}
-// * 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;
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_;
// 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);
if (new_bitmap) {
int bpp, depth;
- bool trueColour;
int redMax, greenMax, blueMax;
int redShift, greenShift, blueShift;
// 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);
-}
-
-
#include <windows.h>
#include <rfb/PixelBuffer.h>
#include <rfb/Region.h>
-#include <rfb/ColourMap.h>
#include <rfb/Exception.h>
namespace rfb {
// -=- DIBSectionBuffer
//
- class DIBSectionBuffer : public FullFramePixelBuffer, ColourMap {
+ class DIBSectionBuffer : public FullFramePixelBuffer {
public:
DIBSectionBuffer(HWND window);
DIBSectionBuffer(HDC device);
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;
// Configure the cursor buffer
cursorBm.setPF(format);
-
- // Set up a palette if required
- if (!format.trueColour)
- updateColourMap();
}
DeviceFrameBuffer::~DeviceFrameBuffer() {
}
-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
// 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))
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;
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());
}
vlog.error("%s", e.str());
}
}
-
-
-void
-DeviceFrameBuffer::updateColourMap() {
- if (!format.trueColour)
- copyDevicePaletteToDIB(device, this);
-}
// - 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!
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");
}
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);
class Notifier {
public:
- typedef enum {DisplaySizeChanged, DisplayColourMapChanged,
+ typedef enum {DisplaySizeChanged,
DisplayPixelFormatChanged} DisplayEventType;
virtual void notifyDisplayEvent(DisplayEventType evt) = 0;
};