1
0
mirror of https://github.com/blawar/GLideN64.git synced 2024-07-04 10:03:36 +00:00

Added floating point support to ColorBufferReader

I consolidated a lot of code that was the same between implementations in
the process, so now the code is common.
This commit is contained in:
Francisco Zurita 2017-04-16 00:11:01 -04:00 committed by Sergey Lipskiy
parent 4a8ae7e1cf
commit 2e1baf433c
14 changed files with 174 additions and 109 deletions

View File

@ -290,6 +290,7 @@
<ClCompile Include="..\..\src\GBI.cpp" />
<ClCompile Include="..\..\src\gDP.cpp" />
<ClCompile Include="..\..\src\GLideN64.cpp" />
<ClCompile Include="..\..\src\Graphics\ColorBufferReader.cpp" />
<ClCompile Include="..\..\src\Graphics\CombinerProgram.cpp" />
<ClCompile Include="..\..\src\Graphics\Context.cpp" />
<ClCompile Include="..\..\src\Graphics\ObjectHandle.cpp" />

View File

@ -296,6 +296,9 @@
<ClCompile Include="..\..\src\Graphics\OpenGLContext\opengl_Utils.cpp">
<Filter>Source Files\Graphics\OpenGL</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\ColorBufferReader.cpp">
<Filter>Source Files\Graphics</Filter>
</ClCompile>
<ClCompile Include="..\..\src\Graphics\CombinerProgram.cpp">
<Filter>Source Files\Graphics</Filter>
</ClCompile>

View File

@ -65,6 +65,7 @@ set(GLideN64_SOURCES
DepthBufferRender/DepthBufferRender.cpp
common/CommonAPIImpl_common.cpp
Graphics/Context.cpp
Graphics/ColorBufferReader.cpp
Graphics/CombinerProgram.cpp
Graphics/ObjectHandle.cpp
Graphics/OpenGLContext/GLFunctions.cpp

View File

@ -0,0 +1,89 @@
#include "ColorBufferReader.h"
#include "FramebufferTextureFormats.h"
#include "Context.h"
#include "Parameters.h"
#include <algorithm>
#include <cstring>
namespace graphics {
ColorBufferReader::ColorBufferReader(CachedTexture * _pTexture)
: m_pTexture(_pTexture)
{
m_pixelData.resize(m_pTexture->textureBytes);
m_tempPixelData.resize(m_pTexture->textureBytes);
}
const u8* ColorBufferReader::_convertFloatTextureBuffer(const u8* _gpuData, u32 _width, u32 _height,
u32 _heightOffset, u32 _stride)
{
std::copy_n(_gpuData, m_tempPixelData.size(), m_tempPixelData.data());
u8* pixelDataAlloc = m_pixelData.data();
float* pixelData = reinterpret_cast<float*>(m_tempPixelData.data());
const u32 colorsPerPixel = 4;
const u32 widthPixels = _width * colorsPerPixel;
const u32 stridePixels = _stride * colorsPerPixel;
for (u32 index = 0; index < _height; ++index) {
for (u32 widthIndex = 0; widthIndex < widthPixels; ++widthIndex) {
u8& dest = *(pixelDataAlloc + index*widthPixels + widthIndex);
float& src = *(pixelData + (index+_heightOffset)*stridePixels + widthIndex);
dest = static_cast<u8>(src*255.0);
}
}
return pixelDataAlloc;
}
const u8* ColorBufferReader::_convertIntegerTextureBuffer(const u8* _gpuData, u32 _width, u32 _height,
u32 _heightOffset, u32 _stride)
{
const u32 colorsPerPixel = 4;
const u32 widthBytes = _width * colorsPerPixel;
const u32 strideBytes = _stride * colorsPerPixel;
u8* pixelDataAlloc = m_pixelData.data();
for (u32 lnIndex = 0; lnIndex < _height; ++lnIndex) {
memcpy(pixelDataAlloc + lnIndex*widthBytes, _gpuData + ((lnIndex+_heightOffset)*strideBytes), widthBytes);
}
return pixelDataAlloc;
}
const u8 * ColorBufferReader::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync)
{
const FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats();
ReadColorBufferParams params;
params.x0 = _x0;
params.y0 = _y0;
params.width = _width;
params.height = _height;
params.sync = _sync;
if (_size > G_IM_SIZ_8b) {
params.colorFormat = fbTexFormat.colorFormat;
params.colorType = fbTexFormat.colorType;
params.colorFormatBytes = fbTexFormat.colorFormatBytes;
} else {
params.colorFormat = fbTexFormat.monochromeFormat;
params.colorType = fbTexFormat.monochromeType;
params.colorFormatBytes = fbTexFormat.monochromeFormatBytes;
}
u32 heightOffset = 0;
u32 stride = 0;
const u8* pixelData = _readPixels(params, heightOffset, stride);
if (pixelData == nullptr)
return nullptr;
if(params.colorType == datatype::FLOAT) {
return _convertFloatTextureBuffer(pixelData, params.width, params.height, heightOffset, stride);
} else {
return _convertIntegerTextureBuffer(pixelData, params.width, params.height, heightOffset, stride);
}
}
}

View File

@ -8,18 +8,32 @@ namespace graphics {
class ColorBufferReader
{
public:
ColorBufferReader(CachedTexture * _pTexture)
: m_pTexture(_pTexture) {
m_pixelData.resize(m_pTexture->textureBytes);
}
virtual ~ColorBufferReader() {}
ColorBufferReader(CachedTexture * _pTexture);
virtual ~ColorBufferReader() = default;
virtual u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) = 0;
virtual const u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync);
virtual void cleanUp() = 0;
protected:
struct ReadColorBufferParams {
s32 x0;
s32 y0;
u32 width;
u32 height;
bool sync;
ColorFormatParam colorFormat;
DatatypeParam colorType;
u32 colorFormatBytes;
};
CachedTexture * m_pTexture;
std::vector<u8> m_pixelData;
std::vector<u8> m_tempPixelData;
private:
const u8* _convertFloatTextureBuffer(const u8* _gpuData, u32 _width, u32 _height, u32 _heightOffset, u32 _stride);
const u8* _convertIntegerTextureBuffer(const u8* _gpuData, u32 _width, u32 _height,u32 _heightOffset, u32 _stride);
virtual const u8 * _readPixels(const ReadColorBufferParams& _params, u32& _heightOffset, u32& _stride) = 0;
};
}

View File

@ -41,25 +41,16 @@ void ColorBufferReaderWithBufferStorage::_destroyBuffers()
m_PBO[index] = 0;
}
u8 * ColorBufferReaderWithBufferStorage::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync)
const u8 * ColorBufferReaderWithBufferStorage::_readPixels(const ReadColorBufferParams& _params, u32& _heightOffset,
u32& _stride)
{
const FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats();
GLenum colorFormat, colorType, colorFormatBytes;
if (_size > G_IM_SIZ_8b) {
colorFormat = GLenum(fbTexFormat.colorFormat);
colorType = GLenum(fbTexFormat.colorType);
colorFormatBytes = GLenum(fbTexFormat.colorFormatBytes);
}
else {
colorFormat = GLenum(fbTexFormat.monochromeFormat);
colorType = GLenum(fbTexFormat.monochromeType);
colorFormatBytes = GLenum(fbTexFormat.monochromeFormatBytes);
}
GLenum format = GLenum(_params.colorFormat);
GLenum type = GLenum(_params.colorType);
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex]));
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
if (!_sync) {
if (!_params.sync) {
//Setup a fence sync object so that we know when glReadPixels completes
m_fence[m_curIndex] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
m_curIndex = (m_curIndex + 1) % _numPBO;
@ -72,19 +63,10 @@ u8 * ColorBufferReaderWithBufferStorage::readPixels(s32 _x0, s32 _y0, u32 _width
glFinish();
}
GLubyte* pixelData = reinterpret_cast<GLubyte*>(m_PBOData[m_curIndex]);
if (pixelData == nullptr)
return nullptr;
_heightOffset = 0;
_stride = m_pTexture->realWidth;
int widthBytes = _width * colorFormatBytes;
int strideBytes = m_pTexture->realWidth * colorFormatBytes;
GLubyte* pixelDataAlloc = m_pixelData.data();
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
memcpy(pixelDataAlloc + lnIndex*widthBytes, pixelData + (lnIndex*strideBytes), widthBytes);
}
return pixelDataAlloc;
return reinterpret_cast<u8*>(m_PBOData[m_curIndex]);
}
void ColorBufferReaderWithBufferStorage::cleanUp()

View File

@ -2,6 +2,7 @@
#include <Graphics/ColorBufferReader.h>
#include "opengl_CachedFunctions.h"
#include <Graphics/Parameter.h>
namespace opengl {
@ -13,7 +14,8 @@ namespace opengl {
CachedBindBuffer * _bindBuffer);
virtual ~ColorBufferReaderWithBufferStorage();
u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) override;
const u8 * _readPixels(const ReadColorBufferParams& _params, u32& _heightOffset, u32& _stride) override;
void cleanUp() override;
private:

