gsdx-ogl:

* make a rough implementation of most of the opengl device interface. Only a savestate nothing to expect yet.
* depend of libglew 1.6 (normally 1.7 but I manually defined the only missing function)


git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@4971 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2011-11-21 22:36:03 +00:00
parent da66ca7fd9
commit 6125baa578
11 changed files with 984 additions and 241 deletions

View File

@ -186,6 +186,9 @@ target_link_libraries(${Output} ${X11_LIBRARIES})
# link target with SDL
target_link_libraries(${Output} ${SDL_LIBRARY})
# link target with glew
target_link_libraries(${Output} ${GLEW_LIBRARY})
# User flags options
if(NOT USER_CMAKE_LD_FLAGS STREQUAL "")
target_link_libraries(${Output} "${USER_CMAKE_LD_FLAGS}")

View File

@ -54,21 +54,52 @@
GSDeviceOGL::GSDeviceOGL()
: m_free_window(false)
, m_window(NULL)
, m_vb(0)
, m_pipeline(0)
, m_srv_changed(false)
, m_ss_changed(false)
{
/* TODO */
m_msaa = theApp.GetConfig("msaa", 0);
memset(&m_merge, 0, sizeof(m_merge));
memset(&m_interlace, 0, sizeof(m_interlace));
memset(&m_convert, 0, sizeof(m_convert));
memset(&m_date, 0, sizeof(m_date));
memset(&m_state, 0, sizeof(m_state));
}
GSDeviceOGL::~GSDeviceOGL() { /* TODO */ }
GSDeviceOGL::~GSDeviceOGL()
{
if(m_window != NULL && m_free_window)
{
SDL_DestroyWindow(m_window);
}
}
GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int format)
{
// A wrapper to call GSTextureOGL, with the different kind of parameter
GSTextureOGL* t = NULL;
t = new GSTextureOGL(type, w, h, msaa, format);
switch(type)
{
case GSTexture::RenderTarget:
ClearRenderTarget(t, 0);
break;
case GSTexture::DepthStencil:
ClearDepth(t, 0);
//FIXME might be need to clear the stencil too
break;
}
return t;
}
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;
@ -81,39 +112,394 @@ GSTexture* GSDeviceOGL::FetchSurface(int type, int w, int h, bool msaa, int form
bool GSDeviceOGL::Create(GSWnd* wnd)
{
/* TODO */
if (m_window == NULL) {
#if SDL_VERSION_ATLEAST(1,3,0)
m_window = SDL_CreateWindowFrom(wnd->GetHandle());
#else
assert(0);
#endif
m_free_window = true;
}
#ifdef __LINUX__
// In GSopen2, sdl failed to received any resize event. GSWnd::GetClientRect need to manually
// set the window size... So we send the m_window to the wnd object to allow some manipulation on it.
wnd->SetWindow(m_window);
#endif
// ****************************************************************
// Various object
// ****************************************************************
glGenProgramPipelines(1, &m_pipeline);
glBindProgramPipeline(m_pipeline);
glGenFramebuffers(1, &m_fbo);
// ****************************************************************
// convert
// ****************************************************************
GSInputLayout il_convert[2] =
{
{0, 4, GL_FLOAT, sizeof(GSVertexPT1), (const GLvoid*)offsetof(struct GSVertexPT1, p) },
{1, 2, GL_FLOAT, sizeof(GSVertexPT1), (const GLvoid*)offsetof(struct GSVertexPT1, t) },
};
m_convert.il[0] = il_convert[0];
m_convert.il[1] = il_convert[1];
CompileShaderFromSource("convert.glsl", "vs_main", GL_VERTEX_SHADER, &m_convert.vs);
for(int i = 0; i < countof(m_convert.ps); i++)
CompileShaderFromSource("convert.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_convert.ps[i]);
// Note the following object are initialized to 0 so disabled.
// Note: maybe enable blend with a factor of 1
// m_convert.dss, m_convert.bs
#if 0
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = false;
hr = m_dev->CreateDepthStencilState(&dsd, &m_convert.dss);
memset(&bsd, 0, sizeof(bsd));
bsd.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
hr = m_dev->CreateBlendState(&bsd, &m_convert.bs);
#endif
glGenSamplers(1, &m_convert.ln);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// FIXME which value for GL_TEXTURE_MIN_LOD
glSamplerParameteri(m_convert.ln, GL_TEXTURE_MAX_LOD, FLT_MAX);
// FIXME: seems there is 2 possibility in opengl
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
// glSamplerParameteri(m_convert.ln, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameteri(m_convert.ln, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
glGenSamplers(1, &m_convert.pt);
glGenSamplers(1, &m_convert.pt);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// FIXME which value for GL_TEXTURE_MIN_LOD
glSamplerParameteri(m_convert.pt, GL_TEXTURE_MAX_LOD, FLT_MAX);
// FIXME: seems there is 2 possibility in opengl
// DX: sd.ComparisonFunc = D3D11_COMPARISON_NEVER;
// glSamplerParameteri(m_convert.pt, GL_TEXTURE_COMPARE_MODE, GL_NONE);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
glSamplerParameteri(m_convert.pt, GL_TEXTURE_COMPARE_FUNC, GL_NEVER);
// ****************************************************************
// merge
// ****************************************************************
m_merge.cb->index = 1;
m_merge.cb->byte_size = sizeof(MergeConstantBuffer);
glGenBuffers(1, &m_merge.cb->buffer);
glBindBuffer(GL_UNIFORM_BUFFER, m_merge.cb->buffer);
glBufferData(GL_UNIFORM_BUFFER, m_merge.cb->byte_size, NULL, GL_DYNAMIC_DRAW);
for(int i = 0; i < countof(m_merge.ps); i++)
CompileShaderFromSource("merge.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_merge.ps[i]);
m_merge.bs->m_enable = true;
m_merge.bs->m_equation_RGB = GL_FUNC_ADD;
m_merge.bs->m_equation_ALPHA = GL_FUNC_ADD;
m_merge.bs->m_func_sRGB = GL_SRC_ALPHA;
m_merge.bs->m_func_dRGB = GL_ONE_MINUS_SRC_ALPHA;
m_merge.bs->m_func_sALPHA = GL_ONE;
m_merge.bs->m_func_dALPHA = GL_ZERO;
// ****************************************************************
// interlace
// ****************************************************************
m_interlace.cb->index = 2;
m_interlace.cb->byte_size = sizeof(InterlaceConstantBuffer);
glGenBuffers(1, &m_interlace.cb->buffer);
glBindBuffer(GL_UNIFORM_BUFFER, m_interlace.cb->buffer);
glBufferData(GL_UNIFORM_BUFFER, m_interlace.cb->byte_size, NULL, GL_DYNAMIC_DRAW);
for(int i = 0; i < countof(m_interlace.ps); i++)
CompileShaderFromSource("interlace.glsl", format("ps_main%d", i), GL_FRAGMENT_SHADER, &m_interlace.ps[i]);
// ****************************************************************
// rasterization configuration
// ****************************************************************
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
glDisable(GL_CULL_FACE);
glEnable(GL_SCISSOR_TEST);
// FIXME enable it when multisample code will be here
// DX: rd.MultisampleEnable = true;
glDisable(GL_MULTISAMPLE);
// Hum I don't know for those options but let's hope there are not activated
#if 0
rd.FrontCounterClockwise = false;
rd.DepthBias = false;
rd.DepthBiasClamp = 0;
rd.SlopeScaledDepthBias = 0;
rd.DepthClipEnable = false; // ???
rd.AntialiasedLineEnable = false;
#endif
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
// ****************************************************************
// The check of capability is done when context is created on openGL
// For the moment don't bother with extension, I just ask the most recent openGL version
// ****************************************************************
#if 0
if(FAILED(hr)) return false;
if(!SetFeatureLevel(level, true))
{
return false;
}
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS options;
hr = m_dev->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &options, sizeof(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS));
// msaa
for(uint32 i = 2; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++)
{
uint32 quality[2] = {0, 0};
if(SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, i, &quality[0])) && quality[0] > 0
&& SUCCEEDED(m_dev->CheckMultisampleQualityLevels(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, i, &quality[1])) && quality[1] > 0)
{
m_msaa_desc.Count = i;
m_msaa_desc.Quality = std::min<uint32>(quality[0] - 1, quality[1] - 1);
if(i >= m_msaa) break;
}
}
if(m_msaa_desc.Count == 1)
{
m_msaa = 0;
}
#endif
// TODO Later
// ****************************************************************
// fxaa
// ****************************************************************
#if 0
memset(&bd, 0, sizeof(bd));
bd.ByteWidth = sizeof(FXAAConstantBuffer);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
hr = m_dev->CreateBuffer(&bd, NULL, &m_fxaa.cb);
hr = CompileShader(IDR_FXAA_FX, "ps_main", NULL, &m_fxaa.ps);
#endif
// TODO later
#if 0
CreateTextureFX();
//
memset(&dsd, 0, sizeof(dsd));
dsd.DepthEnable = false;
dsd.StencilEnable = true;
dsd.StencilReadMask = 1;
dsd.StencilWriteMask = 1;
dsd.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS;
dsd.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE;
dsd.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP;
dsd.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP;
m_dev->CreateDepthStencilState(&dsd, &m_date.dss);
D3D11_BLEND_DESC blend;
memset(&blend, 0, sizeof(blend));
m_dev->CreateBlendState(&blend, &m_date.bs);
#endif
}
bool GSDeviceOGL::Reset(int w, int h)
{
// Hum map, m_backbuffer to a GSTexture
if(!GSDevice::Reset(w, h))
return false;
// TODO
// 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(0, w, h, false, 0);
#if 0
if(m_swapchain)
{
DXGI_SWAP_CHAIN_DESC scd;
memset(&scd, 0, sizeof(scd));
m_swapchain->GetDesc(&scd);
m_swapchain->ResizeBuffers(scd.BufferCount, w, h, scd.BufferDesc.Format, 0);
CComPtr<ID3D11Texture2D> backbuffer;
if(FAILED(m_swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)&backbuffer)))
{
return false;
}
// Swap buffer (back buffer, front buffer)
m_backbuffer = new GSTexture11(backbuffer);
}
#endif
return true;
}
void GSDeviceOGL::Flip()
{
// Warning it is not OGL dependent but application dependant (glx and so not portable)
void GSDeviceOGL::Flip() { /* TODO */ }
#if SDL_VERSION_ATLEAST(1,3,0)
SDL_GL_SwapWindow(m_window);
#else
SDL_GL_SwapBuffers();
#endif
// glDrawArrays
void GSDeviceOGL::DrawPrimitive() { /* TODO */ }
}
// Just a wrapper around glClear* functions
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c) { /* TODO */ }
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c) { /* TODO */ }
void GSDeviceOGL::ClearDepth(GSTexture* t, float c) { /* TODO */ }
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c) { /* TODO */ }
void GSDeviceOGL::DrawPrimitive()
{
glDrawArrays(m_state.topology, m_vertices.start, m_vertices.count);
}
// the 4 next functions are only used to set some default value for the format.
// Need to find the default format...
// depth_stencil => GL_DEPTH32F_STENCIL8
// others => (need 4* 8bits unsigned normalized integer) (GL_RGBA8 )
GSTexture* GSDeviceOGL::CreateRenderTarget(int w, int h, bool msaa, int format) { /* TODO */ }
GSTexture* GSDeviceOGL::CreateDepthStencil(int w, int h, bool msaa, int format) { /* TODO */ }
GSTexture* GSDeviceOGL::CreateTexture(int w, int h, int format) { /* TODO */ }
GSTexture* GSDeviceOGL::CreateOffscreen(int w, int h, int format) { /* TODO */ }
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, const GSVector4& c)
{
GSTextureOGL* t_ogl = (GSTextureOGL*)t;
// FIXME I need to clarify this FBO attachment stuff
// I would like to avoid FBO for a basic clean operation
//glClearBufferfv(GL_COLOR, t_ogl->attachment(), c.v);
}
void GSDeviceOGL::ClearRenderTarget(GSTexture* t, uint32 c)
{
GSTextureOGL* t_ogl = (GSTextureOGL*)t;
GSVector4 color = GSVector4::rgba32(c) * (1.0f / 255);
// FIXME I need to clarify this FBO attachment stuff
// I would like to avoid FBO for a basic clean operation
//glClearBufferfv(GL_COLOR, t_ogl->attachment(), color.v);
}
void GSDeviceOGL::ClearDepth(GSTexture* t, float c)
{
glClearBufferfv(GL_DEPTH, 0, &c);
}
void GSDeviceOGL::ClearStencil(GSTexture* t, uint8 c)
{
GLint color = c;
glClearBufferiv(GL_STENCIL, 0, &color);
}
GSTexture* GSDeviceOGL::CreateRenderTarget(int w, int h, bool msaa, int format)
{
return GSDevice::CreateRenderTarget(w, h, msaa, format ? format : GL_RGBA8);
}
GSTexture* GSDeviceOGL::CreateDepthStencil(int w, int h, bool msaa, int format)
{
return GSDevice::CreateDepthStencil(w, h, msaa, format ? format : GL_DEPTH32F_STENCIL8);
}
GSTexture* GSDeviceOGL::CreateTexture(int w, int h, int format)
{
return GSDevice::CreateTexture(w, h, format ? format : GL_RGBA8);
}
GSTexture* GSDeviceOGL::CreateOffscreen(int w, int h, int format)
{
return GSDevice::CreateOffscreen(w, h, format ? format : GL_RGBA8);
}
// 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.
@ -167,34 +553,49 @@ 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 0
if(!st || !dt)
{
ASSERT(0);
return;
}
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
assert(0);
// FIXME attach the texture to the FBO
GSTextureOGL* st_ogl = (GSTextureOGL*) st;
GSTextureOGL* dt_ogl = (GSTextureOGL*) dt;
dt_ogl->Attach(GL_COLOR_ATTACHMENT0);
st_ogl->Attach(GL_COLOR_ATTACHMENT1);
glReadBuffer(GL_COLOR_ATTACHMENT1);
// FIXME I'not sure how to select the destination
// const GLenum draw_buffer[1] = { GL_COLOR_ATTACHMENT0 };
// glDrawBuffers(draw_buffer);
dt_ogl->EnableUnit(0);
// FIXME need acess of target and it probably need to be same for both
//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);
#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
}
// Raster flow to resize a texture
// Note just call the StretchRect hardware accelerated
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader, bool linear)
{
/* TODO */
StretchRect(st, sr, dt, dr, m_convert.ps[shader], NULL, linear);
}
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, bool linear)
{
// TODO
StretchRect(st, sr, dt, dr, ps, ps_cb, m_convert.bs, linear);
}
// probably no difficult to convert when all helpers function will be done
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL ps_cb, GSBlendStateOGL* bs, bool linear)
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, GSBlendStateOGL* bs, bool linear)
{
//TODO later
assert(0);
#if 0
if(!st || !dt)
{
@ -259,7 +660,6 @@ void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt,
void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c)
{
#if 0
ClearRenderTarget(dt, c);
if(st[1] && !slbg)
@ -269,16 +669,20 @@ void GSDeviceOGL::DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVect
if(st[0])
{
if (m_state.cb != m_merge.cb->buffer) {
m_state.cb = m_merge.cb->buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_merge.cb->buffer);
}
glBufferSubData(GL_UNIFORM_BUFFER, 0, m_merge.cb->byte_size, &c.v);
#if 0
m_ctx->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0);
#endif
StretchRect(st[0], sr[0], dt, dr[0], m_merge.ps[mmod ? 1 : 0], m_merge.cb, m_merge.bs, true);
}
#endif
}
void GSDeviceOGL::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset)
{
#if 0
GSVector4 s = GSVector4(dt->GetSize());
GSVector4 sr(0, 0, 1, 1);
@ -289,18 +693,25 @@ void GSDeviceOGL::DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool lin
cb.ZrH = GSVector2(0, 1.0f / s.y);
cb.hH = s.y / 2;
if (m_state.cb != m_interlace.cb->buffer) {
m_state.cb = m_interlace.cb->buffer;
glBindBuffer(GL_UNIFORM_BUFFER, m_interlace.cb->buffer);
}
// FIXME I'm not sure it will be happy with InterlaceConstantBuffer type
glBufferSubData(GL_UNIFORM_BUFFER, 0, m_interlace.cb->byte_size, &cb);
#if 0
m_ctx->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0);
#endif
StretchRect(st, sr, dt, dr, m_interlace.ps[shader], m_interlace.cb, linear);
#endif
}
// 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)
{
#if 0
ASSERT(t != NULL && t->IsMSAA());
#if 0
if(GSTexture* dst = CreateRenderTarget(t->GetWidth(), t->GetHeight(), false, t->GetFormat()))
{
@ -323,151 +734,78 @@ void GSDeviceOGL::IASetVertexBuffer(const void* vertices, size_t stride, size_t
if(count * stride > m_vertices.limit * m_vertices.stride)
{
// Current GPU buffer is too small need to realocate a new one
#if 0
m_vb_old = m_vb;
m_vb = NULL;
if (m_vb) {
glDeleteBuffers(1, &m_vb);
m_vb = 0;
}
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = std::max<int>(count * 3 / 2, 11000);
#endif
}
if(m_vb == NULL)
if(!m_vb)
{
// Allocate a GPU buffer: GL_DYNAMIC_DRAW vs GL_STREAM_DRAW !!!
// glBufferData(GL_ARRAY_BUFFER, m_vertices.limit, NULL, GL_DYNAMIC_DRAW)
#if 0
D3D11_BUFFER_DESC bd;
memset(&bd, 0, sizeof(bd));
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = m_vertices.limit * stride;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
HRESULT hr;
hr = m_dev->CreateBuffer(&bd, NULL, &m_vb);
if(FAILED(hr)) return;
#endif
glGenBuffers(1, &m_vb);
// FIXME: GL_DYNAMIC_DRAW vs GL_STREAM_DRAW !!!
glBindBuffer(GL_ARRAY_BUFFER, m_vb);
glBufferData(GL_ARRAY_BUFFER, m_vertices.limit, NULL, GL_DYNAMIC_DRAW);
}
// append data or go back to the beginning
// Hum why we don't always go back to the beginning !!!
#if 0
D3D11_MAP type = D3D11_MAP_WRITE_NO_OVERWRITE;
if(m_vertices.start + count > m_vertices.limit || stride != m_vertices.stride)
{
m_vertices.start = 0;
type = D3D11_MAP_WRITE_DISCARD;
}
#endif
// Allocate the buffer
// glBufferSubData
#if 0
D3D11_MAPPED_SUBRESOURCE m;
if(SUCCEEDED(m_ctx->Map(m_vb, 0, type, 0, &m)))
{
GSVector4i::storent((uint8*)m.pData + m_vertices.start * stride, vertices, count * stride);
m_ctx->Unmap(m_vb, 0);
}
#endif
glBufferSubData(GL_ARRAY_BUFFER, m_vertices.start * stride, count * stride, vertices);
m_vertices.count = count;
m_vertices.stride = stride;
// Useless ?
// binding of the buffer must be done anyway before glBufferSubData or glBufferData calls.
#if 0
IASetVertexBuffer(m_vb, stride);
#endif
}
// Useless ?
#if 0
void GSDeviceOGL::IASetVertexBuffer(GLuint vb, size_t stride)
{
if(m_state.vb != vb || m_state.vb_stride != stride)
{
m_state.vb = vb;
m_state.vb_stride = stride;
uint32 stride2 = stride;
uint32 offset = 0;
m_ctx->IASetVertexBuffers(0, 1, &vb, &stride2, &offset);
}
}
#endif
// Useless ?
#if 0
void GSDeviceOGL::IASetInputLayout(ID3D11InputLayout* layout)
void GSDeviceOGL::IASetInputLayout(GSInputLayout* layout, int layout_nbr)
{
if(m_state.layout != layout)
{
m_state.layout = layout;
m_ctx->IASetInputLayout(layout);
for (int i = 0; i < layout_nbr; i++)
glVertexAttribPointer(layout->index, layout->size, layout->type, GL_FALSE, layout->stride, layout->offset);
}
}
#endif
// Useless ?
#if 0
void GSDeviceOGL::IASetPrimitiveTopology(GLenum topology)
{
if(m_state.topology != topology)
{
m_state.topology = topology;
m_ctx->IASetPrimitiveTopology(topology);
}
}
#endif
void GSDeviceOGL::VSSetShader(GLuint vs, GSUniformBufferOGL* vs_cb)
{
// glUseProgramStage
#if 0
if(m_state.vs != vs)
{
m_state.vs = vs;
m_ctx->VSSetShader(vs, NULL, 0);
glUseProgramStages(m_pipeline, GL_VERTEX_SHADER_BIT, vs);
}
#endif
// glBindBufferBase
#if 0
if(m_state.vs_cb != vs_cb)
{
m_state.vs_cb = vs_cb;
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
glBindBufferBase(GL_UNIFORM_BUFFER, vs_cb->index, vs_cb->buffer);
}
#endif
}
void GSDeviceOGL::GSSetShader(GLuint gs)
{
// glUseProgramStage
#if 0
if(m_state.gs != gs)
{
m_state.gs = gs;
m_ctx->GSSetShader(gs, NULL, 0);
glUseProgramStages(m_pipeline, GL_GEOMETRY_SHADER_BIT, gs);
}
#endif
}
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
@ -479,10 +817,9 @@ void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
void GSDeviceOGL::PSSetShaderResource(int i, GSTexture* sr)
{
#if 0
ID3D11ShaderResourceView* srv = NULL;
GSTextureOGL* srv = NULL;
if(sr) srv = *(GSTexture11*)sr;
if(sr) srv = (GSTextureOGL*)sr;
if(m_state.ps_srv[i] != srv)
{
@ -490,12 +827,10 @@ void GSDeviceOGL::PSSetShaderResource(int i, GSTexture* sr)
m_srv_changed = true;
}
#endif
}
void GSDeviceOGL::PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2)
{
#if 0
if(m_state.ps_ss[0] != ss0 || m_state.ps_ss[1] != ss1 || m_state.ps_ss[2] != ss2)
{
m_state.ps_ss[0] = ss0;
@ -504,21 +839,16 @@ void GSDeviceOGL::PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2)
m_ss_changed = true;
}
#endif
}
void GSDeviceOGL::PSSetShader(GLuint ps, GSUniformBufferOGL* ps_cb)
{
// glUseProgramStage
#if 0
if(m_state.ps != ps)
{
m_state.ps = ps;
m_ctx->PSSetShader(ps, NULL, 0);
glUseProgramStages(m_pipeline, GL_FRAGMENT_SHADER_BIT, ps);
}
#endif
// Sampler and texture must be set at the same time
// 1/ select the texture unit
@ -529,6 +859,12 @@ void GSDeviceOGL::PSSetShader(GLuint ps, GSUniformBufferOGL* ps_cb)
// glUniform1i(brickSamplerId , 1);
// 4/ set the sampler state
// glBindSampler(1 , sampler);
if (m_srv_changed || m_ss_changed) {
for (uint i=0 ; i < 3; i++) {
m_state.ps_srv[i]->EnableUnit(i);
glBindSampler(i, m_state.ps_ss[i]);
}
}
#if 0
if (m_srv_changed)
{
@ -545,29 +881,36 @@ void GSDeviceOGL::PSSetShader(GLuint ps, GSUniformBufferOGL* ps_cb)
}
#endif
// glBindBufferBase
#if 0
if(m_state.ps_cb != ps_cb)
{
m_state.ps_cb = ps_cb;
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
glBindBufferBase(GL_UNIFORM_BUFFER, ps_cb->index, ps_cb->buffer);
}
#endif
}
void GSDeviceOGL::OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref)
{
// Setup the stencil object. sref can be set by glStencilFunc (note remove it from the structure)
#if 0
uint ref = sref;
if(m_state.dss != dss || m_state.sref != sref)
{
m_state.dss = dss;
m_state.sref = sref;
m_ctx->OMSetDepthStencilState(dss, sref);
if (dss->m_depth_enable) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(dss->m_depth_func);
glDepthMask(dss->m_depth_mask);
} else
glDisable(GL_DEPTH_TEST);
if (dss->m_stencil_enable) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(dss->m_stencil_func, ref, dss->m_stencil_mask);
glStencilOp(dss->m_stencil_sfail_op, dss->m_stencil_spass_dfail_op, dss->m_stencil_spass_dpass_op);
} else
glDisable(GL_STENCIL_TEST);
}
#endif
}
void GSDeviceOGL::OMSetBlendState(GSBlendStateOGL* bs, float bf)
@ -575,23 +918,26 @@ void GSDeviceOGL::OMSetBlendState(GSBlendStateOGL* bs, float bf)
// DX:Blend factor D3D11_BLEND_BLEND_FACTOR | D3D11_BLEND_INV_BLEND_FACTOR
// OPENGL: GL_CONSTANT_COLOR | GL_ONE_MINUS_CONSTANT_COLOR
// Note factor must be set before by glBlendColor
#if 0
if(m_state.bs != bs || m_state.bf != bf)
{
m_state.bs = bs;
m_state.bf = bf;
float BlendFactor[] = {bf, bf, bf, 0};
// FIXME: double check when blend stuff is complete
if (bs->m_func_sRGB == GL_CONSTANT_COLOR || bs->m_func_sRGB == GL_ONE_MINUS_CONSTANT_COLOR
|| bs->m_func_dRGB == GL_CONSTANT_COLOR || bs->m_func_dRGB == GL_ONE_MINUS_CONSTANT_COLOR)
glBlendColor(bf, bf, bf, 0);
m_ctx->OMSetBlendState(bs, BlendFactor, 0xffffffff);
glBlendEquationSeparate(bs->m_equation_RGB, bs->m_equation_ALPHA);
glBlendFuncSeparate(bs->m_func_sRGB, bs->m_func_dRGB, bs->m_func_sALPHA, bs->m_func_dALPHA);
}
#endif
}
void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
{
// set the attachment inside the FBO
// attach render&depth to the FBO
// Hum, need to separate 2 case, Render target fbo and render target backbuffer
// Or maybe blit final result to the backbuffer
#if 0
ID3D11RenderTargetView* rtv = NULL;
ID3D11DepthStencilView* dsv = NULL;
@ -607,37 +953,98 @@ void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVecto
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
}
#endif
GSTextureOGL* rt_ogl = (GSTextureOGL*)rt;
GSTextureOGL* ds_ogl = (GSTextureOGL*)ds;
if (m_backbuffer == rt_ogl) {
if (m_state.fbo) {
m_state.fbo = 0;
glBindFramebuffer(GL_FRAMEBUFFER, 0); // render in the backbuffer
}
assert(ds_ogl == NULL); // no depth-stencil without FBO
} else {
if (m_state.fbo != m_fbo) {
m_state.fbo = m_fbo;
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
}
assert(rt_ogl != NULL); // a render target must exists
rt_ogl->Attach(GL_COLOR_ATTACHMENT0);
if (ds_ogl != NULL)
ds_ogl->Attach(GL_DEPTH_STENCIL_ATTACHMENT);
}
// Viewport -> glViewport
#if 0
if(m_state.viewport != rt->GetSize())
{
m_state.viewport = rt->GetSize();
D3D11_VIEWPORT vp;
memset(&vp, 0, sizeof(vp));
vp.TopLeftX = 0;
vp.TopLeftY = 0;
vp.Width = (float)rt->GetWidth();
vp.Height = (float)rt->GetHeight();
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
m_ctx->RSSetViewports(1, &vp);
glViewport(0, 0, rt->GetWidth(), rt->GetHeight());
}
#endif
// Scissor -> glScissor (note must be enabled)
#if 0
GSVector4i r = scissor ? *scissor : GSVector4i(rt->GetSize()).zwxy();
if(!m_state.scissor.eq(r))
{
m_state.scissor = r;
// FIXME check position
glScissor(r.x, r.w, r.z-r.x, r.y-r.w);
#if 0
m_ctx->RSSetScissorRects(1, r);
}
#endif
}
}
void GSDeviceOGL::CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program)
{
// Could be useful to filter ubber shader
std::string shader_type;
switch (type) {
case GL_VERTEX_SHADER:
shader_type = "#define VERTEX_SHADER 1\n";
case GL_GEOMETRY_SHADER:
shader_type = "#define GEOMETRY_SHADER 1\n";
case GL_FRAGMENT_SHADER:
shader_type = "#define FRAGMENT_SHADER 1\n";
}
// Select the entry point
std::string entry_main = format("#define %s main\n", entry.c_str());
// Read the source file
std::string source;
std::string line;
// Each linux distributions have his rules for path so we give them the possibility to
// change it with compilation flags. -- Gregory
#ifdef PLUGIN_DIR_COMPILATION
#define xPLUGIN_DIR_str(s) PLUGIN_DIR_str(s)
#define PLUGIN_DIR_str(s) #s
const std::string shader_file = string(xPLUGIN_DIR_str(PLUGIN_DIR_COMPILATION)) + '/' + glsl_file;
#else
const std::string shader_file = string("plugins/") + glsl_file;
#endif
std::ifstream myfile(shader_file.c_str());
if (myfile.is_open()) {
while ( myfile.good() )
{
getline (myfile,line);
source += line;
source += '\n';
}
myfile.close();
} else {
fprintf(stderr, "Error opening %s: ", shader_file.c_str());
}
// Create a giant string with everythings
std::string full_source = shader_type + entry_main + source;
char* sources = (char*)malloc(full_source.size());
strncpy(sources, full_source.c_str(), full_source.size());
sources[full_source.size()] = '\0';
*program = glCreateShaderProgramv(type, 1, (const char**)&sources);
free(sources);
}

View File

@ -21,9 +21,11 @@
#pragma once
#include <fstream>
#include "GSDevice.h"
#include "GSTextureOGL.h"
#include "GSdx.h"
#include "../../3rdparty/SDL-1.3.0-5387/include/SDL.h"
struct GSBlendStateOGL {
// Note: You can also select the index of the draw buffer for which to set the blend setting
@ -31,13 +33,16 @@ struct GSBlendStateOGL {
bool m_enable;
GLenum m_equation_RGB;
GLenum m_equation_ALPHA;
GLenum m_func_RGB;
GLenum m_func_ALPHA;
GLenum m_func_sRGB;
GLenum m_func_dRGB;
GLenum m_func_sALPHA;
GLenum m_func_dALPHA;
};
struct GSDepthStencilOGL {
bool m_depth_enable;
GLenum m_depth_func;
GLboolean m_depth_mask;
// Note front face and back can be split might. But it seems they have same parameter configuration
bool m_stencil_enable;
GLuint m_stencil_mask;
@ -49,16 +54,29 @@ struct GSDepthStencilOGL {
};
struct GSUniformBufferOGL {
GLuint buffer;
GLuint buffer; // data object
GLuint index; // GLSL slot
uint byte_size; // size of the data
};
struct GSInputLayout {
GLuint index;
GLint size;
GLenum type;
GLsizei stride;
const GLvoid* offset;
};
class GSDeviceOGL : public GSDevice
{
uint32 m_msaa;
uint32 m_msaa; // Level of Msaa
// Vertex buffer: glGenBuffers, glBindBuffer GL_ARRAY_BUFFER
GLuint m_vb; // buffer object
bool m_free_window;
SDL_Window* m_window; // pointer to the SDL window
GLuint m_vb; // vertex buffer object
GLuint m_pipeline; // pipeline to attach program shader
GLuint m_fbo; // frame buffer container
struct {
GLuint ps[2]; // program object
@ -71,21 +89,11 @@ class GSDeviceOGL : public GSDevice
GSUniformBufferOGL* cb; // uniform buffer object
} m_interlace;
//struct
//{
// CComPtr<ID3D11InputLayout> il;
// CComPtr<ID3D11VertexShader> vs; // program object
// CComPtr<ID3D11PixelShader> ps[8]; // program object
// CComPtr<ID3D11SamplerState> ln;
// CComPtr<ID3D11SamplerState> pt;
// CComPtr<ID3D11DepthStencilState> dss;
// CComPtr<ID3D11BlendState> bs; // no equivalent
//} m_convert;
struct
{
struct {
// Hum I think this one is useless. As far as I understand
// it only get the index name of GLSL-equivalent input attribut
// ??? CComPtr<ID3D11InputLayout> il;
GSInputLayout il[2]; // description of the vertex array
GLuint vs; // program object
GLuint ps[8]; // program object
GLuint ln; // sampler object
@ -94,11 +102,6 @@ class GSDeviceOGL : public GSDevice
GSBlendStateOGL* bs;
} m_convert;
// struct
// {
// CComPtr<ID3D11DepthStencilState> dss;
// CComPtr<ID3D11BlendState> bs;
// } m_date;
struct
{
GSDepthStencilOGL* dss;
@ -133,8 +136,10 @@ class GSDeviceOGL : public GSDevice
// Hum I think those things can be dropped on OGL. It probably need an others architecture (see glVertexAttribPointer)
// size_t vb_stride;
// ID3D11InputLayout* layout;
GSInputLayout* layout;
GLenum topology; // (ie GL_TRIANGLES...)
GLuint vs; // program
GLuint cb; // uniform current buffer
GSUniformBufferOGL* vs_cb; // uniform buffer
GLuint gs; // program
// FIXME texture binding. Maybe not equivalent for the state but the best I could find.
@ -152,6 +157,9 @@ class GSDeviceOGL : public GSDevice
// FIXME texture attachment in the FBO
// ID3D11RenderTargetView* rtv;
// ID3D11DepthStencilView* dsv;
GSTextureOGL* rtv;
GSTextureOGL* dsv;
GLuint fbo;
} m_state;
bool m_srv_changed;
@ -219,11 +227,15 @@ class GSDeviceOGL : public GSDevice
void CopyRect(GSTexture* st, GSTexture* dt, const GSVector4i& r);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, int shader = 0, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, bool linear);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL ps_cb, GSBlendStateOGL* bs, bool linear);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, bool linear = true);
void StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, GSBlendStateOGL* bs, bool linear = true);
GSTexture* Resolve(GSTexture* t);
void CompileShaderFromSource(const std::string& glsl_file, const std::string& entry, GLenum type, GLuint* program);
void IASetPrimitiveTopology(GLenum topology);
void IASetInputLayout(GSInputLayout* layout, int layout_nbr);
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);
void VSSetShader(GLuint vs, GSUniformBufferOGL* vs_cb);

