gsdx-ogl: LINUX-ONLY

* implement offscreen and cache (mostly a copy past of dx)
* add the missing macro selector of the shader...


git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@5009 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2011-12-23 12:32:40 +00:00
parent 6f5ac7b788
commit 33a9ac370a
4 changed files with 87 additions and 61 deletions

View File

@ -526,12 +526,22 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
{
// FIXME I need to clarify this FBO attachment stuff
// I would like to avoid FBO for a basic clean operation
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
// FIXME can you clean depth and stencil separately
glClearBufferfv(GL_DEPTH, 0, &c);
}
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
{
// FIXME I need to clarify this FBO attachment stuff
// I would like to avoid FBO for a basic clean operation
OMSetFBO(m_fbo);
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
GLint color = c;
// FIXME can you clean depth and stencil separately
glClearBufferiv(GL_STENCIL, 0, &color);
}
@ -558,56 +568,45 @@ GSTexture* GSDeviceOGL::CreateOffscreen(int w, int h, int format)
// blit a texture into an offscreen buffer
GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
// I'm not sure about the object type for offscreen buffer
// TODO later;
assert(0);
// Need to find format equivalent. Then I think it will be straight forward
// A four-component, 32-bit unsigned-normalized-integer format that supports 8 bits per channel including alpha.
// DXGI_FORMAT_R8G8B8A8_UNORM <=> GL_RGBA8
// A single-component, 16-bit unsigned-integer format that supports 16 bits for the red channel
// DXGI_FORMAT_R16_UINT <=> GL_R16
#if 0
GSTexture* dst = NULL;
if(format == 0)
{
format = DXGI_FORMAT_R8G8B8A8_UNORM;
}
if(format == 0) format = GL_RGBA8;
if(format != DXGI_FORMAT_R8G8B8A8_UNORM && format != DXGI_FORMAT_R16_UINT)
if(format != GL_RGBA8 && format != GL_R16UI)
{
ASSERT(0);
return false;
}
if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
// FIXME: I used directly an offscreen texture because they are the same on Opengl
//if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
GSTexture* rt = CreateRenderTarget(w, h, false, format);
if(rt)
{
GSVector4 dr(0, 0, w, h);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
StretchRect(src2, sr, rt, dr, m_convert.ps[format == GL_R16UI ? 1 : 0]);
if(src2 != src) Recycle(src2);
}
#if 0
dst = CreateOffscreen(w, h, format);
if(dst)
{
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
}
#endif
Recycle(rt);
}
return dst;
#endif
//return dst;
return rt;
}
// Copy a sub part of a texture into another
@ -622,12 +621,19 @@ void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
return;
}
// This function is useless on opengl. The only call I found copy the whole texture data to another one
assert(0);
// GL_NV_copy_image seem like the good extension but not supported on AMD...
// Maybe opengl 4.3 !
// FIXME check those function work as expected
// 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());
#if 0
// FIXME attach the texture to the FBO
GSTextureOGL* st_ogl = (GSTextureOGL*) st;
GSTextureOGL* dt_ogl = (GSTextureOGL*) dt;
@ -643,6 +649,7 @@ void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
//glCopyTexSubImage2D(dt_ogl.m_texture_target, 0, 0, 0, r.left, r.bottom, r.right-r.left, r.top-r.bottom);
// FIXME I'm not sure GL_TEXTURE_RECTANGLE is supported!!!
//glCopyTexSubImage2D(GL_TEXTURE_RECTANGLE, 0, 0, 0, r.left, r.bottom, r.right-r.left, r.top-r.bottom);
#endif
#if 0
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
m_ctx->CopySubresourceRegion(*(GSTexture11*)dt, 0, 0, 0, 0, *(GSTexture11*)st, 0, &box);
@ -819,7 +826,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
// gs
GSSetShader(NULL);
GSSetShader(0);
// ps
@ -1153,7 +1160,7 @@ void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const st
// Select the entry point ie the main function
std::string entry_main = format("#define %s main\n", entry.c_str());
std::string header = version + shader_type + entry_main;
std::string header = version + shader_type + entry_main + macro_sel;
// *****************************************************
// Read the source file

View File

@ -30,11 +30,9 @@ GSTextureCacheOGL::GSTextureCacheOGL(GSRenderer* r)
void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
{
// Except format (CopyOffscreen method), everything else seem portable
#if 0
if(t->m_type != RenderTarget)
{
// TODO
assert(0);
return;
}
@ -63,7 +61,10 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
GLuint format = TEX0.PSM == PSM_PSMCT16 || TEX0.PSM == PSM_PSMCT16S ? GL_R16UI : GL_RGBA8;
#if 0
DXGI_FORMAT format = TEX0.PSM == PSM_PSMCT16 || TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
#endif
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format))
{
@ -94,8 +95,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
offscreen->Unmap();
}
m_renderer->m_dev->Recycle(offscreen);
//m_renderer->m_dev->Recycle(offscreen);
}
#endif
}

