Windows2003-3790/termsrv/drivers/rdp/inc/nsbcinl.h
2020-09-30 16:53:55 +02:00

257 lines
11 KiB
C

/****************************************************************************/
// nsbcinl.h
//
// SBC inline functions
//
// Copyright(C) Microsoft Corporation 1997-1999
/****************************************************************************/
#ifndef _H_NSBCINL
#define _H_NSBCINL
#include <nsbcdisp.h>
#define DC_INCLUDE_DATA
#include <nsbcddat.c>
#undef DC_INCLUDE_DATA
/****************************************************************************/
/* Name: SBC_PaletteChanged */
/* */
/* Purpose: Called when the palette changes. */
/****************************************************************************/
__inline void RDPCALL SBC_PaletteChanged(void)
{
sbcPaletteChanged = TRUE;
}
/****************************************************************************/
// SBC_DDIsMemScreenBltCachable
//
// Checks the bitmap format for characteristics that make it uncachable.
// At this point no bitmaps are uncachable since we handle both RLE-encoded
// and regular bitmaps. For RLE bitmaps containing relative-motion deltas
// we have to set up a special flag which is used at the tile level to cause
// us to grab the background screen bits before blt-ing the RLE bitmap over
// them. We also prescan for non-delta RLEs which can be cached normally.
// See MSDN query on "Bitmap Compression" for details on RLE encoding, and
// see comments below.
/****************************************************************************/
__inline BOOLEAN RDPCALL SBC_DDIsMemScreenBltCachable(
PMEMBLT_ORDER_EXTRA_INFO pMemBltInfo)
{
BOOLEAN rc = TRUE;
SURFOBJ *pSourceSurf;
DC_BEGIN_FN("SBC_DDIsMemScreenBltCachable");
if (sbcEnabled & SBC_BITMAP_CACHE_ENABLED) {
pSourceSurf = pMemBltInfo->pSource;
// Tune for the normal case.
if (pSourceSurf->iBitmapFormat != BMF_4RLE &&
pSourceSurf->iBitmapFormat != BMF_8RLE) {
// Reset the RLE flag.
pMemBltInfo->bDeltaRLE = FALSE;
}
else {
BYTE *pBits = (BYTE *)pSourceSurf->pvBits;
BYTE *pEnd = (BYTE *)pSourceSurf->pvBits + pSourceSurf->cjBits - 1;
BYTE RLEDivisor, RLECeilAdjustment;
int PixelsInLine, LinesInBitmap;
TRC_ASSERT((((UINT_PTR)pBits & 1) == 0),
(TB,"Bitmap source address not word aligned!"));
TRC_NRM((TB,"RLE%c, sizl=(%u, %u)", (pSourceSurf->iBitmapFormat ==
BMF_4RLE ? '4' : '8'), pSourceSurf->sizlBitmap.cx,
pSourceSurf->sizlBitmap.cy));
if (pSourceSurf->iBitmapFormat == BMF_8RLE) {
RLEDivisor = 1;
RLECeilAdjustment = 0;
}
else {
RLEDivisor = 2;
RLECeilAdjustment = 1;
}
// Detect offset drawing in bitmap. If offsets are used the bitmap
// cannot be encoded as a regular bitmap since the offsets require
// knowing the screen bits behind the bitmap.
// Note this search is expensive, but since RLE bitmaps are rare
// this is an unusual case. Also note that pEnd is at one less
// than the last byte of the bitmap since all RLE codes are in 2
// byte increments and we scan ahead one byte during loop.
pMemBltInfo->bDeltaRLE = FALSE;
PixelsInLine = 0;
LinesInBitmap = 1;
while (pBits < pEnd) {
if (*pBits == 0x00) {
// 0x00 is an escape. Check the next byte for the action:
// 0x00 means end-of-line
// 0x01 means end-of-bitmap
// 0x02 means delta movement to draw next bits.
// x,y offsets are in 2 bytes after 0x02 code.
// This is the type of encoding we cannot handle.
// 0x03..0xFF means there are this many raw indices
// following. For 4BPP there are 2 indices per
// byte. In both RLE types the run must be padded
// to word alignment relative to the start of the
// bitmap bits.
if (*(pBits + 1) == 0x00) {
// Check that the entire line was drawn in the bitmap.
// Skipping any part of a line means we need to grab
// screen data as a backdrop.
if (PixelsInLine < pSourceSurf->sizlBitmap.cx) {
pMemBltInfo->bDeltaRLE = TRUE;
TRC_NRM((TB,"EOL too soon at %p", pBits));
break;
}
PixelsInLine = 0;
pBits += 2;
LinesInBitmap++;
}
if (*(pBits + 1) == 0x01) {
// Check that the last line was covered (see EOL
// above).
if (PixelsInLine < pSourceSurf->sizlBitmap.cx) {
pMemBltInfo->bDeltaRLE = TRUE;
TRC_NRM((TB,"EOL too soon (EOBitmap) at %p",
pBits));
}
// Check that all lines were covered.
if (LinesInBitmap < pSourceSurf->sizlBitmap.cy) {
pMemBltInfo->bDeltaRLE = TRUE;
TRC_NRM((TB,"EOBitmap too soon not all lines "
"covered at %p", pBits));
}
break;
}
if (*(pBits + 1) == 0x02) {
TRC_NRM((TB,"Delta at %p\n", pBits));
pMemBltInfo->bDeltaRLE = TRUE;
break;
}
else {
PixelsInLine += *(pBits + 1);
if (PixelsInLine > pSourceSurf->sizlBitmap.cx) {
// Implicit wraparound.
TRC_NRM((TB,"Implicit wraparound at %p", pBits));
LinesInBitmap += PixelsInLine / pSourceSurf->
sizlBitmap.cx;
PixelsInLine %= pSourceSurf->sizlBitmap.cx;
}
// Skip the 2 bytes for 0x00 and the number of entries,
// plus #entries bytes for RLE8 (RLEDivisor == 1) or
// ceil(#entries / 2) for RLE4 (RLEDivisor == 2).
pBits += 2 + (*(pBits + 1) + RLECeilAdjustment) /
RLEDivisor;
// Adjust the new pBits for word alignment relative to
// the start of the bitmap. We assume that the
// start addr of the bitmap is word-aligned in memory.
pBits += ((UINT_PTR)pBits & 1);
}
}
else {
// Non-escape count byte, skip it and the next byte
// containing palette indices.
PixelsInLine += *pBits;
if (PixelsInLine > pSourceSurf->sizlBitmap.cx) {
// Implicit wraparound.
TRC_NRM((TB,"Implicit wraparound at %p", pBits));
LinesInBitmap += PixelsInLine / pSourceSurf->
sizlBitmap.cx;
PixelsInLine %= pSourceSurf->sizlBitmap.cx;
}
pBits += 2;
}
}
}
}
else {
rc = FALSE;
TRC_DBG((TB, "Caching not enabled"));
}
DC_END_FN();
return rc;
}
/****************************************************************************/
// SBC_DDQueryBitmapTileSize
//
// Returns the tile size to use for a given bitblt on a given bitmap.
/****************************************************************************/
__inline unsigned SBC_DDQueryBitmapTileSize(
unsigned bmpWidth,
unsigned bmpHeight,
PPOINTL pptlSrc,
unsigned width,
unsigned height)
{
unsigned i;
unsigned TileSize;
DC_BEGIN_FN("SBC_DDQueryBitmapTileSize");
// We should have at least one functional cache or this will go badly.
TRC_ASSERT((pddShm->sbc.NumBitmapCaches > 0),(TB,"No bitmap caches"));
// Loop through all sizes seeing if the src rect start is a multiple of the
// tile dimension, the blt size is not bigger than the tile size, and
// there are an integral number of tiles in the blt. If this matches
// anywhere we have our tile size. Don't check the last tile size since
// that's a default anyway.
for (i = 0; i < pddShm->sbc.NumBitmapCaches; i++) {
TileSize = SBC_CACHE_0_DIMENSION << i;
if ((((pptlSrc->x & (TileSize - 1)) == 0) &&
((pptlSrc->y & (TileSize - 1)) == 0) &&
(width <= TileSize) &&
(height <= TileSize)) ||
((((unsigned)pptlSrc->x >> (SBC_CACHE_0_DIMENSION_SHIFT + i)) ==
(((unsigned)pptlSrc->x + width - 1) >>
(SBC_CACHE_0_DIMENSION_SHIFT + i))) &&
(((unsigned)pptlSrc->y >> (SBC_CACHE_0_DIMENSION_SHIFT + i)) ==
(((unsigned)pptlSrc->y + height - 1) >>
(SBC_CACHE_0_DIMENSION_SHIFT + i))))) {
goto EndFunc;
}
}
// Cycle through the caches, checking for if the bitmap will fit
// into a tile size in one of its dimensions. Don't check the
// last size since that's the default if no others work.
for (i = 0; i < (pddShm->sbc.NumBitmapCaches - 1); i++) {
//TODO: What about using 'or' here -- uses more of smaller tiles when
// one dimension is bad. But could send more data.
if (bmpWidth <= (unsigned)(SBC_CACHE_0_DIMENSION << i) &&
bmpHeight <= (unsigned)(SBC_CACHE_0_DIMENSION << i))
break;
}
EndFunc:
TRC_NRM((TB, "Tile(%u x %u, TileID %d) bmpWidth(%u) bmpHeight(%u)"
"srcLeft(%d) srcTop(%d) width(%d) height(%d)",
(SBC_CACHE_0_DIMENSION << i), (SBC_CACHE_0_DIMENSION << i),
i, bmpWidth, bmpHeight, pptlSrc->x, pptlSrc->y, width,
height));
DC_END_FN();
return i;
}
#endif /* _H_NSBCINL */