2013-04-05 06:13:26 +00:00
|
|
|
#include <malloc.h>
|
2013-06-04 16:00:03 +00:00
|
|
|
#include <assert.h>
|
2013-06-01 13:10:30 +00:00
|
|
|
#include "OpenGL.h"
|
2013-12-14 14:30:20 +00:00
|
|
|
#include "Combiner.h"
|
2013-06-01 13:10:30 +00:00
|
|
|
#include "FrameBuffer.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "DepthBuffer.h"
|
2013-06-04 16:00:03 +00:00
|
|
|
#include "VI.h"
|
2014-04-05 02:57:00 +00:00
|
|
|
#include "Config.h"
|
2013-06-01 13:10:30 +00:00
|
|
|
#include "Debug.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
DepthBufferInfo depthBuffer;
|
2013-12-14 14:30:20 +00:00
|
|
|
const GLuint ZlutImageUnit = 0;
|
|
|
|
const GLuint TlutImageUnit = 1;
|
|
|
|
const GLuint depthImageUnit = 2;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-04-02 15:26:48 +00:00
|
|
|
bool g_bN64DepthCompare = false;
|
2013-12-15 16:46:08 +00:00
|
|
|
|
|
|
|
void DepthBuffer_Init()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
|
|
|
depthBuffer.current = NULL;
|
|
|
|
depthBuffer.top = NULL;
|
|
|
|
depthBuffer.bottom = NULL;
|
|
|
|
depthBuffer.numBuffers = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_RemoveBottom()
|
|
|
|
{
|
|
|
|
DepthBuffer *newBottom = depthBuffer.bottom->higher;
|
|
|
|
|
|
|
|
if (depthBuffer.bottom == depthBuffer.top)
|
2013-04-22 04:10:18 +00:00
|
|
|
depthBuffer.top = NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2013-06-01 13:10:30 +00:00
|
|
|
if (depthBuffer.bottom->renderbuf != 0)
|
2014-03-21 09:38:39 +00:00
|
|
|
glDeleteRenderbuffers(1, &depthBuffer.bottom->renderbuf);
|
2013-10-30 06:07:24 +00:00
|
|
|
if (depthBuffer.bottom->depth_texture != NULL)
|
|
|
|
TextureCache_Remove( depthBuffer.bottom->depth_texture );
|
2013-04-05 06:13:26 +00:00
|
|
|
free( depthBuffer.bottom );
|
|
|
|
|
|
|
|
depthBuffer.bottom = newBottom;
|
|
|
|
|
|
|
|
if (depthBuffer.bottom != NULL)
|
|
|
|
depthBuffer.bottom->lower = NULL;
|
|
|
|
|
|
|
|
depthBuffer.numBuffers--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_Remove( DepthBuffer *buffer )
|
|
|
|
{
|
|
|
|
if ((buffer == depthBuffer.bottom) &&
|
|
|
|
(buffer == depthBuffer.top))
|
|
|
|
{
|
|
|
|
depthBuffer.top = NULL;
|
|
|
|
depthBuffer.bottom = NULL;
|
|
|
|
}
|
|
|
|
else if (buffer == depthBuffer.bottom)
|
|
|
|
{
|
|
|
|
depthBuffer.bottom = buffer->higher;
|
|
|
|
|
|
|
|
if (depthBuffer.bottom)
|
|
|
|
depthBuffer.bottom->lower = NULL;
|
|
|
|
}
|
|
|
|
else if (buffer == depthBuffer.top)
|
|
|
|
{
|
|
|
|
depthBuffer.top = buffer->lower;
|
|
|
|
|
|
|
|
if (depthBuffer.top)
|
|
|
|
depthBuffer.top->higher = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
buffer->higher->lower = buffer->lower;
|
|
|
|
buffer->lower->higher = buffer->higher;
|
|
|
|
}
|
|
|
|
|
2013-06-01 13:10:30 +00:00
|
|
|
if (buffer->renderbuf != 0)
|
2014-03-21 09:38:39 +00:00
|
|
|
glDeleteRenderbuffers(1, &buffer->renderbuf);
|
2013-11-12 07:35:26 +00:00
|
|
|
if (buffer->fbo != 0)
|
2014-03-21 09:38:39 +00:00
|
|
|
glDeleteFramebuffers(1, &buffer->fbo);
|
2013-10-30 06:07:24 +00:00
|
|
|
if (buffer->depth_texture != NULL)
|
|
|
|
TextureCache_Remove( buffer->depth_texture );
|
2013-04-05 06:13:26 +00:00
|
|
|
free( buffer );
|
|
|
|
|
|
|
|
depthBuffer.numBuffers--;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_RemoveBuffer( u32 address )
|
|
|
|
{
|
|
|
|
DepthBuffer *current = depthBuffer.bottom;
|
|
|
|
|
|
|
|
while (current != NULL)
|
|
|
|
{
|
|
|
|
if (current->address == address)
|
|
|
|
{
|
|
|
|
DepthBuffer_Remove( current );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
current = current->higher;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DepthBuffer *DepthBuffer_AddTop()
|
|
|
|
{
|
|
|
|
DepthBuffer *newtop = (DepthBuffer*)malloc( sizeof( DepthBuffer ) );
|
|
|
|
|
|
|
|
newtop->lower = depthBuffer.top;
|
|
|
|
newtop->higher = NULL;
|
2013-06-01 13:10:30 +00:00
|
|
|
newtop->renderbuf = 0;
|
2013-11-12 07:35:26 +00:00
|
|
|
newtop->fbo = 0;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
if (depthBuffer.top)
|
|
|
|
depthBuffer.top->higher = newtop;
|
|
|
|
|
|
|
|
if (!depthBuffer.bottom)
|
|
|
|
depthBuffer.bottom = newtop;
|
|
|
|
|
|
|
|
depthBuffer.top = newtop;
|
|
|
|
|
|
|
|
depthBuffer.numBuffers++;
|
|
|
|
|
|
|
|
return newtop;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_MoveToTop( DepthBuffer *newtop )
|
|
|
|
{
|
|
|
|
if (newtop == depthBuffer.top)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (newtop == depthBuffer.bottom)
|
|
|
|
{
|
|
|
|
depthBuffer.bottom = newtop->higher;
|
|
|
|
depthBuffer.bottom->lower = NULL;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
newtop->higher->lower = newtop->lower;
|
|
|
|
newtop->lower->higher = newtop->higher;
|
|
|
|
}
|
|
|
|
|
|
|
|
newtop->higher = NULL;
|
|
|
|
newtop->lower = depthBuffer.top;
|
|
|
|
depthBuffer.top->higher = newtop;
|
|
|
|
depthBuffer.top = newtop;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_Destroy()
|
|
|
|
{
|
|
|
|
while (depthBuffer.bottom)
|
|
|
|
DepthBuffer_RemoveBottom();
|
|
|
|
|
|
|
|
depthBuffer.top = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_SetBuffer( u32 address )
|
|
|
|
{
|
2013-06-04 16:00:03 +00:00
|
|
|
FrameBuffer * pFrameBuffer = FrameBuffer_FindBuffer(address);
|
|
|
|
if (pFrameBuffer == NULL)
|
|
|
|
pFrameBuffer = frameBuffer.top;
|
2013-06-02 15:20:44 +00:00
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
DepthBuffer *current = depthBuffer.top;
|
|
|
|
|
|
|
|
// Search through saved depth buffers
|
|
|
|
while (current != NULL)
|
|
|
|
{
|
|
|
|
if (current->address == address)
|
|
|
|
{
|
2013-06-04 16:00:03 +00:00
|
|
|
if (pFrameBuffer != NULL && current->width != pFrameBuffer->width) {
|
|
|
|
DepthBuffer_Remove( current );
|
|
|
|
current = NULL;
|
|
|
|
break;
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
DepthBuffer_MoveToTop( current );
|
2013-06-04 16:00:03 +00:00
|
|
|
break;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
current = current->lower;
|
|
|
|
}
|
|
|
|
|
2013-06-04 16:00:03 +00:00
|
|
|
if (current == NULL) {
|
|
|
|
current = DepthBuffer_AddTop();
|
|
|
|
|
|
|
|
current->address = address;
|
|
|
|
current->width = pFrameBuffer != NULL ? pFrameBuffer->width : VI.width;
|
2013-10-30 06:07:24 +00:00
|
|
|
current->depth_texture = NULL;
|
2014-04-05 02:57:00 +00:00
|
|
|
if (config.frameBufferEmulation) {
|
2014-03-21 09:38:39 +00:00
|
|
|
glGenRenderbuffers(1, ¤t->renderbuf);
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, current->renderbuf);
|
2013-06-04 16:00:03 +00:00
|
|
|
if (pFrameBuffer != NULL)
|
2014-03-21 09:38:39 +00:00
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, pFrameBuffer->texture->realWidth, pFrameBuffer->texture->realHeight);
|
2013-06-04 16:00:03 +00:00
|
|
|
else
|
2014-03-21 09:38:39 +00:00
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, (u32)pow2(OGL.width), (u32)pow2(OGL.height));
|
2013-06-04 16:00:03 +00:00
|
|
|
}
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-04-05 02:57:00 +00:00
|
|
|
if (config.frameBufferEmulation) {
|
2013-10-30 06:07:24 +00:00
|
|
|
FrameBuffer_AttachDepthBuffer();
|
2013-06-01 13:10:30 +00:00
|
|
|
|
|
|
|
#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
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2013-06-01 13:10:30 +00:00
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
depthBuffer.current = current;
|
|
|
|
}
|
2014-01-08 16:22:42 +00:00
|
|
|
|
2013-04-05 06:13:26 +00:00
|
|
|
DepthBuffer *DepthBuffer_FindBuffer( u32 address )
|
|
|
|
{
|
|
|
|
DepthBuffer *current = depthBuffer.top;
|
|
|
|
|
|
|
|
while (current)
|
|
|
|
{
|
2014-01-08 16:22:42 +00:00
|
|
|
if (current->address == address)
|
2013-04-05 06:13:26 +00:00
|
|
|
return current;
|
|
|
|
current = current->lower;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2014-01-08 16:22:42 +00:00
|
|
|
|
2013-12-14 14:30:20 +00:00
|
|
|
void DepthBuffer_ClearBuffer() {
|
2013-12-15 17:20:12 +00:00
|
|
|
if (!OGL.bImageTexture)
|
|
|
|
return;
|
2013-12-14 14:30:20 +00:00
|
|
|
DepthBuffer *current = depthBuffer.top;
|
|
|
|
if (current == NULL || current->fbo == 0)
|
|
|
|
return;
|
|
|
|
float color[4] = {1.0f, 1.0f, 0.0f, 0.0f};
|
|
|
|
glBindImageTexture(depthImageUnit, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current->fbo);
|
2013-12-14 14:30:20 +00:00
|
|
|
OGL_DrawRect(0,0,VI.width, VI.height, color);
|
2013-12-15 17:20:12 +00:00
|
|
|
glBindImageTexture(depthImageUnit, current->depth_texture->glName, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBuffer.top->fbo);
|
2013-12-14 14:30:20 +00:00
|
|
|
}
|