428 lines
8.6 KiB
428 lines
8.6 KiB
/* |
|
gl_draw.c - orthogonal drawing stuff |
|
Copyright (C) 2010 Uncle Mike |
|
|
|
This program 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 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program 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. |
|
*/ |
|
|
|
#include "r_local.h" |
|
|
|
/* |
|
============= |
|
R_GetImageParms |
|
============= |
|
*/ |
|
void R_GetTextureParms( int *w, int *h, int texnum ) |
|
{ |
|
image_t *glt; |
|
|
|
glt = R_GetTexture( texnum ); |
|
if( w ) *w = glt->srcWidth; |
|
if( h ) *h = glt->srcHeight; |
|
} |
|
|
|
/* |
|
============= |
|
R_GetSpriteParms |
|
|
|
same as GetImageParms but used |
|
for sprite models |
|
============= |
|
*/ |
|
void GAME_EXPORT R_GetSpriteParms( int *frameWidth, int *frameHeight, int *numFrames, int currentFrame, const model_t *pSprite ) |
|
{ |
|
mspriteframe_t *pFrame; |
|
|
|
if( !pSprite || pSprite->type != mod_sprite ) return; // bad model ? |
|
pFrame = R_GetSpriteFrame( pSprite, currentFrame, 0.0f ); |
|
|
|
if( frameWidth ) *frameWidth = pFrame->width; |
|
if( frameHeight ) *frameHeight = pFrame->height; |
|
if( numFrames ) *numFrames = pSprite->numframes; |
|
} |
|
|
|
int GAME_EXPORT R_GetSpriteTexture( const model_t *m_pSpriteModel, int frame ) |
|
{ |
|
if( !m_pSpriteModel || m_pSpriteModel->type != mod_sprite || !m_pSpriteModel->cache.data ) |
|
return 0; |
|
|
|
return R_GetSpriteFrame( m_pSpriteModel, frame, 0.0f )->gl_texturenum; |
|
} |
|
|
|
|
|
/* |
|
============= |
|
Draw_StretchPicImplementation |
|
============= |
|
*/ |
|
void R_DrawStretchPicImplementation( int x, int y, int w, int h, int s1, int t1, int s2, int t2, image_t *pic ) |
|
{ |
|
pixel_t *source, *dest; |
|
unsigned int v, u, sv; |
|
unsigned int height; |
|
unsigned int f, fstep; |
|
int skip; |
|
qboolean transparent = false; |
|
pixel_t *buffer; |
|
|
|
if( x < 0 ) |
|
{ |
|
s1 += (-x)*(s2-s1) / w; |
|
x = 0; |
|
} |
|
if( x + w > vid.width ) |
|
{ |
|
s2 -= (x + w - vid.width) * (s2 - s1)/ w ; |
|
w = vid.width - x; |
|
} |
|
if( y + h > vid.height ) |
|
{ |
|
t2 -= (y + h - vid.height) * (t2 - t1) / h; |
|
h = vid.height - y; |
|
} |
|
|
|
if( !pic->pixels[0] || s1 >= s2 || t1 >= t2 ) |
|
return; |
|
|
|
//gEngfuncs.Con_Printf ("pixels is %p\n", pic->pixels[0] ); |
|
|
|
height = h; |
|
if (y < 0) |
|
{ |
|
skip = -y; |
|
height += y; |
|
y = 0; |
|
} |
|
else |
|
skip = 0; |
|
|
|
dest = vid.buffer + y * vid.rowbytes + x; |
|
|
|
if( pic->alpha_pixels ) |
|
{ |
|
buffer = pic->alpha_pixels; |
|
transparent = true; |
|
} |
|
else |
|
buffer = pic->pixels[0]; |
|
|
|
|
|
#pragma omp parallel for schedule(static) |
|
for (v=0 ; v<height ; v++) |
|
{ |
|
int alpha1 = vid.alpha; |
|
#ifdef _OPENMP |
|
pixel_t *dest = vid.buffer + (y + v) * vid.rowbytes + x; |
|
#endif |
|
sv = (skip + v)*(t2-t1)/h + t1; |
|
source = buffer + sv*pic->width + s1; |
|
|
|
{ |
|
f = 0; |
|
fstep = ((s2-s1) << 16)/w; |
|
|
|
#if 0 |
|
for (u=0 ; u<w ; u+=4) |
|
{ |
|
dest[u] = source[f>>16]; |
|
f += fstep; |
|
dest[u+1] = source[f>>16]; |
|
f += fstep; |
|
dest[u+2] = source[f>>16]; |
|
f += fstep; |
|
dest[u+3] = source[f>>16]; |
|
f += fstep; |
|
} |
|
#else |
|
for (u=0 ; u<w ; u++) |
|
{ |
|
pixel_t src = source[f>>16]; |
|
int alpha = alpha1; |
|
f += fstep; |
|
|
|
if( transparent ) |
|
{ |
|
alpha &= src >> ( 16 - 3 ); |
|
src = src << 3; |
|
} |
|
|
|
if( alpha == 0 ) |
|
continue; |
|
|
|
if( vid.color != COLOR_WHITE ) |
|
src = vid.modmap[(src & 0xff00)|(vid.color>>8)] << 8 | (src & vid.color & 0xff) | ((src & 0xff) >> 3); |
|
|
|
if( vid.rendermode == kRenderTransAdd) |
|
{ |
|
pixel_t screen = dest[u]; |
|
dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); |
|
} |
|
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) |
|
{ |
|
pixel_t screen = dest[u]; // | 0xff & screen & src ; |
|
dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); |
|
|
|
} |
|
else |
|
dest[u] = src; |
|
|
|
} |
|
#endif |
|
} |
|
dest += vid.rowbytes; |
|
} |
|
} |
|
|
|
|
|
/* |
|
============= |
|
R_DrawStretchPic |
|
============= |
|
*/ |
|
void GAME_EXPORT R_DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, int texnum ) |
|
{ |
|
image_t *pic = R_GetTexture(texnum); |
|
int width = pic->width, height = pic->height; |
|
// GL_Bind( XASH_TEXTURE0, texnum ); |
|
if( s2 > 1.0f || t2 > 1.0f ) |
|
return; |
|
if( s1 < 0.0f || t1 < 0.0f ) |
|
return; |
|
if( w < 1.0f || h < 1.0f ) |
|
return; |
|
R_DrawStretchPicImplementation(x,y,w,h, width * s1, height * t1, width * s2, height * t2, pic); |
|
} |
|
|
|
void Draw_Fill (int x, int y, int w, int h) |
|
{ |
|
pixel_t *dest; |
|
unsigned int v, u; |
|
unsigned int height; |
|
int skip; |
|
pixel_t src = vid.color; |
|
int alpha = vid.alpha; |
|
|
|
if( x < 0 ) |
|
x = 0; |
|
|
|
if( x + w > vid.width ) |
|
w = vid.width - x; |
|
|
|
if( w <= 0 ) |
|
return; |
|
|
|
if( y + h > vid.height ) |
|
h = vid.height - y; |
|
|
|
if( h <= 0 ) |
|
return; |
|
|
|
height = h; |
|
if( y < 0 ) |
|
{ |
|
if( h <= -y ) |
|
return; |
|
skip = -y; |
|
height += y; |
|
y = 0; |
|
} |
|
else |
|
skip = 0; |
|
|
|
dest = vid.buffer + y * vid.rowbytes + x; |
|
|
|
#pragma omp parallel for schedule(static) |
|
for (v=0 ; v<height ; v++) |
|
{ |
|
#ifdef _OPENMP |
|
pixel_t *dest = vid.buffer + (y + v) * vid.rowbytes + x; |
|
#endif |
|
|
|
{ |
|
|
|
#if 0 |
|
for (u=0 ; u<w ; u+=4) |
|
{ |
|
dest[u] = source[f>>16]; |
|
f += fstep; |
|
dest[u+1] = source[f>>16]; |
|
f += fstep; |
|
dest[u+2] = source[f>>16]; |
|
f += fstep; |
|
dest[u+3] = source[f>>16]; |
|
f += fstep; |
|
} |
|
#else |
|
for (u=0 ; u<w ; u++) |
|
{ |
|
if( alpha == 0 ) |
|
continue; |
|
|
|
if( vid.rendermode == kRenderTransAdd) |
|
{ |
|
pixel_t screen = dest[u]; |
|
dest[u] = vid.addmap[(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) | ((src & 0xff) >> 0); |
|
} |
|
else if( alpha < 7) // && (vid.rendermode == kRenderTransAlpha || vid.rendermode == kRenderTransTexture ) ) |
|
{ |
|
pixel_t screen = dest[u]; // | 0xff & screen & src ; |
|
dest[u] = BLEND_ALPHA( alpha, src, screen);//vid.alphamap[( alpha << 16)|(src & 0xff00)|(screen>>8)] << 8 | (screen & 0xff) >> 3 | ((src & 0xff) >> 3); |
|
|
|
} |
|
else |
|
dest[u] = src; |
|
|
|
} |
|
#endif |
|
} |
|
dest += vid.rowbytes; |
|
} |
|
} |
|
|
|
/* |
|
============= |
|
Draw_TileClear |
|
|
|
This repeats a 64*64 tile graphic to fill the screen around a sized down |
|
refresh window. |
|
============= |
|
*/ |
|
void GAME_EXPORT R_DrawTileClear( int texnum, int x, int y, int w, int h ) |
|
{ |
|
int tw, th, x2, i, j; |
|
image_t *pic; |
|
pixel_t *psrc, *pdest; |
|
|
|
GL_SetRenderMode( kRenderNormal ); |
|
_TriColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); |
|
GL_Bind( XASH_TEXTURE0, texnum ); |
|
|
|
pic = R_GetTexture( texnum ); |
|
|
|
tw = pic->width; |
|
th = pic->height; |
|
if (x < 0) |
|
{ |
|
w += x; |
|
x = 0; |
|
} |
|
if (y < 0) |
|
{ |
|
h += y; |
|
y = 0; |
|
} |
|
if (x + w > vid.width) |
|
w = vid.width - x; |
|
if (y + h > vid.height) |
|
h = vid.height - y; |
|
if (w <= 0 || h <= 0) |
|
return; |
|
|
|
x2 = x + w; |
|
pdest = vid.buffer + y*vid.rowbytes; |
|
for (i=0 ; i<h ; i++, pdest += vid.rowbytes) |
|
{ |
|
psrc = pic->pixels[0] + tw * ((i+y)&63); |
|
for (j=x ; j<x2 ; j++) |
|
pdest[j] = psrc[j&63]; |
|
} |
|
} |
|
|
|
/* |
|
============= |
|
R_DrawStretchRaw |
|
============= |
|
*/ |
|
void GAME_EXPORT R_DrawStretchRaw( float x, float y, float w, float h, int cols, int rows, const byte *data, qboolean dirty ) |
|
{ |
|
byte *raw = NULL; |
|
image_t *tex; |
|
|
|
raw = (byte *)data; |
|
|
|
//pglDisable( GL_BLEND ); |
|
//pglDisable( GL_ALPHA_TEST ); |
|
//pglTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); |
|
|
|
tex = R_GetTexture( tr.cinTexture ); |
|
GL_Bind( XASH_TEXTURE0, tr.cinTexture ); |
|
} |
|
|
|
/* |
|
============= |
|
R_UploadStretchRaw |
|
============= |
|
*/ |
|
void GAME_EXPORT R_UploadStretchRaw( int texture, int cols, int rows, int width, int height, const byte *data ) |
|
{ |
|
byte *raw = NULL; |
|
image_t *tex; |
|
raw = (byte *)data; |
|
|
|
tex = R_GetTexture( texture ); |
|
GL_Bind( GL_KEEP_UNIT, texture ); |
|
tex->width = cols; |
|
tex->height = rows; |
|
} |
|
|
|
/* |
|
=============== |
|
R_Set2DMode |
|
=============== |
|
*/ |
|
void GAME_EXPORT R_Set2DMode( qboolean enable ) |
|
{ |
|
vid.color = COLOR_WHITE; |
|
vid.is2d = enable; |
|
vid.alpha = 7; |
|
|
|
if( enable ) |
|
{ |
|
// if( glState.in2DMode ) |
|
// return; |
|
#if 0 |
|
// set 2D virtual screen size |
|
pglViewport( 0, 0, gpGlobals->width, gpGlobals->height ); |
|
pglMatrixMode( GL_PROJECTION ); |
|
pglLoadIdentity(); |
|
pglOrtho( 0, gpGlobals->width, gpGlobals->height, 0, -99999, 99999 ); |
|
pglMatrixMode( GL_MODELVIEW ); |
|
pglLoadIdentity(); |
|
|
|
GL_Cull( GL_NONE ); |
|
|
|
pglDepthMask( GL_FALSE ); |
|
pglDisable( GL_DEPTH_TEST ); |
|
pglEnable( GL_ALPHA_TEST ); |
|
pglColor4f( 1.0f, 1.0f, 1.0f, 1.0f ); |
|
#endif |
|
|
|
// glState.in2DMode = true; |
|
RI.currententity = NULL; |
|
RI.currentmodel = NULL; |
|
} |
|
else |
|
{ |
|
#if 0 |
|
pglDepthMask( GL_TRUE ); |
|
pglEnable( GL_DEPTH_TEST ); |
|
glState.in2DMode = false; |
|
|
|
pglMatrixMode( GL_PROJECTION ); |
|
GL_LoadMatrix( RI.projectionMatrix ); |
|
|
|
pglMatrixMode( GL_MODELVIEW ); |
|
GL_LoadMatrix( RI.worldviewMatrix ); |
|
|
|
GL_Cull( GL_FRONT ); |
|
#endif |
|
} |
|
}
|
|
|