gsdx-ogl: preliminary work of an opengl backend. So far only skeleton and various note.

Current goal is to implement the SW render with pure opengl instead of SDL.
I plan to use OpenGL4.2 capability (the latest actually) => need libglew1.7 and a Dx11 capable GPU/drivers.


git-svn-id: http://pcsx2.googlecode.com/svn/branches/gsdx-ogl@4970 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
gregory.hainaut 2011-11-16 22:17:37 +00:00
parent b2ba781df8
commit da66ca7fd9
16 changed files with 1488 additions and 8 deletions

View File

@ -58,6 +58,7 @@ set(GSdxSources
GSCodeBuffer.cpp
GSCrc.cpp
GSDevice.cpp
GSDeviceOGL.cpp
GSDeviceSDL.cpp
GSDeviceSW.cpp
GSDeviceNull.cpp
@ -76,6 +77,7 @@ set(GSdxSources
GSRasterizer.cpp
GSRenderer.cpp
GSRendererNull.cpp
GSRendererOGL.cpp
GSRendererSW.cpp
GSSetting.cpp
GSSetupPrimCodeGenerator.cpp
@ -88,6 +90,8 @@ set(GSdxSources
GSTexture.cpp
GSTextureCache.cpp
GSTextureCacheSW.cpp
GSTextureCacheOGL.cpp
GSTextureOGL.cpp
GSTextureNull.cpp
GSTextureSW.cpp
GSThread.cpp
@ -123,6 +127,7 @@ set(GSdxHeaders
GSCodeBuffer.h
GSCrc.h
GSDevice.h
GSDeviceOGL.h
GSDeviceNull.h
GSDirtyRect.h
GSDrawScanline.h
@ -137,6 +142,8 @@ set(GSdxHeaders
GSRenderer.h
GSRendererNull.h
GSRendererSW.h
GSRendererHW.h
GSRendererOGL.h
GSScanlineEnvironment.h
GSSetting.h
GSSetupPrimCodeGenerator.h
@ -145,6 +152,7 @@ set(GSdxHeaders
GSTexture.h
GSTextureCache.h
GSTextureCacheSW.h
GSTextureCacheOGL.h
GSTextureNull.h
GSThread.h
GSUtil.h

View File

@ -39,6 +39,9 @@ static HRESULT s_hr = E_FAIL;
#else
#include "GSDeviceOGL.h"
#include "GSRendererOGL.h"
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
@ -215,6 +218,7 @@ static int _GSopen(void** dsp, char* title, int renderer, int threads = -1)
#endif
case 2: dev = new GSDeviceSDL(); break;
case 3: dev = new GSDeviceNull(); break;
case 4: dev = new GSDeviceOGL(); break;
}
if(dev == NULL)
@ -227,11 +231,13 @@ static int _GSopen(void** dsp, char* title, int renderer, int threads = -1)
switch(renderer % 3)
{
default:
#ifdef _WINDOWS
case 0:
#ifdef _WINDOWS
s_gs = (renderer / 3) == 0 ? (GSRenderer*)new GSRendererDX9() : (GSRenderer*)new GSRendererDX11();
break;
#else
s_gs = (GSRenderer*)new GSRendererOGL();
#endif
break;
case 1:
s_gs = new GSRendererSW(threads);
break;

View File

@ -0,0 +1,643 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "GSDeviceOGL.h"
// Various Note: separate build of shader
// ************************** BUILD METHOD 1
// 1/ create a stand alone prog
// uint CreateShaderProgramv( enum type, sizei count, const char **strings );
// 2/ Create various prog pipeline (maybe 1 foreach combination or only 1)
// glGenProgramPipelines
// 3/ Attach a program to a pipeline
// void UseProgramStages( uint pipeline, bitfield stages, uint program );
// ...
// ...
// 5/ Before the use of the program, we can validate it. (mandatory or not ?)
// glValidateProgramPipeline
//
// ************************** BUILD METHOD 2
// Humm, there is another solutions. You can setup function pointer in GLSL and configure them with OPENGL. shader_subroutine. glUseProgram must be replace with glUseProgramInstance in this case (and instance must be managed)
//GL EXT: Overview
//GL EXT:
//GL EXT: This extension adds support to shaders for "indirect subroutine calls",
//GL EXT: where a single shader can include many subroutines and dynamically select
//GL EXT: through the API which subroutine is called from each call site.
//GL EXT: Switching subroutines dynamically in this fashion can avoid the cost of
//GL EXT: recompiling and managing multiple shaders, while still retaining most of
//GL EXT: the performance of specialized shaders.
//
// ************************** Uniform buffer
// // Note don't know how to chose block_binding_point (probably managed like texture unit
// maybe any number will be fine)
// index=glGetUniformBlockIndex(program, "BlockName");
// glBindBufferBase(GL_UNIFORM_BUFFER, block_binding_point, some_buffer_object);
// glUniformBlockBinding(program, block_index, block_binding_point);
GSDeviceOGL::GSDeviceOGL()
{
/* TODO */
m_msaa = theApp.GetConfig("msaa", 0);
}
GSDeviceOGL::~GSDeviceOGL() { /* TODO */ }
GSTexture* GSDeviceOGL::CreateSurface(int type, int w, int h, bool msaa, int format)
{
// A wrapper to call GSTextureOGL, with the different kind of parameter
}
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
#if 0
if(m_msaa < 2) {
msaa = false;
}
#endif
msaa = false;
return GSDevice::FetchSurface(type, w, h, msaa, format);
}
bool GSDeviceOGL::Create(GSWnd* wnd)
{
/* TODO */
}
bool GSDeviceOGL::Reset(int w, int h)
{
// Hum map, m_backbuffer to a GSTexture
}
// Swap buffer (back buffer, front buffer)
// Warning it is not OGL dependent but application dependant (glx and so not portable)
void GSDeviceOGL::Flip() { /* TODO */ }
// 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 */ }
// 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 */ }
// blit a texture into an offscreen buffer
GSTexture* GSDeviceOGL::CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format)
{
// Need to find format equivalent. Then I think it will be straight forward
// A four-component, 32-bit unsigned-normalized-integer format that supports 8 bits per channel including alpha.
// DXGI_FORMAT_R8G8B8A8_UNORM <=> GL_RGBA8
// A single-component, 16-bit unsigned-integer format that supports 16 bits for the red channel
// DXGI_FORMAT_R16_UINT <=> GL_R16
#if 0
GSTexture* dst = NULL;
if(format == 0)
{
format = DXGI_FORMAT_R8G8B8A8_UNORM;
}
if(format != DXGI_FORMAT_R8G8B8A8_UNORM && format != DXGI_FORMAT_R16_UINT)
{
ASSERT(0);
return false;
}
if(GSTexture* rt = CreateRenderTarget(w, h, false, format))
{
GSVector4 dr(0, 0, w, h);
if(GSTexture* src2 = src->IsMSAA() ? Resolve(src) : src)
{
StretchRect(src2, sr, rt, dr, m_convert.ps[format == DXGI_FORMAT_R16_UINT ? 1 : 0], NULL);
if(src2 != src) Recycle(src2);
}
dst = CreateOffscreen(w, h, format);
if(dst)
{
m_ctx->CopyResource(*(GSTexture11*)dst, *(GSTexture11*)rt);
}
Recycle(rt);
}
return dst;
#endif
}
// Copy a sub part of a texture into another
// Several question to answer did texture have same size?
// From a sub-part to the same sub-part
// 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};
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 */
}
void GSDeviceOGL::StretchRect(GSTexture* st, const GSVector4& sr, GSTexture* dt, const GSVector4& dr, GLuint ps, GSUniformBufferOGL* ps_cb, bool linear)
{
// TODO
}
// 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)
{
#if 0
if(!st || !dt)
{
ASSERT(0);
return;
}
BeginScene();
GSVector2i ds = dt->GetSize();
// om
OMSetDepthStencilState(m_convert.dss, 0);
OMSetBlendState(bs, 0);
OMSetRenderTargets(dt, NULL);
// ia
float left = dr.x * 2 / ds.x - 1.0f;
float top = 1.0f - dr.y * 2 / ds.y;
float right = dr.z * 2 / ds.x - 1.0f;
float bottom = 1.0f - dr.w * 2 / ds.y;
GSVertexPT1 vertices[] =
{
{GSVector4(left, top, 0.5f, 1.0f), GSVector2(sr.x, sr.y)},
{GSVector4(right, top, 0.5f, 1.0f), GSVector2(sr.z, sr.y)},
{GSVector4(left, bottom, 0.5f, 1.0f), GSVector2(sr.x, sr.w)},
{GSVector4(right, bottom, 0.5f, 1.0f), GSVector2(sr.z, sr.w)},
};
IASetVertexBuffer(vertices, sizeof(vertices[0]), countof(vertices));
IASetInputLayout(m_convert.il);
IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
// vs
VSSetShader(m_convert.vs, NULL);
// gs
GSSetShader(NULL);
// ps
PSSetShaderResources(st, NULL);
PSSetSamplerState(linear ? m_convert.ln : m_convert.pt, NULL);
PSSetShader(ps, ps_cb);
//
DrawPrimitive();
//
EndScene();
PSSetShaderResources(NULL, NULL);
#endif
}
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)
{
StretchRect(st[1], sr[1], dt, dr[1], m_merge.ps[0], NULL, true);
}
if(st[0])
{
m_ctx->UpdateSubresource(m_merge.cb, 0, NULL, &c, 0, 0);
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);
GSVector4 dr(0.0f, yoffset, s.x, s.y + yoffset);
InterlaceConstantBuffer cb;
cb.ZrH = GSVector2(0, 1.0f / s.y);
cb.hH = s.y / 2;
m_ctx->UpdateSubresource(m_interlace.cb, 0, NULL, &cb, 0, 0);
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(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::IASetVertexBuffer(const void* vertices, size_t stride, size_t count)
{
ASSERT(m_vertices.count == 0);
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;
m_vertices.start = 0;
m_vertices.count = 0;
m_vertices.limit = std::max<int>(count * 3 / 2, 11000);
#endif
}
if(m_vb == NULL)
{
// 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
}
// 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
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)
{
if(m_state.layout != layout)
{
m_state.layout = layout;
m_ctx->IASetInputLayout(layout);
}
}
#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);
}
#endif
// glBindBufferBase
#if 0
if(m_state.vs_cb != vs_cb)
{
m_state.vs_cb = vs_cb;
m_ctx->VSSetConstantBuffers(0, 1, &vs_cb);
}
#endif
}
void GSDeviceOGL::GSSetShader(GLuint gs)
{
// glUseProgramStage
#if 0
if(m_state.gs != gs)
{
m_state.gs = gs;
m_ctx->GSSetShader(gs, NULL, 0);
}
#endif
}
void GSDeviceOGL::PSSetShaderResources(GSTexture* sr0, GSTexture* sr1)
{
PSSetShaderResource(0, sr0);
PSSetShaderResource(1, sr1);
PSSetShaderResource(2, NULL);
}
void GSDeviceOGL::PSSetShaderResource(int i, GSTexture* sr)
{
#if 0
ID3D11ShaderResourceView* srv = NULL;
if(sr) srv = *(GSTexture11*)sr;
if(m_state.ps_srv[i] != srv)
{
m_state.ps_srv[i] = srv;
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;
m_state.ps_ss[1] = ss1;
m_state.ps_ss[2] = 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);
}
#endif
// Sampler and texture must be set at the same time
// 1/ select the texture unit
// glActiveTexture(GL_TEXTURE0 + 1);
// 2/ bind the texture
// glBindTexture(GL_TEXTURE_2D , brickTexture);
// 3/ sets the texture sampler in GLSL (could be useless with layout stuff)
// glUniform1i(brickSamplerId , 1);
// 4/ set the sampler state
// glBindSampler(1 , sampler);
#if 0
if (m_srv_changed)
{
m_ctx->PSSetShaderResources(0, 3, m_state.ps_srv);
m_srv_changed = false;
}
if(m_ss_changed)
{
m_ctx->PSSetSamplers(0, 3, m_state.ps_ss);
m_ss_changed = false;
}
#endif
// glBindBufferBase
#if 0
if(m_state.ps_cb != ps_cb)
{
m_state.ps_cb = ps_cb;
m_ctx->PSSetConstantBuffers(0, 1, &ps_cb);
}
#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
if(m_state.dss != dss || m_state.sref != sref)
{
m_state.dss = dss;
m_state.sref = sref;
m_ctx->OMSetDepthStencilState(dss, sref);
}
#endif
}
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};
m_ctx->OMSetBlendState(bs, BlendFactor, 0xffffffff);
}
#endif
}
void GSDeviceOGL::OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor)
{
// set the attachment inside the FBO
#if 0
ID3D11RenderTargetView* rtv = NULL;
ID3D11DepthStencilView* dsv = NULL;
if(rt) rtv = *(GSTexture11*)rt;
if(ds) dsv = *(GSTexture11*)ds;
if(m_state.rtv != rtv || m_state.dsv != dsv)
{
m_state.rtv = rtv;
m_state.dsv = dsv;
m_ctx->OMSetRenderTargets(1, &rtv, dsv);
}
#endif
// 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);
}
#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;
m_ctx->RSSetScissorRects(1, r);
}
#endif
}

242
plugins/GSdx/GSDeviceOGL.h Normal file
View File

@ -0,0 +1,242 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSDevice.h"
#include "GSTextureOGL.h"
#include "GSdx.h"
struct GSBlendStateOGL {
// Note: You can also select the index of the draw buffer for which to set the blend setting
// We will keep basic the first try
bool m_enable;
GLenum m_equation_RGB;
GLenum m_equation_ALPHA;
GLenum m_func_RGB;
GLenum m_func_ALPHA;
};
struct GSDepthStencilOGL {
bool m_depth_enable;
GLenum m_depth_func;
// 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;
GLuint m_stencil_func;
GLuint m_stencil_ref;
GLuint m_stencil_sfail_op;
GLuint m_stencil_spass_dfail_op;
GLuint m_stencil_spass_dpass_op;
};
struct GSUniformBufferOGL {
GLuint buffer;
GLuint index;
};
class GSDeviceOGL : public GSDevice
{
uint32 m_msaa;
// Vertex buffer: glGenBuffers, glBindBuffer GL_ARRAY_BUFFER
GLuint m_vb; // buffer object
struct {
GLuint ps[2]; // program object
GSUniformBufferOGL* cb; // uniform buffer object
GSBlendStateOGL* bs;
} m_merge;
struct {
GLuint ps[4]; // program object
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
{
// 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;
GLuint vs; // program object
GLuint ps[8]; // program object
GLuint ln; // sampler object
GLuint pt; // sampler object
GSDepthStencilOGL* dss;
GSBlendStateOGL* bs;
} m_convert;
// struct
// {
// CComPtr<ID3D11DepthStencilState> dss;
// CComPtr<ID3D11BlendState> bs;
// } m_date;
struct
{
GSDepthStencilOGL* dss;
GSBlendStateOGL* bs;
} m_date;
// struct
// {
// ID3D11Buffer* vb;
// size_t vb_stride;
// ID3D11InputLayout* layout;
// D3D11_PRIMITIVE_TOPOLOGY topology;
// ID3D11VertexShader* vs;
// ID3D11Buffer* vs_cb;
// ID3D11GeometryShader* gs;
// ID3D11ShaderResourceView* ps_srv[3];
// ID3D11PixelShader* ps;
// ID3D11Buffer* ps_cb;
// ID3D11SamplerState* ps_ss[3];
// GSVector2i viewport;
// GSVector4i scissor;
// ID3D11DepthStencilState* dss;
// uint8 sref;
// ID3D11BlendState* bs;
// float bf;
// ID3D11RenderTargetView* rtv;
// ID3D11DepthStencilView* dsv;
// } m_state;
struct
{
GLuint vb;
// Hum I think those things can be dropped on OGL. It probably need an others architecture (see glVertexAttribPointer)
// size_t vb_stride;
// ID3D11InputLayout* layout;
GLenum topology; // (ie GL_TRIANGLES...)
GLuint vs; // program
GSUniformBufferOGL* vs_cb; // uniform 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* ps_cb; // uniform buffer
GLuint ps_ss[3]; // sampler
GSVector2i viewport;
GSVector4i scissor;
GSDepthStencilOGL* dss;
uint8 sref;
GSBlendStateOGL* bs;
float bf;
// FIXME texture attachment in the FBO
// ID3D11RenderTargetView* rtv;
// ID3D11DepthStencilView* dsv;
} m_state;
bool m_srv_changed;
bool m_ss_changed;
#if 0
CComPtr<ID3D11Device> m_dev;
CComPtr<ID3D11DeviceContext> m_ctx;
CComPtr<IDXGISwapChain> m_swapchain;
CComPtr<ID3D11RasterizerState> m_rs;
struct
{
CComPtr<ID3D11PixelShader> ps;
CComPtr<ID3D11Buffer> cb;
} m_fxaa;
// Shaders...
hash_map<uint32, GSVertexShader11 > m_vs;
CComPtr<ID3D11Buffer> m_vs_cb;
hash_map<uint32, CComPtr<ID3D11GeometryShader> > m_gs;
hash_map<uint32, CComPtr<ID3D11PixelShader> > m_ps;
CComPtr<ID3D11Buffer> m_ps_cb;
hash_map<uint32, CComPtr<ID3D11SamplerState> > m_ps_ss;
CComPtr<ID3D11SamplerState> m_palette_ss;
CComPtr<ID3D11SamplerState> m_rt_ss;
hash_map<uint32, CComPtr<ID3D11DepthStencilState> > m_om_dss;
hash_map<uint32, CComPtr<ID3D11BlendState> > m_om_bs;
VSConstantBuffer m_vs_cb_cache;
PSConstantBuffer m_ps_cb_cache;
#endif
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);
void DoMerge(GSTexture* st[2], GSVector4* sr, GSTexture* dt, GSVector4* dr, bool slbg, bool mmod, const GSVector4& c);
void DoInterlace(GSTexture* st, GSTexture* dt, int shader, bool linear, float yoffset = 0);
public:
GSDeviceOGL();
virtual ~GSDeviceOGL();
bool Create(GSWnd* wnd);
bool Reset(int w, int h);
void Flip();
void DrawPrimitive();
void ClearRenderTarget(GSTexture* t, const GSVector4& c);
void ClearRenderTarget(GSTexture* t, uint32 c);
void ClearDepth(GSTexture* t, float c);
void ClearStencil(GSTexture* t, uint8 c);
GSTexture* CreateRenderTarget(int w, int h, bool msaa, int format = 0);
GSTexture* CreateDepthStencil(int w, int h, bool msaa, int format = 0);
GSTexture* CreateTexture(int w, int h, int format = 0);
GSTexture* CreateOffscreen(int w, int h, int format = 0);
GSTexture* CopyOffscreen(GSTexture* src, const GSVector4& sr, int w, int h, int format = 0);
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);
GSTexture* Resolve(GSTexture* t);
void IASetVertexBuffer(const void* vertices, size_t stride, size_t count);
void VSSetShader(GLuint vs, GSUniformBufferOGL* vs_cb);
void GSSetShader(GLuint gs);
void PSSetShaderResources(GSTexture* sr0, GSTexture* sr1);
void PSSetShaderResource(int i, GSTexture* sr);
void PSSetSamplerState(GLuint ss0, GLuint ss1, GLuint ss2);
void PSSetShader(GLuint ps, GSUniformBufferOGL* ps_cb);
void OMSetDepthStencilState(GSDepthStencilOGL* dss, uint8 sref);
void OMSetBlendState(GSBlendStateOGL* bs, float bf);
void OMSetRenderTargets(GSTexture* rt, GSTexture* ds, const GSVector4i* scissor = NULL);
};