View File

@ -42,13 +42,12 @@ static void SysMessage(const char *fmt, ...)
bool RunLinuxDialog()
{
// FIXME need to add msaa option configuration
GtkWidget *dialog;
GtkWidget *main_frame, *main_box;
GtkWidget *render_label, *render_combo_box;
GtkWidget *interlace_label, *interlace_combo_box;
GtkWidget *swthreads_label, *swthreads_text;
GtkWidget *filter_check, *logz_check, *paltex_check, *fba_check, *aa_check, *win_check;
GtkWidget *filter_check, *logz_check, *paltex_check, *fba_check, *aa_check, *win_check, *msaa_check;
int return_value;
/* Create the widgets */
@ -134,6 +133,7 @@ bool RunLinuxDialog()
fba_check = gtk_check_button_new_with_label("Alpha correction (FBA)");
aa_check = gtk_check_button_new_with_label("Edge anti-aliasing");
win_check = gtk_check_button_new_with_label("Disable Effects Processing");
msaa_check = gtk_check_button_new_with_label("Enable MultiSample AA (not yet implemented)");
gtk_container_add(GTK_CONTAINER(main_box), filter_check);
gtk_container_add(GTK_CONTAINER(main_box), logz_check);
@ -141,6 +141,7 @@ bool RunLinuxDialog()
gtk_container_add(GTK_CONTAINER(main_box), fba_check);
gtk_container_add(GTK_CONTAINER(main_box), aa_check);
gtk_container_add(GTK_CONTAINER(main_box), win_check);
gtk_container_add(GTK_CONTAINER(main_box), msaa_check);
// Filter should be 3 states, not 2.
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filter_check), theApp.GetConfig("filter", 1));
@ -149,6 +150,7 @@ bool RunLinuxDialog()
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(fba_check), theApp.GetConfig("fba", 1));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(aa_check), theApp.GetConfig("aa1", 0));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(win_check), theApp.GetConfig("windowed", 1));
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(msaa_check), theApp.GetConfig("msaa", 0));
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
gtk_widget_show_all (dialog);
@ -188,6 +190,7 @@ bool RunLinuxDialog()
theApp.SetConfig("fba", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(fba_check)));
theApp.SetConfig("aa1", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(aa_check)));
theApp.SetConfig("windowed", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(win_check)));
theApp.SetConfig("msaa", (int)gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(msaa_check)));
gtk_widget_destroy (dialog);

