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

📄 vncbuffer.cpp

📁 teamviewer source code vc++
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//  Copyright (C) 2006 Teamviewer GmbH. All Rights Reserved.
//  Copyright (C) 2002 Ultr@VNC Team Members. All Rights Reserved.
//  Copyright (C) 2000-2002 Const Kaplinsky. All Rights Reserved.
//  Copyright (C) 2002 RealVNC Ltd. All Rights Reserved.
//  Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
//
//  This file is part of TeamViewer.
//
//  TeamViewer 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 TeamViewer is not available from the place 
//  whence you received this file, check http://www.teamviewer.com
//  for information on obtaining it.


// ScrBuffer implementation

#include "stdhdrs.h"

// Header

#include "vncDesktop.h"
#include "vncBuffer.h"

// Implementation

vncBuffer::vncBuffer()
{
	m_freemainbuff = FALSE;
	m_mainbuff = NULL;
	m_backbuff = NULL;
	m_cachebuff =NULL;
	m_use_cache = FALSE;
	m_cursor_shape_cleared = FALSE;
	m_backbuffsize = 0;
	m_desktop=NULL;

	// Modif sf@2002 - Scaling
	m_ScaledBuff = NULL;
	m_nScale = 1;
	m_ScaledSize = 0;

	m_nAccuracyDiv = 4;

	nRowIndex = 0;
	m_cursorpending = false;
	m_display_prim=1;
	m_display_sec=1;

	// sf@2005 - Grey Palette
	m_fGreyPalette = false;
}

vncBuffer::~vncBuffer()
{
	if (m_freemainbuff) {
		// We need to free the slow-blit buffer
		// Modif rdv@2002 - v1.1.x - Videodriver
		if (m_mainbuff != NULL)
		{
			delete [] m_mainbuff;
			m_mainbuff = NULL;
		}
	}
	if (m_backbuff != NULL)
	{
		delete [] m_backbuff;
		m_backbuff = NULL;
	}

	if (m_cachebuff != NULL)
	{
		delete [] m_cachebuff;
		m_cachebuff = NULL;
	}

	// Modif sf@2002 - Scaling
	if (m_ScaledBuff != NULL)
	{
		delete [] m_ScaledBuff;
		m_ScaledBuff = NULL;
	}
	m_ScaledSize = 0;


	m_backbuffsize = 0;
}

void
vncBuffer::SetDesktop(vncDesktop *desktop)
{
	// Called from vncdesktop startup
	// only possible on startup or reinitialization
	// access is block by m_desktop->m_update_lock
	m_desktop=desktop;
	CheckBuffer();
}

rfb::Rect
vncBuffer::GetSize()
{

	try
	{
		return m_desktop->GetSize();
	}
	catch (...)
	{	
		//return rfb::Rect(0, 0, m_scrinfo.framebufferWidth, m_scrinfo.framebufferHeight);
		return rfb::Rect(0, 0, 0, 0);
	}


}

// Modif sf@2002 - Scaling
UINT vncBuffer::GetScale()
{
	return m_nScale;
}


BOOL vncBuffer::SetScale(int nScale)
{
	//called by
	//vncClientThread::run(void *arg) Lock Added
	// case rfbSetScale:  Lock Added OK

	m_nScale = nScale;
	if (m_nScale == 1)
	{
		//if (m_mainbuff)memcpy(m_ScaledBuff, m_mainbuff, m_desktop->ScreenBuffSize());
		//else ZeroMemory(m_ScaledBuff, m_desktop->ScreenBuffSize());
		CheckBuffer(); // added to remove scaled buffer
		if (m_mainbuff)memcpy(m_backbuff, m_mainbuff, m_desktop->ScreenBuffSize());
		else ZeroMemory(m_ScaledBuff, m_desktop->ScreenBuffSize());
	}
	else
	{
		// sf@2002 - Idealy, we must do a ScaleRect of the whole screen here.
		// ScaleRect(rfb::Rect(0, 0, m_scrinfo.framebufferWidth / m_nScale, m_scrinfo.framebufferHeight / m_nScale));
		CheckBuffer();//added to create scaled buffer
		ZeroMemory(m_ScaledBuff, m_desktop->ScreenBuffSize());
		ZeroMemory(m_backbuff, m_desktop->ScreenBuffSize());
	}
	
	return TRUE;
}


rfb::Rect vncBuffer::GetViewerSize()
{
	rfb::Rect rect;
	rect=m_desktop->GetSize();
	return rfb::Rect(rect.tl.x,rect.tl.y, rect.br.x / m_nScale, rect.br.y / m_nScale);
}


rfbPixelFormat
vncBuffer::GetLocalFormat()
{
	return m_scrinfo.format;
}

BOOL
vncBuffer::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]"), m_desktop->ScreenBuffSize());
		if (m_freemainbuff) {
			// Slow blits were enabled - free the slow blit buffer
			// Modif rdv@2002 - v1.1.x - Videodriver
			if (m_mainbuff != NULL)
			{
				delete [] m_mainbuff;
				m_mainbuff = NULL;
			}
		}

		if (m_backbuff != NULL)
		{
			delete [] m_backbuff;
			m_backbuff = NULL;
		}

		if (m_cachebuff != NULL)
		{
			delete [] m_cachebuff;
			m_cachebuff = NULL;
		}

		// Modif sf@2002 - Scaling
		if (m_ScaledBuff != NULL)
		{
			delete [] m_ScaledBuff;
			m_ScaledBuff = NULL;
		}
		m_ScaledSize = 0;
		//

		m_backbuffsize = 0;

		// Check whether or not the vncDesktop is using fast blits
		// Modif rdv@2002 - v1.1.x - Videodriver
		
			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"));
			} 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]"), 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]"), m_desktop->ScreenBuffSize());
			return FALSE;
		}

		if (m_use_cache)
		{
			if ((m_cachebuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)
			{
				vnclog.Print(LL_INTERR, VNCLOG("unable to allocate cache buffer[%d]"), m_desktop->ScreenBuffSize());
				return FALSE;
			}
			ClearCache();
		}

		memset(m_backbuff, 0, m_desktop->ScreenBuffSize());
		m_backbuffsize = m_desktop->ScreenBuffSize();

		/// If scale==1 we don't need to allocate the memory
		if (m_nScale > 1) 
		{
			// Modif sf@2002 - Scaling
			if ((m_ScaledBuff = new BYTE [m_desktop->ScreenBuffSize()]) == NULL)
			{
				vnclog.Print(LL_INTERR, VNCLOG("unable to allocate scaled buffer[%d]"), m_desktop->ScreenBuffSize());
				return FALSE;
			}
			m_ScaledSize = m_desktop->ScreenBuffSize();
			memcpy(m_ScaledBuff, m_mainbuff, m_desktop->ScreenBuffSize());
		}
		else
		{
			delete [] m_ScaledBuff;
			m_ScaledBuff = NULL;
		}
	}

	vnclog.Print(LL_INTINFO, VNCLOG("local buffer=%d"), m_backbuffsize);

	return TRUE;
}


// Modif sf@2002 - v1.1.0
//
// Set the accuracy divider factor 
// that is utilized in the GetChangedRegion function
// for changes detection in Rectangles.
// The higher the value the less accuracy.
// WARNING :this value must be a 32 divider.
//
BOOL vncBuffer::SetAccuracy(int nAccuracy)
{
	m_nAccuracyDiv = nAccuracy;
	nRowIndex = 0;

	return TRUE;
}



// Check a specified rectangle for changes and fill the region with
// the changed subrects
//#pragma function(memcpy,Save_memcmp)

const int BLOCK_SIZE = 32;
void vncBuffer::CheckRect(rfb::Region2D &dest, rfb::Region2D &cacheRgn, const rfb::Rect &srcrect)
{
	//only called from desktopthread
	if (!FastCheckMainbuffer())
		return;

	const UINT bytesPerPixel = m_scrinfo.format.bitsPerPixel / 8;

	rfb::Rect new_rect;
	rfb::Rect srect = srcrect;

	// Modif sf@2002 - Scaling
	rfb::Rect ScaledRect;
	ScaledRect.tl.y = srect.tl.y / m_nScale;
	ScaledRect.br.y = srect.br.y / m_nScale;
	ScaledRect.tl.x = srect.tl.x / m_nScale;
	ScaledRect.br.x = srect.br.x / m_nScale;

	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
			ScaledRect.tl.x -= (ScaledRect.tl.x & 3);	// round down to nearest multiple of 4
		else								// 2 bytes per pixel
			ScaledRect.tl.x -= (ScaledRect.tl.x & 1);	// round down to nearest multiple of 2
	}

	// Modif sf@2002 - Scaling
	unsigned char *TheBuffer;
	if (m_nScale == 1)
		TheBuffer = m_mainbuff;
	else
		TheBuffer = m_ScaledBuff;

	// sf@2004 - Optimization (attempt...)
	int nOptimizedBlockSize; 
	bool fSmallRect = false;
	if (ScaledRect.br.x - ScaledRect.tl.x < 16)
	{
		nOptimizedBlockSize = BLOCK_SIZE / 4;
		fSmallRect = true;
	}
	else if (ScaledRect.br.x - ScaledRect.tl.x < 32)
		nOptimizedBlockSize = BLOCK_SIZE / 2;
	else
		nOptimizedBlockSize = BLOCK_SIZE * 2;

	if (m_use_cache && !m_desktop->m_UltraEncoder_used && m_cachebuff)
	{
	// Scan down the rectangle
	unsigned char *o_topleft_ptr = m_backbuff  + (ScaledRect.tl.y * m_bytesPerRow) + (ScaledRect.tl.x * bytesPerPixel);
	unsigned char *c_topleft_ptr = m_cachebuff + (ScaledRect.tl.y * m_bytesPerRow) + (ScaledRect.tl.x * bytesPerPixel);
	unsigned char *n_topleft_ptr = TheBuffer   + (ScaledRect.tl.y * m_bytesPerRow) + (ScaledRect.tl.x * bytesPerPixel);

	for (y = ScaledRect.tl.y; y < ScaledRect.br.y; y += nOptimizedBlockSize)
	{
		// Work out way down the bitmap
		unsigned char * o_row_ptr = o_topleft_ptr;
		unsigned char * n_row_ptr = n_topleft_ptr;
		unsigned char * c_row_ptr = c_topleft_ptr;

		const UINT blockbottom = min(y + nOptimizedBlockSize, ScaledRect.br.y);
		for (x = ScaledRect.tl.x; x < ScaledRect.br.x; x += nOptimizedBlockSize)
		{
			// Work our way across the row
			unsigned char *n_block_ptr = n_row_ptr;
			unsigned char *o_block_ptr = o_row_ptr;

⌨️ 快捷键说明

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