mirror of
https://github.com/blawar/GLideN64.git
synced 2024-07-04 10:03:36 +00:00
Fix PBOs in Android
This commit is contained in:
parent
8c632ca0ad
commit
87c93d9491
|
@ -9,6 +9,7 @@
|
|||
#include <Config.h>
|
||||
#include <N64.h>
|
||||
#include <VI.h>
|
||||
#include <Log.h>
|
||||
|
||||
ColorBufferToRDRAM::ColorBufferToRDRAM()
|
||||
: m_FBO(0)
|
||||
|
@ -16,7 +17,12 @@ ColorBufferToRDRAM::ColorBufferToRDRAM()
|
|||
, m_pCurFrameBuffer(nullptr)
|
||||
, m_frameCount(-1)
|
||||
, m_startAddress(-1)
|
||||
, m_lastVIWidth(-1)
|
||||
, m_lastVIHeight(-1)
|
||||
{
|
||||
m_allowedRealWidths[0] = 320;
|
||||
m_allowedRealWidths[1] = 480;
|
||||
m_allowedRealWidths[2] = 640;
|
||||
}
|
||||
|
||||
ColorBufferToRDRAM::~ColorBufferToRDRAM()
|
||||
|
@ -30,6 +36,22 @@ void ColorBufferToRDRAM::init()
|
|||
// generate a framebuffer
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
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);
|
||||
|
||||
m_pTexture = textureCache().addFrameBufferTexture();
|
||||
|
@ -41,8 +63,10 @@ void ColorBufferToRDRAM::init()
|
|||
m_pTexture->maskT = 0;
|
||||
m_pTexture->mirrorS = 0;
|
||||
m_pTexture->mirrorT = 0;
|
||||
m_pTexture->realWidth = 640;
|
||||
m_pTexture->realHeight = 580;
|
||||
//The actual VI width is not used for texture width because most texture widths
|
||||
//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;
|
||||
textureCache().addFrameBufferTextureSize(m_pTexture->textureBytes);
|
||||
glBindTexture(GL_TEXTURE_2D, m_pTexture->glName);
|
||||
|
@ -56,20 +80,16 @@ void ColorBufferToRDRAM::init()
|
|||
assert(checkFBO());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
|
||||
// _init(m_pTexture->realWidth, m_pTexture->realHeight, m_pTexture->textureBytes);
|
||||
_init();
|
||||
_initBuffers();
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAM::destroy() {
|
||||
_destroy();
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
if (m_FBO != 0) {
|
||||
glDeleteFramebuffers(1, &m_FBO);
|
||||
m_FBO = 0;
|
||||
}
|
||||
if (m_pTexture != NULL) {
|
||||
void ColorBufferToRDRAM::_destroyFBTexure(void)
|
||||
{
|
||||
_destroyBuffers();
|
||||
|
||||
if (m_pTexture != nullptr) {
|
||||
textureCache().removeFrameBufferTexture(m_pTexture);
|
||||
m_pTexture = NULL;
|
||||
m_pTexture = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -97,6 +117,16 @@ bool ColorBufferToRDRAM::_prepareCopy(u32 _startAddress)
|
|||
if (height == 0)
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!_prepareCopy(_address))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define ColorBufferToRDRAM_H
|
||||
|
||||
#include <OpenGL.h>
|
||||
#include <array>
|
||||
|
||||
struct CachedTexture;
|
||||
struct FrameBuffer;
|
||||
|
@ -27,6 +28,8 @@ protected:
|
|||
private:
|
||||
virtual void _init() = 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 void _cleanUpPixels(GLubyte* pixelData) = 0;
|
||||
|
||||
|
@ -37,10 +40,16 @@ private:
|
|||
u32 raw;
|
||||
};
|
||||
|
||||
void _initFBTexture(void);
|
||||
|
||||
void _destroyFBTexure(void);
|
||||
|
||||
bool _prepareCopy(u32 _startAddress);
|
||||
|
||||
void _copy(u32 _startAddress, u32 _endAddress, bool _sync);
|
||||
|
||||
u32 _getRealWidth(u32 _viWidth);
|
||||
|
||||
// Convert pixel from video memory to N64 buffer format.
|
||||
static u8 _RGBAtoR8(u8 _c);
|
||||
static u16 _RGBAtoRGBA16(u32 _c);
|
||||
|
@ -50,6 +59,11 @@ private:
|
|||
FrameBuffer * m_pCurFrameBuffer;
|
||||
u32 m_frameCount;
|
||||
u32 m_startAddress;
|
||||
|
||||
u32 m_lastVIWidth;
|
||||
u32 m_lastVIHeight;
|
||||
|
||||
std::array<u32, 3> m_allowedRealWidths;
|
||||
};
|
||||
|
||||
void copyWhiteToRDRAM(FrameBuffer * _pBuffer);
|
||||
|
|
|
@ -24,6 +24,8 @@ private:
|
|||
void _destroy() override;
|
||||
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
||||
void _cleanUpPixels(GLubyte* pixelData) override;
|
||||
void _initBuffers(void) override;
|
||||
void _destroyBuffers(void) override;
|
||||
|
||||
GraphicBuffer* m_window;
|
||||
EGLImageKHR m_image;
|
||||
|
@ -37,25 +39,39 @@ ColorBufferToRDRAM & ColorBufferToRDRAM::get()
|
|||
}
|
||||
|
||||
ColorBufferToRDRAMAndroid::ColorBufferToRDRAMAndroid()
|
||||
: ColorBufferToRDRAM()
|
||||
: ColorBufferToRDRAM(),
|
||||
m_window(nullptr),
|
||||
m_image(0)
|
||||
{
|
||||
}
|
||||
|
||||
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_window = new GraphicBuffer();
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
@ -13,8 +13,10 @@ private:
|
|||
void _destroy() override;
|
||||
GLubyte* _getPixels(GLint _x0, GLint _y0, GLsizei _width, GLsizei _height, u32 _size, bool _sync) override;
|
||||
void _cleanUpPixels(GLubyte* pixelData) override;
|
||||
|
||||
GLuint m_PBO[3];
|
||||
void _initBuffers(void) override;
|
||||
void _destroyBuffers(void) override;
|
||||
static const int _numPBO = 3;
|
||||
GLuint m_PBO[_numPBO];
|
||||
u32 m_curIndex;
|
||||
};
|
||||
|
||||
|
@ -28,25 +30,42 @@ ColorBufferToRDRAMDesktop::ColorBufferToRDRAMDesktop()
|
|||
: ColorBufferToRDRAM()
|
||||
, 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()
|
||||
{
|
||||
// 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);
|
||||
// Generate Pixel Buffer Objects
|
||||
glGenBuffers(_numPBO, m_PBO);
|
||||
m_curIndex = 0;
|
||||
}
|
||||
|
||||
void ColorBufferToRDRAMDesktop::_destroy()
|
||||
{
|
||||
glDeleteBuffers(3, m_PBO);
|
||||
m_PBO[0] = m_PBO[1] = m_PBO[2] = 0;
|
||||
glDeleteBuffers(_numPBO, m_PBO);
|
||||
|
||||
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)
|
||||
|
@ -68,22 +87,30 @@ GLubyte* ColorBufferToRDRAMDesktop::_getPixels(GLint _x0, GLint _y0, GLsizei _wi
|
|||
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);
|
||||
glReadPixels(_x0, _y0, m_pTexture->realWidth, _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);
|
||||
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)
|
||||
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)
|
||||
{
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
free(pixelData);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user