mirror of https://github.com/PCSX2/pcsx2.git
GSdx-ogl: LINUX only
* request a minimum of 1 for texture dimension * Use offscreen texture likes DX11. * add more bits for extra texture format * do operation on texture unit 0 to avoid ping-pong between unit 0/2 git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5114 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
92f2ab38ae
commit
d6e7ea4a4e
|
@ -21,6 +21,10 @@
|
||||||
|
|
||||||
#include "GSDeviceOGL.h"
|
#include "GSDeviceOGL.h"
|
||||||
|
|
||||||
|
// TODO performance cost to investigate
|
||||||
|
// Texture attachment/glDrawBuffer. For the moment it set every draw and potentially multiple time (first time in clear, second time in rendering)
|
||||||
|
// Attachment 1 is only used with the GL_16UI format
|
||||||
|
|
||||||
//#define LOUD_DEBUGGING
|
//#define LOUD_DEBUGGING
|
||||||
//#define PRINT_FRAME_NUMBER
|
//#define PRINT_FRAME_NUMBER
|
||||||
//#define ONLY_LINES
|
//#define ONLY_LINES
|
||||||
|
@ -507,7 +511,7 @@ void GSDeviceOGL::DebugInput()
|
||||||
m_state.ps_srv[i]->Save(format("/tmp/in_f%d__d%d__%d.bmp", g_frame_count, g_draw_count, i));
|
m_state.ps_srv[i]->Save(format("/tmp/in_f%d__d%d__%d.bmp", g_frame_count, g_draw_count, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/in_current_out_%d.bmp", g_draw_count));
|
//if (m_state.rtv != NULL) m_state.rtv->Save(format("/tmp/target_f%d__d%d__tex.bmp", g_frame_count, g_draw_count));
|
||||||
//if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count));
|
//if (m_state.dsv != NULL) m_state.dsv->Save(format("/tmp/ds_in_%d.bmp", g_draw_count));
|
||||||
|
|
||||||
fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count);
|
fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count);
|
||||||
|
@ -520,6 +524,8 @@ void GSDeviceOGL::DebugInput()
|
||||||
|
|
||||||
void GSDeviceOGL::DebugOutput()
|
void GSDeviceOGL::DebugOutput()
|
||||||
{
|
{
|
||||||
|
CheckDebugLog();
|
||||||
|
|
||||||
bool dump_me = false;
|
bool dump_me = false;
|
||||||
uint32 start = theApp.GetConfig("debug_ogl_dump", 0);
|
uint32 start = theApp.GetConfig("debug_ogl_dump", 0);
|
||||||
uint32 length = theApp.GetConfig("debug_ogl_dump_length", 5);
|
uint32 length = theApp.GetConfig("debug_ogl_dump_length", 5);
|
||||||
|
@ -536,7 +542,6 @@ void GSDeviceOGL::DebugOutput()
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
CheckDebugLog();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GSDeviceOGL::DrawPrimitive()
|
void GSDeviceOGL::DrawPrimitive()
|
||||||
|
@ -596,12 +601,7 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
||||||
// FIXME1 I need to clarify this FBO attachment stuff
|
// FIXME1 I need to clarify this FBO attachment stuff
|
||||||
// I would like to avoid FBO for a basic clean operation
|
// I would like to avoid FBO for a basic clean operation
|
||||||
OMSetFBO(m_fbo);
|
OMSetFBO(m_fbo);
|
||||||
// FIXME2:
|
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
// it would be better to attach the texture to another slot (like 3)
|
|
||||||
// but it crash for an unknow reason
|
|
||||||
// The following error appears "glClearBufferfv failed because the currently set GL_DRAW_FRAMEBUFFER binding has incomplete status"
|
|
||||||
// Maybe glDrawBuffer must be updated but it does not solve the crash...
|
|
||||||
// FIXME3: I still have another crash on GOW...
|
|
||||||
static_cast<GSTextureOGL*>(t)->Attach(GL_COLOR_ATTACHMENT0);
|
static_cast<GSTextureOGL*>(t)->Attach(GL_COLOR_ATTACHMENT0);
|
||||||
glClearBufferfv(GL_COLOR, 0, c.v);
|
glClearBufferfv(GL_COLOR, 0, c.v);
|
||||||
}
|
}
|
||||||
|
@ -673,8 +673,8 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: I used directly an offscreen texture because they are the same on Opengl
|
// FIXME: It is possible to bypass completely offscreen-buffer on opengl but it needs some re-thinking of the code.
|
||||||
//if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
|
// For the moment mimic dx11
|
||||||
GSTexture* rt = CreateRenderTarget(w, h, false, format);
|
GSTexture* rt = CreateRenderTarget(w, h, false, format);
|
||||||
if(rt)
|
if(rt)
|
||||||
{
|
{
|
||||||
|
@ -687,9 +687,12 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
||||||
if(src2 != src) Recycle(src2);
|
if(src2 != src) Recycle(src2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
|
GSVector4i dor(0, 0, w, h);
|
||||||
dst = CreateOffscreen(w, h, format);
|
dst = CreateOffscreen(w, h, format);
|
||||||
|
|
||||||
|
if (dst) CopyRect(rt, dst, dor);
|
||||||
|
#if 0
|
||||||
if(dst)
|
if(dst)
|
||||||
{
|
{
|
||||||
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
|
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
|
||||||
|
@ -699,8 +702,8 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
||||||
Recycle(rt);
|
Recycle(rt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return dst;
|
return dst;
|
||||||
return rt;
|
//return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy a sub part of a texture into another
|
// Copy a sub part of a texture into another
|
||||||
|
@ -724,27 +727,11 @@ void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
|
||||||
// uint srcName, enum srcTarget, int srcLevel, int srcX, int srcY, int srcZ,
|
// uint srcName, enum srcTarget, int srcLevel, int srcX, int srcY, int srcZ,
|
||||||
// uint dstName, enum dstTarget, int dstLevel, int dstX, int dstY, int dstZ,
|
// uint dstName, enum dstTarget, int dstLevel, int dstX, int dstY, int dstZ,
|
||||||
// sizei width, sizei height, sizei depth);
|
// sizei width, sizei height, sizei depth);
|
||||||
glCopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), GL_TEXTURE_2D,
|
glCopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), static_cast<GSTextureOGL*>(st)->GetTarget(),
|
||||||
0, r.x, r.y, 0,
|
0, r.x, r.y, 0,
|
||||||
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
|
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
|
||||||
0, r.x, r.y, 0,
|
0, r.x, r.y, 0,
|
||||||
r.width(), r.height(), 1);
|
r.width(), r.height(), 1);
|
||||||
#if 0
|
|
||||||
|
|
||||||
// FIXME FBO
|
|
||||||
GLuint fbo_old = m_state.fbo;
|
|
||||||
OMSetFBO(m_fbo);
|
|
||||||
|
|
||||||
// Set the input of glCopyTexSubImage2D
|
|
||||||
static_cast<GSTextureOGL*>(st)->Attach(GL_COLOR_ATTACHMENT1);
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
|
||||||
|
|
||||||
// Copy the full image
|
|
||||||
static_cast<GSTextureOGL*>(dt)->EnableUnit(0);
|
|
||||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, dt->GetWidth(), dt->GetHeight());
|
|
||||||
|
|
||||||
OMSetFBO(fbo_old);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
|
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
|
||||||
|
|
|
@ -62,10 +62,27 @@ GtkWidget* CreateRenderComboBox()
|
||||||
|
|
||||||
if(!s.note.empty()) label += format(" (%s)", s.note.c_str());
|
if(!s.note.empty()) label += format(" (%s)", s.note.c_str());
|
||||||
|
|
||||||
|
// Add some tags to ease users selection
|
||||||
|
switch (i) {
|
||||||
|
// better use opengl instead of SDL
|
||||||
|
case 6:
|
||||||
|
label += " (deprecated)";
|
||||||
|
break;
|
||||||
|
|
||||||
// (dev only) for any NULL stuff
|
// (dev only) for any NULL stuff
|
||||||
if (i >= 7 && i <= 9) label += " (debug only)";
|
case 7:
|
||||||
// (experimental) for opengl stuff
|
case 8:
|
||||||
if (i == 10 || i == 11) label += " (experimental)";
|
case 9:
|
||||||
|
label += " (debug only)";
|
||||||
|
break;
|
||||||
|
|
||||||
|
// opengl harware is not yet finished
|
||||||
|
case 10:
|
||||||
|
label += " (experimental)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
gtk_combo_box_append_text(GTK_COMBO_BOX(render_combo_box), label.c_str());
|
gtk_combo_box_append_text(GTK_COMBO_BOX(render_combo_box), label.c_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
|
||||||
offscreen->Unmap();
|
offscreen->Unmap();
|
||||||
}
|
}
|
||||||
|
|
||||||
//m_renderer->m_dev->Recycle(offscreen);
|
m_renderer->m_dev->Recycle(offscreen);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ static int g_state_texture_unit = -1;
|
||||||
static int g_state_texture_id = -1;
|
static int g_state_texture_id = -1;
|
||||||
|
|
||||||
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read)
|
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read)
|
||||||
: m_extra_buffer_id(0),
|
: m_pbo_id(0),
|
||||||
m_pbo_size(0)
|
m_pbo_size(0)
|
||||||
{
|
{
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
@ -48,8 +48,11 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
||||||
// glBlitFramebuffer
|
// glBlitFramebuffer
|
||||||
|
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
m_size.x = w;
|
// m_size.x = w;
|
||||||
m_size.y = h;
|
// m_size.y = h;
|
||||||
|
// FIXME
|
||||||
|
m_size.x = max(1,w);
|
||||||
|
m_size.y = max(1,h);
|
||||||
m_format = format;
|
m_format = format;
|
||||||
m_type = type;
|
m_type = type;
|
||||||
m_msaa = msaa;
|
m_msaa = msaa;
|
||||||
|
@ -80,7 +83,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Extra buffer to handle various pixel transfer
|
// Extra buffer to handle various pixel transfer
|
||||||
glGenBuffers(1, &m_extra_buffer_id);
|
glGenBuffers(1, &m_pbo_id);
|
||||||
|
|
||||||
uint msaa_level;
|
uint msaa_level;
|
||||||
if (m_msaa) {
|
if (m_msaa) {
|
||||||
|
@ -93,16 +96,30 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
||||||
// Allocate the buffer
|
// Allocate the buffer
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case GSTexture::DepthStencil:
|
case GSTexture::DepthStencil:
|
||||||
EnableUnit(2);
|
EnableUnit(0);
|
||||||
glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
|
glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSTexture::Offscreen:
|
||||||
|
// Allocate a pbo with the texture
|
||||||
|
if (m_format == GL_RGBA8) m_pbo_size = m_size.x * m_size.y * 4;
|
||||||
|
else if (m_format == GL_R16UI) m_pbo_size = m_size.x * m_size.y * 2;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
||||||
|
assert(0); // TODO Later
|
||||||
|
}
|
||||||
|
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
|
||||||
|
glBufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
|
||||||
case GSTexture::RenderTarget:
|
case GSTexture::RenderTarget:
|
||||||
case GSTexture::Texture:
|
case GSTexture::Texture:
|
||||||
// FIXME
|
// FIXME
|
||||||
// Howto allocate the texture unit !!!
|
// Howto allocate the texture unit !!!
|
||||||
// In worst case the HW renderer seems to use 3 texture unit
|
// In worst case the HW renderer seems to use 3 texture unit
|
||||||
// For the moment SW renderer only use 1 so don't bother
|
// For the moment SW renderer only use 1 so don't bother
|
||||||
EnableUnit(2);
|
EnableUnit(0);
|
||||||
if (m_format == GL_RGBA8)
|
if (m_format == GL_RGBA8)
|
||||||
glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(m_texture_target, 0, m_format, m_size.x, m_size.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
else if (m_format == GL_R16UI)
|
else if (m_format == GL_R16UI)
|
||||||
|
@ -114,22 +131,13 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
||||||
assert(0); // TODO Later
|
assert(0); // TODO Later
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GSTexture::Offscreen:
|
|
||||||
if (m_type == GL_RGBA8) m_pbo_size = m_size.x * m_size.y * 4;
|
|
||||||
else if (m_type == GL_R16UI) m_pbo_size = m_size.x * m_size.y * 2;
|
|
||||||
else assert(0);
|
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_extra_buffer_id);
|
|
||||||
glBufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW);
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
|
||||||
break;
|
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureOGL::~GSTextureOGL()
|
GSTextureOGL::~GSTextureOGL()
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &m_extra_buffer_id);
|
glDeleteBuffers(1, &m_pbo_id);
|
||||||
glDeleteTextures(1, &m_texture_id);
|
glDeleteTextures(1, &m_texture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +156,7 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
||||||
// FIXME warning order of the y axis
|
// FIXME warning order of the y axis
|
||||||
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
|
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
|
||||||
|
|
||||||
EnableUnit(2);
|
EnableUnit(0);
|
||||||
|
|
||||||
// pitch could be different of width*element_size
|
// pitch could be different of width*element_size
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch>>2);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch>>2);
|
||||||
|
@ -224,29 +232,41 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
|
||||||
// glMapBuffer — map a buffer object's data store
|
// glMapBuffer — map a buffer object's data store
|
||||||
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
|
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
|
||||||
if (m_type == GSTexture::Offscreen) {
|
if (m_type == GSTexture::Offscreen) {
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_extra_buffer_id);
|
// Bind the texture to the read framebuffer to avoid any disturbance
|
||||||
// FIXME It might be possible to only map a subrange of the texture based on r object
|
EnableUnit(0);
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||||
|
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
|
||||||
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
|
||||||
// Load the PBO
|
// FIXME It might be possible to only read a subrange of the texture based on r object
|
||||||
if (m_format == GL_RGBA8)
|
// Load the PBO with the data
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
|
||||||
|
if (m_format == GL_RGBA8) {
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 4);
|
||||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||||
else if (m_format == GL_R16UI)
|
} else if (m_format == GL_R16UI) {
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 2);
|
||||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, 0);
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, 0);
|
||||||
else if (m_format == GL_R8)
|
} else if (m_format == GL_R8) {
|
||||||
|
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, 0);
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, 0);
|
||||||
else {
|
} else {
|
||||||
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
// Give access from the CPU
|
// Give access from the CPU
|
||||||
uint32 map_flags = GL_MAP_READ_BIT;
|
m.bits = (uint8*) glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, GL_MAP_READ_BIT);
|
||||||
m.bits = (uint8*) glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, map_flags);
|
|
||||||
m.pitch = m_size.x;
|
m.pitch = m_size.x;
|
||||||
|
|
||||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
if ( m.bits ) {
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "bad mapping of the pbo\n");
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -272,6 +292,8 @@ void GSTextureOGL::Unmap()
|
||||||
{
|
{
|
||||||
if (m_type == GSTexture::Offscreen) {
|
if (m_type == GSTexture::Offscreen) {
|
||||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||||
|
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -377,30 +399,45 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
|
||||||
uint32 pitch = 4 * m_size.x;
|
uint32 pitch = 4 * m_size.x;
|
||||||
if (IsDss()) pitch *= 2;
|
if (IsDss()) pitch *= 2;
|
||||||
char* image = (char*)malloc(pitch * m_size.y);
|
char* image = (char*)malloc(pitch * m_size.y);
|
||||||
|
bool status = true;
|
||||||
|
|
||||||
// FIXME instead of swapping manually B and R maybe you can request the driver to do it
|
// FIXME instead of swapping manually B and R maybe you can request the driver to do it
|
||||||
// for us
|
// for us
|
||||||
if (IsBackbuffer()) {
|
if (IsBackbuffer()) {
|
||||||
glReadBuffer(GL_BACK);
|
//glReadBuffer(GL_BACK);
|
||||||
|
//glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||||
} else if(IsDss()) {
|
} else if(IsDss()) {
|
||||||
EnableUnit(2);
|
EnableUnit(0);
|
||||||
glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image);
|
glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image);
|
||||||
} else {
|
} else {
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||||
|
|
||||||
EnableUnit(2);
|
EnableUnit(0);
|
||||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_texture_target, m_texture_id, 0);
|
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
|
||||||
|
|
||||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||||
|
if (m_format == GL_RGBA8)
|
||||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||||
|
else if (m_format == GL_R16UI)
|
||||||
|
{
|
||||||
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED_INTEGER, GL_UNSIGNED_SHORT, image);
|
||||||
|
// Not supported in Save function
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
else if (m_format == GL_R8)
|
||||||
|
{
|
||||||
|
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_BYTE, image);
|
||||||
|
// Not supported in Save function
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Save(fn, image, pitch);
|
if (status) Save(fn, image, pitch);
|
||||||
free(image);
|
free(image);
|
||||||
|
|
||||||
return true;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class GSTextureOGL : public GSTexture
|
||||||
private:
|
private:
|
||||||
GLenum m_texture_target; // texture target: 2D, rectangle etc...
|
GLenum m_texture_target; // texture target: 2D, rectangle etc...
|
||||||
GLuint m_texture_id; // the texture id
|
GLuint m_texture_id; // the texture id
|
||||||
uint m_extra_buffer_id;
|
uint m_pbo_id;
|
||||||
int m_pbo_size;
|
int m_pbo_size;
|
||||||
GLuint m_fbo_read;
|
GLuint m_fbo_read;
|
||||||
|
|
||||||
|
@ -49,4 +49,5 @@ class GSTextureOGL : public GSTexture
|
||||||
bool IsDss() { return (m_type == GSTexture::DepthStencil); }
|
bool IsDss() { return (m_type == GSTexture::DepthStencil); }
|
||||||
|
|
||||||
GLuint GetID() { return m_texture_id; }
|
GLuint GetID() { return m_texture_id; }
|
||||||
|
GLenum GetTarget() { return m_texture_target; }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue