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}")

File diff suppressed because it is too large Load Diff

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,43 +54,46 @@ struct GSDepthStencilOGL {
};
struct GSUniformBufferOGL {
GLuint buffer;
GLuint index;
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
GSUniformBufferOGL* cb; // uniform buffer object
GLuint ps[2]; // program object
GSUniformBufferOGL* cb; // uniform buffer object
GSBlendStateOGL* bs;
} m_merge;
struct {
GLuint ps[4]; // program object
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
{
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 '/'