Files
glide/glide3x/h5/glide3/src/glfb.c

2257 lines
70 KiB
C

/*
** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONL
** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGH
** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DF
** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR
** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
**
** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT T
** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS I
** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013
** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FA
** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS O
** THE UNITED STATES.
**
** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVE
**
** $Header$
** $Log$
** Revision 1.7.4.5 2003/06/27 10:40:52 dborca
** added LFB read/write MMX specializations
**
**
** 02/23/03 KoolSmoky - merged with Colourless's sources
** 14 3dfx 1.7.1.2.1.2 10/11/00 Brent Forced check in to enforce
** branching.
** 13 3dfx 1.7.1.2.1.1 08/29/00 Jonny Cochrane Some 8x FSAA code
** 12 3dfx 1.7.1.2.1.0 08/08/00 Andy Hanson Fix in grLfbReadRegion for
** 32 bit surfaces. If 32 bit is forced, and game isn't aware, we could
** overflow the destination buffer now. but it wouldn't look right anyways.
** Will add FX_GLIDE_LFB_OVERFLOW evar if a problem arises.
** 11 3dfx 1.7.1.2 06/20/00 Joseph Kain Fixed errors introduced by
** my previous merge.
** 10 3dfx 1.7.1.1 06/20/00 Joseph Kain Changes to support the
** Napalm Glide open source release. Changes include cleaned up offensive
** comments and new legal headers.
** 9 3dfx 1.7.1.0 06/15/00 Bill White Merged changes to support
** Linux.
**
** 8 3dfx 1.7 03/16/00 Kenneth Dyke Fix for Y origin swapped
** LFB writes.
** 7 3dfx 1.6 03/03/00 Kenneth Dyke Added support for SLI read
** abort workaround.
** 6 3dfx 1.5 03/01/00 Kenneth Dyke Disable dither rotation for
** 3D lfbs.
** 5 3dfx 1.4 03/01/00 Kenneth Dyke Fixed pixelPipe Aux buffer
** writes.
** Fix for OpenGL that requires read/writes strides to be identical.
** Fixed to use dynamic LFB stride value taken from minihwc.
** 4 3dfx 1.3 01/31/00 Kenneth Dyke Fix IS_NAPALM() macro usage
** for PowerPC systems.
** 3 3dfx 1.2 01/31/00 Kenneth Dyke Use new IS_NAPALM() macro
** for MacOS lfb stuff.
** 2 3dfx 1.1 01/31/00 Kenneth Dyke Improved LFB support for
** 32-bit buffers. Added big-endian swizzling support for PowerPC systems.
** Read locks now return pixel format in lfbInfo.
** 1 3dfx 1.0 09/11/99 StarTeam VTS Administrator
**
** 33 7/14/99 9:39a Atai
** direct register write for glide3x
** test04 can do 4 sample aa (2 chips)
**
** 32 7/02/99 4:43p Kcd
** Improved PowerPC lfb support.
**
** 31 6/24/99 7:15p Atai
** 2 buffers per chip
**
** 30 5/26/99 4:40p Kcd
** Fixed minor compiler warning.
**
** 29 5/26/99 4:19p Kcd
** Use new LFB macros and make grLfbReadRegion & grLfbWriteRegion work
** properly for PowerPC.
**
** 28 5/19/99 3:55p Denis
**
** 27 5/19/99 12:45p Denis
** First check in of the TEXTUREBUFFER extension.
** Contains both the texture color buffer and texture aux. buffer
** extensions
** that allows to specify a piece of texture memory as a rendering target
** and/or a piece of texture memory as the aux. buffer.
**
** Probably a non conventional check in, in the sense that the API
** isn't entirely frozen / specified yet. To ease whoever's job it will be
** to complete the extension, I've added a tbext comment
** everywhere I made a modification. These should go away
** once the API is frozen.
**
**
** 26 4/16/99 2:49p Kcd
** Codewarrior warning fixes
**
** 25 4/04/99 8:51p Atai
** Partial check-in for alt-tab issue. set FX_GLIDE_ALT_TAB=1 to build
** glide3x with hwcQueryContext built into GR_BEGIN_NOFIFOCHECK. It works
** with DEBUG glide only. In the non-debug glide, we can still see the
** desktop corruption.
**
** 24 3/24/99 6:17p Peter
** streamlined (made more dangerouse) state validation
**
** 23 3/10/99 6:47p Peter
** need to bump-n-grind in lfb lock too, fixed nested lock error condition
**
** 22 3/08/99 4:28p Mikec
** Made sure when we return raw lfb ptr in a write lock (pix pipe is off),
** the origin is not lower left.
**
** 21 1/25/99 6:33p Peter
** removed some cruft I saw when cleaning up tiled textures
**
** 20 9/10/98 12:40p Mikec
** Changed grLfbLock to be in sync with glide2x.
**
** 19 9/08/98 7:19p Atai
** fix debug info. added underline for internal routines and some \n
**
** 18 9/01/98 9:59a Dow
** Fixed stride bug for 32-bit formats.
**
** 17 8/29/98 12:14p Mikec
** Changed grLfbLock to return the current buffer lfbptr (read ptr) if it
** is writeOnly and 565 and not pixelpipe.
**
** 15 8/11/98 7:22p Atai
** fix grLfbLock read only
**
** 14 7/18/98 1:45p Jdt
** Removed TACO_MEMORY_FIFO_HACK
**
** 13 7/18/98 12:28a Jdt
** Changes to reflect new shadow register structure.
**
** 12 7/16/98 8:18a Jdt
** fxcmd.h
**
** 11 7/01/98 12:41p Jdt
** Moved some code around to do proper flushing for lfb
** accesses
** Protected hacks for Glide/Win ( FX_TACO_MEMORY_FIFO_HACK )
** Moved towards fixing lfb read on Banshee
**
** 10 6/10/98 11:58a Peter
** lfb tiled addressing
**
** 9 4/30/98 5:01p Peter
** first pass glide3 merge
**
** 7 4/22/98 4:57p Peter
** glide2x merge
**
** 6 4/21/98 1:34p Atai
** make 32 bit clean
**
** 5 2/01/98 7:52p Peter
** grLfbWriteRegion byte count problems
**
** 4 1/28/98 2:20p Atai
** fixed lfb state validation
**
** 3 1/22/98 10:35a Atai
** 1. introduce GLIDE_VERSION, g3\glide.h, g3\glideutl.h, g2\glide.h,
** g2\glideutl.h
** 2. fixed grChromaRange, grSstOrigin, and grGetProcAddress
*
* 2 1/16/98 6:44p Atai
* fixed for glide 3 build
*
* 1 1/16/98 4:29p Atai
* create glide 3 src
*
* 58 1/16/98 4:18p Atai
* fixed lfb and grLoadGammaTable
*
* 57 1/06/98 3:53p Atai
* remove grHint, modify grLfbWriteRegion and grGet
*
* 56 12/17/97 4:45p Peter
* groundwork for CrybabyGlide
*
* 55 12/15/97 6:04p Atai
* disable obsolete glide2 api for glide3
*
* 54 12/15/97 5:54p Peter
* swizzle reads too
*
* 53 12/11/97 4:15p Peter
* mac lfb write region
*
* 52 12/01/97 5:18p Peter
* h3 simulator happiness
*
* 51 11/25/97 12:09p Peter
* nested calls to grLfbLock vs init code locking on v2
*
* 50 11/18/97 4:36p Peter
* chipfield stuff cleanup and w/ direct writes
*
* 49 11/17/97 4:55p Peter
* watcom warnings/chipfield stuff
*
* 48 11/06/97 3:38p Dow
* More banshee stuff
*
* 47 11/04/97 5:04p Peter
* cataclysm part deux
*
* 46 11/03/97 3:43p Peter
* h3/cvg cataclysm
*
* 45 10/27/97 11:10a Peter
* starting cleanup
*
* 44 10/09/97 8:02p Dow
* State Monster 1st Cut
*
* 43 10/08/97 5:18p Peter
* fixed grLfbLock wrt writemode_any
*
* 42 10/08/97 11:33a Peter
* hmmmm....
*
* 41 9/30/97 1:03p Peter
* more debugging code
*
* 40 9/25/97 1:35p Peter
* more fixes for csim
*
* 39 9/24/97 4:09p Peter
* lfb/idle fixes
*
* 38 9/24/97 1:31p Peter
* assert if grXX call inside lock/unlock
*
* 37 9/20/97 10:54a Peter
* naked lfb writes
*
* 36 9/15/97 7:31p Peter
* more cmdfifo cleanup, fixed normal buffer clear, banner in the right
* place, lfb's are on, Hmmmm.. probably more
*
* 35 9/10/97 10:13p Peter
* fifo logic from GaryT, non-normalized fp first cut
*
* 34 9/05/97 5:29p Peter
* changes for direct hw
*
* 33 9/04/97 3:32p Peter
* starting grouping serial reg writes
*
* 32 8/18/97 3:52p Peter
* pre-hw arrival fixes/cleanup
*
* 31 7/30/97 2:42p Peter
* more cleanup
*
* 30 7/28/97 2:41p Peter
* turned sli code back on for cvg, but waiting for hal
*
* 29 7/26/97 3:04p Peter
* gratuitous plug is translucent
*
* 28 7/02/97 12:28p Peter
* removed spurious NOP, tex dl
*
* 27 6/26/97 10:14a Peter
* cmd fifo for lfb
*
* 26 6/06/97 10:47a Peter
* texture downloading, fixed 640x480 dimension, changed cvg dep to be the
* same as sst1
*
**
*/
#include <3dfx.h>
#define FX_DLL_DEFINITION
#include <fxdll.h>
#include <glide.h>
#include "fxglide.h"
#include "fxcmd.h"
#ifdef __linux__
#include <lindri.h>
#endif /* defined(__linux__) */
/*---------------------------------------------------------------------------
** MMX specializations
*/
#ifdef __GNUC__
#define MMX_RESET() __asm __volatile ("emms")
#define MMX_SRCLINE(src, dst, length) __asm __volatile ("\n\
movl %2, %%ecx \n\
movl %0, %%esi \n\
movl %1, %%edi \n\
cmpl $8, %%ecx \n\
jb 4f \n\
testl $2, %%esi \n\
jz 1f \n\
movw (%%esi), %%ax \n\
addl $2, %%esi \n\
movw %%ax, (%%edi) \n\
addl $2, %%edi \n\
subl $2, %%ecx \n\
.p2align 3,,7 \n\
1: \n\
testl $4, %%esi \n\
jz 2f \n\
movl (%%esi), %%eax \n\
addl $4, %%esi \n\
movl %%eax, (%%edi) \n\
addl $4, %%edi \n\
subl $4, %%ecx \n\
.p2align 3,,7 \n\
2: \n\
movl %%ecx, %%eax \n\
andl $7, %%ecx \n\
shrl $3, %%eax \n\
jz 4f \n\
.p2align 3,,7 \n\
3: \n\
movq (%%esi), %%mm0 \n\
addl $8, %%esi \n\
movq %%mm0, (%%edi) \n\
addl $8, %%edi \n\
decl %%eax \n\
jnz 3b \n\
.p2align 3,,7 \n\
4: \n\
testl $4, %%ecx \n\
jz 5f \n\
movl (%%esi), %%eax \n\
addl $4, %%esi \n\
movl %%eax, (%%edi) \n\
addl $4, %%edi \n\
.p2align 3,,7 \n\
5: \n\
testl $2, %%ecx \n\
jz 6f \n\
movw (%%esi), %%ax \n\
movw %%ax, (%%edi) \n\
.p2align 3,,7 \n\
6:"::"g"(src), "g"(dst), "g"(length):"%eax", "%ecx", "%esi", "%edi")
#define MMX_DSTLINE2(src, dst, width) __asm __volatile ("\n\
movl %2, %%ecx \n\
movl %0, %%esi \n\
movl %1, %%edi \n\
cmpl $4, %%ecx \n\
jb 4f \n\
testl $2, %%edi \n\
jz 1f \n\
movw (%%esi), %%ax \n\
addl $2, %%esi \n\
movw %%ax, (%%edi) \n\
addl $2, %%edi \n\
decl %%ecx \n\
.p2align 3,,7 \n\
1: \n\
testl $4, %%edi \n\
jz 2f \n\
movl (%%esi), %%eax \n\
addl $4, %%esi \n\
movl %%eax, (%%edi) \n\
addl $4, %%edi \n\
subl $2, %%ecx \n\
.p2align 3,,7 \n\
2: \n\
movl %%ecx, %%eax \n\
andl $3, %%ecx \n\
shrl $2, %%eax \n\
jz 4f \n\
.p2align 3,,7 \n\
3: \n\
movq (%%esi), %%mm0 \n\
addl $8, %%esi \n\
movq %%mm0, (%%edi) \n\
addl $8, %%edi \n\
decl %%eax \n\
jnz 3b \n\
.p2align 3,,7 \n\
4: \n\
testl $2, %%ecx \n\
jz 5f \n\
movl (%%esi), %%eax \n\
addl $4, %%esi \n\
movl %%eax, (%%edi) \n\
addl $4, %%edi \n\
.p2align 3,,7 \n\
5: \n\
testl $1, %%ecx \n\
jz 6f \n\
movw (%%esi), %%ax \n\
movw %%ax, (%%edi) \n\
.p2align 3,,7 \n\
6:"::"g"(src), "g"(dst), "g"(width):"%eax", "%ecx", "%esi", "%edi")
#define MMX_DSTLINE4(src, dst, width) __asm __volatile ("\n\
movl %2, %%ecx \n\
movl %0, %%esi \n\
movl %1, %%edi \n\
cmpl $2, %%ecx \n\
jb 4f \n\
testl $1, %%edi \n\
jz 2f \n\
movl (%%esi), %%eax \n\
addl $4, %%esi \n\
movl %%eax, (%%edi) \n\
addl $4, %%edi \n\
decl %%ecx \n\
.p2align 3,,7 \n\
2: \n\
movl %%ecx, %%eax \n\
andl $1, %%ecx \n\
shrl %%eax \n\
jz 4f \n\
.p2align 3,,7 \n\
3: \n\
movq (%%esi), %%mm0 \n\
addl $8, %%esi \n\
movq %%mm0, (%%edi) \n\
addl $8, %%edi \n\
decl %%eax \n\
jnz 3b \n\
.p2align 3,,7 \n\
4: \n\
testl $1, %%ecx \n\
jz 5f \n\
movl (%%esi), %%eax \n\
movl %%eax, (%%edi) \n\
.p2align 3,,7 \n\
5:"::"g"(src), "g"(dst), "g"(width):"%eax", "%ecx", "%esi", "%edi")
#else
#define MMX_RESET() __asm { emms }
/* Desc: copy one row of pixels
*
* In : length = number of bytes (pixels*bytesperpixel). Must be even (which
* holds true, because we don't support 8bit. Also the existing
* code assumes this, so this won't be a problem.
* src = source buffer
* dst = destination buffer
*
* Note: Aligns src (LFB) before copying. Clobbers eax, ecx, esi, edi
*/
#define MMX_SRCLINE(src, dst, length) __asm {\
__asm mov ecx, length \
__asm mov esi, src \
__asm mov edi, dst \
__asm cmp ecx, 8 \
__asm jb small_move \
__asm test esi, 2 \
__asm jz check4 \
__asm mov ax, [esi] \
__asm add esi, 2 \
__asm mov [edi], ax \
__asm add edi, 2 \
__asm sub ecx, 2 \
__asm align 8 \
__asm check4: \
__asm test esi, 4 \
__asm jz aligned8 \
__asm mov eax, [esi] \
__asm add esi, 4 \
__asm mov [edi], eax \
__asm add edi, 4 \
__asm sub ecx, 4 \
__asm align 8 \
__asm aligned8: \
__asm mov eax, ecx \
__asm and ecx, 7 \
__asm shr eax, 3 \
__asm jz small_move \
__asm align 8 \
__asm big_move: \
__asm movq mm0, [esi] \
__asm add esi, 8 \
__asm movq [edi], mm0 \
__asm add edi, 8 \
__asm dec eax \
__asm jnz big_move \
__asm align 8 \
__asm small_move: \
__asm test ecx, 4 \
__asm jz check2 \
__asm mov eax, [esi] \
__asm add esi, 4 \
__asm mov [edi], eax \
__asm add edi, 4 \
__asm align 8 \
__asm check2: \
__asm test ecx, 2 \
__asm jz finish \
__asm mov ax, [esi] \
__asm mov [edi], ax \
__asm align 8 \
__asm finish: \
}
/* Desc: copy one row of 16bit pixels
*
* In : width = number of pixels
* src = source buffer
* dst = destination buffer
*
* Note: Aligns dst (LFB) before copying. Clobbers eax, ecx, esi, edi
*/
#define MMX_DSTLINE2(src, dst, width) __asm {\
__asm mov ecx, width \
__asm mov esi, src \
__asm mov edi, dst \
__asm cmp ecx, 4 \
__asm jb small_move_mmx_dstline2 \
__asm test edi, 2 \
__asm jz check4_mmx_dstline2 \
__asm mov ax, [esi] \
__asm add esi, 2 \
__asm mov [edi], ax \
__asm add edi, 2 \
__asm dec ecx \
__asm align 8 \
__asm check4_mmx_dstline2: \
__asm test edi, 4 \
__asm jz aligned8_mmx_dstline2 \
__asm mov eax, [esi] \
__asm add esi, 4 \
__asm mov [edi], eax \
__asm add edi, 4 \
__asm sub ecx, 2 \
__asm align 8 \
__asm aligned8_mmx_dstline2: \
__asm mov eax, ecx \
__asm and ecx, 3 \
__asm shr eax, 2 \
__asm jz small_move_mmx_dstline2 \
__asm align 8 \
__asm big_move_mmx_dstline2: \
__asm movq mm0, [esi] \
__asm add esi, 8 \
__asm movq [edi], mm0 \
__asm add edi, 8 \
__asm dec eax \
__asm jnz big_move_mmx_dstline2 \
__asm align 8 \
__asm small_move_mmx_dstline2: \
__asm test ecx, 2 \
__asm jz check2_mmx_dstline2 \
__asm mov eax, [esi] \
__asm add esi, 4 \
__asm mov [edi], eax \
__asm add edi, 4 \
__asm align 8 \
__asm check2_mmx_dstline2: \
__asm test ecx, 1 \
__asm jz finish_mmx_dstline2 \
__asm mov ax, [esi] \
__asm mov [edi], ax \
__asm align 8 \
__asm finish_mmx_dstline2: \
}
/* Desc: copy one row of 32bit pixels
*
* In : width = number of pixels
* src = source buffer
* dst = destination buffer
*
* Note: Aligns dst (LFB) before copying. Clobbers eax, ecx, esi, edi
*/
#define MMX_DSTLINE4(src, dst, width) __asm {\
__asm mov ecx, width \
__asm mov esi, src \
__asm mov edi, dst \
__asm cmp ecx, 2 \
__asm jb small_move_mmx_dstline4 \
__asm test edi, 4 \
__asm jz aligned8_mmx_dstline4 \
__asm mov eax, [esi] \
__asm add esi, 4 \
__asm mov [edi], eax \
__asm add edi, 4 \
__asm dec ecx \
__asm align 8 \
__asm aligned8_mmx_dstline4: \
__asm mov eax, ecx \
__asm and ecx, 1 \
__asm shr eax, 1 \
__asm jz small_move_mmx_dstline4 \
__asm align 8 \
__asm big_move_mmx_dstline4: \
__asm movq mm0, [esi] \
__asm add esi, 8 \
__asm movq [edi], mm0 \
__asm add edi, 8 \
__asm dec eax \
__asm jnz big_move_mmx_dstline4 \
__asm align 8 \
__asm small_move_mmx_dstline4: \
__asm test ecx, 1 \
__asm jz finish_mmx_dstline4 \
__asm mov eax, [esi] \
__asm mov [edi], eax \
__asm align 8 \
__asm finish_mmx_dstline4: \
}
#endif
/*---------------------------------------------------------------------------
** grLfbConstantAlpha
*/
GR_ENTRY(grLfbConstantAlpha, void, (GrAlpha_t alpha))
{
GR_BEGIN_NOFIFOCHECK("grLfbConstantAlpha",82);
GDBG_INFO_MORE(gc->myLevel,"(0x%x)\n",alpha);
gc->state.lfb_constant_alpha = alpha;
GR_END();
} /* grLfbConstantAlpha */
/*---------------------------------------------------------------------------
** grLfbConstantDepth
*/
GR_ENTRY(grLfbConstantDepth, void, (FxU32 depth))
{
GR_BEGIN_NOFIFOCHECK("grLfbConstantDepth",82);
GDBG_INFO_MORE(gc->myLevel,"(0x%x)\n",depth);
gc->state.lfb_constant_depth = depth;
GR_END();
} /* grLfbConstantDepth */
/*-------------------------------------------------------------------
Function: grLfbLock
Date: 2/19
Implementor(s): jdt
Library: Glide
Description:
Secures a pointer to a requested frame buffer and guarantees ordered
access to that buffer.
Arguments:
type - type of lock, one of:
GR_LOCK_WRITE_ONLY
GR_LOCK_READ_ONLY
buffer - which buffer to lock, one of:
GR_BUFFER_FRONTBUFFER
GR_BUFFER_BACKBUFFER
GR_BUFFER_AUXBUFFER
writeMode - desired destination color format
origin - desired lfb origin
pixelPipeline - flag whether to process through pixpipe
info - pointer to info structure
Return:
FXTRUE - lock is successful
FXFALSE - lock fails
-------------------------------------------------------------------*/
#if LFB_DISABLE_SLAVE_FIFO
static FxU32 slaveBaseSize;
#endif
static FxBool _grLfbLock (GrLock_t type, GrBuffer_t buffer,
GrLfbWriteMode_t writeMode, GrOriginLocation_t origin,
FxBool pixelPipeline, GrLfbInfo_t *info)
{
#define FN_NAME "_grLfbLock"
FxBool
rv = FXTRUE;
const FxBool
idleLockP = ((type & GR_LFB_NOIDLE) == 0);
FxBool
noRead = FXFALSE;
FxU32
lfbMode,
zaColor,
fbzMode,
renderMode,
_3dlfb = FXFALSE;
GrLfbWriteMode_t fbMode = 0;
GrLfbWriteMode_t depthMode = 0;
GR_BEGIN_NOFIFOCHECK_RET("_grLfbLock", 82);
GDBG_INFO_MORE(gc->myLevel,"(%d,%d,0x%x)\n", type, buffer, info);
GR_CHECK_COMPATABILITY(FN_NAME, !info,
"Null info structure passed.");
/* there is only one revision extant */
GR_CHECK_COMPATABILITY(FN_NAME, info->size != sizeof(GrLfbInfo_t),
"uninitialized info structure passed.");
type = type & ~(GR_LFB_NOIDLE);
// LFBWOEXP Extension
if (type == GR_LFB_WRITE_ONLY_EXPLICIT_EXT)
{
type = GR_LFB_WRITE_ONLY;
noRead = FXTRUE;
}
/* Pray that no one has made any glide calls that touch the hardware... */
#ifdef FX_GLIDE_NAPALM
if((gc->sliCount > 1) /*&&
(type == GR_LFB_READ_ONLY)*/) {
hwcSLIReadDisable(gc->bInfo);
}
#endif
#if defined(GLIDE3)
_grValidateState();
#endif
/* Load now flushed state */
lfbMode = gc->state.shadow.lfbMode;
fbzMode = gc->state.shadow.fbzMode;
zaColor = gc->state.shadow.zaColor;
type = type & ~(GR_LFB_NOIDLE);
if (gc->lockPtrs[type] != (FxU32)-1) {
GDBG_INFO(83, "Read lock failure due to existing lock");
rv = FXFALSE;
}
if (rv) {
switch(type) {
case GR_LFB_READ_ONLY:
lfbMode &= ~(SST_LFB_READBUFSELECT |
SST_LFB_YORIGIN);
switch(buffer) {
case GR_BUFFER_FRONTBUFFER:
case GR_BUFFER_BACKBUFFER:
/* tbext */
case GR_BUFFER_TEXTUREBUFFER_EXT:
lfbMode |= SST_LFB_READCOLORBUFFER;
break;
case GR_BUFFER_AUXBUFFER:
/* tbext */
case GR_BUFFER_TEXTUREAUXBUFFER_EXT:
lfbMode |= SST_LFB_READDEPTHABUFFER;
break;
default:
GR_CHECK_F(myName,
1,
"illegal buffer parameter passed");
rv = FXFALSE;
break;
}
/* New: Since we now have multiple read formats, we set the
writeFormat in the passed in lfbInfo struct to match
what the actual framebuffer format is. */
{
FxU32 fbMode = 0;
FxU32 depthMode = 0;
switch(gc->grPixelFormat) {
case GR_PIXFMT_ARGB_1555:
case GR_PIXFMT_AA_2_ARGB_1555:
case GR_PIXFMT_AA_4_ARGB_1555:
case GR_PIXFMT_AA_8_ARGB_1555: /* 8xaa */
fbMode = GR_LFBWRITEMODE_1555;
depthMode = GR_LFBWRITEMODE_ZA16;
break;
case GR_PIXFMT_ARGB_8888:
case GR_PIXFMT_AA_2_ARGB_8888:
case GR_PIXFMT_AA_4_ARGB_8888:
case GR_PIXFMT_AA_8_ARGB_8888: /* 8xaa */
fbMode = GR_LFBWRITEMODE_8888;
depthMode = GR_LFBWRITEMODE_Z32;
break;
case GR_PIXFMT_RGB_565:
case GR_PIXFMT_AA_2_RGB_565:
case GR_PIXFMT_AA_4_RGB_565:
case GR_PIXFMT_AA_8_RGB_565: /* 8xaa */
default:
fbMode = GR_LFBWRITEMODE_565;
depthMode = GR_LFBWRITEMODE_ZA16;
break;
}
info->writeMode = (((buffer == GR_BUFFER_AUXBUFFER) || (buffer == GR_BUFFER_TEXTUREAUXBUFFER_EXT))
? depthMode
: fbMode);
}
lfbMode |= (origin ? SST_LFB_YORIGIN : 0);
break;
case GR_LFB_WRITE_ONLY:
/* Set up the constant depth register because it may have
* been trashed by a call to grDepthBiasLevel
* (depthbiaslevel and constant depth use the same register)
*/
zaColor = (((FxU32) gc->state.lfb_constant_depth) << SST_ZACOLOR_DEPTH_SHIFT);
zaColor |= (gc->state.lfb_constant_alpha << SST_ZACOLOR_ALPHA_SHIFT);
/* disable depth biasing */
fbzMode &= ~(SST_ENZBIAS);
lfbMode &= ~(SST_LFB_YORIGIN |
SST_LFB_FORMAT |
SST_LFB_ENPIXPIPE);
#if (GLIDE_PLATFORM & GLIDE_OS_MACOS) && SET_BSWAP
/* For MacOS/PowerPC we always want to enable at least byte swapping,
and for the 16-bit pixel formats we want to enable word swapping as well. */
lfbMode &= ~(SST_LFB_WRITE_BYTESWAP | SST_LFB_WRITE_SWAP16);
lfbMode |= SST_LFB_WRITE_BYTESWAP;
#endif /* (GLIDE_PLATFORM & GLIDE_OS_MACOS) */
switch(writeMode) {
case GR_LFBWRITEMODE_RESERVED1:
case GR_LFBWRITEMODE_RESERVED2:
case GR_LFBWRITEMODE_RESERVED3:
case GR_LFBWRITEMODE_RESERVED4:
case GR_LFBWRITEMODE_RESERVED5:
case GR_LFBWRITEMODE_RESERVED6:
case GR_LFBWRITEMODE_RESERVED7:
rv = FXFALSE;
}
/* Default to hw */
switch(gc->grPixelFormat) {
case GR_PIXFMT_ARGB_1555:
case GR_PIXFMT_AA_2_ARGB_1555:
case GR_PIXFMT_AA_4_ARGB_1555:
case GR_PIXFMT_AA_8_ARGB_1555: /* 8xaa */
fbMode = GR_LFBWRITEMODE_1555;
depthMode = GR_LFBWRITEMODE_ZA16;
break;
case GR_PIXFMT_ARGB_8888:
case GR_PIXFMT_AA_2_ARGB_8888:
case GR_PIXFMT_AA_4_ARGB_8888:
case GR_PIXFMT_AA_8_ARGB_8888: /* 8xaa */
fbMode = GR_LFBWRITEMODE_8888;
depthMode = GR_LFBWRITEMODE_Z32;
break;
case GR_PIXFMT_RGB_565:
case GR_PIXFMT_AA_2_RGB_565:
case GR_PIXFMT_AA_4_RGB_565:
case GR_PIXFMT_AA_8_RGB_565: /* 8xaa */
default:
fbMode = GR_LFBWRITEMODE_565;
depthMode = GR_LFBWRITEMODE_ZA16;
break;
}
if (writeMode == GR_LFBWRITEMODE_ANY) {
writeMode = (((buffer == GR_BUFFER_AUXBUFFER) || (buffer == GR_BUFFER_TEXTUREAUXBUFFER_EXT))
? depthMode
: fbMode);
}
#if (GLIDE_PLATFORM & GLIDE_OS_MACOS) && SET_BSWAP
/* I'd do this in the switch() up above if writeMode wasn't being munged */
switch(writeMode) {
case GR_LFBWRITEMODE_565:
case GR_LFBWRITEMODE_555:
case GR_LFBWRITEMODE_1555:
case GR_LFBWRITEMODE_ZA16:
lfbMode |= SST_LFB_WRITE_SWAP16;
}
#endif /* (GLIDE_PLATFORM & GLIDE_OS_MACOS) */
switch(buffer) {
case GR_BUFFER_FRONTBUFFER:
case GR_BUFFER_BACKBUFFER:
/* tbext */
case GR_BUFFER_TEXTUREBUFFER_EXT:
rv = ((writeMode != GR_LFBWRITEMODE_ZA16) &&
(writeMode != GR_LFBWRITEMODE_Z32));
break;
case GR_BUFFER_AUXBUFFER:
/* tbext */
case GR_BUFFER_TEXTUREAUXBUFFER_EXT:
rv = (writeMode == GR_LFBWRITEMODE_ZA16) ||
(writeMode == GR_LFBWRITEMODE_Z32);
break;
default:
GR_CHECK_F(myName, 1, "illegal buffer parameter passed");
break;
}
lfbMode |= (writeMode << SST_LFB_FORMAT_SHIFT);
lfbMode |= (origin ? SST_LFB_YORIGIN : 0);
if (pixelPipeline) {
lfbMode |= SST_LFB_ENPIXPIPE;
fbzMode &= ~SST_YORIGIN;
fbzMode |= (origin ? SST_YORIGIN : 0);
}
info->writeMode = writeMode;
break;
default:
rv = FXFALSE;
GDBG_INFO(gc->myLevel, "Lock failed because of invalid lock type.");
break;
}
}
if (rv) {
const FxU32
lockCount = gc->cmdTransportInfo.lfbLockCount;
gc->lockPtrs[type] = buffer;
gc->cmdTransportInfo.lfbLockCount = 0x00UL;
/* Setup the hw w/ the settings computed above. */
switch(type) {
case GR_LFB_READ_ONLY:
/* I'm not sure why this is actually doing anything on UMA
* architectures since reads are always done via direct LFB
* accesses anyway, and nothing in this register affects that. -- KCD */
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, lfbMode, lfbMode);
GR_CHECK_SIZE();
break;
case GR_LFB_WRITE_ONLY:
REG_GROUP_BEGIN(BROADCAST_ID, fbzMode, 3, 0x103);
{
REG_GROUP_SET(hw, fbzMode, fbzMode);
REG_GROUP_SET(hw, lfbMode, lfbMode);
REG_GROUP_SET(hw, zaColor, zaColor);
}
REG_GROUP_END();
break;
}
gc->state.shadow.lfbMode = lfbMode;
/* Get the current lfb buffer */
{
/* FixMe: Is this true if we're triple buffering? */
FxU32 colBufferIndex = 0;
switch(buffer) {
case GR_BUFFER_FRONTBUFFER:
colBufferIndex = gc->frontBuffer;
break;
case GR_BUFFER_BACKBUFFER:
colBufferIndex = gc->backBuffer;
break;
case GR_BUFFER_AUXBUFFER:
colBufferIndex = gc->grColBuf;
break;
/* tbext */
case GR_BUFFER_TEXTUREBUFFER_EXT:
if ( gc->textureBuffer.on )
{
} else {
colBufferIndex = gc->backBuffer;
}
break;
case GR_BUFFER_TEXTUREAUXBUFFER_EXT:
if ( gc->textureAuxBuffer.on )
{
} else {
colBufferIndex = gc->grColBuf;
}
break;
default:
GR_CHECK_F(myName, 1, "illegal buffer parameter passed");
rv = FXFALSE;
break;
}
if (rv) {
#ifdef __linux__
if (!colBufferIndex) {
info->strideInBytes = driInfo.stride;
} else {
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
}
#else /* defined(__linux__) */
/*
* This is the default for 3D LFBs,
* which are always 2048 pixels wide.
*/
info->strideInBytes = 0x1000;
#endif /* defined(__linux__) */
info->origin = origin;
/* tbext. Kind of ugly. Kind of duplicate / unfolded code
** needs checking before collapsing
** Something seems really busted here: in the 2 first cases
** (read only and 2d lfb) we return a stride which is the actual
** stride we are setting the registers to (which is a stride in linear space)
** But in the case of 3d lfb, WE HAVE TO RETURN THE ORIGINAL TILED STRIDE
** even though we are setting the registers to the linear one. This means
** the application that makes a grlfblock IS ACTUALLY USING (OR HAS TO USE)
** the tiled stride to be able to access the supposedly LINEAR lfb space...
*/
switch(type) {
case GR_LFB_READ_ONLY:
{
if(( gc->textureBuffer.on ) &&
( buffer == GR_BUFFER_TEXTUREBUFFER_EXT || buffer == GR_BUFFER_TEXTUREAUXBUFFER_EXT )) {
info->lfbPtr = (void *)((FxU32)gc->rawLfb + gc->textureBuffer.addr);
info->strideInBytes = gc->textureBuffer.stride ;
#if __POWERPC__
if(IS_NAPALM(gc->bInfo->pciInfo.deviceID)) {
if(gc->grPixelSize == 2) {
info->lfbPtr = (void *)((FxU32)info->lfbPtr + gc->bInfo->pciInfo.swizzleOffset[3]);
} else {
info->lfbPtr = (void *)((FxU32)info->lfbPtr + gc->bInfo->pciInfo.swizzleOffset[1]);
}
}
#endif
REG_GROUP_BEGIN(BROADCAST_ID, colBufferAddr, 2, 0x3);
REG_GROUP_SET(hw, colBufferAddr, gc->textureBuffer.addr );
REG_GROUP_SET(hw, colBufferStride, gc->textureBuffer.stride );
REG_GROUP_END();
} else {
info->lfbPtr = (void *)gc->lfbBuffers[colBufferIndex];
#if defined(__linux__)
if (colBufferIndex == 0) {
info->strideInBytes = driInfo.stride;
} else {
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
}
#else /* defined(__linux__) */
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
#endif /* defined(__linux__) */
#if __POWERPC__
if(IS_NAPALM(gc->bInfo->pciInfo.deviceID)) {
if(gc->grPixelSize == 2) {
info->lfbPtr = (void *)((FxU32)info->lfbPtr + gc->bInfo->pciInfo.swizzleOffset[3]);
} else {
info->lfbPtr = (void *)((FxU32)info->lfbPtr + gc->bInfo->pciInfo.swizzleOffset[1]);
}
}
#endif
}
}
break;
case GR_LFB_WRITE_ONLY:
{
if(( gc->textureBuffer.on ) &&
( buffer == GR_BUFFER_TEXTUREBUFFER_EXT || buffer == GR_BUFFER_TEXTUREAUXBUFFER_EXT )) {
/* Next, If it is writeOnly and 565 and not pixelpipe,
we just return the current buffer lfbPtr as the write ptr.
This fixes those games that use the lfb write pointer to do
lfb reads. --mikec */
if((writeMode == (FxI32)fbMode) && (!noRead) &&
(!pixelPipeline) &&
/* Origin must be upper left since we will return raw lfb */
(origin != GR_ORIGIN_LOWER_LEFT)){
info->lfbPtr = (void *)((FxU32)gc->rawLfb + gc->textureBuffer.addr);
info->strideInBytes = gc->textureBuffer.stride ;
} else {
#ifdef __linux__
/*
* For Linux, we just return the correct address and
* stride.
*/
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
info->lfbPtr = (void *)gc->lfbBuffers[colBufferIndex];
#else /* defined(__linux__) */
info->lfbPtr = (void *)gc->lfb_ptr;
#endif /* defined(__linux__) */
#ifndef __linux__
switch (writeMode) {
case GR_LFBWRITEMODE_565_DEPTH:
case GR_LFBWRITEMODE_555_DEPTH:
case GR_LFBWRITEMODE_1555_DEPTH:
case GR_LFBWRITEMODE_888:
case GR_LFBWRITEMODE_8888:
case GR_LFBWRITEMODE_Z32:
info->strideInBytes <<= 1;
break;
}
#endif /* defined(__linux__) */
}
REG_GROUP_BEGIN(BROADCAST_ID, colBufferAddr, 2, 0x3);
REG_GROUP_SET(hw, colBufferAddr, gc->textureBuffer.addr );
REG_GROUP_SET(hw, colBufferStride, gc->textureBuffer.stride );
REG_GROUP_END();
} else {
/* Next, If it is writeOnly and 565 (or matches the FB format exactly)
and not pixelpipe, we just return the current buffer lfbPtr as the
write ptr. This fixes those games that use the lfb write pointer to do
lfb reads. --mikec */
/* Note: It also appears that OpenGL depends on this, since they always
* take both a read and write lock, but only save off the stride value
* from the latter one. So if we return different strides OpenGL's lfb
* accesses will be whacked. -- KCD */
if((writeMode == fbMode) && (!noRead) &&
(!pixelPipeline) &&
/* Origin must be upper left since we will return raw lfb */
(origin != GR_ORIGIN_LOWER_LEFT)){
info->lfbPtr = (void *)gc->lfbBuffers[colBufferIndex];
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
gc->state.shadow.colBufferAddr = gc->buffers0[colBufferIndex];
} else {
gc->state.shadow.colBufferAddr = gc->buffers0[colBufferIndex];
/* tbext */
if ( gc->textureBuffer.on ) {
REG_GROUP_BEGIN(BROADCAST_ID, colBufferAddr, 2, 0x3);
REG_GROUP_SET(hw, colBufferAddr, gc->buffers0[colBufferIndex]);
REG_GROUP_SET(hw, colBufferStride,gc->state.shadow.colBufferStride);
REG_GROUP_END();
/* %%KCD - Make sure we don't program the colBufferAddr to point to
* the AUX buffer if the user is trying to do pixel pipe writes to
* the AUX buffer! */
} else if (colBufferIndex < (FxU32)gc->grColBuf) {
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, colBufferAddr, gc->buffers0[colBufferIndex]);
GR_CHECK_SIZE();
}
/* Make sure dither rotation is disabled for 3D LFBs. */
_3dlfb = FXTRUE;
#if defined(__linux__)
/*
* For Linux, we just return the correct address and
* stride.
*/
info->strideInBytes = gc->bInfo->buffInfo.bufLfbStride;
info->lfbPtr = (void *)gc->lfbBuffers[colBufferIndex];
#else /* defined(__linux__) */
info->lfbPtr = (void *)gc->lfb_ptr;
#endif /* defined(__linux__) */
#ifndef __linux__
switch (writeMode) {
case GR_LFBWRITEMODE_565_DEPTH:
case GR_LFBWRITEMODE_555_DEPTH:
case GR_LFBWRITEMODE_1555_DEPTH:
case GR_LFBWRITEMODE_888:
case GR_LFBWRITEMODE_8888:
case GR_LFBWRITEMODE_Z32:
info->strideInBytes <<= 1;
break;
}
#endif /* defined(__linux__) */
}
}
}
break;
default:
{
/* %%KCD - Make sure we don't program the colBufferAddr to point to
* the AUX buffer if the user is trying to do 3D LFB writes to
* the AUX buffer! */
if (colBufferIndex < (FxU32)gc->grColBuf) {
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, colBufferAddr, gc->buffers0[colBufferIndex]);
GR_CHECK_SIZE();
}
_3dlfb = FXTRUE;
info->lfbPtr = (void *)gc->lfb_ptr;
switch (writeMode) {
case GR_LFBWRITEMODE_565_DEPTH:
case GR_LFBWRITEMODE_555_DEPTH:
case GR_LFBWRITEMODE_1555_DEPTH:
case GR_LFBWRITEMODE_888:
case GR_LFBWRITEMODE_8888:
case GR_LFBWRITEMODE_Z32:
info->strideInBytes <<= 1;
break;
}
}
break;
}
#ifdef FX_GLIDE_NAPALM
/* SLI Effage. It seems that in order for flipped LFBs to work right,
* we have to have renderMode set up the same way rendering would want it,
* otherwise bad stuff happens. */
if(IS_NAPALM(gc->bInfo->pciInfo.deviceID)) {
renderMode = gc->state.shadow.renderMode;
fbzMode = gc->state.shadow.fbzMode;
/* See above. */
if(_3dlfb) {
gc->state.shadow.renderMode &= ~SST_RM_DITHER_ROTATION;
}
/* This will screw with some shadow registers, so put them back. */
_grSstOrigin(origin);
gc->state.shadow.renderMode = renderMode;
gc->state.shadow.fbzMode = fbzMode;
}
#endif
if (idleLockP) {
/* This is required to flush the write buffers before the
* actual LFB accesses.
*/
P6FENCE;
/* If we're not using hole counting then we need to make sure that
* any queued commands are actually flushed before checking the fifo
* ptr's location.
*/
if (!gc->cmdTransportInfo.autoBump)
GR_BUMP_N_GRIND;
grFinish();
}
/* Pray that no one makes any glide calls that touch the hardware... */
#ifdef FX_GLIDE_NAPALM
if((gc->sliCount > 1) /*&&
(type == GR_LFB_READ_ONLY)*/) {
hwcSLIReadEnable(gc->bInfo);
}
#endif
#if LFB_DISABLE_SLAVE_FIFO
/* Disable slave command FIFO */
if(gc->chipCount > 1) {
FxU32 depth;
do {
depth = GR_SLAVE_CAGP_GET(0, depth);
} while(depth != 0);
}
slaveBaseSize = GR_SLAVE_CAGP_GET(0, baseSize);
GR_SLAVE_CAGP_SET(0, baseSize, 0);
#endif
/* Increment lock count */
gc->cmdTransportInfo.lfbLockCount = lockCount + 1;
}
}
}
GR_RETURN(rv);
#undef FN_NAME
} /* _grLfbLock */
/* Hack to correct locks of forced 32 bit surfaces */
static FxU16 *forced_32bpp_lock_buffer = 0;
static FxBool grLfbReadRegionOrigin (GrBuffer_t src_buffer, GrOriginLocation_t origin,
FxU32 src_x, FxU32 src_y,
FxU32 src_width, FxU32 src_height,
FxU32 dst_stride, void *dst_data);
GR_ENTRY(grLfbLock, FxBool,(GrLock_t _type, GrBuffer_t buffer,
GrLfbWriteMode_t writeMode, GrOriginLocation_t origin,
FxBool pixelPipeline, GrLfbInfo_t *info))
{
#define FN_NAME "grLfbLock"
FxBool rv = FXTRUE;
FxBool wantHwc;
FxBool forbidden = FXFALSE;
GrLock_t type;
GR_BEGIN_NOFIFOCHECK_RET("grLfbLock", 82);
GDBG_INFO_MORE(gc->myLevel,"(%d,%d,0x%x)\n", _type, buffer, info);
GR_CHECK_COMPATABILITY(FN_NAME, !info,
"Null info structure passed.");
/* there is only one revision extant */
GR_CHECK_COMPATABILITY(FN_NAME, info->size != sizeof(GrLfbInfo_t),
"uninitialized info structure passed.");
type = _type & ~(GR_LFB_NOIDLE);
if (gc->lockPtrs[type] != (FxU32)-1) {
GDBG_INFO(79, "Read lock failure due to existing lock");
return FXFALSE;
}
/* Ok, we will disallow all Hwc reads (regardless of what the app might want) */
/* If we detect that the buffer is being locked far too much (aka a lock every frame) */
if (_GlideRoot.environment.lockCounter > 3)
{
/* Disable HwcAAforLfbRead */
if (_GlideRoot.environment.useHwcAAforLfbRead & 2)
{
_GlideRoot.environment.useHwcAAforLfbRead |= 4;
_GlideRoot.environment.useHwcAAforLfbRead &= ~2;
}
forbidden = FXTRUE;
}
/* Re-allow it if we drop back to 0 */
else if ((_GlideRoot.environment.lockCounter) == -10 && (_GlideRoot.environment.useHwcAAforLfbRead & 4))
{
/* Re-enable HwcAAforLfbRead */
_GlideRoot.environment.useHwcAAforLfbRead |= 2;
_GlideRoot.environment.useHwcAAforLfbRead &= ~4;
forbidden = FXFALSE;
}
/* We want to read using HWC if we using FSAA with 4 chips or want dithering */
/* or we are using forced 32 bit mode and want dithering */
wantHwc = (_GlideRoot.environment.useHwcAAforLfbRead & 2) &&
((gc->state.forced32BPP != 0 && _GlideRoot.environment.ditherHwcAA) ||
(gc->bInfo->h3pixelSample >= 2 && (gc->chipCount == 4 || _GlideRoot.environment.ditherHwcAA)));
/* Incrememt the lockCounter */
if (type == GR_LFB_READ_ONLY) _GlideRoot.environment.lockCounter++;
/* If we are using forced 32 bpp mode, the app is expecting 16 bit data */
/* Or we want to be using HwcAA for the Lfb read lock */
/* We need to use a hack for reading in OpenGL since they do 2 locks. Why, oh why, oh why...*/
if (!forbidden && (gc->state.forced32BPP || wantHwc) &&
(!_GlideRoot.environment.is_opengl || _GlideRoot.environment.oglLfbLockHack) &&
(buffer == GR_BUFFER_FRONTBUFFER || buffer == GR_BUFFER_BACKBUFFER))
{
if (_GlideRoot.environment.is_opengl && type == GR_LFB_WRITE_ONLY && (gc->lockPtrs[GR_LFB_READ_ONLY] == (FxU32)buffer))
{
GDBG_INFO_MORE(82,"OpenGL Locking forced 32bit->16bit hack(%d, %d)\n", _type, buffer);
/* Now set the lock pointer */
gc->lockPtrs[type] = (FxU32) buffer;
/* Setup the info structure */
info->lfbPtr = forced_32bpp_lock_buffer;
info->writeMode = GR_LFBWRITEMODE_565;
info->strideInBytes = gc->state.screen_width * 2;
info->origin = origin;
GDBG_INFO_MORE(82,"OpenGL Locked forced hack (%d, %d)\n", _type, buffer);
return FXTRUE;
}
else if (type == GR_LFB_READ_ONLY)
{
/* Force origin */
/* origin = GR_ORIGIN_UPPER_LEFT; */
/* Just play with the useHwcAAforLfbRead setting to tell the ReadRegion */
/* function what we want to do */
FxU32 old_useHwcAAforLfbRead = _GlideRoot.environment.useHwcAAforLfbRead;
if (wantHwc) _GlideRoot.environment.useHwcAAforLfbRead |= 1;
else _GlideRoot.environment.useHwcAAforLfbRead = 0;
GDBG_INFO_MORE(82,"Locking forced (%d, %d)\n", _type, buffer);
forced_32bpp_lock_buffer = malloc (gc->state.screen_width * gc->state.screen_height * 2);
rv = grLfbReadRegionOrigin(buffer, origin, 0, 0, gc->state.screen_width, gc->state.screen_height, gc->state.screen_width*2, forced_32bpp_lock_buffer);
/* Reset the useHwcAAforLfbRead setting */
_GlideRoot.environment.useHwcAAforLfbRead = old_useHwcAAforLfbRead;
/* Increment the lock counter again */
_GlideRoot.environment.lockCounter++;
/* Failed to read */
if (!rv)
{
free (forced_32bpp_lock_buffer);
return FXFALSE;
}
/* Now set the lock pointer */
gc->lockPtrs[type] = (FxU32) buffer;
/* Setup the info structure */
info->lfbPtr = forced_32bpp_lock_buffer;
info->writeMode = GR_LFBWRITEMODE_565;
info->strideInBytes = gc->state.screen_width * 2;
info->origin = origin;
GDBG_INFO_MORE(82,"Locked forced (%d, %d)\n", _type, buffer);
return FXTRUE;
}
}
GDBG_INFO_MORE(82,"Conventional Lock (%d, %d)\n", _type, buffer);
return _grLfbLock(_type, buffer, writeMode, origin, pixelPipeline, info);
#undef FN_NAME
}
/*-------------------------------------------------------------------
Function: grLfbUnlock
Date: 2/21
Implementor(s): jdt
Library: Glide
Description:
Unlock a previously locked buffer
Arguments:
type - type of lock (read only/write only)
buffer - which buffer to unlock
Return:
FXTRUE - success
FXFALSE - failure
-------------------------------------------------------------------*/
static FxBool _grLfbUnlock (GrLock_t type, GrBuffer_t buffer)
{
#define FN_NAME "_grLfbUnlock"
FxBool rval = FXFALSE;
GR_BEGIN_NOFIFOCHECK_RET("_grLfbUnLock", 83);
GDBG_INFO_MORE(gc->myLevel,"(%d, %d)\n", type, buffer);
type = type & ~(GR_LFB_NOIDLE);
GR_CHECK_COMPATABILITY(FN_NAME,
type != GR_LFB_WRITE_ONLY &&
type != GR_LFB_READ_ONLY,
"Bad type");
/* tbext */
GR_CHECK_COMPATABILITY(FN_NAME,
buffer != GR_BUFFER_FRONTBUFFER &&
buffer != GR_BUFFER_BACKBUFFER &&
buffer != GR_BUFFER_TEXTUREBUFFER_EXT &&
buffer != GR_BUFFER_TEXTUREAUXBUFFER_EXT &&
buffer != GR_BUFFER_AUXBUFFER,
"Bad buffer");
rval = (gc->lockPtrs[type] == (FxU32)buffer);
if (rval) {
const FxU32
lockCount = gc->cmdTransportInfo.lfbLockCount;
/* Clear the current lfb lock state */
gc->cmdTransportInfo.lfbLockCount = 0;
gc->lockPtrs[type] = (FxU32)-1;
#ifdef FX_GLIDE_NAPALM
if((gc->sliCount > 1) /*&&
(type == GR_LFB_READ_ONLY)*/) {
hwcSLIReadDisable(gc->bInfo);
}
#endif
#if LFB_DISABLE_SLAVE_FIFO
/* Enable slave command FIFO */
if(gc->chipCount > 1) {
GR_SLAVE_CAGP_SET(0, baseSize, slaveBaseSize);
}
#endif
/* tbext */
if ( gc->textureBuffer.on ) {
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, colBufferAddr, gc->textureBuffer.addr );
GR_CHECK_SIZE();
if ( buffer != GR_BUFFER_TEXTUREBUFFER_EXT
&& buffer != GR_BUFFER_TEXTUREAUXBUFFER_EXT ) {
/* need to restore the stride also */
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, colBufferStride, gc->textureBuffer.stride );
GR_CHECK_SIZE();
}
} else {
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, colBufferAddr, gc->buffers0[gc->curBuffer]);
GR_CHECK_SIZE();
gc->state.shadow.colBufferAddr = gc->buffers0[gc->curBuffer];
}
if (type == GR_LFB_WRITE_ONLY) {
GR_SET_EXPECTED_SIZE(sizeof(FxU32) << 1, 2);
{
/* Restore depth bias level */
GR_SET(BROADCAST_ID, hw, zaColor, gc->state.shadow.zaColor);
/* turn back on depth biasing */
GR_SET(BROADCAST_ID, hw, fbzMode, gc->state.shadow.fbzMode);
}
GR_CHECK_SIZE();
}
/* Restore dither rotation (and/or Y origin bit) */
if(IS_NAPALM(gc->bInfo->pciInfo.deviceID)) {
GR_SET_EXPECTED_SIZE(sizeof(FxU32), 1);
GR_SET(BROADCAST_ID, hw, renderMode, gc->state.shadow.renderMode);
GR_CHECK_SIZE();
if (gc->sliCount > 1)
_grEnableSliCtrl() ;
}
gc->cmdTransportInfo.lfbLockCount = lockCount - 1;
#ifdef FX_GLIDE_NAPALM
if((gc->sliCount > 1) /*&&
(type == GR_LFB_READ_ONLY)*/) {
if(gc->cmdTransportInfo.lfbLockCount != 0) {
grFinish();
hwcSLIReadEnable(gc->bInfo);
} else {
hwcSLIReadDisable(gc->bInfo);
}
}
#endif
}
GR_RETURN(rval);
#undef FN_NAME
} /* _grLfbUnlock */
/* Hack to correct locks of forced 32 bit surfaces */
GR_ENTRY(grLfbUnlock, FxBool, (GrLock_t _type, GrBuffer_t buffer))
{
#define FN_NAME "grLfbUnlock"
FxBool rval = FXFALSE;
GrLock_t type;
GR_BEGIN_NOFIFOCHECK_RET("grLfbUnLock", 83);
GDBG_INFO_MORE(gc->myLevel,"(%d, %d)\n", _type, buffer);
type = _type & ~(GR_LFB_NOIDLE);
GR_CHECK_COMPATABILITY(FN_NAME,
type != GR_LFB_WRITE_ONLY &&
type != GR_LFB_READ_ONLY,
"Bad type");
/* tbext */
GR_CHECK_COMPATABILITY(FN_NAME,
buffer != GR_BUFFER_FRONTBUFFER &&
buffer != GR_BUFFER_BACKBUFFER &&
buffer != GR_BUFFER_TEXTUREBUFFER_EXT &&
buffer != GR_BUFFER_TEXTUREAUXBUFFER_EXT &&
buffer != GR_BUFFER_AUXBUFFER,
"Bad buffer");
/* If we are using forced 32 bpp mode, the app is expecting 16 bit data */
/* Or we want to be using HwcAA for the Lfb read lock */
/* We need to use a hack for reading in OpenGL since they do 2 locks. Why, oh why, oh why...*/
if ((gc->state.forced32BPP || _GlideRoot.environment.useHwcAAforLfbRead & 2) &&
(!_GlideRoot.environment.is_opengl || _GlideRoot.environment.oglLfbLockHack) &&
(buffer == GR_BUFFER_FRONTBUFFER || buffer == GR_BUFFER_BACKBUFFER))
{
if (_GlideRoot.environment.is_opengl && type == GR_LFB_WRITE_ONLY && (gc->lockPtrs[GR_LFB_READ_ONLY] == (FxU32)buffer))
{
GDBG_INFO_MORE(82,"OpenGL UnLocking forced 32bit->16bit hack(%d, %d)\n", _type, buffer);
// Not this buffer that is locked
if (gc->lockPtrs[type] != (FxU32) buffer) return FXFALSE;
// Set unlocked
gc->lockPtrs[type] = (FxU32) -1;
GDBG_INFO_MORE(82,"OpenGL UnLocked forced hack (%d, %d)\n", _type, buffer);
return FXTRUE;
}
else if (type == GR_LFB_READ_ONLY)
{
GDBG_INFO_MORE(82,"Unlocking forced (%d, %d)\n", _type, buffer);
// Not this buffer that is locked
if (gc->lockPtrs[type] != (FxU32) buffer) return FXFALSE;
// Set unlocked
gc->lockPtrs[type] = (FxU32) -1;
// But, the buffer didn't exist
if (!forced_32bpp_lock_buffer) return FXFALSE;
// Free the buffer
free (forced_32bpp_lock_buffer);
forced_32bpp_lock_buffer = 0;
GDBG_INFO_MORE(82,"Unlocked forced (%d, %d)\n", _type, buffer);
return FXTRUE;
}
}
return _grLfbUnlock(_type, buffer);
#undef FN_NAME
}
#if GLIDE_DEBUG
/*---------------------------------------------------------------------------
** grLfbWriteColorFormat
**
*/
GR_STATE_ENTRY(grLfbWriteColorFormat, void, (GrColorFormat_t colorFormat))
{
#define FN_NAME "_grLfbWriteColorFormat"
FxU32 lfbMode;
GR_BEGIN_NOFIFOCHECK("_grLfbWriteColorFormat",82);
GDBG_INFO_MORE(gc->myLevel,"(%d)\n",colorFormat);
GR_CHECK_F(myName,
colorFormat < 0 || colorFormat > 0x3,
"invalid color format");
lfbMode = gc->state.shadow.lfbMode;
lfbMode &= ~SST_LFB_RGBALANES;
lfbMode |= (colorFormat << SST_LFB_RGBALANES_SHIFT);
gc->state.shadow.lfbMode = lfbMode;
GR_END();
#undef FN_NAME
} /* grLfbWriteColorFormat */
/*---------------------------------------------------------------------------
** grLfbWriteColorSwizzle - set up SST for byte swizzling and word swapping
**
** Registers/Bits Affected:
** lfbMode: bit(11), bit(12)
**
** WARNING: GMT: SST_LFB_WRITE_SWAP16 changes pixel addressing!!!
*/
GR_STATE_ENTRY(grLfbWriteColorSwizzle, void, (FxBool swizzleBytes, FxBool swapWords))
{
#define FN_NAME "_grLfbWriteColorSwizzle"
FxU32 lfbMode;
GR_BEGIN_NOFIFOCHECK("_grLfbWriteColorSwizzle",82);
GDBG_INFO_MORE(gc->myLevel,"(%d,%d)\n",swizzleBytes,swapWords);
/* Clear out the bits we'll set back if appropriate */
lfbMode = gc->state.shadow.lfbMode;
lfbMode &= ~(SST_LFB_WRITE_SWAP16 | SST_LFB_WRITE_BYTESWAP);
if (swizzleBytes)
lfbMode |= SST_LFB_WRITE_BYTESWAP;
if (swapWords)
lfbMode |= SST_LFB_WRITE_SWAP16;
gc->state.shadow.lfbMode = lfbMode;
GR_END();
#undef FN_NAME
} /* grLfbWriteColorSwizzle */
#endif /* GLIDE_DEBUG */
FxBool
_grLfbWriteRegion(FxBool pixPipelineP,
GrBuffer_t dst_buffer, FxU32 dst_x, FxU32 dst_y,
GrLfbSrcFmt_t src_format,
FxU32 src_width, FxU32 src_height,
FxI32 src_stride, const void *src_data)
{
#define FN_NAME "_grLfbWriteRegion"
FxBool rv = FXTRUE;
GrLfbInfo_t info;
GrLfbWriteMode_t writeMode;
GR_BEGIN_NOFIFOCHECK_RET("_grLfbWriteRegion", 82);
GDBG_INFO_MORE(gc->myLevel,
"(0x%x, %s, %d, %d, %d, %d, %d, %d, 0x%x)\n",
dst_buffer,
(pixPipelineP ? "Enable" : "Disable"),
dst_x, dst_y,
src_format, src_width, src_height,
src_stride, src_data);
/* don't waste time */
if (!(src_width && src_height)) {
goto done;
}
writeMode = ((src_format == GR_LFB_SRC_FMT_RLE16)
? GR_LFBWRITEMODE_565
: src_format);
info.size = sizeof(info);
if (_grLfbLock(GR_LFB_WRITE_ONLY_EXPLICIT_EXT,
dst_buffer,
writeMode,
GR_ORIGIN_UPPER_LEFT,
pixPipelineP,
&info)) {
FxU32 *srcData; /* Tracking Source Pointer */
FxU32 *dstData; /* Tracking Destination Pointer */
FxU32 *end; /* Demarks End of each Scanline */
FxI32 srcJump; /* bytes to next scanline */
FxU32 dstJump; /* bytes to next scanline */
FxU32 length; /* bytes to copy in scanline */
FxU32 scanline; /* scanline number */
int aligned; /* word aligned? */
srcData = (FxU32 *) src_data;
dstData = (FxU32 *) (((char*)info.lfbPtr)+ (dst_y*info.strideInBytes));
scanline = src_height;
switch(src_format) {
/* 16-bit aligned */
case GR_LFB_SRC_FMT_565:
case GR_LFB_SRC_FMT_555:
case GR_LFB_SRC_FMT_1555:
case GR_LFB_SRC_FMT_ZA16:
dstData = (FxU32*)(((FxU16*)dstData) + dst_x);
#if 1 /* Hack alert: disable if SET_LFB_16 is not simple assignment */
if (_GlideRoot.CPUType.os_support & _CPU_FEATURE_MMX) {
do {
MMX_DSTLINE2(srcData, dstData, src_width);
/* adjust for next line */
((FxU8 *)srcData) += src_stride;
((FxU8 *)dstData) += info.strideInBytes;
} while (--scanline);
MMX_RESET();
break;
}
#endif
length = src_width * 2;
aligned = !((int)dstData&0x2);
srcJump = src_stride - length;
dstJump = info.strideInBytes - length;
if (aligned) {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
while(srcData < end) {
SET_LFB(dstData[0], srcData[0]);
dstData++;
srcData++;
}
if (((int)length) & 0x2) {
SET_LFB_16((*(FxU16*)&(dstData[0])),
(*(FxU16*)&(srcData[0])));
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
} else {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
SET_LFB_16((*(FxU16*)&(dstData[0])),
(*(FxU16*)&(srcData[0])));
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
while(srcData < end) {
SET_LFB(dstData[0], srcData[0]);
dstData++;
srcData++;
}
if (!(length & 0x2)) {
SET_LFB_16((*(FxU16*)&(dstData[0])),
(*(FxU16*)&(srcData[0])));
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
}
break;
/* 32-bit aligned */
case GR_LFB_SRC_FMT_888:
case GR_LFB_SRC_FMT_8888:
case GR_LFB_SRC_FMT_565_DEPTH:
case GR_LFB_SRC_FMT_555_DEPTH:
case GR_LFB_SRC_FMT_1555_DEPTH:
dstData = ((FxU32*)dstData) + dst_x;
#if 1 /* Hack alert: disable if SET_LFB is not simple assignment */
if (_GlideRoot.CPUType.os_support & _CPU_FEATURE_MMX) {
do {
MMX_DSTLINE4(srcData, dstData, src_width);
/* adjust for next line */
((FxU8 *)srcData) += src_stride;
((FxU8 *)dstData) += info.strideInBytes;
} while (--scanline);
MMX_RESET();
break;
}
#endif
length = src_width * 4;
srcJump = src_stride - length;
dstJump = info.strideInBytes - length;
while(scanline--) {
end = (FxU32*)((char*)srcData + length);
while(srcData < end) {
SET_LFB(dstData[0], srcData[0]);
dstData++;
srcData++;
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
break;
case GR_LFB_SRC_FMT_RLE16:
/* needs to be implemented */
rv = FXFALSE;
break;
}
_grLfbUnlock(GR_LFB_WRITE_ONLY, dst_buffer);
} else {
rv = FXFALSE;
}
done:
GR_RETURN(rv);
#undef FN_NAME
} /* _grLfbWriteRegion */
/*-------------------------------------------------------------------
Function: grLfbWriteRegion
Date: 3/5
Implementor(s): jdt
Library: Glide
Description:
Write a pixel rectangle to the frame buffer as efficiently as possible
Arguments:
dst_buffer - buffer to which to copy data
dst_x,dst_y - destination image start coordinates
src_format - data format of source image
src_width, src_height
- dimensions of source image
src_stride - stride of source image in bytes, not meaningful
for RLE images
src_data - pointer to source data memory
Return:
FXTRUE succeed
FXFALSE fail
-------------------------------------------------------------------*/
#if defined(GLIDE3) && defined(GLIDE3_ALPHA)
GR_ENTRY(grLfbWriteRegion, FxBool, (GrBuffer_t dst_buffer,
FxU32 dst_x, FxU32 dst_y,
GrLfbSrcFmt_t src_format,
FxU32 src_width, FxU32 src_height,
FxBool pixelPipeline,
FxI32 src_stride, void *src_data))
#else
GR_ENTRY(grLfbWriteRegion, FxBool, (GrBuffer_t dst_buffer,
FxU32 dst_x, FxU32 dst_y,
GrLfbSrcFmt_t src_format,
FxU32 src_width, FxU32 src_height,
FxI32 src_stride, void *src_data))
#endif
{
FxBool rv = FXTRUE;
GR_BEGIN_NOFIFOCHECK_RET("grLfbWriteRegion",82);
GDBG_INFO_MORE(gc->myLevel,
"(0x%x,%d,%d,%d,%d,%d,%d,0x%x)\n",
dst_buffer, dst_x, dst_y,
src_format, src_width, src_height,
src_stride, src_data);
#if defined(GLIDE3) && defined(GLIDE3_ALPHA)
if ((_GlideRoot.hwConfig.SSTs[_GlideRoot.current_sst].type == GR_SSTTYPE_SST96) && (pixelPipeline == FXTRUE))
rv = FXFALSE;
else
rv = _grLfbWriteRegion(pixelPipeline, dst_buffer, dst_x, dst_y,
src_format, src_width, src_height,
src_stride, src_data);
#else
rv = _grLfbWriteRegion(FXFALSE, dst_buffer, dst_x, dst_y,
src_format, src_width, src_height,
src_stride, src_data);
#endif
GR_RETURN(rv);
} /* grLfbWriteRegion */
/*-------------------------------------------------------------------
Function: grLfbReadRegion
Date: 3/12
Implementor(s): jdt
Library: Glide
Description:
Grab a rectangle from the frame buffer into user supplied memory
Arguments:
src_buffer - buffer to read from
src_x - x coordinate of upper left corner rectangle to read
src_y - y coordinate of upper left corner of rectangle to read
src_width - width of rectangle to read
src_height - height of rectangle to read
dst_stride - distance between scanlines in destination buffer
dst_data - pointer to user memory in which to place image
Return:
FXTRUE - success
FXFALSE - failure
-------------------------------------------------------------------*/
#if !__POWERPC__
static FxBool grLfbReadRegionOrigin (GrBuffer_t src_buffer, GrOriginLocation_t origin,
FxU32 src_x, FxU32 src_y,
FxU32 src_width, FxU32 src_height,
FxU32 dst_stride, void *dst_data)
{
#define FN_NAME "grLfbReadRegion"
FxU32 bpp;
FxBool rv;
FxBool wantHwc;
GrLfbInfo_t info;
GR_BEGIN_NOFIFOCHECK_RET("grLfbReadRegion",82);
GDBG_INFO_MORE(gc->myLevel,
"(0x%x,%d,%d,%d,%d,%d,0x%x)\n",
src_buffer, src_x, src_y,
src_width, src_height, dst_stride, dst_data);
/* don't waste time */
if (!(src_width && src_height)) {
rv=FXTRUE;
goto done;
}
bpp=gc->bInfo->h3pixelSize;
info.size = sizeof(info);
rv=FXFALSE;
#ifndef __linux__ /* [dBorca] fixme :D */
/* We want to read using HWC if we using FSAA with 4 chips or want dithering */
/* or we are using forced 32 bit mode and want dithering */
wantHwc = (_GlideRoot.environment.useHwcAAforLfbRead & 1) &&
((gc->state.forced32BPP != 0 && _GlideRoot.environment.ditherHwcAA) ||
(gc->bInfo->h3pixelSample >= 2 && (gc->chipCount == 4 || _GlideRoot.environment.ditherHwcAA)));
/* We want to use the 'advanced' and slow capture method */
if (wantHwc)
{
FxU32 colBufferIndex = 0;
FxU32 bpp = 0;
if (gc->state.forced32BPP) bpp = gc->state.forced32BPP;
else switch(gc->grPixelFormat)
{
case GR_PIXFMT_ARGB_1555:
case GR_PIXFMT_AA_2_ARGB_1555:
case GR_PIXFMT_AA_4_ARGB_1555:
case GR_PIXFMT_AA_8_ARGB_1555: /* 8xaa */
bpp = 15;
break;
case GR_PIXFMT_ARGB_8888:
case GR_PIXFMT_AA_2_ARGB_8888:
case GR_PIXFMT_AA_4_ARGB_8888:
case GR_PIXFMT_AA_8_ARGB_8888: /* 8xaa */
bpp = 32;
break;
case GR_PIXFMT_RGB_565:
case GR_PIXFMT_AA_2_RGB_565:
case GR_PIXFMT_AA_4_RGB_565:
case GR_PIXFMT_AA_8_RGB_565: /* 8xaa */
default:
bpp = 16;
break;
}
switch(src_buffer)
{
case GR_BUFFER_FRONTBUFFER:
colBufferIndex = gc->frontBuffer;
break;
case GR_BUFFER_BACKBUFFER:
colBufferIndex = gc->backBuffer;
break;
}
hwcAAReadRegion(gc->bInfo, colBufferIndex, src_x, src_y,
src_width, src_height, dst_stride, dst_data,
bpp, _GlideRoot.environment.ditherHwcAA);
rv=FXTRUE;
goto done;
}
#endif
if (_grLfbLock(GR_LFB_READ_ONLY,
src_buffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT,
FXFALSE,
&info))
{
FxU32 *src,*dst;
FxI32 length, tmplength;
FxU32 src_adjust,dst_adjust,tmp;
src=(FxU32 *) (((char*)info.lfbPtr)+
(src_y*info.strideInBytes) + (src_x * bpp));
length = src_width * bpp;
tmplength = length; /* koolsmoky - MSC inline asm woes */
if (_GlideRoot.CPUType.os_support & _CPU_FEATURE_MMX) {
if (!gc->state.forced32BPP) {
do {
MMX_SRCLINE(src, dst_data, tmplength);
/* adjust for next line */
((FxU8 *)src) += info.strideInBytes;
((FxU8 *)dst_data) += dst_stride;
} while (--src_height);
MMX_RESET();
goto okay;
}
}
dst=dst_data;
/* set length - alignment fix*/
tmp=(((FxU32)src)&2);
length -= tmp;
src_adjust=info.strideInBytes - tmp;
dst_adjust=dst_stride - tmp;
/* should be endian and pixel size safe */
/* it would be nice to test if quad blocks were faster */
/* like mmx loads and stores */
if (!gc->state.forced32BPP) while(src_height--)
{
/* adjust starting alignment */
if (((FxU32)src)&3)
*((FxU16 *)dst)++=*((FxU16 *)src)++;
/* read in dwords of pixels */
if(length)
{
FxU32 byte_index=0;
FxU32 aligned=length&(~3);
/* copies aligned dwords */
do
{
*((FxU32 *)(((FxU32)dst) + byte_index))=*((FxU32 *)(((FxU32)src) + byte_index));
}while((byte_index+=4)<aligned);
/* handle backend misalignment */
if (byte_index!=(FxU32)length)
*((FxU16 *)(((FxU32)dst) + byte_index))=*((FxU16 *)(((FxU32)src) + byte_index));
}
/* adjust for next line */
((FxU8 *)src)+=src_adjust;
((FxU8 *)dst)+=dst_adjust;
}
/* Nice I've got to convert it from 32 bit to 16 bit */
else if (gc->state.forced32BPP == 16) while(src_height--) {
/* read in dwords of pixels */
if(length)
{
FxU32 byte_index=0;
FxU32 byte_index2=0;
/* copies aligned dwords */
do
{
FxU32 s =*((FxU32 *)(((FxU32)src) + byte_index));
FxU16 d = (FxU16) (s & 0xF8) >> 3;
d |= (s & 0xFC00) >> 5;
d |= (s & 0xF80000) >> 8;
*((FxU16 *)(((FxU32)dst) + (byte_index2))) = d;
byte_index +=4;
}while((byte_index2+=2)<(src_width*2));
}
/* adjust for next line */
((FxU8 *)src)+=info.strideInBytes;
((FxU8 *)dst)+=dst_stride;
}
else if (gc->state.forced32BPP == 15) while(src_height--) {
/* read in dwords of pixels */
if(length)
{
FxU32 byte_index=0;
FxU32 byte_index2=0;
/* copies aligned dwords */
do
{
FxU32 s =*((FxU32 *)(((FxU32)src) + byte_index));
FxU16 d = (FxU16) (s & 0xF8) >> 3;
d |= (s & 0xF800) >> 6;
d |= (s & 0xF80000) >> 9;
*((FxU16 *)(((FxU32)dst) + (byte_index2))) = d;
byte_index +=4;
}while((byte_index2+=2)<(src_width*2));
}
/* adjust for next line */
((FxU8 *)src)+=info.strideInBytes;
((FxU8 *)dst)+=dst_stride;
}
okay:
rv=FXTRUE;
/* unlock buffer */
_grLfbUnlock(GR_LFB_READ_ONLY,src_buffer);
}
done:
GR_RETURN(rv);
}
GR_ENTRY(grLfbReadRegion, FxBool, (GrBuffer_t src_buffer,
FxU32 src_x, FxU32 src_y,
FxU32 src_width, FxU32 src_height,
FxU32 dst_stride, void *dst_data))
{
return grLfbReadRegionOrigin(src_buffer, GR_ORIGIN_UPPER_LEFT, src_x, src_y,
src_width, src_height, dst_stride, dst_data);
}
#else /* if __POWERPC__ */
GR_ENTRY(grLfbReadRegion, FxBool, (GrBuffer_t src_buffer,
FxU32 src_x, FxU32 src_y,
FxU32 src_width, FxU32 src_height,
FxU32 dst_stride, void *dst_data))
{
#define FN_NAME "grLfbReadRegion"
FxBool rv = FXTRUE;
GrLfbInfo_t info;
GR_BEGIN_NOFIFOCHECK_RET("grLfbReadRegion",82);
GDBG_INFO_MORE(gc->myLevel,
"(0x%x,%d,%d,%d,%d,%d,0x%x)\n",
src_buffer, src_x, src_y,
src_width, src_height, dst_stride, dst_data);
info.size = sizeof(info);
if (_grLfbLock(GR_LFB_READ_ONLY,
src_buffer,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT,
FXFALSE,
&info)) {
FxU32 *srcData; /* Tracking Source Pointer */
FxU32 *dstData; /* Tracking Destination Pointer */
FxU32 *end; /* Demarks End of each Scanline */
FxU32 srcJump; /* bytes to next scanline */
FxU32 dstJump; /* bytes to next scanline */
FxU32 length; /* bytes to copy in scanline */
FxU32 scanline; /* scanline number */
int aligned; /* word aligned? */
FxU32 odd; /* is src_y odd? (for sli) */
dstData = (FxU32 *) dst_data;
srcData = (FxU32 *) (((char*)info.lfbPtr)+
(src_y*info.strideInBytes) +
(src_x<<1));
scanline = src_height;
length = src_width * 2;
dstJump = dst_stride - length;
srcJump = info.strideInBytes - length;
aligned = !((int)srcData&0x2);
odd = (src_y+src_height) & 0x1;
#if __POWERPC__
if(!(IS_NAPALM(gc->bInfo->pciInfo.deviceID))) {
#endif
if (aligned) {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
while(srcData < end) {
*dstData++ = GET_LFB(*srcData++);
}
if (((int)length) & 0x2) {
(*(FxU16*)dstData) = (FxU16)GET_LFB_16(*srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
} else {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
(*(FxU16*)dstData) = (FxU16)GET_LFB_16(*srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
while(srcData < end) {
*dstData++ = GET_LFB(*srcData++);
}
if (!(((int)length) & 0x2)) {
(*(FxU16*)dstData) = (FxU16)GET_LFB_16(*srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
}
#if __POWERPC__
} else {
if (aligned) {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
while(srcData < end) {
*dstData++ = *srcData++;
}
if (((int)length) & 0x2) {
(*(FxU16*)dstData) = (*(FxU16 *)srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
} else {
while(scanline--) {
end = (FxU32*)((char*)srcData + length - 2);
(*(FxU16*)dstData) = (*(FxU16 *)srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
while(srcData < end) {
*dstData++ = *srcData++;
}
if (!(((int)length) & 0x2)) {
(*(FxU16*)dstData) = (*(FxU16 *)srcData);
dstData = (FxU32*)(((FxU16*)dstData) + 1);
srcData = (FxU32*)(((FxU16*)srcData) + 1);
}
dstData = (FxU32*)(((char*)dstData)+dstJump);
srcData = (FxU32*)(((char*)srcData)+srcJump);
}
}
}
#endif
_grLfbUnlock(GR_LFB_READ_ONLY, src_buffer);
} else {
rv = FXFALSE;
}
GR_RETURN(rv);
#undef FN_NAME
}/* grLfbReadRegion */
#endif /* if __POWERPC__ */