1
0
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:
Sergey Lipskiy 2016-05-28 21:37:20 +06:00
parent dca2c29edf
commit 2834fa1780
12 changed files with 1143 additions and 992 deletions

View File

@ -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" />

View File

@ -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>

View 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;
}

View 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

View 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

View 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

View 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();
}

View 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

View 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

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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 );