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"
|
||||
|
||||
// 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 PRINT_FRAME_NUMBER
|
||||
//#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));
|
||||
}
|
||||
}
|
||||
//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));
|
||||
|
||||
fprintf(stderr, "Draw %d (Frame %d)\n", g_draw_count, g_frame_count);
|
||||
|
@ -520,6 +524,8 @@ void GSDeviceOGL::DebugInput()
|
|||
|
||||
void GSDeviceOGL::DebugOutput()
|
||||
{
|
||||
CheckDebugLog();
|
||||
|
||||
bool dump_me = false;
|
||||
uint32 start = theApp.GetConfig("debug_ogl_dump", 0);
|
||||
uint32 length = theApp.GetConfig("debug_ogl_dump_length", 5);
|
||||
|
@ -536,7 +542,6 @@ void GSDeviceOGL::DebugOutput()
|
|||
fprintf(stderr, "\n");
|
||||
|
||||
}
|
||||
CheckDebugLog();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::DrawPrimitive()
|
||||
|
@ -596,12 +601,7 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
|||
// FIXME1 I need to clarify this FBO attachment stuff
|
||||
// I would like to avoid FBO for a basic clean operation
|
||||
OMSetFBO(m_fbo);
|
||||
// FIXME2:
|
||||
// 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...
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
static_cast<GSTextureOGL*>(t)->Attach(GL_COLOR_ATTACHMENT0);
|
||||
glClearBufferfv(GL_COLOR, 0, c.v);
|
||||
}
|
||||
|
@ -673,8 +673,8 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
|||
return false;
|
||||
}
|
||||
|
||||
// FIXME: I used directly an offscreen texture because they are the same on Opengl
|
||||
//if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
|
||||
// FIXME: It is possible to bypass completely offscreen-buffer on opengl but it needs some re-thinking of the code.
|
||||
// For the moment mimic dx11
|
||||
GSTexture* rt = CreateRenderTarget(w, h, false, format);
|
||||
if(rt)
|
||||
{
|
||||
|
@ -687,9 +687,12 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
|||
if(src2 != src) Recycle(src2);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
GSVector4i dor(0, 0, w, h);
|
||||
dst = CreateOffscreen(w, h, format);
|
||||
|
||||
if (dst) CopyRect(rt, dst, dor);
|
||||
#if 0
|
||||
if(dst)
|
||||
{
|
||||
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
|
||||
|
@ -699,8 +702,8 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
|||
Recycle(rt);
|
||||
}
|
||||
|
||||
//return dst;
|
||||
return rt;
|
||||
return dst;
|
||||
//return rt;
|
||||
}
|
||||
|
||||
// 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 dstName, enum dstTarget, int dstLevel, int dstX, int dstY, int dstZ,
|
||||
// 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,
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
|
||||
0, r.x, r.y, 0,
|
||||
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
|
||||
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());
|
||||
|
||||
// (dev only) for any NULL stuff
|
||||
if (i >= 7 && i <= 9) label += " (debug only)";
|
||||
// (experimental) for opengl stuff
|
||||
if (i == 10 || i == 11) label += " (experimental)";
|
||||
// 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
|
||||
case 7:
|
||||
case 8:
|
||||
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());
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
|
|||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
// *************************************************************
|
||||
|
@ -48,8 +48,11 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
// glBlitFramebuffer
|
||||
|
||||
// *************************************************************
|
||||
m_size.x = w;
|
||||
m_size.y = h;
|
||||
// m_size.x = w;
|
||||
// m_size.y = h;
|
||||
// FIXME
|
||||
m_size.x = max(1,w);
|
||||
m_size.y = max(1,h);
|
||||
m_format = format;
|
||||
m_type = type;
|
||||
m_msaa = msaa;
|
||||
|
@ -80,7 +83,7 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
break;
|
||||
}
|
||||
// Extra buffer to handle various pixel transfer
|
||||
glGenBuffers(1, &m_extra_buffer_id);
|
||||
glGenBuffers(1, &m_pbo_id);
|
||||
|
||||
uint msaa_level;
|
||||
if (m_msaa) {
|
||||
|
@ -93,16 +96,30 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
// Allocate the buffer
|
||||
switch (m_type) {
|
||||
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);
|
||||
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::Texture:
|
||||
// FIXME
|
||||
// Howto allocate the 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
|
||||
EnableUnit(2);
|
||||
EnableUnit(0);
|
||||
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);
|
||||
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
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
GSTextureOGL::~GSTextureOGL()
|
||||
{
|
||||
glDeleteBuffers(1, &m_extra_buffer_id);
|
||||
glDeleteBuffers(1, &m_pbo_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 I'm not confident with GL_UNSIGNED_BYTE type
|
||||
|
||||
EnableUnit(2);
|
||||
EnableUnit(0);
|
||||
|
||||
// pitch could be different of width*element_size
|
||||
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
|
||||
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
|
||||
if (m_type == GSTexture::Offscreen) {
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, m_extra_buffer_id);
|
||||
// FIXME It might be possible to only map a subrange of the texture based on r object
|
||||
// Bind the texture to the read framebuffer to avoid any disturbance
|
||||
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
|
||||
if (m_format == GL_RGBA8)
|
||||
// FIXME It might be possible to only read a subrange of the texture based on r object
|
||||
// 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);
|
||||
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);
|
||||
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);
|
||||
else {
|
||||
} else {
|
||||
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
||||
assert(0);
|
||||
}
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
// Give access from the CPU
|
||||
uint32 map_flags = GL_MAP_READ_BIT;
|
||||
m.bits = (uint8*) glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, map_flags);
|
||||
m.bits = (uint8*) glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, GL_MAP_READ_BIT);
|
||||
m.pitch = m_size.x;
|
||||
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
return true;
|
||||
if ( m.bits ) {
|
||||
return true;
|
||||
} else {
|
||||
fprintf(stderr, "bad mapping of the pbo\n");
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -272,6 +292,8 @@ void GSTextureOGL::Unmap()
|
|||
{
|
||||
if (m_type == GSTexture::Offscreen) {
|
||||
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;
|
||||
if (IsDss()) pitch *= 2;
|
||||
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
|
||||
// for us
|
||||
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);
|
||||
} else if(IsDss()) {
|
||||
EnableUnit(2);
|
||||
EnableUnit(0);
|
||||
glGetTexImage(m_texture_target, 0, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, image);
|
||||
} else {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
|
||||
EnableUnit(2);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, m_texture_target, m_texture_id, 0);
|
||||
EnableUnit(0);
|
||||
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT1);
|
||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
if (m_format == GL_RGBA8)
|
||||
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);
|
||||
}
|
||||
|
||||
Save(fn, image, pitch);
|
||||
if (status) Save(fn, image, pitch);
|
||||
free(image);
|
||||
|
||||
return true;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ class GSTextureOGL : public GSTexture
|
|||
private:
|
||||
GLenum m_texture_target; // texture target: 2D, rectangle etc...
|
||||
GLuint m_texture_id; // the texture id
|
||||
uint m_extra_buffer_id;
|
||||
uint m_pbo_id;
|
||||
int m_pbo_size;
|
||||
GLuint m_fbo_read;
|
||||
|
||||
|
@ -49,4 +49,5 @@ class GSTextureOGL : public GSTexture
|
|||
bool IsDss() { return (m_type == GSTexture::DepthStencil); }
|
||||
|
||||
GLuint GetID() { return m_texture_id; }
|
||||
GLenum GetTarget() { return m_texture_target; }
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue