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

231 lines
9.4 KiB
C

/****************************************************************************/
// oe2.h
//
// Header for RDP field compression.
//
// Copyright (C) 1997-2000 Microsoft Corporation
/****************************************************************************/
#ifndef __OE2_H
#define __OE2_H
/****************************************************************************/
// Field compression (OE2) overview
//
// OE2 compression maintains a copy of each field value of the last order
// sent, plus other state information like the last bounding rectangle used
// and the last order type. OE2 encoding involves comparing a new display
// order to the last copy, and sending only the fields which have changed.
// Other specialized encoding occurs for certain fields declared to be of
// "coord" type, meaning that a one-byte delta can be sent instead of a
// 2-byte value, if the delta will fit into 8 bits.
//
// The wire format for OE2 encoded orders consists of the following fields:
//
// +------------+------+-------------+--------+----------------+
// | Ctrl flags | Type | Field flags | Bounds | Encoded Fields |
// +------------+------+-------------+--------+----------------+
//
// Control flags: Required byte, corresponding to a TS_ORDER_HEADER and
// available flags. Always contains at least TS_STANDARD flag. These
// flags describe the following encoding; flag meanings are discussed
// below.
//
// Type: If TS_TYPE_CHANGE is present in the control flags, this is a one-
// byte order type value. The initial value agreed-on by both server
// and client is TS_ENC_PATBLT_ORDER.
//
// Field flags: One or more bytes, where the number of bytes is ceil(((number
// of order fields) + 1) / 8). The "+ 1" in that equation is historical
// and means that the first byte of field flags can only encompass 7
// flag bits. The presence of these flags is also governed by the control
// flags TS_ZERO_FIELD_BYTE_BIT0 and TS_ZERO_FIELD_BYTE_BIT1
// (see at128.h description). The ordering of the bytes is as a DWORD
// -- the low order byte is first. The field flags indicate the presence
// of an order field in the encoded fields portion of the packet.
// The ordering of the flags proceeds from 0x01 corresponding to the
// first order field, 0x02 the second, 0x04 the third, etc.
//
// Bounds: The presence of this field is governed by the TS_BOUNDS control
// flag, which indicates the order must have a bounding region applied.
// If control flag TS_ZERO_BOUNDS_DELTAS is set, the bound rect to be
// used is the same as the last bound rect used. Otherwise, the
// bounds are encoded as an encoding description byte followed by one
// or more encoded bounds. The description byte contains two flags
// for each of the left, top, right, and bottom rect components.
// One flag (TS_BOUND_XXX) indicates that the component is present
// and encoded as a 2-byte Intel-ordering value. The other flag
// (TS_BOUND_DELTA_XXX) indicates the component is present and encoded
// as a one-byte value used as an offset (-128 to 127) from the previous
// value of the component. If neither flag is present the component
// value is the same as used last. The initial value for the bounds
// agreed-on by both server and client is the zero rect (0, 0, 0, 0).
//
// Encoded fields: These are the encoded order field values whose presence
// is governed by the field flags. The fields are encoded in order if
// present. The control flag TS_DELTA_COORDINATES is set if all COORD
// type fields in the order can be specified as a one-byte delta from
// their last values. If a field is not present its value is the same
// as the last value sent. The initial values the client and server
// use for all fields is zero. See the order field description tables in
// noe2disp.c for specific order information.
/****************************************************************************/
/****************************************************************************/
// Defines
/****************************************************************************/
#define MAX_BOUNDS_ENCODE_SIZE 9
#define MAX_REPLAY_CLIPPED_ORDER_SIZE (1 + MAX_BOUNDS_ENCODE_SIZE)
#define OE2_CONTROL_FLAGS_FIELD_SIZE 1
#define OE2_TYPE_FIELD_SIZE 1
#define OE2_MAX_FIELD_FLAG_BYTES 3
#define MAX_ENCODED_ORDER_PREFIX_BYTES (OE2_CONTROL_FLAGS_FIELD_SIZE + \
OE2_TYPE_FIELD_SIZE + OE2_MAX_FIELD_FLAG_BYTES + \
MAX_BOUNDS_ENCODE_SIZE)
// Max size: 1 control flag + 1 type change byte + num field flag bytes +
// 9 bounds bytes + fields.
#define MAX_ORDER_SIZE(_NumRects, _NumFieldFlagBytes, _MaxFieldSize) \
(2 + (_NumFieldFlagBytes) + ((_NumRects == 0) ? 0 : 9) + \
(_MaxFieldSize))
/****************************************************************************/
// Types
/****************************************************************************/
// INT_FMT_FIELD: Const data definitions for table-based OE2 order translation.
// Describes the source intermediate and destination wire data formats.
//
// FieldPos: Byte offset into the source intermediate format for the field.
// FieldUnencodedLen: Length of the source field.
// FieldEncodedLen: Length of the destination field (wore format).
// FieldSigned: Flag for signed field value.
// FieldType: Descriptor that specifies how to translate the field.
typedef struct
{
unsigned FieldPos;
unsigned FieldUnencodedLen;
unsigned FieldEncodedLen;
BOOL FieldSigned;
unsigned FieldType;
} INT_FMT_FIELD;
typedef INT_FMT_FIELD const *PINT_FMT_FIELD;
/****************************************************************************/
// Prototypes and inlines
/****************************************************************************/
void OE2_Reset(void);
void OE2_EncodeBounds(BYTE *, BYTE **, RECTL *);
unsigned OE2_CheckZeroFlagBytes(BYTE *, BYTE *, unsigned, unsigned);
void OE2_TableEncodeOrderFields(BYTE *, PUINT32_UA, BYTE **, PINT_FMT_FIELD,
unsigned, BYTE *, BYTE *);
unsigned OE2_EncodeOrder(BYTE *, unsigned, unsigned, BYTE *, BYTE *,
PINT_FMT_FIELD, RECTL *);
/****************************************************************************/
// OE2_EncodeOrderType
//
// Used by order encoding paths to encode the order type byte if different
// from the last order.
//
// void OE2_EncodeOrderType(
// BYTE *pControlFlags,
// BYTE **ppBuffer,
// unsigned OrderType);
/****************************************************************************/
#define OE2_EncodeOrderType(_pControlFlags, _ppBuffer, _OrderType) \
{ \
if (oe2LastOrderType != (_OrderType)) { \
*(_pControlFlags) |= TS_TYPE_CHANGE; \
**(_ppBuffer) = (BYTE)(_OrderType); \
(*(_ppBuffer))++; \
oe2LastOrderType = (_OrderType); \
} \
}
/****************************************************************************/
// OE2_CheckOneZeroFlagByte
//
// 1-field-flag-byte version of OE2_CheckZeroFlagBytes(), optimizes out the
// generalized loop.
/****************************************************************************/
__inline unsigned OE2_CheckOneZeroFlagByte(
BYTE *pControlFlags,
BYTE *pFieldFlag,
unsigned PostFlagsDataLength)
{
if (*pFieldFlag != 0) {
return 0;
}
else {
*pControlFlags |= (1 << TS_ZERO_FIELD_COUNT_SHIFT);
memmove(pFieldFlag, pFieldFlag + 1, PostFlagsDataLength);
return 1;
}
}
/****************************************************************************/
// OE2_CheckTwoZeroFlagBytes
//
// 2-field-flag-byte version of OE2_CheckZeroFlagBytes(), optimizes out the
// generalized loop.
/****************************************************************************/
__inline unsigned OE2_CheckTwoZeroFlagBytes(
BYTE *pControlFlags,
BYTE *pFieldFlags,
unsigned PostFlagsDataLength)
{
if (pFieldFlags[1] != 0) {
return 0;
}
else if (pFieldFlags[0] != 0) {
*pControlFlags |= (1 << TS_ZERO_FIELD_COUNT_SHIFT);
memmove(pFieldFlags + 1, pFieldFlags + 2, PostFlagsDataLength);
return 1;
}
else {
*pControlFlags |= (2 << TS_ZERO_FIELD_COUNT_SHIFT);
memmove(pFieldFlags, pFieldFlags + 2, PostFlagsDataLength);
return 2;
}
}
/****************************************************************************/
// OE2_EmitClippedReplayOrder
//
// Creates a "play-it-again" order -- same order type and all fields
// the same as previous, except with a different bound rect.
//
// void OE2_EmitClippedReplayOrder(
// BYTE **ppBuffer,
// unsigned NumFieldFlagBytes,
// RECTL *pClipRect)
/****************************************************************************/
#define OE2_EmitClippedReplayOrder(_ppBuffer, _NumFieldFlagBytes, _pClipRect) \
{ \
BYTE *pBuffer = *(_ppBuffer); \
\
/* Control flags are primary order plus all field flags bytes zero. */ \
*pBuffer++ = TS_STANDARD | TS_BOUNDS | \
((_NumFieldFlagBytes) << TS_ZERO_FIELD_COUNT_SHIFT); \
\
/* Construct the new bounds rect just after this. */ \
OE2_EncodeBounds(pBuffer - 1, &pBuffer, (_pClipRect)); \
\
*(_ppBuffer) = pBuffer; \
}
#endif // __OE2_H