2
* translate.c - translate between different pixel formats
6
* OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
7
* Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
10
* This is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This software is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this software; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
27
#include <rfb/rfbregion.h>
29
static void PrintPixelFormat(rfbPixelFormat *pf);
30
static rfbBool rfbSetClientColourMapBGR233(rfbClientPtr cl);
32
rfbBool rfbEconomicTranslate = FALSE;
35
* Some standard pixel formats.
38
static const rfbPixelFormat BGR233Format = {
39
8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0
44
* Macro to compare pixel formats.
48
((x.bitsPerPixel == y.bitsPerPixel) && \
49
(x.depth == y.depth) && \
50
((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && \
51
(x.trueColour == y.trueColour) && \
52
(!x.trueColour || ((x.redMax == y.redMax) && \
53
(x.greenMax == y.greenMax) && \
54
(x.blueMax == y.blueMax) && \
55
(x.redShift == y.redShift) && \
56
(x.greenShift == y.greenShift) && \
57
(x.blueShift == y.blueShift))))
59
#define CONCAT2(a,b) a##b
60
#define CONCAT2E(a,b) CONCAT2(a,b)
61
#define CONCAT3(a,b,c) a##b##c
62
#define CONCAT3E(a,b,c) CONCAT3(a,b,c)
63
#define CONCAT4(a,b,c,d) a##b##c##d
64
#define CONCAT4E(a,b,c,d) CONCAT4(a,b,c,d)
70
#include "tableinitcmtemplate.c"
71
#include "tableinittctemplate.c"
73
#include "tabletranstemplate.c"
76
#include "tabletranstemplate.c"
79
#include "tabletranstemplate.c"
84
#include "tableinitcmtemplate.c"
85
#include "tableinittctemplate.c"
87
#include "tabletranstemplate.c"
90
#include "tabletranstemplate.c"
93
#include "tabletranstemplate.c"
98
#include "tableinitcmtemplate.c"
99
#include "tableinittctemplate.c"
101
#include "tabletranstemplate.c"
104
#include "tabletranstemplate.c"
107
#include "tabletranstemplate.c"
112
#define COUNT_OFFSETS 4
113
#define BPP2OFFSET(bpp) ((bpp)/8-1)
114
#include "tableinit24.c"
116
#include "tabletrans24template.c"
119
#include "tabletrans24template.c"
122
#include "tabletrans24template.c"
125
#include "tabletrans24template.c"
128
#define COUNT_OFFSETS 3
129
#define BPP2OFFSET(bpp) ((int)(bpp)/16)
132
typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in,
133
rfbPixelFormat *out,rfbColourMap* cm);
134
typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in,
135
rfbPixelFormat *out);
137
rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = {
138
rfbInitColourMapSingleTable8,
139
rfbInitColourMapSingleTable16,
141
rfbInitColourMapSingleTable24,
143
rfbInitColourMapSingleTable32
146
rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = {
147
rfbInitTrueColourSingleTable8,
148
rfbInitTrueColourSingleTable16,
150
rfbInitTrueColourSingleTable24,
152
rfbInitTrueColourSingleTable32
155
rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = {
156
rfbInitTrueColourRGBTables8,
157
rfbInitTrueColourRGBTables16,
159
rfbInitTrueColourRGBTables24,
161
rfbInitTrueColourRGBTables32
164
rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
165
{ rfbTranslateWithSingleTable8to8,
166
rfbTranslateWithSingleTable8to16,
168
rfbTranslateWithSingleTable8to24,
170
rfbTranslateWithSingleTable8to32 },
171
{ rfbTranslateWithSingleTable16to8,
172
rfbTranslateWithSingleTable16to16,
174
rfbTranslateWithSingleTable16to24,
176
rfbTranslateWithSingleTable16to32 },
178
{ rfbTranslateWithSingleTable24to8,
179
rfbTranslateWithSingleTable24to16,
180
rfbTranslateWithSingleTable24to24,
181
rfbTranslateWithSingleTable24to32 },
183
{ rfbTranslateWithSingleTable32to8,
184
rfbTranslateWithSingleTable32to16,
186
rfbTranslateWithSingleTable32to24,
188
rfbTranslateWithSingleTable32to32 }
191
rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
192
{ rfbTranslateWithRGBTables8to8,
193
rfbTranslateWithRGBTables8to16,
195
rfbTranslateWithRGBTables8to24,
197
rfbTranslateWithRGBTables8to32 },
198
{ rfbTranslateWithRGBTables16to8,
199
rfbTranslateWithRGBTables16to16,
201
rfbTranslateWithRGBTables16to24,
203
rfbTranslateWithRGBTables16to32 },
205
{ rfbTranslateWithRGBTables24to8,
206
rfbTranslateWithRGBTables24to16,
207
rfbTranslateWithRGBTables24to24,
208
rfbTranslateWithRGBTables24to32 },
210
{ rfbTranslateWithRGBTables32to8,
211
rfbTranslateWithRGBTables32to16,
213
rfbTranslateWithRGBTables32to24,
215
rfbTranslateWithRGBTables32to32 }
221
* rfbTranslateNone is used when no translation is required.
225
rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
226
char *iptr, char *optr, int bytesBetweenInputLines,
227
int width, int height)
229
int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
232
memcpy(optr, iptr, bytesPerOutputLine);
233
iptr += bytesBetweenInputLines;
234
optr += bytesPerOutputLine;
241
* rfbSetTranslateFunction sets the translation function.
245
rfbSetTranslateFunction(cl)
248
rfbLog("Pixel format for client %s:\n",cl->host);
249
PrintPixelFormat(&cl->format);
252
* Check that bits per pixel values are valid
255
if ((cl->screen->rfbServerFormat.bitsPerPixel != 8) &&
256
(cl->screen->rfbServerFormat.bitsPerPixel != 16) &&
258
(cl->screen->rfbServerFormat.bitsPerPixel != 24) &&
260
(cl->screen->rfbServerFormat.bitsPerPixel != 32))
262
rfbErr("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
263
"rfbSetTranslateFunction",
264
cl->screen->rfbServerFormat.bitsPerPixel);
269
if ((cl->format.bitsPerPixel != 8) &&
270
(cl->format.bitsPerPixel != 16) &&
272
(cl->format.bitsPerPixel != 24) &&
274
(cl->format.bitsPerPixel != 32))
276
rfbErr("%s: client bits per pixel not 8, 16 or 32\n",
277
"rfbSetTranslateFunction");
282
if (!cl->format.trueColour && (cl->format.bitsPerPixel != 8)) {
283
rfbErr("rfbSetTranslateFunction: client has colour map "
284
"but %d-bit - can only cope with 8-bit colour maps\n",
285
cl->format.bitsPerPixel);
291
* bpp is valid, now work out how to translate
294
if (!cl->format.trueColour) {
296
* truecolour -> colour map
298
* Set client's colour map to BGR233, then effectively it's
302
if (!rfbSetClientColourMapBGR233(cl))
305
cl->format = BGR233Format;
308
/* truecolour -> truecolour */
310
if (PF_EQ(cl->format,cl->screen->rfbServerFormat)) {
312
/* client & server the same */
314
rfbLog("no translation needed\n");
315
cl->translateFn = rfbTranslateNone;
319
if ((cl->screen->rfbServerFormat.bitsPerPixel < 16) ||
320
((!cl->screen->rfbServerFormat.trueColour || !rfbEconomicTranslate) &&
321
(cl->screen->rfbServerFormat.bitsPerPixel == 16))) {
323
/* we can use a single lookup table for <= 16 bpp */
325
cl->translateFn = rfbTranslateWithSingleTableFns
326
[BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
327
[BPP2OFFSET(cl->format.bitsPerPixel)];
329
if(cl->screen->rfbServerFormat.trueColour)
330
(*rfbInitTrueColourSingleTableFns
331
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
332
&(cl->screen->rfbServerFormat), &cl->format);
334
(*rfbInitColourMapSingleTableFns
335
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
336
&(cl->screen->rfbServerFormat), &cl->format,&cl->screen->colourMap);
340
/* otherwise we use three separate tables for red, green and blue */
342
cl->translateFn = rfbTranslateWithRGBTablesFns
343
[BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
344
[BPP2OFFSET(cl->format.bitsPerPixel)];
346
(*rfbInitTrueColourRGBTablesFns
347
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
348
&(cl->screen->rfbServerFormat), &cl->format);
357
* rfbSetClientColourMapBGR233 sets the client's colour map so that it's
358
* just like an 8-bit BGR233 true colour client.
362
rfbSetClientColourMapBGR233(cl)
365
char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
366
rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
367
uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
371
if (cl->format.bitsPerPixel != 8 ) {
372
rfbErr("%s: client not 8 bits per pixel\n",
373
"rfbSetClientColourMapBGR233");
378
scme->type = rfbSetColourMapEntries;
380
scme->firstColour = Swap16IfLE(0);
381
scme->nColours = Swap16IfLE(256);
383
len = sz_rfbSetColourMapEntriesMsg;
387
for (b = 0; b < 4; b++) {
388
for (g = 0; g < 8; g++) {
389
for (r = 0; r < 8; r++) {
390
rgb[i++] = Swap16IfLE(r * 65535 / 7);
391
rgb[i++] = Swap16IfLE(g * 65535 / 7);
392
rgb[i++] = Swap16IfLE(b * 65535 / 3);
399
if (WriteExact(cl, buf, len) < 0) {
400
rfbLogPerror("rfbSetClientColourMapBGR233: write");
407
/* this function is not called very often, so it needn't be
411
* rfbSetClientColourMap is called to set the client's colour map. If the
412
* client is a true colour client, we simply update our own translation table
413
* and mark the whole screen as having been modified.
417
rfbSetClientColourMap(cl, firstColour, nColours)
422
if (cl->screen->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) {
427
nColours = cl->screen->colourMap.count;
430
if (cl->format.trueColour) {
431
(*rfbInitColourMapSingleTableFns
432
[BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
433
&cl->screen->rfbServerFormat, &cl->format,&cl->screen->colourMap);
435
sraRgnDestroy(cl->modifiedRegion);
437
sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
442
return rfbSendSetColourMapEntries(cl, firstColour, nColours);
447
* rfbSetClientColourMaps sets the colour map for each RFB client.
451
rfbSetClientColourMaps(rfbScreen, firstColour, nColours)
452
rfbScreenInfoPtr rfbScreen;
456
rfbClientIteratorPtr i;
459
i = rfbGetClientIterator(rfbScreen);
460
while((cl = rfbClientIteratorNext(i)))
461
rfbSetClientColourMap(cl, firstColour, nColours);
462
rfbReleaseClientIterator(i);
469
if (pf->bitsPerPixel == 1) {
470
rfbLog(" 1 bpp, %s sig bit in each byte is leftmost on the screen.\n",
471
(pf->bigEndian ? "most" : "least"));
473
rfbLog(" %d bpp, depth %d%s\n",pf->bitsPerPixel,pf->depth,
474
((pf->bitsPerPixel == 8) ? ""
475
: (pf->bigEndian ? ", big endian" : ", little endian")));
476
if (pf->trueColour) {
477
rfbLog(" true colour: max r %d g %d b %d, shift r %d g %d b %d\n",
478
pf->redMax, pf->greenMax, pf->blueMax,
479
pf->redShift, pf->greenShift, pf->blueShift);
481
rfbLog(" uses a colour map (not true colour).\n");