View File

@ -23,7 +23,8 @@
#include "GSTextureOGL.h"
GSTextureOGL::GSTextureOGL(/* ID3D11Texture2D* texture */ )
GSTextureOGL::GSTextureOGL(int type, int w, int h, bool msaa, int format)
: m_texture_unit(0)
{
// *************************************************************
// Opengl world
@ -63,6 +64,12 @@ GSTextureOGL::GSTextureOGL(/* ID3D11Texture2D* texture */ )
// : m_type
// : m_format
// : m_msaa
m_size.x = w;
m_size.y = h;
m_format = format;
m_type = type;
m_msaa = msaa;
// == Might be useful to save
// : m_texture_target (like GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE etc...)
// : m_texture_id (return by glGen*)
@ -81,30 +88,68 @@ GSTextureOGL::GSTextureOGL(/* ID3D11Texture2D* texture */ )
// glGetTexImage: read pixels of a bound texture
// => To allow map/unmap. I think we can use a pixel buffer (target GL_PIXEL_UNPACK_BUFFER)
// http://www.opengl.org/wiki/Pixel_Buffer_Objects
// == Enable texture Unit
// EnableUnit();
// == Allocate space
// glRenderbufferStorageMultisample or glTexStorage2D
// Generate the buffer
switch (m_type) {
case GSTexture::RenderTarget:
// FIXME what is the real use case of this texture
// Maybe a texture will be better
glGenRenderbuffers(1, &m_texture_id);
m_texture_target = GL_RENDERBUFFER;
break;
case GSTexture::DepthStencil:
glGenRenderbuffers(1, &m_texture_id);
m_texture_target = GL_RENDERBUFFER;
break;
case GSTexture::Texture:
glGenTextures(1, &m_texture_id);
// FIXME, do we need rectangle (or better to use 2D texture)
//m_texture_target = GL_TEXTURE_2D;
m_texture_target = GL_TEXTURE_RECTANGLE;
// == For texture, the Unit must be selected
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;
default: break;
}
#if 0
m_texture->GetDevice(&m_dev);
m_texture->GetDesc(&m_desc);
uint msaa_level;
if (m_msaa) {
// FIXME which level of MSAA
msaa_level = 1;
} else {
msaa_level = 0;
}
m_dev->GetImmediateContext(&m_ctx);
m_size.x = (int)m_desc.Width;
m_size.y = (int)m_desc.Height;
if(m_desc.BindFlags & D3D11_BIND_RENDER_TARGET) m_type = RenderTarget;
else if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL) m_type = DepthStencil;
else if(m_desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) m_type = Texture;
else if(m_desc.Usage == D3D11_USAGE_STAGING) m_type = Offscreen;
m_format = (int)m_desc.Format;
m_msaa = m_desc.SampleDesc.Count > 1;
#endif
// Allocate the buffer
switch (m_type) {
case GSTexture::RenderTarget:
case GSTexture::DepthStencil:
glBindRenderbuffer(m_texture_target, m_texture_id);
glRenderbufferStorageMultisample(m_texture_target, msaa_level, m_format, m_size.y, m_size.x);
break;
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(0);
glTexStorage2D_glew17(m_texture_target, 0, m_format, m_size.y, m_size.x);
break;
case GSTexture::Offscreen:
assert(0);
break;
default: break;
}
}
GSTextureOGL::~GSTextureOGL()
@ -112,28 +157,36 @@ GSTextureOGL::~GSTextureOGL()
// glDeleteTextures or glDeleteRenderbuffers
}
void GSTextureOGL::EnableUnit()
void GSTextureOGL::Attach(GLenum attachment)
{
// == For texture, the Unit must be selected
// glActiveTexture
// !!!!!!!!!! VERY BIG ISSUE, how to ensure that the different texture use different texture unit.
// I think we need to create a pool on GSdevice.
// 1/ this->m_device_ogl
// 2/ int GSDeviceOGL::get_free_texture_unit() called from GSTextureOGL constructor
// 3/ void GSDeviceOGL::release_texture_unit(int) called from GSDeviceOGL destructor
// Another (better) idea, will be to create a global static pool
//
// == Bind the texture or buffer
// glBindRenderbuffer or glBindTexture
//
// !!!!!!!!!! Maybe attach to the FBO but where to manage the FBO!!!
// Create a separare public method for attachment ???
if (m_type == GSTexture::DepthStencil)
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, m_texture_target, m_texture_id);
else
glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, m_texture_target, m_texture_id, 0);
}
bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
{
// To update only a part of the texture you can use:
// glTexSubImage2D — specify a two-dimensional texture subimage
switch (m_type) {
case GSTexture::Texture:
// glTexSubImage2D specifies a two-dimensional subtexture for the current texture unit, specified with glActiveTexture.
// If a non-zero named buffer object is bound to the GL_PIXEL_UNPACK_BUFFER target
//(see glBindBuffer) while a texture image is
// specified, data is treated as a byte offset into the buffer object's data store
// FIXME warning order of the y axis
// FIXME I'm not confident with GL_UNSIGNED_BYTE type
// FIXME add a state check
glBindTexture(m_texture_target, m_texture_id);
glTexSubImage2D(m_texture_target, 0, r.left, r.bottom, r.right-r.left, r.top-r.bottom, m_format, GL_UNSIGNED_BYTE, data);
break;
case GSTexture::RenderTarget:
case GSTexture::DepthStencil:
case GSTexture::Offscreen:
assert(0);
break;
}
#if 0
if(m_dev && m_texture)
{
@ -148,6 +201,25 @@ bool GSTextureOGL::Update(const GSVector4i& r, const void* data, int pitch)
#endif
}
void GSTextureOGL::EnableUnit(uint unit)
{
switch (m_type) {
case GSTexture::RenderTarget:
case GSTexture::DepthStencil:
case GSTexture::Offscreen:
assert(0);
break;
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
glActiveTexture(GL_TEXTURE0 + unit);
glBindTexture(m_texture_target, m_texture_id);
break;
}
}
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
{
// The function allow to modify the texture from the CPU
@ -156,6 +228,8 @@ bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
// I think in opengl we need to copy back the data to the RAM: glReadPixels — read a block of pixels from the frame buffer
//
// glMapBuffer — map a buffer object's data store
// Can be used on GL_PIXEL_UNPACK_BUFFER or GL_TEXTURE_BUFFER
return false;
#if 0
if(r != NULL)
{

View File

@ -28,16 +28,17 @@ class GSTextureOGL : public GSTexture
private:
GLenum m_texture_target; // texture target: 2D, rectangle etc...
GLuint m_texture_id; // the texture id
int m_texture_unit; // the texture unit offset
void EnableUnit();
uint m_texture_unit; // the texture unit offset
public:
explicit GSTextureOGL();
explicit GSTextureOGL(int type, int w, int h, bool msaa, int format);
virtual ~GSTextureOGL();
bool Update(const GSVector4i& r, const void* data, int pitch);
bool Map(GSMap& m, const GSVector4i* r = NULL);
void Unmap();
bool Save(const string& fn, bool dds = false);
void EnableUnit(uint unit);
void Attach(GLenum attachment);
};

View File

@ -352,6 +352,8 @@ void GSWnd::Detach()
}
}
PFNGLTEXSTORAGE2DPROC glTexStorage2D_glew17 = NULL;
bool GSWnd::Create(const string& title, int w, int h)
{
if(m_window != NULL) return false;
@ -405,6 +407,22 @@ bool GSWnd::Create(const string& title, int w, int h)
SDL_GetWindowWMInfo(m_window, &wminfo);
m_Xwindow = wminfo.info.x11.window;
// OpenGL mode
// FIXME : be sure that the window is map
if ( theApp.GetConfig("renderer", 0) / 3 == 4 ) {
// FIXME......
// GLEW's problem is that it calls glGetString(GL_EXTENSIONS) which causes GL_INVALID_ENUM on GL 3.2 forward compatible context as soon as glewInit() is called. It also doesn't fetch the function pointers. The solution is for GLEW to use glGetStringi instead.
// The current version of GLEW is 1.7.0 but they still haven't corrected it. The only fix is to use glewExperimental for now :
glewExperimental=true;
const int glew_ok = glewInit();
if (glew_ok != GLEW_OK)
{
// FIXME:proper logging
fprintf(stderr, "Failed to init glew\n");
return false;
}
glTexStorage2D_glew17 = (PFNGLTEXSTORAGE2DPROC)glXGetProcAddressARB((const GLubyte*)"glTexStorage2D");
}
return (m_window != NULL);
}