View File

@ -42,6 +42,7 @@ 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;
@ -76,10 +77,25 @@ bool RunLinuxDialog()
if(!s.note.empty()) label += format(" (%s)", s.note.c_str());
// (dev only) for any NULL stuff
if (i >= 7 && i <= 9) label += " (debug only)";
// (experimental) for opengl stuff
if (i == 10 || i == 11) label += " (experimental)";
gtk_combo_box_append_text(GTK_COMBO_BOX(render_combo_box), label.c_str());
}
gtk_combo_box_set_active(GTK_COMBO_BOX(render_combo_box), 0);
int renderer_box_position = 0;
switch (theApp.GetConfig("renderer", 0)) {
// Note the value are based on m_gs_renderers vector on GSdx.cpp
case 7 : renderer_box_position = 0; break;
case 8 : renderer_box_position = 1; break;
case 10: renderer_box_position = 2; break;
case 11: renderer_box_position = 3; break;
case 12: renderer_box_position = 4; break;
case 13: renderer_box_position = 5; break;
}
gtk_combo_box_set_active(GTK_COMBO_BOX(render_combo_box), renderer_box_position );
gtk_container_add(GTK_CONTAINER(main_box), render_label);
gtk_container_add(GTK_CONTAINER(main_box), render_combo_box);
@ -142,12 +158,22 @@ bool RunLinuxDialog()
if (return_value == GTK_RESPONSE_ACCEPT)
{
// Get all the settings from the dialog box.
if (gtk_combo_box_get_active(GTK_COMBO_BOX(render_combo_box)) != -1) {
// FIXME test current opengl version supported through glxinfo (OpenGL version string:)
// Warn the user if 4.2 is not supported and switch back to basic SDL renderer
switch (gtk_combo_box_get_active(GTK_COMBO_BOX(render_combo_box))) {
// Note the value are based on m_gs_renderers vector on GSdx.cpp
case 0: theApp.SetConfig("renderer", 7); break;
case 1: theApp.SetConfig("renderer", 8); break;
case 2: theApp.SetConfig("renderer", 10); break;
case 3: theApp.SetConfig("renderer", 11); break;
case 4: theApp.SetConfig("renderer", 12); break;
case 5: theApp.SetConfig("renderer", 13); break;
}
}
#if 0
// I'll put the right variable names in later.
if (gtk_combo_box_get_active(GTK_COMBO_BOX(render_combo_box)) != -1)
renderer = gtk_combo_box_get_active(GTK_COMBO_BOX(render_combo_box));
// Crash, for some interlace options
if (gtk_combo_box_get_active(GTK_COMBO_BOX(interlace_combo_box)) != -1)
theApp.SetConfig( "interlace", (int)gtk_combo_box_get_active(GTK_COMBO_BOX(interlace_combo_box)) );

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "GSRendererOGL.h"
#include "GSRenderer.h"
GSRendererOGL::GSRendererOGL()
// FIXME
//: GSRendererHW<GSVertexHWOGL>(new GSTextureCacheOGL(this))
: GSRendererHW<GSVertexHW11>(new GSTextureCacheOGL(this))
{
// TODO must be implementer with macro InitVertexKick(GSRendererOGL)
// template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
InitVertexKick(GSRendererOGL);
}
GSRendererOGL::~GSRendererOGL() { /* TODO */ }
bool GSRendererOGL::CreateDevice(GSDevice* dev) { /* TODO */ }
template<uint32 prim, uint32 tme, uint32 fst>
void GSRendererOGL::VertexKick(bool skip) { /* TODO */ }
void GSRendererOGL::Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex) { /* TODO */ }

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSRendererHW.h"
#include "GSRenderer.h"
#include "GSTextureCacheOGL.h"
#include "GSVertexHW.h"
// FIXME does it need a GSVertexHWOGL ??? Data order can be easily programmed on opengl (the only potential
// issue is the unsupported praga push/pop
// Note it impact GSVertexTrace.cpp => void GSVertexTrace::Update(const GSVertexHWOGL* v, int count, GS_PRIM_CLASS primclass)
class GSRendererOGL : public GSRendererHW<GSVertexHW11>
//class GSRendererOGL : public GSRendererHW<GSVertexHWOGL>
{
private:
protected:
GSTextureCache* m_tc;
void Draw(GSTexture* rt, GSTexture* ds, GSTextureCache::Source* tex);
public:
GSRendererOGL();
virtual ~GSRendererOGL();
template<uint32 prim, uint32 tme, uint32 fst> void VertexKick(bool skip);
bool CreateDevice(GSDevice* dev);
};

