1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-07 03:13:49 +00:00

Frame buffer fixes

This commit is contained in:
Sergey Lipskiy 2013-06-01 20:10:30 +07:00
parent 263f4fc112
commit a07555546e
10 changed files with 218 additions and 67 deletions

View File

@ -1,6 +1,8 @@
#include <malloc.h> #include <malloc.h>
#include "OpenGL.h"
#include "FrameBuffer.h"
#include "DepthBuffer.h" #include "DepthBuffer.h"
#include "Types.h" #include "Debug.h"
DepthBufferInfo depthBuffer; DepthBufferInfo depthBuffer;
@ -19,6 +21,8 @@ void DepthBuffer_RemoveBottom()
if (depthBuffer.bottom == depthBuffer.top) if (depthBuffer.bottom == depthBuffer.top)
depthBuffer.top = NULL; depthBuffer.top = NULL;
if (depthBuffer.bottom->renderbuf != 0)
glDeleteRenderbuffers(1, &depthBuffer.bottom->renderbuf);
free( depthBuffer.bottom ); free( depthBuffer.bottom );
depthBuffer.bottom = newBottom; depthBuffer.bottom = newBottom;
@ -57,6 +61,8 @@ void DepthBuffer_Remove( DepthBuffer *buffer )
buffer->lower->higher = buffer->higher; buffer->lower->higher = buffer->higher;
} }
if (buffer->renderbuf != 0)
ogl_glDeleteRenderbuffers(1, &buffer->renderbuf);
free( buffer ); free( buffer );
depthBuffer.numBuffers--; depthBuffer.numBuffers--;
@ -83,6 +89,7 @@ DepthBuffer *DepthBuffer_AddTop()
newtop->lower = depthBuffer.top; newtop->lower = depthBuffer.top;
newtop->higher = NULL; newtop->higher = NULL;
newtop->renderbuf = 0;
if (depthBuffer.top) if (depthBuffer.top)
depthBuffer.top->higher = newtop; depthBuffer.top->higher = newtop;
@ -138,6 +145,18 @@ void DepthBuffer_SetBuffer( u32 address )
{ {
DepthBuffer_MoveToTop( current ); DepthBuffer_MoveToTop( current );
depthBuffer.current = current; depthBuffer.current = current;
if ( frameBuffer.top != NULL && frameBuffer.top->fbo > 0) {
ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, current->renderbuf);
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
ogl_glDrawBuffers(2, attachments, frameBuffer.top->texture->glName);
}
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "DepthBuffer_SetBuffer( 0x%08X ); color buffer is 0x%08X\n",
address, ( frameBuffer.top != NULL && frameBuffer.top->fbo > 0) ? frameBuffer.top->startAddress : 0
);
#endif
return; return;
} }
current = current->lower; current = current->lower;
@ -147,7 +166,25 @@ void DepthBuffer_SetBuffer( u32 address )
current->address = address; current->address = address;
current->cleared = TRUE; current->cleared = TRUE;
if (OGL.frameBufferTextures) {
ogl_glGenRenderbuffers(1, &current->renderbuf);
ogl_glBindRenderbuffer(GL_RENDERBUFFER, current->renderbuf);
ogl_glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, (u32)pow2(OGL.width), (u32)pow2(OGL.height));
if ( frameBuffer.top != NULL && frameBuffer.top->fbo > 0) {
ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, current->renderbuf);
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
ogl_glDrawBuffers(2, attachments, frameBuffer.top->texture->glName);
}
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "DepthBuffer_SetBuffer( 0x%08X ); color buffer is 0x%08X\n",
address, ( frameBuffer.top != NULL && frameBuffer.top->fbo > 0) ? frameBuffer.top->startAddress : 0
);
#endif
}
depthBuffer.current = current; depthBuffer.current = current;
} }
@ -157,7 +194,10 @@ DepthBuffer *DepthBuffer_FindBuffer( u32 address )
while (current) while (current)
{ {
if (current->address == address) if (current->address == address) {
if (OGL.frameBufferTextures)
ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, current->renderbuf);
}
return current; return current;
current = current->lower; current = current->lower;
} }

View File

@ -8,6 +8,7 @@ struct DepthBuffer
DepthBuffer *higher, *lower; DepthBuffer *higher, *lower;
u32 address, cleared; u32 address, cleared;
GLuint renderbuf;
}; };
struct DepthBufferInfo struct DepthBufferInfo

View File

@ -3,13 +3,29 @@
#else #else
# include "winlnxdefs.h" # include "winlnxdefs.h"
#endif // __LINUX__ #endif // __LINUX__
#include <assert.h>
#include "OpenGL.h" #include "OpenGL.h"
#include "FrameBuffer.h" #include "FrameBuffer.h"
#include "DepthBuffer.h"
#include "RSP.h" #include "RSP.h"
#include "RDP.h" #include "RDP.h"
#include "Textures.h" #include "Textures.h"
#include "Combiner.h" #include "Combiner.h"
#include "Types.h" #include "Types.h"
#include "Debug.h"
/*
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,
mFrameBuffer.Identifier );
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
glBlitFramebufferEXT
(
0, 0, ClientWidth, ClientHeight,
0, 0, ClientWidth, ClientHeight,
GL_COLOR_BUFFER_BIT, GL_LINEAR
);
*/
FrameBufferInfo frameBuffer; FrameBufferInfo frameBuffer;
@ -19,6 +35,7 @@ void FrameBuffer_Init()
frameBuffer.top = NULL; frameBuffer.top = NULL;
frameBuffer.bottom = NULL; frameBuffer.bottom = NULL;
frameBuffer.numBuffers = 0; frameBuffer.numBuffers = 0;
frameBuffer.drawBuffer = GL_BACK;
} }
void FrameBuffer_RemoveBottom() void FrameBuffer_RemoveBottom()
@ -26,6 +43,8 @@ void FrameBuffer_RemoveBottom()
FrameBuffer *newBottom = frameBuffer.bottom->higher; FrameBuffer *newBottom = frameBuffer.bottom->higher;
TextureCache_Remove( frameBuffer.bottom->texture ); TextureCache_Remove( frameBuffer.bottom->texture );
if (frameBuffer.bottom->fbo != 0)
ogl_glDeleteFramebuffers(1, &frameBuffer.bottom->fbo);
if (frameBuffer.bottom == frameBuffer.top) if (frameBuffer.bottom == frameBuffer.top)
frameBuffer.top = NULL; frameBuffer.top = NULL;
@ -70,6 +89,8 @@ void FrameBuffer_Remove( FrameBuffer *buffer )
if (buffer->texture) if (buffer->texture)
TextureCache_Remove( buffer->texture ); TextureCache_Remove( buffer->texture );
if (buffer->fbo != 0)
ogl_glDeleteFramebuffers(1, &buffer->fbo);
free( buffer ); free( buffer );
@ -97,6 +118,7 @@ FrameBuffer *FrameBuffer_AddTop()
FrameBuffer *newtop = (FrameBuffer*)malloc( sizeof( FrameBuffer ) ); FrameBuffer *newtop = (FrameBuffer*)malloc( sizeof( FrameBuffer ) );
newtop->texture = TextureCache_AddTop(); newtop->texture = TextureCache_AddTop();
newtop->fbo = 0;
newtop->lower = frameBuffer.top; newtop->lower = frameBuffer.top;
newtop->higher = NULL; newtop->higher = NULL;
@ -146,25 +168,45 @@ void FrameBuffer_Destroy()
void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height ) void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height )
{ {
frameBuffer.drawBuffer = GL_DRAW_FRAMEBUFFER;
FrameBuffer *current = frameBuffer.top; FrameBuffer *current = frameBuffer.top;
// Search through saved frame buffers // Search through saved frame buffers
while (current != NULL) while (current != NULL)
{ {
if ((current->startAddress == address) && if ((current->startAddress <= address) &&
(current->width == width) && (current->endAddress >= address))
(current->height == height) &&
(current->size == size))
{ {
if ((current->scaleX != OGL.scaleX) || if ((current->width != width) ||
(current->height != height) ||
(current->size != size) || // TODO FIX ME
(current->scaleX != OGL.scaleX) ||
(current->scaleY != OGL.scaleY)) (current->scaleY != OGL.scaleY))
{ {
FrameBuffer_Remove( current ); FrameBuffer_Remove( current );
break; break;
} }
glBindTexture( GL_TEXTURE_2D, current->texture->glName ); current->startAddress = address;
glCopyTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, 0, OGL.height - current->texture->height + OGL.heightOffset, current->texture->width, current->texture->height ); current->endAddress = address + ((width * height << size >> 1) - 1);
current->texture->address = current->startAddress;
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current->fbo);
if (depthBuffer.top != NULL && depthBuffer.top->renderbuf > 0) {
ogl_glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer.top->renderbuf);
ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer.top->renderbuf);
}
// define the index array for the outputs
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
ogl_glDrawBuffers(2, attachments, current->texture->glName);
assert(checkFBO());
if (depthBuffer.top != NULL && depthBuffer.top->cleared)
OGL_ClearDepthBuffer();
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "FrameBuffer_SaveBuffer( 0x%08X ); \n", address);
#endif
*(u32*)&RDRAM[current->startAddress] = current->startAddress; *(u32*)&RDRAM[current->startAddress] = current->startAddress;
current->changed = TRUE; current->changed = TRUE;
@ -206,7 +248,30 @@ void FrameBuffer_SaveBuffer( u32 address, u16 size, u16 width, u16 height )
cache.cachedBytes += current->texture->textureBytes; cache.cachedBytes += current->texture->textureBytes;
glBindTexture( GL_TEXTURE_2D, current->texture->glName ); glBindTexture( GL_TEXTURE_2D, current->texture->glName );
glCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, 0, OGL.height - current->texture->height + OGL.heightOffset, current->texture->realWidth, current->texture->realHeight, 0 ); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, current->texture->realWidth, current->texture->realHeight, 0, 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 );
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
ogl_glGenFramebuffers(1, &current->fbo);
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current->fbo);
ogl_glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, current->texture->glName, 0);
if (depthBuffer.top != NULL && depthBuffer.top->renderbuf > 0) {
ogl_glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer.top->renderbuf);
ogl_glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer.top->renderbuf);
}
GLuint attachments[2] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT };
ogl_glDrawBuffers(2, attachments, current->texture->glName);
assert(checkFBO());
if (depthBuffer.top != NULL && depthBuffer.top->cleared)
OGL_ClearDepthBuffer();
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "FrameBuffer_SaveBuffer( 0x%08X ); depth buffer is 0x%08X\n",
address, (depthBuffer.top != NULL && depthBuffer.top->renderbuf > 0) ? depthBuffer.top->address : 0
);
#endif
*(u32*)&RDRAM[current->startAddress] = current->startAddress; *(u32*)&RDRAM[current->startAddress] = current->startAddress;
current->changed = TRUE; current->changed = TRUE;
@ -262,6 +327,7 @@ void FrameBuffer_RenderBuffer( u32 address )
u1 = (float)current->texture->width / (float)current->texture->realWidth; u1 = (float)current->texture->width / (float)current->texture->realWidth;
v1 = (float)current->texture->height / (float)current->texture->realHeight; v1 = (float)current->texture->height / (float)current->texture->realHeight;
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glDrawBuffer( GL_FRONT ); glDrawBuffer( GL_FRONT );
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f( 0.0f, 0.0f ); glTexCoord2f( 0.0f, 0.0f );
@ -277,24 +343,29 @@ void FrameBuffer_RenderBuffer( u32 address )
glVertex2f( current->texture->width, (GLfloat)(OGL.height - current->texture->height) ); glVertex2f( current->texture->width, (GLfloat)(OGL.height - current->texture->height) );
glEnd(); glEnd();
glDrawBuffer( GL_BACK ); glDrawBuffer( GL_BACK );
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo);
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "FrameBuffer_RenderBuffer( 0x%08X ); \n", address);
#endif
/* glEnable( GL_TEXTURE_2D ); /* glEnable( GL_TEXTURE_2D );
glActiveTextureARB( GL_TEXTURE0_ARB ); glActiveTextureARB( GL_TEXTURE0_ARB );
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );*/ glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );*/
glLoadIdentity();
glPopAttrib(); glPopAttrib();
current->changed = FALSE; current->changed = FALSE;
FrameBuffer_MoveToTop( current );
gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT; gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
gDP.changed |= CHANGED_COMBINE; gDP.changed |= CHANGED_COMBINE;
return; return;
} }
current = current->lower; current = current->lower;
} }
} }
void FrameBuffer_RestoreBuffer( u32 address, u16 size, u16 width ) void FrameBuffer_RestoreBuffer( u32 address, u16 size, u16 width )
{ {
FrameBuffer *current = frameBuffer.top; FrameBuffer *current = frameBuffer.top;
@ -346,6 +417,7 @@ void FrameBuffer_RestoreBuffer( u32 address, u16 size, u16 width )
u1 = (float)current->texture->width / (float)current->texture->realWidth; u1 = (float)current->texture->width / (float)current->texture->realWidth;
v1 = (float)current->texture->height / (float)current->texture->realHeight; v1 = (float)current->texture->height / (float)current->texture->realHeight;
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2f( 0.0f, 0.0f ); glTexCoord2f( 0.0f, 0.0f );
glVertex2f( 0.0f, OGL.height - current->texture->height ); glVertex2f( 0.0f, OGL.height - current->texture->height );
@ -359,6 +431,10 @@ void FrameBuffer_RestoreBuffer( u32 address, u16 size, u16 width )
glTexCoord2f( u1, 0.0f ); glTexCoord2f( u1, 0.0f );
glVertex2f( current->texture->width, OGL.height - current->texture->height ); glVertex2f( current->texture->width, OGL.height - current->texture->height );
glEnd(); glEnd();
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo);
#ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "FrameBuffer_RestoreBuffer( 0x%08X ); \n", address);
#endif
glLoadIdentity(); glLoadIdentity();
glPopAttrib(); glPopAttrib();

View File

@ -9,6 +9,7 @@ struct FrameBuffer
FrameBuffer *higher, *lower; FrameBuffer *higher, *lower;
CachedTexture *texture; CachedTexture *texture;
GLuint fbo;
u32 startAddress, endAddress; u32 startAddress, endAddress;
u32 size, width, height, changed; u32 size, width, height, changed;
@ -19,6 +20,7 @@ struct FrameBufferInfo
{ {
FrameBuffer *top, *bottom, *current; FrameBuffer *top, *bottom, *current;
int numBuffers; int numBuffers;
GLenum drawBuffer;
}; };
extern FrameBufferInfo frameBuffer; extern FrameBufferInfo frameBuffer;

View File

@ -496,35 +496,7 @@ void InitGLSLCombiner()
ogl_glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, g_lod_tex, 0); ogl_glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, g_lod_tex, 0);
// check if everything is OK // check if everything is OK
GLenum e = ogl_glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); assert(checkFBO());
switch (e) {
case GL_FRAMEBUFFER_UNDEFINED:
printf("FBO Undefined\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :
printf("FBO Incomplete Attachment\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :
printf("FBO Missing Attachment\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER :
printf("FBO Incomplete Draw Buffer\n");
break;
case GL_FRAMEBUFFER_UNSUPPORTED :
printf("FBO Unsupported\n");
break;
case GL_FRAMEBUFFER_COMPLETE:
printf("FBO OK\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("framebuffer FRAMEBUFFER_DIMENSIONS\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("framebuffer INCOMPLETE_FORMATS\n");
break;
default:
printf("FBO Problem?\n");
}
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
} }
@ -763,7 +735,7 @@ void OGL_UpdateCullFace();
void OGL_UpdateViewport(); void OGL_UpdateViewport();
void OGL_ClearColorBuffer( float *color ); void OGL_ClearColorBuffer( float *color );
/* #if defined(LOD_TEST)
void drawFBO() void drawFBO()
{ {
glUseProgramObjectARB(0); glUseProgramObjectARB(0);
@ -784,8 +756,8 @@ void drawFBO()
glBindTexture(GL_TEXTURE_2D, g_lod_tex); glBindTexture(GL_TEXTURE_2D, g_lod_tex);
glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL );
glColor4f( 1, 1, 1, 1 ); glColor4f( 1, 1, 1, 1 );
const float s0 = 1.0f;//640.0f/1024.0f; const float s0 = 0.5f;//640.0f/1024.0f;
const float t0 = 1.0f;//480.0f/1024.0f; const float t0 = 0.5f;//480.0f/1024.0f;
glBegin( GL_QUADS ); glBegin( GL_QUADS );
@ -807,7 +779,7 @@ void drawFBO()
OGL_UpdateViewport(); OGL_UpdateViewport();
} }
*/ #endif
void GLSL_CalcLOD() { void GLSL_CalcLOD() {
glDisable( GL_DEPTH_TEST ); glDisable( GL_DEPTH_TEST );
@ -816,13 +788,11 @@ void GLSL_CalcLOD() {
// Set Drawing buffers // Set Drawing buffers
GLuint attachments[1] = {GL_COLOR_ATTACHMENT0}; GLuint attachments[1] = {GL_COLOR_ATTACHMENT0};
ogl_glDrawBuffers(1, attachments, g_lod_tex); ogl_glDrawBuffers(1, attachments, g_lod_tex);
float clear_color[4] = {0.0f, 0.0f, 0.0f, 1.0f};
OGL_ClearColorBuffer(clear_color );
glUseProgramObjectARB(g_lod_program); glUseProgramObjectARB(g_lod_program);
glDrawArrays( GL_TRIANGLES, 0, OGL.numVertices ); glDrawArrays( GL_TRIANGLES, 0, OGL.numVertices );
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top != NULL ? frameBuffer.top->fbo : 0);
// drawFBO(); // drawFBO();
@ -854,7 +824,7 @@ void GLSL_PostCalcLOD() {
glUseProgramObjectARB(g_lod_clear_program); glUseProgramObjectARB(g_lod_clear_program);
glDrawArrays( GL_TRIANGLES, 0, OGL.numVertices ); glDrawArrays( GL_TRIANGLES, 0, OGL.numVertices );
ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); ogl_glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top != NULL ? frameBuffer.top->fbo : 0);
Combiner_SetCombine( gDP.combine.mux ); Combiner_SetCombine( gDP.combine.mux );
} }

View File

@ -8,6 +8,7 @@
# include <GL/glext.h> # include <GL/glext.h>
# include "SDL.h" # include "SDL.h"
#endif // __LINUX__ #endif // __LINUX__
#include <assert.h>
#include <math.h> #include <math.h>
#include <stdio.h> #include <stdio.h>
#include "GLideN64.h" #include "GLideN64.h"
@ -98,6 +99,7 @@ PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
@ -109,6 +111,7 @@ PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
#endif // !__LINUX__ #endif // !__LINUX__
BOOL isExtensionSupported( const char *extension ) BOOL isExtensionSupported( const char *extension )
@ -256,6 +259,7 @@ void OGL_InitExtensions()
glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress( "glFramebufferRenderbuffer" ); glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC)wglGetProcAddress( "glFramebufferRenderbuffer" );
glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress( "glDeleteRenderbuffers" ); glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC)wglGetProcAddress( "glDeleteRenderbuffers" );
glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress( "glCheckFramebufferStatus" ); glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC)wglGetProcAddress( "glCheckFramebufferStatus" );
glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC)wglGetProcAddress( "glBlitFramebuffer" );
glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT"); glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT"); glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
@ -268,6 +272,7 @@ void OGL_InitExtensions()
glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT"); glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT"); glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT"); glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC)wglGetProcAddress("glBlitFramebufferEXT");
if (glGenFramebuffers != NULL) if (glGenFramebuffers != NULL)
OGL.framebuffer_mode = GLInfo::fbFBO; OGL.framebuffer_mode = GLInfo::fbFBO;
@ -574,7 +579,7 @@ void OGL_UpdateCullFace()
void OGL_UpdateViewport() void OGL_UpdateViewport()
{ {
glViewport( gSP.viewport.x * OGL.scaleX, (VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY + OGL.heightOffset, glViewport( gSP.viewport.x * OGL.scaleX, (VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY + (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0),
gSP.viewport.width * OGL.scaleX, gSP.viewport.height * OGL.scaleY ); gSP.viewport.width * OGL.scaleX, gSP.viewport.height * OGL.scaleY );
glDepthRange( 0.0f, 1.0f );//gSP.viewport.nearz, gSP.viewport.farz ); glDepthRange( 0.0f, 1.0f );//gSP.viewport.nearz, gSP.viewport.farz );
} }
@ -652,7 +657,7 @@ void OGL_UpdateStates()
if (gDP.changed & CHANGED_SCISSOR) if (gDP.changed & CHANGED_SCISSOR)
{ {
glScissor( gDP.scissor.ulx * OGL.scaleX, (VI.height - gDP.scissor.lry) * OGL.scaleY + OGL.heightOffset, glScissor( gDP.scissor.ulx * OGL.scaleX, (VI.height - gDP.scissor.lry) * OGL.scaleY + (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0),
(gDP.scissor.lrx - gDP.scissor.ulx) * OGL.scaleX, (gDP.scissor.lry - gDP.scissor.uly) * OGL.scaleY ); (gDP.scissor.lrx - gDP.scissor.ulx) * OGL.scaleX, (gDP.scissor.lry - gDP.scissor.uly) * OGL.scaleY );
} }
@ -925,7 +930,7 @@ void OGL_DrawRect( int ulx, int uly, int lrx, int lry, float *color )
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadIdentity(); glLoadIdentity();
glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f ); glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f );
glViewport( 0, OGL.heightOffset, OGL.width, OGL.height ); glViewport( 0, (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), OGL.width, OGL.height );
glDepthRange( 0.0f, 1.0f ); glDepthRange( 0.0f, 1.0f );
glColor4f( color[0], color[1], color[2], color[3] ); glColor4f( color[0], color[1], color[2], color[3] );
@ -957,7 +962,7 @@ void OGL_DrawTexturedRect( float ulx, float uly, float lrx, float lry, float uls
glMatrixMode( GL_PROJECTION ); glMatrixMode( GL_PROJECTION );
glLoadIdentity(); glLoadIdentity();
glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f ); glOrtho( 0, VI.width, VI.height, 0, 1.0f, -1.0f );
glViewport( 0, OGL.heightOffset, OGL.width, OGL.height ); glViewport( 0, (frameBuffer.drawBuffer == GL_BACK ? OGL.heightOffset : 0), OGL.width, OGL.height );
if (combiner.usesT0) if (combiner.usesT0)
{ {
@ -1115,6 +1120,8 @@ void OGL_DrawTexturedRect( float ulx, float uly, float lrx, float lry, float uls
void OGL_ClearDepthBuffer() void OGL_ClearDepthBuffer()
{ {
if (OGL.frameBufferTextures && frameBuffer.top == NULL)
return;
glDisable( GL_SCISSOR_TEST ); glDisable( GL_SCISSOR_TEST );
OGL_UpdateStates(); OGL_UpdateStates();
@ -1263,6 +1270,9 @@ void ogl_glBindFramebuffer (GLenum target, GLuint framebuffer) {
case GL_DRAW_FRAMEBUFFER: case GL_DRAW_FRAMEBUFFER:
target = GL_FRAMEBUFFER_EXT; target = GL_FRAMEBUFFER_EXT;
break; break;
case GL_READ_FRAMEBUFFER:
target = GL_READ_FRAMEBUFFER_EXT;
break;
} }
glBindFramebufferEXT(target, framebuffer); glBindFramebufferEXT(target, framebuffer);
break; break;
@ -1411,6 +1421,7 @@ void ogl_glDrawBuffers (GLsizei n, const GLenum *bufs, GLuint texture) {
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture, 0);
break; break;
} }
assert(checkFBO());
} }
GLenum ogl_glCheckFramebufferStatus (GLenum target) { GLenum ogl_glCheckFramebufferStatus (GLenum target) {
@ -1446,3 +1457,47 @@ GLenum ogl_glCheckFramebufferStatus (GLenum target) {
} }
return GL_FRAMEBUFFER_UNSUPPORTED; return GL_FRAMEBUFFER_UNSUPPORTED;
} }
bool checkFBO() {
GLenum e = ogl_glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
switch (e) {
case GL_FRAMEBUFFER_UNDEFINED:
printf("FBO Undefined\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT :
printf("FBO Incomplete Attachment\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT :
printf("FBO Missing Attachment\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER :
printf("FBO Incomplete Draw Buffer\n");
break;
case GL_FRAMEBUFFER_UNSUPPORTED :
printf("FBO Unsupported\n");
break;
case GL_FRAMEBUFFER_COMPLETE:
printf("FBO OK\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
printf("framebuffer FRAMEBUFFER_DIMENSIONS\n");
break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
printf("framebuffer INCOMPLETE_FORMATS\n");
break;
default:
printf("FBO Problem?\n");
}
return e == GL_FRAMEBUFFER_COMPLETE;
}
void ogl_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
switch (OGL.framebuffer_mode) {
case GLInfo::fbFBO:
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
break;
case GLInfo::fbFBOEXT:
glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
break;
}
}

View File

@ -165,6 +165,7 @@ extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage;
extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers;
extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer;
extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus;
extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer;
extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT; extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT; extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
@ -176,6 +177,7 @@ extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT; extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT; extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT; extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT;
#endif // !__LINUX__ #endif // !__LINUX__
bool OGL_Start(); bool OGL_Start();
@ -206,5 +208,9 @@ void ogl_glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers);
void ogl_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); void ogl_glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void ogl_glDrawBuffers (GLsizei n, const GLenum *bufs, GLuint texture); void ogl_glDrawBuffers (GLsizei n, const GLenum *bufs, GLuint texture);
GLenum ogl_glCheckFramebufferStatus (GLenum target); GLenum ogl_glCheckFramebufferStatus (GLenum target);
void ogl_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
bool checkFBO();
//#define LOD_TEST
#endif #endif

7
VI.cpp
View File

@ -39,16 +39,17 @@ void VI_UpdateScreen()
if (OGL.frameBufferTextures) if (OGL.frameBufferTextures)
{ {
FrameBuffer *current = FrameBuffer_FindBuffer( *REG.VI_ORIGIN ); //FrameBuffer *current = FrameBuffer_FindBuffer( *REG.VI_ORIGIN );
if ((*REG.VI_ORIGIN != VI.lastOrigin) || ((current) && current->changed)) if ((*REG.VI_ORIGIN != VI.lastOrigin) && gDP.colorImage.changed)
{ {
/*
if (gDP.colorImage.changed) if (gDP.colorImage.changed)
{ {
FrameBuffer_SaveBuffer( gDP.colorImage.address, gDP.colorImage.size, gDP.colorImage.width, gDP.colorImage.height ); FrameBuffer_SaveBuffer( gDP.colorImage.address, gDP.colorImage.size, gDP.colorImage.width, gDP.colorImage.height );
gDP.colorImage.changed = FALSE; gDP.colorImage.changed = FALSE;
} }
*/
FrameBuffer_RenderBuffer( *REG.VI_ORIGIN ); FrameBuffer_RenderBuffer( *REG.VI_ORIGIN );
gDP.colorImage.changed = FALSE; gDP.colorImage.changed = FALSE;

18
gDP.cpp
View File

@ -348,13 +348,13 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address )
if (gDP.colorImage.address != address) if (gDP.colorImage.address != address)
{ {
if (OGL.frameBufferTextures) if (OGL.frameBufferTextures && address != gDP.depthImageAddress)
{ {
if (gDP.colorImage.changed) //if (gDP.colorImage.changed)
FrameBuffer_SaveBuffer( gDP.colorImage.address, (u16)gDP.colorImage.size, (u16)gDP.colorImage.width, (u16)gDP.colorImage.height ); FrameBuffer_SaveBuffer( address, (u16)size, (u16)width, width == VI.width ? (u16)VI.height : 1 );
if (address != gDP.depthImageAddress) //if (address != gDP.depthImageAddress)
FrameBuffer_RestoreBuffer( address, (u16)size, (u16)width ); //FrameBuffer_RestoreBuffer( address, (u16)size, (u16)width );
//OGL_ClearDepthBuffer(); //OGL_ClearDepthBuffer();
} }
@ -370,7 +370,7 @@ void gDPSetColorImage( u32 format, u32 size, u32 width, u32 address )
gDP.colorImage.format = format; gDP.colorImage.format = format;
gDP.colorImage.size = size; gDP.colorImage.size = size;
gDP.colorImage.width = width; gDP.colorImage.width = width;
gDP.colorImage.address = RSP_SegmentToPhysical( address ); gDP.colorImage.address = address;
#ifdef DEBUG #ifdef DEBUG
DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n", DebugMsg( DEBUG_HIGH | DEBUG_HANDLED, "gDPSetColorImage( %s, %s, %i, 0x%08X );\n",
@ -405,8 +405,8 @@ void gDPSetDepthImage( u32 address )
DepthBuffer_SetBuffer( RSP_SegmentToPhysical( address ) ); DepthBuffer_SetBuffer( RSP_SegmentToPhysical( address ) );
if (depthBuffer.current->cleared) // if (depthBuffer.current->cleared)
OGL_ClearDepthBuffer(); // OGL_ClearDepthBuffer();
gDP.depthImageAddress = RSP_SegmentToPhysical( address ); gDP.depthImageAddress = RSP_SegmentToPhysical( address );
@ -795,7 +795,7 @@ void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry )
OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.blendColor.r ); OGL_DrawRect( ulx, uly, lrx, lry, (gDP.otherMode.cycleType == G_CYC_FILL) ? &gDP.fillColor.r : &gDP.blendColor.r );
if (depthBuffer.current) depthBuffer.current->cleared = FALSE; if (depthBuffer.top) depthBuffer.top->cleared = FALSE;
gDP.colorImage.changed = TRUE; gDP.colorImage.changed = TRUE;
gDP.colorImage.height = (u32)max( (s32)gDP.colorImage.height, lry ); gDP.colorImage.height = (u32)max( (s32)gDP.colorImage.height, lry );

View File

@ -889,7 +889,7 @@ void gSPTriangle( s32 v0, s32 v1, s32 v2, s32 flag )
DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TRIANGLE, "// Vertex index out of range\n" ); DebugMsg( DEBUG_HIGH | DEBUG_ERROR | DEBUG_TRIANGLE, "// Vertex index out of range\n" );
#endif #endif
if (depthBuffer.current) depthBuffer.current->cleared = FALSE; if (depthBuffer.top) depthBuffer.top->cleared = FALSE;
gDP.colorImage.changed = TRUE; gDP.colorImage.changed = TRUE;
gDP.colorImage.height = max( gDP.colorImage.height, (u32)gDP.scissor.lry ); gDP.colorImage.height = max( gDP.colorImage.height, (u32)gDP.scissor.lry );
} }
@ -1652,7 +1652,7 @@ void gSPObjSprite( u32 sp )
OGL_DrawTriangles(); OGL_DrawTriangles();
glLoadIdentity(); glLoadIdentity();
if (depthBuffer.current) depthBuffer.current->cleared = FALSE; if (depthBuffer.top) depthBuffer.top->cleared = FALSE;
gDP.colorImage.changed = TRUE; gDP.colorImage.changed = TRUE;
gDP.colorImage.height = max( gDP.colorImage.height, gDP.scissor.lry ); gDP.colorImage.height = max( gDP.colorImage.height, gDP.scissor.lry );
} }