vncBuffer.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:11k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. // ScrBuffer implementation
  24. #include "stdhdrs.h"
  25. // Header
  26. #include "vncDesktop.h"
  27. #include "vncEncoder.h"
  28. #include "vncEncodeRRE.h"
  29. #include "vncEncodeCoRRE.h"
  30. #include "vncEncodeHexT.h"
  31. #include "MinMax.h"
  32. #include "vncBuffer.h"
  33. // Implementation
  34. vncBuffer::vncBuffer(vncDesktop *desktop)
  35. {
  36. m_desktop = desktop;
  37. m_encoder = NULL;
  38. m_mainbuff = NULL;
  39. m_backbuff = NULL;
  40. m_mainsize = 0;
  41. m_clientbuff = NULL;
  42. m_clientbuffsize = 0;
  43. m_clientfmtset = FALSE;
  44. // Initialise the screen buffers
  45. CheckBuffer();
  46. }
  47. vncBuffer::~vncBuffer()
  48. {
  49. if (m_mainbuff != NULL)
  50. {
  51. delete [] m_mainbuff;
  52. m_mainbuff = NULL;
  53. }
  54. if (m_backbuff != NULL)
  55. {
  56. delete [] m_backbuff;
  57. m_backbuff = NULL;
  58. }
  59. if (m_encoder != NULL)
  60. {
  61. delete m_encoder;
  62. m_encoder = NULL;
  63. }
  64. if (m_clientbuff != NULL)
  65. {
  66. delete m_clientbuff;
  67. m_clientbuff = NULL;
  68. }
  69. m_clientbuffsize = 0;
  70. m_mainsize = 0;
  71. }
  72. RECT
  73. vncBuffer::GetSize()
  74. {
  75. RECT rect;
  76. rect.left = 0;
  77. rect.top = 0;
  78. rect.right = m_scrinfo.framebufferWidth;
  79. rect.bottom = m_scrinfo.framebufferHeight;
  80. return rect;
  81. }
  82. rfbPixelFormat
  83. vncBuffer::GetLocalFormat()
  84. {
  85. return m_scrinfo.format;
  86. }
  87. BYTE *
  88. vncBuffer::GetClientBuffer()
  89. {
  90. return m_clientbuff;
  91. }
  92. BOOL
  93. vncBuffer::GetRemotePalette(RGBQUAD *quadlist, UINT ncolours)
  94. {
  95. // Try to get the RGBQUAD data from the encoder
  96. // This will only work if the remote client is palette-based,
  97. // in which case the encoder will be storing RGBQUAD data
  98. if (m_encoder == NULL)
  99. {
  100. log.Print(LL_INTWARN, VNCLOG("GetRemotePalette called but no encoder setn"));
  101. return FALSE;
  102. }
  103. // Now get the palette data
  104. return m_encoder->GetRemotePalette(quadlist, ncolours);
  105. }
  106. BOOL
  107. vncBuffer::CheckBuffer()
  108. {
  109. // Get the screen format, in case it has changed
  110. m_desktop->FillDisplayInfo(&m_scrinfo);
  111. // If the client has not specified a pixel format then set one for it
  112. if (!m_clientfmtset) {
  113.     m_clientfmtset = TRUE;
  114.     m_clientformat = m_scrinfo.format;
  115. }
  116. // If the client has not selected an encoding then set one for it
  117. if (m_encoder == NULL) {
  118.     if (!SetEncoding(rfbEncodingRaw))
  119. return FALSE;
  120. }
  121. m_bytesPerRow = m_scrinfo.framebufferWidth * m_scrinfo.format.bitsPerPixel/8;
  122. // Check the client buffer is sufficient
  123. const clientbuffsize =
  124.     m_encoder->RequiredBuffSize(m_scrinfo.framebufferWidth,
  125. m_scrinfo.framebufferHeight);
  126. if (m_clientbuffsize != clientbuffsize)
  127. {
  128.     if (m_clientbuff != NULL)
  129.     {
  130. delete [] m_clientbuff;
  131. m_clientbuff = NULL;
  132.     }
  133.     m_clientbuffsize = 0;
  134.     m_clientbuff = new BYTE [clientbuffsize];
  135.     if (m_clientbuff == NULL)
  136.     {
  137. log.Print(LL_INTERR, VNCLOG("unable to allocate client buffer[%d]n"), clientbuffsize);
  138. return FALSE;
  139.     }
  140.     m_clientbuffsize = clientbuffsize;
  141.     ZeroMemory(m_clientbuff, m_clientbuffsize);
  142. }
  143. // Check that the local format buffers are sufficient
  144. if (m_mainsize != m_desktop->ScreenBuffSize())
  145. {
  146. if (m_mainbuff != NULL)
  147. {
  148. delete [] m_mainbuff;
  149. m_mainbuff = NULL;
  150. }
  151. if (m_backbuff != NULL)
  152. {
  153. delete [] m_backbuff;
  154. m_backbuff = NULL;
  155. }
  156. m_mainsize = 0;
  157. if ((m_mainbuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)
  158. {
  159. log.Print(LL_INTERR, VNCLOG("unable to allocate main buffer[%d]n"), m_desktop->ScreenBuffSize());
  160. return FALSE;
  161. }
  162. if ((m_backbuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)
  163. {
  164. log.Print(LL_INTERR, VNCLOG("unable to allocate back buffer[%d]n"), m_desktop->ScreenBuffSize());
  165. return FALSE;
  166. }
  167. m_mainsize = m_desktop->ScreenBuffSize();
  168. ZeroMemory(m_mainbuff, m_mainsize);
  169. ZeroMemory(m_backbuff, m_mainsize);
  170. }
  171. log.Print(LL_INTINFO, VNCLOG("local buffer=%d, remote buffer=%dn"), m_mainsize, m_clientbuffsize);
  172. return TRUE;
  173. }
  174. // returns true if any *(p1+n) != *(p2+n) for 0<n<count-1
  175. inline static bool
  176. bytesdiff(BYTE *p1, BYTE *p2, int count) {
  177. for (int i=0; i<count; i++) {
  178. if (*(p1+i) != *(p2+i)) return true;
  179. }
  180. return false;
  181. }
  182. // New version of GetChangedRegion.  This version tries to avoid
  183. // sending too much unnecessary data.
  184. void
  185. vncBuffer::GetChangedRegion(vncRegion &rgn, RECT &rect)
  186. {
  187. const int BLOCK_SIZE = 32;
  188. const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;
  189. RECT new_rect;
  190. int x, y, ay, by;
  191. // Scan down the rectangle
  192. unsigned char *o_topleft_ptr = m_backbuff + (rect.top * m_bytesPerRow) + (rect.left * bytesPerPixel);
  193. unsigned char *n_topleft_ptr = m_mainbuff + (rect.top * m_bytesPerRow) + (rect.left * bytesPerPixel);
  194. for (y = rect.top; y<rect.bottom; y+=BLOCK_SIZE)
  195. {
  196. // Work out way down the bitmap
  197. unsigned char * o_row_ptr = o_topleft_ptr;
  198. unsigned char * n_row_ptr = n_topleft_ptr;
  199. const UINT blockbottom = Min(y+BLOCK_SIZE, rect.bottom);
  200. for (x = rect.left; x<rect.right; x+=BLOCK_SIZE)
  201. {
  202. // Work our way across the row
  203. unsigned char *n_block_ptr = n_row_ptr;
  204. unsigned char *o_block_ptr = o_row_ptr;
  205. const UINT blockright = Min(x+BLOCK_SIZE, rect.right);
  206. const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;
  207. // Scan this block
  208. for (ay = y; ay < blockbottom; ay++)
  209. {
  210. if (memcmp(n_block_ptr, o_block_ptr, bytesPerBlockRow) != 0)
  211. {
  212. // A pixel has changed, so this block needs updating
  213. new_rect.top = y;
  214. new_rect.left = x;
  215. new_rect.right = blockright;
  216. new_rect.bottom = blockbottom;
  217. rgn.AddRect(new_rect);
  218. // Copy the changes to the back buffer
  219. n_block_ptr = n_row_ptr;
  220. o_block_ptr = o_row_ptr;
  221. for (by = y; by < blockbottom; by++)
  222. {
  223. memcpy(o_block_ptr, n_block_ptr, bytesPerBlockRow);
  224. n_block_ptr+=m_bytesPerRow;
  225. o_block_ptr+=m_bytesPerRow;
  226. }
  227. break;
  228. }
  229. n_block_ptr += m_bytesPerRow;
  230. o_block_ptr += m_bytesPerRow;
  231. }
  232. o_row_ptr += bytesPerBlockRow;
  233. n_row_ptr += bytesPerBlockRow;
  234. }
  235. o_topleft_ptr += m_bytesPerRow * BLOCK_SIZE;
  236. n_topleft_ptr += m_bytesPerRow * BLOCK_SIZE;
  237. }
  238. }
  239. UINT
  240. vncBuffer::GetNumCodedRects(RECT &rect)
  241. {
  242. // Ask the encoder how many rectangles this update would become
  243. return m_encoder->NumCodedRects(rect);
  244. }
  245. void
  246. vncBuffer::GrabRect(RECT &rect)
  247. {
  248. m_desktop->CaptureScreen(rect, m_mainbuff, m_mainsize);
  249. }
  250. void
  251. vncBuffer::CopyRect(RECT &dest, POINT &source)
  252. {
  253. // Copy the data from one region of the back-buffer to another!
  254. BYTE *srcptr = m_backbuff + (source.y * m_bytesPerRow) +
  255. (source.x * m_scrinfo.format.bitsPerPixel/8);
  256. BYTE *destptr = m_backbuff + (dest.top * m_bytesPerRow) +
  257. (dest.left * m_scrinfo.format.bitsPerPixel/8);
  258. const UINT bytesPerLine = (dest.right-dest.left)*(m_scrinfo.format.bitsPerPixel/8);
  259. if (dest.top < source.y)
  260. {
  261. for (int y=dest.top; y < dest.bottom; y++)
  262. {
  263. memmove(destptr, srcptr, bytesPerLine);
  264. srcptr+=m_bytesPerRow;
  265. destptr+=m_bytesPerRow;
  266. }
  267. }
  268. else
  269. {
  270. srcptr += (m_bytesPerRow * ((dest.bottom-dest.top)-1));
  271. destptr += (m_bytesPerRow * ((dest.bottom-dest.top)-1));
  272. for (int y=dest.bottom; y > dest.top; y--)
  273. {
  274. memmove(destptr, srcptr, bytesPerLine);
  275. srcptr-=m_bytesPerRow;
  276. destptr-=m_bytesPerRow;
  277. }
  278. }
  279. }
  280. RECT
  281. vncBuffer::GrabMouse()
  282. {
  283. m_desktop->CaptureMouse(m_mainbuff, m_mainsize);
  284. return m_desktop->MouseRect();
  285. }
  286. BOOL
  287. vncBuffer::SetClientFormat(rfbPixelFormat &format)
  288. {
  289. log.Print(LL_INTINFO, VNCLOG("SetClientFormat calledn"));
  290. // Save the desired format
  291. m_clientfmtset = TRUE;
  292. m_clientformat = format;
  293. // Tell the encoder of the new format
  294. if (m_encoder != NULL)
  295. m_encoder->SetRemoteFormat(format);
  296. // Check that the output buffer is sufficient
  297. if (!CheckBuffer())
  298. return FALSE;
  299. return TRUE;
  300. }
  301. BOOL
  302. vncBuffer::SetEncoding(CARD32 encoding)
  303. {
  304. // Delete the old encoder
  305. if (m_encoder != NULL)
  306. {
  307. delete m_encoder;
  308. m_encoder = NULL;
  309. }
  310. // Returns FALSE if the desired encoding cannot be used
  311. switch(encoding)
  312. {
  313. case rfbEncodingRaw:
  314. log.Print(LL_INTINFO, VNCLOG("raw encoder requestedn"));
  315. // Create a RAW encoder
  316. m_encoder = new vncEncoder;
  317. if (m_encoder == NULL)
  318. return FALSE;
  319. break;
  320. case rfbEncodingRRE:
  321. log.Print(LL_INTINFO, VNCLOG("RRE encoder requestedn"));
  322. // Create a RRE encoder
  323. m_encoder = new vncEncodeRRE;
  324. if (m_encoder == NULL)
  325. return FALSE;
  326. break;
  327. case rfbEncodingCoRRE:
  328. log.Print(LL_INTINFO, VNCLOG("CoRRE encoder requestedn"));
  329. // Create a CoRRE encoder
  330. m_encoder = new vncEncodeCoRRE;
  331. if (m_encoder == NULL)
  332. return FALSE;
  333. break;
  334. case rfbEncodingHextile:
  335. log.Print(LL_INTINFO, VNCLOG("Hextile encoder requestedn"));
  336. // Create a CoRRE encoder
  337. m_encoder = new vncEncodeHexT;
  338. if (m_encoder == NULL)
  339. return FALSE;
  340. break;
  341. default:
  342. // An unknown encoding was specified
  343. log.Print(LL_INTERR, VNCLOG("unknown encoder requestedn"));
  344. return FALSE;
  345. }
  346. // Initialise it and give it the pixel format
  347. m_encoder->Init();
  348. m_encoder->SetLocalFormat(
  349. m_scrinfo.format,
  350. m_scrinfo.framebufferWidth,
  351. m_scrinfo.framebufferHeight);
  352. if (m_clientfmtset)
  353. if (!m_encoder->SetRemoteFormat(m_clientformat))
  354. {
  355. log.Print(LL_INTERR, VNCLOG("client pixel format is not supportedn"));
  356. return FALSE;
  357. }
  358. // Check that the client buffer is compatible
  359. return CheckBuffer();
  360. }
  361. void
  362. vncBuffer::Clear(RECT &rect)
  363. {
  364. log.Print(LL_INTINFO,
  365. VNCLOG("clearing rectangle (%d, %d)-(%d, %d)n"),
  366. rect.left, rect.top, rect.right, rect.bottom);
  367. // Update the contents of a region, to stop it from being marked as having changed
  368. BYTE *backptr = m_backbuff + (rect.top * m_bytesPerRow) + (rect.left * m_scrinfo.format.bitsPerPixel/8);
  369. BYTE *mainptr = m_mainbuff + (rect.top * m_bytesPerRow) + (rect.left * m_scrinfo.format.bitsPerPixel/8);
  370. const UINT bytesPerLine = (rect.right-rect.left)*(m_scrinfo.format.bitsPerPixel/8);
  371. for (int y=rect.top; y < rect.bottom; y++)
  372. {
  373. memcpy(backptr, mainptr, bytesPerLine);
  374. backptr+=m_bytesPerRow;
  375. mainptr+=m_bytesPerRow;
  376. }
  377. }
  378. // Routine to translate a rectangle between pixel formats
  379. UINT
  380. vncBuffer::TranslateRect(const RECT &rect)
  381. {
  382. // Call the encoder to encode the rectangle into the client buffer...
  383. return m_encoder->EncodeRect(m_mainbuff, m_clientbuff, rect);
  384. }