2021-03-02 02:13:17 +00:00
// Project64 - A Nintendo 64 emulator
2021-05-18 11:51:36 +00:00
// https://www.pj64-emu.com/
2021-03-02 02:13:17 +00:00
// Copyright(C) 2001-2021 Project64
// Copyright(C) 2003-2009 Sergey 'Gonetz' Lipski
// Copyright(C) 2002 Dave2001
// GNU/GPLv2 licensed: https://gnu.org/licenses/gpl-2.0.html
2021-05-18 11:51:36 +00:00
2017-05-17 08:01:54 +00:00
# include <Project64-video/Renderer/Renderer.h>
2015-10-09 04:44:33 +00:00
# define SAVE_CBUFFER
# ifdef _WIN32
# include <windows.h>
# else
# include <stdint.h>
# include <stdarg.h>
# include <string.h>
# endif // _WIN32
# include <stdlib.h>
# include <stdio.h>
# include <iostream>
# include <fstream>
# include <math.h>
2015-10-09 04:53:16 +00:00
# include "glitchmain.h"
2017-04-26 09:40:23 +00:00
# include <Project64-video/trace.h>
2017-07-25 22:13:06 +00:00
# include <Project64-video/Settings.h>
2015-10-09 04:44:33 +00:00
# define OPENGL_CHECK_ERRORS { const GLenum errcode = glGetError(); if (errcode != GL_NO_ERROR) LOG("OpenGL Error code %i in '%s' line %i\n", errcode, __FILE__, __LINE__-1); }
2016-02-14 08:59:33 +00:00
extern void ( * renderCallback ) ( int ) ;
2015-10-09 04:44:33 +00:00
int screen_width , screen_height ;
2016-03-10 18:29:41 +00:00
void Android_JNI_SwapWindow ( void ) ;
2015-10-09 04:44:33 +00:00
/*
static inline void opt_glCopyTexImage2D ( GLenum target ,
2016-02-14 08:59:33 +00:00
GLint level ,
GLenum internalFormat ,
GLint x ,
GLint y ,
GLsizei width ,
GLsizei height ,
GLint border )
{
int w , h , fmt ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_WIDTH , & w ) ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_HEIGHT , & h ) ;
glGetTexLevelParameteriv ( GL_TEXTURE_2D , 0 , GL_TEXTURE_INTERNAL_FORMAT , & fmt ) ;
//printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
if ( w = = ( int ) width & & h = = ( int ) height & & fmt = = ( int ) internalFormat ) {
if ( x + width > = screen_width ) {
width = screen_width - x ;
//printf("resizing w --> %d\n", width);
}
2017-03-13 09:34:51 +00:00
if ( y + height > = screen_height + g_viewport_offset ) {
height = screen_height + g_viewport_offset - y ;
2016-02-14 08:59:33 +00:00
//printf("resizing h --> %d\n", height);
}
glCopyTexSubImage2D ( target , level , 0 , 0 , x , y , width , height ) ;
} else {
//printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);
// glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);
// glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
// printf("--> %dx%d newfmt %x\n", width, height, fmt);
glCopyTexImage2D ( target , level , internalFormat , x , y , width , height , border ) ;
}
2015-10-09 04:44:33 +00:00
}
# define glCopyTexImage2D opt_glCopyTexImage2D
*/
# ifdef _WIN32
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB ;
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT ;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB ;
PFNGLFOGCOORDFPROC glFogCoordfEXT ;
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB ;
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT ;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT ;
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT ;
2021-04-12 11:35:39 +00:00
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = nullptr ;
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = nullptr ;
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = nullptr ;
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = nullptr ;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = nullptr ;
2015-10-09 04:44:33 +00:00
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT ;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT ;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB ;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB ;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB ;
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB ;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB ;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB ;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB ;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB ;
PFNGLUNIFORM1IARBPROC glUniform1iARB ;
PFNGLUNIFORM4IARBPROC glUniform4iARB ;
PFNGLUNIFORM4FARBPROC glUniform4fARB ;
PFNGLUNIFORM1FARBPROC glUniform1fARB ;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB ;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB ;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB ;
PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f ;
2021-05-18 11:51:36 +00:00
// FXT1,DXT1,DXT5 support - Hiroshi Morii
2015-10-09 04:44:33 +00:00
// NOTE: Glide64 + GlideHQ use the following formats
// GL_COMPRESSED_RGB_S3TC_DXT1_EXT
// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
// GL_COMPRESSED_RGB_FXT1_3DFX
// GL_COMPRESSED_RGBA_FXT1_3DFX
PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB ;
# endif // _WIN32
typedef struct
{
2016-02-14 08:59:33 +00:00
unsigned int address ;
int width ;
int height ;
unsigned int fbid ;
unsigned int zbid ;
unsigned int texid ;
int buff_clear ;
2015-10-09 04:44:33 +00:00
} fb ;
int nbAuxBuffers , current_buffer ;
2017-05-17 08:13:04 +00:00
int g_width , widtho , heighto , g_height ;
2015-10-09 04:44:33 +00:00
int saved_width , saved_height ;
int blend_func_separate_support ;
int npot_support ;
int fog_coord_support ;
int render_to_texture = 0 ;
int texture_unit ;
int use_fbo ;
int buffer_cleared ;
2021-05-18 11:51:36 +00:00
// Comment by Ziggy
// To allocate a new static texture name, take the value (free_texture++)
2015-10-09 04:44:33 +00:00
int free_texture ;
2022-07-25 08:22:14 +00:00
GLuint default_texture ; // The infamous "32*1024*1024" is now configurable
2015-10-09 04:44:33 +00:00
int current_texture ;
2022-07-25 08:22:14 +00:00
GLuint depth_texture , color_texture ;
2015-10-09 04:44:33 +00:00
int glsl_support = 1 ;
2017-03-13 09:34:51 +00:00
int viewport_width , viewport_height , g_viewport_offset = 0 , nvidia_viewport_hack = 0 ;
2015-10-09 04:44:33 +00:00
int save_w , save_h ;
int lfb_color_fmt ;
float invtex [ 2 ] ;
# ifdef _WIN32
2021-04-12 11:35:39 +00:00
static HDC hDC = nullptr ;
static HGLRC hGLRC = nullptr ;
static HWND hToolBar = nullptr ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
static unsigned long fullscreen ;
static int savedWidtho , savedHeighto ;
static int savedWidth , savedHeight ;
unsigned int pBufferAddress ;
static int pBufferFmt ;
static int pBufferWidth , pBufferHeight ;
static fb fbs [ 100 ] ;
static int nb_fb = 0 ;
static unsigned int curBufferAddr = 0 ;
2016-02-14 08:59:33 +00:00
struct TMU_USAGE { int min , max ; } tmu_usage [ 2 ] = { { 0xfffffff , 0 } , { 0xfffffff , 0 } } ;
2015-10-09 04:44:33 +00:00
struct texbuf_t {
2017-07-22 22:42:02 +00:00
uint32_t start , end ;
2016-02-14 08:59:33 +00:00
int fmt ;
2015-10-09 04:44:33 +00:00
} ;
2021-05-18 11:51:36 +00:00
# define NB_TEXBUFS 128 // Must be a power of two
2015-10-09 04:44:33 +00:00
static texbuf_t texbufs [ NB_TEXBUFS ] ;
static int texbuf_i ;
2021-05-18 11:51:36 +00:00
unsigned short frameBuffer [ 2048 * 2048 * 2 ] ; // Support 2048x2048 screen resolution at 32-bits (RGBA) per pixel
unsigned short depthBuffer [ 2048 * 2048 ] ; // Support 2048x2048 screen resolution at 16-bits (depth) per pixel
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
void display_warning ( const char * text , . . . )
{
static int first_message = 100 ;
if ( first_message )
{
char buf [ 4096 ] ;
va_list ap ;
va_start ( ap , text ) ;
vsprintf ( buf , text , ap ) ;
va_end ( ap ) ;
first_message - - ;
//LOGINFO(buf);
}
}
2017-07-22 22:42:02 +00:00
void gfxClipWindow ( uint32_t minx , uint32_t miny , uint32_t maxx , uint32_t maxy )
2016-02-14 08:59:33 +00:00
{
2017-04-27 07:31:49 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " minx = %d, miny: %d maxx: %d maxy: %d " , minx , miny , maxx , maxy ) ;
2016-02-14 08:59:33 +00:00
2017-05-22 10:18:43 +00:00
if ( use_fbo & & render_to_texture )
{
2016-02-14 08:59:33 +00:00
if ( int ( minx ) < 0 ) minx = 0 ;
if ( int ( miny ) < 0 ) miny = 0 ;
if ( maxx < minx ) maxx = minx ;
if ( maxy < miny ) maxy = miny ;
glScissor ( minx , miny , maxx - minx , maxy - miny ) ;
glEnable ( GL_SCISSOR_TEST ) ;
return ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( ! use_fbo ) {
2016-03-10 18:29:41 +00:00
int th = g_height ;
2016-02-14 08:59:33 +00:00
if ( th > screen_height )
th = screen_height ;
maxy = th - maxy ;
miny = th - miny ;
2017-07-22 22:42:02 +00:00
uint32_t tmp = maxy ; maxy = miny ; miny = tmp ;
if ( maxx > ( uint32_t ) g_width ) maxx = g_width ;
if ( maxy > ( uint32_t ) g_height ) maxy = g_height ;
2016-02-14 08:59:33 +00:00
if ( int ( minx ) < 0 ) minx = 0 ;
if ( int ( miny ) < 0 ) miny = 0 ;
if ( maxx < minx ) maxx = minx ;
if ( maxy < miny ) maxy = miny ;
2017-03-13 09:34:51 +00:00
glScissor ( minx , miny + g_viewport_offset , maxx - minx , maxy - miny ) ;
2021-05-18 11:51:36 +00:00
//printf("OpenGL scissor %d %d %d %d\n", minx, miny, maxx, maxy);
2016-02-14 08:59:33 +00:00
}
else {
2017-03-13 09:34:51 +00:00
glScissor ( minx , ( g_viewport_offset ) + g_height - maxy , maxx - minx , maxy - miny ) ;
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
glEnable ( GL_SCISSOR_TEST ) ;
}
2017-07-22 23:03:22 +00:00
void gfxColorMask ( bool rgb , bool a )
2015-10-09 04:44:33 +00:00
{
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " rgb = %d, a: %d " , rgb , a ) ;
2016-02-14 08:59:33 +00:00
glColorMask ( rgb , rgb , rgb , a ) ;
2015-10-09 04:44:33 +00:00
}
int isExtensionSupported ( const char * extension )
{
return 0 ;
2021-04-12 11:35:39 +00:00
const GLubyte * extensions = nullptr ;
2016-02-14 08:59:33 +00:00
const GLubyte * start ;
GLubyte * where , * terminator ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
where = ( GLubyte * ) strchr ( extension , ' ' ) ;
if ( where | | * extension = = ' \0 ' )
return 0 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
extensions = glGetString ( GL_EXTENSIONS ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
start = extensions ;
for ( ; ; )
{
where = ( GLubyte * ) strstr ( ( const char * ) start , extension ) ;
if ( ! where )
break ;
terminator = where + strlen ( extension ) ;
if ( where = = start | | * ( where - 1 ) = = ' ' )
if ( * terminator = = ' ' | | * terminator = = ' \0 ' )
return 1 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
start = terminator ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
return 0 ;
2015-10-09 04:44:33 +00:00
}
# ifdef _WIN32
int isWglExtensionSupported ( const char * extension )
{
2021-04-12 11:35:39 +00:00
const GLubyte * extensions = nullptr ;
2016-02-14 08:59:33 +00:00
const GLubyte * start ;
GLubyte * where , * terminator ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
where = ( GLubyte * ) strchr ( extension , ' ' ) ;
if ( where | | * extension = = ' \0 ' )
return 0 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
extensions = ( GLubyte * ) wglGetExtensionsStringARB ( wglGetCurrentDC ( ) ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
start = extensions ;
for ( ; ; )
{
where = ( GLubyte * ) strstr ( ( const char * ) start , extension ) ;
if ( ! where )
break ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
terminator = where + strlen ( extension ) ;
if ( where = = start | | * ( where - 1 ) = = ' ' )
if ( * terminator = = ' ' | | * terminator = = ' \0 ' )
return 1 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
start = terminator ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
return 0 ;
2015-10-09 04:44:33 +00:00
}
# endif // _WIN32
# define GrPixelFormat_t int
2016-03-10 18:29:41 +00:00
# ifdef _WIN32
2015-10-09 04:44:33 +00:00
# include <fcntl.h>
# ifndef ATTACH_PARENT_PROCESS
2017-07-22 22:42:02 +00:00
# define ATTACH_PARENT_PROCESS ((uint32_t)-1)
2015-10-09 04:44:33 +00:00
# endif
# endif
2017-08-08 10:45:53 +00:00
bool gfxSstWinOpen ( gfxColorFormat_t color_format , gfxOriginLocation_t origin_location , int nColBuffers , int nAuxBuffers )
2016-02-14 08:59:33 +00:00
{
static int show_warning = 1 ;
2017-04-26 08:13:55 +00:00
GLCache : : ResetCache ( ) ;
2017-05-16 10:03:02 +00:00
2021-05-18 11:51:36 +00:00
// Ziggy
// Allocate static texture names
// The initial value should be big enough to support the maximal resolution
2016-02-14 08:59:33 +00:00
free_texture = 32 * 2048 * 2048 ;
2022-07-25 08:22:14 +00:00
glGenTextures ( 1 , & default_texture ) ;
glGenTextures ( 1 , & color_texture ) ;
glGenTextures ( 1 , & depth_texture ) ;
2016-02-14 08:59:33 +00:00
2017-01-28 19:27:50 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " color_format: %d, origin_location: %d, nColBuffers: %d, nAuxBuffers: %d " , color_format , origin_location , nColBuffers , nAuxBuffers ) ;
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " g_width: %d, g_height: %d fullscreen: %d " , g_width , g_height , fullscreen ) ;
2015-10-09 04:44:33 +00:00
2017-03-13 09:34:51 +00:00
//g_viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
// ZIGGY g_viewport_offset is WIN32 specific, with SDL just set it to zero
g_viewport_offset = 0 ; //-10 //-20;
2016-02-14 08:59:33 +00:00
2016-03-10 18:29:41 +00:00
printf ( " (II) Setting video mode %dx%d... \n " , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
lfb_color_fmt = color_format ;
2021-05-18 11:51:36 +00:00
if ( origin_location ! = GFX_ORIGIN_UPPER_LEFT ) WriteTrace ( TraceGlitch , TraceWarning , " Origin must be in upper left corner " ) ;
if ( nColBuffers ! = 2 ) WriteTrace ( TraceGlitch , TraceWarning , " Number of color buffer is not 2 " ) ;
if ( nAuxBuffers ! = 1 ) WriteTrace ( TraceGlitch , TraceWarning , " Number of auxiliary buffer is not 1 " ) ;
2016-02-14 08:59:33 +00:00
if ( isExtensionSupported ( " GL_ARB_texture_env_combine " ) = = 0 & &
isExtensionSupported ( " GL_EXT_texture_env_combine " ) = = 0 & &
show_warning )
WriteTrace ( TraceGlitch , TraceWarning , " Your video card doesn't support GL_ARB_texture_env_combine extension " ) ;
if ( isExtensionSupported ( " GL_ARB_multitexture " ) = = 0 & & show_warning )
WriteTrace ( TraceGlitch , TraceWarning , " Your video card doesn't support GL_ARB_multitexture extension " ) ;
if ( isExtensionSupported ( " GL_ARB_texture_mirrored_repeat " ) = = 0 & & show_warning )
WriteTrace ( TraceGlitch , TraceWarning , " Your video card doesn't support GL_ARB_texture_mirrored_repeat extension " ) ;
show_warning = 0 ;
2015-10-09 04:44:33 +00:00
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glActiveTextureARB = ( PFNGLACTIVETEXTUREARBPROC ) wglGetProcAddress ( " glActiveTextureARB " ) ;
glMultiTexCoord2fARB = ( PFNGLMULTITEXCOORD2FARBPROC ) wglGetProcAddress ( " glMultiTexCoord2fARB " ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-02-14 08:59:33 +00:00
nbTextureUnits = 4 ;
nbAuxBuffers = 4 ;
//glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
if ( nbAuxBuffers > 0 )
2021-05-18 11:51:36 +00:00
printf ( " Congratulations, you have %d auxiliary buffers, we'll use them wisely! \n " , nbAuxBuffers ) ;
2015-10-09 04:44:33 +00:00
blend_func_separate_support = 1 ;
packed_pixels_support = 0 ;
2016-02-14 08:59:33 +00:00
if ( isExtensionSupported ( " GL_ARB_texture_non_power_of_two " ) = = 0 )
npot_support = 0 ;
else {
printf ( " NPOT extension used \n " ) ;
npot_support = 1 ;
}
2015-10-09 04:44:33 +00:00
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glBlendFuncSeparateEXT = ( PFNGLBLENDFUNCSEPARATEEXTPROC ) wglGetProcAddress ( " glBlendFuncSeparateEXT " ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-02-14 08:59:33 +00:00
if ( isExtensionSupported ( " GL_EXT_fog_coord " ) = = 0 )
fog_coord_support = 0 ;
else
fog_coord_support = 1 ;
2015-10-09 04:44:33 +00:00
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glFogCoordfEXT = ( PFNGLFOGCOORDFPROC ) wglGetProcAddress ( " glFogCoordfEXT " ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
wglGetExtensionsStringARB = ( PFNWGLGETEXTENSIONSSTRINGARBPROC ) wglGetProcAddress ( " wglGetExtensionsStringARB " ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glBindFramebufferEXT = ( PFNGLBINDFRAMEBUFFEREXTPROC ) wglGetProcAddress ( " glBindFramebufferEXT " ) ;
glFramebufferTexture2DEXT = ( PFNGLFRAMEBUFFERTEXTURE2DEXTPROC ) wglGetProcAddress ( " glFramebufferTexture2DEXT " ) ;
glGenFramebuffersEXT = ( PFNGLGENFRAMEBUFFERSEXTPROC ) wglGetProcAddress ( " glGenFramebuffersEXT " ) ;
glCheckFramebufferStatusEXT = ( PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC ) wglGetProcAddress ( " glCheckFramebufferStatusEXT " ) ;
glDeleteFramebuffersEXT = ( PFNGLDELETEFRAMEBUFFERSEXTPROC ) wglGetProcAddress ( " glDeleteFramebuffersEXT " ) ;
glBindRenderbufferEXT = ( PFNGLBINDRENDERBUFFEREXTPROC ) wglGetProcAddress ( " glBindRenderbufferEXT " ) ;
glDeleteRenderbuffersEXT = ( PFNGLDELETERENDERBUFFERSEXTPROC ) wglGetProcAddress ( " glDeleteRenderbuffersEXT " ) ;
glGenRenderbuffersEXT = ( PFNGLGENRENDERBUFFERSEXTPROC ) wglGetProcAddress ( " glGenRenderbuffersEXT " ) ;
glRenderbufferStorageEXT = ( PFNGLRENDERBUFFERSTORAGEEXTPROC ) wglGetProcAddress ( " glRenderbufferStorageEXT " ) ;
glFramebufferRenderbufferEXT = ( PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC ) wglGetProcAddress ( " glFramebufferRenderbufferEXT " ) ;
2021-04-12 11:35:39 +00:00
use_fbo = g_settings - > wrpFBO ( ) & & ( glFramebufferRenderbufferEXT ! = nullptr ) ;
2015-10-09 04:44:33 +00:00
# else
2017-07-22 22:31:08 +00:00
use_fbo = g_settings - > wrpFBO ( ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-03-10 18:29:41 +00:00
//LOGINFO("use_fbo %d\n", use_fbo);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( isExtensionSupported ( " GL_ARB_shading_language_100 " ) & &
isExtensionSupported ( " GL_ARB_shader_objects " ) & &
isExtensionSupported ( " GL_ARB_fragment_shader " ) & &
isExtensionSupported ( " GL_ARB_vertex_shader " ) )
{
2015-10-09 04:44:33 +00:00
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glCreateShaderObjectARB = ( PFNGLCREATESHADEROBJECTARBPROC ) wglGetProcAddress ( " glCreateShaderObjectARB " ) ;
glShaderSourceARB = ( PFNGLSHADERSOURCEARBPROC ) wglGetProcAddress ( " glShaderSourceARB " ) ;
glCompileShaderARB = ( PFNGLCOMPILESHADERARBPROC ) wglGetProcAddress ( " glCompileShaderARB " ) ;
glCreateProgramObjectARB = ( PFNGLCREATEPROGRAMOBJECTARBPROC ) wglGetProcAddress ( " glCreateProgramObjectARB " ) ;
glAttachObjectARB = ( PFNGLATTACHOBJECTARBPROC ) wglGetProcAddress ( " glAttachObjectARB " ) ;
glLinkProgramARB = ( PFNGLLINKPROGRAMARBPROC ) wglGetProcAddress ( " glLinkProgramARB " ) ;
glUseProgramObjectARB = ( PFNGLUSEPROGRAMOBJECTARBPROC ) wglGetProcAddress ( " glUseProgramObjectARB " ) ;
glGetUniformLocationARB = ( PFNGLGETUNIFORMLOCATIONARBPROC ) wglGetProcAddress ( " glGetUniformLocationARB " ) ;
glUniform1iARB = ( PFNGLUNIFORM1IARBPROC ) wglGetProcAddress ( " glUniform1iARB " ) ;
glUniform4iARB = ( PFNGLUNIFORM4IARBPROC ) wglGetProcAddress ( " glUniform4iARB " ) ;
glUniform4fARB = ( PFNGLUNIFORM4FARBPROC ) wglGetProcAddress ( " glUniform4fARB " ) ;
glUniform1fARB = ( PFNGLUNIFORM1FARBPROC ) wglGetProcAddress ( " glUniform1fARB " ) ;
glDeleteObjectARB = ( PFNGLDELETEOBJECTARBPROC ) wglGetProcAddress ( " glDeleteObjectARB " ) ;
glGetInfoLogARB = ( PFNGLGETINFOLOGARBPROC ) wglGetProcAddress ( " glGetInfoLogARB " ) ;
glGetObjectParameterivARB = ( PFNGLGETOBJECTPARAMETERIVARBPROC ) wglGetProcAddress ( " glGetObjectParameterivARB " ) ;
glSecondaryColor3f = ( PFNGLSECONDARYCOLOR3FPROC ) wglGetProcAddress ( " glSecondaryColor3f " ) ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( isExtensionSupported ( " GL_EXT_texture_compression_s3tc " ) = = 0 & & show_warning )
WriteTrace ( TraceGlitch , TraceWarning , " Your video card doesn't support GL_EXT_texture_compression_s3tc extension " ) ;
if ( isExtensionSupported ( " GL_3DFX_texture_compression_FXT1 " ) = = 0 & & show_warning )
WriteTrace ( TraceGlitch , TraceWarning , " Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension " ) ;
2015-10-09 04:44:33 +00:00
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
glCompressedTexImage2DARB = ( PFNGLCOMPRESSEDTEXIMAGE2DPROC ) wglGetProcAddress ( " glCompressedTexImage2DARB " ) ;
2015-10-09 04:44:33 +00:00
# endif
# ifdef _WIN32
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset , width , height ) ;
2016-02-14 08:59:33 +00:00
viewport_width = width ;
viewport_height = height ;
nvidia_viewport_hack = 1 ;
2015-10-09 04:44:33 +00:00
# else
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset , g_width , g_height ) ;
2016-03-10 18:29:41 +00:00
viewport_width = g_width ;
viewport_height = g_height ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-02-14 08:59:33 +00:00
// void do_benchmarks();
// do_benchmarks();
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
// VP try to resolve z precision issues
// glMatrixMode(GL_MODELVIEW);
// glLoadIdentity();
// glTranslatef(0, 0, 1-zscale);
// glScalef(1, 1, zscale);
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
widtho = g_width / 2 ;
heighto = g_height / 2 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
pBufferWidth = pBufferHeight = - 1 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
current_buffer = GL_BACK ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
texture_unit = GL_TEXTURE0 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
{
int i ;
for ( i = 0 ; i < NB_TEXBUFS ; i + + )
texbufs [ i ] . start = texbufs [ i ] . end = 0xffffffff ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( ! use_fbo & & nbAuxBuffers = = 0 ) {
2021-05-18 11:51:36 +00:00
// Create the framebuffer saving texture
2016-03-10 18:29:41 +00:00
int w = g_width , h = g_height ;
2016-02-14 08:59:33 +00:00
glBindTexture ( GL_TEXTURE_2D , color_texture ) ;
if ( ! npot_support ) {
w = h = 1 ;
2016-03-10 18:29:41 +00:00
while ( w < g_width ) w * = 2 ;
while ( h < g_height ) h * = 2 ;
2016-02-14 08:59:33 +00:00
}
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , w , h , 0 , GL_RGB , GL_UNSIGNED_BYTE , 0 ) ;
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
save_w = save_h = 0 ;
}
//void FindBestDepthBias();
//FindBestDepthBias();
init_geometry ( ) ;
init_textures ( ) ;
init_combiner ( ) ;
return 1 ;
2015-10-09 04:44:33 +00:00
}
2017-07-23 02:53:37 +00:00
bool gfxSstWinClose ( )
2015-10-09 04:44:33 +00:00
{
2017-07-23 02:53:37 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " - " ) ;
2016-02-14 08:59:33 +00:00
int i , clear_texbuff = use_fbo ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
for ( i = 0 ; i < 2 ; i + + ) {
tmu_usage [ i ] . min = 0xfffffff ;
tmu_usage [ i ] . max = 0 ;
invtex [ i ] = 0 ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
free_combiners ( ) ;
2016-03-10 18:29:41 +00:00
# ifndef _WIN32
2021-05-18 11:51:36 +00:00
try // I don't know why, but OpenGL can be killed before this function call when emulator is closed (Gonetz).
// Comment by Ziggy: I found the problem: It's a function pointer, when the extension isn't supported, it is then zero, so just need to check the pointer prior to do the call.
2016-02-14 08:59:33 +00:00
{
if ( use_fbo )
2016-03-10 18:29:41 +00:00
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
2016-02-14 08:59:33 +00:00
}
catch ( . . . )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
clear_texbuff = 0 ;
}
if ( clear_texbuff )
{
2016-03-10 18:29:41 +00:00
for ( i = 0 ; i < nb_fb ; i + + )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
glDeleteTextures ( 1 , & ( fbs [ i ] . texid ) ) ;
glDeleteFramebuffers ( 1 , & ( fbs [ i ] . fbid ) ) ;
glDeleteRenderbuffers ( 1 , & ( fbs [ i ] . zbid ) ) ;
2016-02-14 08:59:33 +00:00
}
2017-05-16 20:03:55 +00:00
}
2015-10-09 04:44:33 +00:00
# endif
2016-02-14 08:59:33 +00:00
nb_fb = 0 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
free_textures ( ) ;
2016-03-10 18:29:41 +00:00
# ifndef _WIN32
2021-05-18 11:51:36 +00:00
// Ziggy for some reasons, Project64 doesn't like remove_tex on exit
2016-02-14 08:59:33 +00:00
remove_tex ( 0 , 0xfffffff ) ;
2015-10-09 04:44:33 +00:00
# endif
# ifdef _WIN32
2016-02-14 08:59:33 +00:00
if ( hGLRC )
{
2021-04-12 11:35:39 +00:00
wglMakeCurrent ( hDC , nullptr ) ;
2016-02-14 08:59:33 +00:00
wglDeleteContext ( hGLRC ) ;
2021-04-12 11:35:39 +00:00
hGLRC = nullptr ;
2016-02-14 08:59:33 +00:00
}
2017-01-28 11:29:03 +00:00
ExitFullScreen ( ) ;
2015-10-09 04:44:33 +00:00
# endif
2017-08-09 22:30:58 +00:00
return true ;
2015-10-09 04:44:33 +00:00
}
2017-07-25 22:17:52 +00:00
void gfxTextureBufferExt ( gfxChipID_t tmu , uint32_t startAddress , gfxLOD_t lodmin , gfxLOD_t lodmax , gfxAspectRatio_t aspect , gfxTextureFormat_t fmt , uint32_t evenOdd )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
int i ;
static int fbs_init = 0 ;
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " tmu: %d startAddress: %d lodmin: %d lodmax: %d aspect: %d fmt: %d evenOdd: %d " , tmu , startAddress , lodmin , lodmax , aspect , fmt , evenOdd ) ;
2021-05-18 11:51:36 +00:00
if ( lodmin ! = lodmax ) WriteTrace ( TraceGlitch , TraceWarning , " gfxTextureBufferExt: Loading more than one LOD " ) ;
2016-02-14 08:59:33 +00:00
if ( ! use_fbo ) {
2021-05-18 11:51:36 +00:00
if ( ! render_to_texture ) { // Initialization
2016-02-14 08:59:33 +00:00
return ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
render_to_texture = 2 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( aspect < 0 )
{
pBufferHeight = 1 < < lodmin ;
pBufferWidth = pBufferHeight > > - aspect ;
}
else
{
pBufferWidth = 1 < < lodmin ;
pBufferHeight = pBufferWidth > > aspect ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( curBufferAddr & & startAddress + 1 ! = curBufferAddr )
updateTexture ( ) ;
2015-10-09 04:44:33 +00:00
# ifdef SAVE_CBUFFER
2016-02-14 08:59:33 +00:00
//printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
2021-05-18 11:51:36 +00:00
// Save color buffer
2016-02-14 08:59:33 +00:00
if ( nbAuxBuffers > 0 ) {
//glDrawBuffer(GL_AUX0);
//current_buffer = GL_AUX0;
}
else {
int tw , th ;
if ( pBufferWidth < screen_width )
tw = pBufferWidth ;
else
tw = screen_width ;
if ( pBufferHeight < screen_height )
th = pBufferHeight ;
else
th = screen_height ;
//glReadBuffer(GL_BACK);
glActiveTexture ( texture_unit ) ;
glBindTexture ( GL_TEXTURE_2D , color_texture ) ;
2021-05-18 11:51:36 +00:00
// Save incrementally the framebuffer
2016-02-14 08:59:33 +00:00
if ( save_w ) {
if ( tw > save_w & & th > save_h ) {
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , save_h ,
2017-03-13 09:34:51 +00:00
0 , g_viewport_offset + save_h , tw , th - save_h ) ;
2016-02-14 08:59:33 +00:00
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , save_w , 0 ,
2017-03-13 09:34:51 +00:00
save_w , g_viewport_offset , tw - save_w , save_h ) ;
2016-02-14 08:59:33 +00:00
save_w = tw ;
save_h = th ;
}
else if ( tw > save_w ) {
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , save_w , 0 ,
2017-03-13 09:34:51 +00:00
save_w , g_viewport_offset , tw - save_w , save_h ) ;
2016-02-14 08:59:33 +00:00
save_w = tw ;
}
else if ( th > save_h ) {
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , save_h ,
2017-03-13 09:34:51 +00:00
0 , g_viewport_offset + save_h , save_w , th - save_h ) ;
2016-02-14 08:59:33 +00:00
save_h = th ;
}
}
else {
glCopyTexSubImage2D ( GL_TEXTURE_2D , 0 , 0 , 0 ,
2017-03-13 09:34:51 +00:00
0 , g_viewport_offset , tw , th ) ;
2016-02-14 08:59:33 +00:00
save_w = tw ;
save_h = th ;
}
glBindTexture ( GL_TEXTURE_2D , default_texture ) ;
2015-10-09 04:44:33 +00:00
}
# endif
2016-02-14 08:59:33 +00:00
if ( startAddress + 1 ! = curBufferAddr | |
( curBufferAddr = = 0L & & nbAuxBuffers = = 0 ) )
buffer_cleared = 0 ;
curBufferAddr = pBufferAddress = startAddress + 1 ;
pBufferFmt = fmt ;
2017-07-23 00:04:04 +00:00
int rtmu = startAddress < gfxTexMinAddress ( GFX_TMU1 ) ? 0 : 1 ;
2016-02-14 08:59:33 +00:00
int size = pBufferWidth * pBufferHeight * 2 ; //grTexFormatSize(fmt);
if ( ( unsigned int ) tmu_usage [ rtmu ] . min > pBufferAddress )
tmu_usage [ rtmu ] . min = pBufferAddress ;
if ( ( unsigned int ) tmu_usage [ rtmu ] . max < pBufferAddress + size )
tmu_usage [ rtmu ] . max = pBufferAddress + size ;
// printf("tmu %d usage now %gMb - %gMb\n",
// rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
2016-03-10 18:29:41 +00:00
g_width = pBufferWidth ;
g_height = pBufferHeight ;
2016-02-14 08:59:33 +00:00
2016-03-10 18:29:41 +00:00
widtho = g_width / 2 ;
heighto = g_height / 2 ;
2016-02-14 08:59:33 +00:00
2021-05-18 11:51:36 +00:00
// This could be improved, but might be enough as long as the set of
2016-02-14 08:59:33 +00:00
// texture buffer addresses stay small
for ( i = ( texbuf_i - 1 ) & ( NB_TEXBUFS - 1 ) ; i ! = texbuf_i ; i = ( i - 1 ) & ( NB_TEXBUFS - 1 ) )
if ( texbufs [ i ] . start = = pBufferAddress )
break ;
texbufs [ i ] . start = pBufferAddress ;
texbufs [ i ] . end = pBufferAddress + size ;
texbufs [ i ] . fmt = fmt ;
if ( i = = texbuf_i )
texbuf_i = ( texbuf_i + 1 ) & ( NB_TEXBUFS - 1 ) ;
//printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
2021-05-18 11:51:36 +00:00
// (Comment by Ziggy) It speeds things up to not delete the buffers
2016-02-14 08:59:33 +00:00
// a better thing would be to delete them *sometimes*
// remove_tex(pBufferAddress+1, pBufferAddress + size);
add_tex ( pBufferAddress ) ;
//printf("viewport %dx%d\n", width, height);
2016-03-10 18:29:41 +00:00
if ( g_height > screen_height ) {
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset + screen_height - g_height , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
}
else
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset , g_width , g_height ) ;
2015-10-09 04:44:33 +00:00
2017-03-13 09:34:51 +00:00
glScissor ( 0 , g_viewport_offset , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
}
else {
2021-05-18 11:51:36 +00:00
if ( ! render_to_texture ) // Initialization
2016-02-14 08:59:33 +00:00
{
if ( ! fbs_init )
{
for ( i = 0 ; i < 100 ; i + + ) fbs [ i ] . address = 0 ;
fbs_init = 1 ;
nb_fb = 0 ;
}
2021-05-18 11:51:36 +00:00
return ; // No need to allocate FBO if render buffer is not texture buffer
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
render_to_texture = 2 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( aspect < 0 )
{
pBufferHeight = 1 < < lodmin ;
pBufferWidth = pBufferHeight > > - aspect ;
}
else
{
pBufferWidth = 1 < < lodmin ;
pBufferHeight = pBufferWidth > > aspect ;
}
pBufferAddress = startAddress + 1 ;
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
g_width = pBufferWidth ;
g_height = pBufferHeight ;
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
widtho = g_width / 2 ;
heighto = g_height / 2 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
for ( i = 0 ; i < nb_fb ; i + + )
{
if ( fbs [ i ] . address = = pBufferAddress )
{
2021-05-18 11:51:36 +00:00
if ( fbs [ i ] . width = = g_width & & fbs [ i ] . height = = g_height ) // Select already allocated FBO
2016-02-14 08:59:33 +00:00
{
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , fbs [ i ] . fbid ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , fbs [ i ] . texid , 0 ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , fbs [ i ] . zbid ) ;
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , fbs [ i ] . zbid ) ;
2016-03-10 18:29:41 +00:00
glViewport ( 0 , 0 , g_width , g_height ) ;
glScissor ( 0 , 0 , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
if ( fbs [ i ] . buff_clear )
{
glDepthMask ( 1 ) ;
2021-05-18 11:51:36 +00:00
glClear ( GL_DEPTH_BUFFER_BIT ) ; // Clear z-buffer only. we may need content, stored in the frame buffer
2016-02-14 08:59:33 +00:00
fbs [ i ] . buff_clear = 0 ;
}
CHECK_FRAMEBUFFER_STATUS ( ) ;
curBufferAddr = pBufferAddress ;
return ;
}
2021-05-18 11:51:36 +00:00
else // Create new FBO at the same address, delete old one
2016-02-14 08:59:33 +00:00
{
glDeleteFramebuffers ( 1 , & ( fbs [ i ] . fbid ) ) ;
glDeleteRenderbuffers ( 1 , & ( fbs [ i ] . zbid ) ) ;
if ( nb_fb > 1 )
memmove ( & ( fbs [ i ] ) , & ( fbs [ i + 1 ] ) , sizeof ( fb ) * ( nb_fb - i ) ) ;
nb_fb - - ;
break ;
}
}
}
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
remove_tex ( pBufferAddress , pBufferAddress + g_width * g_height * 2 /*grTexFormatSize(fmt)*/ ) ;
2021-05-18 11:51:36 +00:00
// Create new FBO
2016-02-14 08:59:33 +00:00
glGenFramebuffers ( 1 , & ( fbs [ nb_fb ] . fbid ) ) ;
glGenRenderbuffers ( 1 , & ( fbs [ nb_fb ] . zbid ) ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , fbs [ nb_fb ] . zbid ) ;
2016-03-10 18:29:41 +00:00
glRenderbufferStorage ( GL_RENDERBUFFER , GL_DEPTH_COMPONENT16 , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
fbs [ nb_fb ] . address = pBufferAddress ;
2016-03-10 18:29:41 +00:00
fbs [ nb_fb ] . width = g_width ;
fbs [ nb_fb ] . height = g_height ;
2016-02-14 08:59:33 +00:00
fbs [ nb_fb ] . texid = pBufferAddress ;
fbs [ nb_fb ] . buff_clear = 0 ;
add_tex ( fbs [ nb_fb ] . texid ) ;
glBindTexture ( GL_TEXTURE_2D , fbs [ nb_fb ] . texid ) ;
2016-03-10 18:29:41 +00:00
glTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB , g_width , g_height , 0 ,
2021-04-12 11:35:39 +00:00
GL_RGB , GL_UNSIGNED_BYTE , nullptr ) ;
2016-02-14 08:59:33 +00:00
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , fbs [ nb_fb ] . fbid ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER ,
GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , fbs [ nb_fb ] . texid , 0 ) ;
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , fbs [ nb_fb ] . zbid ) ;
2016-03-10 18:29:41 +00:00
glViewport ( 0 , 0 , g_width , g_height ) ;
glScissor ( 0 , 0 , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
glClearColor ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
glDepthMask ( 1 ) ;
glClear ( GL_DEPTH_BUFFER_BIT ) ;
CHECK_FRAMEBUFFER_STATUS ( ) ;
curBufferAddr = pBufferAddress ;
nb_fb + + ;
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
2017-07-25 08:29:37 +00:00
int CheckTextureBufferFormat ( gfxChipID_t tmu , uint32_t startAddress , gfxTexInfo * info )
2016-02-14 08:59:33 +00:00
{
int found , i ;
if ( ! use_fbo ) {
for ( found = i = 0 ; i < 2 ; i + + )
2017-07-22 22:42:02 +00:00
if ( ( uint32_t ) tmu_usage [ i ] . min < = startAddress & & ( uint32_t ) tmu_usage [ i ] . max > startAddress ) {
2016-02-14 08:59:33 +00:00
//printf("tmu %d == framebuffer %x\n", tmu, startAddress);
found = 1 ;
break ;
}
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
else {
found = i = 0 ;
while ( i < nb_fb )
{
unsigned int end = fbs [ i ] . address + fbs [ i ] . width * fbs [ i ] . height * 2 ;
if ( startAddress > = fbs [ i ] . address & & startAddress < end )
{
found = 1 ;
break ;
}
i + + ;
}
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
if ( ! use_fbo & & found ) {
int tw , th , rh , cw , ch ;
if ( info - > aspectRatioLog2 < 0 )
{
th = 1 < < info - > largeLodLog2 ;
tw = th > > - info - > aspectRatioLog2 ;
}
else
{
tw = 1 < < info - > largeLodLog2 ;
th = tw > > info - > aspectRatioLog2 ;
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( info - > aspectRatioLog2 < 0 )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
ch = 256 ;
cw = ch > > - info - > aspectRatioLog2 ;
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
else
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
cw = 256 ;
ch = cw > > info - > aspectRatioLog2 ;
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
if ( use_fbo | | th < screen_height )
rh = th ;
else
rh = screen_height ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
//printf("th %d rh %d ch %d\n", th, rh, ch);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
invtex [ tmu ] = 1.0f - ( th - rh ) / ( float ) th ;
2015-10-09 04:44:33 +00:00
}
else
2016-02-14 08:59:33 +00:00
invtex [ tmu ] = 0 ;
2015-10-09 04:44:33 +00:00
2017-05-17 10:34:55 +00:00
if ( info - > format = = GFX_TEXFMT_ALPHA_INTENSITY_88 ) {
2016-02-14 08:59:33 +00:00
if ( ! found ) {
return 0 ;
}
if ( tmu = = 0 )
{
if ( blackandwhite1 ! = found )
{
blackandwhite1 = found ;
need_to_compile = 1 ;
}
}
else
{
if ( blackandwhite0 ! = found )
{
blackandwhite0 = found ;
need_to_compile = 1 ;
}
}
return 1 ;
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
return 0 ;
2015-10-09 04:44:33 +00:00
}
static void render_rectangle ( int texture_number ,
2016-02-14 08:59:33 +00:00
int dst_x , int dst_y ,
int src_width , int src_height ,
int tex_width , int tex_height , int invert )
{
2016-03-10 18:29:41 +00:00
//LOGINFO("render_rectangle(%d,%d,%d,%d,%d,%d,%d,%d)",texture_number,dst_x,dst_y,src_width,src_height,tex_width,tex_height,invert);
2016-02-14 08:59:33 +00:00
static float data [ ] = {
( float ) ( ( int ) dst_x ) , //X 0
( float ) ( invert * - ( ( int ) dst_y ) ) , //Y 0
0.0f , //U 0
0.0f , //V 0
( float ) ( ( int ) dst_x ) , //X 1
( float ) ( invert * - ( ( int ) dst_y + ( int ) src_height ) ) , //Y 1
0.0f , //U 1
( float ) src_height / ( float ) tex_height , //V 1
( float ) ( ( int ) dst_x + ( int ) src_width ) ,
( float ) ( invert * - ( ( int ) dst_y + ( int ) src_height ) ) ,
( float ) src_width / ( float ) tex_width ,
( float ) src_height / ( float ) tex_height ,
( float ) ( ( int ) dst_x ) ,
( float ) ( invert * - ( ( int ) dst_y ) ) ,
0.0f ,
0.0f
} ;
vbo_disable ( ) ;
glDisableVertexAttribArray ( COLOUR_ATTR ) ;
glDisableVertexAttribArray ( TEXCOORD_1_ATTR ) ;
glDisableVertexAttribArray ( FOG_ATTR ) ;
2021-05-18 11:51:36 +00:00
glVertexAttribPointer ( POSITION_ATTR , 2 , GL_FLOAT , false , 2 , data ) ; // Position
glVertexAttribPointer ( TEXCOORD_0_ATTR , 2 , GL_FLOAT , false , 2 , & data [ 2 ] ) ; // Tex
2016-02-14 08:59:33 +00:00
glEnableVertexAttribArray ( COLOUR_ATTR ) ;
glEnableVertexAttribArray ( TEXCOORD_1_ATTR ) ;
glEnableVertexAttribArray ( FOG_ATTR ) ;
disable_textureSizes ( ) ;
glDrawArrays ( GL_TRIANGLE_STRIP , 0 , 4 ) ;
vbo_enable ( ) ;
/*
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glBegin ( GL_QUADS ) ;
glMultiTexCoord2fARB ( texture_number , 0.0f , 0.0f ) ;
glVertex2f ( ( ( int ) dst_x - widtho ) / ( float ) ( width / 2 ) ,
invert * - ( ( int ) dst_y - heighto ) / ( float ) ( height / 2 ) ) ;
glMultiTexCoord2fARB ( texture_number , 0.0f , ( float ) src_height / ( float ) tex_height ) ;
glVertex2f ( ( ( int ) dst_x - widtho ) / ( float ) ( width / 2 ) ,
invert * - ( ( int ) dst_y + ( int ) src_height - heighto ) / ( float ) ( height / 2 ) ) ;
glMultiTexCoord2fARB ( texture_number , ( float ) src_width / ( float ) tex_width , ( float ) src_height / ( float ) tex_height ) ;
glVertex2f ( ( ( int ) dst_x + ( int ) src_width - widtho ) / ( float ) ( width / 2 ) ,
invert * - ( ( int ) dst_y + ( int ) src_height - heighto ) / ( float ) ( height / 2 ) ) ;
glMultiTexCoord2fARB ( texture_number , ( float ) src_width / ( float ) tex_width , 0.0f ) ;
glVertex2f ( ( ( int ) dst_x + ( int ) src_width - widtho ) / ( float ) ( width / 2 ) ,
invert * - ( ( int ) dst_y - heighto ) / ( float ) ( height / 2 ) ) ;
glMultiTexCoord2fARB ( texture_number , 0.0f , 0.0f ) ;
glVertex2f ( ( ( int ) dst_x - widtho ) / ( float ) ( width / 2 ) ,
invert * - ( ( int ) dst_y - heighto ) / ( float ) ( height / 2 ) ) ;
glEnd ( ) ;
*/
compile_shader ( ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_BLEND ) ;
2015-10-09 04:44:33 +00:00
}
void reloadTexture ( )
{
2016-02-14 08:59:33 +00:00
if ( use_fbo | | ! render_to_texture | | buffer_cleared )
return ;
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " width: %d height: %d " , g_width , g_height ) ;
2016-02-14 08:59:33 +00:00
//printf("reload texture %dx%d\n", width, height);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
buffer_cleared = 1 ;
2015-10-09 04:44:33 +00:00
//glPushAttrib(GL_ALL_ATTRIB_BITS);
glActiveTexture ( texture_unit ) ;
glBindTexture ( GL_TEXTURE_2D , pBufferAddress ) ;
2016-02-14 08:59:33 +00:00
//glDisable(GL_ALPHA_TEST);
//glDrawBuffer(current_buffer);
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
set_copy_shader ( ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_CULL_FACE ) ;
int w = 0 , h = 0 ;
2016-03-10 18:29:41 +00:00
if ( g_height > screen_height ) h = screen_height - g_height ;
2016-02-14 08:59:33 +00:00
render_rectangle ( texture_unit ,
- w , - h ,
2016-03-10 18:29:41 +00:00
g_width , g_height ,
g_width , g_height , - 1 ) ;
2015-10-09 04:44:33 +00:00
glBindTexture ( GL_TEXTURE_2D , default_texture ) ;
//glPopAttrib();
2016-02-14 08:59:33 +00:00
}
void updateTexture ( )
{
if ( ! use_fbo & & render_to_texture = = 2 ) {
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " pBufferAddress: %x " , pBufferAddress ) ;
2016-02-14 08:59:33 +00:00
//printf("update texture %x\n", pBufferAddress);
2021-05-18 11:51:36 +00:00
// Nothing changed, don't update the texture
2016-02-14 08:59:33 +00:00
if ( ! buffer_cleared ) {
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " Update cancelled " ) ;
2016-02-14 08:59:33 +00:00
return ;
}
//glPushAttrib(GL_ALL_ATTRIB_BITS);
2021-05-18 11:51:36 +00:00
// Save result of render to texture into actual texture
2016-02-14 08:59:33 +00:00
//glReadBuffer(current_buffer);
glActiveTexture ( texture_unit ) ;
2021-05-18 11:51:36 +00:00
// Ziggy
// Deleting the texture before resampling it increases speed on certain old
// Nvidia cards (GeForce 2 for example), unfortunately it slows down a lot
2016-02-14 08:59:33 +00:00
// on newer cards.
//glDeleteTextures( 1, &pBufferAddress );
glBindTexture ( GL_TEXTURE_2D , pBufferAddress ) ;
glCopyTexImage2D ( GL_TEXTURE_2D , 0 , GL_RGB ,
2017-03-13 09:34:51 +00:00
0 , g_viewport_offset , g_width , g_height , 0 ) ;
2016-02-14 08:59:33 +00:00
glBindTexture ( GL_TEXTURE_2D , default_texture ) ;
//glPopAttrib();
}
2015-10-09 04:44:33 +00:00
}
2017-08-06 22:22:12 +00:00
void gfxRenderBuffer ( gfxBuffer_t buffer )
2015-10-09 04:44:33 +00:00
{
# ifdef _WIN32
2021-04-12 11:35:39 +00:00
static HANDLE region = nullptr ;
2016-02-14 08:59:33 +00:00
int realWidth = pBufferWidth , realHeight = pBufferHeight ;
2015-10-09 04:44:33 +00:00
# endif // _WIN32
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " buffer: %d " , buffer ) ;
2017-05-25 21:48:24 +00:00
//printf("gfxRenderBuffer(%d)\n", buffer);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
switch ( buffer )
2015-10-09 04:44:33 +00:00
{
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_BACKBUFFER :
2016-02-14 08:59:33 +00:00
if ( render_to_texture )
{
updateTexture ( ) ;
2021-05-18 11:51:36 +00:00
// VP Z fix
2016-02-14 08:59:33 +00:00
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
//glTranslatef(0, 0, 1-zscale);
//glScalef(1, 1, zscale);
inverted_culling = 0 ;
2017-05-24 22:36:49 +00:00
gfxCullMode ( culling_mode ) ;
2016-02-14 08:59:33 +00:00
2016-03-10 18:29:41 +00:00
g_width = savedWidth ;
g_height = savedHeight ;
2016-02-14 08:59:33 +00:00
widtho = savedWidtho ;
heighto = savedHeighto ;
if ( use_fbo ) {
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ;
}
curBufferAddr = 0 ;
2017-03-13 09:34:51 +00:00
glViewport ( 0 , g_viewport_offset , g_width , viewport_height ) ;
glScissor ( 0 , g_viewport_offset , g_width , g_height ) ;
2015-10-09 04:44:33 +00:00
# ifdef SAVE_CBUFFER
2016-02-14 08:59:33 +00:00
if ( ! use_fbo & & render_to_texture = = 2 ) {
2021-05-18 11:51:36 +00:00
// Restore color buffer
2016-02-14 08:59:33 +00:00
if ( nbAuxBuffers > 0 ) {
//glDrawBuffer(GL_BACK);
current_buffer = GL_BACK ;
}
else if ( save_w ) {
int tw = 1 , th = 1 ;
//printf("restore %dx%d\n", save_w, save_h);
if ( npot_support ) {
tw = screen_width ;
th = screen_height ;
}
else {
while ( tw < screen_width ) tw < < = 1 ;
while ( th < screen_height ) th < < = 1 ;
}
//glPushAttrib(GL_ALL_ATTRIB_BITS);
//glDisable(GL_ALPHA_TEST);
//glDrawBuffer(GL_BACK);
glActiveTexture ( texture_unit ) ;
glBindTexture ( GL_TEXTURE_2D , color_texture ) ;
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
set_copy_shader ( ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_CULL_FACE ) ;
render_rectangle ( texture_unit ,
0 , 0 ,
save_w , save_h ,
tw , th , - 1 ) ;
glBindTexture ( GL_TEXTURE_2D , default_texture ) ;
//glPopAttrib();
save_w = save_h = 0 ;
}
}
2015-10-09 04:44:33 +00:00
# endif
2016-02-14 08:59:33 +00:00
render_to_texture = 0 ;
}
//glDrawBuffer(GL_BACK);
break ;
2021-05-18 11:51:36 +00:00
case 6 : // Render to texture
2016-02-14 08:59:33 +00:00
if ( ! render_to_texture )
{
2016-03-10 18:29:41 +00:00
savedWidth = g_width ;
savedHeight = g_height ;
2016-02-14 08:59:33 +00:00
savedWidtho = widtho ;
savedHeighto = heighto ;
}
2015-10-09 04:44:33 +00:00
2017-04-18 11:32:43 +00:00
{
if ( ! use_fbo ) {
//glMatrixMode(GL_MODELVIEW);
//glLoadIdentity();
//glTranslatef(0, 0, 1-zscale);
//glScalef(1, 1, zscale);
inverted_culling = 0 ;
}
else {
/*
float m [ 4 * 4 ] = { 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , - 1.0f , 0.0f , 0.0f ,
0.0f , 0.0f , 1.0f , 0.0f ,
0.0f , 0.0f , 0.0f , 1.0f } ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadMatrixf ( m ) ;
// VP z fix
glTranslatef ( 0 , 0 , 1 - zscale ) ;
glScalef ( 1 , 1 * 1 , zscale ) ;
*/
inverted_culling = 1 ;
2017-05-24 22:36:49 +00:00
gfxCullMode ( culling_mode ) ;
2017-04-18 11:32:43 +00:00
}
2016-02-14 08:59:33 +00:00
}
2017-04-18 11:32:43 +00:00
render_to_texture = 1 ;
break ;
2016-02-14 08:59:33 +00:00
default :
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxRenderBuffer: Unknown buffer : %x " , buffer ) ;
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
}
2017-08-06 22:22:12 +00:00
void gfxAuxBufferExt ( gfxBuffer_t buffer )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " buffer: %d " , buffer ) ;
2017-05-25 10:00:21 +00:00
//WriteTrace(TraceGlitch, TraceWarning, "gfxAuxBufferExt");
2016-02-14 08:59:33 +00:00
2017-07-22 06:03:12 +00:00
if ( buffer = = GFX_BUFFER_AUXBUFFER ) {
2016-02-14 08:59:33 +00:00
invtex [ 0 ] = 0 ;
invtex [ 1 ] = 0 ;
need_to_compile = 0 ;
set_depth_shader ( ) ;
glColorMask ( GL_FALSE , GL_FALSE , GL_FALSE , GL_FALSE ) ;
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_ALWAYS ) ;
glDisable ( GL_CULL_FACE ) ;
//glDisable(GL_ALPHA_TEST);
glDepthMask ( GL_TRUE ) ;
2017-08-08 20:23:11 +00:00
gfxTexFilterMode ( GFX_TMU1 , GFX_TEXTUREFILTER_POINT_SAMPLED , GFX_TEXTUREFILTER_POINT_SAMPLED ) ;
2016-02-14 08:59:33 +00:00
}
else {
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
need_to_compile = 1 ;
}
2015-10-09 04:44:33 +00:00
}
2016-03-10 18:29:41 +00:00
2017-07-25 22:25:29 +00:00
void gfxBufferClear ( gfxColor_t color , gfxAlpha_t alpha , uint32_t depth )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " color: %d alpha: %d depth: %d " , color , alpha , depth ) ;
2016-02-14 08:59:33 +00:00
vbo_draw ( ) ;
switch ( lfb_color_fmt )
{
2017-08-03 22:00:04 +00:00
case GFX_COLORFORMAT_ARGB :
2016-02-14 08:59:33 +00:00
glClearColor ( ( ( color > > 16 ) & 0xFF ) / 255.0f ,
( ( color > > 8 ) & 0xFF ) / 255.0f ,
( color & 0xFF ) / 255.0f ,
alpha / 255.0f ) ;
break ;
2017-08-03 22:00:04 +00:00
case GFX_COLORFORMAT_RGBA :
2016-02-14 08:59:33 +00:00
glClearColor ( ( ( color > > 24 ) & 0xFF ) / 255.0f ,
( ( color > > 16 ) & 0xFF ) / 255.0f ,
( color & 0xFF ) / 255.0f ,
alpha / 255.0f ) ;
break ;
default :
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxBufferClear: Unknown color format : %x " , lfb_color_fmt ) ;
2016-02-14 08:59:33 +00:00
}
2015-10-09 04:44:33 +00:00
2016-03-10 18:29:41 +00:00
glClear ( GL_COLOR_BUFFER_BIT ) ;
2016-02-14 08:59:33 +00:00
if ( w_buffer_mode )
glClearDepthf ( 1.0f - ( ( 1.0f + ( depth > > 4 ) / 4096.0f ) * ( 1 < < ( depth & 0xF ) ) ) / 65528.0 ) ;
else
glClearDepthf ( depth / 65535.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2015-10-09 04:44:33 +00:00
2021-05-18 11:51:36 +00:00
// (Comment by Ziggy) TODO: Check that color mask is on
2016-02-14 08:59:33 +00:00
buffer_cleared = 1 ;
2015-10-09 04:44:33 +00:00
}
2017-07-22 22:42:02 +00:00
void gfxBufferSwap ( uint32_t swap_interval )
2016-02-14 08:59:33 +00:00
{
// GLuint program;
vbo_draw ( ) ;
// glFinish();
// printf("rendercallback is %p\n", renderCallback);
2016-03-10 18:29:41 +00:00
//if (renderCallback) {
// glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*) &program);
// glUseProgramObjectARB(0);
//(*renderCallback)(1);
// if (program)
// glUseProgramObjectARB(program);
//}
2016-02-14 08:59:33 +00:00
int i ;
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " swap_interval: %d " , swap_interval ) ;
2016-02-14 08:59:33 +00:00
//printf("swap\n");
if ( render_to_texture ) {
WriteTrace ( TraceGlitch , TraceWarning , " swap while render_to_texture \n " ) ;
return ;
}
2015-10-09 04:44:33 +00:00
2016-12-28 00:25:18 +00:00
# ifdef ANDROID
2016-03-10 18:29:41 +00:00
Android_JNI_SwapWindow ( ) ;
2016-12-28 00:25:18 +00:00
# else
SwapBuffers ( ) ;
# endif
2016-02-14 08:59:33 +00:00
for ( i = 0 ; i < nb_fb ; i + + )
fbs [ i ] . buff_clear = 1 ;
2017-05-16 10:03:02 +00:00
}
2015-10-09 04:44:33 +00:00
2021-05-18 11:51:36 +00:00
// Frame buffer
2017-08-08 12:21:56 +00:00
bool gfxLfbLock ( gfxLock_t type , gfxBuffer_t buffer , gfxLfbWriteMode_t writeMode , gfxOriginLocation_t origin , bool pixelPipeline , gfxLfbInfo_t * info )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " type: %d buffer: %d writeMode: %d origin: %d pixelPipeline: %d " , type , buffer , writeMode , origin , pixelPipeline ) ;
2017-08-04 23:01:05 +00:00
if ( type = = GFX_LFB_WRITE_ONLY )
2016-02-14 08:59:33 +00:00
{
2017-05-25 22:21:29 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxLfbLock : write only " ) ;
2016-02-14 08:59:33 +00:00
}
else
{
unsigned char * buf ;
int i , j ;
switch ( buffer )
{
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_FRONTBUFFER :
2016-02-14 08:59:33 +00:00
//glReadBuffer(GL_FRONT);
break ;
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_BACKBUFFER :
2016-02-14 08:59:33 +00:00
//glReadBuffer(GL_BACK);
break ;
default :
2017-05-25 22:21:29 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxLfbLock : unknown buffer : %x " , buffer ) ;
2017-05-16 10:03:02 +00:00
}
2016-02-14 08:59:33 +00:00
2017-07-22 06:03:12 +00:00
if ( buffer ! = GFX_BUFFER_AUXBUFFER )
2016-02-14 08:59:33 +00:00
{
2017-08-08 12:16:31 +00:00
if ( writeMode = = GFX_LFBWRITEMODE_888 ) {
//printf("LfbLock GFX_LFBWRITEMODE_888\n");
2016-02-14 08:59:33 +00:00
info - > lfbPtr = frameBuffer ;
2016-03-10 18:29:41 +00:00
info - > strideInBytes = g_width * 4 ;
2017-08-08 12:16:31 +00:00
info - > writeMode = GFX_LFBWRITEMODE_888 ;
2016-02-14 08:59:33 +00:00
info - > origin = origin ;
2017-03-13 09:34:51 +00:00
glReadPixels ( 0 , g_viewport_offset , g_width , g_height , GL_RGBA , GL_UNSIGNED_BYTE , frameBuffer ) ;
2016-02-14 08:59:33 +00:00
}
else {
2016-03-10 18:29:41 +00:00
buf = ( unsigned char * ) malloc ( g_width * g_height * 4 ) ;
2016-02-14 08:59:33 +00:00
info - > lfbPtr = frameBuffer ;
2016-03-10 18:29:41 +00:00
info - > strideInBytes = g_width * 2 ;
2017-08-08 12:16:31 +00:00
info - > writeMode = GFX_LFBWRITEMODE_565 ;
2016-02-14 08:59:33 +00:00
info - > origin = origin ;
2017-03-13 09:34:51 +00:00
glReadPixels ( 0 , g_viewport_offset , g_width , g_height , GL_RGBA , GL_UNSIGNED_BYTE , buf ) ;
2016-02-14 08:59:33 +00:00
2016-03-10 18:29:41 +00:00
for ( j = 0 ; j < g_height ; j + + )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
for ( i = 0 ; i < g_width ; i + + )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
frameBuffer [ ( g_height - j - 1 ) * g_width + i ] =
( ( buf [ j * g_width * 4 + i * 4 + 0 ] > > 3 ) < < 11 ) |
( ( buf [ j * g_width * 4 + i * 4 + 1 ] > > 2 ) < < 5 ) |
( buf [ j * g_width * 4 + i * 4 + 2 ] > > 3 ) ;
2016-02-14 08:59:33 +00:00
}
}
free ( buf ) ;
}
}
else
{
info - > lfbPtr = depthBuffer ;
2016-03-10 18:29:41 +00:00
info - > strideInBytes = g_width * 2 ;
2017-08-08 12:16:31 +00:00
info - > writeMode = GFX_LFBWRITEMODE_ZA16 ;
2016-02-14 08:59:33 +00:00
info - > origin = origin ;
2017-03-13 09:34:51 +00:00
glReadPixels ( 0 , g_viewport_offset , g_width , g_height , GL_DEPTH_COMPONENT , GL_UNSIGNED_SHORT , depthBuffer ) ;
2016-02-14 08:59:33 +00:00
}
2017-05-16 10:03:02 +00:00
}
2016-02-14 08:59:33 +00:00
2017-08-09 22:30:58 +00:00
return true ;
2017-05-17 08:13:04 +00:00
}
2016-02-14 08:59:33 +00:00
2017-08-06 22:22:12 +00:00
bool gfxLfbUnlock ( gfxLock_t type , gfxBuffer_t buffer )
2016-02-14 08:59:33 +00:00
{
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " type: %d, buffer: %d " , type , buffer ) ;
2017-08-04 23:01:05 +00:00
if ( type = = GFX_LFB_WRITE_ONLY )
2016-02-14 08:59:33 +00:00
{
2017-05-26 06:32:47 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxLfbUnlock : write only " ) ;
2016-02-14 08:59:33 +00:00
}
2017-08-09 22:30:58 +00:00
return true ;
2016-02-14 08:59:33 +00:00
}
2017-08-06 22:22:12 +00:00
bool gfxLfbReadRegion ( gfxBuffer_t src_buffer , uint32_t src_x , uint32_t src_y , uint32_t src_width , uint32_t src_height , uint32_t dst_stride , void * dst_data )
2016-02-14 08:59:33 +00:00
{
2015-10-09 04:44:33 +00:00
unsigned char * buf ;
2016-02-14 08:59:33 +00:00
unsigned int i , j ;
unsigned short * frameBuffer = ( unsigned short * ) dst_data ;
unsigned short * depthBuffer = ( unsigned short * ) dst_data ;
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " src_buffer: %d src_x: %d src_y: %d src_width: %d src_height: %d dst_stride: %d " , src_buffer , src_x , src_y , src_width , src_height , dst_stride ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
switch ( src_buffer )
2015-10-09 04:44:33 +00:00
{
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_FRONTBUFFER :
2016-02-14 08:59:33 +00:00
//glReadBuffer(GL_FRONT);
break ;
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_BACKBUFFER :
2016-02-14 08:59:33 +00:00
//glReadBuffer(GL_BACK);
break ;
2017-07-22 06:03:12 +00:00
/*case GFX_BUFFER_AUXBUFFER:
2016-02-14 08:59:33 +00:00
glReadBuffer ( current_buffer ) ;
break ; */
2015-10-09 04:44:33 +00:00
default :
2016-02-14 08:59:33 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " grReadRegion : unknown buffer : %x " , src_buffer ) ;
2015-10-09 04:44:33 +00:00
}
2017-07-22 06:03:12 +00:00
if ( src_buffer ! = GFX_BUFFER_AUXBUFFER )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
buf = ( unsigned char * ) malloc ( src_width * src_height * 4 ) ;
2017-03-13 09:34:51 +00:00
glReadPixels ( src_x , ( g_viewport_offset ) + g_height - src_y - src_height , src_width , src_height , GL_RGBA , GL_UNSIGNED_BYTE , buf ) ;
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
for ( i = 0 ; i < src_width ; i + + )
{
frameBuffer [ j * ( dst_stride / 2 ) + i ] =
( ( buf [ ( src_height - j - 1 ) * src_width * 4 + i * 4 + 0 ] > > 3 ) < < 11 ) |
( ( buf [ ( src_height - j - 1 ) * src_width * 4 + i * 4 + 1 ] > > 2 ) < < 5 ) |
( buf [ ( src_height - j - 1 ) * src_width * 4 + i * 4 + 2 ] > > 3 ) ;
}
2015-10-09 04:44:33 +00:00
}
free ( buf ) ;
}
else
{
2016-02-14 08:59:33 +00:00
buf = ( unsigned char * ) malloc ( src_width * src_height * 2 ) ;
2017-03-13 09:34:51 +00:00
glReadPixels ( src_x , ( g_viewport_offset ) + g_height - src_y - src_height , src_width , src_height , GL_DEPTH_COMPONENT , GL_UNSIGNED_SHORT , depthBuffer ) ;
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
{
for ( i = 0 ; i < src_width ; i + + )
{
depthBuffer [ j * ( dst_stride / 2 ) + i ] =
( ( unsigned short * ) buf ) [ ( src_height - j - 1 ) * src_width * 4 + i * 4 ] ;
}
}
free ( buf ) ;
2015-10-09 04:44:33 +00:00
}
2017-08-09 22:30:58 +00:00
return true ;
2015-10-09 04:44:33 +00:00
}
2017-08-08 21:32:10 +00:00
bool gfxLfbWriteRegion ( gfxBuffer_t dst_buffer , uint32_t dst_x , uint32_t dst_y , gfxLfbSrcFmt_t src_format , uint32_t src_width , uint32_t src_height , bool pixelPipeline , int32_t src_stride , void * src_data )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
unsigned char * buf ;
unsigned int i , j ;
unsigned short * frameBuffer = ( unsigned short * ) src_data ;
int texture_number ;
unsigned int tex_width = 1 , tex_height = 1 ;
2016-03-10 18:29:41 +00:00
WriteTrace ( TraceGlitch , TraceDebug , " dst_buffer: %d dst_x: %d dst_y: %d src_format: %d src_width: %d src_height: %d pixelPipeline: %d src_stride: %d " , dst_buffer , dst_x , dst_y , src_format , src_width , src_height , pixelPipeline , src_stride ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
//glPushAttrib(GL_ALL_ATTRIB_BITS);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
while ( tex_width < src_width ) tex_width < < = 1 ;
while ( tex_height < src_height ) tex_height < < = 1 ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
switch ( dst_buffer )
2015-10-09 04:44:33 +00:00
{
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_BACKBUFFER :
2016-02-14 08:59:33 +00:00
//glDrawBuffer(GL_BACK);
break ;
2017-07-22 06:03:12 +00:00
case GFX_BUFFER_AUXBUFFER :
2016-02-14 08:59:33 +00:00
//glDrawBuffer(current_buffer);
break ;
default :
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxLfbWriteRegion: Unknown buffer : %x " , dst_buffer ) ;
2015-10-09 04:44:33 +00:00
}
2017-07-22 06:03:12 +00:00
if ( dst_buffer ! = GFX_BUFFER_AUXBUFFER )
2015-10-09 04:44:33 +00:00
{
2016-02-14 08:59:33 +00:00
buf = ( unsigned char * ) malloc ( tex_width * tex_height * 4 ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
texture_number = GL_TEXTURE0 ;
glActiveTexture ( texture_number ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
const unsigned int half_stride = src_stride / 2 ;
switch ( src_format )
2015-10-09 04:44:33 +00:00
{
2017-08-04 23:01:05 +00:00
case GFX_LFB_SRC_FMT_1555 :
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
{
for ( i = 0 ; i < src_width ; i + + )
{
const unsigned int col = frameBuffer [ j * half_stride + i ] ;
buf [ j * tex_width * 4 + i * 4 + 0 ] = ( ( col > > 10 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 1 ] = ( ( col > > 5 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 2 ] = ( ( col > > 0 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 3 ] = ( col > > 15 ) ? 0xFF : 0 ;
}
}
break ;
2017-08-08 12:16:31 +00:00
case GFX_LFBWRITEMODE_555 :
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
{
for ( i = 0 ; i < src_width ; i + + )
{
const unsigned int col = frameBuffer [ j * half_stride + i ] ;
buf [ j * tex_width * 4 + i * 4 + 0 ] = ( ( col > > 10 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 1 ] = ( ( col > > 5 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 2 ] = ( ( col > > 0 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 3 ] = 0xFF ;
}
}
break ;
2017-08-08 12:16:31 +00:00
case GFX_LFBWRITEMODE_565 :
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
{
for ( i = 0 ; i < src_width ; i + + )
{
const unsigned int col = frameBuffer [ j * half_stride + i ] ;
buf [ j * tex_width * 4 + i * 4 + 0 ] = ( ( col > > 11 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 1 ] = ( ( col > > 5 ) & 0x3F ) < < 2 ;
buf [ j * tex_width * 4 + i * 4 + 2 ] = ( ( col > > 0 ) & 0x1F ) < < 3 ;
buf [ j * tex_width * 4 + i * 4 + 3 ] = 0xFF ;
}
}
break ;
default :
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " gfxLfbWriteRegion: Unknown format : %d " , src_format ) ;
2015-10-09 04:44:33 +00:00
}
2016-02-14 08:59:33 +00:00
glBindTexture ( GL_TEXTURE_2D , default_texture ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , 4 , tex_width , tex_height , 0 , GL_RGBA , GL_UNSIGNED_BYTE , buf ) ;
free ( buf ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
set_copy_shader ( ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_BLEND ) ;
render_rectangle ( texture_number ,
dst_x , dst_y ,
src_width , src_height ,
tex_width , tex_height , + 1 ) ;
2017-05-16 20:03:55 +00:00
}
2016-02-14 08:59:33 +00:00
else
{
2017-04-18 11:32:43 +00:00
float * buf = ( float * ) malloc ( src_width * ( src_height + ( g_viewport_offset ) ) * sizeof ( float ) ) ;
2015-10-09 04:44:33 +00:00
2017-08-08 12:16:31 +00:00
if ( src_format ! = GFX_LFBWRITEMODE_ZA16 )
2021-05-18 11:51:36 +00:00
WriteTrace ( TraceGlitch , TraceWarning , " Unknown depth buffer write format:%x " , src_format ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
if ( dst_x | | dst_y )
WriteTrace ( TraceGlitch , TraceWarning , " dst_x:%d, dst_y:%d \n " , dst_x , dst_y ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
for ( j = 0 ; j < src_height ; j + + )
{
for ( i = 0 ; i < src_width ; i + + )
{
2017-03-13 09:34:51 +00:00
buf [ ( j + ( g_viewport_offset ) ) * src_width + i ] =
2016-02-14 08:59:33 +00:00
( frameBuffer [ ( src_height - j - 1 ) * ( src_stride / 2 ) + i ] / ( 65536.0f * ( 2.0f / zscale ) ) ) + 1 - zscale / 2.0f ;
}
2017-05-16 10:03:02 +00:00
}
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
glEnable ( GL_DEPTH_TEST ) ;
glDepthFunc ( GL_ALWAYS ) ;
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
//glDrawBuffer(GL_BACK);
glClear ( GL_DEPTH_BUFFER_BIT ) ;
glDepthMask ( 1 ) ;
2017-03-13 09:34:51 +00:00
//glDrawPixels(src_width, src_height+(g_viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
2015-10-09 04:44:33 +00:00
2016-02-14 08:59:33 +00:00
free ( buf ) ;
2017-05-16 10:03:02 +00:00
}
2016-02-14 08:59:33 +00:00
//glDrawBuffer(current_buffer);
//glPopAttrib();
2017-08-09 22:30:58 +00:00
return true ;
2017-05-17 08:13:04 +00:00
}
2015-10-09 04:44:33 +00:00
2021-05-18 11:51:36 +00:00
// Wrapper-specific Glide extensions
2017-07-22 22:42:02 +00:00
void gfxLoadGammaTable ( uint32_t nentries , uint32_t * red , uint32_t * green , uint32_t * blue )
2015-10-09 04:44:33 +00:00
{
}
2017-07-22 22:42:02 +00:00
void gfxGetGammaTableExt ( uint32_t nentries , uint32_t * red , uint32_t * green , uint32_t * blue )
2015-10-09 04:44:33 +00:00
{
return ;
}
2017-08-08 22:33:31 +00:00
void gfxGammaCorrectionRGB ( float gammaR , float gammaG , float gammaB )
2015-10-09 04:44:33 +00:00
{
}
2016-03-10 18:06:18 +00:00
void CHECK_FRAMEBUFFER_STATUS ( void )
{
GLenum status ;
status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
WriteTrace ( TraceGlitch , TraceDebug , " status: %X " , status ) ;
2017-04-18 11:32:43 +00:00
switch ( status ) {
2016-03-10 18:06:18 +00:00
case GL_FRAMEBUFFER_COMPLETE :
2021-05-18 11:51:36 +00:00
//WriteTrace(TraceGlitch, TraceWarning, "Frame buffer complete!\n");
2016-03-10 18:06:18 +00:00
break ;
case GL_FRAMEBUFFER_UNSUPPORTED :
WriteTrace ( TraceGlitch , TraceWarning , " framebuffer GL_FRAMEBUFFER_UNSUPPORTED_EXT \n " ) ;
2021-05-18 11:51:36 +00:00
// You have to choose different formats
//assert(0);
2016-03-10 18:06:18 +00:00
break ;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :
WriteTrace ( TraceGlitch , TraceWarning , " framebuffer INCOMPLETE_ATTACHMENT \n " ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :
WriteTrace ( TraceGlitch , TraceWarning , " framebuffer FRAMEBUFFER_MISSING_ATTACHMENT \n " ) ;
break ;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS :
WriteTrace ( TraceGlitch , TraceWarning , " framebuffer FRAMEBUFFER_DIMENSIONS \n " ) ;
break ;
default :
break ;
2021-05-18 11:51:36 +00:00
// Programming error; will fail on all hardware
//assert(0);
2017-05-16 10:03:02 +00:00
}
2021-05-18 11:51:36 +00:00
}