warzone2100/lib/ivis_opengl/rendfunc.c

464 lines
11 KiB
C

/*
This file is part of Warzone 2100.
Copyright (C) 1999-2004 Eidos Interactive
Copyright (C) 2005-2007 Warzone Resurrection Project
Warzone 2100 is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Warzone 2100 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Warzone 2100; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include "lib/ivis_common/rendfunc.h"
#include "lib/ivis_common/rendmode.h"
#include "lib/ivis_common/piepalette.h"
#include "lib/ivis_common/ivispatch.h"
#include "lib/framework/fractions.h"
#include "lib/ivis_common/pieclip.h"
/***************************************************************************/
/*
* Local Variables
*/
/***************************************************************************/
UBYTE aTransTable[256];
UBYTE aTransTable2[256]; // 2 trans tabels so we can have 2 transparancy colours without slowdown.
UBYTE aTransTable3[256]; // 3 trans tabels so we can have 3 transparancy colours without slowdown.
UBYTE aTransTable4[256]; // 4 trans tabels so we can have 4 transparancy colours without slowdown.
/* Set default transparency filter to green pass */
UDWORD transFilter = TRANS_GREY;
//static int g_mode = REND_UNDEFINED;
static IMAGEFILE *MouseImageFile;
static UWORD MouseImageID;
/***************************************************************************/
/*
* Local ProtoTypes
*/
/***************************************************************************/
void iVBlitPixelTransRect(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1);
/* Build a transparency look up table for the interface */
static void pie_BuildTransTable(UDWORD tableNo);
// dummy prototypes for pointer build functions
void (*iV_pBox)(int x0, int y0, int x1, int y1, Uint32 colour);
void (*iV_pBoxFill)(int x0, int y0, int x1, int y1, Uint32 colour);
//*************************************************************************
//*************************************************************************
//*************************************************************************
//*************************************************************************
/***************************************************************************/
/*
* Source
*/
/***************************************************************************/
//*************************************************************************
void SetTransFilter(UDWORD rgb,UDWORD tablenumber)
{
transFilter = rgb;
pie_BuildTransTable(tablenumber); /* Need to recalculate the transparency table */
}
//*************************************************************************
void TransBoxFill(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1)
{
UDWORD *screen;
UDWORD fourPixels;
UDWORD output;
UDWORD width;
UDWORD i,j;
/* Note x1 must be greater than x0 */
width = x1-x0;
/* Not worth it, so use pixel version */
if( (width) < 8)
{
iVBlitPixelTransRect(x0,y0,x1,y1);
}
else
{
/* Get a handle on the current back buffer */
for(i=y0; i<y1; i++)
{
screen = (UDWORD *)(psRendSurface->buffer+psRendSurface->scantable[i] + x0);
/* We need to go through width/4 times */
for (j=x0; j<x1; j+=4)
{
fourPixels = *screen;
output = (UDWORD)aTransTable[(UBYTE)((fourPixels & 0xff000000)>>24)];
output = output<<8;
output = output ^ (UDWORD)aTransTable[(UBYTE)((fourPixels & 0x00ff0000)>>16)];
output = output<<8;
output = output ^ (UDWORD)aTransTable[(UBYTE)((fourPixels & 0x0000ff00)>>8)];
output = output<<8;
output = output ^ (UDWORD)aTransTable[(UBYTE)(fourPixels & 0x000000ff)];
*screen++ = output;
}
}
}
}
//*************************************************************************
void DrawImage(IMAGEFILE *ImageFile,UWORD ID,int x,int y)
{
IMAGEDEF *Image;
iBitmap *Bmp;
UDWORD Modulus;
assert(ID < ImageFile->Header.NumImages);
Image = &ImageFile->ImageDefs[ID];
Modulus = ImageFile->TexturePages[Image->TPageID].width;
Bmp = ImageFile->TexturePages[Image->TPageID].bmp;
Bmp += ((UDWORD)Image->Tu) + ((UDWORD)Image->Tv) * Modulus;
iV_ppBitmap(Bmp,
x+Image->XOffset,y+Image->YOffset,
Image->Width,Image->Height,Modulus);
}
//*************************************************************************
void DrawImageRect(IMAGEFILE *ImageFile,UWORD ID,int x,int y,int x0,int y0,int Width,int Height)
{
UDWORD RepWidth = 1;
UDWORD RepWidthRemain = 0;
UDWORD RepHeight = 1;
UDWORD RepHeightRemain = 0;
BOOL Tiled = FALSE;
UDWORD w,h;
UDWORD tx,ty;
IMAGEDEF *Image;
iBitmap *Bmp;
UDWORD Modulus;
assert(ID < ImageFile->Header.NumImages);
Image = &ImageFile->ImageDefs[ID];
Modulus = ImageFile->TexturePages[Image->TPageID].width;
Bmp = ImageFile->TexturePages[Image->TPageID].bmp;
Bmp += ((UDWORD)Image->Tu) + ((UDWORD)Image->Tv) * Modulus;
if(Width + x0 > Image->Width) {
RepWidth = Width / Image->Width;
RepWidthRemain = Width - RepWidth * Image->Width;
Width = Image->Width;
Tiled = TRUE;
}
if(Height+ y0 > Image->Height) {
RepHeight = Height / Image->Height;
RepHeightRemain = Height - RepHeight * Image->Height;
Height = Image->Height;
Tiled = TRUE;
}
if(Tiled) {
ty = y;
for(h=0; h<RepHeight; h++) {
tx = x;
for(w=0; w<RepWidth; w++) {
iV_ppBitmap(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
Width,Height,Modulus);
tx += Width;
}
if(RepWidthRemain) {
iV_ppBitmap(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
RepWidthRemain,Height,Modulus);
}
ty += Height;
}
if(RepHeightRemain) {
tx = x;
for(w=0; w<RepWidth; w++) {
iV_ppBitmap(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
Width,RepHeightRemain,Modulus);
tx += Width;
}
if(RepWidthRemain) {
iV_ppBitmap(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
RepWidthRemain,RepHeightRemain,Modulus);
}
}
} else {
iV_ppBitmap(Bmp,
x+Image->XOffset,y+Image->YOffset,
Width,Height,Modulus);
}
}
//*************************************************************************
void DrawTransImage(IMAGEFILE *ImageFile,UWORD ID,int x,int y)
{
IMAGEDEF *Image;
iBitmap *Bmp;
UDWORD Modulus;
assert(ID < ImageFile->Header.NumImages);
Image = &ImageFile->ImageDefs[ID];
Modulus = ImageFile->TexturePages[Image->TPageID].width;
Bmp = ImageFile->TexturePages[Image->TPageID].bmp;
Bmp += ((UDWORD)Image->Tu) + ((UDWORD)Image->Tv) * Modulus;
iV_ppBitmapTrans(Bmp,x+Image->XOffset,y+Image->YOffset,
Image->Width,Image->Height,Modulus);
}
//*************************************************************************
void DrawTransImageRect(IMAGEFILE *ImageFile,UWORD ID,int x,int y,int x0,int y0,int Width,int Height)
{
UDWORD RepWidth = 1;
UDWORD RepWidthRemain = 0;
UDWORD RepHeight = 1;
UDWORD RepHeightRemain = 0;
BOOL Tiled = FALSE;
UDWORD w,h;
UDWORD tx,ty;
IMAGEDEF *Image;
iBitmap *Bmp;
UDWORD Modulus;
assert(ID < ImageFile->Header.NumImages);
Image = &ImageFile->ImageDefs[ID];
Modulus = ImageFile->TexturePages[Image->TPageID].width;
Bmp = ImageFile->TexturePages[Image->TPageID].bmp;
Bmp += ((UDWORD)Image->Tu) + ((UDWORD)Image->Tv) * Modulus;
if(Width + x0 > Image->Width) {
RepWidth = Width / Image->Width;
RepWidthRemain = Width - RepWidth * Image->Width;
Width = Image->Width;
Tiled = TRUE;
}
if(Height+ y0 > Image->Height) {
RepHeight = Height / Image->Height;
RepHeightRemain = Height - RepHeight * Image->Height;
Height = Image->Height;
Tiled = TRUE;
}
if(Tiled) {
ty = y;
for(h=0; h<RepHeight; h++) {
tx = x;
for(w=0; w<RepWidth; w++) {
iV_ppBitmapTrans(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
Width,Height,Modulus);
tx += Width;
}
if(RepWidthRemain) {
iV_ppBitmapTrans(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
RepWidthRemain,Height,Modulus);
}
ty += Height;
}
if(RepHeightRemain) {
tx = x;
for(w=0; w<RepWidth; w++) {
iV_ppBitmapTrans(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
Width,RepHeightRemain,Modulus);
tx += Width;
}
if(RepWidthRemain) {
iV_ppBitmapTrans(Bmp,
tx+Image->XOffset,ty+Image->YOffset,
RepWidthRemain,RepHeightRemain,Modulus);
}
}
} else {
iV_ppBitmapTrans(Bmp,
x+Image->XOffset,y+Image->YOffset,
Width,Height,Modulus);
}
}
//*************************************************************************
void iV_SetMousePointer(IMAGEFILE *ImageFile,UWORD ImageID)
{
ASSERT( ImageID < ImageFile->Header.NumImages,"iV_SetMousePointer : Invalid image id" );
MouseImageFile = ImageFile;
MouseImageID = ImageID;
}
UDWORD iV_GetMouseFrame(void)
{
return MouseImageID;
}
void iV_DrawMousePointer(int x,int y)
{
iV_DrawImage(MouseImageFile,MouseImageID,x,y);
}
//*************************************************************************
//
// local functions
//
//*************************************************************************
void iVBlitPixelTransRect(UDWORD x0, UDWORD y0, UDWORD x1, UDWORD y1)
{
UBYTE *screen;
UBYTE present;
UDWORD i,j;
/* Do a horizontal strip at a time. We're going x inside y to take advantage of the scan table */
for (i=y0; i<y1; i++)
{
/* Get this outside loop cos it's invariant to each scan line */
screen = (UBYTE *)psRendSurface->buffer + psRendSurface->scantable[i] + x0;
for(j=x0; j<x1; j++)
{
/* What colour is there at the moment? */
present = *screen;
/* Write in the new improved greener version */
*screen++ = aTransTable[present];
}
}
}
//*************************************************************************
static void pie_BuildTransTable(UDWORD tableNo)
{
UDWORD i;
UBYTE red = 0, green = 0, blue = 0;
iColour* psPalette = pie_GetGamePal();
// Step through all the palette entries for the currently selected iVPALETTE
for(i=0; i<256; i++)
{
switch (transFilter)
{
case TINT_BLUE:
red = (psPalette[i].r * 5) / 8;
blue = (psPalette[i].b * 7) / 8;
green = (psPalette[i].g * 5) / 8;
break;
case TINT_DEEPBLUE:
red = (psPalette[i].r * 3) / 8;
blue = (psPalette[i].b * 5) / 8;
green = (psPalette[i].g * 3) / 8;
break;
case TRANS_GREY:
red = psPalette[i].r/2;
blue = psPalette[i].b/2;
green = psPalette[i].g/2;
break;
case TRANS_BLUE:
red = psPalette[i].r/2;
blue = psPalette[i].b;
green = psPalette[i].g/2;
break;
case TRANS_BRITE:
if( ((UDWORD)psPalette[i].r) + 50 >255)
{
red = 255;
}
else
{
red = (psPalette[i].r+50);
}
if( ((UDWORD)psPalette[i].b) + 50 >255)
{
blue = 255;
}
else
{
blue = (psPalette[i].b+50);
}
if( ((UDWORD)psPalette[i].g)+50 >255)
{
green = 255;
}
else
{
green = (psPalette[i].g+50);
}
break;
default:
ASSERT( FALSE,"Invalid transparency filter selection" );
break;
}
if(tableNo == 0)
{
aTransTable[i] = pal_GetNearestColour(red,green,blue);
}
else if(tableNo == 1)
{
aTransTable2[i] = pal_GetNearestColour(red,green,blue);
}
else if(tableNo == 2)
{
aTransTable3[i] = pal_GetNearestColour(red,green,blue);
}
else
{
aTransTable4[i] = pal_GetNearestColour(red,green,blue);
}
}
}