View File

@ -11,6 +11,7 @@ ColorBufferReaderWithEGLImage::ColorBufferReaderWithEGLImage(CachedTexture *_pTe
: graphics::ColorBufferReader(_pTexture)
, m_bindTexture(_bindTexture)
, m_image(0)
, m_bufferLocked(false)
{
m_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
_initBuffers();
@ -35,48 +36,43 @@ void ColorBufferReaderWithEGLImage::_initBuffers()
}
}
u8 * ColorBufferReaderWithEGLImage::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync)
const u8 * ColorBufferReaderWithEGLImage::_readPixels(const ReadColorBufferParams& _params, u32& _heightOffset,
u32& _stride)
{
const graphics::FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats();
GLenum colorFormat, colorType, colorFormatBytes;
if (_size > G_IM_SIZ_8b) {
colorFormat = GLenum(fbTexFormat.colorFormat);
colorType = GLenum(fbTexFormat.colorType);
colorFormatBytes = GLenum(fbTexFormat.colorFormatBytes);
}
else {
colorFormat = GLenum(fbTexFormat.monochromeFormat);
colorType = GLenum(fbTexFormat.monochromeType);
colorFormatBytes = GLenum(fbTexFormat.monochromeFormatBytes);
}
GLenum format = GLenum(_params.colorFormat);
GLenum type = GLenum(_params.colorType);
u8* pixelData = m_pixelData.data();
void* gpuData = nullptr;
const u8* returnData = nullptr;
if (!_sync) {
void* ptr;
if (!_params.sync) {
m_bindTexture->bind(graphics::Parameter(0), graphics::Parameter(GL_TEXTURE_2D), m_pTexture->name);
m_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, m_image);
m_bindTexture->bind(graphics::Parameter(0), graphics::Parameter(GL_TEXTURE_2D), ObjectHandle());
int widthBytes = _width*colorFormatBytes;
int strideBytes = m_pTexture->realWidth * colorFormatBytes;
m_window.lock(GRALLOC_USAGE_SW_READ_OFTEN, &ptr);
m_window.lock(GRALLOC_USAGE_SW_READ_OFTEN, &gpuData);
m_bufferLocked = true;
_heightOffset = static_cast<u32>(_params.y0);
_stride = m_pTexture->realWidth;
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
memcpy(pixelData + lnIndex*widthBytes, reinterpret_cast<char*>(ptr) + ((lnIndex + _y0)*strideBytes), widthBytes);
}
m_window.unlock();
} else {
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, pixelData);
gpuData = m_pixelData.data();
glReadPixels(_params.x0, _params.y0, _params.width, _params.height, format, type, gpuData);
_heightOffset = 0;
_stride = 0;
}
return pixelData;
return reinterpret_cast<u8*>(gpuData);
}
void ColorBufferReaderWithEGLImage::cleanUp()
{
if (m_bufferLocked) {
m_window.unlock();
m_bufferLocked = false;
}
}
#endif // EGL

View File

@ -19,7 +19,8 @@ public:
CachedBindTexture * _bindTexture);
~ColorBufferReaderWithEGLImage();
u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) override;
const u8 * _readPixels(const ReadColorBufferParams& _params, u32& _heightOffset, u32& _stride) override;
void cleanUp() override;
private:
@ -29,6 +30,7 @@ private:
GraphicBuffer m_window{};
EGLImageKHR m_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES;
bool m_bufferLocked;
};
}

View File

