4 * Routines to implement Hextile Encoding
8 * OSXvnc Copyright (C) 2001 Dan McGuirk <mcguirk@incompleteness.net>.
9 * Original Xvnc code Copyright (C) 1999 AT&T Laboratories Cambridge.
10 * All Rights Reserved.
12 * This is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This software is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this software; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
30 static rfbBool sendHextiles8(rfbClientPtr cl, int x, int y, int w, int h);
31 static rfbBool sendHextiles16(rfbClientPtr cl, int x, int y, int w, int h);
32 static rfbBool sendHextiles32(rfbClientPtr cl, int x, int y, int w, int h);
36 * rfbSendRectEncodingHextile - send a rectangle using hextile encoding.
40 rfbSendRectEncodingHextile(rfbClientPtr cl,
46 rfbFramebufferUpdateRectHeader rect;
48 if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
49 if (!rfbSendUpdateBuf(cl))
53 rect.r.x = Swap16IfLE(x);
54 rect.r.y = Swap16IfLE(y);
55 rect.r.w = Swap16IfLE(w);
56 rect.r.h = Swap16IfLE(h);
57 rect.encoding = Swap32IfLE(rfbEncodingHextile);
59 memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
60 sz_rfbFramebufferUpdateRectHeader);
61 cl->ublen += sz_rfbFramebufferUpdateRectHeader;
63 rfbStatRecordEncodingSent(cl, rfbEncodingHextile,
64 sz_rfbFramebufferUpdateRectHeader,
65 sz_rfbFramebufferUpdateRectHeader + w * (cl->format.bitsPerPixel / 8) * h);
67 switch (cl->format.bitsPerPixel) {
69 return sendHextiles8(cl, x, y, w, h);
71 return sendHextiles16(cl, x, y, w, h);
73 return sendHextiles32(cl, x, y, w, h);
76 rfbLog("rfbSendRectEncodingHextile: bpp %d?\n", cl->format.bitsPerPixel);
81 #define PUT_PIXEL8(pix) (cl->updateBuf[cl->ublen++] = (pix))
83 #define PUT_PIXEL16(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
84 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1])
86 #define PUT_PIXEL32(pix) (cl->updateBuf[cl->ublen++] = ((char*)&(pix))[0], \
87 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[1], \
88 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[2], \
89 cl->updateBuf[cl->ublen++] = ((char*)&(pix))[3])
92 #define DEFINE_SEND_HEXTILES(bpp) \
95 static rfbBool subrectEncode##bpp(rfbClientPtr cli, uint##bpp##_t *data, \
96 int w, int h, uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono);\
97 static void testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, \
98 rfbBool *solid, uint##bpp##_t *bg, uint##bpp##_t *fg); \
106 sendHextiles##bpp(rfbClientPtr cl, int rx, int ry, int rw, int rh) { \
110 uint##bpp##_t bg = 0, fg = 0, newBg, newFg; \
111 rfbBool mono, solid; \
112 rfbBool validBg = FALSE; \
113 rfbBool validFg = FALSE; \
114 uint##bpp##_t 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 ((cl->ublen + 1 + (2 + 16 * 16) * (bpp/8)) > \
126 if (!rfbSendUpdateBuf(cl)) \
130 fbptr = (cl->scaledScreen->frameBuffer + (cl->scaledScreen->paddedWidthInBytes * y) \
131 + (x * (cl->scaledScreen->bitsPerPixel / 8))); \
133 (*cl->translateFn)(cl->translateLookupTable, &(cl->screen->serverFormat), \
134 &cl->format, fbptr, (char *)clientPixelData, \
135 cl->scaledScreen->paddedWidthInBytes, w, h); \
137 startUblen = cl->ublen; \
138 cl->updateBuf[startUblen] = 0; \
140 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
142 testColours##bpp(clientPixelData, w * h, \
143 &mono, &solid, &newBg, &newFg); \
145 if (!validBg || (newBg != bg)) { \
148 cl->updateBuf[startUblen] |= rfbHextileBackgroundSpecified; \
149 PUT_PIXEL##bpp(bg); \
156 cl->updateBuf[startUblen] |= rfbHextileAnySubrects; \
159 if (!validFg || (newFg != fg)) { \
162 cl->updateBuf[startUblen] |= rfbHextileForegroundSpecified; \
163 PUT_PIXEL##bpp(fg); \
167 cl->updateBuf[startUblen] |= rfbHextileSubrectsColoured; \
170 if (!subrectEncode##bpp(cl, clientPixelData, w, h, bg, fg, mono)) { \
171 /* encoding was too large, use raw */ \
174 cl->ublen = startUblen; \
175 cl->updateBuf[cl->ublen++] = rfbHextileRaw; \
176 (*cl->translateFn)(cl->translateLookupTable, \
177 &(cl->screen->serverFormat), &cl->format, fbptr, \
178 (char *)clientPixelData, \
179 cl->scaledScreen->paddedWidthInBytes, w, h); \
181 memcpy(&cl->updateBuf[cl->ublen], (char *)clientPixelData, \
184 cl->ublen += w * h * (bpp/8); \
185 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, \
196 subrectEncode##bpp(rfbClientPtr cl, uint##bpp##_t *data, int w, int h, \
197 uint##bpp##_t bg, uint##bpp##_t fg, rfbBool mono) \
202 int hx=0,hy,vx=0,vy; \
204 uint##bpp##_t *seg; \
205 uint##bpp##_t *line; \
207 int thex,they,thew,theh; \
210 int nSubrectsUblen; \
212 nSubrectsUblen = cl->ublen; \
214 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
216 for (y=0; y<h; y++) { \
218 for (x=0; x<w; x++) { \
219 if (line[x] != bg) { \
223 for (j=y; j<h; j++) { \
225 if (seg[x] != cl2) {break;} \
227 while ((seg[i] == cl2) && (i < w)) i += 1; \
229 if (j == y) vx = hx = i; \
230 if (i < vx) vx = i; \
231 if ((hyflag > 0) && (i >= hx)) { \
239 /* We now have two possible subrects: (x,y,hx,hy) and \
240 * (x,y,vx,vy). We'll choose the bigger of the two. \
250 if ((hw*hh) > (vw*vh)) { \
259 newLen = cl->ublen - nSubrectsUblen + 2; \
261 newLen = cl->ublen - nSubrectsUblen + bpp/8 + 2; \
264 if (newLen > (w * h * (bpp/8))) \
269 if (!mono) PUT_PIXEL##bpp(cl2); \
271 cl->updateBuf[cl->ublen++] = rfbHextilePackXY(thex,they); \
272 cl->updateBuf[cl->ublen++] = rfbHextilePackWH(thew,theh); \
273 rfbStatRecordEncodingSentAdd(cl, rfbEncodingHextile, 1); \
276 * Now mark the subrect as done. \
278 for (j=they; j < (they+theh); j++) { \
279 for (i=thex; i < (thex+thew); i++) { \
287 cl->updateBuf[nSubrectsUblen] = numsubs; \
294 * testColours() tests if there are one (solid), two (mono) or more \
295 * colours in a tile and gets a reasonable guess at the best background \
296 * pixel, and the foreground pixel for mono. \
300 testColours##bpp(uint##bpp##_t *data, int size, rfbBool *mono, rfbBool *solid, \
301 uint##bpp##_t *bg, uint##bpp##_t *fg) { \
302 uint##bpp##_t colour1 = 0, colour2 = 0; \
303 int n1 = 0, n2 = 0; \
307 for (; size > 0; size--, data++) { \
312 if (*data == colour1) { \
322 if (*data == colour2) { \
340 DEFINE_SEND_HEXTILES(8)
341 DEFINE_SEND_HEXTILES(16)
342 DEFINE_SEND_HEXTILES(32)