~ubuntu-branches/debian/lenny/italc/lenny

« back to all changes in this revision

Viewing changes to common/ivs/libvncserver/translate.c

  • Committer: Bazaar Package Importer
  • Author(s): Patrick Winnertz
  • Date: 2008-06-17 13:46:54 UTC
  • mto: This revision was merged to the branch mainline in revision 5.
  • Revision ID: james.westby@ubuntu.com-20080617134654-2y5m7ki93r5c1ysf
Tags: upstream-1.0.9~rc3
ImportĀ upstreamĀ versionĀ 1.0.9~rc3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * translate.c - translate between different pixel formats
3
 
 */
4
 
 
5
 
/*
6
 
 *  OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
7
 
 *  Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.  
8
 
 *  All Rights Reserved.
9
 
 *
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.
14
 
 *
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.
19
 
 *
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,
23
 
 *  USA.
24
 
 */
25
 
 
26
 
#include <rfb/rfb.h>
27
 
#include <rfb/rfbregion.h>
28
 
 
29
 
static void PrintPixelFormat(rfbPixelFormat *pf);
30
 
static rfbBool rfbSetClientColourMapBGR233(rfbClientPtr cl);
31
 
 
32
 
rfbBool rfbEconomicTranslate = FALSE;
33
 
 
34
 
/*
35
 
 * Some standard pixel formats.
36
 
 */
37
 
 
38
 
static const rfbPixelFormat BGR233Format = {
39
 
    8, 8, 0, 1, 7, 7, 3, 0, 3, 6, 0, 0
40
 
};
41
 
 
42
 
 
43
 
/*
44
 
 * Macro to compare pixel formats.
45
 
 */
46
 
 
47
 
#define PF_EQ(x,y)                                                      \
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))))
58
 
 
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)
65
 
 
66
 
#undef OUT
67
 
#undef IN
68
 
 
69
 
#define OUT 8
70
 
#include "tableinitcmtemplate.c"
71
 
#include "tableinittctemplate.c"
72
 
#define IN 8
73
 
#include "tabletranstemplate.c"
74
 
#undef IN
75
 
#define IN 16
76
 
#include "tabletranstemplate.c"
77
 
#undef IN
78
 
#define IN 32
79
 
#include "tabletranstemplate.c"
80
 
#undef IN
81
 
#undef OUT
82
 
 
83
 
#define OUT 16
84
 
#include "tableinitcmtemplate.c"
85
 
#include "tableinittctemplate.c"
86
 
#define IN 8
87
 
#include "tabletranstemplate.c"
88
 
#undef IN
89
 
#define IN 16
90
 
#include "tabletranstemplate.c"
91
 
#undef IN
92
 
#define IN 32
93
 
#include "tabletranstemplate.c"
94
 
#undef IN
95
 
#undef OUT
96
 
 
97
 
#define OUT 32
98
 
#include "tableinitcmtemplate.c"
99
 
#include "tableinittctemplate.c"
100
 
#define IN 8
101
 
#include "tabletranstemplate.c"
102
 
#undef IN
103
 
#define IN 16
104
 
#include "tabletranstemplate.c"
105
 
#undef IN
106
 
#define IN 32
107
 
#include "tabletranstemplate.c"
108
 
#undef IN
109
 
#undef OUT
110
 
 
111
 
#ifdef ALLOW24BPP
112
 
#define COUNT_OFFSETS 4
113
 
#define BPP2OFFSET(bpp) ((bpp)/8-1)
114
 
#include "tableinit24.c"
115
 
#define BPP 8
116
 
#include "tabletrans24template.c"
117
 
#undef BPP
118
 
#define BPP 16
119
 
#include "tabletrans24template.c"
120
 
#undef BPP
121
 
#define BPP 24
122
 
#include "tabletrans24template.c"
123
 
#undef BPP
124
 
#define BPP 32
125
 
#include "tabletrans24template.c"
126
 
#undef BPP
127
 
#else
128
 
#define COUNT_OFFSETS 3
129
 
#define BPP2OFFSET(bpp) ((int)(bpp)/16)
130
 
#endif
131
 
 
132
 
typedef void (*rfbInitCMTableFnType)(char **table, rfbPixelFormat *in,
133
 
                                   rfbPixelFormat *out,rfbColourMap* cm);
134
 
typedef void (*rfbInitTableFnType)(char **table, rfbPixelFormat *in,
135
 
                                   rfbPixelFormat *out);
136
 
 
137
 
