draw.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. #include "vnc.h"
  2. #include "vncv.h"
  3. static struct {
  4. char *name;
  5. int num;
  6. } enctab[] = {
  7. "copyrect", EncCopyRect,
  8. "corre", EncCorre,
  9. "hextile", EncHextile,
  10. "raw", EncRaw,
  11. "rre", EncRre,
  12. "mousewarp", EncMouseWarp,
  13. };
  14. static uchar *pixbuf;
  15. static uchar *linebuf;
  16. static int vpixb;
  17. static int pixb;
  18. static void (*pixcp)(uchar*, uchar*);
  19. static void
  20. vncrdcolor(Vnc *v, uchar *color)
  21. {
  22. vncrdbytes(v, color, vpixb);
  23. if(cvtpixels)
  24. (*cvtpixels)(color, color, 1);
  25. }
  26. void
  27. sendencodings(Vnc *v)
  28. {
  29. char *f[10];
  30. int enc[10], nenc, i, j, nf;
  31. nf = tokenize(encodings, f, nelem(f));
  32. nenc = 0;
  33. for(i=0; i<nf; i++) {
  34. for(j=0; j<nelem(enctab); j++)
  35. if(strcmp(f[i], enctab[j].name) == 0)
  36. break;
  37. if(j == nelem(enctab)) {
  38. print("warning: unknown encoding %s\n", f[i]);
  39. continue;
  40. }
  41. enc[nenc++] = enctab[j].num;
  42. }
  43. vnclock(v);
  44. vncwrchar(v, MSetEnc);
  45. vncwrchar(v, 0);
  46. vncwrshort(v, nenc);
  47. for(i=0; i<nenc; i++)
  48. vncwrlong(v, enc[i]);
  49. vncflush(v);
  50. vncunlock(v);
  51. }
  52. void
  53. requestupdate(Vnc *v, int incremental)
  54. {
  55. int x, y;
  56. lockdisplay(display);
  57. x = Dx(screen->r);
  58. y = Dy(screen->r);
  59. unlockdisplay(display);
  60. if(x > v->dim.x)
  61. x = v->dim.x;
  62. if(y > v->dim.y)
  63. y = v->dim.y;
  64. vnclock(v);
  65. vncwrchar(v, MFrameReq);
  66. vncwrchar(v, incremental);
  67. vncwrrect(v, Rpt(ZP, Pt(x, y)));
  68. vncflush(v);
  69. vncunlock(v);
  70. }
  71. static Rectangle
  72. clippixbuf(Rectangle r, int maxx, int maxy)
  73. {
  74. int y, h, stride1, stride2;
  75. if(r.min.x > maxx || r.min.y > maxy){
  76. r.max.x = 0;
  77. return r;
  78. }
  79. if(r.max.y > maxy)
  80. r.max.y = maxy;
  81. if(r.max.x <= maxx)
  82. return r;
  83. stride2 = Dx(r) * pixb;
  84. r.max.x = maxx;
  85. stride1 = Dx(r) * pixb;
  86. h = Dy(r);
  87. for(y = 0; y < h; y++)
  88. memmove(&pixbuf[y * stride1], &pixbuf[y * stride2], stride1);
  89. return r;
  90. }
  91. /* must be called with display locked */
  92. static void
  93. updatescreen(Rectangle r)
  94. {
  95. int b, bb;
  96. lockdisplay(display);
  97. if(r.max.x > Dx(screen->r) || r.max.y > Dy(screen->r)){
  98. r = clippixbuf(r, Dx(screen->r), Dy(screen->r));
  99. if(r.max.x == 0){
  100. unlockdisplay(display);
  101. return;
  102. }
  103. }
  104. /*
  105. * assume load image fails only because of resize
  106. */
  107. b = Dx(r) * pixb * Dy(r);
  108. bb = loadimage(screen, rectaddpt(r, screen->r.min), pixbuf, b);
  109. if(bb != b && verbose)
  110. fprint(2, "loadimage %d on %R for %R returned %d: %r\n", b, rectaddpt(r, screen->r.min), screen->r, bb);
  111. unlockdisplay(display);
  112. }
  113. static void
  114. fillrect(Rectangle r, int stride, uchar *color)
  115. {
  116. int x, xe, y, off;
  117. y = r.min.y;
  118. off = y * stride;
  119. for(; y < r.max.y; y++){
  120. xe = off + r.max.x * pixb;
  121. for(x = off + r.min.x * pixb; x < xe; x += pixb)
  122. (*pixcp)(&pixbuf[x], color);
  123. off += stride;
  124. }
  125. }
  126. static void
  127. loadbuf(Vnc *v, Rectangle r, int stride)
  128. {
  129. int off, y;
  130. if(cvtpixels){
  131. y = r.min.y;
  132. off = y * stride;
  133. for(; y < r.max.y; y++){
  134. vncrdbytes(v, linebuf, Dx(r) * vpixb);
  135. (*cvtpixels)(&pixbuf[off + r.min.x * pixb], linebuf, Dx(r));
  136. off += stride;
  137. }
  138. }else{
  139. y = r.min.y;
  140. off = y * stride;
  141. for(; y < r.max.y; y++){
  142. vncrdbytes(v, &pixbuf[off + r.min.x * pixb], Dx(r) * pixb);
  143. off += stride;
  144. }
  145. }
  146. }
  147. static Rectangle
  148. hexrect(ushort u)
  149. {
  150. int x, y, w, h;
  151. x = u>>12;
  152. y = (u>>8)&15;
  153. w = ((u>>4)&15)+1;
  154. h = (u&15)+1;
  155. return Rect(x, y, x+w, y+h);
  156. }
  157. static void
  158. dohextile(Vnc *v, Rectangle r, int stride)
  159. {
  160. ulong bg, fg, c;
  161. int enc, nsub, sx, sy, w, h, th, tw;
  162. Rectangle sr, ssr;
  163. fg = bg = 0;
  164. h = Dy(r);
  165. w = Dx(r);
  166. for(sy = 0; sy < h; sy += HextileDim){
  167. th = h - sy;
  168. if(th > HextileDim)
  169. th = HextileDim;
  170. for(sx = 0; sx < w; sx += HextileDim){
  171. tw = w - sx;
  172. if(tw > HextileDim)
  173. tw = HextileDim;
  174. sr = Rect(sx, sy, sx + tw, sy + th);
  175. enc = vncrdchar(v);
  176. if(enc & HextileRaw) {
  177. loadbuf(v, sr, stride);
  178. continue;
  179. }
  180. if(enc & HextileBack)
  181. vncrdcolor(v, (uchar*)&bg);
  182. fillrect(sr, stride, (uchar*)&bg);
  183. if(enc & HextileFore)
  184. vncrdcolor(v, (uchar*)&fg);
  185. if(enc & HextileRects) {
  186. nsub = vncrdchar(v);
  187. (*pixcp)((uchar*)&c, (uchar*)&fg);
  188. while(nsub-- > 0) {
  189. if(enc & HextileCols)
  190. vncrdcolor(v, (uchar*)&c);
  191. ssr = rectaddpt(hexrect(vncrdshort(v)), sr.min);
  192. fillrect(ssr, stride, (uchar*)&c);
  193. }
  194. }
  195. }
  196. }
  197. }
  198. static void
  199. dorectangle(Vnc *v)
  200. {
  201. ulong type;
  202. long n, stride;
  203. ulong color;
  204. Point p;
  205. Rectangle r, subr, maxr;
  206. r = vncrdrect(v);
  207. if(r.min.x == r.max.x || r.min.y == r.max.y)
  208. return;
  209. if(!rectinrect(r, Rpt(ZP, v->dim)))
  210. sysfatal("bad rectangle from server: %R not in %R", r, Rpt(ZP, v->dim));
  211. stride = Dx(r) * pixb;
  212. type = vncrdlong(v);
  213. switch(type) {
  214. default:
  215. sysfatal("bad rectangle encoding from server");
  216. break;
  217. case EncRaw:
  218. loadbuf(v, Rpt(ZP, Pt(Dx(r), Dy(r))), stride);
  219. updatescreen(r);
  220. break;
  221. case EncCopyRect:
  222. p = vncrdpoint(v);
  223. lockdisplay(display);
  224. p = addpt(p, screen->r.min);
  225. r = rectaddpt(r, screen->r.min);
  226. draw(screen, r, screen, nil, p);
  227. unlockdisplay(display);
  228. break;
  229. case EncRre:
  230. case EncCorre:
  231. maxr = Rpt(ZP, Pt(Dx(r), Dy(r)));
  232. n = vncrdlong(v);
  233. vncrdcolor(v, (uchar*)&color);
  234. fillrect(maxr, stride, (uchar*)&color);
  235. while(n-- > 0) {
  236. vncrdcolor(v, (uchar*)&color);
  237. if(type == EncRre)
  238. subr = vncrdrect(v);
  239. else
  240. subr = vncrdcorect(v);
  241. if(!rectinrect(subr, maxr))
  242. sysfatal("bad encoding from server");
  243. fillrect(subr, stride, (uchar*)&color);
  244. }
  245. updatescreen(r);
  246. break;
  247. case EncHextile:
  248. dohextile(v, r, stride);
  249. updatescreen(r);
  250. break;
  251. case EncMouseWarp:
  252. mousewarp(r.min);
  253. break;
  254. }
  255. }
  256. static void
  257. pixcp8(uchar *dst, uchar *src)
  258. {
  259. *dst = *src;
  260. }
  261. static void
  262. pixcp16(uchar *dst, uchar *src)
  263. {
  264. *(ushort*)dst = *(ushort*)src;
  265. }
  266. static void
  267. pixcp32(uchar *dst, uchar *src)
  268. {
  269. *(ulong*)dst = *(ulong*)src;
  270. }
  271. static void
  272. pixcp24(uchar *dst, uchar *src)
  273. {
  274. dst[0] = src[0];
  275. dst[1] = src[1];
  276. dst[2] = src[2];
  277. }
  278. static int
  279. calcpixb(int bpp)
  280. {
  281. if(bpp / 8 * 8 != bpp)
  282. sysfatal("can't handle your screen");
  283. return bpp / 8;
  284. }
  285. void
  286. readfromserver(Vnc *v)
  287. {
  288. uchar type;
  289. uchar junk[100];
  290. long n;
  291. vpixb = calcpixb(v->bpp);
  292. pixb = calcpixb(screen->depth);
  293. switch(pixb){
  294. case 1:
  295. pixcp = pixcp8;
  296. break;
  297. case 2:
  298. pixcp = pixcp16;
  299. break;
  300. case 3:
  301. pixcp = pixcp24;
  302. break;
  303. case 4:
  304. pixcp = pixcp32;
  305. break;
  306. default:
  307. sysfatal("can't handle your screen: bad depth %d", pixb);
  308. }
  309. linebuf = malloc(v->dim.x * vpixb);
  310. pixbuf = malloc(v->dim.x * pixb * v->dim.y);
  311. if(linebuf == nil || pixbuf == nil)
  312. sysfatal("can't allocate pix decompression storage");
  313. for(;;) {
  314. type = vncrdchar(v);
  315. switch(type) {
  316. default:
  317. sysfatal("bad message from server");
  318. break;
  319. case MFrameUpdate:
  320. vncrdchar(v);
  321. n = vncrdshort(v);
  322. while(n-- > 0)
  323. dorectangle(v);
  324. flushimage(display, 1);
  325. requestupdate(v, 1);
  326. break;
  327. case MSetCmap:
  328. vncrdbytes(v, junk, 3);
  329. n = vncrdshort(v);
  330. vncgobble(v, n*3*2);
  331. break;
  332. case MBell:
  333. break;
  334. case MSCut:
  335. vncrdbytes(v, junk, 3);
  336. n = vncrdlong(v);
  337. writesnarf(v, n);
  338. break;
  339. }
  340. }
  341. }