4 * Routines to implement Hextile Encoding
8 * Copyright (C) 2002 RealVNC Ltd.
9 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
11 * This is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This software is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this software; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
30 static Bool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
31 static Bool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
32 static Bool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
36 * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
40 rfbSendRectEncodingHextile(cl, x, y, w, h)
44 rfbFramebufferUpdateRectHeader rect;
46 if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
47 if (!rfbSendUpdateBuf(cl))
51 rect.r.x = Swap16IfLE(x);
52 rect.r.y = Swap16IfLE(y);
53 rect.r.w = Swap16IfLE(w);
54 rect.r.h = Swap16IfLE(h);
55 rect.encoding = Swap32IfLE(rfbEncodingHextile);
57 memcpy(&updateBuf[ublen], (char *)&rect,
58 sz_rfbFramebufferUpdateRectHeader);
59 ublen += sz_rfbFramebufferUpdateRectHeader;
61 cl->rfbRectanglesSent[rfbEncodingHextile]++;
62 cl->rfbBytesSent[rfbEncodingHextile] += sz_rfbFramebufferUpdateRectHeader;
64 switch (cl->format.bitsPerPixel) {
66 return sendHextiles8(cl, x, y, w, h);
68 return sendHextiles16(cl, x, y, w, h);
70 return sendHextiles32(cl, x, y, w, h);
73 rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
78 #define PUT_PIXEL8(pix) (updateBuf[ublen++] = (pix))
80 #define PUT_PIXEL16(pix) (updateBuf[ublen++] = ((char*)&(pix))[0], \
81 updateBuf[ublen++] = ((char*)&(pix))[1])
83 #define PUT_PIXEL32(pix) (updateBuf[ublen++] = ((char*)&(pix))[0], \
84 updateBuf[ublen++] = ((char*)&(pix))[1], \
85 updateBuf[ublen++] = ((char*)&(pix))[2], \
86 updateBuf[ublen++] = ((char*)&(pix))[3])
89 #define DEFINE_SEND_HEXTILES(bpp) \
92 static Bool subrectEncode##bpp(CARD##bpp *data, int w, int h, CARD##bpp bg, \
93 CARD##bpp fg, Bool mono); \
94 static void testColours##bpp(CARD##bpp *data, int size, Bool *mono, \
95 Bool *solid, CARD##bpp *bg, CARD##bpp *fg); \
103 sendHextiles##bpp(cl, rx, ry, rw, rh) \
105 int rx, ry, rw, rh; \
110 CARD##bpp bg=0, fg=0, newBg, newFg; \
112 Bool validBg = FALSE; \
113 Bool validFg = FALSE; \
114 CARD##bpp clientPixelData[16*16*(bpp/8)]; \
116 for (y = ry; y < ry+rh; y += 16) { \
117 for (x = rx; x < rx+rw; x += 16) { \
119 if (rx+rw - x < 16) \
121 if (ry+rh - y < 16) \
124 if ((ublen + 1 + (2 + 16 * 16) * (bpp/8)) > UPDATE_BUF_SIZE) { \
125 if (!rfbSendUpdateBuf(cl)) \
129 fbptr = (rfbScreen.pfbMemory + (rfbScreen.paddedWidthInBytes * y) \
130 + (x * (rfbScreen.bitsPerPixel / 8))); \
132 (*cl->translateFn)(cl->translateLookupTable, &rfbServerFormat, \
133 &cl->format, fbptr, (char *)clientPixelData, \
134 rfbScreen.paddedWidthInBytes, w, h); \
136 startUblen = ublen; \
137 updateBuf[startUblen] = 0; \
140 testColours##bpp(clientPixelData, w * h, \
141 &mono, &solid, &newBg, &newFg); \
143 if (!validBg || (newBg != bg)) { \
146 updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
147 PUT_PIXEL##bpp(bg); \
151 cl->rfbBytesSent[rfbEncodingHextile] += ublen - startUblen; \
155 updateBuf[startUblen] |= rfbHextileAnySubrects; \
158 if (!validFg || (newFg != fg)) { \
161 updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
162 PUT_PIXEL##bpp(fg); \
166 updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
169 if (!subrectEncode##bpp(clientPixelData, w, h, bg, fg, mono)) { \
170 /* encoding was too large, use raw */ \
173 ublen = startUblen; \
174 updateBuf[ublen++] = rfbHextileRaw; \
175 (*cl->translateFn)(cl->translateLookupTable, \
176 &rfbServerFormat, &cl->format, fbptr, \
177 (char *)clientPixelData, \
178 rfbScreen.paddedWidthInBytes, w, h); \
180 memcpy(&updateBuf[ublen], (char *)clientPixelData, \
183 ublen += w * h * (bpp/8); \
186 cl->rfbBytesSent[rfbEncodingHextile] += ublen - startUblen; \
195 subrectEncode##bpp(CARD##bpp *data, int w, int h, CARD##bpp bg, \
196 CARD##bpp fg, Bool mono) \
201 int hx=0,hy,vx=0,vy; \
206 int thex,they,thew,theh; \
209 int nSubrectsUblen; \
211 nSubrectsUblen = ublen; \
214 for (y=0; y<h; y++) { \
216 for (x=0; x<w; x++) { \
217 if (line[x] != bg) { \
221 for (j=y; j<h; j++) { \
223 if (seg[x] != cl) {break;} \
225 while ((seg[i] == cl) && (i < w)) i += 1; \
227 if (j == y) vx = hx = i; \
228 if (i < vx) vx = i; \
229 if ((hyflag > 0) && (i >= hx)) { \
237 /* We now have two possible subrects: (x,y,hx,hy) and \
238 * (x,y,vx,vy). We'll choose the bigger of the two. \
248 if ((hw*hh) > (vw*vh)) { \
257 newLen = ublen - nSubrectsUblen + 2; \
259 newLen = ublen - nSubrectsUblen + bpp/8 + 2; \
262 if (newLen > (w * h * (bpp/8))) \
267 if (!mono) PUT_PIXEL##bpp(cl); \
269 updateBuf[ublen++] = rfbHextilePackXY(thex,they); \
270 updateBuf[ublen++] = rfbHextilePackWH(thew,theh); \
273 * Now mark the subrect as done. \
275 for (j=they; j < (they+theh); j++) { \
276 for (i=thex; i < (thex+thew); i++) { \
284 updateBuf[nSubrectsUblen] = numsubs; \
291 * testColours() tests if there are one (solid), two (mono) or more \
292 * colours in a tile and gets a reasonable guess at the best background \
293 * pixel, and the foreground pixel for mono. \
297 testColours##bpp(data,size,mono,solid,bg,fg) \
305 CARD##bpp colour1=0, colour2=0; \
306 int n1 = 0, n2 = 0; \
310 for (; size > 0; size--, data++) { \
315 if (*data == colour1) { \
325 if (*data == colour2) { \
343 DEFINE_SEND_HEXTILES(8)
344 DEFINE_SEND_HEXTILES(16)
345 DEFINE_SEND_HEXTILES(32)