View File

@ -28,7 +28,7 @@ static uint g_state_texture_id = 0;
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
: m_texture_unit(0),
m_extra_buffer_id(0),
m_extra_buffer_allocated(false)
m_pbo_size(0)
{
// *************************************************************
// Opengl world
@ -83,6 +83,16 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
// Generate the buffer
switch (m_type) {
case GSTexture::Offscreen:
//FIXME I not sure we need a pixel buffer object. It seems more a texture
// glGenBuffers(1, &m_texture_id);
// m_texture_target = GL_PIXEL_UNPACK_BUFFER;
// assert(0);
// Note there is also a buffer texture!!!
// http://www.opengl.org/wiki/Buffer_Texture
// Note: in this case it must use in GLSL
// gvec texelFetch(gsampler sampler, ivec texCoord, int lod[, int sample]);
// corollary we can maybe use it for multisample stuff
case GSTexture::Texture:
case GSTexture::RenderTarget:
glGenTextures(1, &m_texture_id);
@ -92,16 +102,6 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
glGenRenderbuffers(1, &m_texture_id);
m_texture_target = GL_RENDERBUFFER;
break;
case GSTexture::Offscreen:
//FIXME I not sure we need a pixel buffer object. It seems more a texture
// glGenBuffers(1, &m_texture_id);
// m_texture_target = GL_PIXEL_UNPACK_BUFFER;
assert(0);
// Note there is also a buffer texture!!!
// http://www.opengl.org/wiki/Buffer_Texture
// Note: in this case it must use in GLSL
// gvec texelFetch(gsampler sampler, ivec texCoord, int lod[, int sample]);
// corollary we can maybe use it for multisample stuff
break;
case GSTexture::Backbuffer:
m_texture_target = 0;
@ -140,7 +140,12 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
assert(0); // TODO Later
break;
case GSTexture::Offscreen:
assert(0);
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);
break;
default: break;
}
@ -197,19 +202,18 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
// The case appears on SW mode. Src pitch is 2x dst pitch.
int rowbytes = r.width() << 2;
if (pitch != rowbytes) {
uint32 pbo_size = m_size.x * m_size.y * 4;
uint32 map_flags = GL_MAP_WRITE_BIT;
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_extra_buffer_id);
if (!m_extra_buffer_allocated) {
glBufferData(GL_PIXEL_UNPACK_BUFFER, pbo_size, NULL, GL_STREAM_DRAW);
m_extra_buffer_allocated = true;
if (!m_pbo_size) {
m_pbo_size = m_size.x * m_size.y * 4;
glBufferData(GL_PIXEL_UNPACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW);
} else {
GL_MAP_INVALIDATE_BUFFER_BIT;
}
uint8* src = (uint8*) data;
uint8* dst = (uint8*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, pbo_size, map_flags);
uint8* dst = (uint8*) glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, m_pbo_size, map_flags);
for(int h = r.height(); h > 0; h--, src += pitch, dst += rowbytes)
{
memcpy(dst, src, rowbytes);
@ -274,6 +278,26 @@ 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
// Load the PBO
if (m_format == GL_R16UI)
glReadPixels(0, 0, m_size.x, m_size.y, GL_RED, GL_UNSIGNED_SHORT, 0);
else if (m_format == GL_RGBA8)
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, 0);
else
assert(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.pitch = m_size.x;
return true;
}
return false;
#if 0
if(r != NULL)
@ -302,14 +326,9 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
void GSTextureOGL::Unmap()
{
// copy the texture to the GPU
// GLboolean glUnmapBuffer(GLenum target);
#if 0
if(m_texture)
{
m_ctx->Unmap(m_texture, 0);
if (m_type == GSTexture::Offscreen) {
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
}
#endif
}
#ifndef _WINDOWS
@ -358,13 +377,13 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
// Collect the texture data
char* image = (char*)malloc(4 * m_size.x * m_size.y);
if (m_type) {
EnableUnit(0);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
} else {
if (IsBackbuffer()) {
// TODO backbuffer
glReadBuffer(GL_BACK);
glReadPixels(0, 0, m_size.x, m_size.y, GL_RGBA, GL_UNSIGNED_BYTE, image);
} else {
EnableUnit(0);
glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
}
// Build a BMP file

View File

@ -30,7 +30,7 @@ class GSTextureOGL : public GSTexture
GLuint m_texture_id; // the texture id
uint m_texture_unit; // the texture unit offset
uint m_extra_buffer_id;
bool m_extra_buffer_allocated;
int m_pbo_size;
public:
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format);