2013-06-01 13:10:30 +00:00
|
|
|
#include <assert.h>
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "OpenGL.h"
|
|
|
|
#include "FrameBuffer.h"
|
2013-06-01 13:10:30 +00:00
|
|
|
#include "DepthBuffer.h"
|
2013-11-27 10:08:48 +00:00
|
|
|
#include "N64.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "RSP.h"
|
|
|
|
#include "RDP.h"
|
2013-06-29 11:52:57 +00:00
|
|
|
#include "gDP.h"
|
2013-08-10 11:12:17 +00:00
|
|
|
#include "VI.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "Textures.h"
|
|
|
|
#include "Combiner.h"
|
2014-09-02 13:05:53 +00:00
|
|
|
#include "GLSLCombiner.h"
|
2013-04-05 06:13:26 +00:00
|
|
|
#include "Types.h"
|
2014-04-05 02:57:00 +00:00
|
|
|
#include "Config.h"
|
2013-06-01 13:10:30 +00:00
|
|
|
#include "Debug.h"
|
|
|
|
|
2014-09-20 17:34:07 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
|
|
|
const GLint monohromeInternalformat = GL_R8;
|
|
|
|
const GLenum monohromeformat = GL_RED;
|
|
|
|
#else
|
|
|
|
const GLint monohromeInternalformat = GL_LUMINANCE;
|
|
|
|
const GLenum monohromeformat = GL_LUMINANCE;
|
|
|
|
#endif // GLES2
|
|
|
|
|
2014-04-10 14:44:07 +00:00
|
|
|
#ifndef GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
class FrameBufferToRDRAM
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FrameBufferToRDRAM() :
|
2014-03-21 08:16:36 +00:00
|
|
|
m_FBO(0), m_pTexture(NULL), m_curIndex(0)
|
2013-09-05 16:24:34 +00:00
|
|
|
{
|
|
|
|
m_aAddress[0] = m_aAddress[1] = 0;
|
2014-03-21 08:16:36 +00:00
|
|
|
m_aPBO[0] = m_aPBO[1] = 0;
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Init();
|
|
|
|
void Destroy();
|
|
|
|
|
|
|
|
void CopyToRDRAM( u32 address, bool bSync );
|
|
|
|
|
|
|
|
private:
|
|
|
|
struct RGBA {
|
|
|
|
u8 r, g, b, a;
|
|
|
|
};
|
|
|
|
|
2013-09-07 16:28:20 +00:00
|
|
|
GLuint m_FBO;
|
|
|
|
CachedTexture * m_pTexture;
|
2013-09-05 16:24:34 +00:00
|
|
|
u32 m_aAddress[2];
|
|
|
|
u32 m_curIndex;
|
2014-03-21 08:16:36 +00:00
|
|
|
GLuint m_aPBO[2];
|
2013-09-05 16:24:34 +00:00
|
|
|
};
|
|
|
|
|
2013-11-12 08:41:19 +00:00
|
|
|
class DepthBufferToRDRAM
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
DepthBufferToRDRAM() :
|
|
|
|
m_FBO(0), m_pTexture(NULL), m_curIndex(0)
|
|
|
|
{
|
|
|
|
m_aPBO[0] = m_aPBO[1] = 0;
|
|
|
|
m_aAddress[0] = m_aAddress[1] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Init();
|
|
|
|
void Destroy();
|
|
|
|
|
|
|
|
void CopyToRDRAM( u32 address );
|
|
|
|
|
|
|
|
private:
|
|
|
|
GLuint m_FBO;
|
|
|
|
CachedTexture * m_pTexture;
|
|
|
|
u32 m_aAddress[2];
|
|
|
|
u32 m_curIndex;
|
2014-09-25 15:57:50 +00:00
|
|
|
GLuint m_aPBO[2];
|
2013-11-12 08:41:19 +00:00
|
|
|
};
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif // GLES2
|
2013-11-12 08:41:19 +00:00
|
|
|
|
2013-09-07 16:31:04 +00:00
|
|
|
class RDRAMtoFrameBuffer
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
RDRAMtoFrameBuffer() : m_pTexture(NULL), m_PBO(0) {}
|
|
|
|
|
|
|
|
void Init();
|
|
|
|
void Destroy();
|
|
|
|
|
2013-09-15 14:40:16 +00:00
|
|
|
void CopyFromRDRAM( u32 _address, bool _bUseAlpha);
|
2013-09-07 16:31:04 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
struct PBOBinder {
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
PBOBinder(GLuint _PBO)
|
|
|
|
{
|
|
|
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _PBO);
|
|
|
|
}
|
|
|
|
~PBOBinder() {
|
|
|
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
|
|
|
}
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
PBOBinder(GLubyte* _ptr) : ptr(_ptr) {}
|
|
|
|
~PBOBinder() {free(ptr);}
|
|
|
|
GLubyte* ptr;
|
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
};
|
|
|
|
CachedTexture * m_pTexture;
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
GLuint m_PBO;
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
GLubyte* m_PBO;
|
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
};
|
|
|
|
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2014-04-10 14:44:07 +00:00
|
|
|
FrameBufferToRDRAM g_fbToRDRAM;
|
2013-11-12 08:41:19 +00:00
|
|
|
DepthBufferToRDRAM g_dbToRDRAM;
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
RDRAMtoFrameBuffer g_RDRAMtoFB;
|
2013-08-10 11:12:17 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer::FrameBuffer() : m_cleared(false), m_pLoadTile(NULL), m_pDepthBuffer(NULL)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
m_pTexture = textureCache().addFrameBufferTexture();
|
|
|
|
glGenFramebuffers(1, &m_FBO);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer::FrameBuffer(FrameBuffer && _other) :
|
|
|
|
m_startAddress(_other.m_startAddress), m_endAddress(_other.m_endAddress),
|
|
|
|
m_size(_other.m_size), m_width(_other.m_width), m_height(_other.m_height), m_fillcolor(_other.m_fillcolor),
|
2014-09-28 06:09:03 +00:00
|
|
|
m_scaleX(_other.m_scaleX), m_scaleY(_other.m_scaleY), m_cleared(_other.m_cleared), m_cfb(_other.m_cfb),
|
2014-09-08 11:01:22 +00:00
|
|
|
m_FBO(_other.m_FBO), m_pTexture(_other.m_pTexture), m_pLoadTile(_other.m_pLoadTile), m_pDepthBuffer(_other.m_pDepthBuffer)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
_other.m_FBO = 0;
|
|
|
|
_other.m_pTexture = NULL;
|
|
|
|
_other.m_pLoadTile = NULL;
|
|
|
|
_other.m_pDepthBuffer = NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer::~FrameBuffer()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
if (m_FBO != 0)
|
|
|
|
glDeleteFramebuffers(1, &m_FBO);
|
|
|
|
if (m_pTexture != NULL)
|
|
|
|
textureCache().removeFrameBufferTexture(m_pTexture);
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBufferList::init()
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
m_pCurrent = NULL;
|
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBufferList::destroy() {
|
|
|
|
m_list.clear();
|
|
|
|
m_pCurrent = NULL;
|
2014-09-27 06:31:02 +00:00
|
|
|
m_drawBuffer = GL_BACK;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer * FrameBufferList::findBuffer(u32 _address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
for (FrameBuffers::iterator iter = m_list.begin(); iter != m_list.end(); ++iter)
|
|
|
|
if (iter->m_startAddress <= _address && iter->m_endAddress >= _address)
|
|
|
|
return &(*iter);
|
|
|
|
return NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer * FrameBufferList::findTmpBuffer(u32 _address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
for (FrameBuffers::iterator iter = m_list.begin(); iter != m_list.end(); ++iter)
|
|
|
|
if (iter->m_startAddress > _address || iter->m_endAddress < _address)
|
|
|
|
return &(*iter);
|
|
|
|
return NULL;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
|
|
|
|
2014-09-28 06:09:03 +00:00
|
|
|
void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _width, u16 _height, bool _cfb)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-27 06:17:01 +00:00
|
|
|
if (_SHIFTR(*REG.VI_H_START, 0, 10) == 0) // H width is zero. Don't save
|
|
|
|
return;
|
2014-09-21 12:15:22 +00:00
|
|
|
OGLVideo & ogl = video();
|
2014-09-08 11:01:22 +00:00
|
|
|
m_drawBuffer = GL_FRAMEBUFFER;
|
|
|
|
if (m_pCurrent != NULL && gDP.colorImage.height > 1) {
|
2014-09-20 17:34:07 +00:00
|
|
|
m_pCurrent->m_endAddress = min(RDRAMSize, m_pCurrent->m_startAddress + (((m_pCurrent->m_width * gDP.colorImage.height) << m_pCurrent->m_size >> 1) - 1));
|
2014-09-28 06:09:03 +00:00
|
|
|
if (!config.frameBufferEmulation.copyToRDRAM && !m_pCurrent->m_cfb && !m_pCurrent->m_cleared)
|
2014-09-08 11:01:22 +00:00
|
|
|
gDPFillRDRAM(m_pCurrent->m_startAddress, 0, 0, m_pCurrent->m_width, gDP.colorImage.height, m_pCurrent->m_width, m_pCurrent->m_size, m_pCurrent->m_fillcolor);
|
2013-08-10 11:10:44 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
if (m_pCurrent == NULL || m_pCurrent->m_startAddress != _address)
|
|
|
|
m_pCurrent = findBuffer(_address);
|
|
|
|
if (m_pCurrent != NULL) {
|
|
|
|
if ((m_pCurrent->m_startAddress != _address) ||
|
|
|
|
(m_pCurrent->m_width != _width) ||
|
2013-09-04 02:15:05 +00:00
|
|
|
//(current->height != height) ||
|
|
|
|
//(current->size != size) || // TODO FIX ME
|
2014-09-21 12:15:22 +00:00
|
|
|
(m_pCurrent->m_scaleX != ogl.getScaleX()) ||
|
|
|
|
(m_pCurrent->m_scaleY != ogl.getScaleY()))
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
removeBuffer(m_pCurrent->m_startAddress);
|
|
|
|
m_pCurrent = NULL;
|
2013-09-05 15:53:49 +00:00
|
|
|
} else {
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_pCurrent->m_FBO);
|
|
|
|
if (m_pCurrent->m_size != _size) {
|
2013-09-05 15:53:49 +00:00
|
|
|
f32 fillColor[4];
|
|
|
|
gDPGetFillColor(fillColor);
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.getRender().clearColorBuffer(fillColor);
|
2014-09-08 11:01:22 +00:00
|
|
|
m_pCurrent->m_size = _size;
|
|
|
|
m_pCurrent->m_pTexture->format = _format;
|
|
|
|
m_pCurrent->m_pTexture->size = _size;
|
2013-09-05 15:53:49 +00:00
|
|
|
}
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2013-09-05 15:53:49 +00:00
|
|
|
}
|
2014-09-08 11:01:22 +00:00
|
|
|
const bool bNew = m_pCurrent == NULL;
|
2013-10-19 13:32:39 +00:00
|
|
|
if (bNew) {
|
2013-09-05 15:53:49 +00:00
|
|
|
// Wasn't found or removed, create a new one
|
2014-09-08 11:01:22 +00:00
|
|
|
m_list.emplace_front();
|
|
|
|
FrameBuffer & buffer = m_list.front();
|
|
|
|
|
|
|
|
buffer.m_startAddress = _address;
|
|
|
|
buffer.m_endAddress = _address + ((_width * _height << _size >> 1) - 1);
|
|
|
|
buffer.m_width = _width;
|
|
|
|
buffer.m_height = _height;
|
|
|
|
buffer.m_size = _size;
|
2014-09-21 12:15:22 +00:00
|
|
|
buffer.m_scaleX = ogl.getScaleX();
|
|
|
|
buffer.m_scaleY = ogl.getScaleY();
|
2014-09-08 11:01:22 +00:00
|
|
|
buffer.m_fillcolor = 0;
|
2014-09-28 06:09:03 +00:00
|
|
|
buffer.m_cfb = _cfb;
|
2014-09-08 11:01:22 +00:00
|
|
|
|
2014-09-21 12:15:22 +00:00
|
|
|
buffer.m_pTexture->width = (u32)(buffer.m_width * video().getScaleX());
|
|
|
|
buffer.m_pTexture->height = (u32)(buffer.m_height * video().getScaleY());
|
2014-09-08 11:01:22 +00:00
|
|
|
buffer.m_pTexture->format = _format;
|
|
|
|
buffer.m_pTexture->size = _size;
|
|
|
|
buffer.m_pTexture->clampS = 1;
|
|
|
|
buffer.m_pTexture->clampT = 1;
|
|
|
|
buffer.m_pTexture->address = buffer.m_startAddress;
|
|
|
|
buffer.m_pTexture->clampWidth = buffer.m_width;
|
|
|
|
buffer.m_pTexture->clampHeight = buffer.m_height;
|
|
|
|
buffer.m_pTexture->frameBufferTexture = TRUE;
|
|
|
|
buffer.m_pTexture->maskS = 0;
|
|
|
|
buffer.m_pTexture->maskT = 0;
|
|
|
|
buffer.m_pTexture->mirrorS = 0;
|
|
|
|
buffer.m_pTexture->mirrorT = 0;
|
|
|
|
buffer.m_pTexture->realWidth = (u32)pow2( buffer.m_pTexture->width );
|
|
|
|
buffer.m_pTexture->realHeight = (u32)pow2( buffer.m_pTexture->height );
|
|
|
|
buffer.m_pTexture->textureBytes = buffer.m_pTexture->realWidth * buffer.m_pTexture->realHeight * 4;
|
|
|
|
textureCache().addFrameBufferTextureSize(buffer.m_pTexture->textureBytes);
|
|
|
|
|
|
|
|
glBindTexture( GL_TEXTURE_2D, buffer.m_pTexture->glName );
|
|
|
|
if (_size > G_IM_SIZ_8b)
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, buffer.m_pTexture->realWidth, buffer.m_pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2013-06-11 17:20:10 +00:00
|
|
|
else
|
2014-09-08 11:01:22 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, monohromeInternalformat, buffer.m_pTexture->realWidth, buffer.m_pTexture->realHeight, 0, monohromeformat, GL_UNSIGNED_BYTE, NULL);
|
2013-06-04 16:05:09 +00:00
|
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
|
|
|
|
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
|
2014-04-10 14:41:09 +00:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, buffer.m_FBO);
|
|
|
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer.m_pTexture->glName, 0);
|
|
|
|
m_pCurrent = &buffer;
|
2013-06-04 16:05:09 +00:00
|
|
|
}
|
2013-06-01 13:10:30 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
attachDepthBuffer();
|
2013-06-01 13:10:30 +00:00
|
|
|
|
|
|
|
#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
|
2013-10-19 13:32:39 +00:00
|
|
|
// HACK ALERT: Dirty hack for Mario Tennis score board
|
2014-09-08 11:01:22 +00:00
|
|
|
if (bNew && (m_pCurrent->m_startAddress == 0x13ba50 || m_pCurrent->m_startAddress == 0x264430))
|
|
|
|
g_RDRAMtoFB.CopyFromRDRAM(m_pCurrent->m_startAddress, false);
|
|
|
|
*(u32*)&RDRAM[m_pCurrent->m_startAddress] = m_pCurrent->m_startAddress;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
m_pCurrent->m_cleared = false;
|
2013-04-05 06:13:26 +00:00
|
|
|
|
|
|
|
gSP.changed |= CHANGED_TEXTURE;
|
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBufferList::removeBuffer(u32 _address )
|
|
|
|
{
|
|
|
|
for (FrameBuffers::iterator iter = m_list.begin(); iter != m_list.end(); ++iter)
|
|
|
|
if (iter->m_startAddress == _address) {
|
|
|
|
m_list.erase(iter);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferList::attachDepthBuffer()
|
2013-10-30 06:07:24 +00:00
|
|
|
{
|
2014-09-08 11:00:13 +00:00
|
|
|
DepthBuffer * pDepthBuffer = depthBufferList().getCurrent();
|
|
|
|
if (m_pCurrent != NULL && m_pCurrent->m_FBO > 0 && pDepthBuffer != NULL && pDepthBuffer->m_renderbuf > 0) {
|
|
|
|
if (pDepthBuffer->m_pDepthTexture == NULL || pDepthBuffer->m_pDepthTexture->width != m_pCurrent->m_pTexture->width)
|
|
|
|
pDepthBuffer->initDepthTexture(m_pCurrent);
|
|
|
|
m_pCurrent->m_pDepthBuffer = pDepthBuffer;
|
|
|
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, pDepthBuffer->m_renderbuf);
|
2014-04-08 11:53:25 +00:00
|
|
|
#ifndef GLES2
|
2014-09-11 15:03:15 +00:00
|
|
|
GLuint attachments[1] = { GL_COLOR_ATTACHMENT0 };
|
|
|
|
glDrawBuffers(1, attachments);
|
2014-09-08 11:00:13 +00:00
|
|
|
glBindImageTexture(depthImageUnit, pDepthBuffer->m_pDepthTexture->glName, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F);
|
2014-04-08 11:53:25 +00:00
|
|
|
#endif
|
2013-10-30 06:07:24 +00:00
|
|
|
assert(checkFBO());
|
2014-09-08 11:01:22 +00:00
|
|
|
} else if (m_pCurrent != NULL) {
|
|
|
|
m_pCurrent->m_pDepthBuffer = NULL;
|
2014-04-08 11:53:25 +00:00
|
|
|
#ifndef GLES2
|
2013-10-30 06:07:24 +00:00
|
|
|
GLuint attachments[1] = { GL_COLOR_ATTACHMENT0 };
|
2014-03-21 09:38:39 +00:00
|
|
|
glDrawBuffers(1, attachments);
|
2014-04-08 11:53:25 +00:00
|
|
|
#endif
|
2013-10-30 06:07:24 +00:00
|
|
|
assert(checkFBO());
|
|
|
|
}
|
2014-09-03 03:19:27 +00:00
|
|
|
currentCombiner()->updateDepthInfo(true);
|
2013-10-30 06:07:24 +00:00
|
|
|
}
|
2013-06-01 13:13:04 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBuffer_Init()
|
|
|
|
{
|
|
|
|
frameBufferList().init();
|
2014-04-10 14:44:07 +00:00
|
|
|
#ifndef GLES2
|
2014-09-08 11:01:22 +00:00
|
|
|
g_fbToRDRAM.Init();
|
|
|
|
g_dbToRDRAM.Init();
|
|
|
|
#endif
|
|
|
|
g_RDRAMtoFB.Init();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FrameBuffer_Destroy()
|
|
|
|
{
|
|
|
|
g_RDRAMtoFB.Destroy();
|
|
|
|
#ifndef GLES2
|
|
|
|
g_dbToRDRAM.Destroy();
|
|
|
|
g_fbToRDRAM.Destroy();
|
|
|
|
#endif
|
|
|
|
frameBufferList().destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef GLES2
|
|
|
|
void FrameBufferList::renderBuffer(u32 _address)
|
2013-06-01 13:13:04 +00:00
|
|
|
{
|
2014-09-26 12:19:23 +00:00
|
|
|
static u32 vStartPrev = 0;
|
|
|
|
|
2013-09-29 15:02:50 +00:00
|
|
|
if (_SHIFTR( *REG.VI_H_START, 0, 10 ) == 0) // H width is zero. Don't draw
|
|
|
|
return;
|
2014-09-27 15:27:32 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer *pBuffer = findBuffer(_address);
|
|
|
|
if (pBuffer == NULL)
|
2013-09-04 02:15:05 +00:00
|
|
|
return;
|
2014-09-27 15:27:32 +00:00
|
|
|
|
2014-09-21 12:15:22 +00:00
|
|
|
OGLVideo & ogl = video();
|
2013-09-29 15:02:50 +00:00
|
|
|
GLint srcY0, srcY1, dstY0, dstY1;
|
|
|
|
GLint partHeight = 0;
|
|
|
|
const u32 vStart = _SHIFTR( *REG.VI_V_START, 17, 9 );
|
2014-09-26 12:19:23 +00:00
|
|
|
bool isLowerField = false;
|
|
|
|
if ((*REG.VI_STATUS & 0x40) != 0) {
|
|
|
|
const bool isPAL = (*REG.VI_V_SYNC & 0x3ff) > 550;
|
|
|
|
isLowerField = isPAL ? vStart < vStartPrev : vStart > vStartPrev;
|
|
|
|
}
|
|
|
|
vStartPrev = vStart;
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
srcY0 = ((_address - pBuffer->m_startAddress) << 1 >> pBuffer->m_size) / (*REG.VI_WIDTH);
|
2014-09-26 12:19:23 +00:00
|
|
|
if (isLowerField)
|
|
|
|
--srcY0;
|
|
|
|
|
2013-09-29 15:02:50 +00:00
|
|
|
srcY1 = srcY0 + VI.real_height;
|
|
|
|
if (srcY1 > VI.height) {
|
|
|
|
partHeight = srcY1 - VI.height;
|
|
|
|
srcY1 = VI.height;
|
2014-09-27 15:27:32 +00:00
|
|
|
dstY0 = 1;
|
|
|
|
dstY1 = dstY0 + VI.real_height - partHeight;
|
|
|
|
} else {
|
|
|
|
dstY0 = srcY0;
|
|
|
|
dstY1 = srcY1;
|
2013-09-29 15:02:50 +00:00
|
|
|
}
|
|
|
|
|
2014-06-09 04:26:43 +00:00
|
|
|
// glDisable(GL_SCISSOR_TEST) does not affect glBlitFramebuffer, at least on AMD
|
2014-09-21 12:15:22 +00:00
|
|
|
glScissor(0, 0, ogl.getWidth(), ogl.getHeight());
|
2014-06-09 04:26:43 +00:00
|
|
|
glDisable(GL_SCISSOR_TEST);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
2014-03-21 08:16:36 +00:00
|
|
|
//glDrawBuffer( GL_BACK );
|
2013-10-10 10:39:50 +00:00
|
|
|
float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.getRender().clearColorBuffer(clearColor);
|
2014-09-27 15:27:32 +00:00
|
|
|
const float scaleY = ogl.getScaleY();
|
2014-03-21 09:38:39 +00:00
|
|
|
glBlitFramebuffer(
|
2014-09-27 15:27:32 +00:00
|
|
|
0, (GLint)(srcY0*scaleY), ogl.getWidth(), (GLint)(srcY1*scaleY),
|
|
|
|
0, ogl.getHeightOffset() + (GLint)(dstY0*scaleY), ogl.getWidth(), ogl.getHeightOffset() + (GLint)(dstY1*scaleY),
|
2013-09-04 02:15:05 +00:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
|
|
|
);
|
2014-09-26 12:19:23 +00:00
|
|
|
|
2013-09-29 15:02:50 +00:00
|
|
|
if (partHeight > 0) {
|
|
|
|
const u32 size = *REG.VI_STATUS & 3;
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer = findBuffer(_address + (((*REG.VI_WIDTH)*VI.height)<<size>>1));
|
|
|
|
if (pBuffer != NULL) {
|
2013-09-29 15:02:50 +00:00
|
|
|
srcY0 = 0;
|
|
|
|
srcY1 = partHeight;
|
|
|
|
dstY0 = dstY1;
|
|
|
|
dstY1 = dstY0 + partHeight;
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBlitFramebuffer(
|
2014-09-27 15:27:32 +00:00
|
|
|
0, (GLint)(srcY0*scaleY), ogl.getWidth(), (GLint)(srcY1*scaleY),
|
|
|
|
0, ogl.getHeightOffset() + (GLint)(dstY0*scaleY), ogl.getWidth(), ogl.getHeightOffset() + (GLint)(dstY1*scaleY),
|
2013-09-29 15:02:50 +00:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2014-09-26 12:19:23 +00:00
|
|
|
|
2014-06-09 04:26:43 +00:00
|
|
|
glEnable(GL_SCISSOR_TEST);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurrent->m_FBO);
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.swapBuffers();
|
2014-06-09 04:26:43 +00:00
|
|
|
gDP.changed |= CHANGED_SCISSOR;
|
2013-06-01 13:13:04 +00:00
|
|
|
}
|
|
|
|
#else
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBufferList::renderBuffer(u32 _address)
|
2013-04-05 06:13:26 +00:00
|
|
|
{
|
2014-04-10 15:44:05 +00:00
|
|
|
if (_SHIFTR( *REG.VI_H_START, 0, 10 ) == 0) // H width is zero. Don't draw
|
|
|
|
return;
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer *pBuffer = findBuffer(_address);
|
|
|
|
if (pBuffer == NULL)
|
2014-04-10 15:44:05 +00:00
|
|
|
return;
|
2013-06-01 13:10:30 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
CombinerInfo::get().setCombine( EncodeCombineMode( 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1 ) );
|
2014-04-10 15:44:05 +00:00
|
|
|
glDisable( GL_BLEND );
|
2014-05-14 09:23:49 +00:00
|
|
|
glDisable(GL_SCISSOR_TEST);
|
|
|
|
glDisable(GL_DEPTH_TEST);
|
2014-04-10 15:44:05 +00:00
|
|
|
glDisable( GL_CULL_FACE );
|
|
|
|
glDisable( GL_POLYGON_OFFSET_FILL );
|
|
|
|
gSP.changed = gDP.changed = 0;
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
const u32 width = pBuffer->m_width;
|
|
|
|
const u32 height = pBuffer->m_height;
|
2014-04-10 15:44:05 +00:00
|
|
|
|
2014-09-21 12:15:22 +00:00
|
|
|
OGLVideo & ogl = video();
|
|
|
|
pBuffer->m_pTexture->scaleS = ogl.getScaleX() / (float)pBuffer->m_pTexture->realWidth;
|
|
|
|
pBuffer->m_pTexture->scaleT = ogl.getScaleY() / (float)pBuffer->m_pTexture->realHeight;
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleS = 1.0f;
|
|
|
|
pBuffer->m_pTexture->shiftScaleT = 1.0f;
|
|
|
|
pBuffer->m_pTexture->offsetS = 0;
|
|
|
|
pBuffer->m_pTexture->offsetT = (float)height;
|
|
|
|
textureCache().activateTexture(0, pBuffer->m_pTexture);
|
2014-04-10 15:44:05 +00:00
|
|
|
gSP.textureTile[0]->fuls = gSP.textureTile[0]->fult = 0.0f;
|
2014-09-08 11:01:22 +00:00
|
|
|
currentCombiner()->updateTextureInfo(true);
|
2014-04-10 15:44:05 +00:00
|
|
|
|
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
2014-09-26 12:20:19 +00:00
|
|
|
m_drawBuffer = GL_BACK;
|
|
|
|
ogl.getRender().drawTexturedRect(0.0f, 0.0f, width, height, 0.0f, 0.0f, width - 1.0f, height - 1.0f, false);
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.swapBuffers();
|
2014-09-26 12:20:19 +00:00
|
|
|
m_drawBuffer = GL_FRAMEBUFFER;
|
2014-06-09 04:26:43 +00:00
|
|
|
glEnable(GL_SCISSOR_TEST);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_FRAMEBUFFER, m_pCurrent->m_FBO);
|
2014-04-10 15:44:05 +00:00
|
|
|
gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
|
|
|
|
gDP.changed |= CHANGED_COMBINE;
|
2013-04-05 06:13:26 +00:00
|
|
|
}
|
2013-06-01 13:13:04 +00:00
|
|
|
#endif
|
2013-06-01 13:10:30 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBuffer_ActivateBufferTexture(s16 t, FrameBuffer *pBuffer)
|
2013-09-05 16:24:34 +00:00
|
|
|
{
|
2014-09-21 12:15:22 +00:00
|
|
|
pBuffer->m_pTexture->scaleS = video().getScaleX() / (float)pBuffer->m_pTexture->realWidth;
|
|
|
|
pBuffer->m_pTexture->scaleT = video().getScaleY() / (float)pBuffer->m_pTexture->realHeight;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
|
|
|
if (gSP.textureTile[t]->shifts > 10)
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleS = (float)(1 << (16 - gSP.textureTile[t]->shifts));
|
2013-09-05 16:24:34 +00:00
|
|
|
else if (gSP.textureTile[t]->shifts > 0)
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleS = 1.0f / (float)(1 << gSP.textureTile[t]->shifts);
|
2013-09-05 16:24:34 +00:00
|
|
|
else
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleS = 1.0f;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
|
|
|
if (gSP.textureTile[t]->shiftt > 10)
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleT = (float)(1 << (16 - gSP.textureTile[t]->shiftt));
|
2013-09-05 16:24:34 +00:00
|
|
|
else if (gSP.textureTile[t]->shiftt > 0)
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleT = 1.0f / (float)(1 << gSP.textureTile[t]->shiftt);
|
2013-09-05 16:24:34 +00:00
|
|
|
else
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleT = 1.0f;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
const u32 shift = gSP.textureTile[t]->imageAddress - pBuffer->m_startAddress;
|
|
|
|
const u32 factor = pBuffer->m_width << pBuffer->m_size >> 1;
|
2013-09-05 16:24:34 +00:00
|
|
|
if (gSP.textureTile[t]->loadType == LOADTYPE_TILE)
|
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->offsetS = pBuffer->m_pLoadTile->uls;
|
|
|
|
pBuffer->m_pTexture->offsetT = (float)(pBuffer->m_height - (pBuffer->m_pLoadTile->ult + shift/factor));
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->offsetS = (float)(shift % factor);
|
|
|
|
pBuffer->m_pTexture->offsetT = (float)(pBuffer->m_height - shift/factor);
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// FrameBuffer_RenderBuffer(buffer->startAddress);
|
2014-09-08 11:01:22 +00:00
|
|
|
textureCache().activateTexture(t, pBuffer->m_pTexture);
|
2014-04-27 12:26:12 +00:00
|
|
|
gDP.changed |= CHANGED_FB_TEXTURE;
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
void FrameBuffer_ActivateBufferTextureBG(s16 t, FrameBuffer *pBuffer )
|
2013-09-05 16:24:34 +00:00
|
|
|
{
|
2014-09-21 12:15:22 +00:00
|
|
|
pBuffer->m_pTexture->scaleS = video().getScaleX() / (float)pBuffer->m_pTexture->realWidth;
|
|
|
|
pBuffer->m_pTexture->scaleT = video().getScaleY() / (float)pBuffer->m_pTexture->realHeight;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->shiftScaleS = 1.0f;
|
|
|
|
pBuffer->m_pTexture->shiftScaleT = 1.0f;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
pBuffer->m_pTexture->offsetS = gSP.bgImage.imageX;
|
|
|
|
pBuffer->m_pTexture->offsetT = (float)pBuffer->m_height - gSP.bgImage.imageY;
|
2013-09-05 16:24:34 +00:00
|
|
|
|
|
|
|
// FrameBuffer_RenderBuffer(buffer->startAddress);
|
2014-09-08 11:01:22 +00:00
|
|
|
textureCache().activateTexture(t, pBuffer->m_pTexture);
|
2014-04-27 12:26:12 +00:00
|
|
|
gDP.changed |= CHANGED_FB_TEXTURE;
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
2013-08-10 11:12:17 +00:00
|
|
|
|
2014-04-10 14:44:07 +00:00
|
|
|
#ifndef GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
void FrameBufferToRDRAM::Init()
|
2013-08-10 11:12:17 +00:00
|
|
|
{
|
2013-09-05 16:24:34 +00:00
|
|
|
// generate a framebuffer
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glGenFramebuffers(1, &m_FBO);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
2013-09-07 16:28:20 +00:00
|
|
|
|
2014-09-18 16:16:52 +00:00
|
|
|
m_pTexture = textureCache().addFrameBufferTexture();
|
2013-09-07 16:28:20 +00:00
|
|
|
m_pTexture->format = G_IM_FMT_RGBA;
|
|
|
|
m_pTexture->clampS = 1;
|
|
|
|
m_pTexture->clampT = 1;
|
|
|
|
m_pTexture->frameBufferTexture = TRUE;
|
|
|
|
m_pTexture->maskS = 0;
|
|
|
|
m_pTexture->maskT = 0;
|
|
|
|
m_pTexture->mirrorS = 0;
|
|
|
|
m_pTexture->mirrorT = 0;
|
|
|
|
m_pTexture->realWidth = 1024;
|
|
|
|
m_pTexture->realHeight = 512;
|
|
|
|
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
2014-09-18 16:16:52 +00:00
|
|
|
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
2013-09-07 16:28:20 +00:00
|
|
|
glBindTexture( GL_TEXTURE_2D, m_pTexture->glName );
|
2014-03-21 08:16:36 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_pTexture->realWidth, m_pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2013-09-05 16:24:34 +00:00
|
|
|
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);
|
2013-09-07 16:28:20 +00:00
|
|
|
|
2014-04-08 15:18:20 +00:00
|
|
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->glName, 0);
|
2013-09-05 16:24:34 +00:00
|
|
|
// check if everything is OK
|
|
|
|
assert(checkFBO());
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
2013-09-05 16:24:34 +00:00
|
|
|
|
|
|
|
// Generate and initialize Pixel Buffer Objects
|
|
|
|
glGenBuffers(2, m_aPBO);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[0]);
|
|
|
|
glBufferData(GL_PIXEL_PACK_BUFFER, 640*480*4, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[1]);
|
|
|
|
glBufferData(GL_PIXEL_PACK_BUFFER, 640*480*4, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferToRDRAM::Destroy() {
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glDeleteFramebuffers(1, &m_FBO);
|
2013-11-18 03:30:20 +00:00
|
|
|
m_FBO = 0;
|
2014-09-11 07:38:56 +00:00
|
|
|
if (m_pTexture != NULL) {
|
|
|
|
textureCache().removeFrameBufferTexture(m_pTexture);
|
|
|
|
m_pTexture = NULL;
|
|
|
|
}
|
2013-09-07 16:28:20 +00:00
|
|
|
glDeleteBuffers(2, m_aPBO);
|
2013-11-18 03:30:20 +00:00
|
|
|
m_aPBO[0] = m_aPBO[1] = 0;
|
2014-09-25 15:57:50 +00:00
|
|
|
m_curIndex = 0;
|
|
|
|
m_aAddress[0] = m_aAddress[1] = 0;
|
2013-09-05 16:24:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FrameBufferToRDRAM::CopyToRDRAM( u32 address, bool bSync ) {
|
2014-09-27 06:17:01 +00:00
|
|
|
if (_SHIFTR(*REG.VI_H_START, 0, 10) == 0) // H width is zero. Don't copy
|
|
|
|
return;
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer *pBuffer = frameBufferList().findBuffer(address);
|
|
|
|
if (pBuffer == NULL)
|
2013-09-04 02:15:05 +00:00
|
|
|
return;
|
2013-08-10 11:12:17 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
address = pBuffer->m_startAddress;
|
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO);
|
2013-09-04 02:15:05 +00:00
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
2013-09-04 02:15:05 +00:00
|
|
|
GLuint attachment = GL_COLOR_ATTACHMENT0;
|
|
|
|
glDrawBuffers(1, &attachment);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBlitFramebuffer(
|
2014-09-21 12:15:22 +00:00
|
|
|
0, 0, video().getWidth(), video().getHeight(),
|
2014-09-08 11:01:22 +00:00
|
|
|
0, 0, pBuffer->m_width, pBuffer->m_height,
|
2013-09-04 02:15:05 +00:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
|
|
|
);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferList().getCurrent()->m_FBO);
|
2013-09-04 02:15:05 +00:00
|
|
|
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
|
2014-03-21 08:16:36 +00:00
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
2014-04-10 14:44:07 +00:00
|
|
|
#if 1 //ndef GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
// If Sync, read pixels from the buffer, copy them to RDRAM.
|
|
|
|
// If not Sync, read pixels from the buffer, copy pixels from the previous buffer to RDRAM.
|
|
|
|
if (m_aAddress[m_curIndex] == 0)
|
|
|
|
bSync = true;
|
|
|
|
m_curIndex = (m_curIndex + 1) % 2;
|
|
|
|
const u32 nextIndex = bSync ? m_curIndex : (m_curIndex + 1) % 2;
|
|
|
|
m_aAddress[m_curIndex] = address;
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[m_curIndex]);
|
2013-09-26 10:29:59 +00:00
|
|
|
glReadPixels( 0, 0, VI.width, VI.height, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
|
2013-09-05 16:24:34 +00:00
|
|
|
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[nextIndex]);
|
|
|
|
GLubyte* pixelData = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
|
|
|
if(pixelData == NULL) {
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
|
|
return;
|
|
|
|
}
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
m_curIndex = 0;
|
|
|
|
m_aAddress[0] = address;
|
|
|
|
const u32 nextIndex = 0;
|
|
|
|
GLubyte* pixelData = (GLubyte* )malloc(VI.width*VI.height*4);
|
|
|
|
if(pixelData == NULL)
|
|
|
|
return;
|
|
|
|
glReadPixels( 0, 0, VI.width, VI.height, GL_RGBA, GL_UNSIGNED_BYTE, pixelData );
|
|
|
|
#endif // GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
if (pBuffer->m_size == G_IM_SIZ_32b) {
|
2013-09-05 16:24:34 +00:00
|
|
|
u32 *ptr_dst = (u32*)(RDRAM + m_aAddress[nextIndex]);
|
2013-09-04 02:15:05 +00:00
|
|
|
u32 *ptr_src = (u32*)pixelData;
|
|
|
|
|
|
|
|
for (u32 y = 0; y < VI.height; ++y) {
|
|
|
|
for (u32 x = 0; x < VI.width; ++x)
|
|
|
|
ptr_dst[x + y*VI.width] = ptr_src[x + (VI.height - y - 1)*VI.width];
|
|
|
|
}
|
|
|
|
} else {
|
2013-09-05 16:24:34 +00:00
|
|
|
u16 *ptr_dst = (u16*)(RDRAM + m_aAddress[nextIndex]);
|
2013-09-04 02:15:05 +00:00
|
|
|
RGBA * ptr_src = (RGBA*)pixelData;
|
|
|
|
|
|
|
|
for (u32 y = 0; y < VI.height; ++y) {
|
|
|
|
for (u32 x = 0; x < VI.width; ++x) {
|
|
|
|
const RGBA & c = ptr_src[x + (VI.height - y - 1)*VI.width];
|
|
|
|
ptr_dst[(x + y*VI.width)^1] = ((c.r>>3)<<11) | ((c.g>>3)<<6) | ((c.b>>3)<<1) | (c.a == 0 ? 0 : 1);
|
2013-08-10 11:12:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-04-10 14:44:07 +00:00
|
|
|
#if 1 //ndef GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
free(pixelData);
|
|
|
|
#endif
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
2013-08-10 11:12:17 +00:00
|
|
|
}
|
2014-04-10 14:44:07 +00:00
|
|
|
#endif // GLES2
|
2013-08-10 11:12:17 +00:00
|
|
|
|
2013-09-05 16:24:34 +00:00
|
|
|
void FrameBuffer_CopyToRDRAM( u32 address, bool bSync )
|
2013-06-09 11:55:21 +00:00
|
|
|
{
|
2014-04-10 14:44:07 +00:00
|
|
|
#ifndef GLES2
|
2013-09-05 16:24:34 +00:00
|
|
|
g_fbToRDRAM.CopyToRDRAM(address, bSync);
|
2014-04-10 14:44:07 +00:00
|
|
|
#endif
|
2013-06-09 11:55:21 +00:00
|
|
|
}
|
2013-09-07 16:31:04 +00:00
|
|
|
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-11-12 08:41:19 +00:00
|
|
|
void DepthBufferToRDRAM::Init()
|
|
|
|
{
|
|
|
|
// generate a framebuffer
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glGenFramebuffers(1, &m_FBO);
|
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
2013-11-12 08:41:19 +00:00
|
|
|
|
2014-09-18 16:16:52 +00:00
|
|
|
m_pTexture = textureCache().addFrameBufferTexture();
|
2013-11-12 08:41:19 +00:00
|
|
|
m_pTexture->format = G_IM_FMT_IA;
|
|
|
|
m_pTexture->clampS = 1;
|
|
|
|
m_pTexture->clampT = 1;
|
|
|
|
m_pTexture->frameBufferTexture = TRUE;
|
|
|
|
m_pTexture->maskS = 0;
|
|
|
|
m_pTexture->maskT = 0;
|
|
|
|
m_pTexture->mirrorS = 0;
|
|
|
|
m_pTexture->mirrorT = 0;
|
|
|
|
m_pTexture->realWidth = 1024;
|
|
|
|
m_pTexture->realHeight = 512;
|
|
|
|
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 2;
|
2014-09-18 16:16:52 +00:00
|
|
|
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
2013-11-12 08:41:19 +00:00
|
|
|
glBindTexture( GL_TEXTURE_2D, m_pTexture->glName );
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, m_pTexture->realWidth, m_pTexture->realHeight, 0, GL_RED, GL_UNSIGNED_SHORT, 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);
|
|
|
|
|
2014-04-08 15:18:20 +00:00
|
|
|
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->glName, 0);
|
2013-11-12 08:41:19 +00:00
|
|
|
// check if everything is OK
|
|
|
|
assert(checkFBO());
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
2013-11-12 08:41:19 +00:00
|
|
|
|
|
|
|
// Generate and initialize Pixel Buffer Objects
|
|
|
|
glGenBuffers(2, m_aPBO);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[0]);
|
|
|
|
glBufferData(GL_PIXEL_PACK_BUFFER, 640*480*2, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[1]);
|
|
|
|
glBufferData(GL_PIXEL_PACK_BUFFER, 640*480*2, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBufferToRDRAM::Destroy() {
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
|
glDeleteFramebuffers(1, &m_FBO);
|
2013-11-18 03:30:20 +00:00
|
|
|
m_FBO = 0;
|
2014-09-11 07:38:56 +00:00
|
|
|
if (m_pTexture != NULL) {
|
|
|
|
textureCache().removeFrameBufferTexture(m_pTexture);
|
|
|
|
m_pTexture = NULL;
|
|
|
|
}
|
2013-11-12 08:41:19 +00:00
|
|
|
glDeleteBuffers(2, m_aPBO);
|
2013-11-18 03:30:20 +00:00
|
|
|
m_aPBO[0] = m_aPBO[1] = 0;
|
2014-09-25 15:57:50 +00:00
|
|
|
m_curIndex = 0;
|
|
|
|
m_aAddress[0] = m_aAddress[1] = 0;
|
2013-11-12 08:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DepthBufferToRDRAM::CopyToRDRAM( u32 address) {
|
2014-09-27 06:17:01 +00:00
|
|
|
if (_SHIFTR(*REG.VI_H_START, 0, 10) == 0) // H width is zero. Don't copy
|
|
|
|
return;
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer *pBuffer = frameBufferList().findBuffer(address);
|
|
|
|
if (pBuffer == NULL || pBuffer->m_pDepthBuffer == NULL)
|
2013-11-12 08:41:19 +00:00
|
|
|
return;
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
DepthBuffer * pDepthBuffer = pBuffer->m_pDepthBuffer;
|
2014-09-08 11:00:13 +00:00
|
|
|
address = pDepthBuffer->m_address;
|
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, pDepthBuffer->m_FBO);
|
2013-11-12 08:41:19 +00:00
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
2013-11-12 08:41:19 +00:00
|
|
|
GLuint attachment = GL_COLOR_ATTACHMENT0;
|
|
|
|
glDrawBuffers(1, &attachment);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBlitFramebuffer(
|
2014-09-21 12:15:22 +00:00
|
|
|
0, 0, video().getWidth(), video().getHeight(),
|
2014-09-08 11:01:22 +00:00
|
|
|
0, 0, pBuffer->m_width, pBuffer->m_height,
|
2013-11-12 08:41:19 +00:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
|
|
|
);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferList().getCurrent()->m_FBO);
|
2013-11-12 08:41:19 +00:00
|
|
|
|
|
|
|
m_curIndex = (m_curIndex + 1) % 2;
|
|
|
|
const u32 nextIndex = m_aAddress[m_curIndex] == 0 ? m_curIndex : (m_curIndex + 1) % 2;
|
|
|
|
m_aAddress[m_curIndex] = address;
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[m_curIndex]);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
|
2013-11-12 08:41:19 +00:00
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
|
|
|
glReadPixels( 0, 0, VI.width, VI.height, GL_RED, GL_UNSIGNED_SHORT, 0 );
|
|
|
|
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_aPBO[nextIndex]);
|
|
|
|
GLubyte* pixelData = (GLubyte*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
|
|
|
if(pixelData == NULL) {
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 * ptr_src = (u16*)pixelData;
|
|
|
|
u16 *ptr_dst = (u16*)(RDRAM + m_aAddress[nextIndex]);
|
|
|
|
u16 col;
|
|
|
|
|
|
|
|
for (u32 y = 0; y < VI.height; ++y) {
|
|
|
|
for (u32 x = 0; x < VI.width; ++x) {
|
|
|
|
col = ptr_src[x + (VI.height - y - 1)*VI.width];
|
|
|
|
ptr_dst[(x + y*VI.width)^1] = col;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
|
|
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
2013-11-12 08:41:19 +00:00
|
|
|
}
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif // GLES2
|
2013-11-12 08:41:19 +00:00
|
|
|
|
|
|
|
void FrameBuffer_CopyDepthBuffer( u32 address ) {
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-11-12 08:41:19 +00:00
|
|
|
g_dbToRDRAM.CopyToRDRAM(address);
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif
|
2013-11-12 08:41:19 +00:00
|
|
|
}
|
|
|
|
|
2013-09-07 16:31:04 +00:00
|
|
|
void RDRAMtoFrameBuffer::Init()
|
|
|
|
{
|
2014-09-18 16:16:52 +00:00
|
|
|
m_pTexture = textureCache().addFrameBufferTexture();
|
2013-09-07 16:31:04 +00:00
|
|
|
m_pTexture->format = G_IM_FMT_RGBA;
|
|
|
|
m_pTexture->clampS = 1;
|
|
|
|
m_pTexture->clampT = 1;
|
|
|
|
m_pTexture->frameBufferTexture = TRUE;
|
|
|
|
m_pTexture->maskS = 0;
|
|
|
|
m_pTexture->maskT = 0;
|
|
|
|
m_pTexture->mirrorS = 0;
|
|
|
|
m_pTexture->mirrorT = 0;
|
|
|
|
m_pTexture->realWidth = 1024;
|
|
|
|
m_pTexture->realHeight = 512;
|
|
|
|
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
2014-09-18 16:16:52 +00:00
|
|
|
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
2013-09-07 16:31:04 +00:00
|
|
|
glBindTexture( GL_TEXTURE_2D, m_pTexture->glName );
|
2014-03-21 08:16:36 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_pTexture->realWidth, m_pTexture->realHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2013-09-07 16:31:04 +00:00
|
|
|
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);
|
|
|
|
|
|
|
|
// Generate Pixel Buffer Object. Initialize it later
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
glGenBuffers(1, &m_PBO);
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void RDRAMtoFrameBuffer::Destroy()
|
|
|
|
{
|
2014-09-11 07:38:56 +00:00
|
|
|
if (m_pTexture != NULL) {
|
|
|
|
textureCache().removeFrameBufferTexture(m_pTexture);
|
|
|
|
m_pTexture = NULL;
|
|
|
|
}
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
glDeleteBuffers(1, &m_PBO);
|
2013-11-18 03:30:20 +00:00
|
|
|
m_PBO = 0;
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
}
|
|
|
|
|
2013-09-15 14:40:16 +00:00
|
|
|
void RDRAMtoFrameBuffer::CopyFromRDRAM( u32 _address, bool _bUseAlpha)
|
2013-09-07 16:31:04 +00:00
|
|
|
{
|
2014-09-08 11:01:22 +00:00
|
|
|
FrameBuffer *pBuffer = frameBufferList().findBuffer(_address);
|
|
|
|
if (pBuffer == NULL || pBuffer->m_size < G_IM_SIZ_16b)
|
2013-09-07 16:31:04 +00:00
|
|
|
return;
|
|
|
|
|
2014-09-08 11:01:22 +00:00
|
|
|
const u32 width = pBuffer->m_width;
|
|
|
|
const u32 height = pBuffer->m_height;
|
2013-09-07 16:31:04 +00:00
|
|
|
m_pTexture->width = width;
|
|
|
|
m_pTexture->height = height;
|
|
|
|
const u32 dataSize = width*height*4;
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
PBOBinder binder(m_PBO);
|
|
|
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW);
|
|
|
|
GLubyte* ptr = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
m_PBO = (GLubyte*)malloc(dataSize);
|
|
|
|
GLubyte* ptr = m_PBO;
|
|
|
|
PBOBinder binder(m_PBO);
|
|
|
|
#endif // GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
if (ptr == NULL)
|
|
|
|
return;
|
|
|
|
|
2013-09-15 14:40:16 +00:00
|
|
|
u8 * image = RDRAM + _address;
|
2013-09-07 16:31:04 +00:00
|
|
|
u32 * dst = (u32*)ptr;
|
|
|
|
|
|
|
|
u32 empty = 0;
|
|
|
|
u32 r, g, b,a, idx;
|
2014-09-08 11:01:22 +00:00
|
|
|
if (pBuffer->m_size == G_IM_SIZ_16b) {
|
2013-09-07 16:31:04 +00:00
|
|
|
u16 * src = (u16*)image;
|
|
|
|
u16 col;
|
2013-09-15 14:40:16 +00:00
|
|
|
const u32 bound = (RDRAMSize + 1 - _address) >> 1;
|
2013-09-07 16:31:04 +00:00
|
|
|
for (u32 y = 0; y < height; y++)
|
|
|
|
{
|
|
|
|
for (u32 x = 0; x < width; x++)
|
|
|
|
{
|
|
|
|
idx = (x + (height - y - 1)*width)^1;
|
|
|
|
if (idx >= bound)
|
|
|
|
break;
|
|
|
|
col = src[idx];
|
|
|
|
empty |= col;
|
|
|
|
r = ((col >> 11)&31)<<3;
|
|
|
|
g = ((col >> 6)&31)<<3;
|
|
|
|
b = ((col >> 1)&31)<<3;
|
|
|
|
a = col&1 > 0 ? 0xff : 0;
|
|
|
|
//*(dst++) = RGBA5551_RGBA8888(c);
|
|
|
|
dst[x + y*width] = (a<<24)|(b<<16)|(g<<8)|r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// 32 bit
|
|
|
|
u32 * src = (u32*)image;
|
|
|
|
u32 col;
|
2013-09-15 14:40:16 +00:00
|
|
|
const u32 bound = (RDRAMSize + 1 - _address) >> 2;
|
2013-09-07 16:31:04 +00:00
|
|
|
for (u32 y=0; y < height; y++)
|
|
|
|
{
|
|
|
|
for (u32 x=0; x < width; x++)
|
|
|
|
{
|
|
|
|
idx = x + (height - y - 1)*width;
|
|
|
|
if (idx >= bound)
|
|
|
|
break;
|
|
|
|
col = src[idx];
|
|
|
|
empty |= col;
|
|
|
|
r = (col >> 24) & 0xff;
|
|
|
|
g = (col >> 16) & 0xff;
|
|
|
|
b = (col >> 8) & 0xff;
|
|
|
|
a = col & 0xff;
|
|
|
|
dst[x + y*width] = (a<<24)|(b<<16)|(g<<8)|r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer
|
2014-03-21 08:16:36 +00:00
|
|
|
#endif
|
2013-09-07 16:31:04 +00:00
|
|
|
if (empty == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
2014-03-21 08:16:36 +00:00
|
|
|
#ifndef GLES2
|
2013-09-07 16:31:04 +00:00
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
2014-03-21 08:16:36 +00:00
|
|
|
#else
|
|
|
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, m_PBO);
|
|
|
|
#endif
|
2014-09-21 12:15:22 +00:00
|
|
|
|
|
|
|
OGLVideo & ogl = video();
|
|
|
|
|
2013-09-07 16:31:04 +00:00
|
|
|
#if 0
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
|
2013-09-07 16:31:04 +00:00
|
|
|
const GLuint attachment = GL_COLOR_ATTACHMENT0;
|
|
|
|
glReadBuffer(attachment);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, pBuffer->m_FBO);
|
2013-09-07 16:31:04 +00:00
|
|
|
glDrawBuffers(1, &attachment);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBlitFramebuffer(
|
2013-09-07 16:31:04 +00:00
|
|
|
0, 0, width, height,
|
2014-09-21 12:15:22 +00:00
|
|
|
0, 0, ogl.getWidth(), ogl.getHeight(),
|
2013-09-07 16:31:04 +00:00
|
|
|
GL_COLOR_BUFFER_BIT, GL_LINEAR
|
|
|
|
);
|
2014-03-21 09:38:39 +00:00
|
|
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
2014-09-08 11:01:22 +00:00
|
|
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, frameBufferList().getCurrent()->m_FBO);
|
2013-09-07 16:31:04 +00:00
|
|
|
#else
|
2013-09-15 14:40:16 +00:00
|
|
|
if (_bUseAlpha)
|
2014-09-02 13:06:28 +00:00
|
|
|
CombinerInfo::get().setCombine( EncodeCombineMode( 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0 ) );
|
2013-09-15 14:40:16 +00:00
|
|
|
else
|
2014-09-02 13:06:28 +00:00
|
|
|
CombinerInfo::get().setCombine( EncodeCombineMode( 0, 0, 0, TEXEL0, 0, 0, 0, 1, 0, 0, 0, TEXEL0, 0, 0, 0, 1 ) );
|
2013-09-07 16:31:04 +00:00
|
|
|
glEnable( GL_BLEND );
|
|
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
2013-10-19 13:32:39 +00:00
|
|
|
// glDisable( GL_ALPHA_TEST );
|
2013-09-07 16:31:04 +00:00
|
|
|
glDisable( GL_DEPTH_TEST );
|
|
|
|
glDisable( GL_CULL_FACE );
|
|
|
|
glDisable( GL_POLYGON_OFFSET_FILL );
|
2014-04-08 16:48:04 +00:00
|
|
|
gSP.changed = gDP.changed = 0;
|
|
|
|
|
|
|
|
m_pTexture->scaleS = 1.0f / (float)m_pTexture->realWidth;
|
|
|
|
m_pTexture->scaleT = 1.0f / (float)m_pTexture->realHeight;
|
|
|
|
m_pTexture->shiftScaleS = 1.0f;
|
|
|
|
m_pTexture->shiftScaleT = 1.0f;
|
|
|
|
m_pTexture->offsetS = 0;
|
|
|
|
m_pTexture->offsetT = (float)m_pTexture->height;
|
2014-09-18 16:16:52 +00:00
|
|
|
textureCache().activateTexture(0, m_pTexture);
|
2013-09-07 16:31:04 +00:00
|
|
|
|
2014-09-21 12:15:22 +00:00
|
|
|
ogl.getRender().drawTexturedRect( 0.0f, 0.0f, width, height, 0.0f, 0.0f, width-1.0f, height-1.0f, false );
|
2013-09-07 16:31:04 +00:00
|
|
|
gSP.changed |= CHANGED_TEXTURE | CHANGED_VIEWPORT;
|
|
|
|
gDP.changed |= CHANGED_COMBINE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2013-09-15 14:40:16 +00:00
|
|
|
void FrameBuffer_CopyFromRDRAM( u32 address, bool bUseAlpha )
|
2013-09-07 16:31:04 +00:00
|
|
|
{
|
2013-09-15 14:40:16 +00:00
|
|
|
g_RDRAMtoFB.CopyFromRDRAM(address, bUseAlpha);
|
2013-09-07 16:31:04 +00:00
|
|
|
}
|