You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DeviceContext.cxx 5.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2014 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #include <rfb_win32/DeviceContext.h>
  23. #include <rfb_win32/CompatibleBitmap.h>
  24. #include <rfb_win32/BitmapInfo.h>
  25. #include <rdr/Exception.h>
  26. #include <rfb/LogWriter.h>
  27. using namespace rfb;
  28. using namespace win32;
  29. static LogWriter vlog("DeviceContext");
  30. PixelFormat DeviceContext::getPF() const {
  31. return getPF(dc);
  32. }
  33. PixelFormat DeviceContext::getPF(HDC dc) {
  34. bool trueColour, bigEndian;
  35. int bpp, depth;
  36. int redMax, greenMax, blueMax;
  37. int redShift, greenShift, blueShift;
  38. CompatibleBitmap bitmap(dc, 1, 1);
  39. // -=- Get the bitmap format information
  40. BitmapInfo bi;
  41. memset(&bi, 0, sizeof(bi));
  42. bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  43. bi.bmiHeader.biBitCount = 0;
  44. if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
  45. throw rdr::SystemException("unable to determine device pixel format", GetLastError());
  46. }
  47. if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
  48. throw rdr::SystemException("unable to determine pixel shifts/palette", GetLastError());
  49. }
  50. // Set the initial format information
  51. trueColour = bi.bmiHeader.biBitCount > 8;
  52. bigEndian = 0;
  53. bpp = bi.bmiHeader.biBitCount;
  54. if (trueColour) {
  55. DWORD rMask=0, gMask=0, bMask=0;
  56. // Which true colour format is the DIB section using?
  57. switch (bi.bmiHeader.biCompression) {
  58. case BI_RGB:
  59. // Default RGB layout
  60. switch (bi.bmiHeader.biBitCount) {
  61. case 16:
  62. // RGB 555 - High Colour
  63. vlog.info("16-bit High Colour");
  64. rMask = 0x7c00;
  65. bMask = 0x001f;
  66. gMask = 0x03e0;
  67. break;
  68. case 24:
  69. case 32:
  70. // RGB 888 - True Colour
  71. vlog.info("24/32-bit High Colour");
  72. rMask = 0xff0000;
  73. gMask = 0x00ff00;
  74. bMask = 0x0000ff;
  75. break;
  76. default:
  77. vlog.error("bits per pixel %u not supported", bi.bmiHeader.biBitCount);
  78. throw rdr::Exception("unknown bits per pixel specified");
  79. };
  80. break;
  81. case BI_BITFIELDS:
  82. // Custom RGB layout
  83. rMask = bi.mask.red;
  84. gMask = bi.mask.green;
  85. bMask = bi.mask.blue;
  86. vlog.info("%d-bit BitFields: (%lx, %lx, %lx)",
  87. bi.bmiHeader.biBitCount, rMask, gMask, bMask);
  88. break;
  89. };
  90. // Convert the data we just retrieved
  91. initMaxAndShift(rMask, &redMax, &redShift);
  92. initMaxAndShift(gMask, &greenMax, &greenShift);
  93. initMaxAndShift(bMask, &blueMax, &blueShift);
  94. // Calculate the depth from the colour shifts
  95. depth = 0;
  96. Pixel bits = rMask | gMask | bMask;
  97. while (bits) {
  98. depth++;
  99. bits = bits >> 1;
  100. }
  101. // Check that the depth & bpp are valid
  102. if (depth > bpp) {
  103. vlog.error("depth exceeds bits per pixel!");
  104. bpp = depth;
  105. }
  106. // Correct the bits-per-pixel to something we're happy with
  107. if (bpp <= 16)
  108. bpp = 16;
  109. else if (bpp <= 32)
  110. bpp = 32;
  111. } else {
  112. // Palettised format - depth reflects number of colours,
  113. // but bits-per-pixel is ALWAYS 8
  114. depth = bpp;
  115. if (bpp < 8)
  116. bpp = 8;
  117. vlog.info("%d-colour palettised", 1<<depth);
  118. // Aren't really used, but set them to keep the compiler happy
  119. redMax = redShift = 0;
  120. greenMax = greenShift = 0;
  121. blueMax = blueShift = 0;
  122. }
  123. return PixelFormat(bpp, depth, bigEndian, trueColour,
  124. redMax, greenMax, blueMax,
  125. redShift, greenShift, blueShift);
  126. }
  127. Rect DeviceContext::getClipBox() const {
  128. return getClipBox(dc);
  129. }
  130. Rect DeviceContext::getClipBox(HDC dc) {
  131. // Get the display dimensions
  132. RECT cr;
  133. if (!GetClipBox(dc, &cr))
  134. throw rdr::SystemException("GetClipBox", GetLastError());
  135. return Rect(cr.left, cr.top, cr.right, cr.bottom);
  136. }
  137. DeviceDC::DeviceDC(const TCHAR* deviceName) {
  138. dc = ::CreateDC(_T("DISPLAY"), deviceName, NULL, NULL);
  139. if (!dc)
  140. throw rdr::SystemException("failed to create DeviceDC", GetLastError());
  141. }
  142. DeviceDC::~DeviceDC() {
  143. if (dc)
  144. DeleteDC(dc);
  145. }
  146. WindowDC::WindowDC(HWND wnd) : hwnd(wnd) {
  147. dc = GetDC(wnd);
  148. if (!dc)
  149. throw rdr::SystemException("GetDC failed", GetLastError());
  150. }
  151. WindowDC::~WindowDC() {
  152. if (dc)
  153. ReleaseDC(hwnd, dc);
  154. }
  155. CompatibleDC::CompatibleDC(HDC existing) {
  156. dc = CreateCompatibleDC(existing);
  157. if (!dc)
  158. throw rdr::SystemException("CreateCompatibleDC failed", GetLastError());
  159. }
  160. CompatibleDC::~CompatibleDC() {
  161. if (dc)
  162. DeleteDC(dc);
  163. }
  164. BitmapDC::BitmapDC(HDC hdc, HBITMAP hbitmap) : CompatibleDC(hdc){
  165. oldBitmap = (HBITMAP)SelectObject(dc, hbitmap);
  166. if (!oldBitmap)
  167. throw rdr::SystemException("SelectObject to CompatibleDC failed",
  168. GetLastError());
  169. }
  170. BitmapDC::~BitmapDC() {
  171. SelectObject(dc, oldBitmap);
  172. }