mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3245 lines
91 KiB
3245 lines
91 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: hook.c
|
|
*
|
|
* This module contains the hooked functions that will replace some GDI
|
|
* functions for better performance.
|
|
*
|
|
* Copyright (c) 1994 FirePower Systems, Inc.
|
|
* New module for FirePower display model by Neil Ogura (9-7-1994)
|
|
* Copyright (c) 1992 Microsoft Corporation
|
|
* Some functions are quated from DDK sample source code.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
/*
|
|
* Copyright (c) 1995 FirePower Systems, Inc.
|
|
* DO NOT DISTRIBUTE without permission
|
|
*
|
|
* $RCSfile: hooks.c $
|
|
* $Revision: 1.3 $
|
|
* $Date: 1996/05/13 23:17:26 $
|
|
* $Locker: $
|
|
*/
|
|
|
|
#include "driver.h"
|
|
|
|
#define POSITIVE_MAX 0x7fffffff
|
|
|
|
#define DUMPFILL FALSE
|
|
#define DUMPOP FALSE
|
|
#define DUMPCOPY FALSE
|
|
#define DUMPTEXT FALSE
|
|
|
|
// Following structure overlays GLYPHPOS and must be no longer than
|
|
// 4 ULONGS (sizeof(GLYPHPOS))
|
|
// Definition shared with assembly language module textsub.s
|
|
|
|
typedef struct {
|
|
USHORT cjBits;
|
|
USHORT djDst;
|
|
USHORT startline;
|
|
USHORT endline;
|
|
PBYTE pprocFirstText;
|
|
PBYTE pjBits;
|
|
} GLYPHRAST;
|
|
|
|
#if INVESTIGATE
|
|
extern ULONG TextSubEntryCalled[MAX_TEXT_SUB_ENTRY];
|
|
extern ULONG TextSubEntryDCBZCalled[MAX_TEXT_SUB_ENTRY];
|
|
extern ULONG TextSubEntryTransCalled[MAX_TEXT_SUB_ENTRY];
|
|
#endif
|
|
|
|
extern PBYTE __mpcxpprocText8[32*4];
|
|
extern PBYTE __mpcxpprocText8DCBZ[32*4];
|
|
extern PBYTE __mpcxpprocTransText8[32*4];
|
|
extern PBYTE __mpcxpprocText16[32*2];
|
|
extern PBYTE __mpcxpprocText16DCBZ[32*2];
|
|
extern PBYTE __mpcxpprocTransText16[32*2];
|
|
extern PBYTE __mpcxpprocText32[32];
|
|
extern PBYTE __mpcxpprocText32DCBZ[32];
|
|
extern PBYTE __mpcxpprocTransText32[32];
|
|
extern PBYTE __psfontfetchentry[4];
|
|
extern PBYTE __ps2fontfetchentry[4];
|
|
extern PBYTE __fixedfontfetchentry[4];
|
|
extern PBYTE __xorentrytable[32];
|
|
extern PBYTE __andentrytable[32];
|
|
extern PBYTE __orentrytable[32];
|
|
extern PBYTE __orcentrytable[32];
|
|
extern PBYTE __b8opentrytable[32];
|
|
extern PBYTE __andcentrytable[32];
|
|
extern PBYTE __norentrytable[32];
|
|
extern PBYTE __nsrcentrytable[32];
|
|
|
|
//
|
|
// Size of code to subtract to do more than one "dcbz" - i.e. we need additional "dcbz" on top
|
|
// of XXXXDCBZ function for 16 or 32 BPP.
|
|
//
|
|
#define CBDCBZCODE 8
|
|
|
|
//
|
|
// Threshold of the width to use cached VRAM or non-cached VRAM
|
|
//
|
|
|
|
#define PAINT_THRESHOLD 40
|
|
|
|
#if FULLCACHE
|
|
#define FILLTHRESHOLD 64
|
|
#define OPTHRESHOLD 64
|
|
#define COPYBITTHRESHOLD 64
|
|
#else // FULLCACHE
|
|
// PRO threshold is an optimul threshold for PowerPro
|
|
#define PRO_FILLTHRESHOLD 44
|
|
#define PRO_OPTHRESHOLD 9
|
|
#define PRO_COPYBITTHRESHOLDDRAM 50
|
|
#define PRO_COPYBITTHRESHOLDVRAM 10
|
|
#define PRO_PTNOPTHRESHOLD 8
|
|
#define PRO_PTNFILLTHRESHOLD 32
|
|
/*** Warning ****
|
|
PTNFILLTHRESHOLD has to be 32 or less because ptnfill routine itself doesn't
|
|
support non cached target. If non-cached address is passed to pteern fill assembler
|
|
function and "dcbz" is used (it can be used if the width is 32 or more), the system
|
|
will crash. This is only for pattern fill. Fill, XOR and Text functions are supporting
|
|
both cached and non cached target.
|
|
****************/
|
|
#define PRO_TEXTTHRESHOLD 56
|
|
#define PRO_TRANSTEXTTHRESHOLD_8 12
|
|
#define PRO_TRANSTEXTTHRESHOLD_16 24
|
|
#define PRO_TRANSTEXTTHRESHOLD_32 48
|
|
//
|
|
// UP threshold is an optimul threshold for UP PowerTop
|
|
#define UP_FILLTHRESHOLD 8
|
|
#define UP_OPTHRESHOLD 0
|
|
#define UP_COPYBITTHRESHOLDDRAM 20
|
|
#define UP_COPYBITTHRESHOLDVRAM 0
|
|
#define UP_PTNOPTHRESHOLD 0
|
|
#define UP_PTNFILLTHRESHOLD 10
|
|
/*** Warning ****
|
|
PTNFILLTHRESHOLD has to be 32 or less because ptnfill routine itself doesn't
|
|
support non cached target. If non-cached address is passed to pteern fill assembler
|
|
function and "dcbz" is used (it can be used if the width is 32 or more), the system
|
|
will crash. This is only for pattern fill. Fill, XOR and Text functions are supporting
|
|
both cached and non cached target.
|
|
****************/
|
|
#define UP_TEXTTHRESHOLD 8
|
|
#define UP_TRANSTEXTTHRESHOLD_8 0
|
|
#define UP_TRANSTEXTTHRESHOLD_16 0
|
|
#define UP_TRANSTEXTTHRESHOLD_32 0
|
|
//
|
|
// MP threshold is an optimul threshold for SMP PowerPro
|
|
#define MP_FILLTHRESHOLD 8
|
|
#define MP_OPTHRESHOLD 0
|
|
#define MP_COPYBITTHRESHOLDDRAM 18
|
|
#define MP_COPYBITTHRESHOLDVRAM 0
|
|
#define MP_PTNOPTHRESHOLD 0
|
|
#define MP_PTNFILLTHRESHOLD 16
|
|
/*** Warning ****
|
|
PTNFILLTHRESHOLD has to be 32 or less because ptnfill routine itself doesn't
|
|
support non cached target. If non-cached address is passed to pteern fill assembler
|
|
function and "dcbz" is used (it can be used if the width is 32 or more), the system
|
|
will crash. This is only for pattern fill. Fill, XOR and Text functions are supporting
|
|
both cached and non cached target.
|
|
****************/
|
|
#define MP_TEXTTHRESHOLD 0
|
|
#define MP_TRANSTEXTTHRESHOLD_8 0
|
|
#define MP_TRANSTEXTTHRESHOLD_16 0
|
|
#define MP_TRANSTEXTTHRESHOLD_32 0
|
|
//
|
|
static ULONG FILLTHRESHOLD = PRO_FILLTHRESHOLD;
|
|
static ULONG OPTHRESHOLD = PRO_OPTHRESHOLD;
|
|
static ULONG COPYBITTHRESHOLDDRAM = PRO_COPYBITTHRESHOLDDRAM;
|
|
static ULONG COPYBITTHRESHOLDVRAM = PRO_COPYBITTHRESHOLDVRAM;
|
|
static ULONG PtnFillThreshold[2] = {PRO_PTNOPTHRESHOLD, PRO_PTNFILLTHRESHOLD};
|
|
static ULONG TEXTTHRESHOLD = PRO_TEXTTHRESHOLD;
|
|
static ULONG TransTextThreshold[3] = {PRO_TRANSTEXTTHRESHOLD_8, PRO_TRANSTEXTTHRESHOLD_16, PRO_TRANSTEXTTHRESHOLD_32};
|
|
|
|
#endif // FULLCACHE
|
|
|
|
//
|
|
// Define string object accelerator masks.
|
|
//
|
|
|
|
#define SO_MASK \
|
|
(SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \
|
|
SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE)
|
|
|
|
#define SO_LTOR (SO_MASK | SO_HORIZONTAL)
|
|
#define SO_RTOL (SO_LTOR | SO_REVERSED)
|
|
#define SO_TTOB (SO_MASK | SO_VERTICAL)
|
|
#define SO_BTOT (SO_TTOB | SO_REVERSED)
|
|
|
|
const BYTE gaMix[] =
|
|
{
|
|
0xFF, // R2_WHITE - Allow rop = gaMix[mix & 0x0F]
|
|
0x00, // R2_BLACK
|
|
0x05, // R2_NOTMERGEPEN
|
|
0x0A, // R2_MASKNOTPEN
|
|
0x0F, // R2_NOTCOPYPEN
|
|
0x50, // R2_MASKPENNOT
|
|
0x55, // R2_NOT
|
|
0x5A, // R2_XORPEN
|
|
0x5F, // R2_NOTMASKPEN
|
|
0xA0, // R2_MASKPEN
|
|
0xA5, // R2_NOTXORPEN
|
|
0xAA, // R2_NOP
|
|
0xAF, // R2_MERGENOTPEN
|
|
0xF0, // R2_COPYPEN
|
|
0xF5, // R2_MERGEPENNOT
|
|
0xFA, // R2_MERGEPEN
|
|
0xFF // R2_WHITE - Allow rop = gaMix[mix & 0xFF]
|
|
};
|
|
|
|
//
|
|
// Define big endian color mask table conversion table.
|
|
//
|
|
|
|
const ULONG DrvpColorMask[16] = {
|
|
0x00000000, // 0000 -> 0000
|
|
0xff000000, // 0001 -> 1000
|
|
0x00ff0000, // 0010 -> 0100
|
|
0xffff0000, // 0011 -> 1100
|
|
0x0000ff00, // 0100 -> 0010
|
|
0xff00ff00, // 0101 -> 1010
|
|
0x00ffff00, // 0110 -> 0110
|
|
0xffffff00, // 0111 -> 1110
|
|
0x000000ff, // 1000 -> 0001
|
|
0xff0000ff, // 1001 -> 1001
|
|
0x00ff00ff, // 1010 -> 0101
|
|
0xffff00ff, // 1011 -> 1101
|
|
0x0000ffff, // 1100 -> 0011
|
|
0xff00ffff, // 1101 -> 1011
|
|
0x00ffffff, // 1110 -> 0111
|
|
0xffffffff}; // 1111 -> 1111
|
|
|
|
static ULONG mpnibbleulMask8[16] = {
|
|
0xffffffff,
|
|
0x00ffffff,
|
|
0xff00ffff,
|
|
0x0000ffff,
|
|
0xffff00ff,
|
|
0x00ff00ff,
|
|
0xff0000ff,
|
|
0x000000ff,
|
|
0xffffff00,
|
|
0x00ffff00,
|
|
0xff00ff00,
|
|
0x0000ff00,
|
|
0xffff0000,
|
|
0x00ff0000,
|
|
0xff000000,
|
|
0x00000000
|
|
};
|
|
|
|
static ULONG mpnibbleulMask16[4] = {
|
|
0xffffffff,
|
|
0x0000ffff,
|
|
0xffff0000,
|
|
0x00000000
|
|
};
|
|
|
|
static ULONG mpnibbleulMask32[2] = {
|
|
0xffffffff,
|
|
0x00000000
|
|
};
|
|
|
|
//
|
|
// Color table and mask table
|
|
//
|
|
|
|
static ULONG mpnibbleulDraw[16];
|
|
|
|
ULONG ForeGroundColor = 0x12345678; // In order not to match any color at the beginning
|
|
ULONG BackGroundColor = 0x12345678; // This initialization has to be done when a new PDEV
|
|
// is created (in enable.c).
|
|
|
|
//
|
|
// GDI Structure
|
|
//
|
|
|
|
#define BB_RECT_LIMIT 50
|
|
|
|
typedef struct _ENUMRECTLIST
|
|
{
|
|
ULONG c;
|
|
RECTL arcl[BB_RECT_LIMIT];
|
|
} ENUMRECTLIST;
|
|
|
|
static ENUMRECTLIST ClipEnum;
|
|
|
|
typedef struct _FILLPARAM
|
|
{
|
|
PBYTE target;
|
|
ULONG width;
|
|
ULONG lines;
|
|
ULONG delta;
|
|
ULONG brush[2];
|
|
ULONG MaxEntryToFlush;
|
|
ULONG MaxLinesToFlush;
|
|
ULONG control;
|
|
ULONG regsave[8];
|
|
} FILLPARAM;
|
|
|
|
typedef struct _COPYPARAM
|
|
{
|
|
PBYTE target;
|
|
PBYTE source;
|
|
ULONG width;
|
|
ULONG lines;
|
|
ULONG tdelta;
|
|
ULONG sdelta;
|
|
ULONG MaxEntryToFlush;
|
|
ULONG MaxLinesToFlush;
|
|
ULONG control;
|
|
ULONG regsave[8];
|
|
} COPYPARAM;
|
|
|
|
typedef struct _OPPARAM
|
|
{
|
|
PBYTE target;
|
|
PBYTE source;
|
|
ULONG width;
|
|
ULONG lines;
|
|
ULONG tdelta;
|
|
ULONG sdelta;
|
|
ULONG MaxEntryToFlush;
|
|
ULONG MaxLinesToFlush;
|
|
ULONG control;
|
|
PBYTE *funcEntry;
|
|
ULONG solidBrush;
|
|
ULONG regsave[6];
|
|
} OPPARAM;
|
|
|
|
typedef struct _TEXTPARAM
|
|
{
|
|
PBYTE targetline;
|
|
ULONG dest;
|
|
ULONG width;
|
|
ULONG lines;
|
|
LONG delta;
|
|
PULONG colortable;
|
|
PULONG masktable;
|
|
PGLYPHPOS prggp;
|
|
PGLYPHPOS plastgp;
|
|
PBYTE fontfetchentry;
|
|
ULONG MaxLineToFlush;
|
|
ULONG control;
|
|
ULONG ulCharInc;
|
|
ULONG regsave[8];
|
|
} TEXTPARAM;
|
|
|
|
void RectFill(
|
|
FILLPARAM * fillparam
|
|
);
|
|
|
|
void RectOp(
|
|
FILLPARAM * fillparam
|
|
);
|
|
|
|
void RectCopy(
|
|
COPYPARAM * copyparam
|
|
);
|
|
|
|
void RectFillS(
|
|
void * target,
|
|
ULONG solidbrush,
|
|
ULONG width,
|
|
ULONG lines,
|
|
ULONG tdelta
|
|
);
|
|
|
|
void RectOpS(
|
|
void * target,
|
|
ULONG solidbrush,
|
|
ULONG width,
|
|
ULONG lines,
|
|
ULONG tdelta,
|
|
ULONG operation
|
|
);
|
|
|
|
void RectCopyS(
|
|
COPYPARAM * copyparam
|
|
);
|
|
|
|
void RectSrcOpTgt(
|
|
OPPARAM * opparam
|
|
);
|
|
|
|
void RectCopy24to15(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy24to16(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy24to32(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy15to16(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy15to32(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy8to8(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy8to16(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void RectCopy8to32(
|
|
COPYPARAM * copyparam,
|
|
PULONG palette
|
|
);
|
|
|
|
void Stretch16(
|
|
COPYPARAM * copyparam
|
|
);
|
|
|
|
void Stretch32(
|
|
COPYPARAM * copyparam
|
|
);
|
|
|
|
#if PAINT_NEW_METHOD
|
|
void LineFill(
|
|
void *target,
|
|
ULONG *Brush,
|
|
ULONG width,
|
|
ULONG control
|
|
);
|
|
|
|
void LineXor(
|
|
void *target,
|
|
ULONG Color,
|
|
ULONG width,
|
|
ULONG control
|
|
);
|
|
#endif
|
|
|
|
#if (! FULLCACHE)
|
|
void RectFlushCache(
|
|
void * target,
|
|
ULONG width,
|
|
ULONG lines,
|
|
ULONG delta,
|
|
ULONG MaxEntryToFlush,
|
|
ULONG MaxLinesToFlush
|
|
);
|
|
#endif
|
|
|
|
void __fill_pat8(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __fill_pat16(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __fill_pat32(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __xor_pat8(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __xor_pat16(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __xor_pat32(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nxor_pat8(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nxor_pat16(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nxor_pat32(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nand_pat8(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nand_pat16(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __nand_pat32(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __and_pat8(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __and_pat16(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void __and_pat32(
|
|
BYTE *pbDst,
|
|
double *pdFillValue,
|
|
LONG cbX,
|
|
LONG cy,
|
|
LONG ldDst,
|
|
ULONG *prgwSave
|
|
);
|
|
|
|
void PSTextOut2(
|
|
TEXTPARAM * textparam
|
|
);
|
|
|
|
void PSTextOut(
|
|
TEXTPARAM * textparam
|
|
);
|
|
|
|
void FixedTextOut(
|
|
TEXTPARAM * textparam
|
|
);
|
|
|
|
#if DBG
|
|
|
|
ULONG filldumplevel = 4;
|
|
|
|
VOID
|
|
DumpTextParam(
|
|
IN TEXTPARAM *textparam
|
|
)
|
|
{
|
|
DISPDBG((3, "Textout %d lines of data of %d width with %x cache control\n",
|
|
textparam->lines, textparam->width, textparam->control));
|
|
DISPDBG((3, "First line of target = %x-%x\n", textparam->targetline+textparam->dest,
|
|
textparam->targetline+textparam->dest+textparam->width-1));
|
|
DISPDBG((3, "Last line of target = %x-%x\n", textparam->targetline+textparam->dest+(textparam->lines-1)*textparam->delta,
|
|
textparam->targetline+textparam->dest+(textparam->lines-1)*textparam->delta+textparam->width-1));
|
|
}
|
|
|
|
VOID
|
|
DumpFillParam(
|
|
IN FILLPARAM *fillparam
|
|
)
|
|
{
|
|
DISPDBG((filldumplevel, "Filling %d lines of data of %d width with %x cache control using %x color\n",
|
|
fillparam->lines, fillparam->width, fillparam->control, fillparam->brush[0]));
|
|
DISPDBG((filldumplevel, "First line of target = %x-%x\n", fillparam->target,
|
|
fillparam->target+fillparam->width-1));
|
|
DISPDBG((filldumplevel, "Last line of target = %x-%x\n", fillparam->target+(fillparam->lines-1)*fillparam->delta,
|
|
fillparam->target+(fillparam->lines-1)*fillparam->delta+fillparam->width-1));
|
|
}
|
|
|
|
VOID
|
|
DumpFillParamS(
|
|
BYTE * target,
|
|
ULONG solidbrush,
|
|
ULONG width,
|
|
ULONG lines,
|
|
ULONG tdelta
|
|
)
|
|
{
|
|
DISPDBG((filldumplevel, "Filling Short %d lines of data of %d width using %x color\n",
|
|
lines, width, solidbrush));
|
|
DISPDBG((filldumplevel, "First line of target = %x-%x\n", target,
|
|
target+width-1));
|
|
DISPDBG((filldumplevel, "Last line of target = %x-%x\n", target+(lines-1)*tdelta,
|
|
target+(lines-1)*tdelta+width-1));
|
|
}
|
|
|
|
VOID
|
|
DumpOpParam(
|
|
IN FILLPARAM *fillparam
|
|
)
|
|
{
|
|
DISPDBG((5, "Binary operation %d lines of data of %d width with %x control using %x brush\n",
|
|
fillparam->lines, fillparam->width, fillparam->control, fillparam->brush[0]));
|
|
DISPDBG((5, "First line of target = %x-%x\n", fillparam->target,
|
|
fillparam->target+fillparam->width-1));
|
|
DISPDBG((5, "Last line of target = %x-%x\n", fillparam->target+(fillparam->lines-1)*fillparam->delta,
|
|
fillparam->target+(fillparam->lines-1)*fillparam->delta+fillparam->width-1));
|
|
}
|
|
|
|
VOID
|
|
DumpCopyParam(
|
|
IN COPYPARAM *copyparam
|
|
)
|
|
{
|
|
DISPDBG((6, "Copying %d lines of data of %d width with %x cache control\n",
|
|
copyparam->lines, copyparam->width, copyparam->control));
|
|
DISPDBG((6, "First line of source = %x-%x\n", copyparam->source,
|
|
copyparam->source+copyparam->width-1));
|
|
DISPDBG((6, "Last line of source = %x-%x\n", copyparam->source+(copyparam->lines-1)*copyparam->sdelta,
|
|
copyparam->source+(copyparam->lines-1)*copyparam->sdelta+copyparam->width-1));
|
|
DISPDBG((6, "First line of target = %x-%x\n", copyparam->target,
|
|
copyparam->target+copyparam->width-1));
|
|
DISPDBG((6, "Last line of target = %x-%x\n", copyparam->target+(copyparam->lines-1)*copyparam->tdelta,
|
|
copyparam->target+(copyparam->lines-1)*copyparam->tdelta+copyparam->width-1));
|
|
}
|
|
#endif
|
|
|
|
#if (! FULLCACHE)
|
|
VOID
|
|
SetTopThreshold(ULONG SMP)
|
|
{
|
|
if(SMP) {
|
|
FILLTHRESHOLD = MP_FILLTHRESHOLD;
|
|
OPTHRESHOLD = MP_OPTHRESHOLD;
|
|
COPYBITTHRESHOLDDRAM = MP_COPYBITTHRESHOLDDRAM;
|
|
COPYBITTHRESHOLDVRAM = MP_COPYBITTHRESHOLDVRAM;
|
|
PtnFillThreshold[0] = MP_PTNOPTHRESHOLD;
|
|
PtnFillThreshold[1] = MP_PTNFILLTHRESHOLD;
|
|
TEXTTHRESHOLD = MP_TEXTTHRESHOLD;
|
|
TransTextThreshold[0] = MP_TRANSTEXTTHRESHOLD_8;
|
|
TransTextThreshold[1] = MP_TRANSTEXTTHRESHOLD_16;
|
|
TransTextThreshold[2] = MP_TRANSTEXTTHRESHOLD_32;
|
|
} else {
|
|
FILLTHRESHOLD = UP_FILLTHRESHOLD;
|
|
OPTHRESHOLD = UP_OPTHRESHOLD;
|
|
COPYBITTHRESHOLDDRAM = UP_COPYBITTHRESHOLDDRAM;
|
|
COPYBITTHRESHOLDVRAM = UP_COPYBITTHRESHOLDVRAM;
|
|
PtnFillThreshold[0] = UP_PTNOPTHRESHOLD;
|
|
PtnFillThreshold[1] = UP_PTNFILLTHRESHOLD;
|
|
TEXTTHRESHOLD = UP_TEXTTHRESHOLD;
|
|
TransTextThreshold[0] = UP_TRANSTEXTTHRESHOLD_8;
|
|
TransTextThreshold[1] = UP_TRANSTEXTTHRESHOLD_16;
|
|
TransTextThreshold[2] = UP_TRANSTEXTTHRESHOLD_32;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if BUG_5737_WORKAROUND
|
|
|
|
static ModeChanged = FALSE;
|
|
|
|
VOID
|
|
DisplayModeChanged()
|
|
{
|
|
ModeChanged = TRUE;
|
|
}
|
|
|
|
#endif
|
|
|
|
BOOL
|
|
DrvpIntersectRect(
|
|
IN PRECTL Rectl1,
|
|
IN PRECTL Rectl2,
|
|
OUT PRECTL DestRectl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine checks to see if the two specified retangles intersect.
|
|
|
|
N.B. This routine is adopted from a routine written by darrinm.
|
|
|
|
Arguments:
|
|
|
|
Rectl1 - Supplies the coordinates of the first rectangle.
|
|
|
|
Rectl2 - Supplies the coordinates of the second rectangle.
|
|
|
|
DestRectl - Supplies the coordinates of the output rectangle.
|
|
|
|
Return Value:
|
|
|
|
A value of TRUE is returned if the rectangles intersect. Otherwise,
|
|
a value of FALSE is returned.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
|
|
//
|
|
// Compute the maximum left edge and the minimum right edge.
|
|
//
|
|
|
|
DestRectl->left = max(Rectl1->left, Rectl2->left);
|
|
DestRectl->right = min(Rectl1->right, Rectl2->right);
|
|
|
|
//
|
|
// If the minimum right edge is greater than the maximum left edge,
|
|
// then the rectanges may intersect. Otherwise, they do not intersect.
|
|
//
|
|
|
|
if (DestRectl->left < DestRectl->right) {
|
|
|
|
//
|
|
// Compute the maximum top edge and the minimum bottom edge.
|
|
//
|
|
|
|
DestRectl->top = max(Rectl1->top, Rectl2->top);
|
|
DestRectl->bottom = min(Rectl1->bottom, Rectl2->bottom);
|
|
|
|
//
|
|
// If the minimum bottom edge is greater than the maximum top
|
|
// edge, then the rectanges intersect. Otherwise, they do not
|
|
// intersect.
|
|
//
|
|
|
|
if (DestRectl->top < DestRectl->bottom) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
DrvpSolidFill(
|
|
IN PRECTL DstRect,
|
|
IN CLIPOBJ *pco,
|
|
IN ULONG Color,
|
|
IN LONG tdelta,
|
|
IN PBYTE target,
|
|
IN ULONG colorModeShift
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine fills the unclipped areas of the destination rectangle with
|
|
the given color.
|
|
|
|
Arguments:
|
|
|
|
DstRect - Destination Rectangle
|
|
pco - Clipping area.
|
|
Color - Color to fill with.
|
|
tdelta - target delta bytes between lines.
|
|
target - target surface address.
|
|
colorModeShift - 0:8BPP, 1:16BPP, 2:32BPP.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the operation is done, FALSE if not.
|
|
|
|
--*/
|
|
{
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions;
|
|
LONG tline, tpos;
|
|
FILLPARAM fillparam;
|
|
PBYTE cachedtarget;
|
|
|
|
switch(colorModeShift) {
|
|
case 0: Color &= 0xff;
|
|
Color |= (Color << 8);
|
|
case 1: Color &= 0xffff;
|
|
Color |= (Color << 16);
|
|
default: fillparam.brush[0] = fillparam.brush[1] = Color;
|
|
}
|
|
|
|
#if FULLCACHE
|
|
cachedtarget = target;
|
|
#else // FULLCACHE
|
|
if(target == (PBYTE) ScreenBase) { // Target is VRAM
|
|
fillparam.control = ((myPDEV->VRAMcacheflg) & (TFLUSHBIT | TTOUCHBIT));
|
|
fillparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
fillparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
fillparam.control = 0;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
fillparam.delta = tdelta;
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
tline = DstRect->top;
|
|
tpos = DstRect->left;
|
|
fillparam.lines = DstRect->bottom - tline;
|
|
if((fillparam.width = (DstRect->right - tpos) << colorModeShift) >= FILLTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*tline + (tpos << colorModeShift);
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((0));
|
|
RectFill(&fillparam);
|
|
EXITCRITICAL((0));
|
|
} else {
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParamS(target + tdelta*tline + (tpos << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
#endif
|
|
RectFillS(target + tdelta*tline + (tpos << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
}
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do the BLT if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(DstRect, &pco->rclBounds, &BltRectl)) {
|
|
fillparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= FILLTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((0));
|
|
RectFill(&fillparam);
|
|
EXITCRITICAL((0));
|
|
} else {
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParamS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
#endif
|
|
RectFillS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
}
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(DstRect, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
fillparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= FILLTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((0));
|
|
RectFill(&fillparam);
|
|
EXITCRITICAL((0));
|
|
} else {
|
|
#if (DBG && DUMPFILL)
|
|
DumpFillParamS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
#endif
|
|
RectFillS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta);
|
|
}
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DrvpSolidOp(
|
|
IN PRECTL DstRect,
|
|
IN CLIPOBJ *pco,
|
|
IN LONG operation,
|
|
IN ULONG Color,
|
|
IN LONG tdelta,
|
|
IN PBYTE target,
|
|
IN ULONG colorModeShift
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine perform operation on the unclipped areas of the destination rectangle with
|
|
the given operation and color.Currently, only OPXOR is supported.
|
|
|
|
Arguments:
|
|
|
|
DstRect - Destination Rectangle
|
|
pco - Clipping area.
|
|
operation - operation to perform.
|
|
Color - Color to fill with.
|
|
tdelta - target delta bytes between lines.
|
|
target - target surface address.
|
|
colorModeShift - 0:8BPP, 1:16BPP, 2:32BPP.
|
|
|
|
Return Value:
|
|
|
|
TRUE if the operation is done, FALSE if not.
|
|
|
|
--*/
|
|
{
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions;
|
|
LONG tline, tpos;
|
|
FILLPARAM fillparam;
|
|
PBYTE cachedtarget;
|
|
|
|
switch(colorModeShift) {
|
|
case 0: Color &= 0xff;
|
|
Color |= (Color << 8);
|
|
case 1: Color &= 0xffff;
|
|
Color |= (Color << 16);
|
|
default: fillparam.brush[0] = Color;
|
|
}
|
|
|
|
#if FULLCACHE
|
|
cachedtarget = target;
|
|
fillparam.control = operation;
|
|
#else // FULLCACHE
|
|
if(target == (PBYTE) ScreenBase) { // Target is VRAM
|
|
fillparam.control = ((myPDEV->VRAMcacheflg) & TFLUSHBIT) | operation;
|
|
fillparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
fillparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
fillparam.control = operation;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
fillparam.delta = tdelta;
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
tline = DstRect->top;
|
|
tpos = DstRect->left;
|
|
fillparam.lines = DstRect->bottom - tline;
|
|
if((fillparam.width = (DstRect->right - tpos) << colorModeShift) >= OPTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*tline + (tpos << colorModeShift);
|
|
#if (DBG && DUMPOP)
|
|
DumpOpParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((1));
|
|
RectOp(&fillparam);
|
|
EXITCRITICAL((1));
|
|
} else {
|
|
RectOpS(target + tdelta*tline + (tpos << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta, operation);
|
|
}
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do the BLT if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(DstRect, &pco->rclBounds, &BltRectl)) {
|
|
fillparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= OPTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
#if (DBG && DUMPOP)
|
|
DumpOpParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((1));
|
|
RectOp(&fillparam);
|
|
EXITCRITICAL((1));
|
|
} else {
|
|
RectOpS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta, operation);
|
|
}
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(DstRect, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
fillparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= OPTHRESHOLD) {
|
|
fillparam.target = cachedtarget + tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
#if (DBG && DUMPOP)
|
|
DumpOpParam(&fillparam);
|
|
#endif
|
|
ENTERCRITICAL((1));
|
|
RectOp(&fillparam);
|
|
EXITCRITICAL((1));
|
|
} else {
|
|
RectOpS(target + tdelta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, tdelta, operation);
|
|
}
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DrvpPatternFill(
|
|
IN PRECTL DstRect,
|
|
IN CLIPOBJ *pco,
|
|
IN RBRUSH *prb,
|
|
IN POINTL *pptlBrush,
|
|
IN LONG tdelta,
|
|
IN PBYTE target,
|
|
IN ULONG colorModeShift,
|
|
IN ROP4 rop4
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine fills the unclipped areas of the destination rectangle with
|
|
the given pattern.
|
|
|
|
Arguments:
|
|
|
|
DstRect - Destination Rectangle
|
|
pco - Clipping area.
|
|
pbo - pointer to brush to use.
|
|
pptlBrush - specify the origin of the brush
|
|
tdelta - target delta bytes between lines.
|
|
target - target surface address.
|
|
colorModeShift - 0:8BPP, 1:16BPP, 2:32BPP.
|
|
ROP4 - only 0x5a5a (PATINVERT), 0xa5a5 (NOTPATINVERT) and 0xf0f0 (PATFILL) are supported
|
|
|
|
Return Value:
|
|
|
|
TRUE if the operation is done, FALSE if not.
|
|
|
|
--*/
|
|
|
|
{
|
|
PBYTE cachedtarget;
|
|
ULONG control, i;
|
|
LONG ldFill;
|
|
UCHAR *pjDst;
|
|
ULONG cjDst;
|
|
LONG yTop;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions;
|
|
RECTL BltRectl;
|
|
void (*pprocFillPat)();
|
|
ULONG rgwSave[32];
|
|
#if (! FULLCACHE)
|
|
UCHAR *pjDstSave = NULL; // To remove warning messages: 3/20/95
|
|
ULONG PTNFILLTHRESHOLD;
|
|
#endif
|
|
|
|
#if FULLCACHE
|
|
cachedtarget = target;
|
|
#else // FULLCACHE
|
|
if(target == (PBYTE) ScreenBase) { // Target is VRAM
|
|
if(myPDEV->VRAMcacheflg == 0) { // display driver couldn't find DBAT mapping to cacheable VRAM
|
|
return FALSE; // calling assembler function will cause system crash in that case
|
|
}
|
|
control = TFLUSHBIT | TTOUCHBIT;
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
control = 0;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
switch(rop4) {
|
|
case 0xf0f0: // PTNFILL
|
|
#if (! FULLCACHE)
|
|
PTNFILLTHRESHOLD = PtnFillThreshold[1];
|
|
#endif
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
pprocFillPat = __fill_pat8;
|
|
break;
|
|
case 1:
|
|
pprocFillPat = __fill_pat16;
|
|
break;
|
|
default:
|
|
pprocFillPat = __fill_pat32;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x5a5a: // PTNINVERT
|
|
#if (! FULLCACHE)
|
|
PTNFILLTHRESHOLD = PtnFillThreshold[0];
|
|
#endif
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
pprocFillPat = __xor_pat8;
|
|
break;
|
|
case 1:
|
|
pprocFillPat = __xor_pat16;
|
|
break;
|
|
default:
|
|
pprocFillPat = __xor_pat32;
|
|
break;
|
|
}
|
|
break;
|
|
case 0xa5a5: // NOTPTNINVERT
|
|
#if (! FULLCACHE)
|
|
PTNFILLTHRESHOLD = PtnFillThreshold[0];
|
|
#endif
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
pprocFillPat = __nxor_pat8;
|
|
break;
|
|
case 1:
|
|
pprocFillPat = __nxor_pat16;
|
|
break;
|
|
default:
|
|
pprocFillPat = __nxor_pat32;
|
|
break;
|
|
}
|
|
break;
|
|
case 0x0a0a: // NOT PAT AND DEST
|
|
#if (! FULLCACHE)
|
|
PTNFILLTHRESHOLD = PtnFillThreshold[0];
|
|
#endif
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
pprocFillPat = __nand_pat8;
|
|
break;
|
|
case 1:
|
|
pprocFillPat = __nand_pat16;
|
|
break;
|
|
default:
|
|
pprocFillPat = __nand_pat32;
|
|
break;
|
|
}
|
|
break;
|
|
default: // PAT AND DEST
|
|
#if (! FULLCACHE)
|
|
PTNFILLTHRESHOLD = PtnFillThreshold[0];
|
|
#endif
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
pprocFillPat = __and_pat8;
|
|
break;
|
|
case 1:
|
|
pprocFillPat = __and_pat16;
|
|
break;
|
|
default:
|
|
pprocFillPat = __and_pat32;
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
ldFill = tdelta << 3; // fill every 8th scan line
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) {
|
|
#if FULLCACHE
|
|
yTop = DstRect->top;
|
|
pjDst = (BYTE*)cachedtarget + (yTop * tdelta) + (DstRect->left << colorModeShift);
|
|
cjDst = (DstRect->right-DstRect->left) << colorModeShift;
|
|
for(i = 0; (i < 8) && (yTop < DstRect->bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (DstRect->bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
#else // FULLCACHE
|
|
yTop = DstRect->top;
|
|
if((cjDst = (DstRect->right-DstRect->left) << colorModeShift) >= PTNFILLTHRESHOLD) {
|
|
pjDst = pjDstSave = (BYTE*)cachedtarget + (yTop * tdelta) + (DstRect->left << colorModeShift);
|
|
} else {
|
|
pjDst = (BYTE*)target + (yTop * tdelta) + (DstRect->left << colorModeShift);
|
|
}
|
|
ENTERCRITICAL((4));
|
|
for(i = 0; (i < 8) && (yTop < DstRect->bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (DstRect->bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
if((cjDst >= PTNFILLTHRESHOLD) && (control & TFLUSHBIT))
|
|
RectFlushCache(pjDstSave, cjDst, DstRect->bottom-DstRect->top, tdelta, myPDEV->MaxEntryToFlushPtnFill, myPDEV->MaxLineToFlushPtnFill);
|
|
EXITCRITICAL((4));
|
|
#endif
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do the BLT if there is an intersection
|
|
//
|
|
if(DrvpIntersectRect(DstRect, &pco->rclBounds, &BltRectl)) {
|
|
#if FULLCACHE
|
|
yTop = BltRectl.top;
|
|
pjDst = (BYTE*)cachedtarget + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
cjDst = (BltRectl.right-BltRectl.left) << colorModeShift;
|
|
for (i = 0; (i < 8) && (yTop < BltRectl.bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (BltRectl.bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
#else // FULLCACHE
|
|
yTop = BltRectl.top;
|
|
if((cjDst = (BltRectl.right-BltRectl.left) << colorModeShift) >= PTNFILLTHRESHOLD) {
|
|
pjDst = pjDstSave = (BYTE*)cachedtarget + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
} else {
|
|
pjDst = (BYTE*)target + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
}
|
|
ENTERCRITICAL((4));
|
|
for(i = 0; (i < 8) && (yTop < BltRectl.bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (BltRectl.bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
if((cjDst >= PTNFILLTHRESHOLD) && (control & TFLUSHBIT))
|
|
RectFlushCache(pjDstSave, cjDst, BltRectl.bottom-BltRectl.top, tdelta, myPDEV->MaxEntryToFlushPtnFill, myPDEV->MaxLineToFlushPtnFill);
|
|
EXITCRITICAL((4));
|
|
#endif
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(DstRect, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
#if FULLCACHE
|
|
yTop = BltRectl.top;
|
|
pjDst = (BYTE*)cachedtarget + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
cjDst = (BltRectl.right-BltRectl.left) << colorModeShift;
|
|
for (i = 0; (i < 8) && (yTop < BltRectl.bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (BltRectl.bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
#else // FULLCACHE
|
|
yTop = BltRectl.top;
|
|
if((cjDst = (BltRectl.right-BltRectl.left) << colorModeShift) >= PTNFILLTHRESHOLD) {
|
|
pjDst = pjDstSave = (BYTE*)cachedtarget + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
} else {
|
|
pjDst = (BYTE*)target + (BltRectl.top * tdelta) + (BltRectl.left << colorModeShift);
|
|
}
|
|
ENTERCRITICAL((4));
|
|
for(i = 0; (i < 8) && (yTop < BltRectl.bottom); i++, yTop++, pjDst += tdelta)
|
|
(*pprocFillPat)(pjDst,
|
|
&prb->adPattern[((((yTop-pptlBrush->y) & 7)<<3) + (pptlBrush->x & 7)) << colorModeShift],
|
|
cjDst, (BltRectl.bottom - yTop + 7) >> 3, ldFill, rgwSave);
|
|
if((cjDst >= PTNFILLTHRESHOLD) && (control & TFLUSHBIT))
|
|
RectFlushCache(pjDstSave, cjDst, BltRectl.bottom-BltRectl.top, tdelta, myPDEV->MaxEntryToFlushPtnFill, myPDEV->MaxLineToFlushPtnFill);
|
|
EXITCRITICAL((4));
|
|
#endif
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
return FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL DrvpOpSrc(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclDest,
|
|
POINTL *pptlSrc,
|
|
ULONG colorModeShift,
|
|
PBYTE *functable,
|
|
ULONG brush
|
|
)
|
|
{
|
|
LONG tline, tpos;
|
|
PBYTE cachedtarget, target, cachedsource, source;
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions, iDirection, cacheControl;
|
|
OPPARAM opparam;
|
|
|
|
if((psoSrc->iBitmapFormat == psoDest->iBitmapFormat) && (!((opparam.sdelta = psoSrc->lDelta) & 0x03))) {
|
|
opparam.funcEntry = functable;
|
|
opparam.solidBrush = brush;
|
|
opparam.tdelta = psoDest->lDelta;
|
|
#if FULLCACHE
|
|
cachedtarget = target = psoDest->pvScan0;
|
|
#else // FULLCACHE
|
|
if((target = psoDest->pvScan0) == (PBYTE) ScreenBase) { // Target is VRAM
|
|
opparam.control = ((myPDEV->VRAMcacheflg) & TFLUSHBIT);
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
opparam.control = 0;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
#if FULLCACHE
|
|
cachedsource = source = psoSrc->pvScan0;
|
|
#else // FULLCACHE
|
|
if((source = psoSrc->pvScan0) == (PBYTE) ScreenBase) { // Source is VRAM
|
|
opparam.control |= ((myPDEV->VRAMcacheflg) & SFLUSHBIT);
|
|
cachedsource = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
cachedsource = source;
|
|
}
|
|
opparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
opparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
#endif // FULLCACHE
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
tline = prclDest->top;
|
|
tpos = prclDest->left;
|
|
opparam.lines = prclDest->bottom - tline;
|
|
opparam.width = (prclDest->right - tpos) << colorModeShift;
|
|
opparam.target = cachedtarget + opparam.tdelta*tline + (tpos << colorModeShift);
|
|
opparam.source = cachedsource + opparam.sdelta*(pptlSrc->y) + ((pptlSrc->x) << colorModeShift);
|
|
ENTERCRITICAL((3));
|
|
RectSrcOpTgt(&opparam);
|
|
EXITCRITICAL((3));
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do the BLT if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &pco->rclBounds, &BltRectl)) {
|
|
opparam.lines = BltRectl.bottom - BltRectl.top;
|
|
opparam.width = (BltRectl.right - BltRectl.left) << colorModeShift;
|
|
opparam.target = cachedtarget + opparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
opparam.source = cachedsource + opparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
ENTERCRITICAL((3));
|
|
RectSrcOpTgt(&opparam);
|
|
EXITCRITICAL((3));
|
|
} else {
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
if(source == target) {
|
|
if (pptlSrc->y <= prclDest->top) {
|
|
iDirection = CD_UPWARDS;
|
|
} else {
|
|
iDirection = 0;
|
|
}
|
|
if (pptlSrc->x <= prclDest->left) {
|
|
iDirection |= CD_LEFTWARDS;
|
|
}
|
|
} else {
|
|
iDirection = CD_ANY;
|
|
}
|
|
cacheControl = opparam.control;
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
opparam.lines = BltRectl.bottom - BltRectl.top;
|
|
opparam.width = (BltRectl.right - BltRectl.left) << colorModeShift;
|
|
opparam.target = cachedtarget + opparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
opparam.source = cachedsource + opparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
opparam.control = cacheControl;
|
|
ENTERCRITICAL((3));
|
|
RectSrcOpTgt(&opparam);
|
|
EXITCRITICAL((3));
|
|
} else {
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
return(FALSE);
|
|
} else
|
|
return(FALSE);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
#if PAINT_NEW_METHOD
|
|
|
|
BOOL
|
|
DrvpPaintFill(
|
|
IN CLIPOBJ *pco,
|
|
IN ULONG Color,
|
|
IN SURFOBJ *pso
|
|
)
|
|
{
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions;
|
|
FILLPARAM fillparam;
|
|
PBYTE target, cachedtarget;
|
|
ULONG colorModeShift;
|
|
|
|
switch(pso->iBitmapFormat) {
|
|
case BMF_8BPP:
|
|
colorModeShift = 0;
|
|
Color &= 0xff;
|
|
Color |= (Color << 8);
|
|
Color |= (Color << 16);
|
|
break;
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
Color &= 0xffff;
|
|
Color |= (Color << 16);
|
|
break;
|
|
default:
|
|
colorModeShift = 2;
|
|
}
|
|
fillparam.brush[0] = fillparam.brush[1] = Color;
|
|
fillparam.delta = pso->lDelta;
|
|
fillparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
fillparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
target = pso->pvScan0;
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if(DrvpIntersectRect(&pco->rclBounds, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= FILLTHRESHOLD) {
|
|
fillparam.target = cachedtarget + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
if((fillparam.lines = BltRectl.bottom - BltRectl.top) == 1) { // one line fill
|
|
LineFill(fillparam.target, &fillparam.brush[0], fillparam.width, TFLUSHBIT);
|
|
} else {
|
|
fillparam.control = TTOUCHBIT | TFLUSHBIT;
|
|
RectFill(&fillparam);
|
|
}
|
|
} else {
|
|
if((fillparam.lines = BltRectl.bottom - BltRectl.top) == 1) { // one line fill
|
|
LineFill(target + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
&fillparam.brush[0], fillparam.width, 0);
|
|
} else {
|
|
RectFillS(target + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
Color, fillparam.width, fillparam.lines, fillparam.delta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
|
|
/*** This code (RectFlushCache) was used for testing the idea of "writing all PaintFill to cached VRAM
|
|
without flushing, and flush entire rectangle area after all drawing. But, its performance was actually
|
|
it was slower than using cached or non-cached VRAM depending on the width of the area. So, it's not used
|
|
anymore, but I want to leave the code here as a comment just in case (not to try the same thing from scratch).
|
|
To try this method, it's necessary to change above code to use cached VRAM always and not to flush cache
|
|
in each operation (LineFill and RectFill).
|
|
#if (! FULLCACHE)
|
|
// RectFlushCache(cachedtarget + fillparam.delta*pco->rclBounds.top + (pco->rclBounds.left << colorModeShift),
|
|
// (pco->rclBounds.right - pco->rclBounds.left) << colorModeShift,
|
|
// pco->rclBounds.bottom - pco->rclBounds.top,
|
|
// fillparam.delta, POSITIVE_MAX, POSITIVE_MAX);
|
|
#endif
|
|
***/
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
DrvpPaintXOR(
|
|
IN CLIPOBJ *pco,
|
|
IN SURFOBJ *pso
|
|
)
|
|
{
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions;
|
|
FILLPARAM fillparam;
|
|
PBYTE target, cachedtarget;
|
|
ULONG colorModeShift;
|
|
|
|
switch(pso->iBitmapFormat) {
|
|
case BMF_8BPP:
|
|
colorModeShift = 0;
|
|
break;
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
break;
|
|
default:
|
|
colorModeShift = 2;
|
|
}
|
|
fillparam.brush[0] = 0xffffffff;
|
|
fillparam.delta = pso->lDelta;
|
|
target = pso->pvScan0;
|
|
fillparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
fillparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if(DrvpIntersectRect(&pco->rclBounds, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
if((fillparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= OPTHRESHOLD) {
|
|
fillparam.target = cachedtarget + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
if((fillparam.lines = BltRectl.bottom - BltRectl.top) == 1) { // one line fill
|
|
LineXor(fillparam.target, fillparam.brush[0], fillparam.width, TFLUSHBIT);
|
|
} else {
|
|
fillparam.control = OPXOR | TFLUSHBIT;
|
|
RectOp(&fillparam);
|
|
}
|
|
} else {
|
|
if((fillparam.lines = BltRectl.bottom - BltRectl.top) == 1) { // one line fill
|
|
LineXor(target + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
fillparam.brush[0], fillparam.width, 0);
|
|
} else {
|
|
RectOpS(target + fillparam.delta*BltRectl.top + (BltRectl.left << colorModeShift),
|
|
fillparam.brush[0], fillparam.width, fillparam.lines, fillparam.delta, OPXOR);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
|
|
/*** This code (RectFlushCache) was used for testing the idea of "writing all PaintFill to cached VRAM
|
|
without flushing, and flush entire rectangle area after all drawing. But, its performance was actually
|
|
it was slower than using cached or non-cached VRAM depending on the width of the area. So, it's not used
|
|
anymore, but I want to leave the code here as a comment just in case (not to try the same thing from scratch).
|
|
To try this method, it's necessary to change above code to use cached VRAM always and not to flush cache
|
|
in each operation (LineXor and RectOp).
|
|
#if (! FULLCACHE)
|
|
// RectFlushCache(cachedtarget + fillparam.delta*pco->rclBounds.top + (pco->rclBounds.left << colorModeShift),
|
|
// (pco->rclBounds.right - pco->rclBounds.left) << colorModeShift,
|
|
// pco->rclBounds.bottom - pco->rclBounds.top,
|
|
// fillparam.delta, POSITIVE_MAX, POSITIVE_MAX);
|
|
#endif
|
|
***/
|
|
return TRUE;
|
|
}
|
|
|
|
#endif // PAINT_NEW_METHOD
|
|
|
|
/***** Driver Hook Out Functions *****/
|
|
|
|
BOOL DrvBitBlt(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
POINTL *pptlMask,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrush,
|
|
ROP4 rop4)
|
|
{
|
|
BOOL rc;
|
|
LONG tdelta;
|
|
PBYTE target;
|
|
ULONG colorModeShift;
|
|
RBRUSH* prb;
|
|
ULONG Color;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_BITBLT;
|
|
if(traseentry & dbgflg & FL_DRV_BITBLT)
|
|
DISPDBG((0,"+++ Entering DrvBitBlt +++\n"));
|
|
if(breakentry & FL_DRV_BITBLT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_BITBLT));
|
|
|
|
if(! myPDEV)
|
|
goto puntbackBitBlt;
|
|
|
|
switch(psoTrg->iBitmapFormat) {
|
|
case BMF_8BPP:
|
|
colorModeShift = 0;
|
|
break;
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
break;
|
|
case BMF_32BPP:
|
|
colorModeShift = 2;
|
|
break;
|
|
default:
|
|
goto puntbackBitBlt;
|
|
}
|
|
|
|
if((!((tdelta = psoTrg->lDelta) & 0x03)) && ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))) {
|
|
target = psoTrg->pvScan0;
|
|
switch(rop4) {
|
|
case 0x0000: // DDx (BLACKNESS)
|
|
if((rc = DrvpSolidFill(prclTrg, pco, 0, tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0xFFFF: // DDxn (WHITENESS)
|
|
if((rc = DrvpSolidFill(prclTrg, pco, 0xffffff, tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0xF0F0: // P (PATCOPY)
|
|
if(pbo->iSolidColor == 0xFFFFFFFF) { // Pattern fill
|
|
// Try and realize the pattern brush; by doing
|
|
// this call-back, GDI will eventually call us
|
|
// again through DrvRealizeBrush.
|
|
prb = pbo->pvRbrush;
|
|
if (prb == NULL)
|
|
prb = BRUSHOBJ_pvGetRbrush(pbo);
|
|
if (prb == NULL || tdelta & 0x1f)
|
|
// If target delta is not modula of 32 (cache line alignment) or
|
|
// If we couldn't realize the brush, punt
|
|
// the call (it may have been a non 8x8
|
|
// brush or something, which we can't be
|
|
// bothered to handle, so let GDI do the
|
|
// drawing):
|
|
goto puntbackBitBlt;
|
|
if((rc = DrvpPatternFill(prclTrg, pco, prb, pptlBrush, tdelta, target, colorModeShift, rop4)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
} else {
|
|
if((rc = DrvpSolidFill(prclTrg, pco, pbo->iSolidColor, tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
}
|
|
break;
|
|
case 0x0F0F: // Pn (NOTPATCOPY)
|
|
if(pbo->iSolidColor == 0xFFFFFFFF ||
|
|
(rc = DrvpSolidFill(prclTrg, pco, ~(pbo->iSolidColor), tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x5555: // XOR dest (DSTINVERT)
|
|
if((rc = DrvpSolidOp(prclTrg, pco, OPXOR, 0xffffffff, tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x5a5a: // XOR dest with the pattern (PATINVERT)
|
|
case 0xa5a5: // XOR dest with inverted pattern (NOTPATINVERT)
|
|
if(pbo->iSolidColor == 0xFFFFFFFF) { // Pattern xor
|
|
// Try and realize the pattern brush; by doing
|
|
// this call-back, GDI will eventually call us
|
|
// again through DrvRealizeBrush.
|
|
prb = pbo->pvRbrush;
|
|
if (prb == NULL)
|
|
prb = BRUSHOBJ_pvGetRbrush(pbo);
|
|
if (prb == NULL || tdelta & 0x1f)
|
|
// If target delta is not modula of 32 (cache line alignment) or
|
|
// If we couldn't realize the brush, punt
|
|
// the call (it may have been a non 8x8
|
|
// brush or something, which we can't be
|
|
// bothered to handle, so let GDI do the
|
|
// drawing):
|
|
goto puntbackBitBlt;
|
|
if((rc = DrvpPatternFill(prclTrg, pco, prb, pptlBrush, tdelta, target, colorModeShift, rop4)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
} else {
|
|
if(rop4 == 0x5a5a) {
|
|
if((rc = DrvpSolidOp(prclTrg, pco, OPXOR, pbo->iSolidColor, tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
} else {
|
|
if((rc = DrvpSolidOp(prclTrg, pco, OPXOR, ~(pbo->iSolidColor), tdelta, target, colorModeShift)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
}
|
|
}
|
|
break;
|
|
case 0x0a0a: // AND dest with the inverted pattern
|
|
case 0xa0a0: // AND dest with the pattern
|
|
if(pbo->iSolidColor == 0xFFFFFFFF) { // Pattern
|
|
// Try and realize the pattern brush; by doing
|
|
// this call-back, GDI will eventually call us
|
|
// again through DrvRealizeBrush.
|
|
prb = pbo->pvRbrush;
|
|
if (prb == NULL)
|
|
prb = BRUSHOBJ_pvGetRbrush(pbo);
|
|
if (prb == NULL || tdelta & 0x1f)
|
|
// If target delta is not modula of 32 (cache line alignment) or
|
|
// If we couldn't realize the brush, punt
|
|
// the call (it may have been a non 8x8
|
|
// brush or something, which we can't be
|
|
// bothered to handle, so let GDI do the
|
|
// drawing):
|
|
goto puntbackBitBlt;
|
|
if((rc = DrvpPatternFill(prclTrg, pco, prb, pptlBrush, tdelta, target, colorModeShift, rop4)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
} else goto puntbackBitBlt; // Don't support solid brush as it's not so important
|
|
break;
|
|
case 0xb8b8: // OR (AND dest with source) with (AND pattern with inverted source)
|
|
if((Color = pbo->iSolidColor) == 0xFFFFFFFF)
|
|
goto puntbackBitBlt;
|
|
switch(colorModeShift) {
|
|
case 0: Color |= (Color << 8);
|
|
case 1: Color |= (Color << 16);
|
|
}
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __b8opentrytable, Color)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x6666: // XOR dest with the source (SRCINVERT)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __xorentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x8888: // AND dest with the source (SRCAND)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __andentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0xeeee: // OR dest with the source (SRCPAINT)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __orentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0xbbbb: // OR dest with the inverted source (MERGEPAINT)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __orcentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x4444: // AND source with inverted dest (SRCERASE)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __andcentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x1111: // NOR dest and source (NOTSRCERASE)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __norentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
case 0x3333: // COPY inverted source (NOTSRCCOPY)
|
|
if((rc = DrvpOpSrc(psoTrg, psoSrc, pco, prclTrg, pptlSrc, colorModeShift, __nsrcentrytable, 0)) == FALSE)
|
|
goto puntbackBitBlt;
|
|
break;
|
|
default:
|
|
goto puntbackBitBlt;
|
|
}
|
|
} else
|
|
goto puntbackBitBlt;
|
|
|
|
CLOCKEND((DRV_TRAP_BITBLT));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_BITBLT)
|
|
DISPDBG((0,"--- Exiting DrvBitBlt ---\n"));
|
|
if(breakexit & FL_DRV_BITBLT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
|
|
puntbackBitBlt:
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_BITBLT);
|
|
if(traseentry & dbgflg & FL_DRV_BITBLT)
|
|
DISPDBG((0,"###> Punting back to EngBitBlt ---\n"));
|
|
if(breakentry & FL_DRV_BITBLT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngBitBlt(
|
|
psoTrg,
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
pptlMask,
|
|
pbo,
|
|
pptlBrush,
|
|
rop4);
|
|
|
|
CLOCKEND((DRV_TRAP_BITBLT));
|
|
|
|
COUNTUP ((TRAP_BITBLT));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_BITBLT)
|
|
DISPDBG((0,"--- Exiting DrvBitBlt ---\n"));
|
|
if(breakexit & FL_DRV_BITBLT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
BOOL DrvTextOut(
|
|
SURFOBJ *pso,
|
|
STROBJ *pstro,
|
|
FONTOBJ *pfo,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclExtra,
|
|
RECTL *prclOpaque,
|
|
BRUSHOBJ *pboFore,
|
|
BRUSHOBJ *pboOpaque,
|
|
POINTL *pptlOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL Opaque, rc;
|
|
RECTL OpaqueRectl, BgRectl;
|
|
PBYTE pjScreenBase, pjTextScreenBase;
|
|
ULONG colorModeShift, procalign;
|
|
ULONG fore, back;
|
|
LONG cgp;
|
|
PGLYPHPOS prggp;
|
|
PGLYPHPOS pgp;
|
|
BOOL More;
|
|
GLYPHBITS *pgb;
|
|
LONG cx, i;
|
|
PBYTE pjDst;
|
|
ULONG djDst;
|
|
ULONG cjBits;
|
|
ULONG ib;
|
|
PBYTE pprocText;
|
|
PBYTE *textproc, *dcbztextproc, *transtextproc;
|
|
ULONG ijDstLimCB;
|
|
ULONG ijDstLastCB;
|
|
ULONG ijDstLastPrevCB;
|
|
ULONG clipx, clipy, stpos;
|
|
TEXTPARAM textparam;
|
|
#if (! FULLCACHE)
|
|
ULONG textThreshold;
|
|
#endif
|
|
|
|
//
|
|
// If the complexity of the clipping is not trival
|
|
// or not one of our favority bitmap formats, then let GDI
|
|
// process the request.
|
|
//
|
|
// DrvTextOut will only get called with solid color brushes and
|
|
// the mix mode being the simplest R2_COPYPEN. The driver must
|
|
// set a capabilities bit to get called with more complicated
|
|
// mix brushes.
|
|
//
|
|
// The foreground color is used for the text and extra rectangle
|
|
// if it specified. The background color is used for the opaque
|
|
// rectangle. If the foreground color is not a solid color brush
|
|
// or the opaque rectangle is specified and is not a solid color
|
|
// brush, then let GDI process the request.
|
|
//
|
|
|
|
textproc = dcbztextproc = transtextproc = NULL; // To remove warning messages. 3/20/95
|
|
cx = djDst = 0; // To remove warning messages. 3/20/95
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_TEXTOUT;
|
|
#if DBG
|
|
filldumplevel = 3;
|
|
#endif
|
|
if(traseentry & dbgflg & FL_DRV_TEXTOUT)
|
|
DISPDBG((0,"+++ Entering DrvTextOut +++\n"));
|
|
if(breakentry & FL_DRV_TEXTOUT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
ENTERCRITICAL((5));
|
|
CLOCKSTART((DRV_TRAP_TEXTOUT));
|
|
|
|
if(! myPDEV)
|
|
goto puntbackTextOut;
|
|
|
|
switch (pso->iBitmapFormat){
|
|
case BMF_8BPP:
|
|
colorModeShift = 0;
|
|
break;
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
break;
|
|
case BMF_32BPP:
|
|
colorModeShift = 2;
|
|
break;
|
|
default:
|
|
goto puntbackTextOut;
|
|
}
|
|
|
|
#if FULLCACHE
|
|
if(pfo->cxMax > 32 ||
|
|
((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) != SO_HORIZONTAL) ||
|
|
((textparam.delta = pso->lDelta) & 0x1f)) {
|
|
goto puntbackTextOut;
|
|
}
|
|
#else // FULLCACHE
|
|
if(pfo->cxMax > 32 ||
|
|
((pstro->flAccel & (SO_HORIZONTAL | SO_VERTICAL | SO_REVERSED)) != SO_HORIZONTAL) ||
|
|
((textparam.delta = pso->lDelta) & 0x03)) {
|
|
goto puntbackTextOut;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
pjScreenBase = pso->pvScan0;
|
|
BgRectl = pstro->rclBkGround;
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) {
|
|
clipx = 10000; // Large enough number not to cause clipping
|
|
clipy = 0;
|
|
} else if(pco->iDComplexity == DC_RECT && pstro->ulCharInc == 0) { // Support clipping only for PS text
|
|
if(pco->rclBounds.top == pstro->rclBkGround.top && pco->rclBounds.left == pstro->rclBkGround.left) {
|
|
// Support clipping for bottom and right edges only
|
|
if(BgRectl.bottom > pco->rclBounds.bottom) {
|
|
BgRectl.bottom = pco->rclBounds.bottom;
|
|
clipy = pstro->rclBkGround.bottom - BgRectl.bottom;
|
|
} else
|
|
clipy = 0;
|
|
if(BgRectl.right > pco->rclBounds.right)
|
|
BgRectl.right = clipx = pco->rclBounds.right;
|
|
else
|
|
clipx = pco->rclBounds.right;
|
|
} else {
|
|
goto puntbackTextOut;
|
|
}
|
|
} else {
|
|
goto puntbackTextOut;
|
|
}
|
|
|
|
if(prclOpaque == NULL) {
|
|
Opaque = FALSE;
|
|
#if (! FULLCACHE)
|
|
textThreshold = TransTextThreshold[colorModeShift];
|
|
#endif
|
|
} else {
|
|
if(pstro->flAccel == SO_LTOR) { // Simplest case -> we can treat as opaque text
|
|
Opaque = TRUE;
|
|
#if (! FULLCACHE)
|
|
textThreshold = TEXTTHRESHOLD;
|
|
#endif
|
|
//
|
|
// If the top of the opaque rectangle is less than the top of the
|
|
// background rectangle, then fill the region between the top of
|
|
// opaque rectangle and the top of the background rectangle and
|
|
// reduce the size of the opaque rectangle.
|
|
//
|
|
|
|
OpaqueRectl = *prclOpaque;
|
|
if(OpaqueRectl.top < BgRectl.top) {
|
|
OpaqueRectl.bottom = BgRectl.top;
|
|
DrvpSolidFill(&OpaqueRectl, pco, pboOpaque->iSolidColor, textparam.delta, pjScreenBase, colorModeShift);
|
|
OpaqueRectl.top = BgRectl.top;
|
|
OpaqueRectl.bottom = prclOpaque->bottom;
|
|
}
|
|
|
|
//
|
|
// If the bottom of the opaque rectangle is greater than the bottom
|
|
// of the background rectangle, then fill the region between the
|
|
// bottom of the background rectangle and the bottom of the opaque
|
|
// rectangle and reduce the size of the opaque rectangle.
|
|
//
|
|
|
|
if(OpaqueRectl.bottom > BgRectl.bottom) {
|
|
OpaqueRectl.top = BgRectl.bottom;
|
|
DrvpSolidFill(&OpaqueRectl, pco, pboOpaque->iSolidColor, textparam.delta, pjScreenBase, colorModeShift);
|
|
OpaqueRectl.top = BgRectl.top;
|
|
OpaqueRectl.bottom = BgRectl.bottom;
|
|
}
|
|
|
|
//
|
|
// If the left of the opaque rectangle is less than the left of
|
|
// the background rectangle, then fill the region between the
|
|
// left of the opaque rectangle and the left of the background
|
|
// rectangle.
|
|
//
|
|
|
|
if(OpaqueRectl.left < BgRectl.left) {
|
|
OpaqueRectl.right = BgRectl.left;
|
|
DrvpSolidFill(&OpaqueRectl, pco, pboOpaque->iSolidColor, textparam.delta, pjScreenBase, colorModeShift);
|
|
OpaqueRectl.right = prclOpaque->right;
|
|
}
|
|
|
|
//
|
|
// If the right of the opaque rectangle is greater than the right
|
|
// of the background rectangle, then fill the region between the
|
|
// right of the opaque rectangle and the right of the background
|
|
// rectangle.
|
|
//
|
|
|
|
if(OpaqueRectl.right > BgRectl.right) {
|
|
OpaqueRectl.left = BgRectl.right;
|
|
DrvpSolidFill(&OpaqueRectl, pco, pboOpaque->iSolidColor, textparam.delta, pjScreenBase, colorModeShift); }
|
|
} else {
|
|
Opaque = FALSE;
|
|
#if (! FULLCACHE)
|
|
textThreshold = TransTextThreshold[colorModeShift];
|
|
#endif
|
|
DrvpSolidFill(prclOpaque, pco, pboOpaque->iSolidColor, textparam.delta, pjScreenBase, colorModeShift);
|
|
}
|
|
}
|
|
|
|
textparam.MaxLineToFlush = textparam.lines = BgRectl.bottom - BgRectl.top;
|
|
textparam.dest = BgRectl.left << colorModeShift;
|
|
textparam.colortable = mpnibbleulDraw;
|
|
|
|
#if FULLCACHE
|
|
textparam.width = ((BgRectl.right - BgRectl.left) << colorModeShift);
|
|
pjTextScreenBase = pjScreenBase;
|
|
textparam.control = ((myPDEV->VRAMcacheflg) & (TFLUSHBIT | TTOUCHBIT));
|
|
#else // FULLCACHE
|
|
if((textparam.width = ((BgRectl.right - BgRectl.left) << colorModeShift)) >= textThreshold
|
|
&& (textparam.delta & 0x1f) == 0 && pjScreenBase == (PBYTE) ScreenBase) {
|
|
// Target is wide enough VRAM with 32 byte aligned delta
|
|
textparam.control = ((myPDEV->VRAMcacheflg) & (TFLUSHBIT | TTOUCHBIT));
|
|
pjTextScreenBase = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
textparam.control = 0;
|
|
pjTextScreenBase = pjScreenBase;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
if(Opaque) {
|
|
if(ForeGroundColor != pboFore->iSolidColor || BackGroundColor != pboOpaque->iSolidColor) {
|
|
ForeGroundColor = pboFore->iSolidColor;
|
|
fore = ForeGroundColor | (ForeGroundColor << 8);
|
|
fore |= (fore << 16);
|
|
BackGroundColor = pboOpaque->iSolidColor;
|
|
back = BackGroundColor | (BackGroundColor << 8);
|
|
back |= (back << 16);
|
|
for (i = 0; i < 16; i += 1) {
|
|
mpnibbleulDraw[i] = (fore & DrvpColorMask[i]) | (back & (~DrvpColorMask[i]));
|
|
}
|
|
}
|
|
textproc = __mpcxpprocText8;
|
|
dcbztextproc = __mpcxpprocText8DCBZ;
|
|
} else {
|
|
if(ForeGroundColor != pboFore->iSolidColor || BackGroundColor != 0) {
|
|
ForeGroundColor = pboFore->iSolidColor;
|
|
fore = ForeGroundColor | (ForeGroundColor << 8);
|
|
fore |= (fore << 16);
|
|
BackGroundColor = 0;
|
|
for (i = 0; i < 16; i += 1) {
|
|
mpnibbleulDraw[i] = (fore & DrvpColorMask[i]);
|
|
}
|
|
}
|
|
textparam.masktable = mpnibbleulMask8;
|
|
transtextproc = __mpcxpprocTransText8;
|
|
}
|
|
break;
|
|
case 1:
|
|
if(Opaque) {
|
|
if(ForeGroundColor != pboFore->iSolidColor || BackGroundColor != pboOpaque->iSolidColor) {
|
|
ForeGroundColor = pboFore->iSolidColor;
|
|
fore = ForeGroundColor | (ForeGroundColor << 16);
|
|
BackGroundColor = pboOpaque->iSolidColor;
|
|
back = BackGroundColor | (BackGroundColor << 16);
|
|
mpnibbleulDraw[0] = back;
|
|
mpnibbleulDraw[1] = (fore & 0xFFFF0000) | (back & (~0xFFFF0000));
|
|
mpnibbleulDraw[2] = (fore & 0x0000FFFF) | (back & (~0x0000FFFF));
|
|
mpnibbleulDraw[3] = fore;
|
|
}
|
|
textproc = __mpcxpprocText16;
|
|
dcbztextproc = __mpcxpprocText16DCBZ;
|
|
} else {
|
|
if(ForeGroundColor != pboFore->iSolidColor || BackGroundColor != 0) {
|
|
ForeGroundColor = pboFore->iSolidColor;
|
|
fore = ForeGroundColor | (ForeGroundColor << 16);
|
|
fore |= (fore << 16);
|
|
BackGroundColor = mpnibbleulDraw[0] = 0;
|
|
mpnibbleulDraw[1] = fore & 0xFFFF0000;
|
|
mpnibbleulDraw[2] = fore & 0x0000FFFF;
|
|
mpnibbleulDraw[3] = fore;
|
|
}
|
|
textparam.masktable = mpnibbleulMask16;
|
|
transtextproc = __mpcxpprocTransText16;
|
|
}
|
|
break;
|
|
case 2:
|
|
mpnibbleulDraw[1] = pboFore->iSolidColor;
|
|
if(Opaque) {
|
|
mpnibbleulDraw[0] = pboOpaque->iSolidColor;
|
|
textproc = __mpcxpprocText32;
|
|
dcbztextproc = __mpcxpprocText32DCBZ;
|
|
} else {
|
|
mpnibbleulDraw[0] = 0;
|
|
textparam.masktable = mpnibbleulMask32;
|
|
transtextproc = __mpcxpprocTransText32;
|
|
}
|
|
break;
|
|
}
|
|
|
|
textparam.targetline = pjTextScreenBase + (textparam.delta * BgRectl.top);
|
|
ijDstLimCB = ((ULONG)textparam.targetline + (BgRectl.right << colorModeShift)) & ~(31);
|
|
procalign = 2 - colorModeShift;
|
|
|
|
if (pstro->ulCharInc != 0) {
|
|
|
|
textparam.fontfetchentry = __fixedfontfetchentry[((pfo->cxMax + 7) >> 3)-1];
|
|
|
|
//
|
|
// The font is fixed pitch. Capture the glyph dimensions and
|
|
// compute the starting display address.
|
|
//
|
|
|
|
if (pstro->pgp == NULL) {
|
|
More = STROBJ_bEnum(pstro, &cgp, &prggp);
|
|
} else {
|
|
cgp = pstro->cGlyphs;
|
|
prggp = pstro->pgp;
|
|
More = FALSE;
|
|
}
|
|
|
|
pgb = prggp->pgdf->pgb;
|
|
cx = pgb->sizlBitmap.cx;
|
|
cjBits = ((cx + 7) >> 3);
|
|
djDst = (prggp->ptl.x + pgb->ptlOrigin.x) << colorModeShift;
|
|
textparam.ulCharInc = pstro->ulCharInc << colorModeShift;
|
|
|
|
//
|
|
// Output the glyphs.
|
|
//
|
|
|
|
while (1) {
|
|
if(cgp) {
|
|
((GLYPHRAST *)prggp)->cjBits = (USHORT) cjBits;
|
|
((GLYPHRAST *)prggp)->djDst = (USHORT) djDst;
|
|
for(pgp = prggp; cgp > 0; cgp--, pgp++) {
|
|
pgb = pgp->pgdf->pgb;
|
|
pjDst = textparam.targetline + djDst;
|
|
ib = ((ULONG)pjDst & 3) >> colorModeShift;
|
|
if(Opaque) {
|
|
#if FULLCACHE
|
|
#if USE_DCBZ
|
|
ijDstLastPrevCB = ((ULONG)(pjDst-1) & ~31);
|
|
ijDstLastCB = ((ULONG)(pjDst+(cx << colorModeShift)-1) & ~31);
|
|
if(ijDstLastPrevCB != ijDstLastCB && ijDstLastCB != ijDstLimCB) {
|
|
pprocText = dcbztextproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryDCBZCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
ijDstLastPrevCB += 32;
|
|
while(ijDstLastPrevCB != ijDstLastCB) {
|
|
ijDstLastPrevCB += 32;
|
|
if(ijDstLastPrevCB == ijDstLimCB)
|
|
break;
|
|
pprocText -= CBDCBZCODE;
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
#else // USE_DCBZ
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
#endif // USE_DCBZ
|
|
|
|
#else // FULLCACHE
|
|
#if USE_DCBZ
|
|
if(textparam.control & TTOUCHBIT) {
|
|
ijDstLastPrevCB = ((ULONG)(pjDst-1) & ~31);
|
|
ijDstLastCB = ((ULONG)(pjDst+(cx << colorModeShift)-1) & ~31);
|
|
if(ijDstLastPrevCB != ijDstLastCB && ijDstLastCB != ijDstLimCB) {
|
|
pprocText = dcbztextproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryDCBZCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
ijDstLastPrevCB += 32;
|
|
while(ijDstLastPrevCB != ijDstLastCB) {
|
|
ijDstLastPrevCB += 32;
|
|
if(ijDstLastPrevCB == ijDstLimCB)
|
|
break;
|
|
pprocText -= CBDCBZCODE;
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
#else // USE_DCBZ
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
#endif // USE_DCBZ
|
|
|
|
#endif // FULLCACHE
|
|
} else {
|
|
pprocText = transtextproc [((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryTransCalled [((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
((GLYPHRAST *)pgp)->pprocFirstText = pprocText;
|
|
((GLYPHRAST *)pgp)->pjBits = pgb->aj;
|
|
djDst += textparam.ulCharInc;
|
|
}
|
|
textparam.prggp = prggp;
|
|
textparam.plastgp = pgp-1;
|
|
if((! myPDEV->DBAT_Mbit) && textparam.MaxLineToFlush > myPDEV->MaxLineToFlushRectOp)
|
|
textparam.MaxLineToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
#if (DBG && DUMPTEXT)
|
|
DumpTextParam(&textparam);
|
|
#endif
|
|
FixedTextOut(&textparam);
|
|
}
|
|
if (More)
|
|
More = STROBJ_bEnum(pstro, &cgp, &prggp);
|
|
else
|
|
break;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// The font is not fixed pitch. Compute the x and y values for
|
|
// each glyph individually.
|
|
//
|
|
|
|
if(Opaque) {
|
|
textparam.fontfetchentry = __ps2fontfetchentry[((pfo->cxMax + 7) >> 3)-1];
|
|
do {
|
|
More = STROBJ_bEnum(pstro, &cgp, &prggp);
|
|
if(cgp) {
|
|
for(pgp = prggp; cgp > 0; cgp--, pgp++) {
|
|
pgb = pgp->pgdf->pgb;
|
|
cx = pgb->sizlBitmap.cx;
|
|
cjBits = ((cx + 7) >> 3);
|
|
if((stpos = pgp->ptl.x + pgb->ptlOrigin.x) >= clipx)
|
|
break;
|
|
if(stpos+cx >= clipx)
|
|
cx = clipx - stpos;
|
|
djDst = (pgp->ptl.x + pgb->ptlOrigin.x) << colorModeShift;
|
|
pjDst = textparam.targetline + djDst;
|
|
ib = ((ULONG)pjDst & 3) >> colorModeShift;
|
|
#if FULLCACHE
|
|
#if USE_DCBZ
|
|
ijDstLastPrevCB = ((ULONG)(pjDst-1) & ~31);
|
|
ijDstLastCB = ((ULONG)(pjDst+(cx << colorModeShift)-1) & ~31);
|
|
if(ijDstLastPrevCB != ijDstLastCB && ijDstLastCB != ijDstLimCB) {
|
|
pprocText = dcbztextproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryDCBZCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
ijDstLastPrevCB += 32;
|
|
while(ijDstLastPrevCB != ijDstLastCB) {
|
|
ijDstLastPrevCB += 32;
|
|
if(ijDstLastPrevCB == ijDstLimCB)
|
|
break;
|
|
pprocText -= CBDCBZCODE;
|
|
#if INVESTIGATE
|
|
DISPDBG((3,"Additional DCBZ required: %x\n", pprocText));
|
|
#endif
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
#else // USE_DCBZ
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
#endif // USE_DCBZ
|
|
|
|
#else // FULLCACHE
|
|
#if USE_DCBZ
|
|
if(textparam.control & TTOUCHBIT) {
|
|
ijDstLastPrevCB = ((ULONG)(pjDst-1) & ~31);
|
|
ijDstLastCB = ((ULONG)(pjDst+(cx << colorModeShift)-1) & ~31);
|
|
|
|
if(ijDstLastPrevCB != ijDstLastCB && ijDstLastCB != ijDstLimCB) {
|
|
pprocText = dcbztextproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryDCBZCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
ijDstLastPrevCB += 32;
|
|
while(ijDstLastPrevCB != ijDstLastCB) {
|
|
ijDstLastPrevCB += 32;
|
|
if(ijDstLastPrevCB == ijDstLimCB)
|
|
break;
|
|
pprocText -= CBDCBZCODE;
|
|
#if INVESTIGATE
|
|
DISPDBG((3,"Additional DCBZ required: %x\n", pprocText));
|
|
#endif
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
} else {
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
}
|
|
#else // USE_DCBZ
|
|
pprocText = textproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
#endif // USE_DCBZ
|
|
|
|
#endif // FULLCACHE
|
|
((GLYPHRAST *)pgp)->djDst = (USHORT) djDst;
|
|
((GLYPHRAST *)pgp)->cjBits = (USHORT) cjBits;
|
|
((GLYPHRAST *)pgp)->pprocFirstText = pprocText;
|
|
((GLYPHRAST *)pgp)->pjBits = pgb->aj;
|
|
}
|
|
textparam.prggp = prggp;
|
|
textparam.plastgp = pgp-1;
|
|
if((! myPDEV->DBAT_Mbit) && textparam.MaxLineToFlush > myPDEV->MaxLineToFlushRectOp)
|
|
textparam.MaxLineToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
#if (DBG && DUMPTEXT)
|
|
DumpTextParam(&textparam);
|
|
#endif
|
|
PSTextOut2(&textparam);
|
|
}
|
|
} while(More);
|
|
} else {
|
|
textparam.fontfetchentry = __psfontfetchentry[((pfo->cxMax + 7) >> 3)-1];
|
|
do {
|
|
More = STROBJ_bEnum(pstro, &cgp, &prggp);
|
|
if(cgp) {
|
|
for(pgp = prggp; cgp > 0; cgp--, pgp++) {
|
|
pgb = pgp->pgdf->pgb;
|
|
cx = pgb->sizlBitmap.cx;
|
|
cjBits = ((cx + 7) >> 3);
|
|
if((stpos = pgp->ptl.x + pgb->ptlOrigin.x) >= clipx)
|
|
break;
|
|
if(stpos+cx >= clipx)
|
|
cx = clipx - stpos;
|
|
djDst = (pgp->ptl.x + pgb->ptlOrigin.x) << colorModeShift;
|
|
pjDst = textparam.targetline + djDst;
|
|
ib = ((ULONG)pjDst & 3) >> colorModeShift;
|
|
pprocText = transtextproc[((cx-1) << procalign) + ib];
|
|
#if INVESTIGATE
|
|
TextSubEntryTransCalled[((cx-1) << procalign) + ib] += 1;
|
|
#endif
|
|
((GLYPHRAST *)pgp)->djDst = (USHORT) djDst;
|
|
((GLYPHRAST *)pgp)->cjBits = (USHORT) cjBits;
|
|
((GLYPHRAST *)pgp)->startline = (USHORT) (pstro->rclBkGround.bottom - (pgp->ptl.y + pgb->ptlOrigin.y) - clipy);
|
|
/* If the above calculation results in overflow (entire character box is outside of clipping region),
|
|
startline would be very large number and therefore, endline would be very large number in the following calculation.
|
|
And no portion of the characters will be drawn because endline is larger than total lines to draw, which is correct behavior.
|
|
*/
|
|
if(((GLYPHRAST *)pgp)->startline > pgb->sizlBitmap.cy)
|
|
((GLYPHRAST *)pgp)->endline = (USHORT) (((GLYPHRAST *)pgp)->startline - pgb->sizlBitmap.cy);
|
|
else
|
|
((GLYPHRAST *)pgp)->endline = 0;
|
|
((GLYPHRAST *)pgp)->pprocFirstText = pprocText;
|
|
((GLYPHRAST *)pgp)->pjBits = pgb->aj;
|
|
}
|
|
if(textparam.width < djDst + (cx << colorModeShift) - textparam.dest)
|
|
textparam.width = djDst + (cx << colorModeShift) - textparam.dest;
|
|
textparam.prggp = prggp;
|
|
textparam.plastgp = pgp-1;
|
|
#if (DBG && DUMPTEXT)
|
|
DumpTextParam(&textparam);
|
|
#endif
|
|
PSTextOut(&textparam);
|
|
}
|
|
} while(More);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Fill the extra rectangles if specified.
|
|
//
|
|
|
|
if (prclExtra != (PRECTL)NULL) {
|
|
while (prclExtra->left != prclExtra->right) {
|
|
DrvpSolidFill(prclExtra, pco, pboFore->iSolidColor, textparam.delta, pjScreenBase, colorModeShift);
|
|
prclExtra += 1;
|
|
}
|
|
}
|
|
|
|
CLOCKEND((DRV_TRAP_TEXTOUT));
|
|
EXITCRITICAL((5));
|
|
|
|
#if INVESTIGATE
|
|
#if DBG
|
|
filldumplevel = 4;
|
|
#endif
|
|
if(traseexit & dbgflg & FL_DRV_TEXTOUT)
|
|
DISPDBG((0,"--- Exiting DrvTextOut ---\n"));
|
|
if(breakexit & FL_DRV_TEXTOUT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(TRUE);
|
|
|
|
puntbackTextOut:
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_TEXTOUT);
|
|
if(traseentry & dbgflg & FL_DRV_TEXTOUT)
|
|
DISPDBG((0,"###> Punting back to EngTextOut ---\n"));
|
|
if(breakentry & FL_DRV_TEXTOUT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngTextOut(pso,
|
|
pstro,
|
|
pfo,
|
|
pco,
|
|
prclExtra,
|
|
prclOpaque,
|
|
pboFore,
|
|
pboOpaque,
|
|
pptlOrg,
|
|
mix);
|
|
|
|
CLOCKEND((DRV_TRAP_TEXTOUT));
|
|
EXITCRITICAL((5));
|
|
|
|
COUNTUP ((TRAP_TEXTOUT));
|
|
|
|
#if INVESTIGATE
|
|
#if DBG
|
|
filldumplevel = 4;
|
|
#endif
|
|
if(traseexit & dbgflg & FL_DRV_TEXTOUT)
|
|
DISPDBG((0,"--- Exiting DrvTextOut ---\n"));
|
|
if(breakexit & FL_DRV_TEXTOUT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
BOOL DrvCopyBits(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclDest,
|
|
POINTL *pptlSrc)
|
|
{
|
|
BOOL rc;
|
|
LONG tline, tpos, colorModeShift;
|
|
PBYTE cachedtarget, target, cachedsource, source;
|
|
RECTL BltRectl;
|
|
BOOL MoreClipRects;
|
|
ULONG ClipRegions, iDirection;
|
|
COPYPARAM copyparam;
|
|
ULONG widththreshold;
|
|
LONG SrcBytes;
|
|
VOID (*ConvFunc)(COPYPARAM * copyparam, PULONG palette);
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_COPYBIT;
|
|
if(traseentry & dbgflg & FL_DRV_COPYBIT)
|
|
DISPDBG((0,"+++ Entering DrvCopyBits +++\n"));
|
|
if(breakentry & FL_DRV_COPYBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_COPYBITS));
|
|
|
|
if(! myPDEV)
|
|
goto puntbackCopyBits;
|
|
|
|
switch(psoDest->iBitmapFormat) {
|
|
case BMF_8BPP:
|
|
colorModeShift = 0;
|
|
break;
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
break;
|
|
case BMF_32BPP:
|
|
colorModeShift = 2;
|
|
break;
|
|
default:
|
|
goto puntbackCopyBits;
|
|
}
|
|
|
|
if(((copyparam.tdelta = psoDest->lDelta) & 0x03) || ((copyparam.sdelta = psoSrc->lDelta) & 0x03))
|
|
goto puntbackCopyBits;
|
|
|
|
#if FULLCACHE
|
|
cachedtarget = target = psoDest->pvScan0;
|
|
copyparam.control = 0;
|
|
#else // FULLCACHE
|
|
if((target = psoDest->pvScan0) == (PBYTE) ScreenBase) { // Target is VRAM
|
|
copyparam.control = ((myPDEV->VRAMcacheflg) & (TFLUSHBIT | TTOUCHBIT));
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
copyparam.control = 0;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
#if FULLCACHE
|
|
cachedsource = source = psoSrc->pvScan0;
|
|
widththreshold = COPYBITTHRESHOLD;
|
|
#else // FULLCACHE
|
|
if((source = psoSrc->pvScan0) == (PBYTE) ScreenBase) { // Source is VRAM
|
|
copyparam.control |= ((myPDEV->VRAMcacheflg) & SFLUSHBIT);
|
|
cachedsource = (PBYTE)myPDEV->pjCachedScreen;
|
|
widththreshold = COPYBITTHRESHOLDVRAM;
|
|
} else {
|
|
cachedsource = source;
|
|
widththreshold = COPYBITTHRESHOLDDRAM;
|
|
}
|
|
copyparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
copyparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
#endif // FULLCACHE
|
|
|
|
if(psoSrc->iBitmapFormat == psoDest->iBitmapFormat && ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))) {
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
tline = prclDest->top;
|
|
tpos = prclDest->left;
|
|
copyparam.lines = prclDest->bottom - tline;
|
|
if((copyparam.width = (prclDest->right - tpos) << colorModeShift) >= widththreshold) {
|
|
copyparam.target = cachedtarget + copyparam.tdelta*tline + (tpos << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y) + ((pptlSrc->x) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
ENTERCRITICAL((2));
|
|
RectCopy(©param);
|
|
EXITCRITICAL((2));
|
|
} else {
|
|
copyparam.target = target + copyparam.tdelta*tline + (tpos << colorModeShift);
|
|
copyparam.source = source + copyparam.sdelta*(pptlSrc->y) + ((pptlSrc->x) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
RectCopyS(©param);
|
|
}
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do the BLT if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &pco->rclBounds, &BltRectl)) {
|
|
copyparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((copyparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= widththreshold) {
|
|
copyparam.target = cachedtarget + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
ENTERCRITICAL((2));
|
|
RectCopy(©param);
|
|
EXITCRITICAL((2));
|
|
} else {
|
|
copyparam.target = target + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = source + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
RectCopyS(©param);
|
|
}
|
|
} else {
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
if(source == target) {
|
|
if (pptlSrc->y <= prclDest->top) {
|
|
iDirection = CD_UPWARDS;
|
|
} else {
|
|
iDirection = 0;
|
|
}
|
|
if (pptlSrc->x <= prclDest->left) {
|
|
iDirection |= CD_LEFTWARDS;
|
|
}
|
|
} else {
|
|
iDirection = CD_ANY;
|
|
}
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
copyparam.lines = BltRectl.bottom - BltRectl.top;
|
|
if((copyparam.width = (BltRectl.right - BltRectl.left) << colorModeShift) >= widththreshold) {
|
|
copyparam.target = cachedtarget + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
ENTERCRITICAL((2));
|
|
RectCopy(©param);
|
|
EXITCRITICAL((2));
|
|
} else {
|
|
copyparam.target = target + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = source + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) << colorModeShift);
|
|
#if (DBG && DUMPCOPY)
|
|
DumpCopyParam(©param);
|
|
#endif
|
|
RectCopyS(©param);
|
|
}
|
|
} else {
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
goto puntbackCopyBits;
|
|
} else if(pxlo != NULL && pxlo->iSrcType == 0 && copyparam.control == (TFLUSHBIT | TTOUCHBIT) && (! myPDEV->AvoidConversion)) {
|
|
if(pxlo->cEntries == 0) {
|
|
// BPP format conversion with no color translation --> we support only for 24->15, 24->16, 24->32, 15->16 and 15->32
|
|
if(psoSrc->iBitmapFormat == BMF_24BPP) { // Copying 24BPP to 15, 16 or 32 BPP
|
|
SrcBytes = 3;
|
|
switch(myPDEV->flGreen) {
|
|
case 0x3e0: // 15 bit
|
|
ConvFunc = RectCopy24to15;
|
|
break;
|
|
case 0x7e0: // 16 bit
|
|
ConvFunc = RectCopy24to16;
|
|
break;
|
|
case 0xff00: // 32 bit
|
|
ConvFunc = RectCopy24to32;
|
|
break;
|
|
default:
|
|
goto puntbackCopyBits;
|
|
}
|
|
} else if(psoSrc->iBitmapFormat == BMF_16BPP) { // Copying 16BPP (assumed 5-5-5) to 5-6-5 16BPP or 32 BPP
|
|
SrcBytes = 2;
|
|
switch(myPDEV->flGreen) {
|
|
case 0x7e0: // 16 bit
|
|
ConvFunc = RectCopy15to16;
|
|
break;
|
|
case 0xff00: // 32 bit
|
|
#if BUG_5737_WORKAROUND
|
|
if(ModeChanged)
|
|
goto puntbackCopyBits;
|
|
#endif
|
|
ConvFunc = RectCopy15to32;
|
|
break;
|
|
default:
|
|
goto puntbackCopyBits;
|
|
}
|
|
} else
|
|
goto puntbackCopyBits;
|
|
} else if(pxlo->cEntries == 256 && (pxlo->flXlate & XO_TABLE) && psoSrc->iBitmapFormat == BMF_8BPP && pxlo->pulXlate != NULL) {
|
|
SrcBytes = 1;
|
|
switch(colorModeShift) {
|
|
case 0:
|
|
ConvFunc = RectCopy8to8;
|
|
break;
|
|
case 1:
|
|
ConvFunc = RectCopy8to16;
|
|
break;
|
|
case 2:
|
|
ConvFunc = RectCopy8to32;
|
|
break;
|
|
default:
|
|
goto puntbackCopyBits;
|
|
}
|
|
} else
|
|
goto puntbackCopyBits;
|
|
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
tline = prclDest->top;
|
|
tpos = prclDest->left;
|
|
copyparam.lines = prclDest->bottom - tline;
|
|
copyparam.width = (prclDest->right - tpos) << colorModeShift;
|
|
copyparam.target = cachedtarget + copyparam.tdelta*tline + (tpos << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y) + ((pptlSrc->x) * SrcBytes);
|
|
(*ConvFunc)(©param, pxlo->pulXlate);
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do it if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &pco->rclBounds, &BltRectl)) {
|
|
copyparam.lines = BltRectl.bottom - BltRectl.top;
|
|
copyparam.width = (BltRectl.right - BltRectl.left) << colorModeShift;
|
|
copyparam.target = cachedtarget + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) * SrcBytes);
|
|
(*ConvFunc)(©param, pxlo->pulXlate);
|
|
} else {
|
|
}
|
|
} else if(pco->iDComplexity == DC_COMPLEX) {
|
|
iDirection = CD_ANY;
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iDirection, BB_RECT_LIMIT);
|
|
do {
|
|
//
|
|
// Get list of clip rectangles.
|
|
//
|
|
MoreClipRects = CLIPOBJ_bEnum(pco, sizeof(ClipEnum), (PVOID)&ClipEnum);
|
|
|
|
for (ClipRegions=0; ClipRegions<ClipEnum.c; ClipRegions++) {
|
|
//
|
|
// If the rectangles intersect calculate the offset to the
|
|
// source start location to match and do the BitBlt.
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &ClipEnum.arcl[ClipRegions], &BltRectl)) {
|
|
copyparam.lines = BltRectl.bottom - BltRectl.top;
|
|
copyparam.width = (BltRectl.right - BltRectl.left) << colorModeShift;
|
|
copyparam.target = cachedtarget + copyparam.tdelta*BltRectl.top + (BltRectl.left << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(pptlSrc->y + BltRectl.top - prclDest->top) + ((pptlSrc->x + BltRectl.left - prclDest->left) * SrcBytes);
|
|
(*ConvFunc)(©param, pxlo->pulXlate);
|
|
} else {
|
|
}
|
|
}
|
|
} while (MoreClipRects);
|
|
} else
|
|
goto puntbackCopyBits;
|
|
} else {
|
|
goto puntbackCopyBits;
|
|
}
|
|
|
|
CLOCKEND((DRV_TRAP_COPYBITS));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_COPYBIT)
|
|
DISPDBG((0,"--- Exiting DrvCopyBits ---\n"));
|
|
if(breakexit & FL_DRV_COPYBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(TRUE);
|
|
|
|
puntbackCopyBits:
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_COPYBIT);
|
|
if(traseentry & dbgflg & FL_DRV_COPYBIT)
|
|
DISPDBG((0,"###> Punting back to EngCopyBits ---\n"));
|
|
if(breakentry & FL_DRV_COPYBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngCopyBits(
|
|
psoDest,
|
|
psoSrc,
|
|
pco,
|
|
pxlo,
|
|
prclDest,
|
|
pptlSrc);
|
|
|
|
CLOCKEND((DRV_TRAP_COPYBITS));
|
|
|
|
COUNTUP ((TRAP_COPYBITS));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_COPYBIT)
|
|
DISPDBG((0,"--- Exiting DrvCopyBits ---\n"));
|
|
if(breakexit & FL_DRV_COPYBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
BOOL DrvStretchBlt(
|
|
SURFOBJ *psoDest,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
COLORADJUSTMENT *pca,
|
|
POINTL *pptlHTOrg,
|
|
RECTL *prclDest,
|
|
RECTL *prclSrc,
|
|
POINTL *pptlMask,
|
|
ULONG iMode)
|
|
{
|
|
BOOL rc;
|
|
LONG tline, tpos, colorModeShift;
|
|
PBYTE cachedtarget, target, cachedsource, source;
|
|
RECTL BltRectl;
|
|
COPYPARAM copyparam;
|
|
VOID (*stretchFunc)(COPYPARAM * copyparam);
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_STRTBIT;
|
|
if(traseentry & dbgflg & FL_DRV_STRTBIT)
|
|
DISPDBG((0,"+++ Entering DrvStretchBlt +++\n"));
|
|
if(breakentry & FL_DRV_STRTBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_STRETCHBLT));
|
|
|
|
if(! myPDEV)
|
|
goto puntbackStretchBlt;
|
|
|
|
switch(psoDest->iBitmapFormat) {
|
|
case BMF_16BPP:
|
|
colorModeShift = 1;
|
|
stretchFunc = Stretch16;
|
|
break;
|
|
case BMF_32BPP:
|
|
colorModeShift = 2;
|
|
stretchFunc = Stretch32;
|
|
break;
|
|
default:
|
|
goto puntbackStretchBlt;
|
|
}
|
|
|
|
tline = prclDest->top;
|
|
tpos = prclDest->left;
|
|
if((copyparam.lines = prclDest->bottom - tline) != (ULONG)(prclSrc->bottom - prclSrc->top)*2 ||
|
|
(copyparam.width = prclDest->right - tpos) != (ULONG)(prclSrc->right - prclSrc->left)*2 ||
|
|
psoSrc->iBitmapFormat != psoDest->iBitmapFormat ||
|
|
((pxlo != NULL) && (!(pxlo->flXlate & XO_TRIVIAL))) ||
|
|
psoMask != NULL || pca != NULL || iMode > COLORONCOLOR) {
|
|
goto puntbackStretchBlt; // We support only 200% trivial case
|
|
}
|
|
|
|
#if FULLCACHE
|
|
cachedtarget = target = psoDest->pvScan0;
|
|
copyparam.control = 0;
|
|
#else // FULLCACHE
|
|
if((target = psoDest->pvScan0) == (PBYTE) ScreenBase) { // Target is VRAM
|
|
copyparam.control = ((myPDEV->VRAMcacheflg) & (TFLUSHBIT | TTOUCHBIT));
|
|
cachedtarget = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
copyparam.control = 0;
|
|
cachedtarget = target;
|
|
}
|
|
#endif // FULLCACHE
|
|
|
|
#if FULLCACHE
|
|
cachedsource = source = psoSrc->pvScan0;
|
|
#else // FULLCACHE
|
|
if((source = psoSrc->pvScan0) == (PBYTE) ScreenBase) { // Source is VRAM
|
|
copyparam.control |= ((myPDEV->VRAMcacheflg) & SFLUSHBIT);
|
|
cachedsource = (PBYTE)myPDEV->pjCachedScreen;
|
|
} else {
|
|
cachedsource = source;
|
|
}
|
|
copyparam.MaxEntryToFlush = myPDEV->MaxEntryToFlushRectOp;
|
|
copyparam.MaxLinesToFlush = myPDEV->MaxLineToFlushRectOp;
|
|
#endif // FULLCACHE
|
|
|
|
if(copyparam.control == (TFLUSHBIT | TTOUCHBIT) && (! myPDEV->AvoidConversion)) {
|
|
copyparam.tdelta = psoDest->lDelta;
|
|
copyparam.sdelta = psoSrc->lDelta;
|
|
if(pco == NULL || pco->iDComplexity == DC_TRIVIAL) { // Trivial case
|
|
copyparam.width <<= colorModeShift;
|
|
copyparam.target = cachedtarget + copyparam.tdelta*tline + (tpos << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(prclSrc->top) + ((prclSrc->left) << colorModeShift);
|
|
(*stretchFunc)(©param);
|
|
} else if(pco->iDComplexity == DC_RECT) {
|
|
//
|
|
// only do it if there is an intersection
|
|
//
|
|
if (DrvpIntersectRect(prclDest, &pco->rclBounds, &BltRectl)) {
|
|
if(BltRectl.top == tline && BltRectl.left == tpos) { // Top left position has to be in the clipping area
|
|
copyparam.lines = BltRectl.bottom - tline;
|
|
copyparam.width = (BltRectl.right - tpos) << colorModeShift;
|
|
copyparam.target = cachedtarget + copyparam.tdelta*tline + (tpos << colorModeShift);
|
|
copyparam.source = cachedsource + copyparam.sdelta*(prclSrc->top) + ((prclSrc->left) << colorModeShift);
|
|
(*stretchFunc)(©param);
|
|
} else {
|
|
goto puntbackStretchBlt;
|
|
}
|
|
} else {
|
|
}
|
|
} else {
|
|
goto puntbackStretchBlt;
|
|
}
|
|
} else {
|
|
goto puntbackStretchBlt;
|
|
}
|
|
|
|
CLOCKEND((DRV_TRAP_STRETCHBLT));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_STRTBIT)
|
|
DISPDBG((0,"--- Exiting DrvStretchBlt ---\n"));
|
|
if(breakexit & FL_DRV_STRTBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(TRUE);
|
|
|
|
puntbackStretchBlt:
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_STRTBIT);
|
|
if(traseentry & dbgflg & FL_DRV_STRTBIT)
|
|
DISPDBG((0,"###> Punting back to EngStretchBlt ---\n"));
|
|
if(breakentry & FL_DRV_STRTBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngStretchBlt(
|
|
psoDest,
|
|
psoSrc,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
pca,
|
|
pptlHTOrg,
|
|
prclDest,
|
|
prclSrc,
|
|
pptlMask,
|
|
iMode);
|
|
|
|
CLOCKEND((DRV_TRAP_STRETCHBLT));
|
|
|
|
COUNTUP ((TRAP_STRETCHBLT));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_STRTBIT)
|
|
DISPDBG((0,"--- Exiting DrvStretchBlt ---\n"));
|
|
if(breakexit & FL_DRV_STRTBIT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
#if PAINT_NEW_METHOD
|
|
|
|
BOOL DrvPaint(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL rc;
|
|
ROP4 rop4;
|
|
ULONG colorModeShift;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_PAINT;
|
|
if(traseentry & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"+++ Entering DrvPaint +++\n"));
|
|
if(breakentry & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_PAINT));
|
|
|
|
if(myPDEV && ((pco->rclBounds.right - pco->rclBounds.left) << myPDEV->ColorModeShift) > PAINT_THRESHOLD) {
|
|
|
|
rop4 = ((MIX) gaMix[mix >> 8] << 8) | gaMix[mix & 0xf];
|
|
|
|
if((((rop4 == 0xf0f0) && (pbo->iSolidColor != 0xFFFFFFFF)) || rop4 == 0x5555) &&
|
|
(pco && pco->iDComplexity == DC_COMPLEX) &&
|
|
((myPDEV->VRAMcacheflg) && (pso->pvScan0 == (PBYTE) ScreenBase))) {
|
|
|
|
// DrvPaint Hook Conditions (to DrvpPaintFill or DrvpPaintXOR)
|
|
// 1. Solid fill or XOR target
|
|
// 2. DC_COMPLEX clip
|
|
// 3. Target is VRAM and cacheable
|
|
|
|
if(rop4 == 0xf0f0) {
|
|
rc = DrvpPaintFill(pco, pbo->iSolidColor, pso);
|
|
} else {
|
|
rc = DrvpPaintXOR(pco, pso);
|
|
}
|
|
|
|
} else {
|
|
|
|
// Use BitBlt for other (mostly single clipping region) cases.
|
|
|
|
rc = DrvBitBlt(pso, NULL, NULL, pco, NULL, &pco->rclBounds, NULL,
|
|
NULL, pbo, pptlBrushOrg, rop4);
|
|
|
|
}
|
|
|
|
CLOCKEND((DRV_TRAP_PAINT));
|
|
} else {
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_PAINT);
|
|
if(traseentry & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"###> Punting back to EngPaint ---\n"));
|
|
if(breakentry & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngPaint(
|
|
pso,
|
|
pco,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
mix);
|
|
|
|
CLOCKEND((DRV_TRAP_PAINT));
|
|
|
|
COUNTUP ((TRAP_PAINT));
|
|
|
|
}
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"--- Exiting DrvPaint ---\n"));
|
|
if(breakexit & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
#else // PAINT_NEW_METHOD
|
|
|
|
BOOL DrvPaint(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix)
|
|
{
|
|
BOOL rc;
|
|
ROP4 rop4;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv |= FL_DRV_PAINT;
|
|
if(traseentry & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"+++ Entering DrvPaint +++\n"));
|
|
if(breakentry & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_PAINT));
|
|
|
|
if(myPDEV && ((pco->rclBounds.right - pco->rclBounds.left) << myPDEV->ColorModeShift) > PAINT_THRESHOLD) {
|
|
rop4 = ((MIX) gaMix[mix >> 8] << 8) | gaMix[mix & 0xf];
|
|
|
|
rc = DrvBitBlt(pso, NULL, NULL, pco, NULL, &pco->rclBounds, NULL,
|
|
NULL, pbo, pptlBrushOrg, rop4);
|
|
|
|
CLOCKEND((DRV_TRAP_PAINT));
|
|
} else {
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_PAINT);
|
|
if(traseentry & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"###> Punting back to EngPaint ---\n"));
|
|
if(breakentry & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
rc = EngPaint(
|
|
pso,
|
|
pco,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
mix);
|
|
|
|
CLOCKEND((DRV_TRAP_PAINT));
|
|
|
|
COUNTUP ((TRAP_PAINT));
|
|
}
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_PAINT)
|
|
DISPDBG((0,"--- Exiting DrvPaint ---\n"));
|
|
if(breakexit & FL_DRV_PAINT)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
#endif // PAINT_NEW_METHOD
|
|
|
|
#if INVESTIGATE
|
|
|
|
BOOL DrvStrokePath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
LINEATTRS *plineattrs,
|
|
MIX mix)
|
|
{
|
|
BOOL rc;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_STRKPATH);
|
|
if(traseentry & dbgflg & FL_DRV_STRKPATH)
|
|
DISPDBG((0,"+++ Entering DrvStrokePath +++\n"));
|
|
if(breakentry & FL_DRV_STRKPATH)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_STROKEPATH));
|
|
|
|
rc = EngStrokePath(
|
|
pso,
|
|
ppo,
|
|
pco,
|
|
pxo,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
plineattrs,
|
|
mix);
|
|
|
|
CLOCKEND((DRV_TRAP_STROKEPATH));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_STRKPATH)
|
|
DISPDBG((0,"--- Exiting DrvStrokePath ---\n"));
|
|
if(breakexit & FL_DRV_STRKPATH)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
BOOL DrvFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mix,
|
|
FLONG flOptions)
|
|
{
|
|
BOOL rc;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_FILLPATH);
|
|
if(traseentry & dbgflg & FL_DRV_FILLPATH)
|
|
DISPDBG((0,"+++ Entering DrvFillPath +++\n"));
|
|
if(breakentry & FL_DRV_FILLPATH)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_FILLPATH));
|
|
|
|
rc = EngFillPath(
|
|
pso,
|
|
ppo,
|
|
pco,
|
|
pbo,
|
|
pptlBrushOrg,
|
|
mix,
|
|
flOptions);
|
|
|
|
CLOCKEND((DRV_TRAP_FILLPATH));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_FILLPATH)
|
|
DISPDBG((0,"--- Exiting DrvFillPath ---\n"));
|
|
if(breakexit & FL_DRV_FILLPATH)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
BOOL DrvStrokeAndFillPath(
|
|
SURFOBJ *pso,
|
|
PATHOBJ *ppo,
|
|
CLIPOBJ *pco,
|
|
XFORMOBJ *pxo,
|
|
BRUSHOBJ *pboStroke,
|
|
LINEATTRS *plineattrs,
|
|
BRUSHOBJ *pboFill,
|
|
POINTL *pptlBrushOrg,
|
|
MIX mixFill,
|
|
FLONG flOptions)
|
|
{
|
|
BOOL rc;
|
|
|
|
#if INVESTIGATE
|
|
donebydrv &= (~FL_DRV_STRKNFILL);
|
|
if(traseentry & dbgflg & FL_DRV_STRKNFILL)
|
|
DISPDBG((0,"+++ Entering DrvStrokeAndFillPath +++\n"));
|
|
if(breakentry & FL_DRV_STRKNFILL)
|
|
CountBreak();
|
|
#endif
|
|
|
|
CLOCKSTART((DRV_TRAP_STROKENFIL));
|
|
|
|
rc = EngStrokeAndFillPath(
|
|
pso,
|
|
ppo,
|
|
pco,
|
|
pxo,
|
|
pboStroke,
|
|
plineattrs,
|
|
pboFill,
|
|
pptlBrushOrg,
|
|
mixFill,
|
|
flOptions);
|
|
|
|
CLOCKEND((DRV_TRAP_STROKENFIL));
|
|
|
|
#if INVESTIGATE
|
|
if(traseexit & dbgflg & FL_DRV_STRKNFILL)
|
|
DISPDBG((0,"--- Exiting DrvStrokeAndFillPath ---\n"));
|
|
if(breakexit & FL_DRV_STRKNFILL)
|
|
CountBreak();
|
|
#endif
|
|
|
|
return(rc);
|
|
}
|
|
|
|
#endif
|
|
|