project64/Source/Project64-video/Renderer/OGLglitchmain.cpp

2051 lines
74 KiB
C++
Raw Normal View History

2017-04-26 10:23:36 +00:00
/***************************************************************************
* *
* Project64-video - A Nintendo 64 gfx plugin. *
* http://www.pj64-emu.com/ *
* Copyright (C) 2017 Project64. All rights reserved. *
* Copyright (C) 2003-2009 Sergey 'Gonetz' Lipski *
* Copyright (C) 2002 Dave2001 *
* *
* License: *
* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html *
* version 2 of the License, or (at your option) any later version. *
* *
****************************************************************************/
2017-05-17 08:01:54 +00:00
#include <Project64-video/Renderer/Renderer.h>
2013-04-10 07:08:48 +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>
#include "glide.h"
#include "g3ext.h"
#include "glitchmain.h"
#include <Project64-video/trace.h>
2017-07-22 22:31:08 +00:00
#include <Project64-video/Settings.h>
2016-03-26 01:26:53 +00:00
#include <Common/Util.h>
2013-04-10 07:08:48 +00:00
/*
* `GetSystemSetting` and `FindSystemSettingId` from Project64 debugger
2017-04-18 11:32:43 +00:00
* used only in g_Notify->DisplayError when OpenGL extension loading fails on WGL
*/
#include <Settings/Settings.h>
2013-04-10 07:08:48 +00:00
int screen_width, screen_height;
2016-02-03 21:21:30 +00:00
static inline void opt_glCopyTexImage2D(GLenum target,
GLint level,
GLint 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 == width && h == height && fmt == internalFormat) {
if (x + width >= screen_width) {
width = screen_width - x;
//printf("resizing w --> %d\n", width);
}
if (y + height >= screen_height + g_viewport_offset) {
height = screen_height + g_viewport_offset - y;
2016-02-03 21:21:30 +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);
}
grDisplayGLError("opt_glCopyTexImage2D");
2013-04-10 07:08:48 +00:00
}
#define glCopyTexImage2D opt_glCopyTexImage2D
#ifdef _WIN32
/*
* Some post-1.1 OpenGL functions can fail to be loaded through GL extensions
* when running primitive OpenGL contexts on Microsoft Windows, specifically.
*
* As of the Project64 Glide64 version, Glitch64 now assigns these GL
* functions to dummy functions to prevent access violations, while also
* displaying error information showing the missing OpenGL support.
*/
2013-04-10 07:08:48 +00:00
PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
PFNGLFOGCOORDFPROC glFogCoordfEXT;
void APIENTRY dummy_glActiveTexture(GLenum/*texture*/)
{ /* GLX render opcode 197, req. OpenGL 1.3 (1.2 w/ ARB_multitexture) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glActiveTexture");
}
void APIENTRY dummy_glMultiTexCoord2f(GLenum/*target*/, GLfloat/*s*/, GLfloat/*t*/)
{ /* GLX render opcode 203, req. OpenGL 1.3 (1.2 w/ ARB_multitexture) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glMultiTexCoord2f");
}
void APIENTRY dummy_glFogCoordf(GLfloat/*coord*/)
{ /* GLX render opcode 4124, req. OpenGL 1.4 (1.1 w/ EXT_fog_coord) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glFogCoordf");
}
void APIENTRY dummy_glBlendFuncSeparate(GLenum, GLenum, GLenum, GLenum)
{ /* GLX render opcode 4134, req. OpenGL 1.0 w/ EXT_blend_func_separate */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glBlendFuncSeparate");
}
2013-04-10 07:08:48 +00:00
PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
const char * APIENTRY dummy_wglGetExtensionsString(HDC)
{
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("wglGetExtensionsString");
return NULL;
}
2013-04-10 07:08:48 +00:00
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
void APIENTRY dummy_glGenRenderbuffers(GLsizei/*n*/, GLuint* /*renderbuffers*/)
{ /* GLX vendor opcode 1423, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glGenRenderbuffers");
}
void APIENTRY dummy_glGenFramebuffers(GLsizei/*n*/, GLuint* /*framebuffers*/)
{ /* GLX vendor opcode 1426, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glGenFramebuffers");
}
GLenum APIENTRY dummy_glCheckFramebufferStatus(GLenum/*target*/)
{ /* GLX vendor opcode 1427, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glCheckFramebufferStatus");
return 0x00008CDD; /* GL_FRAMEBUFFER_UNSUPPORTED */
}
void APIENTRY dummy_glBindRenderbuffer(GLenum/*target*/, GLuint/*renderbuffer*/)
{ /* GLX render opcode 4316, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glBindRenderbuffer");
}
void APIENTRY dummy_glDeleteRenderbuffers(GLsizei/*n*/, const GLuint* /*renderbuffers*/)
{ /* GLX render opcode 4317, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glDeleteRenderbuffers");
}
void APIENTRY dummy_glRenderbufferStorage(GLenum, GLenum, GLsizei, GLsizei)
{ /* GLX render opcode 4318, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glRenderbufferStorage");
}
void APIENTRY dummy_glBindFramebuffer(GLenum/*target*/, GLuint/*framebuffer*/)
{ /* GLX render opcode 4319, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glBindFramebuffer");
}
void APIENTRY dummy_glDeleteFramebuffers(GLsizei/*n*/, const GLuint* /*framebuffers*/)
{ /* GLX render opcode 4320, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glDeleteFramebuffers");
}
void APIENTRY dummy_glFramebufferTexture2D(GLenum, GLenum, GLenum, GLuint, GLint)
{ /* GLX render opcode 4322, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glFramebufferTexture2D");
}
void APIENTRY dummy_glFramebufferRenderbuffer(GLenum, GLenum, GLenum, GLuint)
{ /* GLX render opcode 4324, req. OpenGL 1.2 w/ EXT_framebuffer_object */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glFramebufferRenderbuffer");
}
2013-04-10 07:08:48 +00:00
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;
void APIENTRY dummy_glSecondaryColor3f(GLfloat/*red*/, GLfloat/*green*/, GLfloat/*blue*/)
{ /* GLX render opcode 4129, req. OpenGL 1.4 (1.1 w/ EXT_secondary_color) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glSecondaryColor3f");
}
GLuint APIENTRY dummy_glCreateShader(GLenum/*type*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glCreateShader");
return ((GLuint)(NULL));
}
void APIENTRY dummy_glShaderSource(GLuint, GLsizei, const GLchar **, GLint *)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glShaderSource");
}
void APIENTRY dummy_glCompileShader(GLuint/*shader*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glCompileShader");
}
GLuint APIENTRY dummy_glCreateProgram(void)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glCreateProgram");
return ((GLuint)(NULL));
}
void APIENTRY dummy_glAttachObject(GLhandleARB, GLhandleARB)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glAttachObject");
}
void APIENTRY dummy_glLinkProgram(GLuint/*program*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glLinkProgram");
}
void APIENTRY dummy_glUseProgram(GLuint/*program*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glUseProgram");
}
GLint APIENTRY dummy_glGetUniformLocation(GLuint/*program*/, GLchar* /*name*/)
{ /* GLX single opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glGetUniformLocation");
return -1;
}
void APIENTRY dummy_glUniform1i(GLint/*location*/, GLint/*v0*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glUniform1i");
}
void APIENTRY dummy_glUniform4i(GLint/*location*/, GLint, GLint, GLint, GLint)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glUniform4i");
}
void APIENTRY dummy_glUniform1f(GLint/*location*/, GLfloat/*v0*/)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glUniform1f");
}
void APIENTRY dummy_glUniform4f(GLint/*location*/, GLfloat, GLfloat, GLfloat, GLfloat)
{ /* GLX render opcode ?, req. OpenGL 2.0 (1.2 w/ ARB_shader_objects) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glUniform4f");
}
void APIENTRY dummy_glDeleteObject(GLhandleARB/*obj*/)
{ /* GLX render opcode ?, req. OpenGL 1.2 w/ ARB_shader_objects */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glDeleteObject");
}
void APIENTRY dummy_glGetInfoLog(GLhandleARB, GLsizei, GLsizei *, GLcharARB *)
{ /* GLX single opcode ?, req. OpenGL 1.2 w/ ARB_shader_objects */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glGetInfoLog");
}
void APIENTRY dummy_glGetObjectParameteriv(GLhandleARB, GLenum, GLint *)
{ /* GLX single opcode ?, req. OpenGL 1.2 w/ ARB_shader_objects */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glGetObjectParameteriv");
}
2013-04-10 07:08:48 +00:00
// FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
// 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;
void APIENTRY dummy_glCompressedTexImage2D(GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *)
{ /* GLX render opcode 215, req. OpenGL 1.3 (1.2 w/ ARB_texture_compression) */
2017-04-18 11:32:43 +00:00
g_Notify->DisplayError("glCompressedTexImage2D");
}
2013-04-10 07:08:48 +00:00
#endif // _WIN32
typedef struct
{
2016-02-03 21:21:30 +00:00
unsigned int address;
int width;
int height;
unsigned int fbid;
unsigned int zbid;
unsigned int texid;
int buff_clear;
2013-04-10 07:08:48 +00:00
} fb;
int nbAuxBuffers, current_buffer;
int g_width, widtho, heighto, g_height;
2013-04-10 07:08:48 +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;
// ZIGGY
// to allocate a new static texture name, take the value (free_texture++)
int free_texture;
int default_texture; // the infamous "32*1024*1024" is now configurable
int current_texture;
int depth_texture, color_texture;
int glsl_support = 1;
int viewport_width, viewport_height, g_viewport_offset = 0, nvidia_viewport_hack = 0;
2013-04-10 07:08:48 +00:00
int save_w, save_h;
int lfb_color_fmt;
float invtex[2];
#ifdef _WIN32
static HDC hDC = NULL;
static HGLRC hGLRC = NULL;
static HWND hToolBar = NULL;
#endif // _WIN32
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;
struct TMU_USAGE { unsigned long min, max; } tmu_usage[2] = {
2016-02-03 21:21:30 +00:00
{ 0x0FFFFFFFul, 0x00000000ul },
{ 0x0FFFFFFFul, 0x00000000ul },
};
2013-04-10 07:08:48 +00:00
struct texbuf_t {
2017-07-22 22:42:02 +00:00
uint32_t start, end;
2016-02-03 21:21:30 +00:00
int fmt;
2013-04-10 07:08:48 +00:00
};
#define NB_TEXBUFS 128 // MUST be a power of two
static texbuf_t texbufs[NB_TEXBUFS];
static int texbuf_i;
2016-02-03 21:21:30 +00:00
unsigned short frameBuffer[2048 * 2048];
unsigned short depthBuffer[2048 * 2048];
2013-04-10 07:08:48 +00:00
//#define VOODOO1
2017-07-22 22:42:02 +00:00
void gfxClipWindow(uint32_t minx, uint32_t miny, uint32_t maxx, uint32_t maxy)
2016-02-03 21:21:30 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "minx = %d, miny: %d maxy: %d", minx, miny, maxy);
2016-02-03 21:21:30 +00:00
if (use_fbo && render_to_texture)
2017-04-27 07:31:49 +00:00
{
2016-02-03 21:21:30 +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);
grDisplayGLError("gfxClipWindow :: use_fbo");
2016-02-03 21:21:30 +00:00
return;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (!use_fbo) {
int th = g_height;
2016-02-03 21:21:30 +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 ((FxI32)maxx > g_width) maxx = g_width;
if ((FxI32)maxy > g_height) maxy = g_height;
2016-02-03 21:21:30 +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 + g_viewport_offset, maxx - minx, maxy - miny);
2016-02-03 21:21:30 +00:00
//printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
}
else
{
glScissor(minx, (g_viewport_offset)+g_height - maxy, maxx - minx, maxy - miny);
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
glEnable(GL_SCISSOR_TEST);
grDisplayGLError("gfxClipWindow");
2013-04-10 07:08:48 +00:00
}
2017-07-22 23:03:22 +00:00
void gfxColorMask(bool rgb, bool a)
2013-04-10 07:08:48 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "rgb = %d, a: %d", rgb, a);
2016-02-03 21:21:30 +00:00
glColorMask((GLboolean)rgb, (GLboolean)rgb, (GLboolean)rgb, (GLboolean)a);
grDisplayGLError("gfxColorMask");
2013-04-10 07:08:48 +00:00
}
int isExtensionSupported(const char *extension)
{
2016-02-03 21:21:30 +00:00
const GLubyte *extensions = NULL;
const GLubyte *start;
GLubyte *where, *terminator;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
where = (GLubyte *)strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
extensions = glGetString(GL_EXTENSIONS);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
start = extensions;
for (;;)
{
where = (GLubyte *)strstr((const char *)start, extension);
if (!where)
break;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
terminator = where + strlen(extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return 1;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
start = terminator;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
return 0;
2013-04-10 07:08:48 +00:00
}
#ifdef _WIN32
int isWglExtensionSupported(const char *extension)
{
2016-02-03 21:21:30 +00:00
const GLubyte *extensions = NULL;
const GLubyte *start;
GLubyte *where, *terminator;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
where = (GLubyte *)strchr(extension, ' ');
if (where || *extension == '\0')
return 0;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
start = extensions;
for (;;)
{
where = (GLubyte *)strstr((const char *)start, extension);
if (!where)
break;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
terminator = where + strlen(extension);
if (where == start || *(where - 1) == ' ')
if (*terminator == ' ' || *terminator == '\0')
return 1;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
start = terminator;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
return 0;
2013-04-10 07:08:48 +00:00
}
#endif // _WIN32
#define GrPixelFormat_t int
2016-03-08 21:55:19 +00:00
#ifdef _WIN32
2013-04-10 07:08:48 +00:00
# include <fcntl.h>
# ifndef ATTACH_PARENT_PROCESS
2017-07-22 22:42:02 +00:00
# define ATTACH_PARENT_PROCESS ((uint32_t)-1)
2013-04-10 07:08:48 +00:00
# endif
extern HWND g_hwnd_win;
2013-04-10 07:08:48 +00:00
#endif
bool gfxSstWinOpen(gfxColorFormat_t color_format, GrOriginLocation_t origin_location, int nColBuffers, int nAuxBuffers)
2016-02-03 21:21:30 +00:00
{
static int show_warning = 1;
// ZIGGY
// allocate static texture names
// the initial value should be big enough to support the maximal resolution
free_texture = 32 * 2048 * 2048;
default_texture = free_texture++;
color_texture = free_texture++;
depth_texture = free_texture++;
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cAuxBuffers = 1;
int pfm;
#else
fputs("ERROR: No GLX yet to start GL on [Free]BSD, Linux etc.\n", stderr);
2013-04-10 07:08:48 +00:00
#endif // _WIN32
WriteTrace(TraceGlitch, TraceDebug, "color_format: %d, origin_location: %d, nColBuffers: %d, nAuxBuffers: %d", color_format, origin_location, nColBuffers, nAuxBuffers);
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2017-07-22 22:31:08 +00:00
TMU_SIZE = ((g_settings->wrpVRAM() * 1024 * 1024) - g_width * g_height * 4 * 3) / 2;
2016-02-03 21:21:30 +00:00
// save screen resolution for hwfbe, after resolution enumeration
screen_width = g_width;
screen_height = g_height;
2016-02-03 21:21:30 +00:00
if ((hDC = GetDC(g_hwnd_win)) == NULL)
2016-02-03 21:21:30 +00:00
{
WriteTrace(TraceGlitch, TraceWarning, "GetDC on main window failed");
2016-02-03 21:21:30 +00:00
return FXFALSE;
}
if ((pfm = ChoosePixelFormat(hDC, &pfd)) == 0) {
//printf("disabling auxiliary buffers\n");
pfd.cAuxBuffers = 0;
pfm = ChoosePixelFormat(hDC, &pfd);
}
if (pfm == 0)
{
WriteTrace(TraceGlitch, TraceWarning, "ChoosePixelFormat failed");
2016-02-03 21:21:30 +00:00
return FXFALSE;
}
if (SetPixelFormat(hDC, pfm, &pfd) == 0)
{
WriteTrace(TraceGlitch, TraceWarning, "SetPixelFormat failed");
2016-02-03 21:21:30 +00:00
return FXFALSE;
}
if ((hGLRC = wglCreateContext(hDC)) == 0)
2013-04-10 07:08:48 +00:00
{
WriteTrace(TraceGlitch, TraceWarning, "wglCreateContext failed!");
gfxSstWinClose();
2016-02-03 21:21:30 +00:00
return FXFALSE;
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +00:00
HGLRC CurrenthGLRC = wglGetCurrentContext();
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (CurrenthGLRC == NULL || CurrenthGLRC == hGLRC)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
if (!wglMakeCurrent(hDC, hGLRC))
{
WriteTrace(TraceGlitch, TraceWarning, "wglMakeCurrent failed!");
gfxSstWinClose();
2016-02-03 21:21:30 +00:00
return FXFALSE;
}
}
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-03 21:21:30 +00:00
lfb_color_fmt = color_format;
if (origin_location != GR_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-03 21:21:30 +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");
2016-02-03 21:21:30 +00:00
if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
WriteTrace(TraceGlitch, TraceWarning, "Your video card doesn't support GL_ARB_multitexture extension");
2016-02-03 21:21:30 +00:00
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");
2016-02-03 21:21:30 +00:00
show_warning = 0;
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
2016-02-03 21:21:30 +00:00
if (glActiveTextureARB == NULL)
glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)dummy_glActiveTexture;
if (glMultiTexCoord2fARB == NULL)
glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)dummy_glMultiTexCoord2f;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-03 21:21:30 +00:00
nbTextureUnits = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, (GLint *)&nbTextureUnits);
if (nbTextureUnits == 1) WriteTrace(TraceGlitch, TraceWarning, "You need a video card that has at least 2 texture units");
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
nbAuxBuffers = 0;
glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
if (nbAuxBuffers > 0)
printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
2013-04-10 07:08:48 +00:00
#ifdef VOODOO1
2016-02-03 21:21:30 +00:00
nbTextureUnits = 2;
2013-04-10 07:08:48 +00:00
#endif
2016-02-03 21:21:30 +00:00
if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
blend_func_separate_support = 0;
else
blend_func_separate_support = 1;
if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
packed_pixels_support = 0;
else {
printf("packed pixels extension used\n");
packed_pixels_support = 1;
}
if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
npot_support = 0;
else {
printf("NPOT extension used\n");
npot_support = 1;
}
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
if (glBlendFuncSeparateEXT == NULL)
glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)dummy_glBlendFuncSeparate;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-03 21:21:30 +00:00
if (isExtensionSupported("GL_EXT_fog_coord") == 0)
fog_coord_support = 0;
else
fog_coord_support = 1;
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
if (glFogCoordfEXT == NULL)
glFogCoordfEXT = (PFNGLFOGCOORDFPROC)dummy_glFogCoordf;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
if (wglGetExtensionsStringARB == NULL)
wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)dummy_wglGetExtensionsString;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
if (glBindFramebufferEXT == NULL)
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)dummy_glBindFramebuffer;
if (glFramebufferTexture2DEXT == NULL)
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)dummy_glFramebufferTexture2D;
if (glGenFramebuffersEXT == NULL)
glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)dummy_glGenFramebuffers;
if (glCheckFramebufferStatusEXT == NULL)
glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)dummy_glCheckFramebufferStatus;
if (glDeleteFramebuffersEXT == NULL)
glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)dummy_glDeleteFramebuffers;
glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
if (glBindRenderbufferEXT == NULL)
glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)dummy_glBindRenderbuffer;
if (glDeleteRenderbuffersEXT == NULL)
glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)dummy_glDeleteRenderbuffers;
if (glGenRenderbuffersEXT == NULL)
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)dummy_glGenRenderbuffers;
if (glRenderbufferStorageEXT == NULL)
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)dummy_glRenderbufferStorage;
if (glFramebufferRenderbufferEXT == NULL)
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)dummy_glFramebufferRenderbuffer;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2017-07-22 22:31:08 +00:00
use_fbo = g_settings->wrpFBO() && glFramebufferRenderbufferEXT;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
printf("use_fbo %d\n", use_fbo);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (isExtensionSupported("GL_ARB_shading_language_100") &&
isExtensionSupported("GL_ARB_shader_objects") &&
isExtensionSupported("GL_ARB_fragment_shader") &&
isExtensionSupported("GL_ARB_vertex_shader"))
{
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +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");
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +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");
2016-02-03 21:21:30 +00:00
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");
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
if (glCreateShaderObjectARB == NULL)
glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)dummy_glCreateShader;
if (glShaderSourceARB == NULL)
glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)dummy_glShaderSource;
if (glCompileShaderARB == NULL)
glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)dummy_glCompileShader;
if (glCreateProgramObjectARB == NULL)
glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)dummy_glCreateProgram;
if (glAttachObjectARB == NULL)
glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)dummy_glAttachObject;
if (glLinkProgramARB == NULL)
glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)dummy_glLinkProgram;
if (glUseProgramObjectARB == NULL)
glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)dummy_glUseProgram;
if (glGetUniformLocationARB == NULL)
glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)dummy_glGetUniformLocation;
if (glUniform1iARB == NULL)
glUniform1iARB = (PFNGLUNIFORM1IARBPROC)dummy_glUniform1i;
if (glUniform4iARB == NULL)
glUniform4iARB = (PFNGLUNIFORM4IARBPROC)dummy_glUniform4i;
if (glUniform4fARB == NULL)
glUniform4fARB = (PFNGLUNIFORM4FARBPROC)dummy_glUniform4f;
if (glUniform1fARB == NULL)
glUniform1fARB = (PFNGLUNIFORM1FARBPROC)dummy_glUniform1f;
if (glDeleteObjectARB == NULL)
glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)dummy_glDeleteObject;
if (glGetInfoLogARB == NULL)
glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)dummy_glGetInfoLog;
if (glGetObjectParameterivARB == NULL)
glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)dummy_glGetObjectParameteriv;
if (glSecondaryColor3f == NULL)
glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)dummy_glSecondaryColor3f;
if (glCompressedTexImage2DARB == NULL)
glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)dummy_glCompressedTexImage2D;
2013-04-10 07:08:48 +00:00
#endif
#ifndef ANDROID
glViewport(0, g_viewport_offset, g_width, g_height);
viewport_width = g_width;
viewport_height = g_height;
2016-02-03 21:21:30 +00:00
nvidia_viewport_hack = 1;
2013-04-10 07:08:48 +00:00
#else
glViewport(0, g_viewport_offset, width, height);
2016-02-03 21:21:30 +00:00
viewport_width = width;
viewport_height = height;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-03 21:21:30 +00:00
// void do_benchmarks();
// do_benchmarks();
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
// VP try to resolve z precision issues
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, 1 - zscale);
glScalef(1, 1, zscale);
2013-04-10 07:08:48 +00:00
widtho = g_width / 2;
heighto = g_height / 2;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
pBufferWidth = pBufferHeight = -1;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
current_buffer = GL_BACK;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
texture_unit = GL_TEXTURE0_ARB;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
{
int i;
for (i = 0; i < NB_TEXBUFS; i++)
texbufs[i].start = texbufs[i].end = 0xffffffff;
}
if (!use_fbo && nbAuxBuffers == 0) {
// create the framebuffer saving texture
int w = g_width, h = g_height;
2016-02-03 21:21:30 +00:00
glBindTexture(GL_TEXTURE_2D, color_texture);
if (!npot_support) {
w = h = 1;
while (w < g_width) w *= 2;
while (h < g_height) h *= 2;
2016-02-03 21:21:30 +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();
// Aniso filter check
2017-07-22 22:31:08 +00:00
if (g_settings->wrpAnisotropic())
{
2016-02-03 21:21:30 +00:00
glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
2017-07-22 22:31:08 +00:00
}
2016-02-03 21:21:30 +00:00
// ATI hack - certain texture formats are slow on ATI?
// Hmm, perhaps the internal format need to be specified explicitly...
{
GLint ifmt;
glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
if (ifmt != GL_RGB5_A1) {
WriteTrace(TraceGlitch, TraceWarning, "ATI SUCKS %x\n", ifmt);
2016-02-03 21:21:30 +00:00
ati_sucks = 1;
}
else
ati_sucks = 0;
}
grDisplayGLError("gfxSstWinOpen");
2016-02-03 21:21:30 +00:00
return 1;
2013-04-10 07:08:48 +00:00
}
bool gfxSstWinClose()
2013-04-10 07:08:48 +00:00
{
WriteTrace(TraceGlitch, TraceDebug, "-");
2016-02-03 21:21:30 +00:00
int i;
#ifndef WIN32
2016-02-03 21:21:30 +00:00
int clear_texbuff = use_fbo;
#endif
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
for (i = 0; i < 2; i++) {
tmu_usage[i].min = 0x0FFFFFFFul;
tmu_usage[i].max = 0x00000000ul;
invtex[i] = 0;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
free_combiners();
2013-04-10 07:08:48 +00:00
#ifndef WIN32
2016-02-03 21:21:30 +00:00
try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
// ZIGGY : I found the problem : it is 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.
{
if (use_fbo && glBindFramebufferEXT)
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
2016-02-03 21:21:30 +00:00
}
catch (...)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
clear_texbuff = 0;
}
if (clear_texbuff)
{
for (i = 0; i < nb_fb; i++)
2016-02-03 21:21:30 +00:00
{
glDeleteTextures(1, &(fbs[i].texid));
2016-02-04 10:22:19 +00:00
glDeleteFramebuffersEXT(1, &(fbs[i].fbid));
glDeleteRenderbuffersEXT(1, &(fbs[i].zbid));
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
}
#endif
2016-02-03 21:21:30 +00:00
nb_fb = 0;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
free_textures();
2013-04-10 07:08:48 +00:00
#ifndef WIN32
2016-02-03 21:21:30 +00:00
// ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
remove_tex(0, 0xfffffff);
2013-04-10 07:08:48 +00:00
#endif
2016-02-03 21:21:30 +00:00
//*/
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
if (hGLRC)
{
wglMakeCurrent(hDC, NULL);
wglDeleteContext(hGLRC);
hGLRC = NULL;
}
ExitFullScreen();
2013-04-10 07:08:48 +00:00
#else
2016-02-03 21:21:30 +00:00
//SDL_QuitSubSystem(SDL_INIT_VIDEO);
//sleep(2);
//m_pScreen = NULL;
2013-04-10 07:08:48 +00:00
#endif
2016-02-03 21:21:30 +00:00
return FXTRUE;
}
2013-04-10 07:08:48 +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)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
int i;
static int fbs_init = 0;
2016-02-04 10:22:19 +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);
if (lodmin != lodmax) WriteTrace(TraceGlitch, TraceWarning, "gfxTextureBufferExt : loading more than one LOD");
2016-02-03 21:21:30 +00:00
if (!use_fbo) {
if (!render_to_texture) { //initialization
return;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
render_to_texture = 2;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (aspect < 0)
{
pBufferHeight = 1 << lodmin;
pBufferWidth = pBufferHeight >> -aspect;
}
else
{
pBufferWidth = 1 << lodmin;
pBufferHeight = pBufferWidth >> aspect;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (curBufferAddr && startAddress + 1 != curBufferAddr)
updateTexture();
2013-04-10 07:08:48 +00:00
#ifdef SAVE_CBUFFER
2016-02-03 21:21:30 +00:00
//printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
// save color buffer
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);
glActiveTextureARB(texture_unit);
glBindTexture(GL_TEXTURE_2D, color_texture);
// save incrementally the framebuffer
if (save_w) {
if (tw > save_w && th > save_h) {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
0, g_viewport_offset + save_h, tw, th - save_h);
2016-02-03 21:21:30 +00:00
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
save_w, g_viewport_offset, tw - save_w, save_h);
2016-02-03 21:21:30 +00:00
save_w = tw;
save_h = th;
}
else if (tw > save_w) {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
save_w, g_viewport_offset, tw - save_w, save_h);
2016-02-03 21:21:30 +00:00
save_w = tw;
}
else if (th > save_h) {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
0, g_viewport_offset + save_h, save_w, th - save_h);
2016-02-03 21:21:30 +00:00
save_h = th;
}
}
else {
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
0, g_viewport_offset, tw, th);
2016-02-03 21:21:30 +00:00
save_w = tw;
save_h = th;
}
glBindTexture(GL_TEXTURE_2D, default_texture);
2013-04-10 07:08:48 +00:00
}
#endif
2016-02-03 21:21:30 +00:00
if (startAddress + 1 != curBufferAddr ||
(curBufferAddr == 0L && nbAuxBuffers == 0))
buffer_cleared = 0;
curBufferAddr = pBufferAddress = startAddress + 1;
pBufferFmt = fmt;
int rtmu = startAddress < gfxTexMinAddress(GFX_TMU1) ? 0 : 1;
2016-02-03 21:21:30 +00:00
int size = pBufferWidth*pBufferHeight * 2; //grTexFormatSize(fmt);
if (tmu_usage[rtmu].min > pBufferAddress + 0)
tmu_usage[rtmu].min = pBufferAddress + 0;
if (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);
g_width = pBufferWidth;
g_height = pBufferHeight;
2016-02-03 21:21:30 +00:00
widtho = g_width / 2;
heighto = g_height / 2;
2016-02-03 21:21:30 +00:00
// this could be improved, but might be enough as long as the set of
// 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);
// ZIGGY it speeds things up to not delete the buffers
// 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);
if (g_height > screen_height) {
glViewport(0, g_viewport_offset + screen_height - g_height, g_width, g_height);
2016-02-03 21:21:30 +00:00
}
else
glViewport(0, g_viewport_offset, g_width, g_height);
2016-02-03 21:21:30 +00:00
glScissor(0, g_viewport_offset, g_width, g_height);
2016-02-03 21:21:30 +00:00
grDisplayGLError("gfxTextureBufferExt :: A");
}
2016-02-03 21:21:30 +00:00
else {
if (!render_to_texture) //initialization
{
if (!fbs_init)
{
for (i = 0; i < 100; i++) fbs[i].address = 0;
fbs_init = 1;
nb_fb = 0;
}
return; //no need to allocate FBO if render buffer is not texture buffer
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
render_to_texture = 2;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (aspect < 0)
{
pBufferHeight = 1 << lodmin;
pBufferWidth = pBufferHeight >> -aspect;
}
else
{
pBufferWidth = 1 << lodmin;
pBufferHeight = pBufferWidth >> aspect;
}
pBufferAddress = startAddress + 1;
2013-04-10 07:08:48 +00:00
g_width = pBufferWidth;
g_height = pBufferHeight;
2013-04-10 07:08:48 +00:00
widtho = g_width / 2;
heighto = g_height / 2;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
for (i = 0; i < nb_fb; i++)
{
if (fbs[i].address == pBufferAddress)
{
if (fbs[i].width == g_width && fbs[i].height == g_height) //select already allocated FBO
2016-02-03 21:21:30 +00:00
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[i].fbid);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbs[i].texid, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbs[i].zbid);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbs[i].zbid);
glViewport(0, 0, g_width, g_height);
glScissor(0, 0, g_width, g_height);
2016-02-03 21:21:30 +00:00
if (fbs[i].buff_clear)
{
glDepthMask(1);
glClear(GL_DEPTH_BUFFER_BIT); //clear z-buffer only. we may need content, stored in the frame buffer
fbs[i].buff_clear = 0;
}
CHECK_FRAMEBUFFER_STATUS();
curBufferAddr = pBufferAddress;
grDisplayGLError("gfxTextureBufferExt :: C");
2016-02-03 21:21:30 +00:00
return;
}
else //create new FBO at the same address, delete old one
{
glDeleteFramebuffersEXT(1, &(fbs[i].fbid));
glDeleteRenderbuffersEXT(1, &(fbs[i].zbid));
if (nb_fb > 1)
memmove(&(fbs[i]), &(fbs[i + 1]), sizeof(fb)*(nb_fb - i));
nb_fb--;
break;
}
}
}
2013-04-10 07:08:48 +00:00
remove_tex(pBufferAddress, pBufferAddress + g_width*g_height * 2/*grTexFormatSize(fmt)*/);
2016-02-03 21:21:30 +00:00
//create new FBO
glGenFramebuffersEXT(1, &(fbs[nb_fb].fbid));
glGenRenderbuffersEXT(1, &(fbs[nb_fb].zbid));
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, g_width, g_height);
2016-02-03 21:21:30 +00:00
fbs[nb_fb].address = pBufferAddress;
fbs[nb_fb].width = g_width;
fbs[nb_fb].height = g_height;
2016-02-03 21:21:30 +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);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, g_width, g_height, 0,
2016-02-03 21:21:30 +00:00
GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbs[nb_fb].fbid);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid);
glViewport(0, 0, g_width, g_height);
glScissor(0, 0, g_width, g_height);
2016-02-03 21:21:30 +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++;
grDisplayGLError("gfxTextureBufferExt :: B");
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
2017-07-25 08:29:37 +00:00
int CheckTextureBufferFormat(gfxChipID_t tmu, uint32_t startAddress, gfxTexInfo *info)
2016-02-03 21:21:30 +00:00
{
int found, i;
if (!use_fbo) {
for (found = i = 0; i < 2; i++)
if (tmu_usage[i].min <= startAddress && tmu_usage[i].max > startAddress) {
//printf("tmu %d == framebuffer %x\n", tmu, startAddress);
found = 1;
break;
}
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +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++;
}
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +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;
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (info->aspectRatioLog2 < 0)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
ch = 256;
cw = ch >> -info->aspectRatioLog2;
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +00:00
else
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
cw = 256;
ch = cw >> info->aspectRatioLog2;
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +00:00
if (use_fbo || th < screen_height)
rh = th;
else
rh = screen_height;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
//printf("th %d rh %d ch %d\n", th, rh, ch);
invtex[tmu] = 1.0f - (th - rh) / (float)th;
2013-04-10 07:08:48 +00:00
}
else
2016-02-03 21:21:30 +00:00
invtex[tmu] = 0;
if (info->format == GFX_TEXFMT_ALPHA_INTENSITY_88) {
2016-02-03 21:21:30 +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;
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +00:00
return 0;
}
2013-04-10 07:08:48 +00:00
2017-07-22 22:42:02 +00:00
uint32_t gfxGet(uint32_t pname, uint32_t plength, FxI32 *params)
2016-02-03 21:21:30 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "pname: %d plength: %d", pname, plength);
2016-02-03 21:21:30 +00:00
switch (pname)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
case GR_MAX_TEXTURE_SIZE:
if (plength < 4 || params == NULL) return 0;
params[0] = 2048;
return 4;
break;
case GR_NUM_TMU:
if (plength < 4 || params == NULL) return 0;
if (!nbTextureUnits)
{
gfxSstWinOpen(GFX_COLORFORMAT_ARGB, GR_ORIGIN_UPPER_LEFT, 2, 1);
gfxSstWinClose();
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
#ifdef VOODOO1
2016-02-03 21:21:30 +00:00
params[0] = 1;
2013-04-10 07:08:48 +00:00
#else
2016-02-03 21:21:30 +00:00
if (nbTextureUnits > 2)
params[0] = 2;
else
params[0] = 1;
2013-04-10 07:08:48 +00:00
#endif
2016-02-03 21:21:30 +00:00
return 4;
break;
case GR_NUM_BOARDS:
case GR_NUM_FB:
case GR_REVISION_FB:
case GR_REVISION_TMU:
if (plength < 4 || params == NULL) return 0;
params[0] = 1;
return 4;
break;
case GR_MEMORY_FB:
if (plength < 4 || params == NULL) return 0;
params[0] = 16 * 1024 * 1024;
return 4;
break;
case GR_MEMORY_TMU:
if (plength < 4 || params == NULL) return 0;
params[0] = 16 * 1024 * 1024;
return 4;
break;
case GR_MEMORY_UMA:
if (plength < 4 || params == NULL) return 0;
params[0] = 16 * 1024 * 1024 * nbTextureUnits;
return 4;
break;
case GR_BITS_RGBA:
if (plength < 16 || params == NULL) return 0;
params[0] = 8;
params[1] = 8;
params[2] = 8;
params[3] = 8;
return 16;
break;
case GR_BITS_DEPTH:
if (plength < 4 || params == NULL) return 0;
params[0] = 16;
return 4;
break;
case GR_BITS_GAMMA:
if (plength < 4 || params == NULL) return 0;
params[0] = 8;
return 4;
break;
case GR_GAMMA_TABLE_ENTRIES:
if (plength < 4 || params == NULL) return 0;
params[0] = 256;
return 4;
break;
case GR_FOG_TABLE_ENTRIES:
if (plength < 4 || params == NULL) return 0;
params[0] = 64;
return 4;
break;
case GR_WDEPTH_MIN_MAX:
if (plength < 8 || params == NULL) return 0;
params[0] = 0;
params[1] = 65528;
return 8;
break;
case GR_ZDEPTH_MIN_MAX:
if (plength < 8 || params == NULL) return 0;
params[0] = 0;
params[1] = 65535;
return 8;
break;
case GR_LFB_PIXEL_PIPE:
if (plength < 4 || params == NULL) return 0;
params[0] = FXFALSE;
return 4;
break;
case GR_MAX_TEXTURE_ASPECT_RATIO:
if (plength < 4 || params == NULL) return 0;
params[0] = 3;
return 4;
break;
case GR_NON_POWER_OF_TWO_TEXTURES:
if (plength < 4 || params == NULL) return 0;
params[0] = FXFALSE;
return 4;
break;
case GR_TEXTURE_ALIGN:
if (plength < 4 || params == NULL) return 0;
params[0] = 0;
return 4;
break;
default:
WriteTrace(TraceGlitch, TraceWarning, "unknown pname in gfxGet : %x", pname);
2016-02-03 21:21:30 +00:00
}
return 0;
2013-04-10 07:08:48 +00:00
}
static void render_rectangle(int texture_number,
2016-02-03 21:21:30 +00:00
int dst_x, int dst_y,
int src_width, int src_height,
int tex_width, int tex_height, int invert)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
GLfloat planar_vertices[5][2];
2016-02-03 21:21:30 +00:00
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);
planar_vertices[0][0] = ((int)dst_x - widtho) / (float)(g_width / 2);
planar_vertices[0][1] = -((int)dst_y - heighto) / (float)(g_height / 2) * invert;
planar_vertices[1][0] = ((int)dst_x - widtho) / (float)(g_width / 2);
planar_vertices[1][1] = -((int)dst_y + (int)src_height - heighto) / (float)(g_height / 2) * invert;
planar_vertices[2][0] = ((int)dst_x + (int)src_width - widtho) / (float)(g_width / 2);
planar_vertices[2][1] = -((int)dst_y + (int)src_height - heighto) / (float)(g_height / 2) * invert;
planar_vertices[3][0] = ((int)dst_x + (int)src_width - widtho) / (float)(g_width / 2);
planar_vertices[3][1] = -((int)dst_y - heighto) / (float)(g_height / 2) * invert;
planar_vertices[4][0] = ((int)dst_x - widtho) / (float)(g_width / 2);
planar_vertices[4][1] = -((int)dst_y - heighto) / (float)(g_height / 2) * invert;
2016-02-03 21:21:30 +00:00
glBegin(GL_QUADS);
2016-02-03 21:21:30 +00:00
glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
glVertex2fv(planar_vertices[0]);
2016-02-03 21:21:30 +00:00
glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);
glVertex2fv(planar_vertices[1]);
2016-02-03 21:21:30 +00:00
glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);
glVertex2fv(planar_vertices[2]);
2016-02-03 21:21:30 +00:00
glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);
glVertex2fv(planar_vertices[3]);
2016-02-03 21:21:30 +00:00
glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
glVertex2fv(planar_vertices[4]);
2016-02-03 21:21:30 +00:00
glEnd();
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
compile_shader();
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
grDisplayGLError("render_rectangle");
2013-04-10 07:08:48 +00:00
}
void reloadTexture()
{
2016-02-03 21:21:30 +00:00
if (use_fbo || !render_to_texture || buffer_cleared)
return;
2013-04-10 07:08:48 +00:00
WriteTrace(TraceGlitch, TraceDebug, "width: %d height: %d", g_width, g_height);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
buffer_cleared = 1;
2013-04-10 07:08:48 +00:00
glPushAttrib(GL_ALL_ATTRIB_BITS);
glActiveTextureARB(texture_unit);
glBindTexture(GL_TEXTURE_2D, pBufferAddress);
2016-02-03 21:21:30 +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;
if (g_height > screen_height) h = screen_height - g_height;
2016-02-03 21:21:30 +00:00
render_rectangle(texture_unit,
-w, -h,
g_width, g_height,
g_width, g_height, -1);
2013-04-10 07:08:48 +00:00
glBindTexture(GL_TEXTURE_2D, default_texture);
glPopAttrib();
2016-02-03 21:21:30 +00:00
grDisplayGLError("reloadTexture");
}
void updateTexture()
{
if (!use_fbo && render_to_texture == 2) {
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "pBufferAddress: %x", pBufferAddress);
2016-02-03 21:21:30 +00:00
//printf("update texture %x\n", pBufferAddress);
// nothing changed, don't update the texture
if (!buffer_cleared) {
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "update cancelled");
2016-02-03 21:21:30 +00:00
return;
}
glPushAttrib(GL_ALL_ATTRIB_BITS);
// save result of render to texture into actual texture
glReadBuffer(current_buffer);
glActiveTextureARB(texture_unit);
// ZIGGY
// deleting the texture before resampling it increases speed on certain old
// nvidia cards (geforce 2 for example), unfortunatly it slows down a lot
// on newer cards.
//glDeleteTextures( 1, &pBufferAddress );
glBindTexture(GL_TEXTURE_2D, pBufferAddress);
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
0, g_viewport_offset, g_width, g_height, 0);
2016-02-03 21:21:30 +00:00
glBindTexture(GL_TEXTURE_2D, default_texture);
glPopAttrib();
}
grDisplayGLError("updateTexture");
2013-04-10 07:08:48 +00:00
}
void gfxRenderBuffer(GrBuffer_t buffer)
2013-04-10 07:08:48 +00:00
{
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
static HANDLE region = NULL;
//int realWidth = pBufferWidth, realHeight = pBufferHeight;
2013-04-10 07:08:48 +00:00
#endif // _WIN32
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "buffer: %d", buffer);
//printf("gfxRenderBuffer(%d)\n", buffer);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
switch (buffer)
2013-04-10 07:08:48 +00:00
{
case GFX_BUFFER_BACKBUFFER:
2016-02-03 21:21:30 +00:00
if (render_to_texture)
{
updateTexture();
// VP z fix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, 1 - zscale);
glScalef(1, 1, zscale);
inverted_culling = 0;
gfxCullMode(culling_mode);
2016-02-03 21:21:30 +00:00
g_width = savedWidth;
g_height = savedHeight;
2016-02-03 21:21:30 +00:00
widtho = savedWidtho;
heighto = savedHeighto;
2017-04-27 07:31:49 +00:00
if (use_fbo)
{
2016-02-03 21:21:30 +00:00
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
}
curBufferAddr = 0;
glViewport(0, g_viewport_offset, g_width, viewport_height);
glScissor(0, g_viewport_offset, g_width, g_height);
2013-04-10 07:08:48 +00:00
#ifdef SAVE_CBUFFER
2016-02-03 21:21:30 +00:00
if (!use_fbo && render_to_texture == 2) {
// restore color buffer
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);
glActiveTextureARB(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;
}
}
2013-04-10 07:08:48 +00:00
#endif
2016-02-03 21:21:30 +00:00
render_to_texture = 0;
}
glDrawBuffer(GL_BACK);
break;
case 6: // RENDER TO TEXTURE
if (!render_to_texture)
{
savedWidth = g_width;
savedHeight = g_height;
2016-02-03 21:21:30 +00:00
savedWidtho = widtho;
savedHeighto = heighto;
}
2013-04-10 07:08:48 +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;
gfxCullMode(culling_mode);
2017-04-18 11:32:43 +00:00
}
2016-02-03 21:21:30 +00:00
}
2017-04-18 11:32:43 +00:00
render_to_texture = 1;
break;
2016-02-03 21:21:30 +00:00
default:
WriteTrace(TraceGlitch, TraceWarning, "gfxRenderBuffer : unknown buffer : %x", buffer);
2016-02-03 21:21:30 +00:00
}
grDisplayGLError("gfxRenderBuffer");
2013-04-10 07:08:48 +00:00
}
void gfxAuxBufferExt(GrBuffer_t buffer)
2016-02-03 21:21:30 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "buffer: %d", buffer);
2016-02-03 21:21:30 +00:00
if (buffer == GFX_BUFFER_AUXBUFFER)
2016-12-25 22:26:36 +00:00
{
2016-02-03 21:21:30 +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);
gfxTexFilterMode(GFX_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);
2016-02-03 21:21:30 +00:00
}
else {
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
need_to_compile = 1;
}
grDisplayGLError("gfxAuxBufferExt");
2013-04-10 07:08:48 +00:00
}
2017-07-25 22:25:29 +00:00
void gfxBufferClear(gfxColor_t color, gfxAlpha_t alpha, uint32_t depth)
2016-02-03 21:21:30 +00:00
{
WriteTrace(TraceGlitch, TraceDebug, "color: %X alpha: %X depth: %X", color, alpha, depth);
2016-02-03 21:21:30 +00:00
switch (lfb_color_fmt)
{
case GFX_COLORFORMAT_ARGB:
2016-02-03 21:21:30 +00:00
glClearColor(((color >> 16) & 0xFF) / 255.0f,
((color >> 8) & 0xFF) / 255.0f,
(color & 0xFF) / 255.0f,
alpha / 255.0f);
break;
case GFX_COLORFORMAT_RGBA:
2016-02-03 21:21:30 +00:00
glClearColor(((color >> 24) & 0xFF) / 255.0f,
((color >> 16) & 0xFF) / 255.0f,
(color & 0xFF) / 255.0f,
alpha / 255.0f);
break;
default:
WriteTrace(TraceGlitch, TraceWarning, "gfxBufferClear: unknown color format : %x", lfb_color_fmt);
2016-02-03 21:21:30 +00:00
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (w_buffer_mode)
glClearDepth(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
else
glClearDepth(depth / 65535.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
// ZIGGY TODO check that color mask is on
buffer_cleared = 1;
2013-04-10 07:08:48 +00:00
grDisplayGLError("gfxBufferClear");
2013-04-10 07:08:48 +00:00
}
2017-07-22 22:42:02 +00:00
void gfxBufferSwap(uint32_t swap_interval)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
int i;
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "swap_interval: %d", swap_interval);
2016-02-03 21:21:30 +00:00
//printf("swap\n");
if (render_to_texture) {
WriteTrace(TraceGlitch, TraceWarning, "swap while render_to_texture\n");
2016-02-03 21:21:30 +00:00
return;
}
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
SwapBuffers(wglGetCurrentDC());
2013-04-10 07:08:48 +00:00
#else // _WIN32
#endif // _WIN32
2016-02-03 21:21:30 +00:00
for (i = 0; i < nb_fb; i++)
fbs[i].buff_clear = 1;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
// VP debugging
2013-04-10 07:08:48 +00:00
}
// frame buffer
2017-08-04 23:01:05 +00:00
bool gfxLfbLock(gfxLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, GrOriginLocation_t origin, bool pixelPipeline, GrLfbInfo_t *info)
2016-02-03 21:21:30 +00:00
{
2016-02-04 10:22:19 +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-03 21:21:30 +00:00
{
2017-05-25 22:21:29 +00:00
WriteTrace(TraceGlitch, TraceWarning, "gfxLfbLock : write only");
2016-02-03 21:21:30 +00:00
}
else
{
unsigned char *buf;
int i, j;
switch (buffer)
{
case GFX_BUFFER_FRONTBUFFER:
2016-02-03 21:21:30 +00:00
glReadBuffer(GL_FRONT);
break;
case GFX_BUFFER_BACKBUFFER:
2016-02-03 21:21:30 +00:00
glReadBuffer(GL_BACK);
break;
default:
2017-05-25 22:21:29 +00:00
WriteTrace(TraceGlitch, TraceWarning, "gfxLfbLock : unknown buffer : %x", buffer);
2016-02-03 21:21:30 +00:00
}
if (buffer != GFX_BUFFER_AUXBUFFER)
2016-02-03 21:21:30 +00:00
{
if (writeMode == GR_LFBWRITEMODE_888) {
//printf("LfbLock GR_LFBWRITEMODE_888\n");
info->lfbPtr = frameBuffer;
info->strideInBytes = g_width * 4;
2016-02-03 21:21:30 +00:00
info->writeMode = GR_LFBWRITEMODE_888;
info->origin = origin;
glReadPixels(0, g_viewport_offset, g_width, g_height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);
2016-02-03 21:21:30 +00:00
}
else {
buf = (unsigned char*)malloc(g_width*g_height * 4);
2016-02-03 21:21:30 +00:00
info->lfbPtr = frameBuffer;
info->strideInBytes = g_width * 2;
2016-02-03 21:21:30 +00:00
info->writeMode = GR_LFBWRITEMODE_565;
info->origin = origin;
glReadPixels(0, g_viewport_offset, g_width, g_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
2016-02-03 21:21:30 +00:00
for (j = 0; j < g_height; j++)
2016-02-03 21:21:30 +00:00
{
for (i = 0; i < g_width; i++)
2016-02-03 21:21:30 +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-03 21:21:30 +00:00
}
}
free(buf);
}
}
else
{
info->lfbPtr = depthBuffer;
info->strideInBytes = g_width * 2;
2016-02-03 21:21:30 +00:00
info->writeMode = GR_LFBWRITEMODE_ZA16;
info->origin = origin;
glReadPixels(0, g_viewport_offset, g_width, g_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
2016-02-03 21:21:30 +00:00
}
}
2017-05-25 22:21:29 +00:00
grDisplayGLError("gfxLfbLock");
2016-02-03 21:21:30 +00:00
return FXTRUE;
}
2016-02-03 21:21:30 +00:00
2017-08-04 23:01:05 +00:00
bool gfxLfbUnlock(gfxLock_t type, GrBuffer_t buffer)
2016-02-03 21:21:30 +00:00
{
2016-02-04 10:22:19 +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-03 21:21:30 +00:00
{
WriteTrace(TraceGlitch, TraceWarning, "gfxLfbUnlock : write only");
2016-02-03 21:21:30 +00:00
}
return FXTRUE;
}
2017-07-22 23:03:22 +00:00
bool gfxLfbReadRegion(GrBuffer_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-03 21:21:30 +00:00
{
2013-04-10 07:08:48 +00:00
unsigned char *buf;
2016-02-03 21:21:30 +00:00
unsigned int i, j;
unsigned short *frameBuffer = (unsigned short*)dst_data;
unsigned short *depthBuffer = (unsigned short*)dst_data;
2016-02-04 10:22:19 +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);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
switch (src_buffer)
2013-04-10 07:08:48 +00:00
{
case GFX_BUFFER_FRONTBUFFER:
2016-02-03 21:21:30 +00:00
glReadBuffer(GL_FRONT);
break;
case GFX_BUFFER_BACKBUFFER:
2016-02-03 21:21:30 +00:00
glReadBuffer(GL_BACK);
break;
/*case GFX_BUFFER_AUXBUFFER:
2016-02-03 21:21:30 +00:00
glReadBuffer(current_buffer);
break;*/
2013-04-10 07:08:48 +00:00
default:
WriteTrace(TraceGlitch, TraceWarning, "grReadRegion : unknown buffer : %x", src_buffer);
2013-04-10 07:08:48 +00:00
}
if (src_buffer != GFX_BUFFER_AUXBUFFER)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
buf = (unsigned char*)malloc(src_width*src_height * 4);
glReadPixels(src_x, (g_viewport_offset)+g_height - src_y - src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
2016-02-03 21:21:30 +00:00
for (j = 0; j < src_height; j++)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +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);
}
2013-04-10 07:08:48 +00:00
}
free(buf);
}
else
{
2016-02-03 21:21:30 +00:00
buf = (unsigned char*)malloc(src_width*src_height * 2);
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-03 21:21:30 +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);
2013-04-10 07:08:48 +00:00
}
grDisplayGLError("gfxLfbReadRegion");
2016-02-03 21:21:30 +00:00
return FXTRUE;
2013-04-10 07:08:48 +00:00
}
2017-07-22 23:03:22 +00:00
bool gfxLfbWriteRegion(GrBuffer_t dst_buffer, uint32_t dst_x, uint32_t dst_y, GrLfbSrcFmt_t src_format, uint32_t src_width, uint32_t src_height, bool pixelPipeline, FxI32 src_stride, void *src_data)
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +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-02-04 10:22:19 +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);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
glPushAttrib(GL_ALL_ATTRIB_BITS);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
while (tex_width < src_width) tex_width <<= 1;
while (tex_height < src_height) tex_height <<= 1;
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
switch (dst_buffer)
2013-04-10 07:08:48 +00:00
{
case GFX_BUFFER_BACKBUFFER:
2016-02-03 21:21:30 +00:00
glDrawBuffer(GL_BACK);
break;
case GFX_BUFFER_AUXBUFFER:
2016-02-03 21:21:30 +00:00
glDrawBuffer(current_buffer);
break;
default:
WriteTrace(TraceGlitch, TraceWarning, "gfxLfbWriteRegion : unknown buffer : %x", dst_buffer);
2013-04-10 07:08:48 +00:00
}
if (dst_buffer != GFX_BUFFER_AUXBUFFER)
2016-02-03 21:21:30 +00:00
{
buf = (unsigned char*)malloc(tex_width*tex_height * 4);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
texture_number = GL_TEXTURE0_ARB;
glActiveTextureARB(texture_number);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
const unsigned int half_stride = src_stride / 2;
switch (src_format)
2013-04-10 07:08:48 +00:00
{
2017-08-04 23:01:05 +00:00
case GFX_LFB_SRC_FMT_1555:
2016-02-03 21:21:30 +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;
case GR_LFBWRITEMODE_555:
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;
case GR_LFBWRITEMODE_565:
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:
WriteTrace(TraceGlitch, TraceWarning, "gfxLfbWriteRegion : unknown format : %d", src_format);
2013-04-10 07:08:48 +00:00
}
2016-02-03 21:21:30 +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);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
set_copy_shader();
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +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);
}
else
{
2017-04-18 11:32:43 +00:00
float *buf = (float*)malloc(src_width*(src_height + (g_viewport_offset)) * sizeof(float));
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (src_format != GR_LFBWRITEMODE_ZA16)
WriteTrace(TraceGlitch, TraceWarning, "unknown depth buffer write format:%x", src_format);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
if (dst_x || dst_y)
WriteTrace(TraceGlitch, TraceWarning, "dst_x:%d, dst_y:%d\n", dst_x, dst_y);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
for (j = 0; j < src_height; j++)
{
for (i = 0; i < src_width; i++)
{
buf[(j + (g_viewport_offset))*src_width + i] =
2016-02-03 21:21:30 +00:00
(frameBuffer[(src_height - j - 1)*(src_stride / 2) + i] / (65536.0f*(2.0f / zscale))) + 1 - zscale / 2.0f;
}
}
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
glDrawBuffer(GL_BACK);
glClear(GL_DEPTH_BUFFER_BIT);
glDepthMask(1);
glDrawPixels(src_width, src_height + (g_viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
2013-04-10 07:08:48 +00:00
2016-02-03 21:21:30 +00:00
free(buf);
2017-05-17 08:01:54 +00:00
}
2016-02-03 21:21:30 +00:00
glDrawBuffer(current_buffer);
glPopAttrib();
grDisplayGLError("gfxLfbWriteRegion");
2016-02-03 21:21:30 +00:00
return FXTRUE;
2017-05-17 08:01:54 +00:00
}
2013-04-10 07:08:48 +00:00
/* wrapper-specific glide extensions */
#ifdef _WIN32
static void CorrectGamma(LPVOID apGammaRamp)
{
2016-02-03 21:21:30 +00:00
HDC hdc = GetDC(NULL);
if (hdc != NULL)
{
SetDeviceGammaRamp(hdc, apGammaRamp);
ReleaseDC(NULL, hdc);
}
}
2013-04-10 07:08:48 +00:00
#else
static void CorrectGamma(const FxU16 aGammaRamp[3][256])
{
int res;
2017-04-18 11:32:43 +00:00
/* res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]); */
res = -1;
fputs("ERROR: Replacement for SDL_SetGammaRamp unimplemented.\n", stderr);
WriteTrace(TraceGlitch, TraceDebug, "SDL_SetGammaRamp returned %d\r\n", res);
}
2013-04-10 07:08:48 +00:00
#endif
2017-07-22 22:42:02 +00:00
void gfxLoadGammaTable(uint32_t /*nentries*/, uint32_t *red, uint32_t *green, uint32_t *blue)
2013-04-10 07:08:48 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "-");
2016-02-03 21:21:30 +00:00
FxU16 aGammaRamp[3][256];
for (int i = 0; i < 256; i++)
{
aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
}
CorrectGamma(aGammaRamp);
2013-04-10 07:08:48 +00:00
}
2017-07-22 22:42:02 +00:00
void gfxGetGammaTableExt(uint32_t /*nentries*/, uint32_t *red, uint32_t *green, uint32_t *blue)
2013-04-10 07:08:48 +00:00
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "-");
2016-02-03 21:21:30 +00:00
FxU16 aGammaRamp[3][256];
2013-04-10 07:08:48 +00:00
#ifdef _WIN32
2016-02-03 21:21:30 +00:00
HDC hdc = GetDC(NULL);
if (hdc == NULL)
return;
if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
{
ReleaseDC(NULL, hdc);
2013-04-10 07:08:48 +00:00
#else
fputs("ERROR: Replacement for SDL_GetGammaRamp unimplemented.\n", stderr);
2017-04-18 11:32:43 +00:00
/* if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1) */
2013-04-10 07:08:48 +00:00
{
2016-02-03 21:21:30 +00:00
#endif
for (int i = 0; i < 256; i++)
{
red[i] = aGammaRamp[0][i] >> 8;
green[i] = aGammaRamp[1][i] >> 8;
blue[i] = aGammaRamp[2][i] >> 8;
}
2013-04-10 07:08:48 +00:00
}
}
2013-04-10 07:08:48 +00:00
void gfxGammaCorrectionRGB(FxFloat gammaR, FxFloat gammaG, FxFloat gammaB)
{
2016-02-04 10:22:19 +00:00
WriteTrace(TraceGlitch, TraceDebug, "-");
2016-02-03 21:21:30 +00:00
FxU16 aGammaRamp[3][256];
for (int i = 0; i < 256; i++)
{
aGammaRamp[0][i] = (((FxU16)((pow(i / 255.0F, 1.0F / gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
aGammaRamp[1][i] = (((FxU16)((pow(i / 255.0F, 1.0F / gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
aGammaRamp[2][i] = (((FxU16)((pow(i / 255.0F, 1.0F / gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
}
CorrectGamma(aGammaRamp);
2017-05-17 08:01:54 +00:00
}
2013-04-10 07:08:48 +00:00
static const char * GL_errors[7 + 1] = {
"GL_NO_ERROR", /* "There is no current error." */
"GL_INVALID_ENUM", /* "Invalid parameter." */
"GL_INVALID_VALUE", /* "Invalid enum parameter value." */
"GL_INVALID_OPERATION", /* "Illegal call." */
"GL_STACK_OVERFLOW",
"GL_STACK_UNDERFLOW",
"GL_OUT_OF_MEMORY", /* "Unable to allocate memory." */
"GL_UNKNOWN_ERROR" /* ??? */
};
#ifndef _DEBUG
int grDisplayGLError(const char* /*unused*/)
{
return -1;
}
#else
int grDisplayGLError(const char* message)
{
GLenum status;
unsigned int error_index;
int failure;
status = glGetError();
failure = 1;
2013-04-10 07:08:48 +00:00
if (status == GL_NO_ERROR)
error_index = failure = 0;
else
error_index =
2016-02-03 21:21:30 +00:00
(status < GL_INVALID_ENUM) /* to avoid underflow when subtracting */
? (7) /* our own, made-up "GL_UNKNOWN_ERROR" error */
: (status - GL_INVALID_ENUM) + 1;
if (error_index > 7)
error_index = 7;
#if !0
2016-02-03 21:21:30 +00:00
/*
* In most cases, we don't want to spam the screen to repeatedly say that
* there were no OpenGL errors yet, though sometimes one may need verbosity.
*/
if (failure == 0)
return (failure);
#endif
#ifdef _WIN32
MessageBoxA(NULL, message, GL_errors[error_index], MB_ICONERROR);
#else
fprintf(stderr, "%s\n%s\n\n", GL_errors[error_index], message);
#endif
return (failure);
}
#endif
2013-04-10 07:08:48 +00:00
void CHECK_FRAMEBUFFER_STATUS()
{
GLenum status;
status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
WriteTrace(TraceGlitch, TraceDebug, "status: %X", status);
switch (status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
/*WriteTrace(TraceGlitch, TraceWarning, "framebuffer complete!\n");*/
break;
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");
/* you gotta choose different formats */
/*assert(0);*/
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer INCOMPLETE_ATTACHMENT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer FRAMEBUFFER_MISSING_ATTACHMENT\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer FRAMEBUFFER_DIMENSIONS\n");
break;
/*case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer INCOMPLETE_DUPLICATE_ATTACHMENT\n");
break;*/
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer INCOMPLETE_FORMATS\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer INCOMPLETE_DRAW_BUFFER\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer INCOMPLETE_READ_BUFFER\n");
break;
case GL_FRAMEBUFFER_BINDING_EXT:
WriteTrace(TraceGlitch, TraceWarning, "framebuffer BINDING_EXT\n");
break;
default:
break;
/* programming error; will fail on all hardware */
/*assert(0);*/
}
}