2014-10-13 12:38:51 +00:00
|
|
|
#ifdef OS_MAC_OS_X
|
|
|
|
#include <malloc/malloc.h>
|
|
|
|
#else
|
2013-04-05 06:13:26 +00:00
|
|
|
#include <malloc.h>
|
2014-10-13 12:38:51 +00:00
|
|
|
#endif
|
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
|
|
|
|
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-09-08 11:00:13 +00:00
|
|
|
DepthBuffer::DepthBuffer() : m_address(0), m_width(0), m_renderbuf(0), m_FBO(0), m_pDepthTexture(NULL)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
glGenRenderbuffers(1, &m_renderbuf);
|
|
|
|
glGenFramebuffers(1, &m_FBO);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
DepthBuffer::DepthBuffer(DepthBuffer && _other) :
|
|
|
|
m_address(_other.m_address), m_width(_other.m_width),
|
|
|
|
m_renderbuf(_other.m_renderbuf), m_FBO(_other.m_FBO), m_pDepthTexture(_other.m_pDepthTexture)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
_other.m_renderbuf = 0;
|
|
|
|
_other.m_FBO = 0;
|
|
|
|
_other.m_pDepthTexture = NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
DepthBuffer::~DepthBuffer()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
if (m_renderbuf != 0)
|
|
|
|
glDeleteRenderbuffers(1, &m_renderbuf);
|
|
|
|
if (m_FBO != 0)
|
|
|
|
glDeleteFramebuffers(1, &m_FBO);
|
|
|
|
if (m_pDepthTexture != NULL)
|
|
|
|
textureCache().removeFrameBufferTexture(m_pDepthTexture);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBuffer::initDepthTexture(FrameBuffer * _pBuffer)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-10-13 12:37:43 +00:00
|
|
|
#ifdef GL_IMAGE_TEXTURES_SUPPORT
|
2014-09-08 11:00:13 +00:00
|
|
|
if (m_pDepthTexture != NULL)
|
|
|
|
textureCache().removeFrameBufferTexture(m_pDepthTexture);
|
|
|
|
m_pDepthTexture = textureCache().addFrameBufferTexture();
|
|
|
|
|
|
|
|
m_pDepthTexture->width = (u32)(_pBuffer->m_pTexture->width);
|
|
|
|
m_pDepthTexture->height = (u32)(_pBuffer->m_pTexture->height);
|
|
|
|
m_pDepthTexture->format = 0;
|
|
|
|
m_pDepthTexture->size = 2;
|
|
|
|
m_pDepthTexture->clampS = 1;
|
|
|
|
m_pDepthTexture->clampT = 1;
|
|
|
|
m_pDepthTexture->address = _pBuffer->m_startAddress;
|
|
|
|
m_pDepthTexture->clampWidth = _pBuffer->m_width;
|
|
|
|
m_pDepthTexture->clampHeight = _pBuffer->m_height;
|
|
|
|
m_pDepthTexture->frameBufferTexture = TRUE;
|
|
|
|
m_pDepthTexture->maskS = 0;
|
|
|
|
m_pDepthTexture->maskT = 0;
|
|
|
|
m_pDepthTexture->mirrorS = 0;
|
|
|
|
m_pDepthTexture->mirrorT = 0;
|
|
|
|
m_pDepthTexture->realWidth = (u32)pow2( m_pDepthTexture->width );
|
|
|
|
m_pDepthTexture->realHeight = (u32)pow2( m_pDepthTexture->height );
|
|
|
|
m_pDepthTexture->textureBytes = m_pDepthTexture->realWidth * m_pDepthTexture->realHeight * 4 * 4; // Width*Height*RGBA*sizeof(GL_RGBA32F)
|
|
|
|
textureCache().addFrameBufferTextureSize(m_pDepthTexture->textureBytes);
|
|
|
|
|
|
|
|
glBindTexture( GL_TEXTURE_2D, m_pDepthTexture->glName );
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, m_pDepthTexture->realWidth, m_pDepthTexture->realHeight, 0, GL_RGBA, GL_FLOAT, NULL);
|
|
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
|
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
|
|
|
glBindTexture( GL_TEXTURE_2D, 0);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
|
|
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pDepthTexture->glName, 0);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO);
|
|
|
|
_pBuffer->m_pDepthBuffer = this;
|
|
|
|
depthBufferList().clearBuffer();
|
2014-10-13 12:37:43 +00:00
|
|
|
#endif // GL_IMAGE_TEXTURES_SUPPORT
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBufferList::init()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
m_pCurrent = NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBufferList::destroy()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
m_pCurrent = NULL;
|
|
|
|
m_list.clear();
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
DepthBuffer * DepthBufferList::findBuffer(u32 _address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
for (DepthBuffers::iterator iter = m_list.begin(); iter != m_list.end(); ++iter)
|
|
|
|
if (iter->m_address == _address)
|
|
|
|
return &(*iter);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBufferList::removeBuffer(u32 _address )
|
|
|
|
{
|
|
|
|
for (DepthBuffers::iterator iter = m_list.begin(); iter != m_list.end(); ++iter)
|
|
|
|
if (iter->m_address == _address) {
|
|
|
|
m_list.erase(iter);
|
|
|
|
return;
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBufferList::saveBuffer(u32 _address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
if (!config.frameBufferEmulation.enable)
|
|
|
|
return;
|
|
|
|
|
|
|
|
FrameBuffer * pFrameBuffer = frameBufferList().findBuffer(_address);
|
2013-06-04 16:00:03 +00:00
|
|
|
if (pFrameBuffer == NULL)
|
2014-09-08 11:01:22 +00:00
|
|
|
pFrameBuffer = frameBufferList().getCurrent();
|
2013-06-02 15:20:44 +00:00
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
if (m_pCurrent == NULL || m_pCurrent->m_address != _address)
|
|
|
|
m_pCurrent = findBuffer(_address);
|
|
|
|
|
|
|
|
if (m_pCurrent != NULL && pFrameBuffer != NULL && m_pCurrent->m_width != pFrameBuffer->m_width) {
|
|
|
|
removeBuffer(_address);
|
|
|
|
m_pCurrent = NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
if (m_pCurrent == NULL) {
|
|
|
|
m_list.emplace_front();
|
|
|
|
DepthBuffer & buffer = m_list.front();
|
2013-06-04 16:00:03 +00:00
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
buffer.m_address = _address;
|
|
|
|
buffer.m_width = pFrameBuffer != NULL ? pFrameBuffer->m_width : VI.width;
|
|
|
|
buffer.m_pDepthTexture = NULL;
|
|
|
|
glBindRenderbuffer(GL_RENDERBUFFER, buffer.m_renderbuf);
|
2014-04-29 12:47:38 +00:00
|
|
|
#ifndef GLES2
|
|
|
|
const GLenum format = GL_DEPTH_COMPONENT;
|
|
|
|
#else
|
|
|
|
const GLenum format = GL_DEPTH_COMPONENT24_OES;
|
|
|
|
#endif
|
2014-09-08 11:00:13 +00:00
|
|
|
if (pFrameBuffer != NULL)
|
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, format, pFrameBuffer->m_pTexture->realWidth, pFrameBuffer->m_pTexture->realHeight);
|
|
|
|
else
|
2014-09-21 12:15:22 +00:00
|
|
|
glRenderbufferStorage(GL_RENDERBUFFER, format, (u32)pow2(video().getWidth()), (u32)pow2(video().getHeight()));
|
2014-09-08 11:00:13 +00:00
|
|
|
|
|
|
|
m_pCurrent = &buffer;
|
2013-06-04 16:00:03 +00:00
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
frameBufferList().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",
|
2014-09-08 11:01:22 +00:00
|
|
|
address, ( pFrameBuffer != NULL && pFrameBuffer->m_FBO > 0) ? pFrameBuffer->m_startAddress : 0
|
2013-06-01 13:10:30 +00:00
|
|
|
);
|
|
|
|
#endif
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
}
|
2014-01-08 16:22:42 +00:00
|
|
|
|
2014-09-08 11:00:13 +00:00
|
|
|
void DepthBufferList::clearBuffer()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-10-13 12:37:43 +00:00
|
|
|
#ifdef GL_IMAGE_TEXTURES_SUPPORT
|
2014-09-21 12:15:22 +00:00
|
|
|
if (!video().getRender().isImageTexturesSupported())
|
2013-12-15 17:20:12 +00:00
|
|
|
return;
|
2014-09-08 11:00:13 +00:00
|
|
|
if (m_pCurrent == NULL || m_pCurrent->m_FBO == 0)
|
2013-12-14 14:30:20 +00:00
|
|
|
return;
|
2014-05-15 16:54:29 +00:00
|
|
|
float color[4] = {1.0f, 1.0f, 0.0f, 1.0f};
|
2013-12-14 14:30:20 +00:00
|
|
|
glBindImageTexture(depthImageUnit, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
2014-09-08 11:00:13 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurrent->m_FBO);
|
2014-11-04 11:02:48 +00:00
|
|
|
const u32 cycleType = gDP.otherMode.cycleType;
|
|
|
|
gDP.otherMode.cycleType == G_CYC_FILL;
|
2014-09-21 12:15:22 +00:00
|
|
|
video().getRender().drawRect(0,0,VI.width, VI.height, color);
|
2014-11-04 11:02:48 +00:00
|
|
|
gDP.otherMode.cycleType = cycleType;
|
2014-09-08 11:00:13 +00:00
|
|
|
glBindImageTexture(depthImageUnit, m_pCurrent->m_pDepthTexture->glName, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferList().getCurrent()->m_FBO);
|
2014-10-13 12:37:43 +00:00
|
|
|
#endif // GL_IMAGE_TEXTURES_SUPPORT
|
2013-12-14 14:30:20 +00:00
|
|
|
}
|
2014-09-08 11:00:13 +00:00
|
|
|
|
|
|
|
void DepthBuffer_Init()
|
|
|
|
{
|
|
|
|
depthBufferList().init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBuffer_Destroy()
|
|
|
|
{
|
|
|
|
depthBufferList().destroy();
|
|
|
|
}
|