View File

@ -0,0 +1,142 @@
#if 0
struct VS_INPUT
{
float4 p : POSITION;
float2 t : TEXCOORD0;
};
struct VS_OUTPUT
{
float4 p : SV_Position;
float2 t : TEXCOORD0;
};
Texture2D Texture;
SamplerState TextureSampler;
float4 sample_c(float2 uv)
{
return Texture.Sample(TextureSampler, uv);
}
struct PS_INPUT
{
float4 p : SV_Position;
float2 t : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 c : SV_Target0;
};
VS_OUTPUT vs_main(VS_INPUT input)
{
VS_OUTPUT output;
output.p = input.p;
output.t = input.t;
return output;
}
PS_OUTPUT ps_main0(PS_INPUT input)
{
PS_OUTPUT output;
output.c = sample_c(input.t);
return output;
}
PS_OUTPUT ps_main7(PS_INPUT input)
{
PS_OUTPUT output;
float4 c = sample_c(input.t);
c.a = dot(c.rgb, float3(0.299, 0.587, 0.114));
output.c = c;
return output;
}
float4 ps_crt(PS_INPUT input, int i)
{
float4 mask[4] =
{
float4(1, 0, 0, 0),
float4(0, 1, 0, 0),
float4(0, 0, 1, 0),
float4(1, 1, 1, 0)
};
return sample_c(input.t) * saturate(mask[i] + 0.5f);
}
uint ps_main1(PS_INPUT input) : SV_Target0
{
float4 c = sample_c(input.t);
c.a *= 256.0f / 127; // hm, 0.5 won't give us 1.0 if we just multiply with 2
uint4 i = c * float4(0x001f, 0x03e0, 0x7c00, 0x8000);
return (i.x & 0x001f) | (i.y & 0x03e0) | (i.z & 0x7c00) | (i.w & 0x8000);
}
PS_OUTPUT ps_main2(PS_INPUT input)
{
PS_OUTPUT output;
clip(sample_c(input.t).a - 128.0f / 255); // >= 0x80 pass
output.c = 0;
return output;
}
PS_OUTPUT ps_main3(PS_INPUT input)
{
PS_OUTPUT output;
clip(127.95f / 255 - sample_c(input.t).a); // < 0x80 pass (== 0x80 should not pass)
output.c = 0;
return output;
}
PS_OUTPUT ps_main4(PS_INPUT input)
{
PS_OUTPUT output;
output.c = fmod(sample_c(input.t) * 255 + 0.5f, 256) / 255;
return output;
}
PS_OUTPUT ps_main5(PS_INPUT input) // triangular
{
PS_OUTPUT output;
uint4 p = (uint4)input.p;
// output.c = ps_crt(input, ((p.x + (p.y & 1) * 3) >> 1) % 3);
output.c = ps_crt(input, ((p.x + ((p.y >> 1) & 1) * 3) >> 1) % 3);
return output;
}
PS_OUTPUT ps_main6(PS_INPUT input) // diagonal
{
PS_OUTPUT output;
uint4 p = (uint4)input.p;
output.c = ps_crt(input, (p.x + (p.y % 3)) % 3);
return output;
}
#endif

