2013-04-04 21:22:19 +00:00
/*
* Glide64 - Glide video plugin for Nintendo 64 emulators .
* Copyright ( c ) 2002 Dave2001
* Copyright ( c ) 2003 - 2009 Sergey ' Gonetz ' Lipski
*
* 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 2 of the License , or
* 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 .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307 USA
*/
//****************************************************************
//
// Glide64 - Glide Plugin for Nintendo 64 emulators
// Project started on December 29th, 2001
//
// Authors:
// Dave2001, original author, founded the project in 2001, left it in 2002
// Gugaman, joined the project in 2002, left it in 2002
// Sergey 'Gonetz' Lipski, joined the project in 2002, main author since fall of 2002
// Hiroshi 'KoolSmoky' Morii, joined the project in 2007
//
//****************************************************************
//
// To modify Glide64:
// * Write your name and (optional)email, commented by your work, so I know who did it, and so that you can find which parts you modified when it comes time to send it to me.
// * Do NOT send me the whole project or file that you modified. Take out your modified code sections, and tell me where to put them. If people sent the whole thing, I would have many different versions, but no idea how to combine them all.
//
//****************************************************************
//
// Draw N64 frame buffer to screen.
// Created by Gonetz, 2007
//
//****************************************************************
2015-10-09 00:07:09 +00:00
# include "Gfx_1.3.h"
2013-04-04 21:22:19 +00:00
# include "FBtoScreen.h"
# include "TexCache.h"
2016-02-11 09:58:42 +00:00
# include <Glide64/trace.h>
2013-04-04 21:22:19 +00:00
2016-01-20 06:14:48 +00:00
static int SetupFBtoScreenCombiner ( uint32_t texture_size , uint32_t opaque )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
int tmu ;
if ( voodoo . tmem_ptr [ GR_TMU0 ] + texture_size < voodoo . tex_max_addr [ 0 ] )
{
tmu = GR_TMU0 ;
grTexCombine ( GR_TMU1 ,
GR_COMBINE_FUNCTION_NONE ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_FUNCTION_NONE ,
GR_COMBINE_FACTOR_NONE ,
FXFALSE ,
FXFALSE ) ;
grTexCombine ( GR_TMU0 ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
FXFALSE ,
FXFALSE ) ;
}
else
{
if ( voodoo . tmem_ptr [ GR_TMU1 ] + texture_size > = voodoo . tex_max_addr [ 1 ] )
ClearCache ( ) ;
tmu = GR_TMU1 ;
grTexCombine ( GR_TMU1 ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
FXFALSE ,
FXFALSE ) ;
grTexCombine ( GR_TMU0 ,
GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
FXFALSE ,
FXFALSE ) ;
}
int filter = ( rdp . filter_mode ! = 2 ) ? GR_TEXTUREFILTER_POINT_SAMPLED : GR_TEXTUREFILTER_BILINEAR ;
grTexFilterMode ( tmu , filter , filter ) ;
grTexClampMode ( tmu ,
2013-04-04 21:22:19 +00:00
GR_TEXTURECLAMP_CLAMP ,
GR_TEXTURECLAMP_CLAMP ) ;
2016-02-11 07:13:51 +00:00
// grConstantColorValue (0xFFFFFFFF);
grColorCombine ( GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_LOCAL_NONE ,
GR_COMBINE_OTHER_TEXTURE ,
// GR_COMBINE_OTHER_CONSTANT,
FXFALSE ) ;
grAlphaCombine ( GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_LOCAL_NONE ,
GR_COMBINE_OTHER_TEXTURE ,
FXFALSE ) ;
if ( opaque )
{
grAlphaTestFunction ( GR_CMP_ALWAYS ) ;
grAlphaBlendFunction ( GR_BLEND_ONE ,
GR_BLEND_ZERO ,
GR_BLEND_ONE ,
GR_BLEND_ZERO ) ;
}
else
{
grAlphaBlendFunction ( GR_BLEND_SRC_ALPHA ,
GR_BLEND_ONE_MINUS_SRC_ALPHA ,
GR_BLEND_ONE ,
GR_BLEND_ZERO ) ;
}
grDepthBufferFunction ( GR_CMP_ALWAYS ) ;
grCullMode ( GR_CULL_DISABLE ) ;
grDepthMask ( FXFALSE ) ;
rdp . update | = UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE ;
return tmu ;
2013-04-04 21:22:19 +00:00
}
static void DrawRE2Video ( FB_TO_SCREEN_INFO & fb_info , float scale )
{
2016-02-11 07:13:51 +00:00
float scale_y = ( float ) fb_info . width / rdp . vi_height ;
float height = g_settings - > scr_res_x / scale_y ;
float ul_x = 0.5f ;
float ul_y = ( g_settings - > scr_res_y - height ) / 2.0f ;
float lr_y = g_settings - > scr_res_y - ul_y - 1.0f ;
float lr_x = g_settings - > scr_res_x - 1.0f ;
float lr_u = ( fb_info . width - 1 ) * scale ;
float lr_v = ( fb_info . height - 1 ) * scale ;
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , 0.5f , 0.5f , 0.5f , 0.5f , { 0.5f , 0.5f , 0.5f , 0.5f } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , 0.5f , lr_u , 0.5f , { lr_u , 0.5f , lr_u , 0.5f } } ,
{ ul_x , lr_y , 1 , 1 , 0.5f , lr_v , 0.5f , lr_v , { 0.5f , lr_v , 0.5f , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
2013-04-04 21:22:19 +00:00
}
static void DrawRE2Video256 ( FB_TO_SCREEN_INFO & fb_info )
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawRE2Video256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
uint32_t * src = ( uint32_t * ) ( gfx . RDRAM + fb_info . addr ) ;
GrTexInfo t_info ;
t_info . smallLodLog2 = GR_LOD_LOG2_256 ;
t_info . largeLodLog2 = GR_LOD_LOG2_256 ;
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
uint16_t * tex = ( uint16_t * ) texture_buffer ;
uint16_t * dst = tex ;
uint32_t col ;
uint8_t r , g , b ;
fb_info . height = minval ( 256 , fb_info . height ) ;
for ( uint32_t h = 0 ; h < fb_info . height ; h + + )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
for ( uint32_t w = 0 ; w < 256 ; w + + )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
col = * ( src + + ) ;
r = ( uint8_t ) ( ( col > > 24 ) & 0xFF ) ;
2016-01-20 06:17:45 +00:00
r = ( uint8_t ) ( ( float ) r / 255.0f * 31.0f ) ;
2016-02-11 07:13:51 +00:00
g = ( uint8_t ) ( ( col > > 16 ) & 0xFF ) ;
2016-01-20 06:17:45 +00:00
g = ( uint8_t ) ( ( float ) g / 255.0f * 63.0f ) ;
2016-02-11 07:13:51 +00:00
b = ( uint8_t ) ( ( col > > 8 ) & 0xFF ) ;
2016-01-20 06:17:45 +00:00
b = ( uint8_t ) ( ( float ) b / 255.0f * 31.0f ) ;
2016-02-11 07:13:51 +00:00
* ( dst + + ) = ( r < < 11 ) | ( g < < 5 ) | b ;
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
src + = ( fb_info . width - 256 ) ;
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
t_info . format = GR_TEXFMT_RGB_565 ;
t_info . data = tex ;
int tmu = SetupFBtoScreenCombiner ( grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & t_info ) , fb_info . opaque ) ;
grTexDownloadMipMap ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
grTexSource ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
DrawRE2Video ( fb_info , 1.0f ) ;
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
static void DrawFrameBufferToScreen256 ( FB_TO_SCREEN_INFO & fb_info )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
if ( g_settings - > hacks & hack_RE2 )
{
DrawRE2Video256 ( fb_info ) ;
return ;
}
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawFrameBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
uint32_t width = fb_info . lr_x - fb_info . ul_x + 1 ;
uint32_t height = fb_info . lr_y - fb_info . ul_y + 1 ;
GrTexInfo t_info ;
uint8_t * image = gfx . RDRAM + fb_info . addr ;
uint32_t width256 = ( ( width - 1 ) > > 8 ) + 1 ;
uint32_t height256 = ( ( height - 1 ) > > 8 ) + 1 ;
2013-04-04 21:22:19 +00:00
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_256 ;
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
2016-02-11 07:13:51 +00:00
t_info . format = GR_TEXFMT_ARGB_1555 ;
2016-01-20 06:26:07 +00:00
uint16_t * tex = ( uint16_t * ) texture_buffer ;
2016-02-11 07:13:51 +00:00
t_info . data = tex ;
uint32_t tex_size = grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
int tmu = SetupFBtoScreenCombiner ( tex_size * width256 * height256 , fb_info . opaque ) ;
2016-01-20 06:26:07 +00:00
uint16_t * src = ( uint16_t * ) image ;
2013-04-04 21:22:19 +00:00
src + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
2016-02-11 07:13:51 +00:00
uint32_t * src32 = ( uint32_t * ) image ;
src32 + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
uint32_t w_tail = width % 256 ;
uint32_t h_tail = height % 256 ;
2016-01-20 06:26:07 +00:00
uint16_t c ;
2016-02-11 07:13:51 +00:00
uint32_t c32 ;
2016-01-20 06:14:48 +00:00
uint32_t idx ;
2016-02-11 07:13:51 +00:00
uint32_t bound = BMASK + 1 - fb_info . addr ;
bound = fb_info . size = = 2 ? bound > > 1 : bound > > 2 ;
uint8_t r , g , b , a ;
uint32_t cur_width , cur_height , cur_tail ;
uint32_t tex_adr = voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ;
if ( ( voodoo . tmem_ptr [ tmu ] < TEXMEM_2MB_EDGE ) & & ( voodoo . tmem_ptr [ tmu ] + tex_size * width256 * height256 > TEXMEM_2MB_EDGE ) )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
tex_adr = TEXMEM_2MB_EDGE ;
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
for ( uint32_t h = 0 ; h < height256 ; h + + )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
for ( uint32_t w = 0 ; w < width256 ; w + + )
{
cur_width = ( 256 * ( w + 1 ) < width ) ? 256 : w_tail ;
cur_height = ( 256 * ( h + 1 ) < height ) ? 256 : h_tail ;
cur_tail = 256 - cur_width ;
uint16_t * dst = tex ;
if ( fb_info . size = = 2 )
{
for ( uint32_t y = 0 ; y < cur_height ; y + + )
{
for ( uint32_t x = 0 ; x < cur_width ; x + + )
{
idx = ( x + 256 * w + ( y + 256 * h ) * fb_info . width ) ^ 1 ;
if ( idx > = bound )
break ;
c = src [ idx ] ;
* ( dst + + ) = ( c > > 1 ) | ( ( c & 1 ) < < 15 ) ;
}
dst + = cur_tail ;
}
}
else
{
for ( uint32_t y = 0 ; y < cur_height ; y + + )
{
for ( uint32_t x = 0 ; x < cur_width ; x + + )
{
idx = ( x + 256 * w + ( y + 256 * h ) * fb_info . width ) ;
if ( idx > = bound )
break ;
c32 = src32 [ idx ] ;
r = ( uint8_t ) ( ( c32 > > 24 ) & 0xFF ) ;
r = ( uint8_t ) ( ( float ) r / 255.0f * 31.0f ) ;
g = ( uint8_t ) ( ( c32 > > 16 ) & 0xFF ) ;
g = ( uint8_t ) ( ( float ) g / 255.0f * 63.0f ) ;
b = ( uint8_t ) ( ( c32 > > 8 ) & 0xFF ) ;
b = ( uint8_t ) ( ( float ) b / 255.0f * 31.0f ) ;
a = ( c32 & 0xFF ) ? 1 : 0 ;
* ( dst + + ) = ( a < < 15 ) | ( r < < 10 ) | ( g < < 5 ) | b ;
}
dst + = cur_tail ;
}
}
grTexDownloadMipMap ( tmu , tex_adr , GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
grTexSource ( tmu , tex_adr , GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
tex_adr + = tex_size ;
float ul_x = ( float ) ( fb_info . ul_x + 256 * w ) ;
float ul_y = ( float ) ( fb_info . ul_y + 256 * h ) ;
float lr_x = ( ul_x + ( float ) ( cur_width ) ) * rdp . scale_x ;
float lr_y = ( ul_y + ( float ) ( cur_height ) ) * rdp . scale_y ;
ul_x * = rdp . scale_x ;
ul_y * = rdp . scale_y ;
ul_x + = rdp . offset_x ;
ul_y + = rdp . offset_y ;
lr_x + = rdp . offset_x ;
lr_y + = rdp . offset_y ;
float lr_u = ( float ) ( cur_width - 1 ) ;
float lr_v = ( float ) ( cur_height - 1 ) ;
// Make the vertices
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , 0.5f , 0.5f , 0.5f , 0.5f , { 0.5f , 0.5f , 0.5f , 0.5f } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , 0.5f , lr_u , 0.5f , { lr_u , 0.5f , lr_u , 0.5f } } ,
{ ul_x , lr_y , 1 , 1 , 0.5f , lr_v , 0.5f , lr_v , { 0.5f , lr_v , 0.5f , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
}
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
}
2013-04-04 21:22:19 +00:00
2016-02-11 07:13:51 +00:00
bool DrawFrameBufferToScreen ( FB_TO_SCREEN_INFO & fb_info )
{
if ( fb_info . width < 200 | | fb_info . size < 2 )
return false ;
uint32_t width = fb_info . lr_x - fb_info . ul_x + 1 ;
uint32_t height = fb_info . lr_y - fb_info . ul_y + 1 ;
uint32_t max_size = minval ( voodoo . max_tex_size , 512 ) ;
if ( width > ( uint32_t ) max_size | | height > ( uint32_t ) max_size )
{
DrawFrameBufferToScreen256 ( fb_info ) ;
return true ;
}
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawFrameBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
GrTexInfo t_info ;
uint8_t * image = gfx . RDRAM + fb_info . addr ;
uint32_t texwidth ;
float scale ;
if ( width < = 256 )
{
texwidth = 256 ;
scale = 1.0f ;
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_256 ;
}
else
{
texwidth = 512 ;
scale = 0.5f ;
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_512 ;
}
if ( height < = ( texwidth > > 1 ) )
{
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_2x1 ;
}
else
{
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
}
if ( fb_info . size = = 2 )
{
uint16_t * tex = ( uint16_t * ) texture_buffer ;
uint16_t * dst = tex ;
uint16_t * src = ( uint16_t * ) image ;
src + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
uint16_t c ;
uint32_t idx ;
const uint32_t bound = ( BMASK + 1 - fb_info . addr ) > > 1 ;
bool empty = true ;
for ( uint32_t y = 0 ; y < height ; y + + )
{
for ( uint32_t x = 0 ; x < width ; x + + )
{
idx = ( x + y * fb_info . width ) ^ 1 ;
if ( idx > = bound )
break ;
c = src [ idx ] ;
if ( c ) empty = false ;
* ( dst + + ) = ( c > > 1 ) | ( ( c & 1 ) < < 15 ) ;
}
dst + = texwidth - width ;
}
if ( empty )
return false ;
t_info . format = GR_TEXFMT_ARGB_1555 ;
t_info . data = tex ;
}
else
{
uint32_t * tex = ( uint32_t * ) texture_buffer ;
uint32_t * dst = tex ;
uint32_t * src = ( uint32_t * ) image ;
src + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
uint32_t col ;
uint32_t idx ;
const uint32_t bound = ( BMASK + 1 - fb_info . addr ) > > 2 ;
for ( uint32_t y = 0 ; y < height ; y + + )
{
for ( uint32_t x = 0 ; x < width ; x + + )
{
idx = x + y * fb_info . width ;
if ( idx > = bound )
break ;
col = src [ idx ] ;
* ( dst + + ) = ( col > > 8 ) | 0xFF000000 ;
}
dst + = texwidth - width ;
}
t_info . format = GR_TEXFMT_ARGB_8888 ;
t_info . data = tex ;
}
int tmu = SetupFBtoScreenCombiner ( grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & t_info ) , fb_info . opaque ) ;
grTexDownloadMipMap ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
grTexSource ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
if ( g_settings - > hacks & hack_RE2 )
{
DrawRE2Video ( fb_info , scale ) ;
}
else
{
float ul_x = fb_info . ul_x * rdp . scale_x + rdp . offset_x ;
float ul_y = fb_info . ul_y * rdp . scale_y + rdp . offset_y ;
float lr_x = fb_info . lr_x * rdp . scale_x + rdp . offset_x ;
float lr_y = fb_info . lr_y * rdp . scale_y + rdp . offset_y ;
float lr_u = ( width - 1 ) * scale ;
float lr_v = ( height - 1 ) * scale ;
// Make the vertices
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , 0.5f , 0.5f , 0.5f , 0.5f , { 0.5f , 0.5f , 0.5f , 0.5f } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , 0.5f , lr_u , 0.5f , { lr_u , 0.5f , lr_u , 0.5f } } ,
{ ul_x , lr_y , 1 , 1 , 0.5f , lr_v , 0.5f , lr_v , { 0.5f , lr_v , 0.5f , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
}
return true ;
2013-04-04 21:22:19 +00:00
}
static void DrawDepthBufferToScreen256 ( FB_TO_SCREEN_INFO & fb_info )
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawDepthBufferToScreen256. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
uint32_t width = fb_info . lr_x - fb_info . ul_x + 1 ;
uint32_t height = fb_info . lr_y - fb_info . ul_y + 1 ;
GrTexInfo t_info ;
uint8_t * image = gfx . RDRAM + fb_info . addr ;
uint32_t width256 = ( ( width - 1 ) > > 8 ) + 1 ;
uint32_t height256 = ( ( height - 1 ) > > 8 ) + 1 ;
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_256 ;
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
t_info . format = GR_TEXFMT_ALPHA_INTENSITY_88 ;
uint16_t * tex = ( uint16_t * ) texture_buffer ;
t_info . data = tex ;
uint32_t tex_size = grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
int tmu = SetupFBtoScreenCombiner ( tex_size * width256 * height256 , fb_info . opaque ) ;
grConstantColorValue ( rdp . fog_color ) ;
grColorCombine ( GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_LOCAL_NONE ,
GR_COMBINE_OTHER_CONSTANT ,
FXFALSE ) ;
uint16_t * src = ( uint16_t * ) image ;
src + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
uint32_t w_tail = width % 256 ;
uint32_t h_tail = height % 256 ;
uint32_t cur_width , cur_height , cur_tail ;
uint32_t tex_adr = voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ;
if ( ( voodoo . tmem_ptr [ tmu ] < TEXMEM_2MB_EDGE ) & & ( voodoo . tmem_ptr [ tmu ] + tex_size * width256 * height256 > TEXMEM_2MB_EDGE ) )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
tex_adr = TEXMEM_2MB_EDGE ;
}
for ( uint32_t h = 0 ; h < height256 ; h + + )
{
for ( uint32_t w = 0 ; w < width256 ; w + + )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
cur_width = ( 256 * ( w + 1 ) < width ) ? 256 : w_tail ;
cur_height = ( 256 * ( h + 1 ) < height ) ? 256 : h_tail ;
cur_tail = 256 - cur_width ;
uint16_t * dst = tex ;
for ( uint32_t y = 0 ; y < cur_height ; y + + )
{
for ( uint32_t x = 0 ; x < cur_width ; x + + )
{
* ( dst + + ) = rdp . pal_8 [ src [ ( x + 256 * w + ( y + 256 * h ) * fb_info . width ) ^ 1 ] > > 8 ] ;
}
dst + = cur_tail ;
}
grTexDownloadMipMap ( tmu , tex_adr , GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
grTexSource ( tmu , tex_adr , GR_MIPMAPLEVELMASK_BOTH , & t_info ) ;
tex_adr + = tex_size ;
float ul_x = ( float ) ( fb_info . ul_x + 256 * w ) ;
float ul_y = ( float ) ( fb_info . ul_y + 256 * h ) ;
float lr_x = ( ul_x + ( float ) ( cur_width ) ) * rdp . scale_x + rdp . offset_x ;
float lr_y = ( ul_y + ( float ) ( cur_height ) ) * rdp . scale_y + rdp . offset_y ;
ul_x = ul_x * rdp . scale_x + rdp . offset_x ;
ul_y = ul_y * rdp . scale_y + rdp . offset_y ;
float lr_u = ( float ) ( cur_width - 1 ) ;
float lr_v = ( float ) ( cur_height - 1 ) ;
// Make the vertices
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , 0.5f , 0.5f , 0.5f , 0.5f , { 0.5f , 0.5f , 0.5f , 0.5f } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , 0.5f , lr_u , 0.5f , { lr_u , 0.5f , lr_u , 0.5f } } ,
{ ul_x , lr_y , 1 , 1 , 0.5f , lr_v , 0.5f , lr_v , { 0.5f , lr_v , 0.5f , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
2013-04-04 21:22:19 +00:00
}
}
}
static void DrawHiresDepthBufferToScreen ( FB_TO_SCREEN_INFO & fb_info )
{
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawHiresDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
GrTexInfo t_info ;
float scale = 0.25f ;
GrLOD_t LOD = GR_LOD_LOG2_1024 ;
if ( g_settings - > scr_res_x > 1024 )
{
scale = 0.125f ;
LOD = GR_LOD_LOG2_2048 ;
}
t_info . format = GR_TEXFMT_ALPHA_INTENSITY_88 ;
t_info . smallLodLog2 = t_info . largeLodLog2 = LOD ;
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
grConstantColorValue ( rdp . fog_color ) ;
grColorCombine ( GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_LOCAL_CONSTANT ,
GR_COMBINE_OTHER_NONE ,
FXFALSE ) ;
grAlphaCombine ( GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_LOCAL_NONE ,
GR_COMBINE_OTHER_TEXTURE ,
FXFALSE ) ;
grAlphaBlendFunction ( GR_BLEND_SRC_ALPHA ,
GR_BLEND_ONE_MINUS_SRC_ALPHA ,
GR_BLEND_ONE ,
GR_BLEND_ZERO ) ;
grDepthBufferFunction ( GR_CMP_ALWAYS ) ;
grDepthMask ( FXFALSE ) ;
grCullMode ( GR_CULL_DISABLE ) ;
grTexCombine ( GR_TMU1 ,
GR_COMBINE_FUNCTION_NONE ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_FUNCTION_NONE ,
GR_COMBINE_FACTOR_NONE ,
FXFALSE ,
FXFALSE ) ;
grTexCombine ( GR_TMU0 ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
GR_COMBINE_FUNCTION_LOCAL ,
GR_COMBINE_FACTOR_NONE ,
FXFALSE ,
FXFALSE ) ;
// grAuxBufferExt( GR_BUFFER_AUXBUFFER );
grTexSource ( rdp . texbufs [ 0 ] . tmu , rdp . texbufs [ 0 ] . begin , GR_MIPMAPLEVELMASK_BOTH , & ( t_info ) ) ;
float ul_x = ( float ) rdp . scissor . ul_x ;
float ul_y = ( float ) rdp . scissor . ul_y ;
float lr_x = ( float ) rdp . scissor . lr_x ;
float lr_y = ( float ) rdp . scissor . lr_y ;
float ul_u = ( float ) rdp . scissor . ul_x * scale ;
float ul_v = ( float ) rdp . scissor . ul_y * scale ;
float lr_u = ( float ) rdp . scissor . lr_x * scale ;
float lr_v = ( float ) rdp . scissor . lr_y * scale ;
// Make the vertices
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , ul_u , ul_v , ul_u , ul_v , { ul_u , ul_v , ul_u , ul_v } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , ul_v , lr_u , ul_v , { lr_u , ul_v , lr_u , ul_v } } ,
{ ul_x , lr_y , 1 , 1 , ul_u , lr_v , ul_u , lr_v , { ul_u , lr_v , ul_u , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
// grAuxBufferExt( GR_BUFFER_TEXTUREAUXBUFFER_EXT );
rdp . update | = UPDATE_COMBINE | UPDATE_ZBUF_ENABLED | UPDATE_CULL_MODE ;
2013-04-04 21:22:19 +00:00
}
void DrawDepthBufferToScreen ( FB_TO_SCREEN_INFO & fb_info )
{
2016-02-11 07:13:51 +00:00
uint32_t width = fb_info . lr_x - fb_info . ul_x + 1 ;
uint32_t height = fb_info . lr_y - fb_info . ul_y + 1 ;
if ( width > ( uint32_t ) voodoo . max_tex_size | | height > ( uint32_t ) voodoo . max_tex_size | | width > 512 )
{
DrawDepthBufferToScreen256 ( fb_info ) ;
return ;
}
if ( fb_hwfbe_enabled & & ! evoodoo )
{
DrawHiresDepthBufferToScreen ( fb_info ) ;
return ;
}
2016-02-11 09:58:42 +00:00
WriteTrace ( TraceRDP , TraceDebug , " DrawDepthBufferToScreen. ul_x=%d, ul_y=%d, lr_x=%d, lr_y=%d, size=%d, addr=%08lx " , fb_info . ul_x , fb_info . ul_y , fb_info . lr_x , fb_info . lr_y , fb_info . size , fb_info . addr ) ;
2016-02-11 07:13:51 +00:00
GrTexInfo t_info ;
uint8_t * image = gfx . RDRAM + fb_info . addr ;
uint32_t texwidth ;
float scale ;
if ( width < = 256 )
{
texwidth = 256 ;
scale = 1.0f ;
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_256 ;
}
else
{
texwidth = 512 ;
scale = 0.5f ;
t_info . smallLodLog2 = t_info . largeLodLog2 = GR_LOD_LOG2_512 ;
}
2013-04-04 21:22:19 +00:00
2016-02-11 07:13:51 +00:00
if ( height < = ( texwidth > > 1 ) )
{
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_2x1 ;
}
else
{
t_info . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
}
2013-04-04 21:22:19 +00:00
2016-02-11 07:13:51 +00:00
uint16_t * tex = ( uint16_t * ) texture_buffer ;
uint16_t * dst = tex ;
uint16_t * src = ( uint16_t * ) image ;
src + = fb_info . ul_x + fb_info . ul_y * fb_info . width ;
for ( uint32_t y = 0 ; y < height ; y + + )
2013-04-04 21:22:19 +00:00
{
2016-02-11 07:13:51 +00:00
for ( uint32_t x = 0 ; x < width ; x + + )
{
* ( dst + + ) = rdp . pal_8 [ src [ ( x + y * fb_info . width ) ^ 1 ] > > 8 ] ;
}
dst + = texwidth - width ;
2013-04-04 21:22:19 +00:00
}
2016-02-11 07:13:51 +00:00
t_info . format = GR_TEXFMT_ALPHA_INTENSITY_88 ;
t_info . data = tex ;
2013-04-04 21:22:19 +00:00
2016-02-11 07:13:51 +00:00
int tmu = SetupFBtoScreenCombiner ( grTexTextureMemRequired ( GR_MIPMAPLEVELMASK_BOTH , & t_info ) , fb_info . opaque ) ;
grConstantColorValue ( rdp . fog_color ) ;
grColorCombine ( GR_COMBINE_FUNCTION_SCALE_OTHER ,
GR_COMBINE_FACTOR_ONE ,
GR_COMBINE_LOCAL_NONE ,
GR_COMBINE_OTHER_CONSTANT ,
FXFALSE ) ;
grTexDownloadMipMap ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
grTexSource ( tmu ,
voodoo . tex_min_addr [ tmu ] + voodoo . tmem_ptr [ tmu ] ,
GR_MIPMAPLEVELMASK_BOTH ,
& t_info ) ;
float ul_x = fb_info . ul_x * rdp . scale_x + rdp . offset_x ;
float ul_y = fb_info . ul_y * rdp . scale_y + rdp . offset_y ;
float lr_x = fb_info . lr_x * rdp . scale_x + rdp . offset_x ;
float lr_y = fb_info . lr_y * rdp . scale_y + rdp . offset_y ;
float lr_u = ( width - 1 ) * scale ;
float lr_v = ( height - 1 ) * scale ;
float zero = scale * 0.5f ;
// Make the vertices
VERTEX v [ 4 ] = {
{ ul_x , ul_y , 1 , 1 , zero , zero , zero , zero , { zero , zero , zero , zero } } ,
{ lr_x , ul_y , 1 , 1 , lr_u , zero , lr_u , zero , { lr_u , zero , lr_u , zero } } ,
{ ul_x , lr_y , 1 , 1 , zero , lr_v , zero , lr_v , { zero , lr_v , zero , lr_v } } ,
{ lr_x , lr_y , 1 , 1 , lr_u , lr_v , lr_u , lr_v , { lr_u , lr_v , lr_u , lr_v } }
} ;
grDrawTriangle ( & v [ 0 ] , & v [ 2 ] , & v [ 1 ] ) ;
grDrawTriangle ( & v [ 2 ] , & v [ 3 ] , & v [ 1 ] ) ;
}