@ -39,45 +39,30 @@ void ColorBufferReaderWithPixelBuffer::_initBuffers()
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle::null);
}
u8 * ColorBufferReaderWithPixelBuffer::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync)
const u8 * ColorBufferReaderWithPixelBuffer::_readPixels(const ReadColorBufferParams& _params, u32& _heightOffset,
u32& _stride)
{
const graphics::FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats();
GLenum colorFormat, colorType, colorFormatBytes;
if (_size > G_IM_SIZ_8b) {
colorFormat = GLenum(fbTexFormat.colorFormat);
colorType = GLenum(fbTexFormat.colorType);
colorFormatBytes = GLenum(fbTexFormat.colorFormatBytes);
} else {
colorFormat = GLenum(fbTexFormat.monochromeFormat);
colorType = GLenum(fbTexFormat.monochromeType);
colorFormatBytes = GLenum(fbTexFormat.monochromeFormatBytes);
}
GLenum format = GLenum(_params.colorFormat);
GLenum type = GLenum(_params.colorType);
// 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) {
if (!_params.sync) {
m_curIndex ^= 1;
const u32 nextIndex = m_curIndex ^ 1;
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[m_curIndex]));
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[nextIndex]));
} else {
m_bindBuffer->bind(Parameter(GL_PIXEL_PACK_BUFFER), ObjectHandle(m_PBO[_numPBO -1]));
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, 0);
}
GLubyte* pixelData = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pTexture->realWidth * _height * colorFormatBytes, GL_MAP_READ_BIT);
if (pixelData == nullptr)
return nullptr;
_heightOffset = 0;
_stride = m_pTexture->realWidth;
int widthBytes = _width*colorFormatBytes;
int strideBytes = m_pTexture->realWidth * colorFormatBytes;
u8 * pixelDataAlloc = m_pixelData.data();
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
memcpy(pixelDataAlloc + lnIndex*widthBytes, pixelData + (lnIndex*strideBytes), widthBytes);
}
return pixelDataAlloc;
return reinterpret_cast<u8*>(glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0,
m_pTexture->realWidth * _params.height * _params.colorFormatBytes, GL_MAP_READ_BIT));
}
void ColorBufferReaderWithPixelBuffer::cleanUp()

View File

@ -12,7 +12,7 @@ public:
CachedBindBuffer * _bindBuffer);
~ColorBufferReaderWithPixelBuffer();
u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) override;
const u8 * _readPixels(const ReadColorBufferParams& _params, u32& _heightOffset, u32& _stride) override;
void cleanUp() override;
private:

View File

@ -11,31 +11,20 @@ ColorBufferReaderWithReadPixels::ColorBufferReaderWithReadPixels(CachedTexture *
}
u8 * ColorBufferReaderWithReadPixels::readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync)
const u8 * ColorBufferReaderWithReadPixels::_readPixels(const ReadColorBufferParams& _params, u32& _heightOffset,
u32& _stride)
{
const graphics::FramebufferTextureFormats & fbTexFormat = gfxContext.getFramebufferTextureFormats();
GLenum colorFormat, colorType, colorFormatBytes;
if (_size > G_IM_SIZ_8b) {
colorFormat = GLenum(fbTexFormat.colorFormat);
colorType = GLenum(fbTexFormat.colorType);
colorFormatBytes = GLenum(fbTexFormat.colorFormatBytes);
} else {
colorFormat = GLenum(fbTexFormat.monochromeFormat);
colorType = GLenum(fbTexFormat.monochromeType);
colorFormatBytes = GLenum(fbTexFormat.monochromeFormatBytes);
}
GLenum format = GLenum(_params.colorFormat);
GLenum type = GLenum(_params.colorType);
// No async pixel buffer copies are supported in this class, this is a last resort fallback
auto pixelData = std::unique_ptr<GLubyte[]>(new GLubyte[m_pTexture->realWidth * _height * colorFormatBytes]) ;
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, pixelData.get());
u8* gpuData = m_pixelData.data();
glReadPixels(_params.x0, _params.y0, m_pTexture->realWidth, _params.height, format, type, gpuData);
int widthBytes = _width*colorFormatBytes;
int strideBytes = m_pTexture->realWidth * colorFormatBytes;
_heightOffset = 0;
_stride = m_pTexture->realWidth;
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
std::copy_n(pixelData.get() + (lnIndex*strideBytes), widthBytes, m_pixelData.data() + lnIndex*widthBytes);
}
return m_pixelData.data();
return gpuData;
}
void ColorBufferReaderWithReadPixels::cleanUp()

View File

@ -11,7 +11,7 @@ public:
ColorBufferReaderWithReadPixels(CachedTexture * _pTexture);
~ColorBufferReaderWithReadPixels() = default;
u8 * readPixels(s32 _x0, s32 _y0, u32 _width, u32 _height, u32 _size, bool _sync) override;
const u8 * _readPixels(const ReadColorBufferParams& _params, u32& _heightOffset, u32& _stride) override;
void cleanUp() override;
};

View File

@ -78,6 +78,7 @@ MY_LOCAL_SRC_FILES := \
$(SRCDIR)/BufferCopy/DepthBufferToRDRAM.cpp \
$(SRCDIR)/BufferCopy/RDRAMtoColorBuffer.cpp \
$(SRCDIR)/Graphics/Context.cpp \
$(SRCDIR)/Graphics/ColorBufferReader.cpp \
$(SRCDIR)/Graphics/CombinerProgram.cpp \
$(SRCDIR)/Graphics/ObjectHandle.cpp \
$(SRCDIR)/Graphics/OpenGLContext/GLFunctions.cpp \