View File

@ -0,0 +1,46 @@
#if 0
Texture2D Texture;
SamplerState Sampler;
cbuffer cb0
{
float2 ZrH;
float hH;
};
struct PS_INPUT
{
float4 p : SV_Position;
float2 t : TEXCOORD0;
};
float4 ps_main0(PS_INPUT input) : SV_Target0
{
clip(frac(input.t.y * hH) - 0.5);
return Texture.Sample(Sampler, input.t);
}
float4 ps_main1(PS_INPUT input) : SV_Target0
{
clip(0.5 - frac(input.t.y * hH));
return Texture.Sample(Sampler, input.t);
}
float4 ps_main2(PS_INPUT input) : SV_Target0
{
float4 c0 = Texture.Sample(Sampler, input.t - ZrH);
float4 c1 = Texture.Sample(Sampler, input.t);
float4 c2 = Texture.Sample(Sampler, input.t + ZrH);
return (c0 + c1 * 2 + c2) / 4;
}
float4 ps_main3(PS_INPUT input) : SV_Target0
{
return Texture.Sample(Sampler, input.t);
}
#endif

View File

@ -0,0 +1,31 @@
#if 0
Texture2D Texture;
SamplerState Sampler;
cbuffer cb0
{
float4 BGColor;
};
struct PS_INPUT
{
float4 p : SV_Position;
float2 t : TEXCOORD0;
};
float4 ps_main0(PS_INPUT input) : SV_Target0
{
float4 c = Texture.Sample(Sampler, input.t);
c.a = min(c.a * 2, 1);
return c;
}
float4 ps_main1(PS_INPUT input) : SV_Target0
{
float4 c = Texture.Sample(Sampler, input.t);
c.a = BGColor.a;
return c;
}
#endif

View File

@ -113,8 +113,14 @@ using namespace stdext;
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <GL/glext.h>
// Need to have glew 1.7 but Debian/Ubuntu is only 1.6
// We will see later for the upgrade
typedef void (GLAPIENTRY * PFNGLTEXSTORAGE2DPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
extern PFNGLTEXSTORAGE2DPROC glTexStorage2D_glew17;
//using namespace __gnu_cxx;
#define DIRECTORY_SEPARATOR '/'