View File

@ -21,6 +21,8 @@
#pragma once
#include "stdafx.h"
struct GSSetting
{
uint32 id;

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "GSTextureCacheOGL.h"
GSTextureCacheOGL::GSTextureCacheOGL(GSRenderer* r)
: GSTextureCache(r)
{
}
void GSTextureCacheOGL::Read(Target* t, const GSVector4i& r)
{
// Except format (CopyOffscreen method), everything else seem portable
#if 0
if(t->m_type != RenderTarget)
{
// TODO
return;
}
const GIFRegTEX0& TEX0 = t->m_TEX0;
if(TEX0.PSM != PSM_PSMCT32
&& TEX0.PSM != PSM_PSMCT24
&& TEX0.PSM != PSM_PSMCT16
&& TEX0.PSM != PSM_PSMCT16S)
{
//ASSERT(0);
return;
}
if(!t->m_dirty.empty())
{
return;
}
// printf("GSRenderTarget::Read %d,%d - %d,%d (%08x)\n", r.left, r.top, r.right, r.bottom, TEX0.TBP0);
int w = r.width();
int h = r.height();
GSVector4 src = GSVector4(r) * GSVector4(t->m_texture->GetScale()).xyxy() / GSVector4(t->m_texture->GetSize()).xyxy();
DXGI_FORMAT format = TEX0.PSM == PSM_PSMCT16 || TEX0.PSM == PSM_PSMCT16S ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R8G8B8A8_UNORM;
if(GSTexture* offscreen = m_renderer->m_dev->CopyOffscreen(t->m_texture, src, w, h, format))
{
GSTexture::GSMap m;
if(offscreen->Map(m))
{
// TODO: block level write
GSOffset* o = m_renderer->m_mem.GetOffset(TEX0.TBP0, TEX0.TBW, TEX0.PSM);
switch(TEX0.PSM)
{
case PSM_PSMCT32:
m_renderer->m_mem.WritePixel32(m.bits, m.pitch, o, r);
break;
case PSM_PSMCT24:
m_renderer->m_mem.WritePixel24(m.bits, m.pitch, o, r);
break;
case PSM_PSMCT16:
case PSM_PSMCT16S:
m_renderer->m_mem.WritePixel16(m.bits, m.pitch, o, r);
break;
default:
ASSERT(0);
}
offscreen->Unmap();
}
m_renderer->m_dev->Recycle(offscreen);
}
#endif
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
* http://www.gabest.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSTextureCache.h"
#include "GSDeviceOGL.h"
class GSTextureCacheOGL : public GSTextureCache
{
protected:
int Get8bitFormat() {/* TODO return DXGI_FORMAT_A8_UNORM;*/}
void Read(Target* t, const GSVector4i& r);
public:
GSTextureCacheOGL(GSRenderer* r);
};

View File

@ -0,0 +1,257 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSTextureOGL.h"
GSTextureOGL::GSTextureOGL(/* ID3D11Texture2D* texture */ )
{
// *************************************************************
// Opengl world
// http://www.opengl.org/wiki/Renderbuffer_Object
// render: constructor -> glGenRenderbuffers, glDeleteRenderbuffers
// info -> glGetRenderbufferParameteriv, glIsRenderbuffer
// binding -> glBindRenderbuffer (only 1 target), glFramebufferRenderbuffer (attach actually)
// setup param -> glRenderbufferStorageMultisample (after this call the buffer is unitialized)
//
// the only way to use a renderbuffer object is to attach it to a Framebuffer Object. After you bind that
// FBO to the context, and set up the draw or read buffers appropriately, you can use pixel transfer operations
// to read and write to it. Of course, you can also render to it. The standard glClear function will also clear the appropriate buffer.
//
// Render work in parallal with framebuffer object (FBO) http://www.opengl.org/wiki/Framebuffer_Objects
// render are attached to FBO through : glFramebufferRenderbuffer. You can query the number of colorattachement with GL_MAX_COLOR_ATTACHMENTS
// FBO : constructor -> glGenFramebuffers, glDeleteFramebuffers
// binding -> glBindFramebuffer (target can be read/write/both)
// blit -> glBlitFramebuffer (read FB to draw FB)
// info -> glIsFramebuffer, glGetFramebufferAttachmentParameter, glCheckFramebufferStatus
//
// There are two types of framebuffer-attachable images; texture images and renderbuffer images.
// If an image of a texture object is attached to a framebuffer, OpenGL performs "render to texture".
// And if an image of a renderbuffer object is attached to a framebuffer, then OpenGL performs "offscreen rendering".
// Blitting:
// glDrawBuffers
// glReadBuffer
// glBlitFramebuffer
// *************************************************************
// Doc
// It might need a texture structure to replace ID3D11Texture2D.
//
// == The function need to set (from parameter)
// : m_size.x
// : m_size.y
// : m_type
// : m_format
// : m_msaa
// == Might be useful to save
// : m_texture_target (like GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE etc...)
// : m_texture_id (return by glGen*)
//
// == Then generate the texture or buffer.
// D3D11_BIND_RENDER_TARGET: Bind a texture as a render target for the output-merger stage.
// => glGenRenderbuffers with GL_COLOR_ATTACHMENTi (Hum glGenTextures might work too)
// D3D11_BIND_DEPTH_STENCIL: Bind a texture as a depth-stencil target for the output-merger stage.
// => glGenRenderbuffers with GL_DEPTH_STENCIL_ATTACHMENT
// D3D11_BIND_SHADER_RESOURCE: Bind a buffer or texture to a shader stage
// => glGenTextures
// D3D11_USAGE_STAGING: A resource that supports data transfer (copy) from the GPU to the CPU.
// glGenTextures
// glReadPixels seems to use a framebuffer. In this case you can setup the source
// with glReadBuffer(GL_COLOR_ATTACHMENTi)
// 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
#if 0
m_texture->GetDevice(&m_dev);
m_texture->GetDesc(&m_desc);
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
}
GSTextureOGL::~GSTextureOGL()
{
// glDeleteTextures or glDeleteRenderbuffers
}
void GSTextureOGL::EnableUnit()
{
// == 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 ???
}
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
#if 0
if(m_dev && m_texture)
{
D3D11_BOX box = {r.left, r.top, 0, r.right, r.bottom, 1};
m_ctx->UpdateSubresource(m_texture, 0, &box, data, pitch, 0);
return true;
}
return false;
#endif
}
bool GSTextureOGL::Map(GSMap& m, const GSVector4i* r)
{
// The function allow to modify the texture from the CPU
// Set m.bits <- pointer to the data
// Set m.pitch <- size of a row
// 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
#if 0
if(r != NULL)
{
// ASSERT(0); // not implemented
return false;
}
if(m_texture && m_desc.Usage == D3D11_USAGE_STAGING)
{
D3D11_MAPPED_SUBRESOURCE map;
if(SUCCEEDED(m_ctx->Map(m_texture, 0, D3D11_MAP_READ_WRITE, 0, &map)))
{
m.bits = (uint8*)map.pData;
m.pitch = (int)map.RowPitch;
return true;
}
}
return false;
#endif
}
void GSTextureOGL::Unmap()
{
// copy the texture to the GPU
// GLboolean glUnmapBuffer(GLenum target);
#if 0
if(m_texture)
{
m_ctx->Unmap(m_texture, 0);
}
#endif
}
// If I'm correct, this function only dump some buffer. Debug only, still very useful!
// Note: check zzogl implementation
bool GSTextureOGL::Save(const string& fn, bool dds)
{
#if 0
CComPtr<ID3D11Resource> res;
if(m_desc.BindFlags & D3D11_BIND_DEPTH_STENCIL)
{
HRESULT hr;
D3D11_TEXTURE2D_DESC desc;
memset(&desc, 0, sizeof(desc));
m_texture->GetDesc(&desc);
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
CComPtr<ID3D11Texture2D> src, dst;
hr = m_dev->CreateTexture2D(&desc, NULL, &src);
m_ctx->CopyResource(src, m_texture);
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
hr = m_dev->CreateTexture2D(&desc, NULL, &dst);
D3D11_MAPPED_SUBRESOURCE sm, dm;
hr = m_ctx->Map(src, 0, D3D11_MAP_READ, 0, &sm);
hr = m_ctx->Map(dst, 0, D3D11_MAP_WRITE, 0, &dm);
uint8* s = (uint8*)sm.pData;
uint8* d = (uint8*)dm.pData;
for(uint32 y = 0; y < desc.Height; y++, s += sm.RowPitch, d += dm.RowPitch)
{
for(uint32 x = 0; x < desc.Width; x++)
{
((uint32*)d)[x] = (uint32)(ldexpf(((float*)s)[x*2], 32));
}
}
m_ctx->Unmap(src, 0);
m_ctx->Unmap(dst, 0);
res = dst;
}
else
{
res = m_texture;
}
return SUCCEEDED(D3DX11SaveTextureToFile(m_ctx, res, dds ? D3DX11_IFF_DDS : D3DX11_IFF_BMP, fn.c_str()));
#endif
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2011-2011 Gregory hainaut
* Copyright (C) 2007-2009 Gabest
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "GSTexture.h"
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();
public:
explicit GSTextureOGL();
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);
};

