mirror of https://github.com/PCSX2/pcsx2.git
gsdx ogl:
* allow to switch renderer with F9 * skip first frame in stat of the replayer * drop msaa. Fxaa and internal resolution will do the job * move texture attachment from texture object into device object (allow to keep sanely the state) * split the write buffer and attachment setup * completely split sampler and texture input setup * redo GSDeviceOGL::CopyOffscreen to avoid an extra copy. git-svn-id: http://pcsx2.googlecode.com/svn/trunk@5704 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
92487e2618
commit
d3e1e4da0d
|
@ -429,9 +429,17 @@ EXPORT_C_(int) GSopen2(void** dsp, uint32 flags)
|
|||
case 0: renderer = 1; break; // DX9: HW to SW
|
||||
case 4: renderer = 3; break; // DX11: SW to HW
|
||||
case 3: renderer = 4; break; // DX11: HW to SW
|
||||
case 13: renderer = 12; break; // OGL: SW to HW
|
||||
case 12: renderer = 13; break; // OGL: HW to SW
|
||||
default: renderer = best_sw_renderer; // If wasn't using DX (e.g. SDL), use best SW renderer.
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef _LINUX
|
||||
switch(renderer) {
|
||||
case 13: renderer = 12; break; // OGL: SW to HW
|
||||
case 12: renderer = 13; break; // OGL: HW to SW
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1594,23 +1602,27 @@ EXPORT_C GSReplay(char* lpszCmdLine, int renderer)
|
|||
finished--;
|
||||
}
|
||||
|
||||
// Print some nice stats
|
||||
float n = (float)theApp.GetConfig("linux_replay", 1);
|
||||
float mean = 0;
|
||||
float sd = 0;
|
||||
for (auto i = stats.begin(); i != stats.end(); i++) {
|
||||
mean += *i;
|
||||
}
|
||||
mean = mean/n;
|
||||
for (auto i = stats.begin(); i != stats.end(); i++) {
|
||||
sd += pow((*i)-mean, 2);
|
||||
}
|
||||
sd = sqrt(sd/n);
|
||||
if (theApp.GetConfig("linux_replay", 1) > 1) {
|
||||
// Print some nice stats
|
||||
// Skip first frame (shader compilation populate the result)
|
||||
// it divides by 10 the standard deviation...
|
||||
float n = (float)theApp.GetConfig("linux_replay", 1) - 1.0f;
|
||||
float mean = 0;
|
||||
float sd = 0;
|
||||
for (auto i = stats.begin()+1; i != stats.end(); i++) {
|
||||
mean += *i;
|
||||
}
|
||||
mean = mean/n;
|
||||
for (auto i = stats.begin()+1; i != stats.end(); i++) {
|
||||
sd += pow((*i)-mean, 2);
|
||||
}
|
||||
sd = sqrt(sd/n);
|
||||
|
||||
fprintf(stderr, "\n\nMean: %fms\n", mean);
|
||||
fprintf(stderr, "Standard deviation: %fms\n", sd);
|
||||
fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean);
|
||||
fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number);
|
||||
fprintf(stderr, "\n\nMean: %fms\n", mean);
|
||||
fprintf(stderr, "Standard deviation: %fms\n", sd);
|
||||
fprintf(stderr, "Mean by frame: %fms (%ffps)\n", mean/(float)frame_number, 1000.0f*frame_number/mean);
|
||||
fprintf(stderr, "Standard deviatin by frame: %fms\n", sd/(float)frame_number);
|
||||
}
|
||||
|
||||
for(auto i = packets.begin(); i != packets.end(); i++)
|
||||
{
|
||||
|
|
|
@ -24,10 +24,6 @@
|
|||
|
||||
#include "res/glsl_source.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
|
||||
|
@ -54,8 +50,6 @@ GSDeviceOGL::GSDeviceOGL()
|
|||
, m_vb_sr(NULL)
|
||||
, m_shader(NULL)
|
||||
{
|
||||
m_msaa = !!theApp.GetConfig("UserHacks", 0) ? theApp.GetConfig("UserHacks_MSAA", 0) : 0;
|
||||
|
||||
memset(&m_merge_obj, 0, sizeof(m_merge_obj));
|
||||
memset(&m_interlace, 0, sizeof(m_interlace));
|
||||
memset(&m_convert, 0, sizeof(m_convert));
|
||||
|
@ -143,7 +137,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
|
|||
{
|
||||
// A wrapper to call GSTextureOGL, with the different kind of parameter
|
||||
GSTextureOGL* t = NULL;
|
||||
t = new GSTextureOGL(type, w, h, msaa, format, m_fbo_read);
|
||||
t = new GSTextureOGL(type, w, h, format, m_fbo_read);
|
||||
|
||||
switch(type)
|
||||
{
|
||||
|
@ -152,7 +146,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
|
|||
break;
|
||||
case GSTexture::DepthStencil:
|
||||
ClearDepth(t, 0);
|
||||
//FIXME might be need to clear the stencil too
|
||||
// No need to clear the stencil now.
|
||||
break;
|
||||
}
|
||||
return t;
|
||||
|
@ -160,16 +154,7 @@ GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int for
|
|||
|
||||
GSTexture* GSDeviceOGL::FetchSurface(int type, int w, int h, bool msaa, int format)
|
||||
{
|
||||
// FIXME: keep DX code. Do not know how work msaa but not important for the moment
|
||||
// Current config give only 0 or 1
|
||||
#if 0
|
||||
if(m_msaa < 2) {
|
||||
msaa = false;
|
||||
}
|
||||
#endif
|
||||
msaa = false;
|
||||
|
||||
return GSDevice::FetchSurface(type, w, h, msaa, format);
|
||||
return GSDevice::FetchSurface(type, w, h, false, format);
|
||||
}
|
||||
|
||||
bool GSDeviceOGL::Create(GSWnd* wnd)
|
||||
|
@ -180,9 +165,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
if (!GLLoader::check_gl_supported_extension()) return false;
|
||||
}
|
||||
|
||||
// FIXME disable it when code is ready
|
||||
// glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);
|
||||
|
||||
m_window = wnd;
|
||||
|
||||
// ****************************************************************
|
||||
|
@ -281,7 +263,7 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
#endif
|
||||
|
||||
// ****************************************************************
|
||||
// fxaa (bonus)
|
||||
// fxaa
|
||||
// ****************************************************************
|
||||
std::string fxaa_macro = "#define FXAA_GLSL_130 1\n";
|
||||
if (GLLoader::found_GL_ARB_gpu_shader5) {
|
||||
|
@ -320,59 +302,6 @@ bool GSDeviceOGL::Create(GSWnd* wnd)
|
|||
GSVector4i rect = wnd->GetClientRect();
|
||||
Reset(rect.z, rect.w);
|
||||
|
||||
#if 0
|
||||
HRESULT hr = E_FAIL;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
D3D11_BUFFER_DESC bd;
|
||||
D3D11_SAMPLER_DESC sd;
|
||||
D3D11_DEPTH_STENCIL_DESC dsd;
|
||||
D3D11_RASTERIZER_DESC rd;
|
||||
D3D11_BLEND_DESC bsd;
|
||||
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
|
||||
scd.BufferCount = 2;
|
||||
scd.BufferDesc.Width = 1;
|
||||
scd.BufferDesc.Height = 1;
|
||||
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
//scd.BufferDesc.RefreshRate.Numerator = 60;
|
||||
//scd.BufferDesc.RefreshRate.Denominator = 1;
|
||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
scd.OutputWindow = (HWND)m_wnd->GetHandle();
|
||||
scd.SampleDesc.Count = 1;
|
||||
scd.SampleDesc.Quality = 0;
|
||||
|
||||
// Always start in Windowed mode. According to MS, DXGI just "prefers" this, and it's more or less
|
||||
// required if we want to add support for dual displays later on. The fullscreen/exclusive flip
|
||||
// will be issued after all other initializations are complete.
|
||||
|
||||
scd.Windowed = TRUE;
|
||||
|
||||
// NOTE : D3D11_CREATE_DEVICE_SINGLETHREADED
|
||||
// This flag is safe as long as the DXGI's internal message pump is disabled or is on the
|
||||
// same thread as the GS window (which the emulator makes sure of, if it utilizes a
|
||||
// multithreaded GS). Setting the flag is a nice and easy 5% speedup on GS-intensive scenes.
|
||||
|
||||
uint32 flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
|
||||
|
||||
#ifdef DEBUG
|
||||
flags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
D3D_FEATURE_LEVEL level;
|
||||
|
||||
const D3D_FEATURE_LEVEL levels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
};
|
||||
|
||||
hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, flags, levels, countof(levels), D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
|
||||
// hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_REFERENCE, NULL, flags, NULL, 0, D3D11_SDK_VERSION, &scd, &m_swapchain, &m_dev, &level, &m_ctx);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -385,7 +314,7 @@ bool GSDeviceOGL::Reset(int w, int h)
|
|||
// Opengl allocate the backbuffer with the window. The render is done in the backbuffer when
|
||||
// there isn't any FBO. Only a dummy texture is created to easily detect when the rendering is done
|
||||
// in the backbuffer
|
||||
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, false, 0, m_fbo_read);
|
||||
m_backbuffer = new GSTextureOGL(GSTextureOGL::Backbuffer, w, h, 0, m_fbo_read);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -458,7 +387,9 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
|
|||
gl_ClearBufferfv(GL_COLOR, 0, c.v);
|
||||
} else {
|
||||
OMSetFBO(m_fbo);
|
||||
static_cast<GSTextureOGL*>(t)->Attach(GL_COLOR_ATTACHMENT0);
|
||||
// FIXME useful
|
||||
OMSetWriteBuffer();
|
||||
OMAttachRt(t);
|
||||
|
||||
gl_ClearBufferfv(GL_COLOR, 0, c.v);
|
||||
}
|
||||
|
@ -474,7 +405,9 @@ void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
|
|||
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
|
||||
{
|
||||
OMSetFBO(m_fbo);
|
||||
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
// FIXME useful
|
||||
OMSetWriteBuffer();
|
||||
OMAttachDs(t);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
if (m_state.dss != NULL && m_state.dss->IsMaskEnable()) {
|
||||
|
@ -490,7 +423,9 @@ void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
|
|||
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
|
||||
{
|
||||
OMSetFBO(m_fbo);
|
||||
static_cast<GSTextureOGL*>(t)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
// FIXME useful
|
||||
OMSetWriteBuffer();
|
||||
OMAttachDs(t);
|
||||
GLint color = c;
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
@ -608,48 +543,19 @@ 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)
|
||||
{
|
||||
GSTexture* dst = NULL;
|
||||
ASSERT(src);
|
||||
ASSERT(format == GL_RGBA8 || format == GL_R16UI);
|
||||
|
||||
if(format == 0) format = GL_RGBA8;
|
||||
|
||||
if(format != GL_RGBA8 && format != GL_R16UI)
|
||||
{
|
||||
ASSERT(0);
|
||||
if(format != GL_RGBA8 && format != GL_R16UI) return NULL;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
GSTexture* dst = CreateOffscreen(w, h, format);
|
||||
GSVector4 dr(0, 0, w, h);
|
||||
|
||||
// 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)
|
||||
{
|
||||
GSVector4 dr(0, 0, w, h);
|
||||
|
||||
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
|
||||
{
|
||||
StretchRect(src2, sr, rt, dr, m_convert.ps[format == GL_R16UI ? 1 : 0]);
|
||||
|
||||
if(src2 != src) Recycle(src2);
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
Recycle(rt);
|
||||
}
|
||||
StretchRect(src, sr, dst, dr, m_convert.ps[format == GL_R16UI ? 1 : 0]);
|
||||
|
||||
return dst;
|
||||
//return rt;
|
||||
}
|
||||
|
||||
// Copy a sub part of a texture into another
|
||||
|
@ -658,32 +564,23 @@ GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w
|
|||
// From a sub-part to a full texture
|
||||
void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
|
||||
{
|
||||
if(!st || !dt)
|
||||
{
|
||||
ASSERT(0);
|
||||
return;
|
||||
}
|
||||
ASSERT(st && dt);
|
||||
|
||||
// FIXME: the extension was integrated in opengl 4.3 (now we need driver that support OGL4.3)
|
||||
// FIXME check those function work as expected
|
||||
// void CopyImageSubDataNV(
|
||||
// uint32 srcName, enum srcTarget, int srcLevel, int srcX, int srcY, int srcZ,
|
||||
// uint32 dstName, enum dstTarget, int dstLevel, int dstX, int dstY, int dstZ,
|
||||
// sizei width, sizei height, sizei depth);
|
||||
if (GLLoader::found_GL_NV_copy_image) {
|
||||
#ifndef ENABLE_GLES
|
||||
gl_CopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), static_cast<GSTextureOGL*>(st)->GetTarget(),
|
||||
gl_CopyImageSubDataNV( static_cast<GSTextureOGL*>(st)->GetID(), GL_TEXTURE_2D,
|
||||
0, r.x, r.y, 0,
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
|
||||
0, r.x, r.y, 0,
|
||||
r.width(), r.height(), 1);
|
||||
#endif
|
||||
} else if (GLLoader::found_GL_ARB_copy_image) {
|
||||
// Would need an update of GL definition. For the moment it isn't supported by driver anyway.
|
||||
#if 0
|
||||
gl_CopyImageSubData( static_cast<GSTextureOGL*>(st)->GetID(), static_cast<GSTextureOGL*>(st)->GetTarget(),
|
||||
gl_CopyImageSubData( static_cast<GSTextureOGL*>(st)->GetID(), GL_TEXTURE_2D,
|
||||
0, r.x, r.y, 0,
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), static_cast<GSTextureOGL*>(dt)->GetTarget(),
|
||||
static_cast<GSTextureOGL*>(dt)->GetID(), GL_TEXTURE_2D,
|
||||
0, r.x, r.y, 0,
|
||||
r.width(), r.height(), 1);
|
||||
#endif
|
||||
|
@ -694,17 +591,14 @@ void GSDeviceOGL::CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r)
|
|||
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
|
||||
st_ogl->AttachRead(GL_COLOR_ATTACHMENT0);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(st_ogl)->GetID(), 0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
dt_ogl->EnableUnit(6);
|
||||
glCopyTexSubImage2D(dt_ogl->GetTarget(), 0, r.x, r.y, r.x, r.y, r.width(), r.height());
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.x, r.y, r.width(), r.height());
|
||||
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
#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);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
|
||||
|
@ -801,8 +695,8 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
// ps
|
||||
// ************************************
|
||||
|
||||
PSSetShaderResources(st, NULL);
|
||||
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, 0);
|
||||
PSSetShaderResource(0, st);
|
||||
PSSetSamplerState(0, linear ? m_convert.ln : m_convert.pt);
|
||||
m_shader->PS(ps);
|
||||
|
||||
// ************************************
|
||||
|
@ -815,8 +709,6 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
|
|||
// ************************************
|
||||
|
||||
EndScene();
|
||||
|
||||
PSSetShaderResources(NULL, NULL);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
|
||||
|
@ -896,7 +788,7 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
|||
{
|
||||
#ifdef ENABLE_OGL_STENCIL_DEBUG
|
||||
const GSVector2i& size = rt->GetSize();
|
||||
GSTexture* t = CreateRenderTarget(size.x, size.y, rt->IsMSAA());
|
||||
GSTexture* t = CreateRenderTarget(size.x, size.y, false);
|
||||
#else
|
||||
GSTexture* t = NULL;
|
||||
#endif
|
||||
|
@ -928,10 +820,8 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
|||
|
||||
// ps
|
||||
|
||||
GSTexture* rt2 = rt->IsMSAA() ? Resolve(rt) : rt;
|
||||
|
||||
PSSetShaderResources(rt2, NULL);
|
||||
PSSetSamplerState(m_convert.pt, 0);
|
||||
PSSetShaderResource(0, rt);
|
||||
PSSetSamplerState(0, m_convert.pt);
|
||||
m_shader->PS(m_convert.ps[datm ? 2 : 3]);
|
||||
|
||||
//
|
||||
|
@ -943,31 +833,9 @@ void GSDeviceOGL::SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* ver
|
|||
EndScene();
|
||||
|
||||
#ifdef ENABLE_OGL_STENCIL_DEBUG
|
||||
// FIXME invalidate data
|
||||
Recycle(t);
|
||||
#endif
|
||||
|
||||
if(rt2 != rt) Recycle(rt2);
|
||||
}
|
||||
|
||||
// copy a multisample texture to a non-texture multisample. On opengl you need 2 FBO with different level of
|
||||
// sample and then do a blit. Headach expected to for the moment just drop MSAA...
|
||||
GSTexture* GSDeviceOGL::Resolve(GSTexture* t)
|
||||
{
|
||||
ASSERT(t != NULL && t->IsMSAA());
|
||||
#if 0
|
||||
|
||||
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
|
||||
{
|
||||
dst->SetScale(t->GetScale());
|
||||
|
||||
m_ctx->ResolveSubresource(*(GSTexture11*)dst, 0, *(GSTexture11*)t, 0, (DXGI_FORMAT)t->GetFormat());
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GSDeviceOGL::EndScene()
|
||||
|
@ -1018,53 +886,54 @@ void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
|
|||
m_state.vb->SetTopology(topology);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
|
||||
void GSDeviceOGL::PSSetShaderResource(const int i, GSTexture* sr)
|
||||
{
|
||||
PSSetShaderResource(0, sr0);
|
||||
PSSetShaderResource(1, sr1);
|
||||
//PSSetShaderResource(2, NULL);
|
||||
ASSERT(sr);
|
||||
|
||||
static_cast<GSTextureOGL*>(sr)->EnableUnit(i);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetShaderResource(int i, GSTexture* sr)
|
||||
void GSDeviceOGL::PSSetSamplerState(const int i, GLuint ss)
|
||||
{
|
||||
GSTextureOGL* srv = static_cast<GSTextureOGL*>(sr);
|
||||
|
||||
if (m_state.ps_srv[i] != srv)
|
||||
{
|
||||
m_state.ps_srv[i] = srv;
|
||||
if (srv != NULL)
|
||||
m_state.ps_srv[i]->EnableUnit(i);
|
||||
if (m_state.ps_ss[i] != ss) {
|
||||
m_state.ps_ss[i] = ss;
|
||||
gl_BindSampler(i, ss);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2)
|
||||
void GSDeviceOGL::OMAttachRt(GSTexture* rt)
|
||||
{
|
||||
if (m_state.ps_ss[0] != ss0) {
|
||||
m_state.ps_ss[0] = ss0;
|
||||
gl_BindSampler(0, ss0);
|
||||
}
|
||||
if (m_state.ps_ss[1] != ss1) {
|
||||
m_state.ps_ss[1] = ss1;
|
||||
gl_BindSampler(1, ss1);
|
||||
if (m_state.rt != rt) {
|
||||
m_state.rt = rt;
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(rt)->GetID(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetFBO(GLuint fbo, GLenum buffer)
|
||||
void GSDeviceOGL::OMAttachDs(GSTexture* ds)
|
||||
{
|
||||
if (m_state.ds != ds) {
|
||||
m_state.ds = ds;
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, static_cast<GSTextureOGL*>(ds)->GetID(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetFBO(GLuint fbo)
|
||||
{
|
||||
if (m_state.fbo != fbo) {
|
||||
m_state.fbo = fbo;
|
||||
gl_BindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
// FIXME DEBUG
|
||||
//if (fbo) fprintf(stderr, "FB status %x\n", gl_CheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||
}
|
||||
}
|
||||
|
||||
// Note if m_fbo is 0, standard GL_BACK will be used instead
|
||||
if (m_fbo && m_state.draw != buffer) {
|
||||
void GSDeviceOGL::OMSetWriteBuffer(GLenum buffer)
|
||||
{
|
||||
// Note if fbo is 0, standard GL_BACK will be used instead
|
||||
if (m_state.fbo && m_state.draw != buffer) {
|
||||
m_state.draw = buffer;
|
||||
|
||||
GLenum target[1] = {buffer};
|
||||
gl_DrawBuffers(1, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void GSDeviceOGL::OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref)
|
||||
|
@ -1093,16 +962,18 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
|
|||
if (rt == NULL || !static_cast<GSTextureOGL*>(rt)->IsBackbuffer()) {
|
||||
if (rt) {
|
||||
OMSetFBO(m_fbo);
|
||||
static_cast<GSTextureOGL*>(rt)->Attach(GL_COLOR_ATTACHMENT0);
|
||||
OMSetWriteBuffer();
|
||||
OMAttachRt(rt);
|
||||
} else {
|
||||
// Note: NULL rt is only used in DATE so far. Color writing is disabled
|
||||
// on the blend setup
|
||||
OMSetFBO(m_fbo, GL_NONE);
|
||||
OMSetFBO(m_fbo);
|
||||
OMSetWriteBuffer(GL_NONE);
|
||||
}
|
||||
|
||||
// Note: it must be done after OMSetFBO
|
||||
if (ds)
|
||||
static_cast<GSTextureOGL*>(ds)->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
|
||||
OMAttachDs(ds);
|
||||
|
||||
} else {
|
||||
// Render in the backbuffer
|
||||
|
|
|
@ -43,7 +43,6 @@ class GSBlendStateOGL {
|
|||
bool m_g_msk;
|
||||
bool m_a_msk;
|
||||
bool constant_factor;
|
||||
float debug_factor;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -104,7 +103,6 @@ public:
|
|||
if (m_enable) {
|
||||
glEnable(GL_BLEND);
|
||||
if (HasConstantFactor()) {
|
||||
debug_factor = factor;
|
||||
gl_BlendColor(factor, factor, factor, 0);
|
||||
}
|
||||
|
||||
|
@ -114,38 +112,6 @@ public:
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
}
|
||||
|
||||
char* NameOfParam(GLenum p)
|
||||
{
|
||||
switch (p) {
|
||||
case GL_FUNC_ADD: return "ADD";
|
||||
case GL_FUNC_SUBTRACT: return "SUB";
|
||||
case GL_FUNC_REVERSE_SUBTRACT: return "REV SUB";
|
||||
case GL_ONE: return "ONE";
|
||||
case GL_ZERO: return "ZERO";
|
||||
#ifndef ENABLE_GLES
|
||||
case GL_SRC1_ALPHA: return "SRC1 ALPHA";
|
||||
case GL_ONE_MINUS_SRC1_ALPHA: return "1 - SRC1 ALPHA";
|
||||
#endif
|
||||
case GL_SRC_ALPHA: return "SRC ALPHA";
|
||||
case GL_ONE_MINUS_DST_ALPHA: return "1 - DST ALPHA";
|
||||
case GL_DST_ALPHA: return "DST ALPHA";
|
||||
case GL_DST_COLOR: return "DST COLOR";
|
||||
case GL_ONE_MINUS_SRC_ALPHA: return "1 - SRC ALPHA";
|
||||
case GL_CONSTANT_COLOR: return "CST";
|
||||
case GL_ONE_MINUS_CONSTANT_COLOR: return "1 - CST";
|
||||
default: return "UKN";
|
||||
}
|
||||
return "UKN";
|
||||
}
|
||||
|
||||
void debug()
|
||||
{
|
||||
if (!m_enable) return;
|
||||
fprintf(stderr,"Blend op: %s; src:%s; dst:%s\n", NameOfParam(m_equation_RGB), NameOfParam(m_func_sRGB), NameOfParam(m_func_dRGB));
|
||||
if (HasConstantFactor()) fprintf(stderr, "Blend constant: %f\n", debug_factor);
|
||||
fprintf(stderr,"Mask. R:%d B:%d G:%d A:%d\n", m_r_msk, m_b_msk, m_g_msk, m_a_msk);
|
||||
}
|
||||
};
|
||||
|
||||
class GSDepthStencilOGL {
|
||||
|
@ -161,21 +127,6 @@ class GSDepthStencilOGL {
|
|||
const GLuint m_stencil_spass_dfail_op;
|
||||
GLuint m_stencil_spass_dpass_op;
|
||||
|
||||
char* NameOfParam(GLenum p)
|
||||
{
|
||||
switch(p) {
|
||||
case GL_NEVER: return "NEVER";
|
||||
case GL_ALWAYS: return "ALWAYS";
|
||||
case GL_GEQUAL: return "GEQUAL";
|
||||
case GL_GREATER: return "GREATER";
|
||||
case GL_KEEP: return "KEEP";
|
||||
case GL_EQUAL: return "EQUAL";
|
||||
case GL_REPLACE: return "REPLACE";
|
||||
default: return "UKN";
|
||||
}
|
||||
return "UKN";
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
GSDepthStencilOGL() : m_depth_enable(false)
|
||||
|
@ -188,7 +139,11 @@ public:
|
|||
, m_stencil_sfail_op(GL_KEEP)
|
||||
, m_stencil_spass_dfail_op(GL_KEEP)
|
||||
, m_stencil_spass_dpass_op(GL_KEEP)
|
||||
{}
|
||||
{
|
||||
// Only needed once since m_stencil_mask is constant
|
||||
// Control which stencil bitplane are written
|
||||
glStencilMask(m_stencil_mask);
|
||||
}
|
||||
|
||||
void EnableDepth() { m_depth_enable = true; }
|
||||
void EnableStencil() { m_stencil_enable = true; }
|
||||
|
@ -213,27 +168,10 @@ public:
|
|||
// Note: here the mask control which bitplane is considered by the operation
|
||||
glStencilFunc(m_stencil_func, m_stencil_ref, m_stencil_mask);
|
||||
glStencilOp(m_stencil_sfail_op, m_stencil_spass_dfail_op, m_stencil_spass_dpass_op);
|
||||
// FIXME only needed once since m_stencil_mask is constant
|
||||
// Control which stencil bitplane are written
|
||||
glStencilMask(m_stencil_mask);
|
||||
} else
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void debug() { debug_depth(); debug_stencil(); }
|
||||
|
||||
void debug_depth()
|
||||
{
|
||||
if (!m_depth_enable) return;
|
||||
fprintf(stderr, "Depth %s. Mask %x\n", NameOfParam(m_depth_func), m_depth_mask);
|
||||
}
|
||||
|
||||
void debug_stencil()
|
||||
{
|
||||
if (!m_stencil_enable) return;
|
||||
fprintf(stderr, "Stencil %s. Both pass op %s\n", NameOfParam(m_stencil_func), NameOfParam(m_stencil_spass_dpass_op));
|
||||
}
|
||||
|
||||
bool IsMaskEnable() { return m_depth_mask != GL_FALSE; }
|
||||
};
|
||||
|
||||
|
@ -540,26 +478,17 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
struct {
|
||||
GSVertexBufferStateOGL* vb;
|
||||
GLuint vs; // program
|
||||
GSUniformBufferOGL* cb; // uniform current buffer
|
||||
GLuint gs; // program
|
||||
// FIXME texture binding. Maybe not equivalent for the state but the best I could find.
|
||||
GSTextureOGL* ps_srv[3];
|
||||
// ID3D11ShaderResourceView* ps_srv[3];
|
||||
GLuint ps; // program
|
||||
GSUniformBufferOGL* cb;
|
||||
GLuint ps_ss[3]; // sampler
|
||||
GSVector2i viewport;
|
||||
GSVector4i scissor;
|
||||
GSDepthStencilOGL* dss;
|
||||
GSBlendStateOGL* bs;
|
||||
float bf;
|
||||
// FIXME texture attachment in the FBO
|
||||
// ID3D11RenderTargetView* rtv;
|
||||
// ID3D11DepthStencilView* dsv;
|
||||
GSTextureOGL* rtv;
|
||||
GSTextureOGL* dsv;
|
||||
float bf; // blend factor
|
||||
GLuint fbo;
|
||||
GLenum draw;
|
||||
GSTexture* rt; // render target
|
||||
GSTexture* ds; // Depth-Stencil
|
||||
} m_state;
|
||||
|
||||
GSShaderOGL* m_shader;
|
||||
|
@ -580,7 +509,6 @@ class GSDeviceOGL : public GSDevice
|
|||
VSConstantBuffer m_vs_cb_cache;
|
||||
PSConstantBuffer m_ps_cb_cache;
|
||||
|
||||
protected:
|
||||
GSTexture* CreateSurface(int type, int w, int h, bool msaa, int format);
|
||||
GSTexture* FetchSurface(int type, int w, int h, bool msaa, int format);
|
||||
|
||||
|
@ -589,6 +517,11 @@ class GSDeviceOGL : public GSDevice
|
|||
void DoFXAA(GSTexture* st, GSTexture* dt);
|
||||
void DoShadeBoost(GSTexture* st, GSTexture* dt);
|
||||
|
||||
void OMAttachRt(GSTexture* rt);
|
||||
void OMAttachDs(GSTexture* ds);
|
||||
void OMSetFBO(GLuint fbo);
|
||||
void OMSetWriteBuffer(GLenum buffer = GL_COLOR_ATTACHMENT0);
|
||||
|
||||
public:
|
||||
GSDeviceOGL();
|
||||
virtual ~GSDeviceOGL();
|
||||
|
@ -629,8 +562,6 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
void SetupDATE(GSTexture* rt, GSTexture* ds, const GSVertexPT1* vertices, bool datm);
|
||||
|
||||
GSTexture* Resolve(GSTexture* t);
|
||||
|
||||
void EndScene();
|
||||
|
||||
void IASetPrimitiveTopology(GLenum topology);
|
||||
|
@ -642,11 +573,9 @@ class GSDeviceOGL : public GSDevice
|
|||
|
||||
void SetUniformBuffer(GSUniformBufferOGL* cb);
|
||||
|
||||
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
|
||||
void PSSetShaderResource(int i, GSTexture* sr);
|
||||
void PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2 = 0);
|
||||
void PSSetShaderResource(const int i, GSTexture* sr);
|
||||
void PSSetSamplerState(const int i, GLuint ss);
|
||||
|
||||
void OMSetFBO(GLuint fbo, GLenum buffer = GL_COLOR_ATTACHMENT0);
|
||||
void OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref);
|
||||
void OMSetBlendState(GSBlendStateOGL* bs, float bf);
|
||||
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
|
||||
|
@ -665,6 +594,8 @@ class GSDeviceOGL : public GSDevice
|
|||
void SetupIA(const void* vertex, int vertex_count, const uint32* index, int index_count, int prim);
|
||||
void SetupVS(VSSelector sel, const VSConstantBuffer* cb);
|
||||
void SetupGS(GSSelector sel);
|
||||
void SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel);
|
||||
void SetupPS(PSSelector sel, const PSConstantBuffer* cb);
|
||||
void SetupSampler(PSSelector sel, PSSamplerSelector ssel);
|
||||
void SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix);
|
||||
|
||||
};
|
||||
|
|
|
@ -486,6 +486,11 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
ps_ssel.tau = (context->CLAMP.WMS + 3) >> 1;
|
||||
ps_ssel.tav = (context->CLAMP.WMT + 3) >> 1;
|
||||
ps_ssel.ltf = bilinear && simple_sample;
|
||||
|
||||
dev->SetupSampler(ps_sel, ps_ssel);
|
||||
dev->PSSetShaderResource(0, tex->m_texture);
|
||||
if (tex->m_palette)
|
||||
dev->PSSetShaderResource(1, tex->m_palette);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -497,8 +502,6 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
GSVector4i scissor = GSVector4i(GSVector4(rtscale).xyxy() * context->scissor.in).rintersect(GSVector4i(rtsize).zwxy());
|
||||
|
||||
dev->OMSetRenderTargets(rt, ds, &scissor);
|
||||
dev->PSSetShaderResource(0, tex ? tex->m_texture : NULL);
|
||||
dev->PSSetShaderResource(1, tex ? tex->m_palette : NULL);
|
||||
|
||||
uint8 afix = context->ALPHA.FIX;
|
||||
|
||||
|
@ -507,7 +510,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
dev->SetupOM(om_dssel, om_bsel, afix);
|
||||
dev->SetupVS(vs_sel, &vs_cb);
|
||||
dev->SetupGS(gs_sel);
|
||||
dev->SetupPS(ps_sel, &ps_cb, ps_ssel);
|
||||
dev->SetupPS(ps_sel, &ps_cb);
|
||||
|
||||
// draw
|
||||
|
||||
|
@ -524,7 +527,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
ps_selneg.colclip = 2;
|
||||
|
||||
dev->SetupOM(om_dssel, om_bselneg, afix);
|
||||
dev->SetupPS(ps_selneg, &ps_cb, ps_ssel);
|
||||
dev->SetupPS(ps_selneg, &ps_cb);
|
||||
|
||||
dev->DrawIndexedPrimitive();
|
||||
dev->SetupOM(om_dssel, om_bsel, afix);
|
||||
|
@ -539,7 +542,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
|
||||
ps_sel.atst = iatst[ps_sel.atst];
|
||||
|
||||
dev->SetupPS(ps_sel, &ps_cb, ps_ssel);
|
||||
dev->SetupPS(ps_sel, &ps_cb);
|
||||
|
||||
bool z = om_dssel.zwe;
|
||||
bool r = om_bsel.wr;
|
||||
|
@ -577,7 +580,7 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour
|
|||
ps_selneg.colclip = 2;
|
||||
|
||||
dev->SetupOM(om_dssel, om_bselneg, afix);
|
||||
dev->SetupPS(ps_selneg, &ps_cb, ps_ssel);
|
||||
dev->SetupPS(ps_selneg, &ps_cb);
|
||||
|
||||
dev->DrawIndexedPrimitive();
|
||||
}
|
||||
|
|
|
@ -318,6 +318,8 @@ std::string GSShaderOGL::GenGlslHeader(const std::string& entry, GLenum type, co
|
|||
|
||||
GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& entry, GLenum type, const char* glsl_h_code, const std::string& macro_sel)
|
||||
{
|
||||
ASSERT(glsl_h_code != NULL);
|
||||
|
||||
GLuint program = 0;
|
||||
|
||||
#ifndef ENABLE_GLES
|
||||
|
@ -331,26 +333,22 @@ GLuint GSShaderOGL::Compile(const std::string& glsl_file, const std::string& ent
|
|||
const char* sources[2];
|
||||
|
||||
std::string header = GenGlslHeader(entry, type, macro_sel);
|
||||
int shader_nb = 1;
|
||||
#if 0
|
||||
sources[0] = header.c_str();
|
||||
|
||||
if (glsl_h_code)
|
||||
sources[1] = glsl_h_code;
|
||||
else
|
||||
sources[1] = '\0';
|
||||
sources[1] = glsl_h_code;
|
||||
shader_nb++;
|
||||
#else
|
||||
sources[0] = header.append(glsl_h_code).c_str();
|
||||
#endif
|
||||
|
||||
if (m_sso) {
|
||||
#ifndef ENABLE_GLES
|
||||
#if 0
|
||||
const GLchar* ShaderSource[1];
|
||||
ShaderSource[0] = header.append(glsl_h_code).c_str();
|
||||
program = gl_CreateShaderProgramv(type, 1, &ShaderSource[0]);
|
||||
#else
|
||||
program = gl_CreateShaderProgramv(type, 2, sources);
|
||||
#endif
|
||||
program = gl_CreateShaderProgramv(type, shader_nb, sources);
|
||||
#endif
|
||||
} else {
|
||||
program = gl_CreateShader(type);
|
||||
gl_ShaderSource(program, 2, sources, NULL);
|
||||
gl_ShaderSource(program, shader_nb, sources, NULL);
|
||||
gl_CompileShader(program);
|
||||
}
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
|
|||
{
|
||||
if(t->m_type != RenderTarget)
|
||||
{
|
||||
assert(0);
|
||||
ASSERT(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -96,6 +96,7 @@ void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
|
|||
offscreen->Unmap();
|
||||
}
|
||||
|
||||
// FIXME invalidate data
|
||||
m_renderer->m_dev->Recycle(offscreen);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -151,7 +151,7 @@ void GSDeviceOGL::SetupGS(GSSelector sel)
|
|||
m_shader->GS(gs);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerSelector ssel)
|
||||
void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb)
|
||||
{
|
||||
// *************************************************************
|
||||
// Static
|
||||
|
@ -174,25 +174,18 @@ void GSDeviceOGL::SetupPS(PSSelector sel, const PSConstantBuffer* cb, PSSamplerS
|
|||
m_ps_cb->upload(cb);
|
||||
}
|
||||
|
||||
GLuint ss0, ss1;
|
||||
ss0 = ss1 = 0;
|
||||
if(sel.tfx != 4)
|
||||
m_shader->PS(ps);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupSampler(PSSelector sel, PSSamplerSelector ssel)
|
||||
{
|
||||
if(!(sel.fmt < 3 && sel.wms < 3 && sel.wmt < 3))
|
||||
{
|
||||
if(!(sel.fmt < 3 && sel.wms < 3 && sel.wmt < 3))
|
||||
{
|
||||
ssel.ltf = 0;
|
||||
}
|
||||
|
||||
ss0 = m_ps_ss[ssel];
|
||||
|
||||
if(sel.fmt >= 3)
|
||||
{
|
||||
ss1 = m_palette_ss;
|
||||
}
|
||||
ssel.ltf = 0;
|
||||
}
|
||||
|
||||
PSSetSamplerState(ss0, ss1, 0);
|
||||
m_shader->PS(ps);
|
||||
PSSetSamplerState(0, m_ps_ss[ssel]);
|
||||
PSSetSamplerState(1, m_palette_ss);
|
||||
}
|
||||
|
||||
void GSDeviceOGL::SetupOM(OMDepthStencilSelector dssel, OMBlendSelector bsel, uint8 afix)
|
||||
|
|
|
@ -24,17 +24,14 @@
|
|||
#include "GSTextureOGL.h"
|
||||
static GLuint g_state_texture_unit = -1;
|
||||
static GLuint g_state_texture_id[7] = {0, 0, 0, 0, 0, 0, 0};
|
||||
static GLuint g_color0 = 0;
|
||||
static GLuint g_color1 = 0;
|
||||
static GLuint g_depth = 0;
|
||||
|
||||
// FIXME: check if it possible to always use those setup by default
|
||||
// glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
// glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
|
||||
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read)
|
||||
GSTextureOGL::GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read)
|
||||
: m_pbo_id(0),
|
||||
m_pbo_size(0)
|
||||
m_pbo_size(0)
|
||||
{
|
||||
// *************************************************************
|
||||
// Opengl world
|
||||
|
@ -62,15 +59,14 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
m_size.y = max(1,h);
|
||||
m_format = format;
|
||||
m_type = type;
|
||||
m_msaa = msaa;
|
||||
m_fbo_read = fbo_read;
|
||||
m_texture_id = 0;
|
||||
|
||||
// Generate the buffer
|
||||
switch (m_type) {
|
||||
case GSTexture::Offscreen:
|
||||
//FIXME I not sure we need a pixel buffer object. It seems more a texture
|
||||
// gl_GenBuffers(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
|
||||
|
@ -81,11 +77,8 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
case GSTexture::RenderTarget:
|
||||
case GSTexture::DepthStencil:
|
||||
glGenTextures(1, &m_texture_id);
|
||||
m_texture_target = GL_TEXTURE_2D;
|
||||
break;
|
||||
case GSTexture::Backbuffer:
|
||||
m_texture_target = 0;
|
||||
m_texture_id = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -93,16 +86,6 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
// Extra buffer to handle various pixel transfer
|
||||
gl_GenBuffers(1, &m_pbo_id);
|
||||
|
||||
#if 0
|
||||
uint32 msaa_level;
|
||||
if (m_msaa) {
|
||||
// FIXME which level of MSAA
|
||||
msaa_level = 1;
|
||||
} else {
|
||||
msaa_level = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Allocate the buffer
|
||||
switch (m_type) {
|
||||
case GSTexture::Offscreen:
|
||||
|
@ -117,19 +100,12 @@ GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint
|
|||
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, m_pbo_id);
|
||||
gl_BufferData(GL_PIXEL_PACK_BUFFER, m_pbo_size, NULL, GL_STREAM_DRAW);
|
||||
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
ASSERT(!m_msaa);
|
||||
|
||||
case GSTexture::DepthStencil:
|
||||
case GSTexture::RenderTarget:
|
||||
case GSTexture::Texture:
|
||||
EnableUnit(3);
|
||||
if (m_msaa) {
|
||||
ASSERT(m_texture_target == GL_TEXTURE_2D_MULTISAMPLE);
|
||||
// Require a recent GL4.3 extension
|
||||
//gl_TexStorage2DMultisample(m_texture_target, msaa_level, m_format, m_size.x, m_size.y, false);
|
||||
} else {
|
||||
gl_TexStorage2D(m_texture_target, 1, m_format, m_size.x, m_size.y);
|
||||
}
|
||||
gl_TexStorage2D(GL_TEXTURE_2D, 1, m_format, m_size.x, m_size.y);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
@ -146,45 +122,9 @@ GSTextureOGL::~GSTextureOGL()
|
|||
glDeleteTextures(1, &m_texture_id);
|
||||
}
|
||||
|
||||
void GSTextureOGL::Attach(GLenum attachment)
|
||||
{
|
||||
switch(attachment) {
|
||||
case GL_COLOR_ATTACHMENT0:
|
||||
if (g_color0 != m_texture_id) {
|
||||
g_color0 = m_texture_id;
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
|
||||
}
|
||||
break;
|
||||
case GL_COLOR_ATTACHMENT1:
|
||||
if (g_color1 != m_texture_id) {
|
||||
g_color1 = m_texture_id;
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
|
||||
}
|
||||
break;
|
||||
case GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
if (g_depth != m_texture_id) {
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
|
||||
g_depth = m_texture_id;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
gl_FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME DEBUG
|
||||
//fprintf(stderr, "FB status %x\n", gl_CheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||
}
|
||||
|
||||
void GSTextureOGL::AttachRead(GLenum attachment)
|
||||
{
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
|
||||
glReadBuffer(attachment);
|
||||
}
|
||||
|
||||
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
||||
{
|
||||
if (m_type == GSTexture::DepthStencil || m_type == GSTexture::Offscreen) ASSERT(0);
|
||||
ASSERT(m_type != GSTexture::DepthStencil && m_type != GSTexture::Offscreen);
|
||||
|
||||
// FIXME warning order of the y axis
|
||||
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
|
||||
|
@ -234,7 +174,7 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
|||
}
|
||||
#endif
|
||||
|
||||
glTexSubImage2D(m_texture_target, 0, r.x, r.y, r.width(), r.height(), format, type, data);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, r.x, r.y, r.width(), r.height(), format, type, data);
|
||||
|
||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); // Restore default behavior
|
||||
|
||||
|
@ -253,25 +193,26 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
|
|||
#endif
|
||||
}
|
||||
|
||||
void GSTextureOGL::EnableUnit(uint32 unit)
|
||||
void GSTextureOGL::EnableUnit(const uint32 unit)
|
||||
{
|
||||
/* Not a real texture */
|
||||
if (IsBackbuffer()) {
|
||||
return;
|
||||
}
|
||||
ASSERT(!IsBackbuffer());
|
||||
|
||||
if (g_state_texture_unit != unit) {
|
||||
gl_ActiveTexture(GL_TEXTURE0 + unit);
|
||||
g_state_texture_unit = unit;
|
||||
}
|
||||
|
||||
if (g_state_texture_id[unit] != m_texture_id) {
|
||||
g_state_texture_id[unit] = m_texture_id;
|
||||
glBindTexture(m_texture_target, m_texture_id);
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
|
||||
{
|
||||
if (m_type != GSTexture::Offscreen) return false;
|
||||
|
||||
// The function allow to modify the texture from the CPU
|
||||
// Set m.bits <- pointer to the data
|
||||
// Set m.pitch <- size of a row
|
||||
|
@ -279,47 +220,45 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
|
|||
//
|
||||
// gl_MapBuffer — map a buffer object's data store
|
||||
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
|
||||
if (m_type == GSTexture::Offscreen) {
|
||||
// Bind the texture to the read framebuffer to avoid any disturbance
|
||||
EnableUnit(5);
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
// FIXME It might be possible to only read a subrange of the texture based on r object
|
||||
// Load the PBO with the data
|
||||
gl_BindBuffer(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);
|
||||
m.pitch = m_size.x * 4;
|
||||
} 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);
|
||||
m.pitch = m_size.x * 2;
|
||||
} 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);
|
||||
m.pitch = m_size.x;
|
||||
} else {
|
||||
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
||||
ASSERT(0);
|
||||
}
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
// Bind the texture to the read framebuffer to avoid any disturbance
|
||||
EnableUnit(5);
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
// Give access from the CPU
|
||||
m.bits = (uint8*) gl_MapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, GL_MAP_READ_BIT);
|
||||
// FIXME It might be possible to only read a subrange of the texture based on r object
|
||||
// Load the PBO with the data
|
||||
gl_BindBuffer(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);
|
||||
m.pitch = m_size.x * 4;
|
||||
} 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);
|
||||
m.pitch = m_size.x * 2;
|
||||
} 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);
|
||||
m.pitch = m_size.x;
|
||||
} else {
|
||||
fprintf(stderr, "wrong texture pixel format :%x\n", m_format);
|
||||
ASSERT(0);
|
||||
}
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
||||
if ( m.bits ) {
|
||||
return true;
|
||||
} else {
|
||||
fprintf(stderr, "bad mapping of the pbo\n");
|
||||
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
return false;
|
||||
}
|
||||
// Give access from the CPU
|
||||
m.bits = (uint8*) gl_MapBufferRange(GL_PIXEL_PACK_BUFFER, 0, m_pbo_size, GL_MAP_READ_BIT);
|
||||
|
||||
if ( m.bits ) {
|
||||
return true;
|
||||
} else {
|
||||
fprintf(stderr, "bad mapping of the pbo\n");
|
||||
gl_BindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
#if 0
|
||||
if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING)
|
||||
{
|
||||
|
@ -465,7 +404,7 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
|
|||
} else if(IsDss()) {
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, m_texture_target, m_texture_id, 0);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_texture_id, 0);
|
||||
glReadPixels(0, 0, m_size.x, m_size.y, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, image);
|
||||
|
||||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
|
@ -473,7 +412,7 @@ bool GSTextureOGL::Save(const string& fn, bool dds)
|
|||
gl_BindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read);
|
||||
|
||||
EnableUnit(6);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_target, m_texture_id, 0);
|
||||
gl_FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0);
|
||||
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
if (m_format == GL_RGBA8)
|
||||
|
|
|
@ -26,14 +26,13 @@
|
|||
class GSTextureOGL : public GSTexture
|
||||
{
|
||||
private:
|
||||
GLenum m_texture_target; // texture target: 2D, rectangle etc...
|
||||
GLuint m_texture_id; // the texture id
|
||||
uint32 m_pbo_id;
|
||||
int m_pbo_size;
|
||||
GLuint m_fbo_read;
|
||||
|
||||
public:
|
||||
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format, GLuint fbo_read);
|
||||
explicit GSTextureOGL(int type, int w, int h, int format, GLuint fbo_read);
|
||||
virtual ~GSTextureOGL();
|
||||
|
||||
bool Update(const GSVector4i& r, const void* data, int pitch);
|
||||
|
@ -42,13 +41,10 @@ class GSTextureOGL : public GSTexture
|
|||
bool Save(const string& fn, bool dds = false);
|
||||
void Save(const string& fn, const void* image, uint32 pitch);
|
||||
|
||||
void EnableUnit(uint32 unit);
|
||||
void Attach(GLenum attachment);
|
||||
void AttachRead(GLenum attachment);
|
||||
void EnableUnit(const uint32 unit);
|
||||
|
||||
bool IsBackbuffer() { return (m_type == GSTexture::Backbuffer); }
|
||||
bool IsDss() { return (m_type == GSTexture::DepthStencil); }
|
||||
|
||||
GLuint GetID() { return m_texture_id; }
|
||||
GLenum GetTarget() { return m_texture_target; }
|
||||
};
|
||||
|
|
|
@ -25,12 +25,10 @@ class GSUniformBufferOGL {
|
|||
GLuint buffer; // data object
|
||||
GLuint index; // GLSL slot
|
||||
uint32 size; // size of the data
|
||||
const GLenum target;
|
||||
|
||||
public:
|
||||
GSUniformBufferOGL(GLuint index, uint32 size) : index(index)
|
||||
, size(size)
|
||||
,target(GL_UNIFORM_BUFFER)
|
||||
{
|
||||
gl_GenBuffers(1, &buffer);
|
||||
bind();
|
||||
|
@ -40,17 +38,17 @@ public:
|
|||
|
||||
void bind()
|
||||
{
|
||||
gl_BindBuffer(target, buffer);
|
||||
gl_BindBuffer(GL_UNIFORM_BUFFER, buffer);
|
||||
}
|
||||
|
||||
void allocate()
|
||||
{
|
||||
gl_BufferData(target, size, NULL, GL_STREAM_DRAW);
|
||||
gl_BufferData(GL_UNIFORM_BUFFER, size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
void attach()
|
||||
{
|
||||
gl_BindBufferBase(target, index, buffer);
|
||||
gl_BindBufferBase(GL_UNIFORM_BUFFER, index, buffer);
|
||||
}
|
||||
|
||||
void upload(const void* src)
|
||||
|
@ -58,7 +56,7 @@ public:
|
|||
// glMapBufferRange allow to set various parameter but the call is
|
||||
// synchronous whereas glBufferSubData could be asynchronous.
|
||||
// TODO: investigate the extension ARB_invalidate_subdata
|
||||
gl_BufferSubData(target, 0, size, src);
|
||||
gl_BufferSubData(GL_UNIFORM_BUFFER, 0, size, src);
|
||||
}
|
||||
|
||||
~GSUniformBufferOGL() {
|
||||
|
|
Loading…
Reference in New Issue