mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-02 09:03:37 +00:00
Code refactor: move classes FrameBufferToRDRAM, DepthBufferToRDRAM and RDRAMtoFrameBuffer from FrameBuffer.cpp to separate files.
This commit is contained in:
parent
dca2c29edf
commit
2834fa1780
|
@ -111,7 +111,7 @@
|
|||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>freetype253MT_D.lib;..\..\src\GLideNUI\debug\GLideNUI.lib;osal\Debug\osal.lib;GLideNHQ\Debug\libGLideNHQ.lib;opengl32.lib;glu32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
@ -136,7 +136,7 @@
|
|||
<PrecompiledHeaderFile>glN64.h</PrecompiledHeaderFile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
|
@ -168,7 +168,7 @@
|
|||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<AdditionalIncludeDirectories>../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>freetype253MT.lib;..\..\src\GLideNUI\release\GLideNUI.lib;osal\Release\osal.lib;GLideNHQ\Release\libGLideNHQ.lib;opengl32.lib;winmm.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
|
@ -197,7 +197,7 @@
|
|||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>../../src;../../src/inc;../../src/osal;../../../freetype/include</AdditionalIncludeDirectories>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
|
@ -215,6 +215,9 @@
|
|||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\3DMath.cpp" />
|
||||
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM.cpp" />
|
||||
<ClCompile Include="..\..\src\BufferCopy\DepthBufferToRDRAM.cpp" />
|
||||
<ClCompile Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.cpp" />
|
||||
<ClCompile Include="..\..\src\Combiner.cpp" />
|
||||
<ClCompile Include="..\..\src\CommonPluginAPI.cpp" />
|
||||
<ClCompile Include="..\..\src\common\CommonAPIImpl_common.cpp" />
|
||||
|
@ -303,6 +306,10 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\3DMath.h" />
|
||||
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM.h" />
|
||||
<ClInclude Include="..\..\src\BufferCopy\DepthBufferToRDRAM.h" />
|
||||
<ClInclude Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.h" />
|
||||
<ClInclude Include="..\..\src\BufferCopy\WriteToRDRAM.h" />
|
||||
<ClInclude Include="..\..\src\Combiner.h" />
|
||||
<ClInclude Include="..\..\src\Config.h" />
|
||||
<ClInclude Include="..\..\src\convert.h" />
|
||||
|
|
|
@ -36,6 +36,12 @@
|
|||
<Filter Include="Source Files\OGL3X">
|
||||
<UniqueIdentifier>{32bbb389-ea50-4ac9-bb55-84e4f066fe94}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\BufferCopy">
|
||||
<UniqueIdentifier>{e9bcfc4d-06e5-496a-a069-3d28e2fcd559}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\BufferCopy">
|
||||
<UniqueIdentifier>{03c90b24-47cf-4a72-8652-837470d2a641}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\Combiner.cpp">
|
||||
|
@ -197,6 +203,15 @@
|
|||
<ClCompile Include="..\..\src\FrameBufferInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\BufferCopy\ColorBufferToRDRAM.cpp">
|
||||
<Filter>Source Files\BufferCopy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\BufferCopy\DepthBufferToRDRAM.cpp">
|
||||
<Filter>Source Files\BufferCopy</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.cpp">
|
||||
<Filter>Source Files\BufferCopy</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\3DMath.h">
|
||||
|
@ -358,5 +373,17 @@
|
|||
<ClInclude Include="..\..\src\FrameBufferInfoAPI.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BufferCopy\ColorBufferToRDRAM.h">
|
||||
<Filter>Header Files\BufferCopy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BufferCopy\DepthBufferToRDRAM.h">
|
||||
<Filter>Header Files\BufferCopy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BufferCopy\RDRAMtoColorBuffer.h">
|
||||
<Filter>Header Files\BufferCopy</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\BufferCopy\WriteToRDRAM.h">
|
||||
<Filter>Header Files\BufferCopy</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
370
src/BufferCopy/ColorBufferToRDRAM.cpp
Normal file
370
src/BufferCopy/ColorBufferToRDRAM.cpp
Normal file
|
@ -0,0 +1,370 @@
|
|||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "ColorBufferToRDRAM.h"
|
||||
#include "WriteToRDRAM.h"
|
||||
|
||||
#include <FrameBuffer.h>
|
||||
#include <Textures.h>
|
||||
#include <Config.h>
|
||||
#include <N64.h>
|
||||
#include <VI.h>
|
||||
|
||||
ColorBufferToRDRAM::ColorBufferToRDRAM()
|
||||
: m_FBO(0)
|
||||
, m_pTexture(nullptr)
|
||||
, m_pCurFrameBuffer(nullptr)
|
||||
, m_curIndex(-1)
|
||||
, m_frameCount(-1)
|
||||
, m_startAddress(-1)
|
||||
{
|
||||
m_PBO[0] = m_PBO[1] = m_PBO[2] = 0;
|
||||
}
|
||||
|
||||
ColorBufferToRDRAM::~ColorBufferToRDRAM()
|
||||
{
|
||||
}
|
||||
|
||||
ColorBufferToRDRAM & ColorBufferToRDRAM::get()
|
||||
{
|
||||
static ColorBufferToRDRAM cbCopy;
|
||||
return cbCopy;
|
||||
}
|
||||
|
||||
#ifndef GLES2
|
||||
|
||||
void ColorBufferToRDRAM::init()
|
||||
{
|
||||
// generate a framebuffer
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
||||
|
||||
m_pTexture = textureCache().addFrameBufferTexture();
|
||||
m_pTexture->format = G_IM_FMT_RGBA;
|
||||
m_pTexture->clampS = 1;
|
||||
m_pTexture->clampT = 1;
|
||||
m_pTexture->frameBufferTexture = CachedTexture::fbOneSample;
|
||||
m_pTexture->maskS = 0;
|
||||
m_pTexture->maskT = 0;
|
||||
m_pTexture->mirrorS = 0;
|
||||
m_pTexture->mirrorT = 0;
|
||||
m_pTexture->realWidth = 640;
|
||||
m_pTexture->realHeight = 580;
|
||||
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
||||
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fboFormats.colorInternalFormat, m_pTexture->realWidth, m_pTexture->realHeight, 0, fboFormats.colorFormat, fboFormats.colorType, 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);
|
||||
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pTexture->glName, 0);
|
||||
// check if everything is OK
|
||||
assert(checkFBO());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
#ifdef ANDROID
|
||||
m_window = new GraphicBuffer(m_pTexture->realWidth, m_pTexture->realHeight,
|
||||
PIXEL_FORMAT_RGBA_8888, GraphicBuffer::USAGE_SW_READ_OFTEN | GraphicBuffer::USAGE_HW_TEXTURE);
|
||||
|
||||
EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
|
||||
m_image = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
|
||||
EGL_NATIVE_BUFFER_ANDROID, (EGLClientBuffer)m_window->getNativeBuffer(), eglImgAttrs);
|
||||
|
||||
m_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||
#else
|
||||
// Generate and initialize Pixel Buffer Objects
|
||||
glGenBuffers(3, m_PBO);
|
||||
for (u32 i = 0; i < 3; ++i) {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[i]);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, m_pTexture->textureBytes, NULL, GL_DYNAMIC_READ);
|
||||
}
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
m_curIndex = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::destroy() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
if (m_FBO != 0) {
|
||||
glDeleteFramebuffers(1, &m_FBO);
|
||||
m_FBO = 0;
|
||||
}
|
||||
if (m_pTexture != NULL) {
|
||||
textureCache().removeFrameBufferTexture(m_pTexture);
|
||||
m_pTexture = NULL;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_image);
|
||||
#else
|
||||
glDeleteBuffers(3, m_PBO);
|
||||
m_PBO[0] = m_PBO[1] = m_PBO[2] = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ColorBufferToRDRAM::_prepareCopy(u32 _startAddress)
|
||||
{
|
||||
if (VI.width == 0 || frameBufferList().getCurrent() == NULL)
|
||||
return false;
|
||||
|
||||
OGLVideo & ogl = video();
|
||||
const u32 curFrame = ogl.getBuffersSwapCount();
|
||||
FrameBuffer * pBuffer = frameBufferList().findBuffer(_startAddress);
|
||||
|
||||
if (pBuffer == NULL || pBuffer->m_isOBScreen)
|
||||
return false;
|
||||
|
||||
if (m_frameCount == curFrame && pBuffer == m_pCurFrameBuffer && m_startAddress != _startAddress)
|
||||
return true;
|
||||
|
||||
const u32 numPixels = pBuffer->m_width * pBuffer->m_height;
|
||||
if (numPixels == 0)
|
||||
return false;
|
||||
|
||||
const u32 stride = pBuffer->m_width << pBuffer->m_size >> 1;
|
||||
const u32 height = cutHeight(_startAddress, pBuffer->m_height, stride);
|
||||
if (height == 0)
|
||||
return false;
|
||||
|
||||
m_pCurFrameBuffer = pBuffer;
|
||||
|
||||
if ((config.generalEmulation.hacks & hack_subscreen) != 0 && m_pCurFrameBuffer->m_width == VI.width && m_pCurFrameBuffer->m_height == VI.height) {
|
||||
copyWhiteToRDRAM(m_pCurFrameBuffer);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (config.video.multisampling != 0) {
|
||||
m_pCurFrameBuffer->resolveMultisampledTexture();
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_pCurFrameBuffer->m_resolveFBO);
|
||||
}
|
||||
else
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_pCurFrameBuffer->m_FBO);
|
||||
|
||||
if (m_pCurFrameBuffer->m_scaleX > 1.0f) {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
||||
u32 x0 = 0;
|
||||
u32 width, height;
|
||||
if (config.frameBufferEmulation.nativeResFactor == 0) {
|
||||
height = ogl.getHeight();
|
||||
const u32 screenWidth = ogl.getWidth();
|
||||
width = screenWidth;
|
||||
if (ogl.isAdjustScreen()) {
|
||||
width = static_cast<u32>(screenWidth*ogl.getAdjustScale());
|
||||
x0 = (screenWidth - width) / 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
width = m_pCurFrameBuffer->m_pTexture->realWidth;
|
||||
height = m_pCurFrameBuffer->m_pTexture->realHeight;
|
||||
}
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBlitFramebuffer(
|
||||
x0, 0, x0 + width, height,
|
||||
0, 0, VI.width, VI.height,
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
|
||||
frameBufferList().setCurrentDrawBuffer();
|
||||
}
|
||||
|
||||
m_frameCount = curFrame;
|
||||
m_startAddress = _startAddress;
|
||||
return true;
|
||||
}
|
||||
|
||||
u8 ColorBufferToRDRAM::_RGBAtoR8(u8 _c) {
|
||||
return _c;
|
||||
}
|
||||
|
||||
u16 ColorBufferToRDRAM::_RGBAtoRGBA16(u32 _c) {
|
||||
RGBA c;
|
||||
c.raw = _c;
|
||||
return ((c.r >> 3) << 11) | ((c.g >> 3) << 6) | ((c.b >> 3) << 1) | (c.a == 0 ? 0 : 1);
|
||||
}
|
||||
|
||||
u32 ColorBufferToRDRAM::_RGBAtoRGBA32(u32 _c) {
|
||||
RGBA c;
|
||||
c.raw = _c;
|
||||
return (c.r << 24) | (c.g << 16) | (c.b << 8) | c.a;
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
GLubyte* ColorBufferToRDRAM::getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, bool _sync)
|
||||
{
|
||||
GLenum colorFormat, colorType, colorFormatBytes;
|
||||
if (m_pCurFrameBuffer->m_size > G_IM_SIZ_8b) {
|
||||
colorFormat = fboFormats.colorFormat;
|
||||
colorType = fboFormats.colorType;
|
||||
colorFormatBytes = fboFormats.colorFormatBytes;
|
||||
}
|
||||
else {
|
||||
colorFormat = fboFormats.monochromeFormat;
|
||||
colorType = fboFormats.monochromeType;
|
||||
colorFormatBytes = fboFormats.monochromeFormatBytes;
|
||||
}
|
||||
|
||||
GLubyte* pixelData = (GLubyte*)malloc(m_pTexture->realWidth * m_pTexture->realHeight * colorFormatBytes);
|
||||
|
||||
if (!_sync) {
|
||||
void* ptr;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
||||
m_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
m_window->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &ptr);
|
||||
memcpy(pixelData, ptr, m_pTexture->realWidth * m_pTexture->realHeight * colorFormatBytes);
|
||||
m_window->unlock();
|
||||
|
||||
int widthBytes = _width*colorFormatBytes;
|
||||
int strideBytes = m_pTexture->realWidth*colorFormatBytes;
|
||||
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex)
|
||||
{
|
||||
memmove(pixelData + lnIndex*widthBytes, pixelData + ((lnIndex + _y0)*strideBytes), widthBytes);
|
||||
}
|
||||
}
|
||||
else {
|
||||
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, pixelData);
|
||||
}
|
||||
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::cleanUpPixels(GLubyte* pixelData)
|
||||
{
|
||||
free(pixelData);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
GLubyte* ColorBufferToRDRAM::getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, bool _sync)
|
||||
{
|
||||
GLenum colorFormat, colorType, colorFormatBytes;
|
||||
if (m_pCurFrameBuffer->m_size > G_IM_SIZ_8b) {
|
||||
colorFormat = fboFormats.colorFormat;
|
||||
colorType = fboFormats.colorType;
|
||||
colorFormatBytes = fboFormats.colorFormatBytes;
|
||||
}
|
||||
else {
|
||||
colorFormat = fboFormats.monochromeFormat;
|
||||
colorType = fboFormats.monochromeType;
|
||||
colorFormatBytes = fboFormats.monochromeFormatBytes;
|
||||
}
|
||||
|
||||
// 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 (!_sync) {
|
||||
m_curIndex ^= 1;
|
||||
const u32 nextIndex = m_curIndex ^ 1;
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[m_curIndex]);
|
||||
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, 0);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[nextIndex]);
|
||||
}
|
||||
else {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[2]);
|
||||
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, 0);
|
||||
}
|
||||
|
||||
GLubyte* pixelData = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, _width * _height * colorFormatBytes, GL_MAP_READ_BIT);
|
||||
if (pixelData == NULL)
|
||||
return NULL;
|
||||
|
||||
return pixelData;
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::cleanUpPixels(GLubyte* pixelData)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
#endif //ANDROID
|
||||
|
||||
|
||||
void ColorBufferToRDRAM::_copy(u32 _startAddress, u32 _endAddress, bool _sync)
|
||||
{
|
||||
const u32 stride = m_pCurFrameBuffer->m_width << m_pCurFrameBuffer->m_size >> 1;
|
||||
const u32 max_height = cutHeight(_startAddress, m_pCurFrameBuffer->m_height, stride);
|
||||
|
||||
u32 numPixels = (_endAddress - _startAddress) >> (m_pCurFrameBuffer->m_size - 1);
|
||||
if (numPixels / m_pCurFrameBuffer->m_width > max_height) {
|
||||
_endAddress = _startAddress + (max_height * stride);
|
||||
numPixels = (_endAddress - _startAddress) >> (m_pCurFrameBuffer->m_size - 1);
|
||||
}
|
||||
|
||||
const GLsizei width = m_pCurFrameBuffer->m_width;
|
||||
const GLint x0 = 0;
|
||||
const GLint y0 = max_height - (_endAddress - m_pCurFrameBuffer->m_startAddress) / stride;
|
||||
const GLint y1 = max_height - (_startAddress - m_pCurFrameBuffer->m_startAddress) / stride;
|
||||
const GLsizei height = std::min(max_height, 1u + y1 - y0);
|
||||
|
||||
GLubyte* pixelData = getPixels(x0, y0, width, height, _sync);
|
||||
|
||||
if (m_pCurFrameBuffer->m_size == G_IM_SIZ_32b) {
|
||||
u32 *ptr_src = (u32*)pixelData;
|
||||
u32 *ptr_dst = (u32*)(RDRAM + _startAddress);
|
||||
writeToRdram<u32, u32>(ptr_src, ptr_dst, &ColorBufferToRDRAM::_RGBAtoRGBA32, 0, 0, width, height, numPixels, _startAddress, m_pCurFrameBuffer->m_startAddress, m_pCurFrameBuffer->m_size);
|
||||
}
|
||||
else if (m_pCurFrameBuffer->m_size == G_IM_SIZ_16b) {
|
||||
u32 *ptr_src = (u32*)pixelData;
|
||||
u16 *ptr_dst = (u16*)(RDRAM + _startAddress);
|
||||
writeToRdram<u32, u16>(ptr_src, ptr_dst, &ColorBufferToRDRAM::_RGBAtoRGBA16, 0, 1, width, height, numPixels, _startAddress, m_pCurFrameBuffer->m_startAddress, m_pCurFrameBuffer->m_size);
|
||||
}
|
||||
else if (m_pCurFrameBuffer->m_size == G_IM_SIZ_8b) {
|
||||
u8 *ptr_src = (u8*)pixelData;
|
||||
u8 *ptr_dst = RDRAM + _startAddress;
|
||||
writeToRdram<u8, u8>(ptr_src, ptr_dst, &ColorBufferToRDRAM::_RGBAtoR8, 0, 3, width, height, numPixels, _startAddress, m_pCurFrameBuffer->m_startAddress, m_pCurFrameBuffer->m_size);
|
||||
}
|
||||
|
||||
m_pCurFrameBuffer->m_copiedToRdram = true;
|
||||
m_pCurFrameBuffer->copyRdram();
|
||||
m_pCurFrameBuffer->m_cleared = false;
|
||||
|
||||
cleanUpPixels(pixelData);
|
||||
|
||||
gDP.changed |= CHANGED_SCISSOR;
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::copyToRDRAM(u32 _address, bool _sync)
|
||||
{
|
||||
if (!_prepareCopy(_address))
|
||||
return;
|
||||
const u32 numBytes = (m_pCurFrameBuffer->m_width*m_pCurFrameBuffer->m_height) << m_pCurFrameBuffer->m_size >> 1;
|
||||
_copy(m_pCurFrameBuffer->m_startAddress, m_pCurFrameBuffer->m_startAddress + numBytes, _sync);
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::copyChunkToRDRAM(u32 _address)
|
||||
{
|
||||
if (!_prepareCopy(_address))
|
||||
return;
|
||||
_copy(_address, _address + 0x1000, true);
|
||||
}
|
||||
|
||||
#endif // GLES2
|
||||
|
||||
void copyWhiteToRDRAM(FrameBuffer * _pBuffer)
|
||||
{
|
||||
if (_pBuffer->m_size == G_IM_SIZ_32b) {
|
||||
u32 *ptr_dst = (u32*)(RDRAM + _pBuffer->m_startAddress);
|
||||
|
||||
for (u32 y = 0; y < VI.height; ++y) {
|
||||
for (u32 x = 0; x < VI.width; ++x)
|
||||
ptr_dst[x + y*VI.width] = 0xFFFFFFFF;
|
||||
}
|
||||
}
|
||||
else {
|
||||
u16 *ptr_dst = (u16*)(RDRAM + _pBuffer->m_startAddress);
|
||||
|
||||
for (u32 y = 0; y < VI.height; ++y) {
|
||||
for (u32 x = 0; x < VI.width; ++x) {
|
||||
ptr_dst[(x + y*VI.width) ^ 1] = 0xFFFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
_pBuffer->m_copiedToRdram = true;
|
||||
_pBuffer->copyRdram();
|
||||
|
||||
_pBuffer->m_cleared = false;
|
||||
}
|
73
src/BufferCopy/ColorBufferToRDRAM.h
Normal file
73
src/BufferCopy/ColorBufferToRDRAM.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#ifndef ColorBufferToRDRAM_H
|
||||
#define ColorBufferToRDRAM_H
|
||||
|
||||
#include <OpenGL.h>
|
||||
|
||||
#ifdef ANDROID
|
||||
#include "ui/GraphicBuffer.h"
|
||||
#include <android/native_window.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, EGLImageKHR image);
|
||||
typedef void (GL_APIENTRY* PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, EGLImageKHR image);
|
||||
|
||||
using namespace android;
|
||||
#endif
|
||||
|
||||
struct CachedTexture;
|
||||
struct FrameBuffer;
|
||||
|
||||
class ColorBufferToRDRAM
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
void copyToRDRAM(u32 _address, bool _sync);
|
||||
void copyChunkToRDRAM(u32 _address);
|
||||
|
||||
static ColorBufferToRDRAM & get();
|
||||
|
||||
private:
|
||||
ColorBufferToRDRAM();
|
||||
ColorBufferToRDRAM(const ColorBufferToRDRAM &);
|
||||
~ColorBufferToRDRAM();
|
||||
|
||||
union RGBA {
|
||||
struct {
|
||||
u8 r, g, b, a;
|
||||
};
|
||||
u32 raw;
|
||||
};
|
||||
|
||||
bool _prepareCopy(u32 _startAddress);
|
||||
|
||||
GLubyte* getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, bool _sync);
|
||||
void cleanUpPixels(GLubyte* pixelData);
|
||||
void _copy(u32 _startAddress, u32 _endAddress, bool _sync);
|
||||
|
||||
// Convert pixel from video memory to N64 buffer format.
|
||||
static u8 _RGBAtoR8(u8 _c);
|
||||
static u16 _RGBAtoRGBA16(u32 _c);
|
||||
static u32 _RGBAtoRGBA32(u32 _c);
|
||||
|
||||
GLuint m_FBO;
|
||||
CachedTexture * m_pTexture;
|
||||
FrameBuffer * m_pCurFrameBuffer;
|
||||
u32 m_curIndex;
|
||||
u32 m_frameCount;
|
||||
u32 m_startAddress;
|
||||
|
||||
GLuint m_PBO[3];
|
||||
|
||||
#ifdef ANDROID
|
||||
GraphicBuffer* m_window;
|
||||
EGLImageKHR m_image;
|
||||
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
|
||||
#endif
|
||||
};
|
||||
|
||||
void copyWhiteToRDRAM(FrameBuffer * _pBuffer);
|
||||
|
||||
#endif // ColorBufferToRDRAM
|
226
src/BufferCopy/DepthBufferToRDRAM.cpp
Normal file
226
src/BufferCopy/DepthBufferToRDRAM.cpp
Normal file
|
@ -0,0 +1,226 @@
|
|||
#include <assert.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include "DepthBufferToRDRAM.h"
|
||||
#include "WriteToRDRAM.h"
|
||||
|
||||
#include <FrameBuffer.h>
|
||||
#include <DepthBuffer.h>
|
||||
#include <Textures.h>
|
||||
#include <Config.h>
|
||||
#include <N64.h>
|
||||
#include <VI.h>
|
||||
|
||||
#ifndef GLES2
|
||||
|
||||
DepthBufferToRDRAM::DepthBufferToRDRAM()
|
||||
: m_FBO(0)
|
||||
, m_PBO(0)
|
||||
, m_frameCount(-1)
|
||||
, m_pColorTexture(nullptr)
|
||||
, m_pDepthTexture(nullptr)
|
||||
, m_pCurDepthBuffer(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
DepthBufferToRDRAM::~DepthBufferToRDRAM()
|
||||
{
|
||||
}
|
||||
|
||||
DepthBufferToRDRAM & DepthBufferToRDRAM::get()
|
||||
{
|
||||
static DepthBufferToRDRAM dbCopy;
|
||||
return dbCopy;
|
||||
}
|
||||
|
||||
void DepthBufferToRDRAM::init()
|
||||
{
|
||||
// generate a framebuffer
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
||||
|
||||
m_pColorTexture = textureCache().addFrameBufferTexture();
|
||||
m_pColorTexture->format = G_IM_FMT_I;
|
||||
m_pColorTexture->clampS = 1;
|
||||
m_pColorTexture->clampT = 1;
|
||||
m_pColorTexture->frameBufferTexture = CachedTexture::fbOneSample;
|
||||
m_pColorTexture->maskS = 0;
|
||||
m_pColorTexture->maskT = 0;
|
||||
m_pColorTexture->mirrorS = 0;
|
||||
m_pColorTexture->mirrorT = 0;
|
||||
m_pColorTexture->realWidth = 640;
|
||||
m_pColorTexture->realHeight = 580;
|
||||
m_pColorTexture->textureBytes = m_pColorTexture->realWidth * m_pColorTexture->realHeight;
|
||||
textureCache().addFrameBufferTextureSize(m_pColorTexture->textureBytes);
|
||||
|
||||
m_pDepthTexture = textureCache().addFrameBufferTexture();
|
||||
m_pDepthTexture->format = G_IM_FMT_I;
|
||||
m_pDepthTexture->clampS = 1;
|
||||
m_pDepthTexture->clampT = 1;
|
||||
m_pDepthTexture->frameBufferTexture = CachedTexture::fbOneSample;
|
||||
m_pDepthTexture->maskS = 0;
|
||||
m_pDepthTexture->maskT = 0;
|
||||
m_pDepthTexture->mirrorS = 0;
|
||||
m_pDepthTexture->mirrorT = 0;
|
||||
m_pDepthTexture->realWidth = 640;
|
||||
m_pDepthTexture->realHeight = 580;
|
||||
m_pDepthTexture->textureBytes = m_pDepthTexture->realWidth * m_pDepthTexture->realHeight * sizeof(float);
|
||||
textureCache().addFrameBufferTextureSize(m_pDepthTexture->textureBytes);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pColorTexture->glName);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fboFormats.monochromeInternalFormat, m_pColorTexture->realWidth, m_pColorTexture->realHeight, 0, fboFormats.monochromeFormat, fboFormats.monochromeType, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pDepthTexture->glName);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fboFormats.depthInternalFormat, m_pDepthTexture->realWidth, m_pDepthTexture->realHeight, 0, GL_DEPTH_COMPONENT, fboFormats.depthType, NULL);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_pColorTexture->glName, 0);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_pDepthTexture->glName, 0);
|
||||
// check if everything is OK
|
||||
assert(checkFBO());
|
||||
assert(!isGLError());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
// Generate and initialize Pixel Buffer Objects
|
||||
glGenBuffers(1, &m_PBO);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, m_pDepthTexture->realWidth * m_pDepthTexture->realHeight * sizeof(float), NULL, GL_DYNAMIC_READ);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
|
||||
void DepthBufferToRDRAM::destroy() {
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
glDeleteFramebuffers(1, &m_FBO);
|
||||
m_FBO = 0;
|
||||
if (m_pColorTexture != NULL) {
|
||||
textureCache().removeFrameBufferTexture(m_pColorTexture);
|
||||
m_pColorTexture = NULL;
|
||||
}
|
||||
if (m_pDepthTexture != NULL) {
|
||||
textureCache().removeFrameBufferTexture(m_pDepthTexture);
|
||||
m_pDepthTexture = NULL;
|
||||
}
|
||||
if (m_PBO != 0) {
|
||||
glDeleteBuffers(1, &m_PBO);
|
||||
m_PBO = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool DepthBufferToRDRAM::_prepareCopy(u32 _address, bool _copyChunk)
|
||||
{
|
||||
const u32 curFrame = video().getBuffersSwapCount();
|
||||
if (_copyChunk && m_frameCount == curFrame)
|
||||
return true;
|
||||
|
||||
const u32 numPixels = VI.width * VI.height;
|
||||
if (numPixels == 0) // Incorrect buffer size. Don't copy
|
||||
return false;
|
||||
FrameBuffer *pBuffer = frameBufferList().findBuffer(_address);
|
||||
if (pBuffer == NULL || pBuffer->isAuxiliary() || pBuffer->m_pDepthBuffer == NULL || !pBuffer->m_pDepthBuffer->m_cleared)
|
||||
return false;
|
||||
|
||||
m_pCurDepthBuffer = pBuffer->m_pDepthBuffer;
|
||||
const u32 address = m_pCurDepthBuffer->m_address;
|
||||
if (address + numPixels * 2 > RDRAMSize)
|
||||
return false;
|
||||
|
||||
const u32 height = cutHeight(address, std::min(VI.height, m_pCurDepthBuffer->m_lry), pBuffer->m_width * 2);
|
||||
if (height == 0)
|
||||
return false;
|
||||
|
||||
if (config.video.multisampling == 0)
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_FBO);
|
||||
else {
|
||||
m_pCurDepthBuffer->resolveDepthBufferTexture(pBuffer);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, pBuffer->m_resolveFBO);
|
||||
}
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBlitFramebuffer(
|
||||
0, 0, pBuffer->m_pTexture->realWidth, pBuffer->m_pTexture->realHeight,
|
||||
0, 0, pBuffer->m_width, pBuffer->m_height,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST
|
||||
);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
frameBufferList().setCurrentDrawBuffer();
|
||||
m_frameCount = curFrame;
|
||||
return true;
|
||||
}
|
||||
|
||||
u16 DepthBufferToRDRAM::_FloatToUInt16(f32 _z)
|
||||
{
|
||||
static const u16 * const zLUT = depthBufferList().getZLUT();
|
||||
u32 idx = 0x3FFFF;
|
||||
if (_z < 1.0f) {
|
||||
_z *= 262144.0f;
|
||||
idx = std::min(0x3FFFFU, u32(floorf(_z + 0.5f)));
|
||||
}
|
||||
return zLUT[idx];
|
||||
}
|
||||
|
||||
bool DepthBufferToRDRAM::_copy(u32 _startAddress, u32 _endAddress)
|
||||
{
|
||||
const u32 stride = m_pCurDepthBuffer->m_width << 1;
|
||||
const u32 max_height = cutHeight(_startAddress, std::min(VI.height, m_pCurDepthBuffer->m_lry), stride);
|
||||
|
||||
u32 numPixels = (_endAddress - _startAddress) >> 1;
|
||||
if (numPixels / m_pCurDepthBuffer->m_width > max_height) {
|
||||
_endAddress = _startAddress + (max_height * stride);
|
||||
numPixels = (_endAddress - _startAddress) >> 1;
|
||||
}
|
||||
|
||||
const GLsizei width = m_pCurDepthBuffer->m_width;
|
||||
const GLint x0 = 0;
|
||||
const GLint y0 = max_height - (_endAddress - m_pCurDepthBuffer->m_address) / stride;
|
||||
const GLint y1 = max_height - (_startAddress - m_pCurDepthBuffer->m_address) / stride;
|
||||
const GLsizei height = std::min(max_height, 1u + y1 - y0);
|
||||
|
||||
PBOBinder binder(GL_PIXEL_PACK_BUFFER, m_PBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_FBO);
|
||||
glReadPixels(x0, y0, width, height, fboFormats.depthFormat, fboFormats.depthType, 0);
|
||||
|
||||
GLubyte* pixelData = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, width * height * fboFormats.depthFormatBytes, GL_MAP_READ_BIT);
|
||||
if (pixelData == NULL)
|
||||
return false;
|
||||
|
||||
f32 * ptr_src = (f32*)pixelData;
|
||||
u16 *ptr_dst = (u16*)(RDRAM + _startAddress);
|
||||
|
||||
std::vector<f32> srcBuf(width * height);
|
||||
memcpy(srcBuf.data(), ptr_src, width * height * sizeof(f32));
|
||||
writeToRdram<f32, u16>(srcBuf.data(), ptr_dst, &DepthBufferToRDRAM::_FloatToUInt16, 2.0f, 1, width, height, numPixels, _startAddress, m_pCurDepthBuffer->m_address, G_IM_SIZ_16b);
|
||||
|
||||
m_pCurDepthBuffer->m_cleared = false;
|
||||
FrameBuffer * pBuffer = frameBufferList().findBuffer(m_pCurDepthBuffer->m_address);
|
||||
if (pBuffer != NULL)
|
||||
pBuffer->m_cleared = false;
|
||||
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
gDP.changed |= CHANGED_SCISSOR;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DepthBufferToRDRAM::copyToRDRAM(u32 _address)
|
||||
{
|
||||
if (!_prepareCopy(_address, false))
|
||||
return false;
|
||||
|
||||
const u32 endAddress = m_pCurDepthBuffer->m_address + (std::min(VI.height, m_pCurDepthBuffer->m_lry) * m_pCurDepthBuffer->m_width * 2);
|
||||
return _copy(m_pCurDepthBuffer->m_address, endAddress);
|
||||
}
|
||||
|
||||
bool DepthBufferToRDRAM::copyChunkToRDRAM(u32 _address)
|
||||
{
|
||||
if (!_prepareCopy(_address, true))
|
||||
return false;
|
||||
|
||||
const u32 endAddress = _address + 0x1000;
|
||||
return _copy(_address, endAddress);
|
||||
}
|
||||
#endif // GLES2
|
38
src/BufferCopy/DepthBufferToRDRAM.h
Normal file
38
src/BufferCopy/DepthBufferToRDRAM.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
#ifndef DepthBufferToRDRAM_H
|
||||
#define DepthBufferToRDRAM_H
|
||||
|
||||
#include <OpenGL.h>
|
||||
|
||||
struct CachedTexture;
|
||||
struct DepthBuffer;
|
||||
|
||||
class DepthBufferToRDRAM
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
bool copyToRDRAM(u32 _address);
|
||||
bool copyChunkToRDRAM(u32 _address);
|
||||
|
||||
static DepthBufferToRDRAM & get();
|
||||
|
||||
private:
|
||||
DepthBufferToRDRAM();
|
||||
~DepthBufferToRDRAM();
|
||||
|
||||
bool _prepareCopy(u32 _address, bool _copyChunk);
|
||||
bool _copy(u32 _startAddress, u32 _endAddress);
|
||||
|
||||
// Convert pixel from video memory to N64 depth buffer format.
|
||||
static u16 _FloatToUInt16(f32 _z);
|
||||
|
||||
GLuint m_FBO;
|
||||
GLuint m_PBO;
|
||||
u32 m_frameCount;
|
||||
CachedTexture * m_pColorTexture;
|
||||
CachedTexture * m_pDepthTexture;
|
||||
DepthBuffer * m_pCurDepthBuffer;
|
||||
};
|
||||
|
||||
#endif // DepthBufferToRDRAM_H
|
281
src/BufferCopy/RDRAMtoColorBuffer.cpp
Normal file
281
src/BufferCopy/RDRAMtoColorBuffer.cpp
Normal file
|
@ -0,0 +1,281 @@
|
|||
#include "RDRAMtoColorBuffer.h"
|
||||
|
||||
#include <FrameBufferInfo.h>
|
||||
#include <GLSLCombiner.h>
|
||||
#include <FrameBuffer.h>
|
||||
#include <Combiner.h>
|
||||
#include <Textures.h>
|
||||
#include <Config.h>
|
||||
#include <N64.h>
|
||||
#include <VI.h>
|
||||
|
||||
RDRAMtoColorBuffer::RDRAMtoColorBuffer()
|
||||
: m_pCurBuffer(nullptr)
|
||||
, m_pTexture(nullptr)
|
||||
, m_PBO(0) {
|
||||
}
|
||||
|
||||
RDRAMtoColorBuffer & RDRAMtoColorBuffer::get()
|
||||
{
|
||||
static RDRAMtoColorBuffer toCB;
|
||||
return toCB;
|
||||
}
|
||||
|
||||
void RDRAMtoColorBuffer::init()
|
||||
{
|
||||
m_pTexture = textureCache().addFrameBufferTexture();
|
||||
m_pTexture->format = G_IM_FMT_RGBA;
|
||||
m_pTexture->clampS = 1;
|
||||
m_pTexture->clampT = 1;
|
||||
m_pTexture->frameBufferTexture = CachedTexture::fbOneSample;
|
||||
m_pTexture->maskS = 0;
|
||||
m_pTexture->maskT = 0;
|
||||
m_pTexture->mirrorS = 0;
|
||||
m_pTexture->mirrorT = 0;
|
||||
m_pTexture->realWidth = 640;
|
||||
m_pTexture->realHeight = 580;
|
||||
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
||||
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
||||
glBindTexture( GL_TEXTURE_2D, m_pTexture->glName );
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, fboFormats.colorInternalFormat, m_pTexture->realWidth, m_pTexture->realHeight, 0, fboFormats.colorFormat, fboFormats.colorType, 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);
|
||||
|
||||
// Generate Pixel Buffer Object. Initialize it later
|
||||
#ifndef GLES2
|
||||
glGenBuffers(1, &m_PBO);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RDRAMtoColorBuffer::destroy()
|
||||
{
|
||||
if (m_pTexture != NULL) {
|
||||
textureCache().removeFrameBufferTexture(m_pTexture);
|
||||
m_pTexture = NULL;
|
||||
}
|
||||
#ifndef GLES2
|
||||
if (m_PBO != 0) {
|
||||
glDeleteBuffers(1, &m_PBO);
|
||||
m_PBO = 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RDRAMtoColorBuffer::addAddress(u32 _address, u32 _size)
|
||||
{
|
||||
if (m_pCurBuffer == nullptr) {
|
||||
m_pCurBuffer = frameBufferList().findBuffer(_address);
|
||||
if (m_pCurBuffer == nullptr)
|
||||
return;
|
||||
}
|
||||
|
||||
const u32 pixelSize = 1 << m_pCurBuffer->m_size >> 1;
|
||||
if (_size != pixelSize && (_address%pixelSize) > 0)
|
||||
return;
|
||||
m_vecAddress.push_back(_address);
|
||||
gDP.colorImage.changed = TRUE;
|
||||
}
|
||||
|
||||
// Write the whole buffer
|
||||
template <typename TSrc>
|
||||
bool _copyBufferFromRdram(u32 _address, u32* _dst, u32(*converter)(TSrc _c, bool _bCFB), u32 _xor, u32 _x0, u32 _y0, u32 _width, u32 _height, bool _bCFB)
|
||||
{
|
||||
TSrc * src = reinterpret_cast<TSrc*>(RDRAM + _address);
|
||||
const u32 bound = (RDRAMSize + 1 - _address) >> (sizeof(TSrc) / 2);
|
||||
TSrc col;
|
||||
u32 idx;
|
||||
u32 summ = 0;
|
||||
u32 dsty = 0;
|
||||
const u32 y1 = _y0 + _height;
|
||||
for (u32 y = _y0; y < y1; ++y) {
|
||||
for (u32 x = _x0; x < _width; ++x) {
|
||||
idx = (x + (_height - y - 1)*_width) ^ _xor;
|
||||
if (idx >= bound)
|
||||
break;
|
||||
col = src[idx];
|
||||
summ += col;
|
||||
_dst[x + dsty*_width] = converter(col, _bCFB);
|
||||
}
|
||||
++dsty;
|
||||
}
|
||||
|
||||
return summ != 0;
|
||||
}
|
||||
|
||||
// Write only pixels provided with FBWrite
|
||||
template <typename TSrc>
|
||||
bool _copyPixelsFromRdram(u32 _address, const std::vector<u32> & _vecAddress, u32* _dst, u32(*converter)(TSrc _c, bool _bCFB), u32 _xor, u32 _width, u32 _height, bool _bCFB)
|
||||
{
|
||||
memset(_dst, 0, _width*_height*sizeof(u32));
|
||||
TSrc * src = reinterpret_cast<TSrc*>(RDRAM + _address);
|
||||
const u32 szPixel = sizeof(TSrc);
|
||||
const size_t numPixels = _vecAddress.size();
|
||||
TSrc col;
|
||||
u32 summ = 0;
|
||||
u32 idx, w, h;
|
||||
for (size_t i = 0; i < numPixels; ++i) {
|
||||
if (_vecAddress[i] < _address)
|
||||
return false;
|
||||
idx = (_vecAddress[i] - _address) / szPixel;
|
||||
w = idx % _width;
|
||||
h = idx / _width;
|
||||
if (h > _height)
|
||||
return false;
|
||||
col = src[idx];
|
||||
summ += col;
|
||||
_dst[(w + (_height - h)*_width) ^ _xor] = converter(col, _bCFB);
|
||||
}
|
||||
|
||||
return summ != 0;
|
||||
}
|
||||
|
||||
static
|
||||
u32 RGBA16ToABGR32(u16 col, bool _bCFB)
|
||||
{
|
||||
u32 r, g, b, a;
|
||||
r = ((col >> 11) & 31) << 3;
|
||||
g = ((col >> 6) & 31) << 3;
|
||||
b = ((col >> 1) & 31) << 3;
|
||||
if (_bCFB)
|
||||
a = 0xFF;
|
||||
else
|
||||
a = (col & 1) > 0 && (r | g | b) > 0 ? 0xFF : 0U;
|
||||
return ((a << 24) | (b << 16) | (g << 8) | r);
|
||||
}
|
||||
|
||||
static
|
||||
u32 RGBA32ToABGR32(u32 col, bool _bCFB)
|
||||
{
|
||||
u32 r, g, b, a;
|
||||
r = (col >> 24) & 0xff;
|
||||
g = (col >> 16) & 0xff;
|
||||
b = (col >> 8) & 0xff;
|
||||
if (_bCFB)
|
||||
a = 0xFF;
|
||||
else
|
||||
a = (r | g | b) > 0 ? col & 0xFF : 0U;
|
||||
return ((a << 24) | (b << 16) | (g << 8) | r);
|
||||
}
|
||||
|
||||
void RDRAMtoColorBuffer::copyFromRDRAM(u32 _address, bool _bCFB)
|
||||
{
|
||||
Cleaner cleaner(this);
|
||||
|
||||
if (m_pCurBuffer == nullptr) {
|
||||
if (_bCFB || (config.frameBufferEmulation.copyFromRDRAM != 0 && !FBInfo::fbInfo.isSupported()))
|
||||
m_pCurBuffer = frameBufferList().findBuffer(_address);
|
||||
} else if (m_vecAddress.empty())
|
||||
return;
|
||||
|
||||
if (m_pCurBuffer == nullptr || m_pCurBuffer->m_size < G_IM_SIZ_16b)
|
||||
return;
|
||||
|
||||
if (m_pCurBuffer->m_startAddress == _address && gDP.colorImage.changed != 0)
|
||||
return;
|
||||
|
||||
const u32 address = m_pCurBuffer->m_startAddress;
|
||||
|
||||
const u32 height = cutHeight(address, m_pCurBuffer->m_startAddress == _address ? VI.real_height : m_pCurBuffer->m_height, m_pCurBuffer->m_width << m_pCurBuffer->m_size >> 1);
|
||||
if (height == 0)
|
||||
return;
|
||||
|
||||
const u32 width = m_pCurBuffer->m_width;
|
||||
|
||||
const u32 x0 = 0;
|
||||
const u32 y0 = 0;
|
||||
const u32 y1 = y0 + height;
|
||||
|
||||
const bool bUseAlpha = !_bCFB && m_pCurBuffer->m_changed;
|
||||
|
||||
m_pTexture->width = width;
|
||||
m_pTexture->height = height;
|
||||
const u32 dataSize = width*height * 4;
|
||||
#ifndef GLES2
|
||||
PBOBinder binder(GL_PIXEL_UNPACK_BUFFER, m_PBO);
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, dataSize, NULL, GL_DYNAMIC_DRAW);
|
||||
GLubyte* ptr = (GLubyte*)glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, dataSize, GL_MAP_WRITE_BIT);
|
||||
#else
|
||||
GLubyte* ptr = (GLubyte*)malloc(dataSize);
|
||||
PBOBinder binder(ptr);
|
||||
#endif // GLES2
|
||||
if (ptr == NULL)
|
||||
return;
|
||||
|
||||
u32 * dst = (u32*)ptr;
|
||||
bool bCopy;
|
||||
if (m_vecAddress.empty()) {
|
||||
if (m_pCurBuffer->m_size == G_IM_SIZ_16b)
|
||||
bCopy = _copyBufferFromRdram<u16>(address, dst, RGBA16ToABGR32, 1, x0, y0, width, height, _bCFB);
|
||||
else
|
||||
bCopy = _copyBufferFromRdram<u32>(address, dst, RGBA32ToABGR32, 0, x0, y0, width, height, _bCFB);
|
||||
}
|
||||
else {
|
||||
if (m_pCurBuffer->m_size == G_IM_SIZ_16b)
|
||||
bCopy = _copyPixelsFromRdram<u16>(address, m_vecAddress, dst, RGBA16ToABGR32, 1, width, height, _bCFB);
|
||||
else
|
||||
bCopy = _copyPixelsFromRdram<u32>(address, m_vecAddress, dst, RGBA32ToABGR32, 0, width, height, _bCFB);
|
||||
}
|
||||
|
||||
if (bUseAlpha) {
|
||||
u32 totalBytes = (width * height) << m_pCurBuffer->m_size >> 1;
|
||||
if (address + totalBytes > RDRAMSize + 1)
|
||||
totalBytes = RDRAMSize + 1 - address;
|
||||
memset(RDRAM + address, 0, totalBytes);
|
||||
}
|
||||
|
||||
#ifndef GLES2
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); // release the mapped buffer
|
||||
#endif
|
||||
if (!bCopy)
|
||||
return;
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
||||
#ifndef GLES2
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
#else
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, ptr);
|
||||
#endif
|
||||
|
||||
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;
|
||||
textureCache().activateTexture(0, m_pTexture);
|
||||
|
||||
gDPTile tile0;
|
||||
tile0.fuls = tile0.fult = 0.0f;
|
||||
gDPTile * pTile0 = gSP.textureTile[0];
|
||||
gSP.textureTile[0] = &tile0;
|
||||
|
||||
const u32 cycleType = gDP.otherMode.cycleType;
|
||||
gDP.otherMode.cycleType = G_CYC_1CYCLE;
|
||||
CombinerInfo::get().setCombine(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
|
||||
currentCombiner()->disableBlending();
|
||||
gDP.otherMode.cycleType = cycleType;
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
currentCombiner()->updateFrameBufferInfo();
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurBuffer->m_FBO);
|
||||
OGLRender::TexturedRectParams params((float)x0, (float)y0, (float)width, (float)height,
|
||||
0.0f, 0.0f, width - 1.0f, height - 1.0f, 1.0f, 1.0f,
|
||||
false, true, false, m_pCurBuffer);
|
||||
video().getRender().drawTexturedRect(params);
|
||||
frameBufferList().setCurrentDrawBuffer();
|
||||
|
||||
gSP.textureTile[0] = pTile0;
|
||||
|
||||
gDP.changed |= CHANGED_RENDERMODE | CHANGED_COMBINE | CHANGED_SCISSOR;
|
||||
}
|
||||
|
||||
void RDRAMtoColorBuffer::reset()
|
||||
{
|
||||
m_pCurBuffer = nullptr;
|
||||
m_vecAddress.clear();
|
||||
}
|
45
src/BufferCopy/RDRAMtoColorBuffer.h
Normal file
45
src/BufferCopy/RDRAMtoColorBuffer.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef RDRAMtoColorBuffer_H
|
||||
#define RDRAMtoColorBuffer_H
|
||||
|
||||
#include <vector>
|
||||
#include <OpenGL.h>
|
||||
|
||||
struct CachedTexture;
|
||||
struct FrameBuffer;
|
||||
|
||||
class RDRAMtoColorBuffer
|
||||
{
|
||||
public:
|
||||
void init();
|
||||
void destroy();
|
||||
|
||||
void addAddress(u32 _address, u32 _size);
|
||||
void copyFromRDRAM(u32 _address, bool _bCFB);
|
||||
|
||||
static RDRAMtoColorBuffer & get();
|
||||
|
||||
private:
|
||||
RDRAMtoColorBuffer();
|
||||
RDRAMtoColorBuffer(const RDRAMtoColorBuffer &);
|
||||
|
||||
void reset();
|
||||
|
||||
class Cleaner
|
||||
{
|
||||
public:
|
||||
Cleaner(RDRAMtoColorBuffer * _p) : m_p(_p) {}
|
||||
~Cleaner()
|
||||
{
|
||||
m_p->reset();
|
||||
}
|
||||
private:
|
||||
RDRAMtoColorBuffer * m_p;
|
||||
};
|
||||
|
||||
FrameBuffer * m_pCurBuffer;
|
||||
CachedTexture * m_pTexture;
|
||||
GLuint m_PBO;
|
||||
std::vector<u32> m_vecAddress;
|
||||
};
|
||||
|
||||
#endif // RDRAMtoColorBuffer_H
|
43
src/BufferCopy/WriteToRDRAM.h
Normal file
43
src/BufferCopy/WriteToRDRAM.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef WriteToRDRAM_H
|
||||
#define WriteToRDRAM_H
|
||||
|
||||
|
||||
#include "../Types.h"
|
||||
|
||||
template <typename TSrc, typename TDst>
|
||||
void writeToRdram(TSrc* _src, TDst* _dst, TDst(*converter)(TSrc _c), TSrc _testValue, u32 _xor, u32 _width, u32 _height, u32 _numPixels, u32 _startAddress, u32 _bufferAddress, u32 _bufferSize)
|
||||
{
|
||||
u32 chunkStart = ((_startAddress - _bufferAddress) >> (_bufferSize - 1)) % _width;
|
||||
if (chunkStart % 2 != 0) {
|
||||
--chunkStart;
|
||||
--_dst;
|
||||
++_numPixels;
|
||||
}
|
||||
|
||||
u32 numStored = 0;
|
||||
u32 y = 0;
|
||||
TSrc c;
|
||||
if (chunkStart > 0) {
|
||||
for (u32 x = chunkStart; x < _width; ++x) {
|
||||
c = _src[x + (_height - 1)*_width];
|
||||
if (c != _testValue)
|
||||
_dst[numStored ^ _xor] = converter(c);
|
||||
++numStored;
|
||||
}
|
||||
++y;
|
||||
_dst += numStored;
|
||||
}
|
||||
|
||||
u32 dsty = 0;
|
||||
for (; y < _height; ++y) {
|
||||
for (u32 x = 0; x < _width && numStored < _numPixels; ++x) {
|
||||
c = _src[x + (_height - y - 1)*_width];
|
||||
if (c != _testValue)
|
||||
_dst[(x + dsty*_width) ^ _xor] = converter(c);
|
||||
++numStored;
|
||||
}
|
||||
++dsty;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // WriteToRDRAM_H
|
|
@ -8,11 +8,13 @@ project( GLideN64 )
|
|||
|
||||
set(GLideN64_SOURCES
|
||||
3DMath.cpp
|
||||
BufferCopy/ColorBufferToRDRAM.cpp
|
||||
Combiner.cpp
|
||||
CommonPluginAPI.cpp
|
||||
Config.cpp
|
||||
CRC.cpp
|
||||
DepthBuffer.cpp
|
||||
BufferCopy/DepthBufferToRDRAM.cpp
|
||||
F3D.cpp
|
||||
F3DDKR.cpp
|
||||
F3DEX.cpp
|
||||
|
@ -35,6 +37,7 @@ set(GLideN64_SOURCES
|
|||
N64.cpp
|
||||
OpenGL.cpp
|
||||
RDP.cpp
|
||||
BufferCopy/RDRAMtoColorBuffer.cpp
|
||||
RSP.cpp
|
||||
S2DEX2.cpp
|
||||
S2DEX.cpp
|
||||
|
@ -75,7 +78,7 @@ if(MUPENPLUSAPI)
|
|||
-DMUPENPLUSAPI
|
||||
-DTXFILTER_LIB
|
||||
)
|
||||
include_directories( inc )
|
||||
include_directories( . inc )
|
||||
set(GLideN64_SOURCES_UNIX
|
||||
MupenPlusPluginAPI.cpp
|
||||
mupenplus/Config_mupenplus.cpp
|
||||
|
|
1010
src/FrameBuffer.cpp
1010
src/FrameBuffer.cpp
File diff suppressed because it is too large
Load Diff
|
@ -130,6 +130,8 @@ FrameBufferList & frameBufferList()
|
|||
return FrameBufferList::get();
|
||||
}
|
||||
|
||||
u32 cutHeight(u32 _address, u32 _height, u32 _stride);
|
||||
|
||||
void FrameBuffer_Init();
|
||||
void FrameBuffer_Destroy();
|
||||
void FrameBuffer_CopyToRDRAM( u32 _address , bool _sync );
|
||||
|
|
Loading…
Reference in New Issue
Block a user