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:
gregory.hainaut 2012-03-05 20:16:26 +00:00
parent 92f2ab38ae
commit d6e7ea4a4e
5 changed files with 116 additions and 74 deletions

View File

@ -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};

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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; }
};