rfbInitCMTableFnType rfbInitColourMapSingleTableFns[COUNT_OFFSETS] = {
138
 
    rfbInitColourMapSingleTable8,
139
 
    rfbInitColourMapSingleTable16,
140
 
#ifdef ALLOW24BPP
141
 
    rfbInitColourMapSingleTable24,
142
 
#endif
143
 
    rfbInitColourMapSingleTable32
144
 
};
145
 
 
146
 
rfbInitTableFnType rfbInitTrueColourSingleTableFns[COUNT_OFFSETS] = {
147
 
    rfbInitTrueColourSingleTable8,
148
 
    rfbInitTrueColourSingleTable16,
149
 
#ifdef ALLOW24BPP
150
 
    rfbInitTrueColourSingleTable24,
151
 
#endif
152
 
    rfbInitTrueColourSingleTable32
153
 
};
154
 
 
155
 
rfbInitTableFnType rfbInitTrueColourRGBTablesFns[COUNT_OFFSETS] = {
156
 
    rfbInitTrueColourRGBTables8,
157
 
    rfbInitTrueColourRGBTables16,
158
 
#ifdef ALLOW24BPP
159
 
    rfbInitTrueColourRGBTables24,
160
 
#endif
161
 
    rfbInitTrueColourRGBTables32
162
 
};
163
 
 
164
 
rfbTranslateFnType rfbTranslateWithSingleTableFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
165
 
    { rfbTranslateWithSingleTable8to8,
166
 
      rfbTranslateWithSingleTable8to16,
167
 
#ifdef ALLOW24BPP
168
 
      rfbTranslateWithSingleTable8to24,
169
 
#endif
170
 
      rfbTranslateWithSingleTable8to32 },
171
 
    { rfbTranslateWithSingleTable16to8,
172
 
      rfbTranslateWithSingleTable16to16,
173
 
#ifdef ALLOW24BPP
174
 
      rfbTranslateWithSingleTable16to24,
175
 
#endif
176
 
      rfbTranslateWithSingleTable16to32 },
177
 
#ifdef ALLOW24BPP
178
 
    { rfbTranslateWithSingleTable24to8,
179
 
      rfbTranslateWithSingleTable24to16,
180
 
      rfbTranslateWithSingleTable24to24,
181
 
      rfbTranslateWithSingleTable24to32 },
182
 
#endif
183
 
    { rfbTranslateWithSingleTable32to8,
184
 
      rfbTranslateWithSingleTable32to16,
185
 
#ifdef ALLOW24BPP
186
 
      rfbTranslateWithSingleTable32to24,
187
 
#endif
188
 
      rfbTranslateWithSingleTable32to32 }
189
 
};
190
 
 
191
 
rfbTranslateFnType rfbTranslateWithRGBTablesFns[COUNT_OFFSETS][COUNT_OFFSETS] = {
192
 
    { rfbTranslateWithRGBTables8to8,
193
 
      rfbTranslateWithRGBTables8to16,
194
 
#ifdef ALLOW24BPP
195
 
      rfbTranslateWithRGBTables8to24,
196
 
#endif
197
 
      rfbTranslateWithRGBTables8to32 },
198
 
    { rfbTranslateWithRGBTables16to8,
199
 
      rfbTranslateWithRGBTables16to16,
200
 
#ifdef ALLOW24BPP
201
 
      rfbTranslateWithRGBTables16to24,
202
 
#endif
203
 
      rfbTranslateWithRGBTables16to32 },
204
 
#ifdef ALLOW24BPP
205
 
    { rfbTranslateWithRGBTables24to8,
206
 
      rfbTranslateWithRGBTables24to16,
207
 
      rfbTranslateWithRGBTables24to24,
208
 
      rfbTranslateWithRGBTables24to32 },
209
 
#endif
210
 
    { rfbTranslateWithRGBTables32to8,
211
 
      rfbTranslateWithRGBTables32to16,
212
 
#ifdef ALLOW24BPP
213
 
      rfbTranslateWithRGBTables32to24,
214
 
#endif
215
 
      rfbTranslateWithRGBTables32to32 }
216
 
};
217
 
 
218
 
 
219
 
 
220
 
/*
221
 
 * rfbTranslateNone is used when no translation is required.
222
 
 */
223
 
 
224
 
void
225
 
rfbTranslateNone(char *table, rfbPixelFormat *in, rfbPixelFormat *out,
226
 
                 char *iptr, char *optr, int bytesBetweenInputLines,
227
 
                 int width, int height)
228
 
{
229
 
    int bytesPerOutputLine = width * (out->bitsPerPixel / 8);
230
 
 
231
 
    while (height > 0) {
232
 
        memcpy(optr, iptr, bytesPerOutputLine);
233
 
        iptr += bytesBetweenInputLines;
234
 
        optr += bytesPerOutputLine;
235
 
        height--;
236
 
    }
237
 
}
238
 
 
239
 
 
240
 
/*
241
 
 * rfbSetTranslateFunction sets the translation function.
242
 
 */
243
 
 
244
 
rfbBool
245
 
rfbSetTranslateFunction(cl)
246
 
    rfbClientPtr cl;
247
 
{
248
 
    rfbLog("Pixel format for client %s:\n",cl->host);
249
 
    PrintPixelFormat(&cl->format);
250
 
 
251
 
    /*
252
 
     * Check that bits per pixel values are valid
253
 
     */
254
 
 
255
 
    if ((cl->screen->rfbServerFormat.bitsPerPixel != 8) &&
256
 
        (cl->screen->rfbServerFormat.bitsPerPixel != 16) &&
257
 
#ifdef ALLOW24BPP
258
 
        (cl->screen->rfbServerFormat.bitsPerPixel != 24) &&
259
 
#endif
260
 
        (cl->screen->rfbServerFormat.bitsPerPixel != 32))
261
 
    {
262
 
        rfbErr("%s: server bits per pixel not 8, 16 or 32 (is %d)\n",
263
 
               "rfbSetTranslateFunction", 
264
 
               cl->screen->rfbServerFormat.bitsPerPixel);
265
 
        rfbCloseClient(cl);
266
 
        return FALSE;
267
 
    }
268
 
 
269
 
    if ((cl->format.bitsPerPixel != 8) &&
270
 
        (cl->format.bitsPerPixel != 16) &&
271
 
#ifdef ALLOW24BPP
272
 
        (cl->format.bitsPerPixel != 24) &&
273
 
#endif
274
 
        (cl->format.bitsPerPixel != 32))
275
 
    {
276
 
        rfbErr("%s: client bits per pixel not 8, 16 or 32\n",
277
 
                "rfbSetTranslateFunction");
278
 
        rfbCloseClient(cl);
279
 
        return FALSE;
280
 
    }
281
 
 
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);
286
 
        rfbCloseClient(cl);
287
 
        return FALSE;
288
 
    }
289
 
 
290
 
    /*
291
 
     * bpp is valid, now work out how to translate
292
 
     */
293
 
 
294
 
    if (!cl->format.trueColour) {
295
 
        /*
296
 
         * truecolour -> colour map
297
 
         *
298
 
         * Set client's colour map to BGR233, then effectively it's
299
 
         * truecolour as well
300
 
         */
301
 
 
302
 
        if (!rfbSetClientColourMapBGR233(cl))
303
 
            return FALSE;
304
 
 
305
 
        cl->format = BGR233Format;
306
 
    }
307
 
 
308
 
    /* truecolour -> truecolour */
309
 
 
310
 
    if (PF_EQ(cl->format,cl->screen->rfbServerFormat)) {
311
 
 
312
 
        /* client & server the same */
313
 
 
314
 
        rfbLog("no translation needed\n");
315
 
        cl->translateFn = rfbTranslateNone;
316
 
        return TRUE;
317
 
    }
318
 
 
319
 
    if ((cl->screen->rfbServerFormat.bitsPerPixel < 16) ||
320
 
        ((!cl->screen->rfbServerFormat.trueColour || !rfbEconomicTranslate) &&
321
 
           (cl->screen->rfbServerFormat.bitsPerPixel == 16))) {
322
 
 
323
 
        /* we can use a single lookup table for <= 16 bpp */
324
 
 
325
 
        cl->translateFn = rfbTranslateWithSingleTableFns
326
 
                              [BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
327
 
                                  [BPP2OFFSET(cl->format.bitsPerPixel)];
328
 
 
329
 
        if(cl->screen->rfbServerFormat.trueColour)
330
 
          (*rfbInitTrueColourSingleTableFns
331
 
           [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
332
 
                                                   &(cl->screen->rfbServerFormat), &cl->format);
333
 
        else
334
 
          (*rfbInitColourMapSingleTableFns
335
 
           [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
336
 
                                                   &(cl->screen->rfbServerFormat), &cl->format,&cl->screen->colourMap);
337
 
 
338
 
    } else {
339
 
 
340
 
        /* otherwise we use three separate tables for red, green and blue */
341
 
 
342
 
        cl->translateFn = rfbTranslateWithRGBTablesFns
343
 
                              [BPP2OFFSET(cl->screen->rfbServerFormat.bitsPerPixel)]
344
 
                                  [BPP2OFFSET(cl->format.bitsPerPixel)];
345
 
 
346
 
        (*rfbInitTrueColourRGBTablesFns
347
 
            [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
348
 
                                             &(cl->screen->rfbServerFormat), &cl->format);
349
 
    }
350
 
 
351
 
    return TRUE;
352
 
}
353
 
 
354
 
 
355
 
 
356
 
/*
357
 
 * rfbSetClientColourMapBGR233 sets the client's colour map so that it's
358
 
 * just like an 8-bit BGR233 true colour client.
359
 
 */
360
 
 
361
 
static rfbBool
362
 
rfbSetClientColourMapBGR233(cl)
363
 
    rfbClientPtr cl;
364
 
{
365
 
    char buf[sz_rfbSetColourMapEntriesMsg + 256 * 3 * 2];
366
 
    rfbSetColourMapEntriesMsg *scme = (rfbSetColourMapEntriesMsg *)buf;
367
 
    uint16_t *rgb = (uint16_t *)(&buf[sz_rfbSetColourMapEntriesMsg]);
368
 
    int i, len;
369
 
    int r, g, b;
370
 
 
371
 
    if (cl->format.bitsPerPixel != 8 ) {
372
 
        rfbErr("%s: client not 8 bits per pixel\n",
373
 
                "rfbSetClientColourMapBGR233");
374
 
        rfbCloseClient(cl);
375
 
        return FALSE;
376
 
    }
377
 
    
378
 
    scme->type = rfbSetColourMapEntries;
379
 
 
380
 
    scme->firstColour = Swap16IfLE(0);
381
 
    scme->nColours = Swap16IfLE(256);
382
 
 
383
 
    len = sz_rfbSetColourMapEntriesMsg;
384
 
 
385
 
    i = 0;
386
 
 
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);
393
 
            }
394
 
        }
395
 
    }
396
 
 
397
 
    len += 256 * 3 * 2;
398
 
 
399
 
    if (WriteExact(cl, buf, len) < 0) {
400
 
        rfbLogPerror("rfbSetClientColourMapBGR233: write");
401
 
        rfbCloseClient(cl);
402
 
        return FALSE;
403
 
    }
404
 
    return TRUE;
405
 
}
406
 
 
407
 
/* this function is not called very often, so it needn't be
408
 
   efficient. */
409
 
 
410
 
/*
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.
414
 
 */
415
 
 
416
 
rfbBool
417
 
rfbSetClientColourMap(cl, firstColour, nColours)
418
 
    rfbClientPtr cl;
419
 
    int firstColour;
420
 
    int nColours;
421
 
{
422
 
    if (cl->screen->rfbServerFormat.trueColour || !cl->readyForSetColourMapEntries) {
423
 
        return TRUE;
424
 
    }
425
 
 
426
 
    if (nColours == 0) {
427
 
        nColours = cl->screen->colourMap.count;
428
 
    }
429
 
 
430
 
    if (cl->format.trueColour) {
431
 
        (*rfbInitColourMapSingleTableFns
432
 
            [BPP2OFFSET(cl->format.bitsPerPixel)]) (&cl->translateLookupTable,
433
 
                                             &cl->screen->rfbServerFormat, &cl->format,&cl->screen->colourMap);
434
 
 
435
 
        sraRgnDestroy(cl->modifiedRegion);
436
 
        cl->modifiedRegion =
437
 
          sraRgnCreateRect(0,0,cl->screen->width,cl->screen->height);
438
 
 
439
 
        return TRUE;
440
 
    }
441
 
 
442
 
    return rfbSendSetColourMapEntries(cl, firstColour, nColours);
443
 
}
444
 
 
445
 
 
446
 
/*
447
 
 * rfbSetClientColourMaps sets the colour map for each RFB client.
448
 
 */
449
 
 
450
 
void
451
 
rfbSetClientColourMaps(rfbScreen, firstColour, nColours)
452
 
    rfbScreenInfoPtr rfbScreen;
453
 
    int firstColour;
454
 
    int nColours;
455
 
{
456
 
    rfbClientIteratorPtr i;
457
 
    rfbClientPtr cl;
458
 
 
459
 
    i = rfbGetClientIterator(rfbScreen);
460
 
    while((cl = rfbClientIteratorNext(i)))
461
 
      rfbSetClientColourMap(cl, firstColour, nColours);
462
 
    rfbReleaseClientIterator(i);
463
 
}
464
 
 
465
 
static void
466
 
PrintPixelFormat(pf)
467
 
    rfbPixelFormat *pf;
468
 
{
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"));
472
 
    } else {
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);
480
 
        } else {
481
 
            rfbLog("  uses a colour map (not true colour).\n");
482
 
        }
483
 
    }
484
 
}