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.
2502 lines
80 KiB
2502 lines
80 KiB
/*
|
|
*
|
|
* Copyright (C) 1993, 1995 by
|
|
* DIGITAL EQUIPMENT CORPORATION, Maynard, MA.
|
|
*
|
|
* This software is furnished under a license and may be used and copied
|
|
* only in accordance with the terms of such license and with the inclusion
|
|
* of the above copyright notice. This software or any other copies there-
|
|
* of may not be provided or otherwise made available to any other person.
|
|
* No title to and ownership of the software is hereby transferred.
|
|
*
|
|
* The information in this software is subject to change without notice
|
|
* and should not be construed as a commitment by DIGITAL EQUIPMENT COR-
|
|
* PORATION.
|
|
*
|
|
* DIGITAL assumes no responsibility for the use or reliability of its
|
|
* software on equipment which is not supplied by DIGITAL.
|
|
*
|
|
*******************************************************************************
|
|
* Module: bitblt.c
|
|
*
|
|
* Abstract: Contains GDI entry points for bit blit functionality.
|
|
*
|
|
* HISTORY
|
|
*
|
|
* 01-Nov-1993 Bob Seitsinger
|
|
* Original version.
|
|
*
|
|
* 01-Nov-1993 Bob Seitsinger
|
|
* Add code to 'set simple mode', if punting. Also, got rid of
|
|
* any QV-specific (or rather non-TGA) stuff.
|
|
*
|
|
* 02-Nov-1993 Bob Seitsinger
|
|
* Add 'solid fill' code. Use Transparent Fill mode. Initially use
|
|
* this routine for BLACKNESS, DSTINVERT and WHITENESS rops.
|
|
*
|
|
* 03-Nov-1993 Bob Seitsinger
|
|
* Add code to determine if incoming surface object(s) points to the
|
|
* 'virtualized' frame buffer. If so, call scr->scr, scr->mem or
|
|
* mem->scr routines appropriately.
|
|
*
|
|
* 03-Nov-1993 Bob Seitsinger
|
|
* Add code to get around current cursor problem. This can be
|
|
* found by searching for #ifndef HARDWARE_CURSOR.
|
|
*
|
|
* 03-Nov-1993 Bob Seitsinger
|
|
* Remove #ifndef HARDWARE_CURSOR code.
|
|
*
|
|
* 05-Nov-1993 Bob Seitsinger
|
|
* Change all but entry and exit messages to the Drv routines to
|
|
* DISPBLTDBG().
|
|
*
|
|
* 08-Nov-1993 Bob Seitsinger
|
|
* Implement coding conventions:
|
|
* o Insert a WBFLUSH() call at the start of each Drv routine.
|
|
* o Remove excess CYCLE_REGS() calls.
|
|
* o Ensure CYCLE_REGS() calls are made if writing to registers out
|
|
* of order.
|
|
*
|
|
* 08-Nov-1993 Bob Seitsinger
|
|
* Add code to handle MERGECOPY, PATCOPY and PATINVERT rops. Just
|
|
* call fill_pattern_8, if I get an 8x8 pattern and have a simple
|
|
* ROP, otherwise do other things to handle it.
|
|
*
|
|
* 10-Nov-1993 Bob Seitsinger
|
|
* Add code to handle 'table' color translations.
|
|
*
|
|
* 10-Nov-1993 Bob Seitsinger
|
|
* Punt MERGECOPY rop, for the moment. Involves a 'source' surface
|
|
* object, and my 'pattern' code isn't set up to handle this.
|
|
*
|
|
* 10-Nov-1993 Bob Seitsinger
|
|
* Insert new 'punting' code, i.e. use PDEV->bInPuntRoutine member.
|
|
*
|
|
* 11-Nov-1993 Bob Seitsinger
|
|
* Punt PATINVERT rop, for the moment. Involves a 'destination' surface
|
|
* object, and my 'pattern' code isn't set up to handle this.
|
|
*
|
|
* 11-Nov-1993 Barry Tannenbaum
|
|
* Determine ppdev in DrvBitBlt and DrvCopyBits only, then pass the
|
|
* value down to the routines we call
|
|
*
|
|
* 12-Nov-1993 Barry Tannenbaum
|
|
* Check psrTrg instead of psoSrc to get around bogus dhpdev value.
|
|
*
|
|
* 15-Nov-1993 Bob Seitsinger
|
|
* Do NOT assign psoSrc = psoTrg if psoSrc == NULL. Just display a
|
|
* message and continue (or return FALSE?). CopyBits only.
|
|
*
|
|
* 17-Nov-1993 Bob Seitsinger
|
|
* Fix color translation code.
|
|
*
|
|
* 22-Nov-1993 Bob Seitsinger
|
|
* Fix for Disk Administrator Key Displays (at bottom of screen).
|
|
* They are currently displaying as bitonal patterns, instead of
|
|
* a solid color. The scenario - upon entry into bSolidFill pbo->
|
|
* iSolidColor is -1 (i.e. pattern needs to be realized and/or used).
|
|
* As such, a call to bPatternFill is made. However, in bPatternFill
|
|
* we never check the iBitmapFormat value after the brush is realized
|
|
* to see if the brush is a mono/bi-tonal brush which would allow us
|
|
* to call back to the solid brush code. That is essentially what
|
|
* the fix is going to be. The foreground color that is defined for
|
|
* a 1-bpp brush will be used as the pbo->iSolidColor and a call
|
|
* back to bSolidFill will be made.
|
|
*
|
|
* Also, add code in bPatternFill to punt all but 1bpp and 8bpp
|
|
* patterns.
|
|
*
|
|
* 23-Nov-1993 Bob Seitsinger
|
|
* Modify DrvCopyBits to call bBitBlt and '#if 0' bCopyBits.
|
|
*
|
|
* 23-Nov-1993 Bob Seitsinger
|
|
* FreeCell color problem - vertical sides of 'red' cards had
|
|
* red borders, when they should have been black. In this case,
|
|
* a bitblt call with a BLACKNESS rop was issued. However, the
|
|
* iSolidColor of the brush object was -1, causing the pattern
|
|
* fill code to be executed. This is unnecessary (and undesirable).
|
|
* If I get a BLACKNESS or WHITENESS rop, all I need to do is set
|
|
* the pbo->iSolidColor to something other than -1 and call solid fill.
|
|
* The rop will take care of the color to draw, the target rectangle
|
|
* will take are of where to draw.
|
|
*
|
|
* 03-Dec-1993 Bob Seitsinger
|
|
* Add check to avoid 'pattern fill' code if whiteness or blackness
|
|
* ROP, while in bSolidFill code.
|
|
*
|
|
* 03-Dec-1993 Bob Seitsinger
|
|
* Make PATINVERT one of the 'simple' rops that passes through
|
|
* bSolidFill.
|
|
*
|
|
* 03-Nov-1993 Bob Seitsinger
|
|
* Remove the bCopyBits code. Also, modify 'pattern fill' code to
|
|
* handle complex PATINVERT and MERGECOPY ROPs. Lastly, moved
|
|
* code around to do away with the bitblt.h file.
|
|
*
|
|
* 10-Dec-1993 Barry Tannenbaum
|
|
* Modifications for sparse space support
|
|
*
|
|
* 07-Jan-1994 Bob Seitsinger
|
|
* Add #ifdef TEST_ENV where appropriate to allow integration within
|
|
* 'model' test environment, without having to modify code each
|
|
* time.
|
|
*
|
|
* 24-Jan-1994 Bob Seitsinger
|
|
* Add TGA_BITBLT and TGA_COPYBITS constants and make use of them to
|
|
* turn on and off punting of bitblt and copybits code. Also add a
|
|
* dummy XLATEOBJ_piVector() routine to handle when we compile for
|
|
* the test environment.
|
|
*
|
|
* 31-Jan-1994 Bob Seitsinger
|
|
* Fix bug when 1bpp non-face black cards in Freecell are partially
|
|
* occluded and then unoccluded and are incorrectly redrawn.
|
|
*
|
|
* 01-Feb-1994 Bob Seitsinger
|
|
* Add 'extern' for ulXlateBmfToBpp() and fill in parameters for
|
|
* all 'extern's.
|
|
*
|
|
* 14-Feb-1994 Bob Seitsinger
|
|
* Make use of the new routines for surface object address, stride
|
|
* and format.
|
|
*
|
|
* 23-Feb-1994 Bob Seitsinger
|
|
* Removed commented out code that dealt with a NULL clip object.
|
|
* Implemented simpler code to handle it.
|
|
*
|
|
* 24-Feb-1994 Barry Tannenbaum
|
|
* - Moved fill code into paint.c.
|
|
* - Replace call to ulXlateBmfToBpp with call to SURFOBJ_format
|
|
*
|
|
* 28-Feb-1994 Bob Seitsinger
|
|
* Make height in bBitblt defined all the time. Not just for checked
|
|
* builds.
|
|
*
|
|
* 04-Mar-1994 Bob Seitsinger
|
|
* Moved XLATEOBJ_piVector() routine to test_stuff.c. Also, made minor
|
|
* modifications based on feedback from code review.
|
|
*
|
|
* 24-Mar-1994 Bob Seitsinger
|
|
* If we receive a Noop rop (0x0000AAAA), just return.
|
|
*
|
|
* 25-Mar-1994 Barry Tannenbaum
|
|
* Typecast pso->dhpev to (PPDEV) to keep the Daytona compiler happy
|
|
*
|
|
* 16-May-1994 Bob Seitsinger
|
|
* Add code in support of DPna (0x00000A0A) rop.
|
|
*
|
|
* 16-May-1994 Barry Tannenbaum
|
|
* Added code to accelerate display of 1BPP bitmaps
|
|
*
|
|
* 17-May-1994 Barry Tannenbaum
|
|
* Fix bugs with 1BPP bitmaps when source offset + alignment pixels > 32
|
|
*
|
|
* 25-May-1994 Bob Seitsinger
|
|
* Add code to handle new rops - 0xfafa (DPo) and 0xafaf (DPno) and a
|
|
* host->screen express routine to handle simple requests (i.e. trivial
|
|
* clip object and no or trivial color translation). The main thrust
|
|
* behind the 'express' routine is to minimize/eliminate code branches
|
|
* due to procedure calls and if/switch statements for the simple
|
|
* case. The theory being that code branches cause pipeline stalls,
|
|
* which is badness!
|
|
*
|
|
* Lastly, do some code cleanup (a) get rid of those DISPDBG() macros,
|
|
* not needed since we now have a 'real' debugger that can display
|
|
* source code, (b) eliminate unnecessary local variables, (c) pass
|
|
* ppdev down from the Drv routines and (d) minimize parameters passed.
|
|
*
|
|
* 31-May-1994 Bob Seitsinger
|
|
* Modify ulAccelRops table to include ulTGARop table functionality,
|
|
* amongst other things. Also move bBitBlt code into DrvBitBlt (since
|
|
* that's the only routine using it) and make bBitBlt something else
|
|
* that DrvBitBlt uses.
|
|
*
|
|
* Lastly, accelerate rop 0xA5 - PDxn ((Destination XOR Pattern) NOT).
|
|
*
|
|
* 01-Jun-1994 Bob Seitsinger
|
|
* Move some tests in DrvBitBlt until after branching to DrvPaint,
|
|
* since they are not relevant for those rops which make use of
|
|
* DrvPaint. Also, use ppdev->pcoDefault if pco is NULL.
|
|
*
|
|
* Oops, back-out usage of pcoDefault. Use ppdev->pcoTrivial when we
|
|
* don't need to modify rclBounds, and use a local clip object when
|
|
* we do (like when DrvBitBlt calls DrvPaint).
|
|
*
|
|
* 01-Jun-1994 Bob Seitsinger
|
|
* Accelerate rops 05, 0f, 50, 5f and f5 (from WinBench tests) and
|
|
* redo ulAccelRop table entries for 0a, a5 and af entries. All these
|
|
* rops can be performed with one call to DrvPaint.
|
|
*
|
|
* 03-Jun-1994 Bob Seitsinger
|
|
* Call solid fill code directly, instead of going through DrvPaint.
|
|
* This will require a modification to the ulAccelRops table entries
|
|
* for Blackness, DstInvert and Whiteness - which are the three rops
|
|
* that will call the solid fill code directly. Also, have to make
|
|
* use of some additional bits, to define the color to use (only
|
|
* really relevant for blackness and whiteness).
|
|
*
|
|
* 07-Jun-1994 Bob Seitsinger
|
|
* Add code in DrvCopyBits and DrvBitBlt to handle 'device managed
|
|
* bitmap' (i.e. STYPE_DEVBITMAP) cases. They are essentially handled
|
|
* the same as 'on screen' (i.e. STYPE_DEVICE) cases.
|
|
*
|
|
* 14-Jun-1994 Bob Seitsinger
|
|
* Add check in DrvCopyBits and DrvBitBlt to punt on 4bpp bitmaps
|
|
* that have a source x value not = 0. The host->screen code
|
|
* currently can't handle this.
|
|
*
|
|
* 20-Jun-1994 Bob Seitsinger
|
|
* 14-JUN-1994 fix checked for source bitmap of < 8bpp, when it
|
|
* should have checked for a source bitmap of == 4bpp.
|
|
*
|
|
* 27-Jun-1994 Bob Seitsinger
|
|
* Remove punting of 4bpp bitmaps when source x value is not = 0.
|
|
* The host->screen code will now be able to handle these.
|
|
*
|
|
* 2-Jul-1994 Barry Tannenbaum
|
|
* Fixed bugs with 1BPP pixmaps
|
|
* - Model found a CYCLE_REGS bug
|
|
* - Not properly incrementing through source bitmap
|
|
*
|
|
* 21-Jul-1994 Bob Seitsinger
|
|
* Write the plane mask register when using block fill mode -
|
|
* in fill_solid_color.
|
|
*
|
|
* 05-Aug-1994 Bob Seitsinger
|
|
* Ensure that psoSrc is NOT NULL before dereferencing it
|
|
* to get PDEV. Two mods - in DrvCopyBits and DrvBitBlt.
|
|
*
|
|
* 9-Aug-1994 Barry Tannenbaum
|
|
* Setup for 24 plane:
|
|
* - Make TGAROP and TGAMODE accept simply ULONGs instead of structures
|
|
* - Use default values from ulModeTemplate and ulRopTemplate
|
|
*
|
|
* 25-Aug-1994 Bob Seitsinger
|
|
* 24 plane modifications:
|
|
* - use fill_solid code from paint.c.
|
|
* - move bHSExpress into it's own module for multi-compiles, and
|
|
* modify where it's called to call the appropriate permutation.
|
|
* - move copy_masked_and_unmasked into it's own module for multi-compiles
|
|
* and modify where it's called to call the appropriate permutation.
|
|
* - modify s->s, s->h and h->s routines to call appropriate routine
|
|
* based on source and target bit depths.
|
|
* - Moved DrvSaveScreenBits from blt.c to here, since we have to
|
|
* break up blt.c into seperate modules for s->s, h->s and s->h
|
|
* for multiple compiles.
|
|
* - Fix MemScr_1BPP to handle both 8plane and 24plane boards.
|
|
* - Do NOT use the plane mask to flush the high 8 bits for
|
|
* 32bpp frame buffers. Explicitly mask off the bits for each frame
|
|
* buffer write. This is mostly relevant when using Simple mode.
|
|
*
|
|
* 6-Sep-1994 Bob Seitsinger
|
|
* Fix a bug in MemScr_1BPP. We were using the left_shift value as
|
|
* a 'pixel' value AND a 'byte' value. Recalc it to a 'pixel' value
|
|
* after we're done with it as a 'byte' value.
|
|
*
|
|
* 12-Sep-1994 Bob Seitsinger
|
|
* Call the appropriate host->screen routine in bHostToScrn. 4bpp-
|
|
* specific routines have been added.
|
|
*
|
|
* 15-Sep-1994 Bob Seitsinger
|
|
* Make sure to WBFLUSH() before calling fill_solid_color in
|
|
* DrvBitBlt.
|
|
*
|
|
* 19-Sep-1994 Barry Tannenbaum
|
|
* Fixed handling of monochrome bitmaps when the initial stipple mask
|
|
* crosses two ULONGs of source data.
|
|
*
|
|
* 20-Sep-1994 Bob Seitsinger
|
|
* Re-insert 24plane mods in monochrome code from 25-Aug and 6-Sep.
|
|
* They were accidentally deleted.
|
|
*
|
|
* 21-Sep-1994 Bob Seitsinger
|
|
* In MemScr_1BPP - align to 4 bytes (4 pixels) for 8bpp target and
|
|
* 8 bytes (2 pixels) for 32bpp target. Also, make use of ppdev->
|
|
* ulPlanemaskTemplate when rop != copy.
|
|
*
|
|
* 4-Oct-1994 Barry Tannenbaum
|
|
* DrvPaint will now return FALSE if it is given a TGA ROP and can't
|
|
* accelerate the call. This lets us punt it from DrvBitBlt instead of
|
|
* from DrvPaint, preventing an ACCVIO.
|
|
*
|
|
* 10-Oct-1994 Bob Seitsinger
|
|
* Accelerate rop B8 - PSDPxax - (((Pat XOR Dest) AND Src) XOR Pat).
|
|
* No need to do the XORs if pattern is a solid color black.
|
|
*
|
|
* 11-Oct-1994 Bob Seitsinger
|
|
* Accelerate rop FB - DPSnoo - ((NOT Source OR Pattern) OR Destination).
|
|
* No need to OR Source and Pattern if pattern is a solid color black.
|
|
*
|
|
* 12-Oct-1994 Bob Seitsinger
|
|
* Accelerate rop 69 - PDSxxn - NOT ((Src XOR Dest) XOR Pat).
|
|
*
|
|
* 25-Oct-1994 Bob Seitsinger
|
|
* Write plane mask with ppdev->ulPlanemaskTemplate all the
|
|
* time (except in DrvSaveScreenBits (i.e. offscreen save
|
|
* and restore) and screen->host copies).
|
|
*
|
|
* For 24 plane boards we don't want to blow away the
|
|
* windows ids for 3d windows. The GL driver removes the
|
|
* window ids when it relinquishes a rectangular area.
|
|
*
|
|
* 3-Nov-1994 Tim Dziechowski
|
|
* Stats support
|
|
*
|
|
* 3-Nov-1994 Bob Seitsinger
|
|
* Replace references to REVERSE_DATA with REVERSE_BYTE, found
|
|
* in driver.h. Also, delete the REVERSE_DATA macro.
|
|
*
|
|
* 20-Jan-1995 Bob Seitsinger
|
|
* Use ulPlanemaskTemplate in DrvSaveScreenBits - don't touch the
|
|
* tag bits for a 32bpp frame buffer.
|
|
*
|
|
* 2-Mar-1995 Barry Tannenbaum
|
|
* Changes to support EV5
|
|
*
|
|
* 22-Mar-1995 Bob Seitsinger
|
|
* Exit DrvBitBlt immediately ONLY if both foreground and background
|
|
* rops (i.e. low and high byte) are 0xaa. Currently I'm exiting
|
|
* only if the low byte (foreground) is a noop. Thus, not punting on
|
|
* cases where the low byte is 0xaa and the high byte is some other
|
|
* useful rop that we want processed.
|
|
*
|
|
* 28-Mar-1995 Bob Seitsinger
|
|
* Oops! Messed up on the 0xAA fix. Fix it! Specifically, in my
|
|
* attempt to save a shift I was inadvertently comparing 0xff00
|
|
* rop4 bits (background) against 0x00ff rop4 bits (foreground),
|
|
* which would always be unequal, and thus always punt! Not what
|
|
* we want to do.
|
|
*/
|
|
|
|
#include "driver.h"
|
|
#include "tgablt.h"
|
|
#include "tgastats.h"
|
|
|
|
// Function prototypes
|
|
|
|
BOOL bSupportedBpp(
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoTrg,
|
|
PPDEV ppdev);
|
|
|
|
BOOL fill_solid_color(
|
|
SURFOBJ *pso,
|
|
CLIPOBJ *pco,
|
|
ULONG color,
|
|
ULONG tga_rop);
|
|
|
|
// prototypes for which function to call
|
|
|
|
typedef VOID (*SSFUNC) (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
ULONG flDir,
|
|
POINTL *pptlSrc,
|
|
PRECTL prclTrg);
|
|
|
|
typedef VOID (*HSFUNC) (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
POINTL *pptlSrc,
|
|
PRECTL prclTrg,
|
|
PULONG pulXlate);
|
|
|
|
typedef VOID (*SHFUNC) (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
POINTL *pptlSrc,
|
|
PRECTL prclTrg,
|
|
PULONG pulXlate);
|
|
|
|
// Table of raster ops we're accelerating.
|
|
//
|
|
// Bit Description
|
|
// ---------------------------------------
|
|
// 31 0 - not from blit code
|
|
// 1 - from blit code
|
|
// 30 0 - do not invert bits
|
|
// 1 - invert bits
|
|
// 29 0 - does not contain source
|
|
// 1 - contains source
|
|
// 28 0 - does not contain a pattern
|
|
// 1 - contains a pattern
|
|
// ---------------------------------------
|
|
// 27 0 - not accelerating
|
|
// 1 - accelerating
|
|
// 26 0 - do not call DrvPaint
|
|
// 1 - call DrvPaint
|
|
// 25 0 - not a special-case rop
|
|
// 1 - special case rop
|
|
// 24 0 - do not call solid fill code
|
|
// 1 - call solid fill code
|
|
// ---------------------------------------
|
|
// 23->16 solid fill color
|
|
// ---------------------------------------
|
|
// 15->4 not currently used
|
|
// 3->0 tga rop
|
|
// ---------------------------------------
|
|
//
|
|
ULONG ulAccelRops[256] =
|
|
{
|
|
0x89000003, 0x00000000, 0x00000000, 0x00000000, // 0x03
|
|
0x00000000, 0x9c000008, 0x00000000, 0x00000000, // 0x07
|
|
0x00000000, 0x00000000, 0x9c000004, 0x00000000, // 0x0b
|
|
0x00000000, 0x00000000, 0x00000000, 0x9c00000c, // 0x0f
|
|
|
|
0x00000000, 0xa8000008, 0x00000000, 0x00000000, // 0x13
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x17
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x1b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x1f
|
|
|
|
0x00000000, 0x00000000, 0xa8000004, 0x00000000, // 0x23
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x27
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x2b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x2f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0xa800000c, // 0x33
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x37
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x3b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x3f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x43
|
|
0xa8000002, 0x00000000, 0x00000000, 0x00000000, // 0x47
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x4b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x4f
|
|
|
|
0x9c000002, 0x00000000, 0x00000000, 0x00000000, // 0x53
|
|
0x00000000, 0x8900000a, 0x00000000, 0x00000000, // 0x57
|
|
0x00000000, 0x00000000, 0x9c000006, 0x00000000, // 0x5b
|
|
0x00000000, 0x00000000, 0x00000000, 0x9c00000e, // 0x5f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x63
|
|
0x00000000, 0x00000000, 0xa8000006, 0x00000000, // 0x67
|
|
0x00000000, 0xba000009, 0x00000000, 0x00000000, // 0x6b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x6f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x73
|
|
0x00000000, 0x00000000, 0x00000000, 0xa800000e, // 0x77
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x7b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x7f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x83
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x87
|
|
0xa8000001, 0x00000000, 0x00000000, 0x00000000, // 0x8b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x8f
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x93
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x97
|
|
0x00000000, 0xa8000009, 0x00000000, 0x00000000, // 0x9b
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0x9f
|
|
|
|
0x9c000001, 0x00000000, 0x00000000, 0x00000000, // 0xa3
|
|
0x00000000, 0x9c000009, 0x00000000, 0x00000000, // 0xa7
|
|
0x00000000, 0x00000000, 0x88000005, 0x00000000, // 0xab
|
|
0x00000000, 0x00000000, 0x00000000, 0x9c00000d, // 0xaf
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xb3
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xb7
|
|
0xba000006, 0x00000000, 0x00000000, 0xa800000d, // 0xbb
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xbf
|
|
|
|
0xba000001, 0x00000000, 0x00000000, 0x00000000, // 0xc3
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xc7
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xcb
|
|
0xa8000003, 0x00000000, 0x00000000, 0x00000000, // 0xcf
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xd3
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xd7
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xdb
|
|
0x00000000, 0xa800000b, 0x00000000, 0x00000000, // 0xdf
|
|
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xe3
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xe7
|
|
0x00000000, 0x00000000, 0x00000000, 0x00000000, // 0xeb
|
|
0x00000000, 0x00000000, 0xa8000007, 0x00000000, // 0xef
|
|
|
|
0x9c000003, 0x00000000, 0x00000000, 0x00000000, // 0xf3
|
|
0x00000000, 0x9c00000b, 0x00000000, 0x00000000, // 0xf7
|
|
0x00000000, 0x00000000, 0x9c000007, 0xba000000, // 0xfb
|
|
0x00000000, 0x00000000, 0x00000000, 0x89ff0003 // 0xff
|
|
};
|
|
|
|
|
|
/*****************************************************************************
|
|
* TGA Screen to Screen Copy
|
|
****************************************************************************/
|
|
BOOL bScrnToScrn (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
ULONG tgarop)
|
|
|
|
{
|
|
|
|
ULONG flDir; // forward or backward copy
|
|
SSFUNC pSSFunc; // function permutation to call
|
|
|
|
DISPDBG ((1, "TGA.DLL!bScrnToScrn - Entry\n"));
|
|
|
|
// Calculate blt direction. Use CLIPOBJ direction flags
|
|
// to signify direction to copy.
|
|
|
|
flDir = CD_RIGHTDOWN;
|
|
|
|
if ( (prclTrg->top > pptlSrc->y) ||
|
|
((prclTrg->top == pptlSrc->y) && (prclTrg->left >= pptlSrc->x)) )
|
|
flDir = CD_LEFTUP;
|
|
|
|
// Select the appropriate screen->screen permutation.
|
|
// There are no translations allowed/required for scr->scr copies.
|
|
|
|
if (32 == ppdev->ulBitCount)
|
|
pSSFunc = vBitbltSS32to32;
|
|
else
|
|
pSSFunc = vBitbltSS8to8;
|
|
|
|
// Determine bits to write for a given pixel.
|
|
|
|
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
|
|
|
|
// Set the ROP register
|
|
|
|
TGAROP (ppdev, ppdev->ulRopTemplate | tgarop);
|
|
|
|
// Call the next level routine as many times as there are
|
|
// clipping objects.
|
|
|
|
switch ( pco->iDComplexity )
|
|
{
|
|
// This is a simple case where the entire Dst rectangle is to
|
|
// be updated.
|
|
|
|
case DC_TRIVIAL:
|
|
(*pSSFunc) (ppdev, psoTrg, psoSrc, flDir, pptlSrc, prclTrg);
|
|
return TRUE;
|
|
|
|
// There is only one clip rect.
|
|
|
|
case DC_RECT:
|
|
{
|
|
ENUMRECTS1 clip;
|
|
|
|
if (bIntersectRects(&clip.arcl, &pco->rclBounds, prclTrg))
|
|
{
|
|
POINTL ptlSrc;
|
|
ptlSrc.x = pptlSrc->x + clip.arcl.left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + clip.arcl.top - prclTrg->top;
|
|
(*pSSFunc) (ppdev, psoTrg, psoSrc, flDir, &ptlSrc, &clip.arcl);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// There are multiple clip rects.
|
|
// (Do not limit the number of clip rects we'll enumerate.)
|
|
|
|
case DC_COMPLEX:
|
|
{
|
|
BOOL bMore;
|
|
ENUMRECTS8 clip;
|
|
UINT iClip;
|
|
PRECTL prcl;
|
|
POINTL ptlSrc;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, flDir, 0);
|
|
|
|
// Call blt code for each cliprect.
|
|
|
|
do
|
|
{
|
|
// Get list of clip rects.
|
|
|
|
bMore = CLIPOBJ_bEnum(pco, sizeof(clip), (PVOID) &clip);
|
|
|
|
for (iClip = 0; iClip < clip.c; iClip++)
|
|
{
|
|
prcl = &clip.arcl[iClip];
|
|
|
|
// Bound clip rect with Dst rect and update
|
|
// Src start point.
|
|
|
|
if (bIntersectRects(prcl, prcl, prclTrg))
|
|
{
|
|
ptlSrc.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
(*pSSFunc) (ppdev, psoTrg, psoSrc, flDir, &ptlSrc, prcl);
|
|
}
|
|
}
|
|
} while (bMore);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* MemScr_1BPP
|
|
****************************************************************************/
|
|
static
|
|
VOID MemScr_1BPP (SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
INT xSrc,
|
|
INT ySrc,
|
|
RECTL *prclTrg)
|
|
{
|
|
|
|
PPDEV ppdev = (PPDEV) psoTrg->dhpdev;
|
|
PBYTE src_base_address;
|
|
PBYTE trg_base_address;
|
|
INT src_stride;
|
|
INT trg_stride;
|
|
PULONG src_data;
|
|
PBYTE trg_address;
|
|
ULONG stipple_mask;
|
|
UINT left_shift, right_shift;
|
|
UINT left_mask_shift, right_mask_shift;
|
|
ULONG left_mask, right_mask;
|
|
int width, height;
|
|
int x, y;
|
|
ULONG last_stipple_mask, cur_stipple_mask;
|
|
|
|
// Fetch the base address and stride for the source bitmap. Calculate the
|
|
// address of the first ULONG that we'll fetch from the bitmap
|
|
|
|
src_base_address = SURFOBJ_base_address (psoSrc);
|
|
src_stride = SURFOBJ_stride (psoSrc);
|
|
|
|
src_base_address += (ySrc * src_stride) + // Y offset
|
|
((xSrc & (-32)) >> 3); // X offset rounded to LONGs
|
|
|
|
xSrc &= 0x1f; // % 32
|
|
|
|
// Fetch the base address and stride for the frame buffer. Calculate the
|
|
// address of the first ULONG that we'll write. Note that we have to back
|
|
// up by 'xSrc' to the beginning of the ULONG
|
|
|
|
trg_base_address = SURFOBJ_base_address (psoTrg);
|
|
trg_stride = SURFOBJ_stride (psoTrg);
|
|
|
|
trg_base_address += (prclTrg->top * trg_stride) +
|
|
((prclTrg->left - xSrc) * ppdev->ulBytesPerPixel);
|
|
|
|
// Align the target to either a 4-byte boundary (8bpp) or
|
|
// 8-byte boundary (32bpp).
|
|
|
|
if (BMF_8BPP == SURFOBJ_format(psoTrg))
|
|
left_shift = (unsigned int)trg_base_address & 0x03;
|
|
else
|
|
left_shift = (unsigned int)trg_base_address & 0x07;
|
|
|
|
trg_base_address = trg_base_address - left_shift;
|
|
|
|
// Convert left_shift from bytes to pixels.
|
|
// From this point on, left_shift is used as 'number of pixels'
|
|
// to shift left.
|
|
|
|
left_shift /= ppdev->ulBytesPerPixel;
|
|
|
|
right_shift = 32 - left_shift;
|
|
|
|
// Calculate width and height. Add 'left_shift' and 'xSrc' to the width,
|
|
// since they effect whether we're emitting one or more stipple masks
|
|
|
|
width = (prclTrg->right - prclTrg->left) + left_shift + xSrc;
|
|
height = prclTrg->bottom - prclTrg->top;
|
|
|
|
// Calculate the shift masks. If left_shift + xSrc is greater than 32,
|
|
// shift the target address to the next aligned spot
|
|
|
|
left_mask_shift = left_shift + xSrc;
|
|
if (left_mask_shift >= 32)
|
|
{
|
|
left_mask_shift -= 32; // Adjust for new target address,
|
|
// 32 pixels worth.
|
|
width -= 32;
|
|
trg_base_address += (32 * ppdev->ulBytesPerPixel);
|
|
}
|
|
left_mask = 0xffffffff << left_mask_shift;
|
|
|
|
right_mask_shift = width & 0x1f; // % 32
|
|
if (0 == right_mask_shift)
|
|
right_mask = 0xffffffff;
|
|
else
|
|
right_mask = 0xffffffff >> (32 - right_mask_shift);
|
|
|
|
// Check for skinny stipples - The whole thing in a ULONG or less. We can
|
|
// optimize these by using the persistent pixel mask
|
|
|
|
if (width <= 32)
|
|
{
|
|
TGAPERSISTENTPIXELMASK (ppdev, left_mask & right_mask);
|
|
|
|
if (0 == left_shift)
|
|
{
|
|
// Aligned stipple, 1 ULONG per scanline - Simplest possible case
|
|
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
src_data = (PULONG)src_base_address;
|
|
|
|
stipple_mask = *src_data;
|
|
REVERSE_BYTE (stipple_mask);
|
|
TGAWRITE (ppdev, trg_base_address, stipple_mask);
|
|
|
|
trg_base_address += trg_stride;
|
|
src_base_address += src_stride;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// Unaligned stipple, 1 ULONG per scanline - Not much harder
|
|
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
src_data = (PULONG)src_base_address;
|
|
|
|
// If left_shift + xSrc is greater than 32, we've shifted the targe
|
|
// address to the next aligned address. We have to pick up the
|
|
// trailing bits from the last stipple mask
|
|
|
|
if (left_shift + xSrc >= 32)
|
|
{
|
|
last_stipple_mask = *src_data++;
|
|
REVERSE_BYTE (last_stipple_mask);
|
|
}
|
|
else
|
|
last_stipple_mask = 0; // Ignored
|
|
|
|
cur_stipple_mask = *src_data;
|
|
REVERSE_BYTE (cur_stipple_mask);
|
|
stipple_mask = (last_stipple_mask >> right_shift) |
|
|
(cur_stipple_mask << left_shift);
|
|
TGAWRITE (ppdev, trg_base_address, stipple_mask);
|
|
|
|
trg_base_address += trg_stride;
|
|
src_base_address += src_stride;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// We have to write more than 1 ULONG per scanline
|
|
|
|
if (0 == left_shift)
|
|
{
|
|
// Aligned, multi-ULONG stipple - Still pretty easy
|
|
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
// Set the source & target address for the left edge and then
|
|
// calculate the address of the next scanline. The target
|
|
// address has to be cycled through the aliases since we're
|
|
// going to be twiddling the PIXEL MASK register and the order
|
|
// must be maintained
|
|
|
|
trg_address = trg_base_address;
|
|
src_data = (PULONG)src_base_address;
|
|
|
|
trg_base_address = cycle_fb_address_double (ppdev,
|
|
trg_base_address);
|
|
|
|
trg_base_address += trg_stride;
|
|
src_base_address += src_stride;
|
|
|
|
// Write out the stipple masks for this scanline except for the
|
|
// last one. The PIXEL MASK register will automatically be
|
|
// reset after the first write to the frame buffer
|
|
|
|
CYCLE_REGS (ppdev);
|
|
TGAPIXELMASK (ppdev, left_mask);
|
|
|
|
for (x = 0; x < width - 32; x+=32)
|
|
{
|
|
stipple_mask = *src_data++;
|
|
REVERSE_BYTE (stipple_mask);
|
|
TGAWRITE (ppdev, trg_address, stipple_mask);
|
|
trg_address += (32 * ppdev->ulBytesPerPixel);
|
|
}
|
|
|
|
// Set the PIXEL MASK for the last stipple mask and write the
|
|
// last stipple mask for this scanline to the frame buffer.
|
|
// Note that the last frame buffer write must be in it's own
|
|
// alias to maintain ordering. If we shared the alias of the
|
|
// next scanline, it's possible that the left mask will be
|
|
// applied to the wrong write
|
|
|
|
CYCLE_REGS (ppdev);
|
|
TGAPIXELMASK (ppdev, right_mask);
|
|
|
|
stipple_mask = *src_data;
|
|
REVERSE_BYTE (stipple_mask);
|
|
|
|
trg_address = cycle_fb_address (ppdev, trg_address);
|
|
TGAWRITE (ppdev, trg_address, stipple_mask);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
// UnAligned, multi-ULONG stipple - Don't try this at home folks...
|
|
|
|
for (y = 0; y < height; y++)
|
|
{
|
|
// Set the source & target address for the left edge and then
|
|
// calculate the address of the next scanline. The target
|
|
// address has to be cycled through the aliases since we're
|
|
// going to be twiddling the PIXEL MASK register and the order
|
|
// must be maintained
|
|
|
|
trg_address = trg_base_address;
|
|
src_data = (PULONG)src_base_address;
|
|
|
|
trg_base_address = cycle_fb_address_double (ppdev,
|
|
trg_base_address);
|
|
|
|
trg_base_address += trg_stride;
|
|
src_base_address += src_stride;
|
|
|
|
// Write out the stipple masks for this scanline except for the
|
|
// last one. The PIXEL MASK register will automatically be
|
|
// reset after the first write to the frame buffer
|
|
|
|
CYCLE_REGS (ppdev);
|
|
TGAPIXELMASK (ppdev, left_mask);
|
|
|
|
// If left_shift + xSrc is greater than 32, we've shifted the targe
|
|
// address to the next aligned address. We have to pick up the
|
|
// trailing bits from the last stipple mask
|
|
|
|
if (left_shift + xSrc >= 32)
|
|
{
|
|
last_stipple_mask = *src_data++;
|
|
REVERSE_BYTE (last_stipple_mask);
|
|
}
|
|
else
|
|
last_stipple_mask = 0; // Ignored
|
|
|
|
// Write out the first through next-to-last stipple masks. The PIXEL
|
|
// MASK will automatically reset after the first write to the frame
|
|
// buffer
|
|
|
|
for (x = 0; x < width - 32; x+=32)
|
|
{
|
|
cur_stipple_mask = *src_data++;
|
|
REVERSE_BYTE (cur_stipple_mask);
|
|
|
|
stipple_mask = (cur_stipple_mask << left_shift) |
|
|
(last_stipple_mask >> right_shift);
|
|
last_stipple_mask = cur_stipple_mask;
|
|
|
|
TGAWRITE (ppdev, trg_address, stipple_mask);
|
|
trg_address += (32 * ppdev->ulBytesPerPixel);
|
|
}
|
|
|
|
// Set the PIXEL MASK for the last stipple mask and write the
|
|
// last stipple mask for this scanline to the frame buffer.
|
|
// Note that the last frame buffer write must be in it's own
|
|
// alias to maintain ordering. If we shared the alias of the
|
|
// next scanline, it's possible that the left mask will be
|
|
// applied to the wrong write
|
|
|
|
CYCLE_REGS (ppdev);
|
|
TGAPIXELMASK (ppdev, right_mask);
|
|
|
|
if ((char* )src_data == src_base_address)
|
|
stipple_mask = last_stipple_mask >> right_shift;
|
|
else
|
|
{
|
|
cur_stipple_mask = *src_data;
|
|
REVERSE_BYTE (cur_stipple_mask);
|
|
|
|
stipple_mask = (cur_stipple_mask << left_shift) |
|
|
(last_stipple_mask >> right_shift);
|
|
}
|
|
|
|
trg_address = cycle_fb_address (ppdev, trg_address);
|
|
TGAWRITE (ppdev, trg_address, stipple_mask);
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* TGA Host to Screen Copy
|
|
****************************************************************************/
|
|
BOOL bHostToScrn (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
PULONG pulXlate,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
ULONG tgarop)
|
|
|
|
{
|
|
|
|
HSFUNC pHSFunc; // function permutation to call
|
|
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - Entry\n"));
|
|
|
|
// Figure out which routine to use.
|
|
|
|
if (32 == ppdev->ulBitCount)
|
|
{
|
|
if (BMF_4BPP == psoSrc->iBitmapFormat)
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - vBitbltHS4to32 selected\n"));
|
|
pHSFunc = vBitbltHS4to32;
|
|
}
|
|
else if (BMF_8BPP == psoSrc->iBitmapFormat)
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - vBitbltHS8to32 selected\n"));
|
|
pHSFunc = vBitbltHS8to32;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - vBitbltHS32to32 selected\n"));
|
|
pHSFunc = vBitbltHS32to32;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (BMF_4BPP == psoSrc->iBitmapFormat)
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - vBitbltHS4to8 selected\n"));
|
|
pHSFunc = vBitbltHS4to8;
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!bHostToScrn - vBitbltHS8to8 selected\n"));
|
|
pHSFunc = vBitbltHS8to8;
|
|
}
|
|
}
|
|
|
|
// Determine which bits to write for a given pixel.
|
|
|
|
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
|
|
|
|
// Set the ROP register
|
|
|
|
TGAROP (ppdev, ppdev->ulRopTemplate | tgarop);
|
|
|
|
// Call the next level routine as many times as there are
|
|
// clipping objects.
|
|
|
|
if (BMF_1BPP == SURFOBJ_format (psoSrc))
|
|
{
|
|
CYCLE_REGS (ppdev);
|
|
|
|
// Load the foreground and background
|
|
// registers appropriately.
|
|
|
|
if (pulXlate)
|
|
{
|
|
if (8 == ppdev->ulBitCount)
|
|
{
|
|
ULONG color;
|
|
|
|
color = pulXlate[1] |
|
|
(pulXlate[1] << 8);
|
|
color |= color << 16;
|
|
TGAFOREGROUND (ppdev, color);
|
|
|
|
color = pulXlate[0] |
|
|
(pulXlate[0] << 8);
|
|
color |= color << 16;
|
|
TGABACKGROUND (ppdev, color);
|
|
}
|
|
else
|
|
{
|
|
TGAFOREGROUND (ppdev, pulXlate[1]);
|
|
TGABACKGROUND (ppdev, pulXlate[0]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TGAFOREGROUND (ppdev, 0xffffffff);
|
|
TGABACKGROUND (ppdev, 0);
|
|
}
|
|
|
|
CYCLE_REGS (ppdev);
|
|
|
|
TGAMODE (ppdev, ppdev->ulModeTemplate | TGA_MODE_OPAQUE_STIPPLE);
|
|
|
|
switch (pco->iDComplexity)
|
|
{
|
|
case DC_TRIVIAL:
|
|
MemScr_1BPP (psoTrg, psoSrc, pptlSrc->x, pptlSrc->y, prclTrg);
|
|
return TRUE;
|
|
|
|
case DC_RECT:
|
|
{
|
|
ENUMRECTS1 clip;
|
|
if (bIntersectRects(&clip.arcl, &pco->rclBounds, prclTrg))
|
|
MemScr_1BPP (psoTrg,
|
|
psoSrc,
|
|
pptlSrc->x + clip.arcl.left - prclTrg->left,
|
|
pptlSrc->y + clip.arcl.top - prclTrg->top,
|
|
&clip.arcl);
|
|
return TRUE;
|
|
}
|
|
|
|
case DC_COMPLEX:
|
|
{
|
|
BOOL bMore;
|
|
ENUMRECTS8 clip;
|
|
UINT iClip;
|
|
PRECTL prcl;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
|
|
|
do
|
|
{
|
|
bMore = CLIPOBJ_bEnum(pco, sizeof(clip), (PVOID) &clip);
|
|
for (iClip = 0; iClip < clip.c; iClip++)
|
|
{
|
|
prcl = &clip.arcl[iClip];
|
|
if (bIntersectRects(prcl, prcl, prclTrg))
|
|
{
|
|
MemScr_1BPP (psoTrg,
|
|
psoSrc,
|
|
pptlSrc->x + prcl->left -
|
|
prclTrg->left,
|
|
pptlSrc->y + prcl->top - prclTrg->top,
|
|
prcl);
|
|
CYCLE_REGS (ppdev);
|
|
}
|
|
}
|
|
} while (bMore);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
switch ( pco->iDComplexity )
|
|
{
|
|
// This is a simple case where the entire Dst rectangle is to
|
|
// be updated.
|
|
|
|
case DC_TRIVIAL:
|
|
(*pHSFunc) (ppdev, psoTrg, psoSrc, pptlSrc, prclTrg, pulXlate);
|
|
return TRUE;
|
|
|
|
// There is only one clip rect.
|
|
|
|
case DC_RECT:
|
|
{
|
|
ENUMRECTS1 clip;
|
|
|
|
if (bIntersectRects(&clip.arcl, &pco->rclBounds, prclTrg))
|
|
{
|
|
POINTL ptlSrc;
|
|
ptlSrc.x = pptlSrc->x + clip.arcl.left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + clip.arcl.top - prclTrg->top;
|
|
(*pHSFunc) (ppdev, psoTrg, psoSrc, &ptlSrc, &clip.arcl, pulXlate);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// There are multiple clip rects.
|
|
// (Do not limit the number of clip rects we'll enumerate.)
|
|
|
|
case DC_COMPLEX:
|
|
{
|
|
BOOL bMore;
|
|
ENUMRECTS8 clip;
|
|
UINT iClip;
|
|
PRECTL prcl;
|
|
POINTL ptlSrc;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
|
|
|
// Call device blt code for each cliprect.
|
|
|
|
do
|
|
{
|
|
// Get list of clip rects.
|
|
|
|
bMore = CLIPOBJ_bEnum(pco, sizeof(clip), (PVOID) &clip);
|
|
|
|
for (iClip = 0; iClip < clip.c; iClip++)
|
|
{
|
|
prcl = &clip.arcl[iClip];
|
|
|
|
// Bound clip rect with Dst rect and update
|
|
// Src start point.
|
|
|
|
if (bIntersectRects(prcl, prcl, prclTrg))
|
|
{
|
|
ptlSrc.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
(*pHSFunc) (ppdev, psoTrg, psoSrc, &ptlSrc, prcl, pulXlate);
|
|
}
|
|
}
|
|
} while (bMore);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* TGA Screen to Host Copy
|
|
****************************************************************************/
|
|
BOOL bScrnToHost (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
PULONG pulXlate,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
ULONG tgarop)
|
|
{
|
|
|
|
SHFUNC pSHFunc; // function permutation to call
|
|
|
|
DISPDBG ((1, "TGA.DLL!bScrnToHost - Entry\n"));
|
|
|
|
// Wait for the TGA to finish processing anything in the command queue
|
|
|
|
TGASYNC (ppdev);
|
|
|
|
// Figure out which routine to use.
|
|
|
|
if (32 == ppdev->ulBitCount)
|
|
pSHFunc = vBitbltSH32to32;
|
|
else
|
|
pSHFunc = vBitbltSH8to8;
|
|
|
|
// Write all bits for a given pixel.
|
|
|
|
TGAPLANEMASK (ppdev, 0xffffffff);
|
|
|
|
// Set the ROP register.
|
|
// Since we punt scr->host copies that involve different
|
|
// source and destination formats, we DON'T have to conditionally
|
|
// set the 'destination bits' of this register.
|
|
|
|
TGAROP (ppdev, ppdev->ulRopTemplate | tgarop);
|
|
|
|
// Call the next level routine as many times as there are
|
|
// clipping objects.
|
|
|
|
switch ( pco->iDComplexity )
|
|
{
|
|
// This is a simple case where the entire Dst rectangle is to
|
|
// be updated.
|
|
|
|
case DC_TRIVIAL:
|
|
(*pSHFunc) (ppdev, psoTrg, psoSrc, pptlSrc, prclTrg, pulXlate);
|
|
return TRUE;
|
|
|
|
// There is only one clip rect.
|
|
|
|
case DC_RECT:
|
|
{
|
|
ENUMRECTS1 clip;
|
|
|
|
if (bIntersectRects(&clip.arcl, &pco->rclBounds, prclTrg))
|
|
{
|
|
POINTL ptlSrc;
|
|
ptlSrc.x = pptlSrc->x + clip.arcl.left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + clip.arcl.top - prclTrg->top;
|
|
(*pSHFunc) (ppdev, psoTrg, psoSrc, &ptlSrc, &clip.arcl, pulXlate);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// There are multiple clip rects.
|
|
// (Do not limit the number of clip rects we'll enumerate.)
|
|
|
|
case DC_COMPLEX:
|
|
{
|
|
BOOL bMore;
|
|
ENUMRECTS8 clip;
|
|
UINT iClip;
|
|
PRECTL prcl;
|
|
POINTL ptlSrc;
|
|
|
|
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, 0);
|
|
|
|
// Call device blt code for each cliprect.
|
|
|
|
do
|
|
{
|
|
// Get list of clip rects.
|
|
|
|
bMore = CLIPOBJ_bEnum(pco, sizeof(clip), (PVOID) &clip);
|
|
|
|
for (iClip = 0; iClip < clip.c; iClip++)
|
|
{
|
|
prcl = &clip.arcl[iClip];
|
|
|
|
// Bound clip rect with Dst rect and update
|
|
// Src start point.
|
|
|
|
if (bIntersectRects(prcl, prcl, prclTrg))
|
|
{
|
|
ptlSrc.x = pptlSrc->x + prcl->left - prclTrg->left;
|
|
ptlSrc.y = pptlSrc->y + prcl->top - prclTrg->top;
|
|
(*pSHFunc) (ppdev, psoTrg, psoSrc, &ptlSrc, prcl, pulXlate);
|
|
}
|
|
}
|
|
} while (bMore);
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* bPuntCopyBits
|
|
****************************************************************************/
|
|
BOOL bPuntCopyBits (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc)
|
|
|
|
{
|
|
|
|
/*
|
|
** No-op punt code if building in the 'model' test environment.
|
|
*/
|
|
#ifdef TEST_ENV
|
|
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
BOOL status;
|
|
BOOL old_bInPuntRoutine;
|
|
SURFOBJ *src, *trg;
|
|
RECTL src_rect;
|
|
|
|
DISPDBG ((1, "TGA.DLL!bPuntCopyBits - Entry\n"));
|
|
|
|
BUMP_TGA_STAT(pStats->copypunts);
|
|
|
|
// Figure out what to use for source and target surfaces
|
|
|
|
if (STYPE_DEVICE == psoTrg->iType)
|
|
trg = ppdev->pPuntSurf;
|
|
else
|
|
trg = psoTrg;
|
|
|
|
if (STYPE_DEVICE == psoSrc->iType)
|
|
{
|
|
src = ppdev->pPuntSurf;
|
|
|
|
src_rect.left = pptlSrc->x;
|
|
src_rect.top = pptlSrc->y;
|
|
src_rect.right = pptlSrc->x + (prclTrg->right - prclTrg->left);
|
|
src_rect.bottom = pptlSrc->y + (prclTrg->bottom - prclTrg->top);
|
|
}
|
|
else
|
|
src = psoSrc;
|
|
|
|
// If we don't have a valid address for PPDEV now, we're in *very*
|
|
// deep kimchee
|
|
|
|
if (NULL == ppdev)
|
|
{
|
|
BUMP_TGA_STAT(pStats->copypunt_reasons.deep_kimchee);
|
|
return FALSE;
|
|
}
|
|
|
|
// Force back to simple mode and wait for memory to flush
|
|
|
|
if (! ppdev->bSimpleMode)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
// Punt the call
|
|
|
|
if (trg != psoTrg)
|
|
PUNT_GET_BITS (ppdev, prclTrg);
|
|
if (src != psoSrc)
|
|
PUNT_GET_BITS (ppdev, &src_rect);
|
|
|
|
old_bInPuntRoutine = ppdev->bInPuntRoutine;
|
|
ppdev->bInPuntRoutine = TRUE;
|
|
|
|
status = EngCopyBits (trg,
|
|
src,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc);
|
|
|
|
ppdev->bInPuntRoutine = old_bInPuntRoutine;
|
|
|
|
if (trg != psoTrg)
|
|
PUNT_PUT_BITS (status, ppdev, prclTrg);
|
|
if (src != psoSrc)
|
|
PUNT_PUT_BITS (status,ppdev, &src_rect);
|
|
|
|
return status;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* bPuntBitBlt
|
|
****************************************************************************/
|
|
BOOL bPuntBitBlt (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
POINTL *pptlMask,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrush,
|
|
ROP4 rop4)
|
|
|
|
{
|
|
|
|
/*
|
|
** No-op punt code if building in the 'model' test environment.
|
|
*/
|
|
#ifdef TEST_ENV
|
|
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
BOOL status;
|
|
BOOL old_bInPuntRoutine;
|
|
SURFOBJ *src, *trg;
|
|
RECTL src_rect;
|
|
|
|
DISPDBG ((1, "TGA.DLL!bPuntBitBlt - Entry, rop4 [%x]\n", rop4));
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunts);
|
|
BUMP_TGA_STAT(pStats->bltpunts_by_rop[rop4 & 0xff]);
|
|
|
|
// Figure out what to use for source and target surfaces
|
|
|
|
if (STYPE_DEVICE == psoTrg->iType)
|
|
{
|
|
trg = ppdev->pPuntSurf;
|
|
}
|
|
else
|
|
trg = psoTrg;
|
|
|
|
if (NULL == psoSrc)
|
|
src = psoSrc;
|
|
else
|
|
if (STYPE_DEVICE == psoSrc->iType)
|
|
{
|
|
src = ppdev->pPuntSurf;
|
|
|
|
src_rect.left = pptlSrc->x;
|
|
src_rect.top = pptlSrc->y;
|
|
src_rect.right = pptlSrc->x + (prclTrg->right - prclTrg->left);
|
|
src_rect.bottom = pptlSrc->y + (prclTrg->bottom - prclTrg->top);
|
|
}
|
|
else
|
|
src = psoSrc;
|
|
|
|
// If we don't have a valid address for PPDEV now, we're in *very*
|
|
// deep kimchee
|
|
|
|
if (NULL == ppdev)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.deep_kimchee);
|
|
return FALSE;
|
|
}
|
|
|
|
// Force back to simple mode and wait for memory to flush
|
|
|
|
if (! ppdev->bSimpleMode)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
// Punt the call
|
|
|
|
if (trg != psoTrg)
|
|
PUNT_GET_BITS (ppdev, prclTrg);
|
|
if (src != psoSrc)
|
|
PUNT_GET_BITS (ppdev, &src_rect);
|
|
|
|
old_bInPuntRoutine = ppdev->bInPuntRoutine;
|
|
ppdev->bInPuntRoutine = TRUE;
|
|
|
|
status = EngBitBlt (trg,
|
|
src,
|
|
psoMask,
|
|
pco,
|
|
pxlo,
|
|
prclTrg,
|
|
pptlSrc,
|
|
pptlMask,
|
|
pbo,
|
|
pptlBrush,
|
|
rop4);
|
|
|
|
ppdev->bInPuntRoutine = old_bInPuntRoutine;
|
|
|
|
if (trg != psoTrg)
|
|
PUNT_PUT_BITS (status, ppdev, prclTrg);
|
|
if (src != psoSrc)
|
|
PUNT_PUT_BITS (status,ppdev, &src_rect);
|
|
|
|
return status;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* DrvSaveScreenBits
|
|
****************************************************************************/
|
|
ULONG DrvSaveScreenBits (SURFOBJ *pso,
|
|
ULONG iMode,
|
|
ULONG iIdent,
|
|
RECTL *prcl)
|
|
|
|
{
|
|
|
|
ULONG ulRet; // return value
|
|
PPDEV ppdev = (PPDEV) pso->dhpdev;
|
|
SURFOBJ soTemp; // source (for restore) or target (for save)
|
|
OffScreen *pOffScreen; // pointer to offscreen structure (for save)
|
|
ULONG height; // height of rectangle
|
|
ULONG stride; // scanline stride of rectangle
|
|
ULONG bytes; // number of bytes to allocate (for save)
|
|
RECTL rclTrg; // target rectangle
|
|
POINTL ptlSrc; // source starting point
|
|
SaveOffScreen *pSave; // temp structure pointer
|
|
SSFUNC pSSFunc; // function permutation to call
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvSaveScreenBits - Entry\n"));
|
|
|
|
// Make sure we're not getting something we don't expect
|
|
|
|
Assert ((NULL != ppdev), "DrvSaveScreenBits - PPDEV == NULL");
|
|
Assert (((SS_SAVE == iMode) || (SS_RESTORE == iMode) || (SS_FREE == iMode)),
|
|
"DrvSaveScreenBits - iMode invalid");
|
|
Assert ((prcl->left >= 0), "DrvSaveScreenBits - prcl->left < 0");
|
|
Assert ((prcl->top >= 0), "DrvSaveScreenBits - prcl->top < 0");
|
|
Assert ((prcl->right >= 0), "DrvSaveScreenBits - prcl->right < 0");
|
|
Assert ((prcl->bottom >= 0), "DrvSaveScreenBits - prcl->bottom < 0");
|
|
Assert ((prcl->right >= prcl->left), "DrvSaveScreenBits - prcl->right < left");
|
|
Assert ((prcl->bottom >= prcl->top), "DrvSaveScreenBits - prcl->bottom < top");
|
|
|
|
// Flush the write buffers before saving/restoring bits
|
|
|
|
WBFLUSH (ppdev);
|
|
TGASYNC (ppdev);
|
|
|
|
// Reset the simple mode flag, so if the next operation punts,
|
|
// TGA will get reset to simple mode as appropriate.
|
|
|
|
ppdev->bSimpleMode = FALSE;
|
|
|
|
// Select the appropriate screen->screen permutation.
|
|
|
|
if (32 == ppdev->ulBitCount)
|
|
pSSFunc = vBitbltSS32to32;
|
|
else
|
|
pSSFunc = vBitbltSS8to8;
|
|
|
|
// Determine which bits to write for a given pixel.
|
|
|
|
TGAPLANEMASK (ppdev, ppdev->ulPlanemaskTemplate);
|
|
|
|
// Set raster operation code and target visual.
|
|
|
|
TGAROP (ppdev, ppdev->ulRopTemplate | TGA_ROP_COPY);
|
|
|
|
// Do the appropriate thing based on iMode passed in
|
|
|
|
switch (iMode)
|
|
{
|
|
// Save the bits to offscreen memory.
|
|
|
|
case SS_SAVE:
|
|
{
|
|
|
|
// Remember height (in pixels) and stride (in bytes).
|
|
|
|
height = prcl->bottom - prcl->top;
|
|
stride = (prcl->right - prcl->left) * SURFOBJ_bytes_per_pixel(pso);
|
|
|
|
// Quadword-align stride.
|
|
//
|
|
// This is necessary due to the alignment requirements of
|
|
// COPY mode and to make the odd and even scan line shift
|
|
// values the same, which allows us to use the TGA*BitbltScrScr
|
|
// routine, which assumes they will be.
|
|
|
|
stride += (8 - (stride & 0x7));
|
|
|
|
// Allocate a SaveOffScreen structure.
|
|
|
|
pSave = (SaveOffScreen *) EngAllocMem (FL_ZERO_MEMORY, sizeof(SaveOffScreen), ALLOC_TAG);
|
|
|
|
if (NULL == pSave)
|
|
{
|
|
ulRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
// Fill in the temp surface object. It will be the target.
|
|
// We need to do this to provide for a different stride
|
|
// and base address for the offscreen memory bitmap.
|
|
|
|
soTemp = *pso;
|
|
soTemp.iType = STYPE_DEVBITMAP;
|
|
soTemp.lDelta = pSave->ulStride = stride;
|
|
|
|
// Construct the target rectangle. Since we're copying to
|
|
// offscreen memory, we'll always copy to an upper left
|
|
// (x,y) of (0,0).
|
|
|
|
rclTrg.left = 0;
|
|
rclTrg.top = 0;
|
|
rclTrg.right = prcl->right - prcl->left;
|
|
rclTrg.bottom = height;
|
|
|
|
// Allocate some offscreen memory for the bits.
|
|
//
|
|
// Add 8 to ensure we have enough as a result of
|
|
// alignment adjustments in the CONJUGATE_* macro.
|
|
//
|
|
// Actually, I don't think we really need to add anything,
|
|
// since we always adjust backwards, i.e. to lower addresses.
|
|
// And those addresses are masked off anyway, and as such
|
|
// are untouched. But I'll keep it in just to be safe.
|
|
|
|
bytes = (height * stride) + 8;
|
|
|
|
pOffScreen = pTgaOffScreenMalloc (ppdev, bytes, 0);
|
|
|
|
if (NULL == pOffScreen)
|
|
{
|
|
ulRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
pSave->pOffScreen = pOffScreen;
|
|
|
|
// Store the offscreen bitmaps address in it's surface object.
|
|
|
|
soTemp.pvScan0 = pOffScreen->addr;
|
|
|
|
// Set the source starting point.
|
|
|
|
ptlSrc.x = prcl->left;
|
|
ptlSrc.y = prcl->top;
|
|
|
|
// Copy bits to offscreen memory.
|
|
|
|
(*pSSFunc) (ppdev, &soTemp, pso, CD_RIGHTDOWN, &ptlSrc, &rclTrg);
|
|
|
|
// Return the pointer to the SaveScreenBits structure. This
|
|
// will be passed in as iIdent to a Restore and/or Free request.
|
|
|
|
ulRet = (ULONG) pSave;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Restore the bits from offscreen memory.
|
|
|
|
case SS_RESTORE:
|
|
{
|
|
|
|
// Fill in the temp surface object. It will be the source.
|
|
// We need to do this to provide for a different stride
|
|
// and base address for the offscreen memory bitmap.
|
|
//
|
|
// Load in the stride and offscreen address from the previously
|
|
// created SaveOffScreen structure.
|
|
|
|
soTemp = *pso;
|
|
soTemp.iType = STYPE_DEVBITMAP;
|
|
soTemp.lDelta = ((SaveOffScreen *) iIdent)->ulStride;
|
|
soTemp.pvScan0 = ((OffScreen *) ((SaveOffScreen *) iIdent)->pOffScreen)->addr;
|
|
|
|
// Set the source starting point.
|
|
|
|
ptlSrc.x = 0x0;
|
|
ptlSrc.y = 0x0;
|
|
|
|
// Copy from offscreen to onscreen.
|
|
|
|
(*pSSFunc) (ppdev, pso, &soTemp, CD_RIGHTDOWN, &ptlSrc, prcl);
|
|
|
|
// Flush write buffers and Sync to make sure the copy is done.
|
|
|
|
WBFLUSH (ppdev);
|
|
TGASYNC (ppdev);
|
|
|
|
// Now that the copy is done, free up the OffScreen memory.
|
|
|
|
vTgaOffScreenFree (ppdev, ((SaveOffScreen *) iIdent)->pOffScreen);
|
|
|
|
// Now, free up the SaveOffScreen structure memory.
|
|
|
|
EngFreeMem ((SaveOffScreen *) iIdent);
|
|
|
|
ulRet = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Free the offscreen memory.
|
|
|
|
case SS_FREE:
|
|
{
|
|
|
|
// First, free up the OffScreen memory.
|
|
|
|
vTgaOffScreenFree (ppdev, ((SaveOffScreen *) iIdent)->pOffScreen);
|
|
|
|
// Now, free up the SaveOffScreen structure memory.
|
|
|
|
EngFreeMem ((SaveOffScreen *) iIdent);
|
|
|
|
ulRet = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
{
|
|
|
|
ulRet = FALSE;
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
// Reset to simple mode, if necessary.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode(ppdev);
|
|
|
|
return ulRet;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* DrvCopyBits
|
|
****************************************************************************/
|
|
BOOL DrvCopyBits (SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc)
|
|
|
|
{
|
|
|
|
PPDEV ppdev = NULL; // display PDEV structure pointer
|
|
ULONG height; // target rectangle height
|
|
PULONG pulXlate; // color xlate table pointer
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Entry\n"));
|
|
|
|
BUMP_TGA_STAT(pStats->copybits);
|
|
|
|
// Fetch PDEV from source or target surface. If we don't find one, scream.
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) ||
|
|
(STYPE_DEVBITMAP == psoTrg->iType) ||
|
|
(NULL == psoSrc))
|
|
ppdev = (PPDEV)psoTrg->dhpdev;
|
|
else
|
|
ppdev = (PPDEV)psoSrc->dhpdev;
|
|
|
|
if (NULL == ppdev)
|
|
{
|
|
BUMP_TGA_STAT(pStats->copypunt_reasons.deep_kimchee);
|
|
return FALSE;
|
|
}
|
|
|
|
height = prclTrg->bottom - prclTrg->top;
|
|
|
|
// Reasons to reject this blit request:
|
|
//
|
|
// a. Height is zero.
|
|
// b. Visual depths not supported.
|
|
// c. Color translation not supported.
|
|
|
|
#ifdef TGA_STATS
|
|
// do all this stuff upfront so we don't make the test
|
|
// below incomprehensible due to conditionals and macros
|
|
|
|
pReason = &pStats->copypunt_reasons;
|
|
if (0 == height)
|
|
{
|
|
BUMP_TGA_STAT(pReason->height_is_zero);
|
|
}
|
|
else if (!(bSupportedBpp(psoSrc, psoTrg, ppdev)))
|
|
{
|
|
BUMP_TGA_STAT(pReason->unsupported_depth);
|
|
// bail out here so we don't doublecount bSupportedBpp stats
|
|
return bPuntCopyBits (ppdev, psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
|
|
}
|
|
else if ((NULL != pxlo) &&
|
|
(!(pxlo->flXlate & XO_TRIVIAL) && !(pxlo->flXlate & XO_TABLE)))
|
|
{
|
|
BUMP_TGA_STAT(pReason->unsupported_xlation);
|
|
}
|
|
#endif
|
|
|
|
if (
|
|
(0 == height) ||
|
|
!(bSupportedBpp(psoSrc, psoTrg, ppdev)) ||
|
|
((NULL != pxlo) &&
|
|
(!(pxlo->flXlate & XO_TRIVIAL) && !(pxlo->flXlate & XO_TABLE)))
|
|
)
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Rejected!!!!!!!!!!!!!!!!!!!\n"));
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - height [%d], pxlo [%x]\n", height, pxlo));
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Screen-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Host-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Screen-Host!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Host-Host?????????????????\n"));
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - TrgItype %d/%s, SrcItype %d/%s\n",
|
|
psoTrg->iType, name_stype(psoTrg->iType), psoSrc->iType, name_stype(psoSrc->iType)));
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - TrgItype %d/%x, SrcItype %d/%x\n",
|
|
psoTrg->iType, psoTrg->iType, psoSrc->iType, psoSrc->iType));
|
|
|
|
return bPuntCopyBits (ppdev, psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - NOT Rejected\n"));
|
|
|
|
// Protect the driver from a potentially NULL clip object.
|
|
// ppdev->pcoTrivial is initialized to be a trivial clipobj.
|
|
|
|
if (NULL == pco)
|
|
pco = ppdev->pcoTrivial;
|
|
|
|
// Check for usage of host->screen express copy code.
|
|
//
|
|
// Criteria:
|
|
// a. Trivial clip object.
|
|
// b. Trivial (or no) color translation object.
|
|
// c. Source and destination formats the same, i.e.
|
|
// no format translation.
|
|
// d. Source is host and destination is screen.
|
|
|
|
if (
|
|
(DC_TRIVIAL == pco->iDComplexity) &&
|
|
((NULL == pxlo) || (XO_TRIVIAL & pxlo->flXlate)) &&
|
|
(SURFOBJ_format(psoSrc) == SURFOBJ_format(psoTrg)) &&
|
|
((psoSrc->iType == STYPE_BITMAP) &&
|
|
((psoTrg->iType == STYPE_DEVICE) || (psoTrg->iType == STYPE_DEVBITMAP)))
|
|
)
|
|
{
|
|
if (8 == ppdev->ulBitCount)
|
|
bHSExpress8to8 (ppdev, psoTrg, psoSrc, prclTrg, pptlSrc, TGA_ROP_COPY);
|
|
else
|
|
bHSExpress32to32 (ppdev, psoTrg, psoSrc, prclTrg, pptlSrc, TGA_ROP_COPY);
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - pxlo %x\n", pxlo));
|
|
|
|
// pulXlate is used in later routines to determine
|
|
// if color translation is required.
|
|
|
|
pulXlate = NULL;
|
|
|
|
// Get the color translation table, if needed.
|
|
|
|
if ( (NULL != pxlo) && (pxlo->flXlate & XO_TABLE) )
|
|
{
|
|
if (NULL == pxlo->pulXlate)
|
|
{
|
|
if (PAL_INDEXED == pxlo->iSrcType)
|
|
pulXlate = XLATEOBJ_piVector(pxlo);
|
|
else
|
|
{
|
|
BUMP_TGA_STAT(pReason->unxlated_color);
|
|
return bPuntCopyBits (ppdev, psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pulXlate = pxlo->pulXlate;
|
|
}
|
|
|
|
if (NULL == pulXlate)
|
|
{
|
|
BUMP_TGA_STAT(pReason->unxlated_color);
|
|
return bPuntCopyBits (ppdev, psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
|
|
}
|
|
}
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Screen-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Host-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - Screen-Host!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((0, "TGA.DLL!DrvCopyBits - Host-Host?????????????????\n"));
|
|
DISPDBG ((0, "TGA.DLL!DrvCopyBits - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((0, "TGA.DLL!DrvCopyBits - TrgItype %d/%s, SrcItype %d/%s\n",
|
|
psoTrg->iType, name_stype(psoTrg->iType), psoSrc->iType, name_stype(psoSrc->iType)));
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((1, "TGA.DLL!DrvCopyBits - TrgItype %d/%x, SrcItype %d/%x\n",
|
|
psoTrg->iType, psoTrg->iType, psoSrc->iType, psoSrc->iType));
|
|
|
|
// Ensure write buffer(s) are flushed
|
|
|
|
WBFLUSH(ppdev);
|
|
|
|
// Reset the simple mode flag, so if the next operation punts
|
|
// it'll flush the buffers and set TGA to simple mode before
|
|
// punting back to GDI.
|
|
|
|
ppdev->bSimpleMode = FALSE;
|
|
|
|
// Branch to the appropriate routine.
|
|
//
|
|
// We can handle:
|
|
// a. onscreen -> onscreen
|
|
// b. onscreen -> offscreen
|
|
// c. onscreen -> host bitmap
|
|
// d. offscreen -> onscreen
|
|
// e. offscreen -> offscreen
|
|
// f. offscreen -> host bitmap
|
|
// g. host bitmap -> onscreen
|
|
// h. host bitmap -> offscreen
|
|
//
|
|
// We do NOT handle host bitmap -> host bitmap.
|
|
|
|
// Target is onscreen or offscreen.
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
{
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
// ** Screen -> Screen
|
|
bScrnToScrn (ppdev, psoTrg, psoSrc, pco,
|
|
prclTrg, pptlSrc, TGA_ROP_COPY);
|
|
else
|
|
// ** Host -> Screen
|
|
bHostToScrn (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, TGA_ROP_COPY);
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Source is on/off screen and Target is host bitmap.
|
|
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
// ** Screen -> Host
|
|
|
|
bScrnToHost (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, TGA_ROP_COPY);
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Safety valve, punt whatever falls through.
|
|
|
|
DISPDBG ((0, "TGA.DLL!DrvCopyBits - REACHED BOTTOM!!!\n"));
|
|
|
|
BUMP_TGA_STAT(pReason->everything_else);
|
|
return bPuntCopyBits (ppdev, psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* bBitBlt
|
|
*
|
|
* We need this routine to assist in handling 'special case' rops.
|
|
* We're not making this an inline routine for use in other places
|
|
* because we're not checking to see if we need to reset TGA to simple
|
|
* mode before returning, which is necessary in all the other places
|
|
* where this code could be used.
|
|
****************************************************************************/
|
|
BOOL bBitBlt (PPDEV ppdev,
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
CLIPOBJ *pco,
|
|
PULONG pulXlate,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
ULONG tgarop)
|
|
|
|
{
|
|
|
|
DISPDBG ((1, "TGA.DLL!bBitBlt - Entry\n"));
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
{
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
// ** Screen -> Screen
|
|
return bScrnToScrn (ppdev, psoTrg, psoSrc, pco,
|
|
prclTrg, pptlSrc, tgarop);
|
|
else
|
|
// ** Host -> Screen
|
|
return bHostToScrn (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, tgarop);
|
|
}
|
|
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
// ** Screen -> Host
|
|
return bScrnToHost (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, tgarop);
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
* DrvBitBlt
|
|
****************************************************************************/
|
|
BOOL DrvBitBlt (SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
SURFOBJ *psoMask,
|
|
CLIPOBJ *pco,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
POINTL *pptlMask,
|
|
BRUSHOBJ *pbo,
|
|
POINTL *pptlBrush,
|
|
ROP4 rop4)
|
|
|
|
{
|
|
|
|
PPDEV ppdev = NULL; // display PDEV structure pointer
|
|
PULONG pulXlate; // color xlate table pointer
|
|
ULONG height; // target rectangle height
|
|
ULONG ulRopF; // incoming rop4 foreground rop
|
|
ULONG ulRopB; // incoming rop4 background rop
|
|
ULONG ulAccelRopBits; // bits from table for a given rop
|
|
ULONG ulFillColor; // color used passed to fill_solid_color
|
|
CLIPOBJ clipobj; // temp clip object, if pco == NULL
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Entry, rop4 [%x]\n", rop4));
|
|
|
|
BUMP_TGA_STAT(pStats->blts);
|
|
BUMP_TGA_STAT(pStats->blts_by_rop[rop4 & 0xff]);
|
|
|
|
// Fetch PDEV from source or target surface.
|
|
// If we don't find one, scream.
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) ||
|
|
(STYPE_DEVBITMAP == psoTrg->iType) ||
|
|
(NULL == psoSrc)
|
|
)
|
|
ppdev = (PPDEV)psoTrg->dhpdev;
|
|
else
|
|
ppdev = (PPDEV)psoSrc->dhpdev;
|
|
|
|
if (NULL == ppdev)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.deep_kimchee);
|
|
return FALSE;
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - ppdev != NULL\n"));
|
|
|
|
// Extract the foreground and background rops from
|
|
// the incoming rop4.
|
|
|
|
ulRopF = (rop4 & 0xff);
|
|
ulRopB = ((rop4 >> 8) & 0xff);
|
|
|
|
// Check for reasons to reject this blit request,
|
|
// based on DrvPaint requirements:
|
|
//
|
|
// a. Foreground and background rops not the same.
|
|
|
|
if (ulRopF != ulRopB)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.foreground_ne_background);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - ROPs Equal, ulRopF %x\n", ulRopF));
|
|
|
|
// If the rop is a NOOP, then return now.
|
|
|
|
if (ulRopF == 0xAA)
|
|
return TRUE;
|
|
|
|
// Remember the bits from the table for the given rop.
|
|
|
|
ulAccelRopBits = ulAccelRops[ulRopF];
|
|
|
|
// Protect the driver from a potentially NULL clip object.
|
|
// We need to load rclBounds for DrvPaint, so use a local
|
|
// clip object.
|
|
|
|
if (NULL == pco)
|
|
{
|
|
pco = &clipobj;
|
|
pco->iDComplexity = DC_TRIVIAL;
|
|
pco->rclBounds = *prclTrg;
|
|
}
|
|
|
|
// Handle simple paint rops here (whiteness, blackness and dstinvert).
|
|
// The 'call solid fill code' bit implies acceleration, so don't have
|
|
// to check the acceleration bit.
|
|
|
|
if (ulAccelRopBits & 0x01000000)
|
|
{
|
|
// Get color to fill with.
|
|
|
|
ulFillColor = ulAccelRopBits & 0x00ff0000;
|
|
|
|
// Duplicate the color over 32 bits.
|
|
// This is not a problem since the solid fill code
|
|
// is only called for whiteness, blackness and dstinvert,
|
|
// with the colors being white, black and black, respectively.
|
|
|
|
ulFillColor |= (ulFillColor << 8);
|
|
ulFillColor |= (ulFillColor >> 16);
|
|
|
|
// Ensure write buffer(s) are flushed
|
|
|
|
WBFLUSH(ppdev);
|
|
|
|
return fill_solid_color (psoTrg, pco, ulFillColor, (ulAccelRopBits & 0xf));
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - NOT fill_solid_color\n"));
|
|
|
|
// Handle rops that use DrvPaint here. The DrvPaint bit
|
|
// being set implies acceleration, so don't have to
|
|
// check acceleration bit.
|
|
//
|
|
// DrvPaint handles write buffer flushing, so don't
|
|
// have to do any of that here.
|
|
|
|
if (ulAccelRopBits & 0x04000000)
|
|
{
|
|
if (DrvPaint (psoTrg, pco, pbo, pptlBrush, ulAccelRopBits))
|
|
return TRUE;
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - NOT handled by paint\n"));
|
|
|
|
// Initialize additional local variables we're using soon.
|
|
|
|
height = prclTrg->bottom - prclTrg->top;
|
|
|
|
// Check for the remaining reasons to reject this blit
|
|
// request:
|
|
//
|
|
// a. Rop4 is not accelerated.
|
|
// b. Visual depths not supported.
|
|
// c. Mask was passed.
|
|
// d. Height is zero.
|
|
// e. Color translation not supported.
|
|
|
|
#ifdef TGA_STATS
|
|
// do all this stuff upfront so we don't make the test
|
|
// below incomprehensible due to conditionals and macros
|
|
|
|
pReason = &pStats->bltpunt_reasons;
|
|
if (!(ulAccelRopBits & 0x08000000))
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.rop4_unaccelerated);
|
|
}
|
|
else if (!(bSupportedBpp(psoSrc, psoTrg, ppdev)))
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unsupported_depth);
|
|
// bail out here so we don't doublecount bSupportedBpp stats
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
else if (NULL != psoMask)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.mask_was_passed);
|
|
}
|
|
else if (0 == height)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.height_is_zero);
|
|
}
|
|
else if ((NULL != pxlo) &&
|
|
(!(pxlo->flXlate & XO_TRIVIAL) && !(pxlo->flXlate & XO_TABLE)))
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unsupported_xlation);
|
|
}
|
|
#endif
|
|
|
|
if (
|
|
!(ulAccelRopBits & 0x08000000) ||
|
|
!(bSupportedBpp(psoSrc, psoTrg, ppdev)) ||
|
|
(NULL != psoMask) ||
|
|
(0 == height) ||
|
|
((NULL != pxlo) &&
|
|
(!(pxlo->flXlate & XO_TRIVIAL) && !(pxlo->flXlate & XO_TABLE)))
|
|
)
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - NOT Rejected\n"));
|
|
|
|
// Check for usage of host->screen express copy code.
|
|
//
|
|
// Criteria:
|
|
// a. Not a special-case rop.
|
|
// b. Trivial clip object.
|
|
// c. Trivial (or no) color translation object.
|
|
// d. Source and destination formats the same, i.e.
|
|
// no format translation.
|
|
// e. Source is host and destination is screen.
|
|
|
|
if (
|
|
!(ulAccelRopBits & 0x02000000) &&
|
|
(DC_TRIVIAL == pco->iDComplexity) &&
|
|
((NULL == pxlo) || (XO_TRIVIAL & pxlo->flXlate)) &&
|
|
((NULL != psoSrc) && (SURFOBJ_format(psoSrc) == SURFOBJ_format(psoTrg))) &&
|
|
((psoSrc->iType == STYPE_BITMAP) &&
|
|
((psoTrg->iType == STYPE_DEVICE) || (psoTrg->iType == STYPE_DEVBITMAP)))
|
|
)
|
|
{
|
|
if (8 == ppdev->ulBitCount)
|
|
bHSExpress8to8 (ppdev, psoTrg, psoSrc, prclTrg, pptlSrc,
|
|
(ulAccelRopBits & 0xff));
|
|
else
|
|
bHSExpress32to32 (ppdev, psoTrg, psoSrc, prclTrg, pptlSrc,
|
|
(ulAccelRopBits & 0xff));
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Not express, pxlo %x\n", pxlo));
|
|
|
|
// pulXlate is used in later routines to determine
|
|
// if color translation is required.
|
|
|
|
pulXlate = NULL;
|
|
|
|
// Get the color translation table, if needed.
|
|
|
|
if ( (NULL != pxlo) && (pxlo->flXlate & XO_TABLE) )
|
|
{
|
|
if (NULL == pxlo->pulXlate)
|
|
{
|
|
if (PAL_INDEXED == pxlo->iSrcType)
|
|
pulXlate = XLATEOBJ_piVector(pxlo);
|
|
else
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unxlated_color);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pulXlate = pxlo->pulXlate;
|
|
}
|
|
if (NULL == pulXlate)
|
|
{
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unxlated_color);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
}
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Screen-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Host-Screen!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Screen-Host!!!!!!!!!!!!!!!!!!!\n"));
|
|
}
|
|
else
|
|
{
|
|
DISPDBG ((0, "TGA.DLL!DrvBitBlt - Host-Host?????????????????\n"));
|
|
DISPDBG ((0, "TGA.DLL!DrvBitBlt - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((0, "TGA.DLL!DrvBitBlt - TrgItype %d/%s, SrcItype %d/%s\n",
|
|
psoTrg->iType, name_stype(psoTrg->iType), psoSrc->iType, name_stype(psoSrc->iType)));
|
|
}
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - STYPE: DEVICE %d, DEVBITMAP %d, BITMAP %d\n",
|
|
STYPE_DEVICE, STYPE_DEVBITMAP, STYPE_BITMAP));
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - TrgItype %d/%x, SrcItype %d/%x\n",
|
|
psoTrg->iType, psoTrg->iType, psoSrc->iType, psoSrc->iType));
|
|
|
|
// Ensure write buffer(s) are flushed
|
|
|
|
WBFLUSH(ppdev);
|
|
|
|
// Reset the simple mode flag, so if we punt it'll flush
|
|
// the buffers and set TGA to simple mode before moving on.
|
|
|
|
ppdev->bSimpleMode = FALSE;
|
|
|
|
// If not a special-case rop, then must be one of the
|
|
// following - scr->scr, host->scr or scr->host.
|
|
|
|
if ( !(ulAccelRopBits & 0x02000000) )
|
|
{
|
|
// Branch to the appropriate routine.
|
|
//
|
|
// We can handle:
|
|
// a. onscreen -> onscreen
|
|
// b. onscreen -> offscreen
|
|
// c. onscreen -> host bitmap
|
|
// d. offscreen -> onscreen
|
|
// e. offscreen -> offscreen
|
|
// f. offscreen -> host bitmap
|
|
// g. host bitmap -> onscreen
|
|
// h. host bitmap -> offscreen
|
|
//
|
|
// We do NOT handle host bitmap -> host bitmap.
|
|
|
|
// Target is onscreen or offscreen.
|
|
|
|
if ((STYPE_DEVICE == psoTrg->iType) || (STYPE_DEVBITMAP == psoTrg->iType))
|
|
{
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
// ** Screen -> Screen
|
|
bScrnToScrn (ppdev, psoTrg, psoSrc, pco,
|
|
prclTrg, pptlSrc, (ulAccelRopBits & 0xff));
|
|
else
|
|
// ** Host -> Screen
|
|
bHostToScrn (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, (ulAccelRopBits & 0xff));
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// Source is on/off screen. Target is host bitmap.
|
|
|
|
if ((STYPE_DEVICE == psoSrc->iType) || (STYPE_DEVBITMAP == psoSrc->iType))
|
|
{
|
|
// ** Screen -> Host
|
|
bScrnToHost (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, (ulAccelRopBits & 0xff));
|
|
|
|
// If GDI called us while punting, then reset TGA.
|
|
|
|
if (ppdev->bInPuntRoutine)
|
|
vSetSimpleMode (ppdev);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.hostbm_to_hostbm);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
// ** SPECIAL CASE ROPS GO HERE
|
|
|
|
DISPDBG ((1, "TGA.DLL!DrvBitBlt - Special ROP [%x]\n", ulRopF));
|
|
|
|
// Handle MERGECOPY (Source AND Pattern) rop
|
|
|
|
if (ulRopF == 0xC0)
|
|
{
|
|
// Blit the 'source' bits to the target rectangle(s)
|
|
|
|
if (bBitBlt (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, TGA_ROP_COPY))
|
|
{
|
|
// Now AND the pattern bits with the 'source' bits that were just
|
|
// copied to the target rectangle(s). If that failed, let NT
|
|
// handle it.
|
|
|
|
if (DrvPaint (psoTrg, pco, pbo, pptlBrush, ulAccelRopBits))
|
|
return TRUE;
|
|
}
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unhandled_mergecopy);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
// Handle B8 (((Pattern XOR Dest) AND Source) XOR Pattern) rop
|
|
|
|
if (ulRopF == 0xB8)
|
|
{
|
|
// Steps:
|
|
// 1. Pattern XOR Destination via DrvPaint.
|
|
// 2. Source AND Destination via Bitblt.
|
|
// 3. Pattern XOR Destination via DrvPaint (again).
|
|
|
|
// No sense XOR'ing the color black, the destination won't change.
|
|
// So, the rop becomes simply (Source AND Destination).
|
|
|
|
if (0x00000000 == pbo->iSolidColor)
|
|
if (bBitBlt (ppdev, psoTrg, psoSrc, pco, pulXlate, prclTrg, pptlSrc, TGA_ROP_AND))
|
|
return TRUE;
|
|
else
|
|
if (DrvPaint (psoTrg, pco, pbo, pptlBrush, ulAccelRopBits))
|
|
if (bBitBlt (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, TGA_ROP_AND))
|
|
if (DrvPaint (psoTrg, pco, pbo, pptlBrush, ulAccelRopBits))
|
|
return TRUE;
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unhandled_B8);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
// Handle FB ((NOT Source OR Pattern) OR Destination) rop - sort of!
|
|
|
|
if (ulRopF == 0xFB)
|
|
{
|
|
// No need OR'ing the color black, it'll have no effect.
|
|
// So, the rop becomes simply (NOT Source OR Destination).
|
|
|
|
if (0x00000000 == pbo->iSolidColor)
|
|
if (bBitBlt (ppdev, psoTrg, psoSrc, pco, pulXlate, prclTrg, pptlSrc, TGA_ROP_OR_INVERTED))
|
|
return TRUE;
|
|
|
|
// Punt otherwise.
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.unhandled_FB);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
}
|
|
|
|
// Handle 69 (NOT ((Source XOR Destination) XOR Pattern)) rop
|
|
|
|
if (ulRopF == 0x69)
|
|
{
|
|
// Steps:
|
|
// 1. Source XOR Destination via bitblt.
|
|
// 2. NOT Pattern XOR Destination via DrvPaint.
|
|
// (NOT'ing the pattern bits will take care of the 'NOT', which is
|
|
// applied to the final destination bits. A nice attribute of XOR.
|
|
// In other words, we don't have to do a seperate destination invert
|
|
// operation at the end, we can roll it into 'pattern xor dest' by
|
|
// making this last operation 'not pattern xor dest').
|
|
|
|
if (bBitBlt (ppdev, psoTrg, psoSrc, pco, pulXlate,
|
|
prclTrg, pptlSrc, TGA_ROP_XOR))
|
|
{
|
|
// Now XOR the pattern bits with the 'source' bits that were just
|
|
// XOR'd with the target rectangle(s). If that failed, let NT
|
|
// handle it.
|
|
|
|
// We could potentially bypass this last operation if we had a
|
|
// straight forward way of telling whether the pattern is a
|
|
// solid color white, since the pattern bits will be inverted
|
|
// and XOR'ing black with the destination has no effect. But
|
|
// I can't think of a simple 'if' statement to check for that,
|
|
// since pbo->iSolidColor = 0xffffffff is an indication of a
|
|
// 'non-solid-color' brush. Arg!
|
|
//
|
|
// Actually, sending in a white pattern in this call doesn't
|
|
// make sense, because as I showed above, it wouldn't have
|
|
// any effect.
|
|
|
|
if (DrvPaint (psoTrg, pco, pbo, pptlBrush, ulAccelRopBits))
|
|
return TRUE;
|
|
}
|
|
|
|
}
|
|
|
|
// Safety valve, punt whatever falls through.
|
|
|
|
DISPDBG ((0, "TGA.DLL!DrvBitBlt - REACHED BOTTOM!!!\n"));
|
|
|
|
BUMP_TGA_STAT(pStats->bltpunt_reasons.everything_else);
|
|
return bPuntBitBlt (ppdev, psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg,
|
|
pptlSrc, pptlMask, pbo, pptlBrush, rop4);
|
|
|
|
}
|