Initial commit
This commit is contained in:
200
win/rfb_win32/DeviceContext.cxx
Normal file
200
win/rfb_win32/DeviceContext.cxx
Normal file
@@ -0,0 +1,200 @@
|
||||
/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
|
||||
* Copyright 2014 Pierre Ossman for Cendio AB
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this software; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include <rfb_win32/DeviceContext.h>
|
||||
#include <rfb_win32/CompatibleBitmap.h>
|
||||
#include <rfb_win32/BitmapInfo.h>
|
||||
#include <rdr/Exception.h>
|
||||
#include <rfb/LogWriter.h>
|
||||
|
||||
using namespace rfb;
|
||||
using namespace win32;
|
||||
|
||||
|
||||
static LogWriter vlog("DeviceContext");
|
||||
|
||||
PixelFormat DeviceContext::getPF() const {
|
||||
return getPF(dc);
|
||||
}
|
||||
|
||||
PixelFormat DeviceContext::getPF(HDC dc) {
|
||||
bool trueColour, bigEndian;
|
||||
int bpp, depth;
|
||||
int redMax, greenMax, blueMax;
|
||||
int redShift, greenShift, blueShift;
|
||||
|
||||
CompatibleBitmap bitmap(dc, 1, 1);
|
||||
|
||||
// -=- Get the bitmap format information
|
||||
BitmapInfo bi;
|
||||
memset(&bi, 0, sizeof(bi));
|
||||
bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bi.bmiHeader.biBitCount = 0;
|
||||
if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
|
||||
throw rdr::SystemException("unable to determine device pixel format", GetLastError());
|
||||
}
|
||||
if (!::GetDIBits(dc, bitmap, 0, 1, NULL, (BITMAPINFO*)&bi, DIB_RGB_COLORS)) {
|
||||
throw rdr::SystemException("unable to determine pixel shifts/palette", GetLastError());
|
||||
}
|
||||
|
||||
// Set the initial format information
|
||||
trueColour = bi.bmiHeader.biBitCount > 8;
|
||||
bigEndian = 0;
|
||||
bpp = bi.bmiHeader.biBitCount;
|
||||
|
||||
if (trueColour) {
|
||||
DWORD rMask=0, gMask=0, bMask=0;
|
||||
|
||||
// Which true colour format is the DIB section using?
|
||||
switch (bi.bmiHeader.biCompression) {
|
||||
case BI_RGB:
|
||||
// Default RGB layout
|
||||
switch (bi.bmiHeader.biBitCount) {
|
||||
case 16:
|
||||
// RGB 555 - High Colour
|
||||
vlog.info("16-bit High Colour");
|
||||
rMask = 0x7c00;
|
||||
bMask = 0x001f;
|
||||
gMask = 0x03e0;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
// RGB 888 - True Colour
|
||||
vlog.info("24/32-bit High Colour");
|
||||
rMask = 0xff0000;
|
||||
gMask = 0x00ff00;
|
||||
bMask = 0x0000ff;
|
||||
break;
|
||||
default:
|
||||
vlog.error("bits per pixel %u not supported", bi.bmiHeader.biBitCount);
|
||||
throw rdr::Exception("unknown bits per pixel specified");
|
||||
};
|
||||
break;
|
||||
case BI_BITFIELDS:
|
||||
// Custom RGB layout
|
||||
rMask = bi.mask.red;
|
||||
gMask = bi.mask.green;
|
||||
bMask = bi.mask.blue;
|
||||
vlog.info("%d-bit BitFields: (%lx, %lx, %lx)",
|
||||
bi.bmiHeader.biBitCount, rMask, gMask, bMask);
|
||||
break;
|
||||
};
|
||||
|
||||
// Convert the data we just retrieved
|
||||
initMaxAndShift(rMask, &redMax, &redShift);
|
||||
initMaxAndShift(gMask, &greenMax, &greenShift);
|
||||
initMaxAndShift(bMask, &blueMax, &blueShift);
|
||||
|
||||
// Calculate the depth from the colour shifts
|
||||
depth = 0;
|
||||
Pixel bits = rMask | gMask | bMask;
|
||||
while (bits) {
|
||||
depth++;
|
||||
bits = bits >> 1;
|
||||
}
|
||||
|
||||
// Check that the depth & bpp are valid
|
||||
if (depth > bpp) {
|
||||
vlog.error("depth exceeds bits per pixel!");
|
||||
bpp = depth;
|
||||
}
|
||||
|
||||
// Correct the bits-per-pixel to something we're happy with
|
||||
if (bpp <= 16)
|
||||
bpp = 16;
|
||||
else if (bpp <= 32)
|
||||
bpp = 32;
|
||||
} else {
|
||||
// Palettised format - depth reflects number of colours,
|
||||
// but bits-per-pixel is ALWAYS 8
|
||||
depth = bpp;
|
||||
if (bpp < 8)
|
||||
bpp = 8;
|
||||
vlog.info("%d-colour palettised", 1<<depth);
|
||||
// Aren't really used, but set them to keep the compiler happy
|
||||
redMax = redShift = 0;
|
||||
greenMax = greenShift = 0;
|
||||
blueMax = blueShift = 0;
|
||||
}
|
||||
|
||||
|
||||
return PixelFormat(bpp, depth, bigEndian, trueColour,
|
||||
redMax, greenMax, blueMax,
|
||||
redShift, greenShift, blueShift);
|
||||
}
|
||||
|
||||
Rect DeviceContext::getClipBox() const {
|
||||
return getClipBox(dc);
|
||||
}
|
||||
|
||||
Rect DeviceContext::getClipBox(HDC dc) {
|
||||
// Get the display dimensions
|
||||
RECT cr;
|
||||
if (!GetClipBox(dc, &cr))
|
||||
throw rdr::SystemException("GetClipBox", GetLastError());
|
||||
return Rect(cr.left, cr.top, cr.right, cr.bottom);
|
||||
}
|
||||
|
||||
|
||||
DeviceDC::DeviceDC(const TCHAR* deviceName) {
|
||||
dc = ::CreateDC(_T("DISPLAY"), deviceName, NULL, NULL);
|
||||
if (!dc)
|
||||
throw rdr::SystemException("failed to create DeviceDC", GetLastError());
|
||||
}
|
||||
|
||||
DeviceDC::~DeviceDC() {
|
||||
if (dc)
|
||||
DeleteDC(dc);
|
||||
}
|
||||
|
||||
|
||||
WindowDC::WindowDC(HWND wnd) : hwnd(wnd) {
|
||||
dc = GetDC(wnd);
|
||||
if (!dc)
|
||||
throw rdr::SystemException("GetDC failed", GetLastError());
|
||||
}
|
||||
|
||||
WindowDC::~WindowDC() {
|
||||
if (dc)
|
||||
ReleaseDC(hwnd, dc);
|
||||
}
|
||||
|
||||
|
||||
CompatibleDC::CompatibleDC(HDC existing) {
|
||||
dc = CreateCompatibleDC(existing);
|
||||
if (!dc)
|
||||
throw rdr::SystemException("CreateCompatibleDC failed", GetLastError());
|
||||
}
|
||||
|
||||
CompatibleDC::~CompatibleDC() {
|
||||
if (dc)
|
||||
DeleteDC(dc);
|
||||
}
|
||||
|
||||
|
||||
BitmapDC::BitmapDC(HDC hdc, HBITMAP hbitmap) : CompatibleDC(hdc){
|
||||
oldBitmap = (HBITMAP)SelectObject(dc, hbitmap);
|
||||
if (!oldBitmap)
|
||||
throw rdr::SystemException("SelectObject to CompatibleDC failed",
|
||||
GetLastError());
|
||||
}
|
||||
|
||||
BitmapDC::~BitmapDC() {
|
||||
SelectObject(dc, oldBitmap);
|
||||
}
|
||||
Reference in New Issue
Block a user