View File

@ -33,7 +33,7 @@ public:
{
m_base = _aligned_malloc(sizeof(Vertex) * countof(m_v), 32);
for(int i = 0; i < countof(m_v); i++)
for(uint i = 0; i < countof(m_v); i++)
{
m_v[i] = &((Vertex*)m_base)[i];
}

View File

@ -376,6 +376,22 @@ bool GSWnd::Create(const string& title, int w, int h)
#endif
m_managed = true;
// If the user request OpenGL acceleration, we take recent OGL version (4.2)
// We keep the default 2.1 version in SW mode (only DX11 capable card, are compatible with OGL4)
if ( theApp.GetConfig("renderer", 0) / 3 == 4 ) {
// Setup visual attribute
SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 32 );
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
SDL_GL_SetAttribute( SDL_GL_ACCELERATED_VISUAL, 1 );
// Ask for an advance opengl version
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4 );
SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 );
}
m_window = SDL_CreateWindow(title.c_str(), 100, 100, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
// Get the X window from the newly created window

View File

@ -116,6 +116,8 @@ GSdxApp::GSdxApp()
m_gs_renderers.push_back(GSSetting(8, "SDL 1.3", "Null"));
m_gs_renderers.push_back(GSSetting(10, "Null", "Software"));
m_gs_renderers.push_back(GSSetting(11, "Null", "Null"));
m_gs_renderers.push_back(GSSetting(12, "OpenGL", "Hardware"));
m_gs_renderers.push_back(GSSetting(13, "OpenGL", "Software"));
m_gs_interlace.push_back(GSSetting(0, "None", ""));
m_gs_interlace.push_back(GSSetting(1, "Weave tff", "saw-tooth"));

View File

@ -111,6 +111,10 @@ using namespace stdext;
//#include <ext/hash_map>
//#include <ext/hash_set>
#include <GL/glew.h>
#include <GL/gl.h>
#include <GL/glext.h>
//using namespace __gnu_cxx;
#define DIRECTORY_SEPARATOR '/'
@ -333,4 +337,4 @@ extern void vmfree(void* ptr, size_t size);
//#define NO_CRC_HACKS // Disable all game specific hacks
#ifdef HW_NO_TEXTURE_CACHE
#define NO_CRC_HACKS
#endif
#endif