mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-07 03:13:49 +00:00
Fix PBOs in Android
This commit is contained in:
parent
8c632ca0ad
commit
87c93d9491
|
@ -9,6 +9,7 @@
|
||||||
#include <Config.h>
|
#include <Config.h>
|
||||||
#include <N64.h>
|
#include <N64.h>
|
||||||
#include <VI.h>
|
#include <VI.h>
|
||||||
|
#include <Log.h>
|
||||||
|
|
||||||
ColorBufferToRDRAM::ColorBufferToRDRAM()
|
ColorBufferToRDRAM::ColorBufferToRDRAM()
|
||||||
: m_FBO(0)
|
: m_FBO(0)
|
||||||
|
@ -16,7 +17,12 @@ ColorBufferToRDRAM::ColorBufferToRDRAM()
|
||||||
, m_pCurFrameBuffer(nullptr)
|
, m_pCurFrameBuffer(nullptr)
|
||||||
, m_frameCount(-1)
|
, m_frameCount(-1)
|
||||||
, m_startAddress(-1)
|
, m_startAddress(-1)
|
||||||
|
, m_lastVIWidth(-1)
|
||||||
|
, m_lastVIHeight(-1)
|
||||||
{
|
{
|
||||||
|
m_allowedRealWidths[0] = 320;
|
||||||
|
m_allowedRealWidths[1] = 480;
|
||||||
|
m_allowedRealWidths[2] = 640;
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorBufferToRDRAM::~ColorBufferToRDRAM()
|
ColorBufferToRDRAM::~ColorBufferToRDRAM()
|
||||||
|
@ -30,6 +36,22 @@ void ColorBufferToRDRAM::init()
|
||||||
// generate a framebuffer
|
// generate a framebuffer
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
glGenFramebuffers(1, &m_FBO);
|
glGenFramebuffers(1, &m_FBO);
|
||||||
|
|
||||||
|
_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAM::destroy() {
|
||||||
|
_destroyFBTexure();
|
||||||
|
_destroy();
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
if (m_FBO != 0) {
|
||||||
|
glDeleteFramebuffers(1, &m_FBO);
|
||||||
|
m_FBO = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAM::_initFBTexture(void)
|
||||||
|
{
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_FBO);
|
||||||
|
|
||||||
m_pTexture = textureCache().addFrameBufferTexture();
|
m_pTexture = textureCache().addFrameBufferTexture();
|
||||||
|
@ -41,8 +63,10 @@ void ColorBufferToRDRAM::init()
|
||||||
m_pTexture->maskT = 0;
|
m_pTexture->maskT = 0;
|
||||||
m_pTexture->mirrorS = 0;
|
m_pTexture->mirrorS = 0;
|
||||||
m_pTexture->mirrorT = 0;
|
m_pTexture->mirrorT = 0;
|
||||||
m_pTexture->realWidth = 640;
|
//The actual VI width is not used for texture width because most texture widths
|
||||||
m_pTexture->realHeight = 580;
|
//cause slowdowns in the glReadPixels call, at least on Android
|
||||||
|
m_pTexture->realWidth = _getRealWidth(m_lastVIWidth);
|
||||||
|
m_pTexture->realHeight = m_lastVIHeight;
|
||||||
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
m_pTexture->textureBytes = m_pTexture->realWidth * m_pTexture->realHeight * 4;
|
||||||
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
||||||
|
@ -56,20 +80,16 @@ void ColorBufferToRDRAM::init()
|
||||||
assert(checkFBO());
|
assert(checkFBO());
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// _init(m_pTexture->realWidth, m_pTexture->realHeight, m_pTexture->textureBytes);
|
_initBuffers();
|
||||||
_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAM::destroy() {
|
void ColorBufferToRDRAM::_destroyFBTexure(void)
|
||||||
_destroy();
|
{
|
||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
_destroyBuffers();
|
||||||
if (m_FBO != 0) {
|
|
||||||
glDeleteFramebuffers(1, &m_FBO);
|
if (m_pTexture != nullptr) {
|
||||||
m_FBO = 0;
|
|
||||||
}
|
|
||||||
if (m_pTexture != NULL) {
|
|
||||||
textureCache().removeFrameBufferTexture(m_pTexture);
|
textureCache().removeFrameBufferTexture(m_pTexture);
|
||||||
m_pTexture = NULL;
|
m_pTexture = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,6 +117,16 @@ bool ColorBufferToRDRAM::_prepareCopy(u32 _startAddress)
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if(m_pTexture == nullptr ||
|
||||||
|
(m_lastVIWidth != VI.width || m_lastVIHeight != VI.height))
|
||||||
|
{
|
||||||
|
_destroyFBTexure();
|
||||||
|
|
||||||
|
m_lastVIWidth = VI.width;
|
||||||
|
m_lastVIHeight = VI.height;
|
||||||
|
_initFBTexture();
|
||||||
|
}
|
||||||
|
|
||||||
m_pCurFrameBuffer = pBuffer;
|
m_pCurFrameBuffer = pBuffer;
|
||||||
|
|
||||||
if ((config.generalEmulation.hacks & hack_subscreen) != 0 && m_pCurFrameBuffer->m_width == VI.width && m_pCurFrameBuffer->m_height == VI.height) {
|
if ((config.generalEmulation.hacks & hack_subscreen) != 0 && m_pCurFrameBuffer->m_width == VI.width && m_pCurFrameBuffer->m_height == VI.height) {
|
||||||
|
@ -204,6 +234,17 @@ void ColorBufferToRDRAM::_copy(u32 _startAddress, u32 _endAddress, bool _sync)
|
||||||
gDP.changed |= CHANGED_SCISSOR;
|
gDP.changed |= CHANGED_SCISSOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ColorBufferToRDRAM::_getRealWidth(u32 _viWidth)
|
||||||
|
{
|
||||||
|
u32 index = 0;
|
||||||
|
while(index < m_allowedRealWidths.size() && _viWidth > m_allowedRealWidths[index])
|
||||||
|
{
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_allowedRealWidths[index];
|
||||||
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAM::copyToRDRAM(u32 _address, bool _sync)
|
void ColorBufferToRDRAM::copyToRDRAM(u32 _address, bool _sync)
|
||||||
{
|
{
|
||||||
if (!_prepareCopy(_address))
|
if (!_prepareCopy(_address))
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define ColorBufferToRDRAM_H
|
#define ColorBufferToRDRAM_H
|
||||||
|
|
||||||
#include <OpenGL.h>
|
#include <OpenGL.h>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
struct CachedTexture;
|
struct CachedTexture;
|
||||||
struct FrameBuffer;
|
struct FrameBuffer;
|
||||||
|
@ -27,6 +28,8 @@ protected:
|
||||||
private:
|
private:
|
||||||
virtual void _init() = 0;
|
virtual void _init() = 0;
|
||||||
virtual void _destroy() = 0;
|
virtual void _destroy() = 0;
|
||||||
|
virtual void _initBuffers(void) = 0;
|
||||||
|
virtual void _destroyBuffers(void) = 0;
|
||||||
virtual GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) = 0;
|
virtual GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) = 0;
|
||||||
virtual void _cleanUpPixels(GLubyte* pixelData) = 0;
|
virtual void _cleanUpPixels(GLubyte* pixelData) = 0;
|
||||||
|
|
||||||
|
@ -37,10 +40,16 @@ private:
|
||||||
u32 raw;
|
u32 raw;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void _initFBTexture(void);
|
||||||
|
|
||||||
|
void _destroyFBTexure(void);
|
||||||
|
|
||||||
bool _prepareCopy(u32 _startAddress);
|
bool _prepareCopy(u32 _startAddress);
|
||||||
|
|
||||||
void _copy(u32 _startAddress, u32 _endAddress, bool _sync);
|
void _copy(u32 _startAddress, u32 _endAddress, bool _sync);
|
||||||
|
|
||||||
|
u32 _getRealWidth(u32 _viWidth);
|
||||||
|
|
||||||
// Convert pixel from video memory to N64 buffer format.
|
// Convert pixel from video memory to N64 buffer format.
|
||||||
static u8 _RGBAtoR8(u8 _c);
|
static u8 _RGBAtoR8(u8 _c);
|
||||||
static u16 _RGBAtoRGBA16(u32 _c);
|
static u16 _RGBAtoRGBA16(u32 _c);
|
||||||
|
@ -50,6 +59,11 @@ private:
|
||||||
FrameBuffer * m_pCurFrameBuffer;
|
FrameBuffer * m_pCurFrameBuffer;
|
||||||
u32 m_frameCount;
|
u32 m_frameCount;
|
||||||
u32 m_startAddress;
|
u32 m_startAddress;
|
||||||
|
|
||||||
|
u32 m_lastVIWidth;
|
||||||
|
u32 m_lastVIHeight;
|
||||||
|
|
||||||
|
std::array<u32, 3> m_allowedRealWidths;
|
||||||
};
|
};
|
||||||
|
|
||||||
void copyWhiteToRDRAM(FrameBuffer * _pBuffer);
|
void copyWhiteToRDRAM(FrameBuffer * _pBuffer);
|
||||||
|
|
|
@ -24,6 +24,8 @@ private:
|
||||||
void _destroy() override;
|
void _destroy() override;
|
||||||
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
||||||
void _cleanUpPixels(GLubyte* pixelData) override;
|
void _cleanUpPixels(GLubyte* pixelData) override;
|
||||||
|
void _initBuffers(void) override;
|
||||||
|
void _destroyBuffers(void) override;
|
||||||
|
|
||||||
GraphicBuffer* m_window;
|
GraphicBuffer* m_window;
|
||||||
EGLImageKHR m_image;
|
EGLImageKHR m_image;
|
||||||
|
@ -37,25 +39,39 @@ ColorBufferToRDRAM & ColorBufferToRDRAM::get()
|
||||||
}
|
}
|
||||||
|
|
||||||
ColorBufferToRDRAMAndroid::ColorBufferToRDRAMAndroid()
|
ColorBufferToRDRAMAndroid::ColorBufferToRDRAMAndroid()
|
||||||
: ColorBufferToRDRAM()
|
: ColorBufferToRDRAM(),
|
||||||
|
m_window(nullptr),
|
||||||
|
m_image(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAMAndroid::_init()
|
void ColorBufferToRDRAMAndroid::_init()
|
||||||
{
|
{
|
||||||
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");
|
m_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
|
||||||
|
|
||||||
|
m_window = new GraphicBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAMAndroid::_destroy()
|
void ColorBufferToRDRAMAndroid::_destroy()
|
||||||
{
|
{
|
||||||
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_image);
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAMAndroid::_initBuffers(void)
|
||||||
|
{
|
||||||
|
m_window->reallocate(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAMAndroid::_destroyBuffers(void)
|
||||||
|
{
|
||||||
|
if(m_image != 0)
|
||||||
|
{
|
||||||
|
eglDestroyImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), m_image);
|
||||||
|
m_image = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GLubyte* ColorBufferToRDRAMAndroid::_getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync)
|
GLubyte* ColorBufferToRDRAMAndroid::_getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync)
|
||||||
|
|
|
@ -13,8 +13,10 @@ private:
|
||||||
void _destroy() override;
|
void _destroy() override;
|
||||||
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
||||||
void _cleanUpPixels(GLubyte* pixelData) override;
|
void _cleanUpPixels(GLubyte* pixelData) override;
|
||||||
|
void _initBuffers(void) override;
|
||||||
GLuint m_PBO[3];
|
void _destroyBuffers(void) override;
|
||||||
|
static const int _numPBO = 3;
|
||||||
|
GLuint m_PBO[_numPBO];
|
||||||
u32 m_curIndex;
|
u32 m_curIndex;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,25 +30,42 @@ ColorBufferToRDRAMDesktop::ColorBufferToRDRAMDesktop()
|
||||||
: ColorBufferToRDRAM()
|
: ColorBufferToRDRAM()
|
||||||
, m_curIndex(-1)
|
, m_curIndex(-1)
|
||||||
{
|
{
|
||||||
m_PBO[0] = m_PBO[1] = m_PBO[2] = 0;
|
for(int index = 0; index < _numPBO; ++index)
|
||||||
|
{
|
||||||
|
m_PBO[index] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAMDesktop::_init()
|
void ColorBufferToRDRAMDesktop::_init()
|
||||||
{
|
{
|
||||||
// Generate and initialize Pixel Buffer Objects
|
// Generate Pixel Buffer Objects
|
||||||
glGenBuffers(3, m_PBO);
|
glGenBuffers(_numPBO, 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;
|
m_curIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAMDesktop::_destroy()
|
void ColorBufferToRDRAMDesktop::_destroy()
|
||||||
{
|
{
|
||||||
glDeleteBuffers(3, m_PBO);
|
glDeleteBuffers(_numPBO, m_PBO);
|
||||||
m_PBO[0] = m_PBO[1] = m_PBO[2] = 0;
|
|
||||||
|
for(int index = 0; index < _numPBO; ++index)
|
||||||
|
{
|
||||||
|
m_PBO[index] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAMDesktop::_initBuffers(void)
|
||||||
|
{
|
||||||
|
// Initialize Pixel Buffer Objects
|
||||||
|
for (u32 i = 0; i < _numPBO; ++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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ColorBufferToRDRAMDesktop::_destroyBuffers(void)
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GLubyte* ColorBufferToRDRAMDesktop::_getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync)
|
GLubyte* ColorBufferToRDRAMDesktop::_getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync)
|
||||||
|
@ -68,22 +87,30 @@ GLubyte* ColorBufferToRDRAMDesktop::_getPixels(GLint _x0, GLint _y0, GLsizei _wi
|
||||||
m_curIndex ^= 1;
|
m_curIndex ^= 1;
|
||||||
const u32 nextIndex = m_curIndex ^ 1;
|
const u32 nextIndex = m_curIndex ^ 1;
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[m_curIndex]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[m_curIndex]);
|
||||||
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, 0);
|
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[nextIndex]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[nextIndex]);
|
||||||
} else {
|
} else {
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[2]);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_PBO[2]);
|
||||||
glReadPixels(_x0, _y0, _width, _height, colorFormat, colorType, 0);
|
glReadPixels(_x0, _y0, m_pTexture->realWidth, _height, colorFormat, colorType, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLubyte* pixelData = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, _width * _height * colorFormatBytes, GL_MAP_READ_BIT);
|
GLubyte* pixelData = (GLubyte*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pTexture->realWidth * _height * colorFormatBytes, GL_MAP_READ_BIT);
|
||||||
if (pixelData == NULL)
|
if (pixelData == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return pixelData;
|
int widthBytes = _width*colorFormatBytes;
|
||||||
|
int strideBytes = m_pTexture->realWidth * colorFormatBytes;
|
||||||
|
GLubyte* pixelDataAlloc = (GLubyte*)malloc(_width * _height * colorFormatBytes);
|
||||||
|
for (unsigned int lnIndex = 0; lnIndex < _height; ++lnIndex) {
|
||||||
|
memcpy(pixelDataAlloc + lnIndex*widthBytes, pixelData + (lnIndex*strideBytes), widthBytes);
|
||||||
|
}
|
||||||
|
return pixelDataAlloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorBufferToRDRAMDesktop::_cleanUpPixels(GLubyte* pixelData)
|
void ColorBufferToRDRAMDesktop::_cleanUpPixels(GLubyte* pixelData)
|
||||||
{
|
{
|
||||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
|
||||||
|
free(pixelData);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user