📄 vncbuffer.cpp
字号:
// 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 + -