📄 vncbuffer.cpp
字号:
unsigned char *c_block_ptr = c_row_ptr;
const UINT blockright = min(x + nOptimizedBlockSize, ScaledRect.br.x);
const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;
BOOL fCache = TRUE; // RDV@2002
// Modif sf@2002 - v1.1.0
// int nRowIndex = 0; // We don't reinit nRowIndex for each rect -> we don't always miss the same changed pixels
int nOffset = (int)(bytesPerBlockRow / m_nAccuracyDiv);
unsigned char *y_o_ptr = o_block_ptr;
unsigned char *y_n_ptr = n_block_ptr;
unsigned char *y_c_ptr = c_block_ptr;
// Scan this block
for (ay = y; ay < blockbottom; ay++)
{
if (
memcmp( n_block_ptr + (nRowIndex * nOffset),
o_block_ptr + (nRowIndex * nOffset),
nOffset
) != 0
)
{
// A pixel has changed, so this block needs updating
if (fSmallRect) // Ignore unchanged first rows (samll rect : less chance to miss changes when using nAccuracy div)
{
new_rect.tl.y = ay * m_nScale;
y_n_ptr += ((ay-y) * m_bytesPerRow);
y_o_ptr += ((ay-y) * m_bytesPerRow);
}
else
{
new_rect.tl.y = y * m_nScale;
}
new_rect.tl.x = x * m_nScale;
new_rect.br.x = blockright * m_nScale;
new_rect.br.y = blockbottom * m_nScale;
for (by = ((fSmallRect) ? ay : y); by < blockbottom; by++)
{
// Until then, new rect and cached rect are equal.
// So test the next row
// TODO: send the common part as cached rect and the rest as changed rect
if (fCache)
if (memcmp(y_n_ptr, y_c_ptr, bytesPerBlockRow) != 0)
{
fCache = FALSE; // New rect and cached rect differ
}
memcpy(y_c_ptr, y_o_ptr, bytesPerBlockRow); // Save back buffer rect in cache
memcpy(y_o_ptr, y_n_ptr, bytesPerBlockRow); // Save new rect in back buffer
y_n_ptr += m_bytesPerRow;
y_o_ptr += m_bytesPerRow;
y_c_ptr += m_bytesPerRow;
}
if (fCache) // The Rect was in the cache
{
cacheRgn = cacheRgn.union_(rfb::Region2D(new_rect));
}
else // The Rect wasn't in the cache
{
dest = dest.union_ (new_rect);
}
break;
}
n_block_ptr += m_bytesPerRow;
o_block_ptr += m_bytesPerRow;
c_block_ptr += m_bytesPerRow;
nRowIndex = (nRowIndex + 1) % m_nAccuracyDiv; // sf@2002 - v1.1.0
}
o_row_ptr += bytesPerBlockRow;
n_row_ptr += bytesPerBlockRow;
c_row_ptr += bytesPerBlockRow;
}
o_topleft_ptr += m_bytesPerRow * nOptimizedBlockSize;
n_topleft_ptr += m_bytesPerRow * nOptimizedBlockSize;
c_topleft_ptr += m_bytesPerRow * nOptimizedBlockSize;
}
}
else
{
// Scan down the rectangle
unsigned char *o_topleft_ptr = m_backbuff + (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;
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;
const UINT blockright = min(x+nOptimizedBlockSize, ScaledRect.br.x);
const UINT bytesPerBlockRow = (blockright-x) * bytesPerPixel;
// Modif sf@2002
unsigned char *y_o_ptr = o_block_ptr;
unsigned char *y_n_ptr = n_block_ptr;
// int nRowIndex = 0;
int nOffset = (int)(bytesPerBlockRow / m_nAccuracyDiv);
// Scan this block
for (ay = y; ay < blockbottom; ay++)
{
if (memcmp( n_block_ptr + (nRowIndex * nOffset),
o_block_ptr + (nRowIndex * nOffset),
nOffset
) != 0
)
{
// A pixel has changed, so this block needs updating
if (fSmallRect) // Ignore unchanged first rows (samll rect : less chance to miss changes when using nAccuracy div)
{
new_rect.tl.y = ay * m_nScale;
y_n_ptr += ((ay-y) * m_bytesPerRow);
y_o_ptr += ((ay-y) * m_bytesPerRow);
}
else
{
new_rect.tl.y = y * m_nScale;
}
new_rect.tl.x = x * m_nScale;
new_rect.br.x = (blockright * m_nScale);
new_rect.br.y = (blockbottom * m_nScale);
dest = dest.union_(new_rect);
// Copy the changes to the back buffer
for (by = ((fSmallRect) ? ay : y); by < blockbottom; by++)
{
memcpy(y_o_ptr, y_n_ptr, bytesPerBlockRow);
y_n_ptr += m_bytesPerRow;
y_o_ptr += m_bytesPerRow;
}
break;
}
// Last Run Ptr gets over de bounding
// Boundcheker keeps complaining
if (ay!=blockbottom-1)
{
n_block_ptr += m_bytesPerRow;
o_block_ptr += m_bytesPerRow;
nRowIndex = (nRowIndex + 1) % m_nAccuracyDiv;
}
}
if (x != ScaledRect.br.x-1)
{
o_row_ptr += bytesPerBlockRow;
n_row_ptr += bytesPerBlockRow;
}
}
if (y != ScaledRect.br.y-1)
{
o_topleft_ptr += m_bytesPerRow * nOptimizedBlockSize;
n_topleft_ptr += m_bytesPerRow * nOptimizedBlockSize;
}
}
}
}
//rdv modif scaled and videodriver
void
vncBuffer::GrabRegion(rfb::Region2D &src,BOOL driver)
{
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
//
//
//************ Added extra cliprect check
int x,y,w,h;
for (i = rects.begin(); i != rects.end(); i++)
{
rfb::Rect rect = *i;
x=rect.tl.x;
y=rect.tl.y;
w=rect.br.x-rect.tl.x;
h=rect.br.y-rect.tl.y;
src.subtract(rect);
if (ClipRect(&x, &y, &w, &h, m_desktop->m_Cliprect.tl.x, m_desktop->m_Cliprect.tl.y,
m_desktop->m_Cliprect.br.x-m_desktop->m_Cliprect.tl.x, m_desktop->m_Cliprect.br.y-m_desktop->m_Cliprect.tl.y))
{
rect.tl.x=x;
rect.tl.y=y;
rect.br.x=x+w;
rect.br.y=y+h;
src.union_(rect);
}
}
src.get_rects(rects, 1, 1);
if (rects.empty())
{
return;
}
// 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,driver);
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,driver);
}
void
vncBuffer::CheckRegion(rfb::Region2D &dest,rfb::Region2D &cacheRgn ,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
//
// Block desactivation mainbuff while running
// No Lock Needed, only called from vncdesktopthread
for (i = rects.begin(); i != rects.end(); i++)
{
CheckRect(dest,cacheRgn, *i);
}
}
// Reduce possible colors to 8 shades of gray
int To8GreyColors(int r, int g, int b)
{
int Value;
Value = (r*11 + g*16 +b*5 ) / 32;
if (Value <= 0x20)
return 0x101010;
else if (Value <= 0x40)
return 0x303030;
else if (Value <= 0x60)
return 0x505050;
else if (Value <= 0x80)
return 0x707070;
else if (Value <= 0xa0)
return 0x909090;
else if (Value <= 0xc0)
return 0xb0b0b0;
else if (Value <= 0xe0)
return 0xd0d0d0;
else
return 0xf0f0f0;
}
// Modif sf@2002 - Scaling
void vncBuffer::ScaleRect(rfb::Rect &rect)
{
bool fCanReduceColors = true;
//JK 26th Jan, 2005: Color conversion to 8 shades of gray added,
//at the moment only works if server has 24/32-bit color
if ((m_scrinfo.format.redMax == 255)
&&
(m_scrinfo.format.blueMax == 255)
&&
(m_scrinfo.format.greenMax == 255)
&&
m_fGreyPalette
)
fCanReduceColors = true;
else
fCanReduceColors = false;
//End JK
// called from grabrect and grabmouse
// grabmouse is only called from desktopthread, no lock needed
// grebrect called from grabregion called from desktopthread, no lock needed
// no lock needed
if (!FastCheckMainbuffer())
return;
///////////
rect.tl.y = (rect.tl.y - (rect.tl.y % m_nScale));
rect.br.y = (rect.br.y - (rect.br.y % m_nScale)) + m_nScale - 1;
rect.tl.x = (rect.tl.x - (rect.tl.x % m_nScale));
rect.br.x = (rect.br.x - (rect.br.x % m_nScale)) + m_nScale - 1;
rfb::Rect ScaledRect;
ScaledRect.tl.y = rect.tl.y / m_nScale;
ScaledRect.br.y = rect.br.y / m_nScale;
ScaledRect.tl.x = rect.tl.x / m_nScale;
ScaledRect.br.x = rect.br.x / m_nScale;
// Copy and scale data from screen Main buffer to Scaled buffer
BYTE *pMain = m_mainbuff + (rect.tl.y * m_bytesPerRow) +
(rect.tl.x * m_scrinfo.format.bitsPerPixel / 8);
BYTE *pScaled = m_ScaledBuff + (ScaledRect.tl.y * m_bytesPerRow) +
(ScaledRect.tl.x * m_scrinfo.format.bitsPerPixel / 8);
// We keep one pixel for m_Scale*m_nScale pixels in the Main buffer
// and copy it in the Scaled Buffer
// TrueColor Case.
// Pixels Blending (takes the "medium" pixel of each m_Scale*m_nScale square)
// This TrueColor Pixel blending routine comes from the Harakan's WinVNC with Server Side Scaling
// Extension. It replaces my own buggy Blending function that given *ugly* results.
if (m_scrinfo.format.trueColour)
{
unsigned long lRed;
unsigned long lGreen;
unsigned long lBlue;
unsigned long lScaledPixel;
UINT nBytesPerPixel = (m_scrinfo.format.bitsPerPixel / 8);
// For each line of the Destination ScaledRect
for (int y = ScaledRect.tl.y; y < ScaledRect.br.y; y++)
{
// For each Pixel of the line
for (int x = 0; x < (ScaledRect.br.x - ScaledRect.tl.x); x++)
{
lRed = 0;
lGreen = 0;
lBlue = 0;
// Take a m_Scale*m_nScale square of pixels in the Main Buffer
// and get the global Red, Green, Blue values for this square
for (int r = 0; r < m_nScale; r++)
{
for (int c = 0; c < m_nScale; c++)
{
lScaledPixel = 0;
for (int b = 0; b < nBytesPerPixel; b++)
{
lScaledPixel += (pMain[(((x * m_nScale) + c) * nBytesPerPixel) + (r * m_bytesPerRow) + b]) << (8 * b);
}
lRed += (lScaledPixel >> m_scrinfo.format.redShift) & m_scrinfo.format.redMax;
lGreen += (lScaledPixel >> m_scrinfo.format.greenShift) & m_scrinfo.format.greenMax;
lBlue += (lScaledPixel >> m_scrinfo.format.blueShift) & m_scrinfo.format.blueMax;
}
}
// Get the medium R,G,B values for the sqare
lRed /= m_nScale * m_nScale;
lGreen /= m_nScale * m_nScale;
lBlue /= m_nScale * m_nScale;
// Calculate the resulting "medium" pixel
// lScaledPixel = (lRed << m_scrinfo.format.redShift) + (lGreen << m_scrinfo.format.greenShift) + (lBlue << m_scrinfo.format.blueShift);
// JK 26th Jan, 2005: Reduce possible colors to 8 shades of gray
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -