⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vncbuffer.cpp

📁 realvnc是一个非常流行的远程控制程序
💻 CPP
字号:
//  Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.////  This file is part of the VNC system.////  The VNC system 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 program 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 program; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,//  USA.//// If the source code for the VNC system is not available from the place // whence you received this file, check http://www.uk.research.att.com/vnc or contact// the authors on vnc@uk.research.att.com for information on obtaining it.// ScrBuffer implementation#include "stdhdrs.h"// Header#include "vncDesktop.h"#include "rfbMisc.h"#include "vncBuffer.h"// ImplementationvncBuffer::vncBuffer(){	m_freemainbuff = FALSE;	m_mainbuff = NULL;	m_backbuff = NULL;	m_backbuffsize = 0;	m_desktop=NULL;}vncBuffer::~vncBuffer(){	if (m_freemainbuff) {		// We need to free the slow-blit buffer		if (m_mainbuff != NULL)		{			delete [] m_mainbuff;			m_mainbuff = NULL;		}	}	if (m_backbuff != NULL)	{		delete [] m_backbuff;		m_backbuff = NULL;	}	m_backbuffsize = 0;}voidvncBuffer::SetDesktop(vncDesktop *desktop){	m_desktop=desktop;	CheckBuffer();}rfb::RectvncBuffer::GetSize(){	return rfb::Rect(0, 0, m_scrinfo.framebufferWidth, m_scrinfo.framebufferHeight);}rfbPixelFormatvncBuffer::GetLocalFormat(){	return m_scrinfo.format;}BOOLvncBuffer::CheckBuffer(){	// Get the screen format, in case it has changed	m_desktop->FillDisplayInfo(&m_scrinfo);	m_bytesPerRow = m_scrinfo.framebufferWidth * m_scrinfo.format.bitsPerPixel/8;	// Check that the local format buffers are sufficient	if ((m_backbuffsize != m_desktop->ScreenBuffSize()) || !m_freemainbuff)	{		vnclog.Print(LL_INTINFO, VNCLOG("request local buffer[%d]\n"), m_desktop->ScreenBuffSize());		if (m_freemainbuff) {			// Slow blits were enabled - free the slow blit buffer			if (m_mainbuff != NULL)			{				delete [] m_mainbuff;				m_mainbuff = NULL;			}		}		if (m_backbuff != NULL)		{			delete [] m_backbuff;			m_backbuff = NULL;		}		m_backbuffsize = 0;		// Check whether or not the vncDesktop is using fast blits		m_mainbuff = (BYTE *)m_desktop->OptimisedBlitBuffer();		if (m_mainbuff) {			// Prevent us from freeing the DIBsection buffer			m_freemainbuff = FALSE;			vnclog.Print(LL_INTINFO, VNCLOG("fast blits detected - using DIBsection buffer\n"));		} else {			// Create our own buffer to copy blits through			m_freemainbuff = TRUE;			if ((m_mainbuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)			{				vnclog.Print(LL_INTERR, VNCLOG("unable to allocate main buffer[%d]\n"), m_desktop->ScreenBuffSize());				return FALSE;			}			memset(m_mainbuff, 0, m_desktop->ScreenBuffSize());		}		// Always create a back buffer		if ((m_backbuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)		{			vnclog.Print(LL_INTERR, VNCLOG("unable to allocate back buffer[%d]\n"), m_desktop->ScreenBuffSize());			return FALSE;		}		memset(m_backbuff, 0, m_desktop->ScreenBuffSize());		m_backbuffsize = m_desktop->ScreenBuffSize();				// Clear the backbuffer		//memcpy(m_backbuff, m_mainbuff, m_desktop->ScreenBuffSize());	}	vnclog.Print(LL_INTINFO, VNCLOG("local buffer=%d\n"), m_backbuffsize);	return TRUE;}// Check a specified rectangle for changes and fill the region with// the changed subrects#pragma function(memcpy,memcmp)voidvncBuffer::CheckRect(rfb::Region2D &dest, const rfb::Rect &srcrect){	if (!FastCheckMainbuffer())		return;	const int BLOCK_SIZE = 32;	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;	rfb::Rect new_rect;	rfb::Rect srect = srcrect;	int x, y, ay, by;	// DWORD align the incoming rectangle.  (bPP will be 8, 16 or 32)	if (bytesPerPixel < 4) {		if (bytesPerPixel == 1)				// 1 byte per pixel			srect.tl.x -= (srect.tl.x & 3);	// round down to nearest multiple of 4		else								// 2 bytes per pixel			srect.tl.x -= (srect.tl.x & 1);	// round down to nearest multiple of 2	}	// Scan down the rectangle	unsigned char *o_topleft_ptr = m_backbuff + (srect.tl.y * m_bytesPerRow) + (srect.tl.x * bytesPerPixel);	unsigned char *n_topleft_ptr = m_mainbuff + (srect.tl.y * m_bytesPerRow) + (srect.tl.x * bytesPerPixel);	for (y = srect.tl.y; y<srect.br.y; y+=BLOCK_SIZE)	{		// Work out way down the bitmap		unsigned char * o_row_ptr = o_topleft_ptr;		unsigned char * n_row_ptr = n_topleft_ptr;		const UINT blockbottom = min(y+BLOCK_SIZE, srect.br.y);		for (x = srect.tl.x; x<srect.br.x; x+=BLOCK_SIZE)		{			// Work our way across the row			unsigned char *n_block_ptr = n_row_ptr;			unsigned char *o_block_ptr = o_row_ptr;			const UINT blockright = min(x+BLOCK_SIZE, srect.br.x);			const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;			// Scan this block			for (ay = y; ay < blockbottom; ay++)			{				if (memcmp(n_block_ptr, o_block_ptr, bytesPerBlockRow) != 0)				{					// A pixel has changed, so this block needs updating					new_rect.tl.y = y;					new_rect.tl.x = x;					new_rect.br.x = blockright;					new_rect.br.y = blockbottom;					dest = dest.union_(rfb::Region2D(new_rect));					// Copy the changes to the back buffer					for (by = ay; by < blockbottom; by++)					{						memcpy(o_block_ptr, n_block_ptr, bytesPerBlockRow);						n_block_ptr+=m_bytesPerRow;						o_block_ptr+=m_bytesPerRow;					}					break;				}				n_block_ptr += m_bytesPerRow;				o_block_ptr += m_bytesPerRow;			}			o_row_ptr += bytesPerBlockRow;			n_row_ptr += bytesPerBlockRow;		}		o_topleft_ptr += m_bytesPerRow * BLOCK_SIZE;		n_topleft_ptr += m_bytesPerRow * BLOCK_SIZE;	}}voidvncBuffer::GrabRegion(const rfb::Region2D &src){	rfb::RectVector rects;	rfb::RectVector::iterator i;	rfb::Rect grabRect;	//	// - Are there any rectangles to check?	//	src.get_rects(rects, 1, 1);	if (rects.empty()) return;	//	// - Grab the rectangles that may have changed	//	// The rectangles should have arrived in order of height	for (i = rects.begin(); i != rects.end(); i++)	{		rfb::Rect current = *i;		// Check that this rectangle is part of this capture region		if (current.tl.y > grabRect.br.y)		{			// If the existing rect is non-null the capture it			if (!grabRect.is_empty()) GrabRect(grabRect);			grabRect = current;		} else {			grabRect = current.union_boundary(grabRect);		}	}	// If there are still some rects to be done then do them	if (!grabRect.is_empty()) GrabRect(grabRect);}voidvncBuffer::CheckRegion(rfb::Region2D &dest, const rfb::Region2D &src){	rfb::RectVector rects;	rfb::RectVector::iterator i;	// If there is nothing to do then do nothing...	src.get_rects(rects, 1, 1);	if (rects.empty()) return;	//	// - Scan the specified rectangles for changes	//	for (i = rects.begin(); i != rects.end(); i++)	{		// Get the buffer to check for changes in the rect		CheckRect(dest, *i);	}}voidvncBuffer::GrabRect(const rfb::Rect &rect){	if (!FastCheckMainbuffer()) return;	m_desktop->CaptureScreen(rect, m_mainbuff, m_backbuffsize);}voidvncBuffer::CopyRect(const rfb::Rect &dest, const rfb::Point &delta){	rfb::Rect src = dest.translate(delta.negate());	// Copy the data from one part of the back-buffer to another!	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel/8;	const UINT bytesPerLine = (dest.br.x-dest.tl.x)*bytesPerPixel;	BYTE *srcptr = m_backbuff + (src.tl.y * m_bytesPerRow) +		(src.tl.x * bytesPerPixel);	BYTE *destptr = m_backbuff + (dest.tl.y * m_bytesPerRow) +		(dest.tl.x * bytesPerPixel);	// Copy the data around in the right order	if (dest.tl.y < src.tl.y)	{		for (int y=dest.tl.y; y < dest.br.y; y++)		{			memmove(destptr, srcptr, bytesPerLine);			srcptr+=m_bytesPerRow;			destptr+=m_bytesPerRow;		}	}	else	{		srcptr += (m_bytesPerRow * ((dest.br.y-dest.tl.y)-1));		destptr += (m_bytesPerRow * ((dest.br.y-dest.tl.y)-1));		for (int y=dest.br.y; y > dest.tl.y; y--)		{			memmove(destptr, srcptr, bytesPerLine);			srcptr-=m_bytesPerRow;			destptr-=m_bytesPerRow;		}	}}voidvncBuffer::GrabMouse(){	if (!FastCheckMainbuffer()) return;	m_desktop->CaptureMouse(m_mainbuff, m_backbuffsize);}voidvncBuffer::GetMousePos(rfb::Rect &rect){	rect = m_desktop->MouseRect();}voidvncBuffer::Clear(const rfb::Rect &rect){	if (!FastCheckMainbuffer())		return;	vnclog.Print(LL_INTINFO,		VNCLOG("clearing rectangle (%d, %d)-(%d, %d)\n"),		rect.tl.x, rect.tl.y, rect.br.x, rect.br.y);	// Update the contents of a region, to stop it from being marked as having changed	BYTE *backptr = m_backbuff + (rect.tl.y * m_bytesPerRow) + (rect.tl.x * m_scrinfo.format.bitsPerPixel/8);	BYTE *mainptr = m_mainbuff + (rect.tl.y * m_bytesPerRow) + (rect.tl.x * m_scrinfo.format.bitsPerPixel/8);	const UINT bytesPerLine = (rect.br.x-rect.tl.x)*(m_scrinfo.format.bitsPerPixel/8);	for (int y=rect.tl.y; y < rect.br.y; y++)	{		memcpy(backptr, mainptr, bytesPerLine);		backptr+=m_bytesPerRow;		mainptr+=m_bytesPerRow;	}}// Verify that the fast blit buffer hasn't changedinline BOOLvncBuffer::FastCheckMainbuffer() {	VOID *tmp = m_desktop->OptimisedBlitBuffer();	if (tmp && (m_mainbuff != tmp))		return CheckBuffer();	return TRUE;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -