mirror of https://github.com/PCSX2/pcsx2.git
GSdx: more opengl code, please review, I have no idea if it done the right way ^_^
git-svn-id: http://pcsx2.googlecode.com/svn/trunk@1372 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
c60095f6b0
commit
48eae0c907
|
@ -32,7 +32,6 @@ GPURendererSW::GPURendererSW(GSDevice* dev)
|
|||
|
||||
GPURendererSW::~GPURendererSW()
|
||||
{
|
||||
m_rl.Terminate();
|
||||
}
|
||||
|
||||
void GPURendererSW::ResetDevice()
|
||||
|
|
|
@ -167,8 +167,15 @@ void GSDevice::Merge(GSTexture* st[2], GSVector4* sr, GSVector4* dr, const GSVec
|
|||
// KH:COM crashes at startup when booting *through the bios* due to m_merge being NULL.
|
||||
// (texture appears to be non-null, and is being re-created at a size around like 1700x340,
|
||||
// dunno if that's relevant) -- air
|
||||
if( m_merge )
|
||||
|
||||
if(m_merge)
|
||||
{
|
||||
DoMerge(st, sr, dr, m_merge, slbg, mmod, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("GSdx: m_merge is NULL!\n");
|
||||
}
|
||||
|
||||
m_current = m_merge;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
, m_vbo(0)
|
||||
, m_fbo(0)
|
||||
, m_topology(-1)
|
||||
, m_rt((GLuint)-1)
|
||||
, m_ds((GLuint)-1)
|
||||
{
|
||||
m_vertices.stride = 0;
|
||||
m_vertices.start = 0;
|
||||
|
@ -110,10 +112,26 @@ bool GSDeviceOGL::Create(GSWnd* wnd, bool vsync)
|
|||
return false;
|
||||
}
|
||||
|
||||
// const char* exts = (const char*)glGetString(GL_EXTENSIONS);
|
||||
#ifdef _WINDOWS
|
||||
|
||||
glGenBuffers(1, &m_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
if(WGLEW_EXT_swap_control)
|
||||
{
|
||||
wglSwapIntervalEXT(vsync ? 1 : 0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
const char* vendor = (const char*)glGetString(GL_VENDOR);
|
||||
const char* renderer = (const char*)glGetString(GL_RENDERER);
|
||||
const char* version = (const char*)glGetString(GL_VERSION);
|
||||
const char* exts = (const char*)glGetString(GL_EXTENSIONS);
|
||||
|
||||
printf("%s, %s, OpenGL %s\n", vendor, renderer, version);
|
||||
|
||||
const char* str = strstr(exts, "ARB_texture_non_power_of_two");
|
||||
|
||||
glGenBuffers(1, &m_vbo); CheckError();
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo); CheckError();
|
||||
// TODO: setup layout?
|
||||
|
||||
GSVector4i r = wnd->GetClientRect();
|
||||
|
@ -128,33 +146,40 @@ bool GSDeviceOGL::Reset(int w, int h, bool fs)
|
|||
if(!__super::Reset(w, h, fs))
|
||||
return false;
|
||||
|
||||
m_backbuffer = new GSTextureOGL(0, GSTexture::RenderTarget, w, h);
|
||||
glCullFace(GL_FRONT_AND_BACK); CheckError();
|
||||
glDisable(GL_LIGHTING); CheckError();
|
||||
glDisable(GL_ALPHA_TEST); CheckError();
|
||||
glEnable(GL_SCISSOR_TEST); CheckError();
|
||||
|
||||
glCullFace(GL_FRONT_AND_BACK);
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glMatrixMode(GL_PROJECTION); CheckError();
|
||||
glLoadIdentity(); CheckError();
|
||||
glMatrixMode(GL_MODELVIEW); CheckError();
|
||||
glLoadIdentity(); CheckError();
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
|
||||
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); CheckError();
|
||||
|
||||
// glViewport(0, 0, w, h);
|
||||
|
||||
if(m_fbo) {glDeleteFramebuffersEXT(1, &m_fbo); m_fbo = 0;}
|
||||
|
||||
glGenFramebuffers(1, &m_fbo);
|
||||
glGenFramebuffers(1, &m_fbo); CheckError();
|
||||
|
||||
if(m_fbo == 0) return false;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); CheckError();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::Present(const GSVector4i& r, int shader)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); CheckError();
|
||||
|
||||
// TODO: m_current => backbuffer
|
||||
|
||||
Flip();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::Flip()
|
||||
{
|
||||
#ifdef _WINDOWS
|
||||
|
@ -170,7 +195,7 @@ void GSDeviceOGL::BeginScene()
|
|||
|
||||
void GSDeviceOGL::DrawPrimitive()
|
||||
{
|
||||
glDrawArrays(m_topology, m_vertices.count, m_vertices.start);
|
||||
glDrawArrays(m_topology, m_vertices.count, m_vertices.start); CheckError();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::EndScene()
|
||||
|
@ -181,10 +206,21 @@ void GSDeviceOGL::EndScene()
|
|||
|
||||
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
||||
{
|
||||
GLuint texture = *(GSTextureOGL*)t;
|
||||
|
||||
if(texture == 0)
|
||||
{
|
||||
// TODO: backbuffer
|
||||
}
|
||||
else
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, texture); CheckError();
|
||||
}
|
||||
|
||||
// TODO: disable scissor, color mask
|
||||
|
||||
glClearColor(c.r, c.g, c.b, c.a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glClearColor(c.r, c.g, c.b, c.a); CheckError();
|
||||
glClear(GL_COLOR_BUFFER_BIT); CheckError();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
|
||||
|
@ -194,18 +230,22 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
|
|||
|
||||
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, *(GSTextureOGL*)t); CheckError();
|
||||
|
||||
// TODO: disable scissor, depth mask
|
||||
|
||||
glClearDepth(c);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
glClearDepth(c); CheckError();
|
||||
glClear(GL_DEPTH_BUFFER_BIT); CheckError();
|
||||
}
|
||||
|
||||
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX, *(GSTextureOGL*)t); CheckError();
|
||||
|
||||
// TODO: disable scissor, depth (?) mask
|
||||
|
||||
glClearStencil((GLint)c);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
glClearStencil((GLint)c); CheckError();
|
||||
glClear(GL_STENCIL_BUFFER_BIT); CheckError();
|
||||
}
|
||||
|
||||
GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format)
|
||||
|
@ -215,20 +255,20 @@ GSTexture* GSDeviceOGL::Create(int type, int w, int h, int format)
|
|||
switch(type)
|
||||
{
|
||||
case GSTexture::RenderTarget:
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glGenTextures(1, &texture); CheckError();
|
||||
glBindTexture(GL_TEXTURE_2D, texture); CheckError();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CheckError();
|
||||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
glGenRenderbuffersEXT(1, &texture);
|
||||
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, texture);
|
||||
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH32F_STENCIL8, w, h);
|
||||
glGenRenderbuffers(1, &texture); CheckError();
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, texture); CheckError();
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH32F_STENCIL8, w, h); CheckError();
|
||||
// TODO: depth textures?
|
||||
break;
|
||||
case GSTexture::Texture:
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||
glGenTextures(1, &texture); CheckError();
|
||||
glBindTexture(GL_TEXTURE_2D, texture); CheckError();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); CheckError();
|
||||
break;
|
||||
case GSTexture::Offscreen:
|
||||
// TODO: ???
|
||||
|
@ -298,34 +338,41 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
|
|||
{
|
||||
ASSERT(m_vertices.count == 0);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_vbo); CheckError();
|
||||
|
||||
bool growbuffer = false;
|
||||
bool discard = false; // in opengl 3.x this should be a flag to glMapBuffer, as I read somewhere
|
||||
|
||||
if(count * stride > m_vertices.limit * m_vertices.stride)
|
||||
{
|
||||
m_vertices.start = 0;
|
||||
m_vertices.count = 0;
|
||||
m_vertices.limit = 0;
|
||||
}
|
||||
|
||||
if(m_vertices.limit == 0)
|
||||
{
|
||||
m_vertices.limit = max(count * 3 / 2, 10000);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_DYNAMIC_DRAW); // GL_STREAM_DRAW?
|
||||
growbuffer = true;
|
||||
}
|
||||
|
||||
if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride)
|
||||
{
|
||||
m_vertices.start = 0; // TODO: how to discard and not overwrite previous data?
|
||||
m_vertices.start = 0;
|
||||
|
||||
discard = true;
|
||||
}
|
||||
|
||||
if(growbuffer || discard)
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit * stride, NULL, GL_DYNAMIC_DRAW); CheckError(); // GL_STREAM_DRAW?
|
||||
}
|
||||
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_vertices.start * stride, count * stride, vertices); CheckError();
|
||||
/*
|
||||
if(GLvoid* v = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY))
|
||||
{
|
||||
GSVector4i::storent((uint8*)v + m_vertices.start * stride, vertices, count * stride);
|
||||
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER); CheckError();
|
||||
}
|
||||
|
||||
*/
|
||||
m_vertices.count = count;
|
||||
m_vertices.stride = stride;
|
||||
}
|
||||
|
@ -340,3 +387,25 @@ void GSDeviceOGL::IASetPrimitiveTopology(int topology)
|
|||
m_topology = topology;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds)
|
||||
{
|
||||
GLuint rti = 0;
|
||||
GLuint dsi = 0;
|
||||
|
||||
if(rt) rti = *(GSTextureOGL*)rt;
|
||||
if(ds) dsi = *(GSTextureOGL*)ds;
|
||||
|
||||
// TODO: if(m_rt != rti)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rti); CheckError();
|
||||
|
||||
// TODO: m_rt = rti;
|
||||
}
|
||||
|
||||
// TODO: if(m_ds != dsi)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT, dsi); CheckError();
|
||||
|
||||
// TODO: m_ds = dsi;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ class GSDeviceOGL : public GSDevice
|
|||
} m_vertices;
|
||||
|
||||
int m_topology;
|
||||
GLuint m_rt;
|
||||
GLuint m_ds;
|
||||
|
||||
//
|
||||
|
||||
|
@ -62,6 +64,7 @@ public:
|
|||
bool Create(GSWnd* wnd, bool vsync);
|
||||
bool Reset(int w, int h, bool fs);
|
||||
|
||||
void Present(const GSVector4i& r, int shader);
|
||||
void Flip();
|
||||
|
||||
void BeginScene();
|
||||
|
@ -85,4 +88,30 @@ public:
|
|||
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);
|
||||
void IASetInputLayout(); // TODO
|
||||
void IASetPrimitiveTopology(int topology);
|
||||
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds);
|
||||
|
||||
static void CheckError()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
|
||||
GLenum error = glGetError();
|
||||
|
||||
if(error != GL_NO_ERROR)
|
||||
{
|
||||
printf("%s\n", gluErrorString(error));
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
static void CheckFrameBuffer()
|
||||
{
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
|
||||
|
||||
if(status != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
printf("%d\n", status);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -823,12 +823,9 @@ GSRasterizerMT::GSRasterizerMT(IDrawScanline* ds, int id, int threads, long* syn
|
|||
}
|
||||
}
|
||||
|
||||
GSRasterizerMT::~GSRasterizerMT() {}
|
||||
|
||||
void GSRasterizerMT::Terminate()
|
||||
GSRasterizerMT::~GSRasterizerMT()
|
||||
{
|
||||
m_exit = true;
|
||||
CloseThread();
|
||||
}
|
||||
|
||||
void GSRasterizerMT::Draw(const GSRasterizerData* data)
|
||||
|
@ -879,15 +876,9 @@ GSRasterizerList::GSRasterizerList()
|
|||
|
||||
GSRasterizerList::~GSRasterizerList()
|
||||
{
|
||||
_aligned_free(m_sync);
|
||||
}
|
||||
FreeRasterizers();
|
||||
|
||||
void GSRasterizerList::Terminate()
|
||||
{
|
||||
for(list<IRasterizer*>::iterator i = begin(); i != end(); i++)
|
||||
{
|
||||
(*i)->Terminate();
|
||||
}
|
||||
_aligned_free(m_sync);
|
||||
}
|
||||
|
||||
void GSRasterizerList::FreeRasterizers()
|
||||
|
|
|
@ -43,7 +43,6 @@ public:
|
|||
|
||||
virtual void Draw(const GSRasterizerData* data) = 0;
|
||||
virtual void GetStats(GSRasterizerStats& stats) = 0;
|
||||
virtual void Terminate() = 0;
|
||||
virtual void PrintStats() = 0;
|
||||
};
|
||||
|
||||
|
@ -102,7 +101,6 @@ public:
|
|||
void Draw(const GSRasterizerData* data);
|
||||
void GetStats(GSRasterizerStats& stats);
|
||||
void PrintStats() {m_ds->PrintStats();}
|
||||
void Terminate() {}
|
||||
};
|
||||
|
||||
class GSRasterizerMT : public GSRasterizer, private GSThread
|
||||
|
@ -120,7 +118,6 @@ public:
|
|||
// IRasterizer
|
||||
|
||||
void Draw(const GSRasterizerData* data);
|
||||
void Terminate();
|
||||
};
|
||||
|
||||
class GSRasterizerList : protected list<IRasterizer*>, public IRasterizer
|
||||
|
@ -151,5 +148,4 @@ public:
|
|||
void Draw(const GSRasterizerData* data);
|
||||
void GetStats(GSRasterizerStats& stats);
|
||||
void PrintStats();
|
||||
void Terminate();
|
||||
};
|
||||
|
|
|
@ -38,8 +38,6 @@ GSRendererSW::GSRendererSW(uint8* base, bool mt, void (*irq)(), GSDevice* dev)
|
|||
|
||||
GSRendererSW::~GSRendererSW()
|
||||
{
|
||||
m_rl.Terminate();
|
||||
|
||||
delete m_tc;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "stdafx.h"
|
||||
#include "GSTextureOGL.h"
|
||||
#include "GSDeviceOGL.h"
|
||||
|
||||
GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int format)
|
||||
: m_texture(texture)
|
||||
|
@ -29,19 +30,27 @@ GSTextureOGL::GSTextureOGL(GLuint texture, int type, int width, int height, int
|
|||
, m_height(height)
|
||||
, m_format(format)
|
||||
{
|
||||
// TODO: offscreen type should be just a memory array, also returned in Map
|
||||
|
||||
glGenBuffers(1, &m_pbo); GSDeviceOGL::CheckError();
|
||||
}
|
||||
|
||||
GSTextureOGL::~GSTextureOGL()
|
||||
{
|
||||
if(m_pbo)
|
||||
{
|
||||
glDeleteBuffers(1, &m_pbo); GSDeviceOGL::CheckError();
|
||||
}
|
||||
|
||||
if(m_texture)
|
||||
{
|
||||
switch(m_type)
|
||||
{
|
||||
case DepthStencil:
|
||||
glDeleteRenderbuffersEXT(1, &m_texture);
|
||||
glDeleteRenderbuffers(1, &m_texture); GSDeviceOGL::CheckError();
|
||||
break;
|
||||
default:
|
||||
glDeleteTextures(1, &m_texture);
|
||||
glDeleteTextures(1, &m_texture); GSDeviceOGL::CheckError();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +78,32 @@ int GSTextureOGL::GetFormat() const
|
|||
|
||||
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
||||
{
|
||||
// TODO: glTexSubImage2D looks like UpdateSubresource but does not take a pitch
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, m_pbo); GSDeviceOGL::CheckError();
|
||||
|
||||
int w = r.width();
|
||||
int h = r.height();
|
||||
int bpp = 32; // TODO: should be in sync with m_format
|
||||
int dstpitch = w * bpp >> 3;
|
||||
|
||||
glBufferData(GL_PIXEL_UNPACK_BUFFER, h * dstpitch, NULL, GL_STREAM_DRAW); GSDeviceOGL::CheckError();
|
||||
|
||||
if(uint8* dst = (uint8*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY))
|
||||
{
|
||||
uint8* src = (uint8*)data;
|
||||
|
||||
for(int i = 0; i < h; i++, src += pitch, dst += dstpitch)
|
||||
{
|
||||
memcpy(dst, src, dstpitch);
|
||||
}
|
||||
|
||||
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); GSDeviceOGL::CheckError();
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture); GSDeviceOGL::CheckError();
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, r.left, r.top, w, h, GL_RGBA, GL_UNSIGNED_BYTE, 0); GSDeviceOGL::CheckError();
|
||||
|
||||
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); GSDeviceOGL::CheckError();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
class GSTextureOGL : public GSTexture
|
||||
{
|
||||
GLuint m_texture;
|
||||
GLuint m_pbo;
|
||||
|
||||
int m_type;
|
||||
int m_width;
|
||||
|
@ -45,4 +46,6 @@ public:
|
|||
bool Map(GSMap& m, const GSVector4i* r);
|
||||
void Unmap();
|
||||
bool Save(const string& fn, bool dds = false);
|
||||
|
||||
operator GLuint() {return m_texture;}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue