From 7621516c1ca0ecf9f80d094763a1705c32d7458f Mon Sep 17 00:00:00 2001 From: Chris Xiong Date: Mon, 12 Feb 2018 23:39:19 +0800 Subject: Now we have unified the GLFW versions (uglily). Also fixed a symbol conflict for the good old msvc. --- README.md | 6 +- examples/makefile | 5 +- smelt/glfw/gfx_glfw.cpp | 610 ++++++++++------------ smelt/glfw/gfx_glfw_compat.cpp | 1085 +++++++++++++++++++++++++++++++++++++++ smelt/glfw/makefile | 2 +- smelt/glfw/sfx_dumb.cpp | 3 +- smelt/glfw/sfx_oal.cpp | 2 +- smelt/glfw/smelt_config.hpp | 7 +- smelt/glfw/smelt_internal.hpp | 13 +- smelt/glfw/smmath_priv.hpp | 102 ++++ smelt/glfw/sys_glfw.cpp | 8 +- smelt/glfw_m/CxImage | 1 - smelt/glfw_m/gfx_glfw.cpp | 1028 ------------------------------------- smelt/glfw_m/inp_glfw.cpp | 204 -------- smelt/glfw_m/makefile | 27 - smelt/glfw_m/sfx_dumb.cpp | 63 --- smelt/glfw_m/sfx_oal.cpp | 368 ------------- smelt/glfw_m/smelt_config.hpp | 30 -- smelt/glfw_m/smelt_internal.hpp | 249 --------- smelt/glfw_m/smmath_priv.hpp | 165 ------ smelt/glfw_m/sys_glfw.cpp | 334 ------------ 21 files changed, 1498 insertions(+), 2814 deletions(-) create mode 100644 smelt/glfw/gfx_glfw_compat.cpp create mode 100644 smelt/glfw/smmath_priv.hpp delete mode 120000 smelt/glfw_m/CxImage delete mode 100644 smelt/glfw_m/gfx_glfw.cpp delete mode 100644 smelt/glfw_m/inp_glfw.cpp delete mode 100644 smelt/glfw_m/makefile delete mode 100644 smelt/glfw_m/sfx_dumb.cpp delete mode 100644 smelt/glfw_m/sfx_oal.cpp delete mode 100644 smelt/glfw_m/smelt_config.hpp delete mode 100644 smelt/glfw_m/smelt_internal.hpp delete mode 100644 smelt/glfw_m/smmath_priv.hpp delete mode 100644 smelt/glfw_m/sys_glfw.cpp diff --git a/README.md b/README.md index 4ed66b2..5519c5f 100644 --- a/README.md +++ b/README.md @@ -21,8 +21,10 @@ Additional building dependencies for the GLFW version on a debian-based system: >libglfw3-dev libglew-dev -Now there's a OpenGL 3.2+ port for the GLFW version which can be found -in the `glfw_m` folder. It is experimental and buggy. Use with caution. +With the GLFW version, you are now allowed to choose the OpenGL version +to use (at compile time). Refer to `smelt_config.hpp` in the +implementation folder for details. The OpenGL 3.2 port is still +experimental and buggy. Use with caution. Please also note that minor differences exist across different versions. diff --git a/examples/makefile b/examples/makefile index d25e638..c927ae7 100644 --- a/examples/makefile +++ b/examples/makefile @@ -4,9 +4,8 @@ LINK= -lSDL2 -lvorbis -lvorbisfile -lopenal -ljpeg -lpng -lfreetype -lz -lsmelte LINK_GLFW= -lglfw -lGLEW -lGL -lvorbis -lvorbisfile -lopenal -ljpeg -lpng -lfreetype -lz -lsmeltext -lsmelt -lCxImage LINK_FOLDER= -L../smelt/sdl -L../extensions LINK_GLFW_FOLDER= -L../smelt/glfw -L../extensions -LINK_GLFW_M_FOLDER= -L../smelt/glfw_m -L../extensions -all: sdl glfw glfw_m +all: sdl glfw sdl: $(CC) smelt_test.cpp $(CXXFLAGS) $(LINK_FOLDER) $(LINK) -o smelt_test @@ -14,5 +13,3 @@ clean: rm smelt_test glfw: $(CC) smelt_test.cpp $(CXXFLAGS) $(LINK_GLFW_FOLDER) $(LINK_GLFW) -o smelt_test_glfw -glfw_m: - $(CC) smelt_test.cpp $(CXXFLAGS) $(LINK_GLFW_M_FOLDER) $(LINK_GLFW) -o smelt_test_glfw_m diff --git a/smelt/glfw/gfx_glfw.cpp b/smelt/glfw/gfx_glfw.cpp index 5586112..d8135e8 100644 --- a/smelt/glfw/gfx_glfw.cpp +++ b/smelt/glfw/gfx_glfw.cpp @@ -2,7 +2,7 @@ /* * Simple MultimEdia LiTerator(SMELT) * by Chris Xiong 2015 - * GFX implementation based on GLFW/OpenGL 2.1 + * GFX implementation based on GLFW/OpenGL 3.2+ * * WARNING: This library is in development and interfaces would be very * unstable. @@ -11,7 +11,35 @@ #include "smelt_internal.hpp" #include "CxImage/ximage.h" #define dbg printf("%d: 0x%X\n",__LINE__,glGetError()) +#ifndef USE_OPENGL_COMPATIBILITY_PROFILE +#include "smmath_priv.hpp" static const char* GFX_GLFW_SRCFN="smelt/glfw/gfx_glfw.cpp"; +static const char* fixedfunc_pipeline_vsh= + "#version 330 core\n" + "layout (location=0) in vec3 vp;" + "layout (location=1) in vec4 vc;" + "layout (location=2) in vec2 vtc;" + "out vec4 fc;" + "out vec2 ftc;" + "uniform mat4 mmodv;" + "uniform mat4 mproj;" + "void main(){" + "gl_Position=mproj*mmodv*vec4(vp,1.0f);" + "ftc=vec2(vtc.x,1.0f-vtc.y);" + "fc.rgba=vc.bgra;" + "}" +; +static const char* fixedfunc_pipeline_fsh= + "#version 330 core\n" + "in vec4 fc;" + "in vec2 ftc;" + "out vec4 color;" + "uniform sampler2D tex;" + "void main(){" + "color=fc*texture(tex,ftc);" + "if(color.a<1./256.)discard;" + "}" +; struct glTexture { GLuint name,rw,rh,dw,dh; @@ -25,8 +53,7 @@ bool SMELT_IMPL::smRenderBegin2D(bool ztest,SMTRG trg) TRenderTargetList *targ=(TRenderTargetList*)trg; if(vertexArray) {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,(targ)?targ->frame:0); + glBindFramebuffer(GL_FRAMEBUFFER,(targ)?targ->frame:0); glDepthFunc(GL_GEQUAL); ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); zbufenabled=ztest; @@ -52,8 +79,7 @@ bool SMELT_IMPL::smRenderBegin3D(float fov,bool ztest,SMTRG trg) TRenderTargetList *targ=(TRenderTargetList*)trg; if(vertexArray) {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,(targ)?targ->frame:0); + glBindFramebuffer(GL_FRAMEBUFFER,(targ)?targ->frame:0); glDepthFunc(GL_LESS); ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); zbufenabled=ztest; @@ -77,20 +103,6 @@ bool SMELT_IMPL::smRenderBegin3D(float fov,bool ztest,SMTRG trg) bool SMELT_IMPL::smRenderEnd() { batchOGL(true); - if(curTarget&&!pOpenGLDevice->have_GL_EXT_framebuffer_object) - { - glTexture *pTex=(glTexture*)curTarget->tex; - if(pTex&&pTex->lost) - configTexture(pTex,pTex->rw,pTex->rh,pTex->px); - int w=curTarget->w,h=curTarget->h; - glFinish(); - DWORD *px=new DWORD[w*h]; - glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(pOpenGLDevice->TextureTarget,pTex->name); - glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); - delete[] px; - } if(curTarget&&curTarget->ms) { glTexture *pTex=(glTexture*)curTarget->tex; @@ -99,14 +111,14 @@ bool SMELT_IMPL::smRenderEnd() int w=curTarget->w,h=curTarget->h; glFinish(); DWORD *px=new DWORD[w*h]; - glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,curTarget->frame); - glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,curTarget->sframe); - glBlitFramebufferEXT(0,0,w,h,0,0,w,h,GL_COLOR_BUFFER_BIT,GL_NEAREST); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget->sframe); + glBindFramebuffer(GL_READ_FRAMEBUFFER,curTarget->frame); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER,curTarget->sframe); + glBlitFramebuffer(0,0,w,h,0,0,w,h,GL_COLOR_BUFFER_BIT,GL_NEAREST); + glBindFramebuffer(GL_FRAMEBUFFER,curTarget->sframe); glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(pOpenGLDevice->TextureTarget,pTex->name); - glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + glBindTexture(GL_TEXTURE_2D,pTex->name); + glTexSubImage2D(GL_TEXTURE_2D,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); delete[] px; } if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); @@ -127,28 +139,37 @@ void SMELT_IMPL::smClrscr(DWORD color,bool clearcol,bool cleardep) void SMELT_IMPL::sm3DCamera6f2v(float *pos,float *rot) { batchOGL(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - if(!pos||!rot)return; - glRotatef((GLfloat)-rot[0],1,0,0); - glRotatef((GLfloat)-rot[1],0,1,0); - glRotatef((GLfloat)-rot[2],0,0,1); - glTranslatef((GLfloat)-pos[0],(GLfloat)-pos[1],(GLfloat)-pos[2]); + _smMatrix Mmodv; + Mmodv.loadIdentity(); + if(pos&&rot) + { + Mmodv.rotate(_smMath::deg2rad(-rot[0]),1,0,0); + Mmodv.rotate(_smMath::deg2rad(-rot[1]),0,1,0); + Mmodv.rotate(_smMath::deg2rad(-rot[2]),0,0,1); + Mmodv.translate(-pos[0],-pos[1],-pos[2]); + } + memcpy(mmodv,Mmodv.m,sizeof(mmodv)); + glUniformMatrix4fv(loc_mmodv,1,0,mmodv); } void SMELT_IMPL::smMultViewMatrix(float *mat) { - glMatrixMode(GL_MODELVIEW); - glMultMatrixf(mat); + _smMatrix Mmodv(mmodv); + Mmodv=Mmodv*_smMatrix(mat); + memcpy(mmodv,Mmodv.m,sizeof(mmodv)); } void SMELT_IMPL::sm2DCamera5f3v(float *pos,float *dpos,float *rot) { batchOGL(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - if(!pos||!dpos||!rot)return; - glTranslatef(-pos[0],-pos[1],0.0f); - glRotatef(*rot,0.0f,0.0f,1.0f); - glTranslatef(pos[0]+dpos[0],pos[1]+dpos[1],0.0f); + _smMatrix Mmodv; + Mmodv.loadIdentity(); + if(pos&&dpos&&rot) + { + Mmodv.translate(-pos[0],-pos[1],.0f); + Mmodv.rotate(*rot,.0f,.0f,1.0f); + Mmodv.translate(pos[0]+dpos[0],pos[1]+dpos[1],.0f); + } + memcpy(mmodv,Mmodv.m,sizeof(mmodv)); + glUniformMatrix4fv(loc_mmodv,1,0,mmodv); } void SMELT_IMPL::smRenderLinefd(float x1,float y1,float z1,float x2,float y2,float z2,DWORD color) { @@ -241,28 +262,12 @@ void SMELT_IMPL::smDrawCustomIndexedVertices(smVertex* vb,WORD* ib,int vbc,int i if(vertexArray) { batchOGL(); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,0); - glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vb[0].x); - glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vb[0].col); - glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vb[0].tx); - float twm=1.,thm=1.; + float twm=-1.,thm=-1.; if(texture) { - if(filtermode==TFLT_NEAREST) - { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - } - if(filtermode==TFLT_LINEAR) - { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - } glTexture *ptex=(glTexture*)texture; - if(pOpenGLDevice->TextureTarget==GL_TEXTURE_RECTANGLE_ARB) - {twm=ptex->rw;thm=ptex->rh;} - else if(ptex->dw&&ptex->dh) + if(ptex->dw&&ptex->dh) { twm=(ptex->rw)/(float)(ptex->dw); thm=(ptex->rh)/(float)(ptex->dh); @@ -277,27 +282,25 @@ void SMELT_IMPL::smDrawCustomIndexedVertices(smVertex* vb,WORD* ib,int vbc,int i vertexArray[i].z=-vertexArray[i].z; } } + if(twm>0&&thm>0) for(int i=0;i>24)&0xFF); - BYTE r=((color>>16)&0xFF); - BYTE g=((color>> 8)&0xFF); - BYTE b=((color>> 0)&0xFF); - col[0]=r;col[1]=g; - col[2]=b;col[3]=a; + vb[i].ty*=thm; } if(texture!=primTex)bindTexture((glTexture*)texture); if(blend!=primBlend)setBlend(blend); - glDrawElements(GL_TRIANGLES,ibc,GL_UNSIGNED_SHORT,ib); + glBindVertexArray(VertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER,VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER,sizeof(smVertex)*vbc,vb,GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*ibc,ib,GL_DYNAMIC_DRAW); + glDrawElements(GL_TRIANGLES,ibc,GL_UNSIGNED_SHORT,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*((VERTEX_BUFFER_SIZE*6)/4),indexBuf,GL_DYNAMIC_DRAW); + glBindVertexArray(0); + if(texture!=primTex)bindTexture((glTexture*)primTex); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); - glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].x); - glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vertexBuf[0].col); - glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].tx); } } SMTRG SMELT_IMPL::smTargetCreate(int w,int h,int ms) @@ -336,20 +339,17 @@ void SMELT_IMPL::smTargetFree(SMTRG targ) { if(pLastTarg)pLastTarg->next=pTarget->next; else targets=pTarget->next; - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + if(curTarget==(TRenderTargetList*)targ) + glBindFramebuffer(GL_FRAMEBUFFER_EXT,0); + if(pTarget->depth) + glDeleteRenderbuffers(1,&pTarget->depth); + glDeleteFramebuffers(1,&pTarget->frame); + if(pTarget->ms) { - if(curTarget==(TRenderTargetList*)targ) - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); - if(pTarget->depth) - glDeleteRenderbuffersEXT(1,&pTarget->depth); - glDeleteFramebuffersEXT(1,&pTarget->frame); - if(pTarget->ms) - { - glDeleteRenderbuffersEXT(1,&pTarget->colorms); - glDeleteRenderbuffersEXT(1,&pTarget->scolor); - glDeleteRenderbuffersEXT(1,&pTarget->sdepth); - glDeleteFramebuffersEXT(1,&pTarget->sframe); - } + glDeleteRenderbuffers(1,&pTarget->colorms); + glDeleteRenderbuffers(1,&pTarget->scolor); + glDeleteRenderbuffers(1,&pTarget->sdepth); + glDeleteFramebuffers(1,&pTarget->sframe); } if(curTarget==(TRenderTargetList*)targ)curTarget=0; smTextureFree(pTarget->tex); @@ -428,7 +428,9 @@ void SMELT_IMPL::smTextureFree(SMTEX tex) if(tex) { glTexture *ptex=(glTexture*)tex; - delete[] ptex->fn;delete[] ptex->locpx;delete[] ptex->px; + delete[] ptex->fn; + delete[] ptex->locpx; + delete[] ptex->px; glDeleteTextures(1,&ptex->name); delete ptex; } @@ -438,38 +440,26 @@ void SMELT_IMPL::smTextureOpt(int potopt,int filter) batchOGL(); if(potopt==TPOT_NONPOT) { - if(pOpenGLDevice->have_GL_ARB_texture_rectangle) - pOpenGLDevice->TextureTarget=GL_TEXTURE_RECTANGLE_ARB; - else if(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) - pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; - else pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; - glDisable(GL_TEXTURE_2D); - if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); - glEnable(pOpenGLDevice->TextureTarget); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); } if(potopt==TPOT_POT) { - pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; - glDisable(GL_TEXTURE_2D); - if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); - glEnable(pOpenGLDevice->TextureTarget); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_REPEAT); } filtermode=filter; if(filter==TFLT_NEAREST) { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); } if(filter==TFLT_LINEAR) { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); } } int SMELT_IMPL::smTextureGetWidth(SMTEX tex,bool original) @@ -548,11 +538,11 @@ void SMELT_IMPL::smTexutreUnlock(SMTEX tex) if(ptex->lost)configTexture(ptex,ptex->rw,ptex->rh,ptex->px); else { - glBindTexture(pOpenGLDevice->TextureTarget,ptex->name); - glTexSubImage2D(pOpenGLDevice->TextureTarget,0,ptex->locx, - (ptex->rh-ptex->locy)-ptex->loch,ptex->locw,ptex->loch,GL_RGBA, - GL_UNSIGNED_BYTE,ptex->locpx); - glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + glBindTexture(GL_TEXTURE_2D,ptex->name); + glTexSubImage2D(GL_TEXTURE_2D,0,ptex->locx, + (ptex->rh-ptex->locy)-ptex->loch,ptex->locw,ptex->loch,GL_RGBA, + GL_UNSIGNED_BYTE,ptex->locpx); + glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); } } if(ptex->fn&&ptex->roloc){delete[] ptex->px;ptex->px=NULL;} @@ -592,7 +582,7 @@ DWORD* SMELT_IMPL::decodeImage(BYTE *data,const char *fn,DWORD size,int &w,int & w=img.GetWidth();h=img.GetHeight(); px=new DWORD[w*h]; BYTE *sptr=(BYTE*)px; - bool atunnel=img.AlphaIsValid(); + bool achannel=img.AlphaIsValid(); for(int i=0;irw,t->rh,t->px); if(((SMTEX)t)!=primTex) { - glBindTexture(pOpenGLDevice->TextureTarget,t?t->name:0); + glBindTexture(GL_TEXTURE_2D,t?t->name:((glTexture*)emptyTex)->name); + glUniform1i(loc_tex,0); primTex=(SMTEX)t; } } @@ -620,75 +611,67 @@ bool SMELT_IMPL::buildTarget(TRenderTargetList *pTarget,GLuint texid,int w,int h bool ok=true; if(ms) { - if(!pOpenGLDevice->have_GL_EXT_framebuffer_object|| - !pOpenGLDevice->have_GL_EXT_framebuffer_multisample|| - !pOpenGLDevice->have_GL_EXT_framebuffer_blit) - ms=0; + glGenFramebuffers(1,&pTarget->sframe); + glBindFramebuffer(GL_FRAMEBUFFER,pTarget->sframe); + glGenRenderbuffers(1,&pTarget->scolor); + glBindRenderbuffer(GL_RENDERBUFFER,pTarget->scolor); + glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,w,h); + glGenRenderbuffers(1,&pTarget->sdepth); + glBindRenderbuffer(GL_RENDERBUFFER,pTarget->sdepth); + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,pTarget->scolor); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->sdepth); + + glGenFramebuffers(1,&pTarget->frame); + glBindFramebuffer(GL_FRAMEBUFFER,pTarget->frame); + glGenRenderbuffers(1,&pTarget->colorms); + glBindRenderbuffer(GL_RENDERBUFFER,pTarget->colorms); + glRenderbufferStorageMultisample(GL_RENDERBUFFER,ms,GL_RGBA,w,h); + glGenRenderbuffers(1,&pTarget->depth); + glBindRenderbuffer(GL_RENDERBUFFER,pTarget->depth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER,ms,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,pTarget->colorms); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->depth); + GLenum rc=glCheckFramebufferStatus(GL_FRAMEBUFFER); + if((rc==GL_FRAMEBUFFER_COMPLETE)&&(glGetError()==GL_NO_ERROR)) + { + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + ok=true;pTarget->ms=ms; + } else { - glGenFramebuffersEXT(1,&pTarget->sframe); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->sframe); - glGenRenderbuffersEXT(1,&pTarget->scolor); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->scolor); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_RGBA,w,h); - glGenRenderbuffersEXT(1,&pTarget->sdepth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->sdepth); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_RENDERBUFFER_EXT,pTarget->scolor); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->sdepth); - - glGenFramebuffersEXT(1,&pTarget->frame); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->frame); - glGenRenderbuffersEXT(1,&pTarget->colorms); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->colorms); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,ms,GL_RGBA,w,h); - glGenRenderbuffersEXT(1,&pTarget->depth); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->depth); - glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,ms,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_RENDERBUFFER_EXT,pTarget->colorms); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->depth); - GLenum rc=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - if((rc==GL_FRAMEBUFFER_COMPLETE_EXT)&&(glGetError()==GL_NO_ERROR)) - { - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - ok=true;pTarget->ms=ms; - } - else - { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); - glDeleteRenderbuffersEXT(1,&pTarget->colorms); - glDeleteRenderbuffersEXT(1,&pTarget->depth); - glDeleteFramebuffersEXT(1,&pTarget->frame); - glDeleteFramebuffersEXT(1,&pTarget->sframe); - ok=false;ms=0; - } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget?curTarget->frame:0); + glBindFramebuffer(GL_FRAMEBUFFER,0); + glDeleteRenderbuffers(1,&pTarget->colorms); + glDeleteRenderbuffers(1,&pTarget->depth); + glDeleteFramebuffers(1,&pTarget->frame); + glDeleteFramebuffers(1,&pTarget->sframe); + ok=false;ms=0; } + glBindFramebuffer(GL_FRAMEBUFFER,curTarget?curTarget->frame:0); } if(!ms) - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) { - glGenFramebuffersEXT(1,&pTarget->frame); - glGenRenderbuffersEXT(1,&pTarget->depth); - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->frame); - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,pOpenGLDevice->TextureTarget,texid,0); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->depth); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->depth); - GLenum rc=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - if((rc==GL_FRAMEBUFFER_COMPLETE_EXT)&&(glGetError()==GL_NO_ERROR)) + glGenFramebuffers(1,&pTarget->frame); + glGenRenderbuffers(1,&pTarget->depth); + glBindFramebuffer(GL_FRAMEBUFFER,pTarget->frame); + glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texid,0); + glBindRenderbuffer(GL_RENDERBUFFER,pTarget->depth); + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->depth); + GLenum rc=glCheckFramebufferStatus(GL_FRAMEBUFFER); + if((rc==GL_FRAMEBUFFER_COMPLETE)&&(glGetError()==GL_NO_ERROR)) { glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); ok=true;pTarget->ms=0; } else { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); - glDeleteRenderbuffersEXT(1,&pTarget->depth); - glDeleteFramebuffersEXT(1,&pTarget->frame); + glBindFramebuffer(GL_FRAMEBUFFER,0); + glDeleteRenderbuffers(1,&pTarget->depth); + glDeleteFramebuffers(1,&pTarget->frame); ok=false; } - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget?curTarget->frame:0); + glBindFramebuffer(GL_FRAMEBUFFER,curTarget?curTarget->frame:0); } return ok; } @@ -715,28 +698,16 @@ void SMELT_IMPL::configTexture(glTexture *t,int w,int h,DWORD *px,bool compresse free(buff); fclose(pFile); } - glBindTexture(pOpenGLDevice->TextureTarget,tex); - if(pOpenGLDevice->TextureTarget!=GL_TEXTURE_RECTANGLE_ARB) - { - glTexParameterf(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_LOD,0.0f); - glTexParameterf(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAX_LOD,0.0f); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_BASE_LEVEL,0); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAX_LEVEL,0); - } - const GLenum fmt=pOpenGLDevice->have_GL_EXT_texture_compression_s3tc&&compressed?/*GL_COMPRESSED_RGBA_S3TC_DXT5_EXT*/GL_COMPRESSED_RGBA_ARB:GL_RGBA8; - if((pOpenGLDevice->have_GL_ARB_texture_rectangle)||(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two)||(ispot(w)&&ispot(h))) - { - glTexImage2D(pOpenGLDevice->TextureTarget,0,fmt,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,px); - } - else - { - t->dw=npot(w); - t->dh=npot(h); - glTexImage2D(pOpenGLDevice->TextureTarget,0,fmt,t->dw,t->dh,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); - glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - } - glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); - if (fromfile)delete[] px; + glBindTexture(GL_TEXTURE_2D,tex); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_LOD,0.0f); + glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_LOD,0.0f); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0); + compressed=false;//compression is unusable at this moment + const GLenum fmt=compressed?/*GL_COMPRESSED_RGBA_S3TC_DXT5_EXT*/GL_COMPRESSED_RGBA_ARB:GL_RGBA8; + glTexImage2D(GL_TEXTURE_2D,0,fmt,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); + if(fromfile)delete[] px; } SMTEX SMELT_IMPL::buildTexture(int w,int h,DWORD *px) { @@ -748,45 +719,34 @@ SMTEX SMELT_IMPL::buildTexture(int w,int h,DWORD *px) } void SMELT_IMPL::configProjectionMatrix2D(int w,int h) { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0,(float)w,0,(float)h,0.0f,1.0f); + memset(mproj,0,sizeof(mproj)); + mproj[0]=2./w; + mproj[5]=2./h; + mproj[10]=-2.; + mproj[15]=1.; + mproj[12]=mproj[13]=mproj[14]=-1.; + glUniformMatrix4fv(loc_mproj,1,0,mproj); } void SMELT_IMPL::configProjectionMatrix3D(int w,int h,float fov) { - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - - GLfloat matrix[16]={0.0f}; + memset(mproj,0,sizeof(mproj)); float f=1./tanf(M_PI*fov/360.); float ar=(float)w/(float)h; float Near=0.1,Far=1000.; - matrix[0]=f/ar;matrix[5]=f; - matrix[10]=(Far+Near)/(Near-Far);matrix[11]=-1.0f; - matrix[14]=(2*Far*Near)/(Near-Far); - glMultMatrixf(matrix); + mproj[0]=f/ar;mproj[5]=f; + mproj[10]=(Far+Near)/(Near-Far);mproj[11]=-1.0f; + mproj[14]=(2*Far*Near)/(Near-Far); + glUniformMatrix4fv(loc_mproj,1,0,mproj); } void SMELT_IMPL::batchOGL(bool endScene) { if(vertexArray&&primcnt) { - float twm=1.,thm=1.; + float twm=-1.,thm=-1.; if(primTex) { - if(filtermode==TFLT_NEAREST) - { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - } - if(filtermode==TFLT_LINEAR) - { - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - } glTexture *ptex=(glTexture*)primTex; - if(pOpenGLDevice->TextureTarget==GL_TEXTURE_RECTANGLE_ARB) - {twm=ptex->rw;thm=ptex->rh;} - else if(ptex->dw&&ptex->dh) + if(ptex->dw&&ptex->dh) { twm=(ptex->rw)/(float)(ptex->dw); thm=(ptex->rh)/(float)(ptex->dh); @@ -801,19 +761,15 @@ void SMELT_IMPL::batchOGL(bool endScene) vertexArray[i].z=-vertexArray[i].z; } } + if(twm>0&&thm>0) for(int i=0;i>24)&0xFF); - BYTE r=((color>>16)&0xFF); - BYTE g=((color>> 8)&0xFF); - BYTE b=((color>> 0)&0xFF); - col[0]=r;col[1]=g; - col[2]=b;col[3]=a; + vertexArray[i].ty*=thm; } + glBindVertexArray(VertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER,VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER,sizeof(smVertex)*primcnt*primType,vertexBuf,GL_DYNAMIC_DRAW); switch(primType) { case PRIM_LINES: @@ -823,7 +779,7 @@ void SMELT_IMPL::batchOGL(bool endScene) glDrawArrays(GL_TRIANGLES,0,3*primcnt); break; case PRIM_QUADS: - glDrawElements(GL_TRIANGLES,6*primcnt,GL_UNSIGNED_SHORT,pOpenGLDevice->have_GL_ARB_vertex_buffer_object?0:indexBuf); + glDrawElements(GL_TRIANGLES,6*primcnt,GL_UNSIGNED_SHORT,0); #if 0 for (int i=0;ihave_base_opengl=true; - pOpenGLDevice->have_GL_ARB_texture_rectangle=true; - pOpenGLDevice->have_GL_ARB_texture_non_power_of_two=true; - pOpenGLDevice->have_GL_EXT_framebuffer_object=true; - pOpenGLDevice->have_GL_EXT_texture_compression_s3tc=false; - pOpenGLDevice->have_GL_ARB_vertex_buffer_object=true; - pOpenGLDevice->have_GL_EXT_framebuffer_multisample=true; - pOpenGLDevice->have_GL_EXT_framebuffer_blit=true; + /* + * All OpenGL features utilized by SMELT are in the core profile + * for OpenGL >= 3.2. So this function is essentially useless. + */ + glewExperimental=true; GLenum glewret=glewInit(); if(glewret) { smLog("%s:" SLINE ": glewInit() failed with error %s\n",GFX_GLFW_SRCFN,glewGetErrorString(glewret)); + pOpenGLDevice->have_base_opengl=false; return false; } if (!pOpenGLDevice->have_base_opengl) @@ -905,83 +862,27 @@ bool SMELT_IMPL::loadGLEntryPoints() const char *verstr=(const char*)glGetString(GL_VERSION); int maj=0,min=0; sscanf(verstr,"%d.%d",&maj,&min); - if((maj<1)||((maj==1)&&(min<2))) + if((maj<3)||((maj==3)&&(min<2))) { - smLog("%s:" SLINE ": OpenGL implementation must be at least version 1.2.\n",GFX_GLFW_SRCFN); + smLog("%s:" SLINE ": OpenGL implementation must be at least version 3.2.\n",GFX_GLFW_SRCFN); unloadGLEntryPoints(); return false; } - const char *exts=(const char*)glGetString(GL_EXTENSIONS); - pOpenGLDevice->have_GL_ARB_texture_rectangle= - checkGLExtension(exts,"GL_ARB_texture_rectangle")|| - checkGLExtension(exts,"GL_EXT_texture_rectangle")|| - checkGLExtension(exts, "GL_NV_texture_rectangle"); - pOpenGLDevice->have_GL_ARB_texture_non_power_of_two= - maj>=2||checkGLExtension(exts,"GL_ARB_texture_non_power_of_two"); - if(pOpenGLDevice->have_GL_ARB_texture_rectangle) - { - smLog("%s:" SLINE ": OpenGL: Using GL_ARB_texture_rectangle.\n",GFX_GLFW_SRCFN); - pOpenGLDevice->TextureTarget=GL_TEXTURE_RECTANGLE_ARB; - } - else if(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) - { - smLog("%s:" SLINE ": OpenGL: Using GL_ARB_texture_non_power_of_two.\n",GFX_GLFW_SRCFN); - pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; - } - else - { - smLog("%s:" SLINE ": OpenGL: Using power-of-two textures. This costs more memory!\n",GFX_GLFW_SRCFN); - pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; - } - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) - pOpenGLDevice->have_GL_EXT_framebuffer_object= - checkGLExtension(exts, "GL_EXT_framebuffer_object"); - if(pOpenGLDevice->have_GL_EXT_framebuffer_object) - smLog("%s:" SLINE ": OpenGL: Using GL_EXT_framebuffer_object.\n",GFX_GLFW_SRCFN); - else - smLog("%s:" SLINE ": OpenGL: WARNING! No render-to-texture support. Things may render badly.\n",GFX_GLFW_SRCFN); - if(pOpenGLDevice->have_GL_EXT_texture_compression_s3tc) - pOpenGLDevice->have_GL_EXT_texture_compression_s3tc= - checkGLExtension(exts,"GL_ARB_texture_compression")&& - checkGLExtension(exts,"GL_EXT_texture_compression_s3tc"); - if(pOpenGLDevice->have_GL_EXT_texture_compression_s3tc) - smLog("%s:" SLINE ": OpenGL: Using GL_EXT_texture_compression_s3tc.\n",GFX_GLFW_SRCFN); - else if (true) - { - smLog("%s:" SLINE ": OpenGL: Texture compression disabled!\n",GFX_GLFW_SRCFN); - } - if(pOpenGLDevice->have_GL_ARB_vertex_buffer_object) - { - pOpenGLDevice->have_GL_ARB_vertex_buffer_object= - checkGLExtension(exts,"GL_ARB_vertex_buffer_object"); - } - if(pOpenGLDevice->have_GL_ARB_vertex_buffer_object) - smLog("%s:" SLINE ": OpenGL: Using GL_ARB_vertex_buffer_object.\n",GFX_GLFW_SRCFN); - else - smLog("%s:" SLINE ": OpenGL: WARNING! No VBO support; performance may suffer.\n",GFX_GLFW_SRCFN); - pOpenGLDevice->have_GL_EXT_framebuffer_multisample= - checkGLExtension(exts,"GL_EXT_framebuffer_multisample"); - pOpenGLDevice->have_GL_EXT_framebuffer_blit= - checkGLExtension(exts,"GL_EXT_framebuffer_blit"); - if(!pOpenGLDevice->have_GL_EXT_framebuffer_multisample||!pOpenGLDevice->have_GL_EXT_framebuffer_blit) - smLog("%s:" SLINE ": Multisampling is not supported.\n",GFX_GLFW_SRCFN); - else - smLog("%s:" SLINE ": Multisampling is supported. Still experimental!\n",GFX_GLFW_SRCFN); return true; } bool SMELT_IMPL::initOGL() { - primTex=0; + primTex=0;emptyTex=0; if(pOpenGLDevice){smLog("%s:" SLINE ": Multiple initialization!\n",GFX_GLFW_SRCFN);return false;} pOpenGLDevice=new TOpenGLDevice; if(!loadGLEntryPoints())return false; smLog("%s:" SLINE ": Mode: %d x %d\n",GFX_GLFW_SRCFN,scrw,scrh); - vertexArray=NULL;textures=NULL;IndexBufferObject=0; + vertexArray=NULL;textures=NULL; + ShaderProgram=vertshader=fragshader=0; + VertexBufferObject=VertexArrayObject=IndexBufferObject=0; if(!confOGL())return false; glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); return true; } void SMELT_IMPL::finiOGL() @@ -993,15 +894,20 @@ void SMELT_IMPL::finiOGL() delete[] indexBuf;indexBuf=NULL; if(pOpenGLDevice) { - if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + if(VertexBufferObject!=0) { - if (IndexBufferObject!=0) - { - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,0); - glDeleteBuffersARB(1,&IndexBufferObject); - IndexBufferObject=0; - } + glBindVertexArray(VertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER,0); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); + glDeleteBuffers(1,&VertexBufferObject); + glDeleteBuffers(1,&IndexBufferObject); + glBindVertexArray(0); + glDeleteVertexArrays(1,&VertexArrayObject); + VertexArrayObject=0; + VertexBufferObject=0; + IndexBufferObject=0; } + glDeleteProgram(ShaderProgram); delete pOpenGLDevice; pOpenGLDevice=NULL; } @@ -1020,6 +926,10 @@ bool SMELT_IMPL::restOGL() bool SMELT_IMPL::confOGL() { bindTexture(NULL); + DWORD ones=~0U; + if(!emptyTex) + {emptyTex=buildTexture(1,1,&ones);} + configTexture((glTexture*)emptyTex,1,1,&ones,false); for(TTextureList *i=textures;i;i=i->next) { glTexture *t=(glTexture*)i->tex; @@ -1033,6 +943,39 @@ bool SMELT_IMPL::confOGL() buildTarget(target,tex?tex->name:0,target->w,target->h); target=target->next; } + int compret=0; + ShaderProgram=glCreateProgram(); + vertshader=glCreateShader(GL_VERTEX_SHADER); + fragshader=glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(vertshader,1,&fixedfunc_pipeline_vsh,NULL); + glShaderSource(fragshader,1,&fixedfunc_pipeline_fsh,NULL); + glCompileShader(vertshader); + glGetShaderiv(vertshader,GL_COMPILE_STATUS,&compret); + //char log[1024]; + //glGetShaderInfoLog(vertshader,1024,NULL,log); + //puts(log); + if(!compret) + smLog("%s:" SLINE ": Warning: Your shitty vertex shader failed to compile!\n",GFX_GLFW_SRCFN); + glCompileShader(fragshader); + glGetShaderiv(fragshader,GL_COMPILE_STATUS,&compret); + //glGetShaderInfoLog(fragshader,1024,NULL,log); + //puts(log); + if(!compret) + smLog("%s:" SLINE ": Warning: Your shitty fragment shader failed to compile!\n",GFX_GLFW_SRCFN); + glAttachShader(ShaderProgram,vertshader); + glAttachShader(ShaderProgram,fragshader); + glLinkProgram(ShaderProgram); + //glGetProgramInfoLog(ShaderProgram,1024,NULL,log); + //puts(log); + glGetProgramiv(ShaderProgram,GL_LINK_STATUS,&compret); + if(!compret) + smLog("%s:" SLINE ": Warning: Default shader linkage failure!\n",GFX_GLFW_SRCFN); + glDeleteShader(vertshader); + glDeleteShader(fragshader); + glUseProgram(ShaderProgram); + loc_tex=glGetUniformLocation(ShaderProgram,"tex"); + loc_mmodv=glGetUniformLocation(ShaderProgram,"mmodv"); + loc_mproj=glGetUniformLocation(ShaderProgram,"mproj"); vertexBuf=new smVertex[VERTEX_BUFFER_SIZE]; indexBuf=new GLushort[VERTEX_BUFFER_SIZE*6/4]; GLushort* indices=indexBuf; @@ -1043,46 +986,47 @@ bool SMELT_IMPL::confOGL() *indices++=n+3;*indices++=n; n+=4; } - if(pOpenGLDevice->have_GL_ARB_vertex_buffer_object) - { - glGenBuffersARB(1,&IndexBufferObject); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*((VERTEX_BUFFER_SIZE*6)/4),indexBuf,GL_STATIC_DRAW); - } - glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].x); - glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vertexBuf[0].col); - glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].tx); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glGenBuffers(1,&VertexBufferObject); + glGenVertexArrays(1,&VertexArrayObject); + glGenBuffers(1,&IndexBufferObject); + glBindVertexArray(VertexArrayObject); + glBindBuffer(GL_ARRAY_BUFFER,VertexBufferObject); + glBufferData(GL_ARRAY_BUFFER,sizeof(smVertex)*VERTEX_BUFFER_SIZE,vertexBuf,GL_DYNAMIC_DRAW); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); + glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*((VERTEX_BUFFER_SIZE*6)/4),indexBuf,GL_DYNAMIC_DRAW); + glVertexAttribPointer(0,3,GL_FLOAT,0,sizeof(smVertex),(void*)offsetof(smVertex,x));//vp + glVertexAttribPointer(1,4,GL_UNSIGNED_BYTE,1,sizeof(smVertex),(void*)offsetof(smVertex,col));//vc + glVertexAttribPointer(2,2,GL_FLOAT,0,sizeof(smVertex),(void*)offsetof(smVertex,tx));//vtc + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glEnableVertexAttribArray(2); + glBindVertexArray(0); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glPixelStorei(GL_PACK_ALIGNMENT,1); - glDisable(GL_TEXTURE_2D); - if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); - glEnable(pOpenGLDevice->TextureTarget); glEnable(GL_SCISSOR_TEST); glDisable(GL_CULL_FACE); - glDisable(GL_LIGHTING); + glActiveTexture(GL_TEXTURE0); glDepthFunc(GL_GEQUAL); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GEQUAL,1.0f/255.0f); - glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); filtermode=TFLT_LINEAR; - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); //GL_REPEAT doesn't work with non-pot textures... - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); primcnt=0;primType=PRIM_QUADS;primBlend=BLEND_ALPHABLEND;primTex=0; glScissor(0,0,scrw,scrh); glViewport(0,0,scrw,scrh); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); configProjectionMatrix2D(scrw,scrh); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + _smMatrix Mmodv;Mmodv.loadIdentity(); + memcpy(mmodv,Mmodv.m,sizeof(mmodv)); + glUniformMatrix4fv(loc_mmodv,1,0,mmodv); return true; } +#else +#include "gfx_glfw_compat.cpp" +#endif //USE_OPENGL_COMPATIBILITY_PROFILE diff --git a/smelt/glfw/gfx_glfw_compat.cpp b/smelt/glfw/gfx_glfw_compat.cpp new file mode 100644 index 0000000..995f697 --- /dev/null +++ b/smelt/glfw/gfx_glfw_compat.cpp @@ -0,0 +1,1085 @@ +// -*- C++ -*- +/* + * Simple MultimEdia LiTerator(SMELT) + * by Chris Xiong 2015 + * GFX implementation based on GLFW/OpenGL 2.1 + * + * WARNING: This library is in development and interfaces would be very + * unstable. + * + */ +static const char* GFX_GLFW_SRCFN="smelt/glfw/gfx_glfw_compat.cpp"; +struct glTexture +{ + GLuint name,rw,rh,dw,dh; + const char *fn; + DWORD *px,*locpx; + bool isTarget,lost,roloc; + GLint locx,locy,locw,loch; +}; +bool SMELT_IMPL::smRenderBegin2D(bool ztest,SMTRG trg) +{ + TRenderTargetList *targ=(TRenderTargetList*)trg; + if(vertexArray) + {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,(targ)?targ->frame:0); + glDepthFunc(GL_GEQUAL); + ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); + zbufenabled=ztest; + if(targ) + { + glScissor(0,0,targ->w,targ->h); + glViewport(0,0,targ->w,targ->h); + configProjectionMatrix2D(targ->w,targ->h); + } + else + { + glScissor(0,0,scrw,scrh); + glViewport(0,0,scrw,scrh); + configProjectionMatrix2D(scrw,scrh); + } + sm2DCamera5f3v(NULL,NULL,NULL); + curTarget=targ;tdmode=0; + vertexArray=vertexBuf; + return true; +} +bool SMELT_IMPL::smRenderBegin3D(float fov,bool ztest,SMTRG trg) +{ + TRenderTargetList *targ=(TRenderTargetList*)trg; + if(vertexArray) + {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,(targ)?targ->frame:0); + glDepthFunc(GL_LESS); + ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); + zbufenabled=ztest; + if(targ) + { + glScissor(0,0,targ->w,targ->h); + glViewport(0,0,targ->w,targ->h); + configProjectionMatrix3D(targ->w,targ->h,fov); + } + else + { + glScissor(0,0,scrw,scrh); + glViewport(0,0,scrw,scrh); + configProjectionMatrix3D(scrw,scrh,fov); + } + sm3DCamera6f2v(NULL,NULL); + curTarget=targ;tdmode=1; + vertexArray=vertexBuf; + return true; +} +bool SMELT_IMPL::smRenderEnd() +{ + batchOGL(true); + if(curTarget&&!pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + glTexture *pTex=(glTexture*)curTarget->tex; + if(pTex&&pTex->lost) + configTexture(pTex,pTex->rw,pTex->rh,pTex->px); + int w=curTarget->w,h=curTarget->h; + glFinish(); + DWORD *px=new DWORD[w*h]; + glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(pOpenGLDevice->TextureTarget,pTex->name); + glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + delete[] px; + } + if(curTarget&&curTarget->ms) + { + glTexture *pTex=(glTexture*)curTarget->tex; + if(pTex&&pTex->lost) + configTexture(pTex,pTex->rw,pTex->rh,pTex->px); + int w=curTarget->w,h=curTarget->h; + glFinish(); + DWORD *px=new DWORD[w*h]; + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT,curTarget->frame); + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT,curTarget->sframe); + glBlitFramebufferEXT(0,0,w,h,0,0,w,h,GL_COLOR_BUFFER_BIT,GL_NEAREST); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget->sframe); + glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(pOpenGLDevice->TextureTarget,pTex->name); + glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + delete[] px; + } + if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); + return true; +} +void SMELT_IMPL::smClrscr(DWORD color,bool clearcol,bool cleardep) +{ + GLfloat a=(GLfloat)(GETA(color))/255.f; + GLfloat r=(GLfloat)(GETR(color))/255.f; + GLfloat g=(GLfloat)(GETG(color))/255.f; + GLfloat b=(GLfloat)(GETB(color))/255.f; + if(clearcol) + glClearColor(r,g,b,a); + if(tdmode)glClearDepth(1); + else if(zbufenabled)glClearDepth(0); + glClear((clearcol?GL_COLOR_BUFFER_BIT:0)|(((zbufenabled||tdmode)&&cleardep)?GL_DEPTH_BUFFER_BIT:0)); +} +void SMELT_IMPL::sm3DCamera6f2v(float *pos,float *rot) +{ + batchOGL(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + if(!pos||!rot)return; + glRotatef((GLfloat)-rot[0],1,0,0); + glRotatef((GLfloat)-rot[1],0,1,0); + glRotatef((GLfloat)-rot[2],0,0,1); + glTranslatef((GLfloat)-pos[0],(GLfloat)-pos[1],(GLfloat)-pos[2]); +} +void SMELT_IMPL::smMultViewMatrix(float *mat) +{ + glMatrixMode(GL_MODELVIEW); + glMultMatrixf(mat); +} +void SMELT_IMPL::sm2DCamera5f3v(float *pos,float *dpos,float *rot) +{ + batchOGL(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + if(!pos||!dpos||!rot)return; + glTranslatef(-pos[0],-pos[1],0.0f); + glRotatef(*rot,0.0f,0.0f,1.0f); + glTranslatef(pos[0]+dpos[0],pos[1]+dpos[1],0.0f); +} +void SMELT_IMPL::smRenderLinefd(float x1,float y1,float z1,float x2,float y2,float z2,DWORD color) +{ + if(vertexArray) + { + if(primType!=PRIM_LINES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_LINES||primTex||primBlend!=BLEND_ALPHABLEND) + { + batchOGL(); + primType=PRIM_LINES; + if(primBlend!=BLEND_ALPHAADD)setBlend(BLEND_ALPHAADD); + bindTexture(NULL); + } + int i=(primcnt++)*PRIM_LINES; + vertexArray[i].x=x1,vertexArray[i+1].x=x2; + vertexArray[i].y=y1,vertexArray[i+1].y=y2; + vertexArray[i].x=z1,vertexArray[i+1].x=z2; + vertexArray[i].col=vertexArray[i+1].col=color; + vertexArray[i].tx=vertexArray[i+1].tx=.0; + vertexArray[i].ty=vertexArray[i+1].ty=.0; + } +} +void SMELT_IMPL::smRenderLinefvd(float *p1,float *p2,DWORD color) +{ + if(vertexArray&&p1&&p2) + { + if(primType!=PRIM_LINES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_LINES||primTex||primBlend!=BLEND_ALPHABLEND) + { + batchOGL(); + primType=PRIM_LINES; + if(primBlend!=BLEND_ALPHAADD)setBlend(BLEND_ALPHAADD); + bindTexture(NULL); + } + int i=(primcnt++)*PRIM_LINES; + vertexArray[i].x=p1[0],vertexArray[i+1].x=p2[0]; + vertexArray[i].y=p1[1],vertexArray[i+1].y=p2[1]; + vertexArray[i].x=p2[2],vertexArray[i+1].x=p2[2]; + vertexArray[i].col=vertexArray[i+1].col=color; + vertexArray[i].tx=vertexArray[i+1].tx=.0; + vertexArray[i].ty=vertexArray[i+1].ty=.0; + } +} +void SMELT_IMPL::smRenderTriangle(smTriangle *t) +{ + if(vertexArray) + { + if(primType!=PRIM_TRIANGLES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_TRIANGLES|| + primTex!=t->tex||primBlend!=t->blend) + { + batchOGL(); + primType=PRIM_TRIANGLES; + if(primBlend!=t->blend)setBlend(t->blend); + bindTexture((glTexture*)t->tex); + } + memcpy(&vertexArray[(primcnt++)*PRIM_TRIANGLES],t->v,sizeof(smVertex)*PRIM_TRIANGLES); + } +} +void SMELT_IMPL::smRenderQuad(smQuad *q) +{ + if(vertexArray) + { + if(primType!=PRIM_QUADS||primcnt>=VERTEX_BUFFER_SIZE/PRIM_QUADS|| + primTex!=q->tex||primBlend!=q->blend) + { + batchOGL(); + primType=PRIM_QUADS; + if(primBlend!=q->blend)setBlend(q->blend); + bindTexture((glTexture*)q->tex); + } + memcpy(&vertexArray[(primcnt++)*PRIM_QUADS],q->v,sizeof(smVertex)*PRIM_QUADS); + } +} +smVertex* SMELT_IMPL::smGetVertArray() +{ + if(vertexArray) + { + batchOGL(); + return vertexArray; + } + else return NULL; +} +void SMELT_IMPL::smDrawVertArray(int prim,SMTEX texture,int blend,int _primcnt) +{ + primType=prim; + bindTexture((glTexture*)texture); + if(primBlend!=blend)setBlend(blend); + primcnt=primcnt; +} +void SMELT_IMPL::smDrawCustomIndexedVertices(smVertex* vb,WORD* ib,int vbc,int ibc,int blend,SMTEX texture) +{ + if(vertexArray) + { + batchOGL(); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,0); + glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vb[0].x); + glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vb[0].col); + glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vb[0].tx); + + float twm=1.,thm=1.; + if(texture) + { + if(filtermode==TFLT_NEAREST) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + } + if(filtermode==TFLT_LINEAR) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + } + glTexture *ptex=(glTexture*)texture; + if(pOpenGLDevice->TextureTarget==GL_TEXTURE_RECTANGLE_ARB) + {twm=ptex->rw;thm=ptex->rh;} + else if(ptex->dw&&ptex->dh) + { + twm=(ptex->rw)/(float)(ptex->dw); + thm=(ptex->rh)/(float)(ptex->dh); + } + } + if(!tdmode) + { + float h=curTarget?curTarget->h:scrh; + for(int i=0;i>24)&0xFF); + BYTE r=((color>>16)&0xFF); + BYTE g=((color>> 8)&0xFF); + BYTE b=((color>> 0)&0xFF); + col[0]=r;col[1]=g; + col[2]=b;col[3]=a; + } + if(texture!=primTex)bindTexture((glTexture*)texture); + if(blend!=primBlend)setBlend(blend); + glDrawElements(GL_TRIANGLES,ibc,GL_UNSIGNED_SHORT,ib); + + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); + glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].x); + glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vertexBuf[0].col); + glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].tx); + } +} +SMTRG SMELT_IMPL::smTargetCreate(int w,int h,int ms) +{ + bool ok=false; + TRenderTargetList *pTarget=new TRenderTargetList; + memset(pTarget,0,sizeof(TRenderTargetList)); + pTarget->tex=buildTexture(w,h,NULL); + glTexture *gltex=(glTexture*)pTarget->tex; + gltex->isTarget=true;gltex->lost=false; + configTexture(gltex,w,h,NULL,false); + pTarget->w=w;pTarget->h=h; + ok=buildTarget(pTarget,gltex->name,w,h,ms); + if(!ok) + { + smLog("%s:" SLINE ": Failed to create render target.\n",GFX_GLFW_SRCFN); + smTextureFree(pTarget->tex); + delete pTarget; + return 0; + } + pTarget->next=targets; + targets=pTarget; + return (SMTRG)pTarget; +} +SMTEX SMELT_IMPL::smTargetTexture(SMTRG targ) +{ + TRenderTargetList *pTarg=(TRenderTargetList*)targ; + return targ?pTarg->tex:0; +} +void SMELT_IMPL::smTargetFree(SMTRG targ) +{ + TRenderTargetList *pTarget=targets,*pLastTarg=NULL; + while(pTarget) + { + if((TRenderTargetList*)targ==pTarget) + { + if(pLastTarg)pLastTarg->next=pTarget->next; + else targets=pTarget->next; + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + if(curTarget==(TRenderTargetList*)targ) + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); + if(pTarget->depth) + glDeleteRenderbuffersEXT(1,&pTarget->depth); + glDeleteFramebuffersEXT(1,&pTarget->frame); + if(pTarget->ms) + { + glDeleteRenderbuffersEXT(1,&pTarget->colorms); + glDeleteRenderbuffersEXT(1,&pTarget->scolor); + glDeleteRenderbuffersEXT(1,&pTarget->sdepth); + glDeleteFramebuffersEXT(1,&pTarget->sframe); + } + } + if(curTarget==(TRenderTargetList*)targ)curTarget=0; + smTextureFree(pTarget->tex); + delete pTarget; + return; + } + pLastTarg=pTarget; + pTarget=pTarget->next; + } +} +SMTEX SMELT_IMPL::smTextureCreate(int w,int h) +{ + DWORD *px=new DWORD[w*h]; + memset(px,0,sizeof(DWORD)*w*h); + SMTEX ret=buildTexture(w,h,px); + if(ret) + { + TTextureList *tex=new TTextureList; + tex->tex=ret; + tex->w=w; + tex->h=h; + tex->next=textures; + textures=tex; + } + return ret; +} +SMTEX SMELT_IMPL::smTextureLoad(const char *path) +{ + FILE *pFile;DWORD size,rsize;char *buff; + SMTEX ret=0; + pFile=fopen(path,"rb"); + if(!pFile)return 0; + fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); + buff=(char*)malloc(sizeof(char)*size); + if(!buff)return 0; + rsize=fread(buff,1,size,pFile); + if(rsize!=size)return 0; + ret=smTextureLoadFromMemory(buff,size);if(!ret)return 0; + glTexture *t=(glTexture*)ret; + configTexture(t,t->rw,t->rh,t->px); + delete[] t->px;t->px=NULL; + t->fn=strcpy(new char[strlen(path)+1],path); + free(buff); + fclose(pFile); + return ret; +} +SMTEX SMELT_IMPL::smTextureLoadFromMemory(const char *ptr,DWORD size) +{ + int w=0,h=0;SMTEX ret=0; + DWORD *px=decodeImage((BYTE*)ptr,NULL,size,w,h); + if(px)ret=buildTexture(w,h,px); + if(ret) + { + TTextureList *tex=new TTextureList; + tex->tex=ret;tex->w=w;tex->h=h; + tex->next=textures;textures=tex; + }else smLog("%s:" SLINE ": Unsupported texture format.\n",GFX_GLFW_SRCFN); + return ret; +} +void SMELT_IMPL::smTextureFree(SMTEX tex) +{ + if(!pOpenGLDevice)return; + TTextureList *ctex=textures,*lasttex=NULL; + while(ctex) + { + if(ctex->tex==tex) + { + if(lasttex)lasttex->next=ctex->next; + else textures=ctex->next; + delete ctex; + break; + } + lasttex=ctex; + ctex=ctex->next; + } + if(tex) + { + glTexture *ptex=(glTexture*)tex; + delete[] ptex->fn;delete[] ptex->locpx;delete[] ptex->px; + glDeleteTextures(1,&ptex->name); + delete ptex; + } +} +void SMELT_IMPL::smTextureOpt(int potopt,int filter) +{ + batchOGL(); + if(potopt==TPOT_NONPOT) + { + if(pOpenGLDevice->have_GL_ARB_texture_rectangle) + pOpenGLDevice->TextureTarget=GL_TEXTURE_RECTANGLE_ARB; + else if(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) + pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; + else pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; + glDisable(GL_TEXTURE_2D); + if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); + glEnable(pOpenGLDevice->TextureTarget); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); + } + if(potopt==TPOT_POT) + { + pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; + glDisable(GL_TEXTURE_2D); + if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); + glEnable(pOpenGLDevice->TextureTarget); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_REPEAT); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_REPEAT); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_REPEAT); + } + filtermode=filter; + if(filter==TFLT_NEAREST) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + } + if(filter==TFLT_LINEAR) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + } +} +int SMELT_IMPL::smTextureGetWidth(SMTEX tex,bool original) +{ + if(original) + { + TTextureList *ctex=textures; + while(ctex){if(ctex->tex==tex)return ctex->w;ctex=ctex->next;} + } + else return ((glTexture*)tex)->rw; + return 0; +} +int SMELT_IMPL::smTextureGetHeight(SMTEX tex,bool original) +{ + if(original) + { + TTextureList *ctex=textures; + while(ctex){if(ctex->tex==tex)return ctex->h;ctex=ctex->next;} + } + else return ((glTexture*)tex)->rh; + return 0; +} +DWORD* SMELT_IMPL::smTextureLock(SMTEX tex,int l,int t,int w,int h,bool ro) +{ + glTexture *ptex=(glTexture*)tex; + if(ptex->locpx)return NULL; + bool fromfile=(ptex->px==NULL&&ptex->fn); + if(fromfile) + { + FILE *pFile;DWORD size,rsize;char *buff; + pFile=fopen(ptex->fn,"rb"); + if(!pFile)return 0; + fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); + buff=(char*)malloc(sizeof(char)*size); + if(!buff)return 0; + rsize=fread(buff,1,size,pFile); + if(rsize!=size)return 0; + int _w,_h; + ptex->px=decodeImage((BYTE*)buff,ptex->fn,size,_w,_h); + if(_w!=(int)ptex->rw||_h!=(int)ptex->rh) + {delete[] ptex->px;ptex->px=NULL;} + free(buff); + fclose(pFile); + if(ptex->px&&!ro){delete[] ptex->fn;ptex->fn=NULL;} + } + if(!ptex->px&&!ptex->isTarget)return 0; + if(!w)w=ptex->rw;if(!h)h=ptex->rh; + //asserts... + ptex->roloc=ro;ptex->locx=l;ptex->locy=t;ptex->locw=w;ptex->loch=h; + ptex->locpx=new DWORD[w*h]; + if(!ptex->isTarget) + { + DWORD *dst=ptex->locpx,*src=ptex->px+((t*ptex->rw)+l); + for(int i=0;irw; + } + } + else return 0; + return ptex->locpx; +} +void SMELT_IMPL::smTexutreUnlock(SMTEX tex) +{ + glTexture *ptex=(glTexture*)tex; + if(!ptex->locpx)return; + if(!ptex->roloc) + { + DWORD *src=ptex->locpx+ptex->locw*(ptex->loch-1), + *dst=ptex->px+(((ptex->rh-ptex->locy-1)*ptex->rw)+ptex->locx); + for(int i=0;iloch;++i) + { + memcpy(dst,src,ptex->locw*sizeof(DWORD)); + dst-=ptex->rw;src-=ptex->locw; + } + if(ptex->lost)configTexture(ptex,ptex->rw,ptex->rh,ptex->px); + else + { + glBindTexture(pOpenGLDevice->TextureTarget,ptex->name); + glTexSubImage2D(pOpenGLDevice->TextureTarget,0,ptex->locx, + (ptex->rh-ptex->locy)-ptex->loch,ptex->locw,ptex->loch,GL_RGBA, + GL_UNSIGNED_BYTE,ptex->locpx); + glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + } + } + if(ptex->fn&&ptex->roloc){delete[] ptex->px;ptex->px=NULL;} + delete[] ptex->locpx;ptex->locpx=NULL; + ptex->roloc=false; + ptex->locx=ptex->locy=ptex->locw=ptex->loch=-1; +} + +inline bool ispot(GLuint x){return((x&(x-1))==0);} +inline GLuint npot(GLuint x) +{ + --x; + for(unsigned i=1;i>i; + return x+1; +} +DWORD* SMELT_IMPL::decodeImage(BYTE *data,const char *fn,DWORD size,int &w,int &h) +{ + w=h=0; + DWORD *px=NULL; + int fnlen=fn?strlen(fn):0; + if((fnlen>5)&&(strcasecmp((fn+fnlen)-5,".rgba"))==0)//raw image... pending remove + { + DWORD *ptr=(DWORD*)data; + DWORD _w=ptr[0],_h=ptr[1]; + if(((_w*_h*4)+8)==size) + { + w=_w;h=_h; + px=new DWORD[w*h]; + memcpy(px,ptr+2,w*h*4); + } + return px; + } + CxImage img; + img.Decode(data,size,CXIMAGE_FORMAT_UNKNOWN); + if(img.IsValid()) + { + w=img.GetWidth();h=img.GetHeight(); + px=new DWORD[w*h]; + BYTE *sptr=(BYTE*)px; + bool atunnel=img.AlphaIsValid(); + for(int i=0;ilost) + configTexture(t,t->rw,t->rh,t->px); + if(((SMTEX)t)!=primTex) + { + glBindTexture(pOpenGLDevice->TextureTarget,t?t->name:0); + primTex=(SMTEX)t; + } +} +bool SMELT_IMPL::buildTarget(TRenderTargetList *pTarget,GLuint texid,int w,int h,int ms=0) +{ + bool ok=true; + if(ms) + { + if(!pOpenGLDevice->have_GL_EXT_framebuffer_object|| + !pOpenGLDevice->have_GL_EXT_framebuffer_multisample|| + !pOpenGLDevice->have_GL_EXT_framebuffer_blit) + ms=0; + else + { + glGenFramebuffersEXT(1,&pTarget->sframe); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->sframe); + glGenRenderbuffersEXT(1,&pTarget->scolor); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->scolor); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_RGBA,w,h); + glGenRenderbuffersEXT(1,&pTarget->sdepth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->sdepth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_RENDERBUFFER_EXT,pTarget->scolor); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->sdepth); + + glGenFramebuffersEXT(1,&pTarget->frame); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->frame); + glGenRenderbuffersEXT(1,&pTarget->colorms); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->colorms); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,ms,GL_RGBA,w,h); + glGenRenderbuffersEXT(1,&pTarget->depth); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->depth); + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT,ms,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,GL_RENDERBUFFER_EXT,pTarget->colorms); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->depth); + GLenum rc=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if((rc==GL_FRAMEBUFFER_COMPLETE_EXT)&&(glGetError()==GL_NO_ERROR)) + { + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + ok=true;pTarget->ms=ms; + } + else + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); + glDeleteRenderbuffersEXT(1,&pTarget->colorms); + glDeleteRenderbuffersEXT(1,&pTarget->depth); + glDeleteFramebuffersEXT(1,&pTarget->frame); + glDeleteFramebuffersEXT(1,&pTarget->sframe); + ok=false;ms=0; + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget?curTarget->frame:0); + } + } + if(!ms) + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + { + glGenFramebuffersEXT(1,&pTarget->frame); + glGenRenderbuffersEXT(1,&pTarget->depth); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,pTarget->frame); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,GL_COLOR_ATTACHMENT0_EXT,pOpenGLDevice->TextureTarget,texid,0); + glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,pTarget->depth); + glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT,GL_DEPTH_COMPONENT24,w,h); + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,GL_DEPTH_ATTACHMENT_EXT,GL_RENDERBUFFER_EXT,pTarget->depth); + GLenum rc=glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + if((rc==GL_FRAMEBUFFER_COMPLETE_EXT)&&(glGetError()==GL_NO_ERROR)) + { + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + ok=true;pTarget->ms=0; + } + else + { + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); + glDeleteRenderbuffersEXT(1,&pTarget->depth); + glDeleteFramebuffersEXT(1,&pTarget->frame); + ok=false; + } + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,curTarget?curTarget->frame:0); + } + return ok; +} +void SMELT_IMPL::configTexture(glTexture *t,int w,int h,DWORD *px,bool compressed) +{ + GLuint tex=0; + glGenTextures(1,&tex); + t->lost=false;t->name=tex;t->rw=w;t->rh=h;t->px=px; + t->dw=t->dh=0; + bool fromfile=(!px&&(t->fn)); + if(fromfile) + { + FILE *pFile;DWORD size,rsize;char *buff; + pFile=fopen(t->fn,"rb"); + if(!pFile)return; + fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); + buff=(char*)malloc(sizeof(char)*size); + if(!buff)return; + rsize=fread(buff,1,size,pFile); + if(rsize!=size)return; + int _w,_h; + px=decodeImage((BYTE*)buff,t->fn,size,_w,_h); + if(_w!=w||_h!=h){delete[] px;px=NULL;} + free(buff); + fclose(pFile); + } + glBindTexture(pOpenGLDevice->TextureTarget,tex); + if(pOpenGLDevice->TextureTarget!=GL_TEXTURE_RECTANGLE_ARB) + { + glTexParameterf(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_LOD,0.0f); + glTexParameterf(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAX_LOD,0.0f); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_BASE_LEVEL,0); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAX_LEVEL,0); + } + const GLenum fmt=pOpenGLDevice->have_GL_EXT_texture_compression_s3tc&&compressed?/*GL_COMPRESSED_RGBA_S3TC_DXT5_EXT*/GL_COMPRESSED_RGBA_ARB:GL_RGBA8; + if((pOpenGLDevice->have_GL_ARB_texture_rectangle)||(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two)||(ispot(w)&&ispot(h))) + { + glTexImage2D(pOpenGLDevice->TextureTarget,0,fmt,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,px); + } + else + { + t->dw=npot(w); + t->dh=npot(h); + glTexImage2D(pOpenGLDevice->TextureTarget,0,fmt,t->dw,t->dh,0,GL_RGBA,GL_UNSIGNED_BYTE,NULL); + glTexSubImage2D(pOpenGLDevice->TextureTarget,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); + } + glBindTexture(pOpenGLDevice->TextureTarget,primTex?(((glTexture*)primTex)->name):0); + if (fromfile)delete[] px; +} +SMTEX SMELT_IMPL::buildTexture(int w,int h,DWORD *px) +{ + glTexture *ret=new glTexture; + memset(ret,0,sizeof(glTexture)); + ret->lost=true; + ret->rw=w;ret->rh=h;ret->px=px; + return (SMTEX)ret; +} +void SMELT_IMPL::configProjectionMatrix2D(int w,int h) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0,(float)w,0,(float)h,0.0f,1.0f); +} +void SMELT_IMPL::configProjectionMatrix3D(int w,int h,float fov) +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + GLfloat matrix[16]={0.0f}; + float f=1./tanf(M_PI*fov/360.); + float ar=(float)w/(float)h; + float Near=0.1,Far=1000.; + matrix[0]=f/ar;matrix[5]=f; + matrix[10]=(Far+Near)/(Near-Far);matrix[11]=-1.0f; + matrix[14]=(2*Far*Near)/(Near-Far); + glMultMatrixf(matrix); +} +void SMELT_IMPL::batchOGL(bool endScene) +{ + if(vertexArray&&primcnt) + { + float twm=1.,thm=1.; + if(primTex) + { + if(filtermode==TFLT_NEAREST) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + } + if(filtermode==TFLT_LINEAR) + { + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + } + glTexture *ptex=(glTexture*)primTex; + if(pOpenGLDevice->TextureTarget==GL_TEXTURE_RECTANGLE_ARB) + {twm=ptex->rw;thm=ptex->rh;} + else if(ptex->dw&&ptex->dh) + { + twm=(ptex->rw)/(float)(ptex->dw); + thm=(ptex->rh)/(float)(ptex->dh); + } + } + if(!tdmode) + { + float h=curTarget?curTarget->h:scrh; + for(int i=0;i>24)&0xFF); + BYTE r=((color>>16)&0xFF); + BYTE g=((color>> 8)&0xFF); + BYTE b=((color>> 0)&0xFF); + col[0]=r;col[1]=g; + col[2]=b;col[3]=a; + } + switch(primType) + { + case PRIM_LINES: + glDrawArrays(GL_LINES,0,2*primcnt); + break; + case PRIM_TRIANGLES: + glDrawArrays(GL_TRIANGLES,0,3*primcnt); + break; + case PRIM_QUADS: + glDrawElements(GL_TRIANGLES,6*primcnt,GL_UNSIGNED_SHORT,pOpenGLDevice->have_GL_ARB_vertex_buffer_object?0:indexBuf); +#if 0 + for (int i=0;ihave_base_opengl=true; + pOpenGLDevice->have_GL_ARB_texture_rectangle=true; + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two=true; + pOpenGLDevice->have_GL_EXT_framebuffer_object=true; + pOpenGLDevice->have_GL_EXT_texture_compression_s3tc=false; + pOpenGLDevice->have_GL_ARB_vertex_buffer_object=true; + pOpenGLDevice->have_GL_EXT_framebuffer_multisample=true; + pOpenGLDevice->have_GL_EXT_framebuffer_blit=true; + GLenum glewret=glewInit(); + if(glewret) + { + smLog("%s:" SLINE ": glewInit() failed with error %s\n",GFX_GLFW_SRCFN,glewGetErrorString(glewret)); + return false; + } + if (!pOpenGLDevice->have_base_opengl) + { + unloadGLEntryPoints(); + return false; + } + smLog("%s:" SLINE ": GL_RENDERER: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_RENDERER)); + smLog("%s:" SLINE ": GL_VENDOR: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_VENDOR)); + smLog("%s:" SLINE ": GL_VERSION: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_VERSION)); + const char *verstr=(const char*)glGetString(GL_VERSION); + int maj=0,min=0; + sscanf(verstr,"%d.%d",&maj,&min); + if((maj<1)||((maj==1)&&(min<2))) + { + smLog("%s:" SLINE ": OpenGL implementation must be at least version 1.2.\n",GFX_GLFW_SRCFN); + unloadGLEntryPoints(); + return false; + } + const char *exts=(const char*)glGetString(GL_EXTENSIONS); + pOpenGLDevice->have_GL_ARB_texture_rectangle= + checkGLExtension(exts,"GL_ARB_texture_rectangle")|| + checkGLExtension(exts,"GL_EXT_texture_rectangle")|| + checkGLExtension(exts, "GL_NV_texture_rectangle"); + pOpenGLDevice->have_GL_ARB_texture_non_power_of_two= + maj>=2||checkGLExtension(exts,"GL_ARB_texture_non_power_of_two"); + if(pOpenGLDevice->have_GL_ARB_texture_rectangle) + { + smLog("%s:" SLINE ": OpenGL: Using GL_ARB_texture_rectangle.\n",GFX_GLFW_SRCFN); + pOpenGLDevice->TextureTarget=GL_TEXTURE_RECTANGLE_ARB; + } + else if(pOpenGLDevice->have_GL_ARB_texture_non_power_of_two) + { + smLog("%s:" SLINE ": OpenGL: Using GL_ARB_texture_non_power_of_two.\n",GFX_GLFW_SRCFN); + pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; + } + else + { + smLog("%s:" SLINE ": OpenGL: Using power-of-two textures. This costs more memory!\n",GFX_GLFW_SRCFN); + pOpenGLDevice->TextureTarget=GL_TEXTURE_2D; + } + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + pOpenGLDevice->have_GL_EXT_framebuffer_object= + checkGLExtension(exts, "GL_EXT_framebuffer_object"); + if(pOpenGLDevice->have_GL_EXT_framebuffer_object) + smLog("%s:" SLINE ": OpenGL: Using GL_EXT_framebuffer_object.\n",GFX_GLFW_SRCFN); + else + smLog("%s:" SLINE ": OpenGL: WARNING! No render-to-texture support. Things may render badly.\n",GFX_GLFW_SRCFN); + if(pOpenGLDevice->have_GL_EXT_texture_compression_s3tc) + pOpenGLDevice->have_GL_EXT_texture_compression_s3tc= + checkGLExtension(exts,"GL_ARB_texture_compression")&& + checkGLExtension(exts,"GL_EXT_texture_compression_s3tc"); + if(pOpenGLDevice->have_GL_EXT_texture_compression_s3tc) + smLog("%s:" SLINE ": OpenGL: Using GL_EXT_texture_compression_s3tc.\n",GFX_GLFW_SRCFN); + else if (true) + { + smLog("%s:" SLINE ": OpenGL: Texture compression disabled!\n",GFX_GLFW_SRCFN); + } + if(pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + { + pOpenGLDevice->have_GL_ARB_vertex_buffer_object= + checkGLExtension(exts,"GL_ARB_vertex_buffer_object"); + } + if(pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + smLog("%s:" SLINE ": OpenGL: Using GL_ARB_vertex_buffer_object.\n",GFX_GLFW_SRCFN); + else + smLog("%s:" SLINE ": OpenGL: WARNING! No VBO support; performance may suffer.\n",GFX_GLFW_SRCFN); + pOpenGLDevice->have_GL_EXT_framebuffer_multisample= + checkGLExtension(exts,"GL_EXT_framebuffer_multisample"); + pOpenGLDevice->have_GL_EXT_framebuffer_blit= + checkGLExtension(exts,"GL_EXT_framebuffer_blit"); + if(!pOpenGLDevice->have_GL_EXT_framebuffer_multisample||!pOpenGLDevice->have_GL_EXT_framebuffer_blit) + smLog("%s:" SLINE ": Multisampling is not supported.\n",GFX_GLFW_SRCFN); + else + smLog("%s:" SLINE ": Multisampling is supported. Still experimental!\n",GFX_GLFW_SRCFN); + return true; +} +bool SMELT_IMPL::initOGL() +{ + primTex=0; + if(pOpenGLDevice){smLog("%s:" SLINE ": Multiple initialization!\n",GFX_GLFW_SRCFN);return false;} + pOpenGLDevice=new TOpenGLDevice; + if(!loadGLEntryPoints())return false; + smLog("%s:" SLINE ": Mode: %d x %d\n",GFX_GLFW_SRCFN,scrw,scrh); + vertexArray=NULL;textures=NULL;IndexBufferObject=0; + if(!confOGL())return false; + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); + return true; +} +void SMELT_IMPL::finiOGL() +{ + while(textures)smTextureFree(textures->tex); + while(targets)smTargetFree((SMTRG)targets); + textures=NULL;targets=NULL;vertexArray=NULL; + delete[] vertexBuf;vertexBuf=NULL; + delete[] indexBuf;indexBuf=NULL; + if(pOpenGLDevice) + { + if (pOpenGLDevice->have_GL_ARB_vertex_buffer_object) + { + if (IndexBufferObject!=0) + { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,0); + glDeleteBuffersARB(1,&IndexBufferObject); + IndexBufferObject=0; + } + } + delete pOpenGLDevice; + pOpenGLDevice=NULL; + } +} +bool SMELT_IMPL::restOGL() +{ + if(!pOpenGLDevice)return false; + delete[] vertexBuf;vertexBuf=NULL; + delete[] indexBuf;indexBuf=NULL; + unloadGLEntryPoints(); + if(!loadGLEntryPoints())return false; + if(!confOGL())return false; + //if()return();//TODO: rest func + return true; +} +bool SMELT_IMPL::confOGL() +{ + bindTexture(NULL); + for(TTextureList *i=textures;i;i=i->next) + { + glTexture *t=(glTexture*)i->tex; + if(!t)continue;t->lost=true;t->name=0; + } + TRenderTargetList *target=targets; + while(target) + { + glTexture *tex=(glTexture*)target->tex; + bindTexture(tex);bindTexture(NULL); + buildTarget(target,tex?tex->name:0,target->w,target->h); + target=target->next; + } + vertexBuf=new smVertex[VERTEX_BUFFER_SIZE]; + indexBuf=new GLushort[VERTEX_BUFFER_SIZE*6/4]; + GLushort* indices=indexBuf; + for(int i=0,n=0;ihave_GL_ARB_vertex_buffer_object) + { + glGenBuffersARB(1,&IndexBufferObject); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER,IndexBufferObject); + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER,sizeof(GLushort)*((VERTEX_BUFFER_SIZE*6)/4),indexBuf,GL_STATIC_DRAW); + } + glVertexPointer(3,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].x); + glColorPointer(4,GL_UNSIGNED_BYTE,sizeof(smVertex),&vertexBuf[0].col); + glTexCoordPointer(2,GL_FLOAT,sizeof(smVertex),&vertexBuf[0].tx); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glPixelStorei(GL_UNPACK_ALIGNMENT,1); + glPixelStorei(GL_PACK_ALIGNMENT,1); + glDisable(GL_TEXTURE_2D); + if(pOpenGLDevice->have_GL_ARB_texture_rectangle)glDisable(GL_TEXTURE_RECTANGLE_ARB); + glEnable(pOpenGLDevice->TextureTarget); + glEnable(GL_SCISSOR_TEST); + glDisable(GL_CULL_FACE); + glDisable(GL_LIGHTING); + glDepthFunc(GL_GEQUAL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GEQUAL,1.0f/255.0f); + glTexEnvi(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE); + filtermode=TFLT_LINEAR; + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MIN_FILTER,GL_LINEAR); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_MAG_FILTER,GL_LINEAR); + //GL_REPEAT doesn't work with non-pot textures... + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); + glTexParameteri(pOpenGLDevice->TextureTarget,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); + primcnt=0;primType=PRIM_QUADS;primBlend=BLEND_ALPHABLEND;primTex=0; + glScissor(0,0,scrw,scrh); + glViewport(0,0,scrw,scrh); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + configProjectionMatrix2D(scrw,scrh); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + return true; +} diff --git a/smelt/glfw/makefile b/smelt/glfw/makefile index d487454..3594e5f 100644 --- a/smelt/glfw/makefile +++ b/smelt/glfw/makefile @@ -1,5 +1,5 @@ CC= g++ -CXXFLAGS= -c -g -O2 -std=c++11 -Wall -I../../include -D_LINUX -fPIC +CXXFLAGS+= -c -g -O2 -std=c++11 -Wall -I../../include -D_LINUX -fPIC TARGET= libsmelt.a all: objects-normal archive-normal diff --git a/smelt/glfw/sfx_dumb.cpp b/smelt/glfw/sfx_dumb.cpp index 4464da1..2ef89d1 100644 --- a/smelt/glfw/sfx_dumb.cpp +++ b/smelt/glfw/sfx_dumb.cpp @@ -10,6 +10,7 @@ * */ +static const char* SFX_DUMB_SRCFN="smelt/glfw/sfx_dumb.cpp"; SMSFX SMELT_IMPL::smSFXLoad(const char *path) {return 0;} SMSFX SMELT_IMPL::smSFXLoadFromMemory(const char *ptr,DWORD size) @@ -55,7 +56,7 @@ void SMELT_IMPL::smChannelSetPosd(SMCHN chn,int pos) bool SMELT_IMPL::initOAL() { - smLog("%s:" SLINE ": I'm dumb!\n",SFX_OAL_SRCFN); + smLog("%s:" SLINE ": I'm dumb!\n",SFX_DUMB_SRCFN); return true; } void SMELT_IMPL::finiOAL() diff --git a/smelt/glfw/sfx_oal.cpp b/smelt/glfw/sfx_oal.cpp index 5b8d135..a8a3299 100644 --- a/smelt/glfw/sfx_oal.cpp +++ b/smelt/glfw/sfx_oal.cpp @@ -10,8 +10,8 @@ */ #include "smelt_internal.hpp" -static const char* SFX_OAL_SRCFN="smelt/glfw/sfx_oal.cpp"; #ifndef ENABLE_DUMB +static const char* SFX_OAL_SRCFN="smelt/glfw/sfx_oal.cpp"; #ifdef ENABLE_OGG_SUPPORT struct oggdata{const BYTE *data;DWORD size,pos;}; static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); diff --git a/smelt/glfw/smelt_config.hpp b/smelt/glfw/smelt_config.hpp index 3d8c2ca..9ce9729 100644 --- a/smelt/glfw/smelt_config.hpp +++ b/smelt/glfw/smelt_config.hpp @@ -15,7 +15,7 @@ #define SRC_MAX 128 /* - * Client-side vertex buffer size. + * Vertex buffer size. */ #define VERTEX_BUFFER_SIZE 4000 @@ -28,3 +28,8 @@ * Undefine this to disable ogg support. */ #define ENABLE_OGG_SUPPORT + +/* + * Uncomment this to use the OpenGL 1.2/2.1 implementation instead. + */ +//#define USE_OPENGL_COMPATIBILITY_PROFILE diff --git a/smelt/glfw/smelt_internal.hpp b/smelt/glfw/smelt_internal.hpp index 9f51838..5b82bf6 100644 --- a/smelt/glfw/smelt_internal.hpp +++ b/smelt/glfw/smelt_internal.hpp @@ -44,8 +44,9 @@ class TOpenGLDevice { public: - GLenum TextureTarget; bool have_base_opengl; +#ifdef USE_OPENGL_COMPATIBILITY_PROFILE + GLenum TextureTarget; bool have_GL_ARB_texture_rectangle; bool have_GL_ARB_texture_non_power_of_two; bool have_GL_EXT_framebuffer_object; @@ -53,6 +54,7 @@ public: bool have_GL_ARB_vertex_buffer_object; bool have_GL_EXT_framebuffer_multisample; bool have_GL_EXT_framebuffer_blit; +#endif }; struct glTexture; @@ -193,6 +195,15 @@ public: smVertex *vertexBuf; GLushort *indexBuf; GLuint IndexBufferObject; +#ifndef USE_OPENGL_COMPATIBILITY_PROFILE + GLuint VertexBufferObject; + GLuint VertexArrayObject; + GLuint ShaderProgram; + GLuint fragshader,vertshader; + int loc_tex,loc_mmodv,loc_mproj; + float mmodv[16],mproj[16]; + SMTEX emptyTex; +#endif TRenderTargetList *targets; TRenderTargetList *curTarget; TTextureList *textures; diff --git a/smelt/glfw/smmath_priv.hpp b/smelt/glfw/smmath_priv.hpp new file mode 100644 index 0000000..ac62335 --- /dev/null +++ b/smelt/glfw/smmath_priv.hpp @@ -0,0 +1,102 @@ +// -*- C++ -*- +/* + * Simple MultimEdia LiTerator(SMELT) + * by Chris Xiong 2015 + * Math header & implementation for the core + * + * WARNING: This library is in development and interfaces would be very + * unstable. + * + */ +#ifndef SMMATH_H +#define SMMATH_H +#include +#include +#define sqr(x) ((x)*(x)) +#define EPS 1e-6 +#ifndef PI +#define PI 3.14159265358979323846f +#endif + +class _smMath +{ +public: + static double deg2rad(double deg){return deg/180.*PI;} + static double rad2deg(double rad){return rad/PI*180.;} + static double clamprad(double a){while(a<0)a+=2*PI;while(a>2*PI)a-=2*PI;return a;} + static double clampdeg(double a){while(a<0)a+=360.;while(a>360)a-=360.;return a;} +}; + +class _smvec3d +{ +public: + double x,y,z; + _smvec3d(double _x,double _y,double _z){x=_x;y=_y;z=_z;} + _smvec3d(){x=y=z=.0;} + double l(){return sqrt(sqr(x)+sqr(y)+sqr(z));} + void normalize(){double L=l();if(L=0&&s<4)return m+s*4;else return NULL;} + void clear(){for(int i=0;i<16;++i)m[i]=.0;} + void loadIdentity(){clear();m[0]=m[5]=m[10]=m[15]=1.;} + void translate(float x,float y,float z) + { + _smMatrix tmp;tmp.loadIdentity(); + tmp.m[12]=x;tmp.m[13]=y;tmp.m[14]=z; + *this=*this*tmp; + } + void rotate(float a,float x,float y,float z) + { + if(_smvec3d(x,y,z).l()<=EPS)return; + if(fabsf(_smvec3d(x,y,z).l()-1)>EPS) + { + _smvec3d a(x,y,z);a.normalize(); + x=a.x;y=a.y;z=a.z; + } + _smMatrix tmp; + float c=cosf(a),s=sinf(a); + tmp.m[ 0]=x*x*(1-c)+c; + tmp.m[ 4]=x*y*(1-c)-z*s; + tmp.m[ 8]=x*z*(1-c)+y*s; + tmp.m[ 1]=y*x*(1-c)+z*s; + tmp.m[ 5]=y*y*(1-c)+c; + tmp.m[ 9]=y*z*(1-c)-x*s; + tmp.m[ 2]=x*z*(1-c)-y*s; + tmp.m[ 6]=y*z*(1-c)+x*s; + tmp.m[10]=z*z*(1-c)+c; + tmp.m[15]=1; + *this=*this*tmp; + } + friend _smMatrix operator *(_smMatrix a,_smMatrix b) + { + _smMatrix ret; + for(int i=0;i<4;++i) + for(int j=0;j<4;++j) + for(int k=0;k<4;++k) + ret[j][i]+=a[k][i]*b[j][k]; + return ret; + } +}; +#endif diff --git a/smelt/glfw/sys_glfw.cpp b/smelt/glfw/sys_glfw.cpp index 2c8b2e9..89049dc 100644 --- a/smelt/glfw/sys_glfw.cpp +++ b/smelt/glfw/sys_glfw.cpp @@ -11,7 +11,7 @@ #include "smelt_internal.hpp" #include #include -static const char* SYS_GLFW_SRCFN="smelt/glfw/sys_glfw.cpp"; +static const char* SYS_GLFW_SRCFN="smelt/glfw_m/sys_glfw.cpp"; int refcnt=0; SMELT_IMPL *pSM=0; char lasterr[1024]; @@ -115,8 +115,14 @@ bool SMELT_IMPL::smInit() glfwWindowHint(GLFW_ALPHA_BITS,8); glfwWindowHint(GLFW_DEPTH_BITS,16); glfwWindowHint(GLFW_DOUBLEBUFFER,1); +#ifdef USE_OPENGL_COMPATIBILITY_PROFILE glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,2); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,1); +#else + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3); + glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); +#endif GLFWwindow *screen=glfwCreateWindow(windowed?scrw:dispw,windowed?scrh:disph,winTitle,NULL,NULL); hwnd=(void*)screen; if(!hwnd) diff --git a/smelt/glfw_m/CxImage b/smelt/glfw_m/CxImage deleted file mode 120000 index 07300ae..0000000 --- a/smelt/glfw_m/CxImage +++ /dev/null @@ -1 +0,0 @@ -../glfw/CxImage \ No newline at end of file diff --git a/smelt/glfw_m/gfx_glfw.cpp b/smelt/glfw_m/gfx_glfw.cpp deleted file mode 100644 index 1310fb7..0000000 --- a/smelt/glfw_m/gfx_glfw.cpp +++ /dev/null @@ -1,1028 +0,0 @@ -// -*- C++ -*- -/* - * Simple MultimEdia LiTerator(SMELT) - * by Chris Xiong 2015 - * GFX implementation based on GLFW/OpenGL 3.2+ - * - * WARNING: This library is in development and interfaces would be very - * unstable. - * - */ -#include "smelt_internal.hpp" -#include "CxImage/ximage.h" -#include "smmath_priv.hpp" -#define dbg printf("%d: 0x%X\n",__LINE__,glGetError()) -static const char* GFX_GLFW_SRCFN="smelt/glfw_m/gfx_glfw.cpp"; -static const char* fixedfunc_pipeline_vsh= - "#version 330 core\n" - "layout (location=0) in vec3 vp;" - "layout (location=1) in vec4 vc;" - "layout (location=2) in vec2 vtc;" - "out vec4 fc;" - "out vec2 ftc;" - "uniform mat4 mmodv;" - "uniform mat4 mproj;" - "void main(){" - "gl_Position=mproj*mmodv*vec4(vp,1.0f);" - "ftc=vec2(vtc.x,1.0f-vtc.y);" - "fc.rgba=vc.bgra;" - "}" -; -static const char* fixedfunc_pipeline_fsh= - "#version 330 core\n" - "in vec4 fc;" - "in vec2 ftc;" - "out vec4 color;" - "uniform sampler2D tex;" - "void main(){" - "color=fc*texture(tex,ftc);" - "if(color.a<1./256.)discard;" - "}" -; -struct glTexture -{ - GLuint name,rw,rh,dw,dh; - const char *fn; - DWORD *px,*locpx; - bool isTarget,lost,roloc; - GLint locx,locy,locw,loch; -}; -bool SMELT_IMPL::smRenderBegin2D(bool ztest,SMTRG trg) -{ - TRenderTargetList *targ=(TRenderTargetList*)trg; - if(vertexArray) - {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} - glBindFramebuffer(GL_FRAMEBUFFER,(targ)?targ->frame:0); - glDepthFunc(GL_GEQUAL); - ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); - zbufenabled=ztest; - if(targ) - { - glScissor(0,0,targ->w,targ->h); - glViewport(0,0,targ->w,targ->h); - configProjectionMatrix2D(targ->w,targ->h); - } - else - { - glScissor(0,0,scrw,scrh); - glViewport(0,0,scrw,scrh); - configProjectionMatrix2D(scrw,scrh); - } - sm2DCamera5f3v(NULL,NULL,NULL); - curTarget=targ;tdmode=0; - vertexArray=vertexBuf; - return true; -} -bool SMELT_IMPL::smRenderBegin3D(float fov,bool ztest,SMTRG trg) -{ - TRenderTargetList *targ=(TRenderTargetList*)trg; - if(vertexArray) - {smLog("%s:" SLINE ": Last frame not closed.\n",GFX_GLFW_SRCFN);return false;} - glBindFramebuffer(GL_FRAMEBUFFER,(targ)?targ->frame:0); - glDepthFunc(GL_LESS); - ztest?glEnable(GL_DEPTH_TEST):glDisable(GL_DEPTH_TEST); - zbufenabled=ztest; - if(targ) - { - glScissor(0,0,targ->w,targ->h); - glViewport(0,0,targ->w,targ->h); - configProjectionMatrix3D(targ->w,targ->h,fov); - } - else - { - glScissor(0,0,scrw,scrh); - glViewport(0,0,scrw,scrh); - configProjectionMatrix3D(scrw,scrh,fov); - } - sm3DCamera6f2v(NULL,NULL); - curTarget=targ;tdmode=1; - vertexArray=vertexBuf; - return true; -} -bool SMELT_IMPL::smRenderEnd() -{ - batchOGL(true); - if(curTarget&&curTarget->ms) - { - glTexture *pTex=(glTexture*)curTarget->tex; - if(pTex&&pTex->lost) - configTexture(pTex,pTex->rw,pTex->rh,pTex->px); - int w=curTarget->w,h=curTarget->h; - glFinish(); - DWORD *px=new DWORD[w*h]; - glBindFramebuffer(GL_READ_FRAMEBUFFER,curTarget->frame); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER,curTarget->sframe); - glBlitFramebuffer(0,0,w,h,0,0,w,h,GL_COLOR_BUFFER_BIT,GL_NEAREST); - glBindFramebuffer(GL_FRAMEBUFFER,curTarget->sframe); - glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(GL_TEXTURE_2D,pTex->name); - glTexSubImage2D(GL_TEXTURE_2D,0,0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); - delete[] px; - } - if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); - return true; -} -void SMELT_IMPL::smClrscr(DWORD color,bool clearcol,bool cleardep) -{ - GLfloat a=(GLfloat)(GETA(color))/255.f; - GLfloat r=(GLfloat)(GETR(color))/255.f; - GLfloat g=(GLfloat)(GETG(color))/255.f; - GLfloat b=(GLfloat)(GETB(color))/255.f; - if(clearcol) - glClearColor(r,g,b,a); - if(tdmode)glClearDepth(1); - else if(zbufenabled)glClearDepth(0); - glClear((clearcol?GL_COLOR_BUFFER_BIT:0)|(((zbufenabled||tdmode)&&cleardep)?GL_DEPTH_BUFFER_BIT:0)); -} -void SMELT_IMPL::sm3DCamera6f2v(float *pos,float *rot) -{ - batchOGL(); - smMatrix Mmodv; - Mmodv.loadIdentity(); - if(pos&&rot) - { - Mmodv.rotate(smMath::deg2rad(-rot[0]),1,0,0); - Mmodv.rotate(smMath::deg2rad(-rot[1]),0,1,0); - Mmodv.rotate(smMath::deg2rad(-rot[2]),0,0,1); - Mmodv.translate(-pos[0],-pos[1],-pos[2]); - } - memcpy(mmodv,Mmodv.m,sizeof(mmodv)); - glUniformMatrix4fv(loc_mmodv,1,0,mmodv); -} -void SMELT_IMPL::smMultViewMatrix(float *mat) -{ - smMatrix Mmodv(mmodv); - Mmodv=Mmodv*smMatrix(mat); - memcpy(mmodv,Mmodv.m,sizeof(mmodv)); -} -void SMELT_IMPL::sm2DCamera5f3v(float *pos,float *dpos,float *rot) -{ - batchOGL(); - smMatrix Mmodv; - Mmodv.loadIdentity(); - if(pos&&dpos&&rot) - { - Mmodv.translate(-pos[0],-pos[1],.0f); - Mmodv.rotate(*rot,.0f,.0f,1.0f); - Mmodv.translate(pos[0]+dpos[0],pos[1]+dpos[1],.0f); - } - memcpy(mmodv,Mmodv.m,sizeof(mmodv)); - glUniformMatrix4fv(loc_mmodv,1,0,mmodv); -} -void SMELT_IMPL::smRenderLinefd(float x1,float y1,float z1,float x2,float y2,float z2,DWORD color) -{ - if(vertexArray) - { - if(primType!=PRIM_LINES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_LINES||primTex||primBlend!=BLEND_ALPHABLEND) - { - batchOGL(); - primType=PRIM_LINES; - if(primBlend!=BLEND_ALPHAADD)setBlend(BLEND_ALPHAADD); - bindTexture(NULL); - } - int i=(primcnt++)*PRIM_LINES; - vertexArray[i].x=x1,vertexArray[i+1].x=x2; - vertexArray[i].y=y1,vertexArray[i+1].y=y2; - vertexArray[i].x=z1,vertexArray[i+1].x=z2; - vertexArray[i].col=vertexArray[i+1].col=color; - vertexArray[i].tx=vertexArray[i+1].tx=.0; - vertexArray[i].ty=vertexArray[i+1].ty=.0; - } -} -void SMELT_IMPL::smRenderLinefvd(float *p1,float *p2,DWORD color) -{ - if(vertexArray&&p1&&p2) - { - if(primType!=PRIM_LINES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_LINES||primTex||primBlend!=BLEND_ALPHABLEND) - { - batchOGL(); - primType=PRIM_LINES; - if(primBlend!=BLEND_ALPHAADD)setBlend(BLEND_ALPHAADD); - bindTexture(NULL); - } - int i=(primcnt++)*PRIM_LINES; - vertexArray[i].x=p1[0],vertexArray[i+1].x=p2[0]; - vertexArray[i].y=p1[1],vertexArray[i+1].y=p2[1]; - vertexArray[i].x=p2[2],vertexArray[i+1].x=p2[2]; - vertexArray[i].col=vertexArray[i+1].col=color; - vertexArray[i].tx=vertexArray[i+1].tx=.0; - vertexArray[i].ty=vertexArray[i+1].ty=.0; - } -} -void SMELT_IMPL::smRenderTriangle(smTriangle *t) -{ - if(vertexArray) - { - if(primType!=PRIM_TRIANGLES||primcnt>=VERTEX_BUFFER_SIZE/PRIM_TRIANGLES|| - primTex!=t->tex||primBlend!=t->blend) - { - batchOGL(); - primType=PRIM_TRIANGLES; - if(primBlend!=t->blend)setBlend(t->blend); - bindTexture((glTexture*)t->tex); - } - memcpy(&vertexArray[(primcnt++)*PRIM_TRIANGLES],t->v,sizeof(smVertex)*PRIM_TRIANGLES); - } -} -void SMELT_IMPL::smRenderQuad(smQuad *q) -{ - if(vertexArray) - { - if(primType!=PRIM_QUADS||primcnt>=VERTEX_BUFFER_SIZE/PRIM_QUADS|| - primTex!=q->tex||primBlend!=q->blend) - { - batchOGL(); - primType=PRIM_QUADS; - if(primBlend!=q->blend)setBlend(q->blend); - bindTexture((glTexture*)q->tex); - } - memcpy(&vertexArray[(primcnt++)*PRIM_QUADS],q->v,sizeof(smVertex)*PRIM_QUADS); - } -} -smVertex* SMELT_IMPL::smGetVertArray() -{ - if(vertexArray) - { - batchOGL(); - return vertexArray; - } - else return NULL; -} -void SMELT_IMPL::smDrawVertArray(int prim,SMTEX texture,int blend,int _primcnt) -{ - primType=prim; - bindTexture((glTexture*)texture); - if(primBlend!=blend)setBlend(blend); - primcnt=primcnt; -} -void SMELT_IMPL::smDrawCustomIndexedVertices(smVertex* vb,WORD* ib,int vbc,int ibc,int blend,SMTEX texture) -{ - if(vertexArray) - { - batchOGL(); - - float twm=-1.,thm=-1.; - if(texture) - { - glTexture *ptex=(glTexture*)texture; - if(ptex->dw&&ptex->dh) - { - twm=(ptex->rw)/(float)(ptex->dw); - thm=(ptex->rh)/(float)(ptex->dh); - } - } - if(!tdmode) - { - float h=curTarget?curTarget->h:scrh; - for(int i=0;i0&&thm>0) - for(int i=0;itex=buildTexture(w,h,NULL); - glTexture *gltex=(glTexture*)pTarget->tex; - gltex->isTarget=true;gltex->lost=false; - configTexture(gltex,w,h,NULL,false); - pTarget->w=w;pTarget->h=h; - ok=buildTarget(pTarget,gltex->name,w,h,ms); - if(!ok) - { - smLog("%s:" SLINE ": Failed to create render target.\n",GFX_GLFW_SRCFN); - smTextureFree(pTarget->tex); - delete pTarget; - return 0; - } - pTarget->next=targets; - targets=pTarget; - return (SMTRG)pTarget; -} -SMTEX SMELT_IMPL::smTargetTexture(SMTRG targ) -{ - TRenderTargetList *pTarg=(TRenderTargetList*)targ; - return targ?pTarg->tex:0; -} -void SMELT_IMPL::smTargetFree(SMTRG targ) -{ - TRenderTargetList *pTarget=targets,*pLastTarg=NULL; - while(pTarget) - { - if((TRenderTargetList*)targ==pTarget) - { - if(pLastTarg)pLastTarg->next=pTarget->next; - else targets=pTarget->next; - if(curTarget==(TRenderTargetList*)targ) - glBindFramebuffer(GL_FRAMEBUFFER_EXT,0); - if(pTarget->depth) - glDeleteRenderbuffers(1,&pTarget->depth); - glDeleteFramebuffers(1,&pTarget->frame); - if(pTarget->ms) - { - glDeleteRenderbuffers(1,&pTarget->colorms); - glDeleteRenderbuffers(1,&pTarget->scolor); - glDeleteRenderbuffers(1,&pTarget->sdepth); - glDeleteFramebuffers(1,&pTarget->sframe); - } - if(curTarget==(TRenderTargetList*)targ)curTarget=0; - smTextureFree(pTarget->tex); - delete pTarget; - return; - } - pLastTarg=pTarget; - pTarget=pTarget->next; - } -} -SMTEX SMELT_IMPL::smTextureCreate(int w,int h) -{ - DWORD *px=new DWORD[w*h]; - memset(px,0,sizeof(DWORD)*w*h); - SMTEX ret=buildTexture(w,h,px); - if(ret) - { - TTextureList *tex=new TTextureList; - tex->tex=ret; - tex->w=w; - tex->h=h; - tex->next=textures; - textures=tex; - } - return ret; -} -SMTEX SMELT_IMPL::smTextureLoad(const char *path) -{ - FILE *pFile;DWORD size,rsize;char *buff; - SMTEX ret=0; - pFile=fopen(path,"rb"); - if(!pFile)return 0; - fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); - buff=(char*)malloc(sizeof(char)*size); - if(!buff)return 0; - rsize=fread(buff,1,size,pFile); - if(rsize!=size)return 0; - ret=smTextureLoadFromMemory(buff,size);if(!ret)return 0; - glTexture *t=(glTexture*)ret; - configTexture(t,t->rw,t->rh,t->px); - delete[] t->px;t->px=NULL; - t->fn=strcpy(new char[strlen(path)+1],path); - free(buff); - fclose(pFile); - return ret; -} -SMTEX SMELT_IMPL::smTextureLoadFromMemory(const char *ptr,DWORD size) -{ - int w=0,h=0;SMTEX ret=0; - DWORD *px=decodeImage((BYTE*)ptr,NULL,size,w,h); - if(px)ret=buildTexture(w,h,px); - if(ret) - { - TTextureList *tex=new TTextureList; - tex->tex=ret;tex->w=w;tex->h=h; - tex->next=textures;textures=tex; - }else smLog("%s:" SLINE ": Unsupported texture format.\n",GFX_GLFW_SRCFN); - return ret; -} -void SMELT_IMPL::smTextureFree(SMTEX tex) -{ - if(!pOpenGLDevice)return; - TTextureList *ctex=textures,*lasttex=NULL; - while(ctex) - { - if(ctex->tex==tex) - { - if(lasttex)lasttex->next=ctex->next; - else textures=ctex->next; - delete ctex; - break; - } - lasttex=ctex; - ctex=ctex->next; - } - if(tex) - { - glTexture *ptex=(glTexture*)tex; - delete[] ptex->fn; - delete[] ptex->locpx; - delete[] ptex->px; - glDeleteTextures(1,&ptex->name); - delete ptex; - } -} -void SMELT_IMPL::smTextureOpt(int potopt,int filter) -{ - batchOGL(); - if(potopt==TPOT_NONPOT) - { - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_CLAMP_TO_EDGE); - } - if(potopt==TPOT_POT) - { - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_R,GL_REPEAT); - } - filtermode=filter; - if(filter==TFLT_NEAREST) - { - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); - } - if(filter==TFLT_LINEAR) - { - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); - } -} -int SMELT_IMPL::smTextureGetWidth(SMTEX tex,bool original) -{ - if(original) - { - TTextureList *ctex=textures; - while(ctex){if(ctex->tex==tex)return ctex->w;ctex=ctex->next;} - } - else return ((glTexture*)tex)->rw; - return 0; -} -int SMELT_IMPL::smTextureGetHeight(SMTEX tex,bool original) -{ - if(original) - { - TTextureList *ctex=textures; - while(ctex){if(ctex->tex==tex)return ctex->h;ctex=ctex->next;} - } - else return ((glTexture*)tex)->rh; - return 0; -} -DWORD* SMELT_IMPL::smTextureLock(SMTEX tex,int l,int t,int w,int h,bool ro) -{ - glTexture *ptex=(glTexture*)tex; - if(ptex->locpx)return NULL; - bool fromfile=(ptex->px==NULL&&ptex->fn); - if(fromfile) - { - FILE *pFile;DWORD size,rsize;char *buff; - pFile=fopen(ptex->fn,"rb"); - if(!pFile)return 0; - fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); - buff=(char*)malloc(sizeof(char)*size); - if(!buff)return 0; - rsize=fread(buff,1,size,pFile); - if(rsize!=size)return 0; - int _w,_h; - ptex->px=decodeImage((BYTE*)buff,ptex->fn,size,_w,_h); - if(_w!=(int)ptex->rw||_h!=(int)ptex->rh) - {delete[] ptex->px;ptex->px=NULL;} - free(buff); - fclose(pFile); - if(ptex->px&&!ro){delete[] ptex->fn;ptex->fn=NULL;} - } - if(!ptex->px&&!ptex->isTarget)return 0; - if(!w)w=ptex->rw;if(!h)h=ptex->rh; - //asserts... - ptex->roloc=ro;ptex->locx=l;ptex->locy=t;ptex->locw=w;ptex->loch=h; - ptex->locpx=new DWORD[w*h]; - if(!ptex->isTarget) - { - DWORD *dst=ptex->locpx,*src=ptex->px+((t*ptex->rw)+l); - for(int i=0;irw; - } - } - else return 0; - return ptex->locpx; -} -void SMELT_IMPL::smTexutreUnlock(SMTEX tex) -{ - glTexture *ptex=(glTexture*)tex; - if(!ptex->locpx)return; - if(!ptex->roloc) - { - DWORD *src=ptex->locpx+ptex->locw*(ptex->loch-1), - *dst=ptex->px+(((ptex->rh-ptex->locy-1)*ptex->rw)+ptex->locx); - for(int i=0;iloch;++i) - { - memcpy(dst,src,ptex->locw*sizeof(DWORD)); - dst-=ptex->rw;src-=ptex->locw; - } - if(ptex->lost)configTexture(ptex,ptex->rw,ptex->rh,ptex->px); - else - { - glBindTexture(GL_TEXTURE_2D,ptex->name); - glTexSubImage2D(GL_TEXTURE_2D,0,ptex->locx, - (ptex->rh-ptex->locy)-ptex->loch,ptex->locw,ptex->loch,GL_RGBA, - GL_UNSIGNED_BYTE,ptex->locpx); - glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); - } - } - if(ptex->fn&&ptex->roloc){delete[] ptex->px;ptex->px=NULL;} - delete[] ptex->locpx;ptex->locpx=NULL; - ptex->roloc=false; - ptex->locx=ptex->locy=ptex->locw=ptex->loch=-1; -} - -inline bool ispot(GLuint x){return((x&(x-1))==0);} -inline GLuint npot(GLuint x) -{ - --x; - for(unsigned i=1;i>i; - return x+1; -} -DWORD* SMELT_IMPL::decodeImage(BYTE *data,const char *fn,DWORD size,int &w,int &h) -{ - w=h=0; - DWORD *px=NULL; - int fnlen=fn?strlen(fn):0; - if((fnlen>5)&&(strcasecmp((fn+fnlen)-5,".rgba"))==0)//raw image... pending remove - { - DWORD *ptr=(DWORD*)data; - DWORD _w=ptr[0],_h=ptr[1]; - if(((_w*_h*4)+8)==size) - { - w=_w;h=_h; - px=new DWORD[w*h]; - memcpy(px,ptr+2,w*h*4); - } - return px; - } - CxImage img; - img.Decode(data,size,CXIMAGE_FORMAT_UNKNOWN); - if(img.IsValid()) - { - w=img.GetWidth();h=img.GetHeight(); - px=new DWORD[w*h]; - BYTE *sptr=(BYTE*)px; - bool achannel=img.AlphaIsValid(); - for(int i=0;ilost) - configTexture(t,t->rw,t->rh,t->px); - if(((SMTEX)t)!=primTex) - { - glBindTexture(GL_TEXTURE_2D,t?t->name:((glTexture*)emptyTex)->name); - glUniform1i(loc_tex,0); - primTex=(SMTEX)t; - } -} -bool SMELT_IMPL::buildTarget(TRenderTargetList *pTarget,GLuint texid,int w,int h,int ms=0) -{ - bool ok=true; - if(ms) - { - glGenFramebuffers(1,&pTarget->sframe); - glBindFramebuffer(GL_FRAMEBUFFER,pTarget->sframe); - glGenRenderbuffers(1,&pTarget->scolor); - glBindRenderbuffer(GL_RENDERBUFFER,pTarget->scolor); - glRenderbufferStorage(GL_RENDERBUFFER,GL_RGBA,w,h); - glGenRenderbuffers(1,&pTarget->sdepth); - glBindRenderbuffer(GL_RENDERBUFFER,pTarget->sdepth); - glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,pTarget->scolor); - glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->sdepth); - - glGenFramebuffers(1,&pTarget->frame); - glBindFramebuffer(GL_FRAMEBUFFER,pTarget->frame); - glGenRenderbuffers(1,&pTarget->colorms); - glBindRenderbuffer(GL_RENDERBUFFER,pTarget->colorms); - glRenderbufferStorageMultisample(GL_RENDERBUFFER,ms,GL_RGBA,w,h); - glGenRenderbuffers(1,&pTarget->depth); - glBindRenderbuffer(GL_RENDERBUFFER,pTarget->depth); - glRenderbufferStorageMultisample(GL_RENDERBUFFER,ms,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_RENDERBUFFER,pTarget->colorms); - glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->depth); - GLenum rc=glCheckFramebufferStatus(GL_FRAMEBUFFER); - if((rc==GL_FRAMEBUFFER_COMPLETE)&&(glGetError()==GL_NO_ERROR)) - { - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - ok=true;pTarget->ms=ms; - } - else - { - glBindFramebuffer(GL_FRAMEBUFFER,0); - glDeleteRenderbuffers(1,&pTarget->colorms); - glDeleteRenderbuffers(1,&pTarget->depth); - glDeleteFramebuffers(1,&pTarget->frame); - glDeleteFramebuffers(1,&pTarget->sframe); - ok=false;ms=0; - } - glBindFramebuffer(GL_FRAMEBUFFER,curTarget?curTarget->frame:0); - } - if(!ms) - { - glGenFramebuffers(1,&pTarget->frame); - glGenRenderbuffers(1,&pTarget->depth); - glBindFramebuffer(GL_FRAMEBUFFER,pTarget->frame); - glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,texid,0); - glBindRenderbuffer(GL_RENDERBUFFER,pTarget->depth); - glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT24,w,h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,pTarget->depth); - GLenum rc=glCheckFramebufferStatus(GL_FRAMEBUFFER); - if((rc==GL_FRAMEBUFFER_COMPLETE)&&(glGetError()==GL_NO_ERROR)) - { - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - ok=true;pTarget->ms=0; - } - else - { - glBindFramebuffer(GL_FRAMEBUFFER,0); - glDeleteRenderbuffers(1,&pTarget->depth); - glDeleteFramebuffers(1,&pTarget->frame); - ok=false; - } - glBindFramebuffer(GL_FRAMEBUFFER,curTarget?curTarget->frame:0); - } - return ok; -} -void SMELT_IMPL::configTexture(glTexture *t,int w,int h,DWORD *px,bool compressed) -{ - GLuint tex=0; - glGenTextures(1,&tex); - t->lost=false;t->name=tex;t->rw=w;t->rh=h;t->px=px; - t->dw=t->dh=0; - bool fromfile=(!px&&(t->fn)); - if(fromfile) - { - FILE *pFile;DWORD size,rsize;char *buff; - pFile=fopen(t->fn,"rb"); - if(!pFile)return; - fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); - buff=(char*)malloc(sizeof(char)*size); - if(!buff)return; - rsize=fread(buff,1,size,pFile); - if(rsize!=size)return; - int _w,_h; - px=decodeImage((BYTE*)buff,t->fn,size,_w,_h); - if(_w!=w||_h!=h){delete[] px;px=NULL;} - free(buff); - fclose(pFile); - } - glBindTexture(GL_TEXTURE_2D,tex); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_LOD,0.0f); - glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAX_LOD,0.0f); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0); - glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAX_LEVEL,0); - compressed=false;//compression is unusable at this moment - const GLenum fmt=compressed?/*GL_COMPRESSED_RGBA_S3TC_DXT5_EXT*/GL_COMPRESSED_RGBA_ARB:GL_RGBA8; - glTexImage2D(GL_TEXTURE_2D,0,fmt,w,h,0,GL_RGBA,GL_UNSIGNED_BYTE,px); - glBindTexture(GL_TEXTURE_2D,primTex?(((glTexture*)primTex)->name):0); - if(fromfile)delete[] px; -} -SMTEX SMELT_IMPL::buildTexture(int w,int h,DWORD *px) -{ - glTexture *ret=new glTexture; - memset(ret,0,sizeof(glTexture)); - ret->lost=true; - ret->rw=w;ret->rh=h;ret->px=px; - return (SMTEX)ret; -} -void SMELT_IMPL::configProjectionMatrix2D(int w,int h) -{ - memset(mproj,0,sizeof(mproj)); - mproj[0]=2./w; - mproj[5]=2./h; - mproj[10]=-2.; - mproj[15]=1.; - mproj[12]=mproj[13]=mproj[14]=-1.; - glUniformMatrix4fv(loc_mproj,1,0,mproj); -} -void SMELT_IMPL::configProjectionMatrix3D(int w,int h,float fov) -{ - memset(mproj,0,sizeof(mproj)); - float f=1./tanf(M_PI*fov/360.); - float ar=(float)w/(float)h; - float Near=0.1,Far=1000.; - mproj[0]=f/ar;mproj[5]=f; - mproj[10]=(Far+Near)/(Near-Far);mproj[11]=-1.0f; - mproj[14]=(2*Far*Near)/(Near-Far); - glUniformMatrix4fv(loc_mproj,1,0,mproj); -} -void SMELT_IMPL::batchOGL(bool endScene) -{ - if(vertexArray&&primcnt) - { - float twm=-1.,thm=-1.; - if(primTex) - { - glTexture *ptex=(glTexture*)primTex; - if(ptex->dw&&ptex->dh) - { - twm=(ptex->rw)/(float)(ptex->dw); - thm=(ptex->rh)/(float)(ptex->dh); - } - } - if(!tdmode) - { - float h=curTarget?curTarget->h:scrh; - for(int i=0;i0&&thm>0) - for(int i=0;ihave_base_opengl=true; - /* - * All OpenGL features utilized by SMELT are in the core profile - * for OpenGL >= 3.2. So this function is essentially useless. - */ - glewExperimental=true; - GLenum glewret=glewInit(); - if(glewret) - { - smLog("%s:" SLINE ": glewInit() failed with error %s\n",GFX_GLFW_SRCFN,glewGetErrorString(glewret)); - pOpenGLDevice->have_base_opengl=false; - return false; - } - if (!pOpenGLDevice->have_base_opengl) - { - unloadGLEntryPoints(); - return false; - } - smLog("%s:" SLINE ": GL_RENDERER: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_RENDERER)); - smLog("%s:" SLINE ": GL_VENDOR: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_VENDOR)); - smLog("%s:" SLINE ": GL_VERSION: %s\n",GFX_GLFW_SRCFN,(const char *)glGetString(GL_VERSION)); - const char *verstr=(const char*)glGetString(GL_VERSION); - int maj=0,min=0; - sscanf(verstr,"%d.%d",&maj,&min); - if((maj<3)||((maj==3)&&(min<2))) - { - smLog("%s:" SLINE ": OpenGL implementation must be at least version 3.2.\n",GFX_GLFW_SRCFN); - unloadGLEntryPoints(); - return false; - } - return true; -} -bool SMELT_IMPL::initOGL() -{ - primTex=0;emptyTex=0; - if(pOpenGLDevice){smLog("%s:" SLINE ": Multiple initialization!\n",GFX_GLFW_SRCFN);return false;} - pOpenGLDevice=new TOpenGLDevice; - if(!loadGLEntryPoints())return false; - smLog("%s:" SLINE ": Mode: %d x %d\n",GFX_GLFW_SRCFN,scrw,scrh); - vertexArray=NULL;textures=NULL; - ShaderProgram=vertshader=fragshader=0; - VertexBufferObject=VertexArrayObject=IndexBufferObject=0; - if(!confOGL())return false; - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); - if(!curTarget)glfwSwapBuffers((GLFWwindow*)hwnd); - return true; -} -void SMELT_IMPL::finiOGL() -{ - while(textures)smTextureFree(textures->tex); - while(targets)smTargetFree((SMTRG)targets); - textures=NULL;targets=NULL;vertexArray=NULL; - delete[] vertexBuf;vertexBuf=NULL; - delete[] indexBuf;indexBuf=NULL; - if(pOpenGLDevice) - { - if(VertexBufferObject!=0) - { - glBindVertexArray(VertexArrayObject); - glBindBuffer(GL_ARRAY_BUFFER,0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0); - glDeleteBuffers(1,&VertexBufferObject); - glDeleteBuffers(1,&IndexBufferObject); - glBindVertexArray(0); - glDeleteVertexArrays(1,&VertexArrayObject); - VertexArrayObject=0; - VertexBufferObject=0; - IndexBufferObject=0; - } - glDeleteProgram(ShaderProgram); - delete pOpenGLDevice; - pOpenGLDevice=NULL; - } -} -bool SMELT_IMPL::restOGL() -{ - if(!pOpenGLDevice)return false; - delete[] vertexBuf;vertexBuf=NULL; - delete[] indexBuf;indexBuf=NULL; - unloadGLEntryPoints(); - if(!loadGLEntryPoints())return false; - if(!confOGL())return false; - //if()return();//TODO: rest func - return true; -} -bool SMELT_IMPL::confOGL() -{ - bindTexture(NULL); - DWORD ones=~0U; - if(!emptyTex) - {emptyTex=buildTexture(1,1,&ones);} - configTexture((glTexture*)emptyTex,1,1,&ones,false); - for(TTextureList *i=textures;i;i=i->next) - { - glTexture *t=(glTexture*)i->tex; - if(!t)continue;t->lost=true;t->name=0; - } - TRenderTargetList *target=targets; - while(target) - { - glTexture *tex=(glTexture*)target->tex; - bindTexture(tex);bindTexture(NULL); - buildTarget(target,tex?tex->name:0,target->w,target->h); - target=target->next; - } - int compret=0; - ShaderProgram=glCreateProgram(); - vertshader=glCreateShader(GL_VERTEX_SHADER); - fragshader=glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(vertshader,1,&fixedfunc_pipeline_vsh,NULL); - glShaderSource(fragshader,1,&fixedfunc_pipeline_fsh,NULL); - glCompileShader(vertshader); - glGetShaderiv(vertshader,GL_COMPILE_STATUS,&compret); - //char log[1024]; - //glGetShaderInfoLog(vertshader,1024,NULL,log); - //puts(log); - if(!compret) - smLog("%s:" SLINE ": Warning: Your shitty vertex shader failed to compile!\n",GFX_GLFW_SRCFN); - glCompileShader(fragshader); - glGetShaderiv(fragshader,GL_COMPILE_STATUS,&compret); - //glGetShaderInfoLog(fragshader,1024,NULL,log); - //puts(log); - if(!compret) - smLog("%s:" SLINE ": Warning: Your shitty fragment shader failed to compile!\n",GFX_GLFW_SRCFN); - glAttachShader(ShaderProgram,vertshader); - glAttachShader(ShaderProgram,fragshader); - glLinkProgram(ShaderProgram); - //glGetProgramInfoLog(ShaderProgram,1024,NULL,log); - //puts(log); - glGetProgramiv(ShaderProgram,GL_LINK_STATUS,&compret); - if(!compret) - smLog("%s:" SLINE ": Warning: Default shader linkage failure!\n",GFX_GLFW_SRCFN); - glDeleteShader(vertshader); - glDeleteShader(fragshader); - glUseProgram(ShaderProgram); - loc_tex=glGetUniformLocation(ShaderProgram,"tex"); - loc_mmodv=glGetUniformLocation(ShaderProgram,"mmodv"); - loc_mproj=glGetUniformLocation(ShaderProgram,"mproj"); - vertexBuf=new smVertex[VERTEX_BUFFER_SIZE]; - indexBuf=new GLushort[VERTEX_BUFFER_SIZE*6/4]; - GLushort* indices=indexBuf; - for(int i=0,n=0;ie,sizeof(smInpEvent)); - inpQueue=inpQueue->next;delete eptr;return true; - } - return false; -} -void SMELT_IMPL::smGetMouse2f(float *x,float *y){*x=posx,*y=posy;} -void SMELT_IMPL::smSetMouse2f(float x,float y){glfwSetInputMode((GLFWwindow*)hwnd,x,y);} -void SMELT_IMPL::smSetMouseGrab(bool enabled){glfwSetInputMode((GLFWwindow*)hwnd,GLFW_CURSOR,enabled?GLFW_CURSOR_DISABLED:GLFW_CURSOR_NORMAL);} -int SMELT_IMPL::smGetWheel(){return posz;} -bool SMELT_IMPL::smIsMouseOver(){return mouseOver;} -int SMELT_IMPL::smGetKey(){return lkey;} -int SMELT_IMPL::smGetKeyState(int key) -{ - if(!(keyz[key]&4)&&keylst[key])return SMKST_RELEASE; - if(!(keyz[key]&4))return SMKST_NONE; - if((keyz[key]&4)&&!keylst[key])return SMKST_HIT; - return SMKST_KEEP; -} - -void SMELT_IMPL::buildEvent(int type,int k,int scan,int flags,int x,int y) -{ - TInputEventList *last,*eptr=new TInputEventList; - eptr->e.type=type;eptr->e.chcode=0; - int ptx=x,pty=y; - if(type==INPUT_KEYDOWN) - { - k=GLFWKeyToSMKey(k); - if((k<0)||(k>(int)(sizeof(keyz)/sizeof(keyz[0]))))return; - keyz[k]|=4;if(!(flags&SMINP_REPEAT))keyz[k]|=1; - eptr->e.chcode=(k>=32&&k<=127)?k:0; - } - if(type==INPUT_KEYUP) - { - k=GLFWKeyToSMKey(k); - if((k<0)||(k>(int)(sizeof(keyz)/sizeof(keyz[0]))))return; - keyz[k]&=~4;keyz[k]|=2; - eptr->e.chcode=(k>=32&&k<=127)?k:0; - } - if(type==INPUT_MOUSEWHEEL) - {eptr->e.sccode=0;eptr->e.wheel=k;} - else{eptr->e.sccode=k;eptr->e.wheel=0;} - if(type==INPUT_MBUTTONDOWN){keyz[k]|=1|4;captured=true;} - if(type==INPUT_MBUTTONUP){keyz[k]|=2;keyz[k]&=~4;ptx=(int)posx;pty=(int)posy;captured=false;} - if(keymods&GLFW_MOD_SHIFT)flags|=SMINP_SHIFT; - if(keymods&GLFW_MOD_CONTROL)flags|=SMINP_CTRL; - if(keymods&GLFW_MOD_ALT)flags|=SMINP_ALT; - //if(keymods&KMOD_CAPS)flags|=SMINP_CAPSLOCK; - //if(keymods&KMOD_MODE)flags|=SMINP_SCROLLLOCK; - //if(keymods&KMOD_NUM)flags|=SMINP_NUMLOCK; - eptr->e.flag=flags; - if(ptx==-1){eptr->e.x=posx;eptr->e.y=posy;} - else - { - ptx<0?ptx=0:0;pty<0?pty=0:0; - ptx>=scrw?ptx=scrw-1:0;pty>=scrh?pty=scrh-1:0; - eptr->e.x=(float)ptx;eptr->e.y=(float)pty; - } - eptr->next=0; - if(!inpQueue)inpQueue=eptr; - else - { - last=inpQueue; - while(last->next)last=last->next; - last->next=eptr; - } - if(eptr->e.type==INPUT_KEYDOWN||eptr->e.type==INPUT_MBUTTONDOWN) - lkey=eptr->e.sccode; - if(eptr->e.type==INPUT_MOUSEMOVE)posx=eptr->e.x,posy=eptr->e.y; - if(eptr->e.type==INPUT_MOUSEWHEEL)posz=eptr->e.wheel; -} -void SMELT_IMPL::initInput(){posx=posy=.0;memset(keyz,0,sizeof(keyz));} -void SMELT_IMPL::clearQueue() -{ - TInputEventList *nxt,*eptr=inpQueue; - for(unsigned i=0;inext;delete eptr;eptr=nxt;} - inpQueue=NULL;posz=0;lkey=0; -} -int SMELT_IMPL::GLFWKeyToSMKey(int glfwkey) -{ - switch (glfwkey) - { - case GLFW_KEY_ESCAPE: return SMK_ESCAPE; - case GLFW_KEY_BACKSPACE: return SMK_BACKSPACE; - case GLFW_KEY_TAB: return SMK_TAB; - case GLFW_KEY_ENTER: return SMK_ENTER; - case GLFW_KEY_SPACE: return SMK_SPACE; - case GLFW_KEY_LEFT_SHIFT: return SMK_SHIFT; - case GLFW_KEY_RIGHT_SHIFT: return SMK_SHIFT; - case GLFW_KEY_LEFT_CONTROL: return SMK_CTRL; - case GLFW_KEY_RIGHT_CONTROL: return SMK_CTRL; - case GLFW_KEY_LEFT_ALT: return SMK_ALT; - case GLFW_KEY_RIGHT_ALT: return SMK_ALT; - case GLFW_KEY_LEFT_SUPER: return SMK_LWIN; - case GLFW_KEY_RIGHT_SUPER: return SMK_RWIN; - case GLFW_KEY_PAUSE: return SMK_PAUSE; - case GLFW_KEY_CAPS_LOCK: return SMK_CAPSLOCK; - case GLFW_KEY_NUM_LOCK: return SMK_NUMLOCK; - case GLFW_KEY_SCROLL_LOCK: return SMK_SCROLLLOCK; - case GLFW_KEY_PAGE_UP: return SMK_PGUP; - case GLFW_KEY_PAGE_DOWN: return SMK_PGDN; - case GLFW_KEY_HOME: return SMK_HOME; - case GLFW_KEY_END: return SMK_END; - case GLFW_KEY_INSERT: return SMK_INSERT; - case GLFW_KEY_DELETE: return SMK_DELETE; - case GLFW_KEY_LEFT: return SMK_LEFT; - case GLFW_KEY_UP: return SMK_UP; - case GLFW_KEY_RIGHT: return SMK_RIGHT; - case GLFW_KEY_DOWN: return SMK_DOWN; - case GLFW_KEY_0: return SMK_0; - case GLFW_KEY_1: return SMK_1; - case GLFW_KEY_2: return SMK_2; - case GLFW_KEY_3: return SMK_3; - case GLFW_KEY_4: return SMK_4; - case GLFW_KEY_5: return SMK_5; - case GLFW_KEY_6: return SMK_6; - case GLFW_KEY_7: return SMK_7; - case GLFW_KEY_8: return SMK_8; - case GLFW_KEY_9: return SMK_9; - case GLFW_KEY_A: return SMK_A; - case GLFW_KEY_B: return SMK_B; - case GLFW_KEY_C: return SMK_C; - case GLFW_KEY_D: return SMK_D; - case GLFW_KEY_E: return SMK_E; - case GLFW_KEY_F: return SMK_F; - case GLFW_KEY_G: return SMK_G; - case GLFW_KEY_H: return SMK_H; - case GLFW_KEY_I: return SMK_I; - case GLFW_KEY_J: return SMK_J; - case GLFW_KEY_K: return SMK_K; - case GLFW_KEY_L: return SMK_L; - case GLFW_KEY_M: return SMK_M; - case GLFW_KEY_N: return SMK_N; - case GLFW_KEY_O: return SMK_O; - case GLFW_KEY_P: return SMK_P; - case GLFW_KEY_Q: return SMK_Q; - case GLFW_KEY_R: return SMK_R; - case GLFW_KEY_S: return SMK_S; - case GLFW_KEY_T: return SMK_T; - case GLFW_KEY_U: return SMK_U; - case GLFW_KEY_V: return SMK_V; - case GLFW_KEY_W: return SMK_W; - case GLFW_KEY_X: return SMK_X; - case GLFW_KEY_Y: return SMK_Y; - case GLFW_KEY_Z: return SMK_Z; - case GLFW_KEY_MINUS: return SMK_MINUS; - case GLFW_KEY_EQUAL: return SMK_EQUALS; - case GLFW_KEY_BACKSLASH: return SMK_BACKSLASH; - case GLFW_KEY_LEFT_BRACKET: return SMK_LBRACKET; - case GLFW_KEY_RIGHT_BRACKET: return SMK_RBRACKET; - case GLFW_KEY_SEMICOLON: return SMK_SEMICOLON; - case GLFW_KEY_APOSTROPHE: return SMK_APOSTROPHE; - case GLFW_KEY_COMMA: return SMK_COMMA; - case GLFW_KEY_PERIOD: return SMK_PERIOD; - case GLFW_KEY_SLASH: return SMK_SLASH; - case GLFW_KEY_KP_0: return SMK_NUMPAD0; - case GLFW_KEY_KP_1: return SMK_NUMPAD1; - case GLFW_KEY_KP_2: return SMK_NUMPAD2; - case GLFW_KEY_KP_3: return SMK_NUMPAD3; - case GLFW_KEY_KP_4: return SMK_NUMPAD4; - case GLFW_KEY_KP_5: return SMK_NUMPAD5; - case GLFW_KEY_KP_6: return SMK_NUMPAD6; - case GLFW_KEY_KP_7: return SMK_NUMPAD7; - case GLFW_KEY_KP_8: return SMK_NUMPAD8; - case GLFW_KEY_KP_9: return SMK_NUMPAD9; - case GLFW_KEY_KP_MULTIPLY: return SMK_MULTIPLY; - case GLFW_KEY_KP_DIVIDE: return SMK_DIVIDE; - case GLFW_KEY_KP_ADD: return SMK_ADD; - case GLFW_KEY_KP_SUBTRACT: return SMK_SUBTRACT; - case GLFW_KEY_KP_DECIMAL: return SMK_DECIMAL; - case GLFW_KEY_KP_ENTER:return SMK_ENTER; - case GLFW_KEY_F1: return SMK_F1; - case GLFW_KEY_F2: return SMK_F2; - case GLFW_KEY_F3: return SMK_F3; - case GLFW_KEY_F4: return SMK_F4; - case GLFW_KEY_F5: return SMK_F5; - case GLFW_KEY_F6: return SMK_F6; - case GLFW_KEY_F7: return SMK_F7; - case GLFW_KEY_F8: return SMK_F8; - case GLFW_KEY_F9: return SMK_F9; - case GLFW_KEY_F10: return SMK_F10; - case GLFW_KEY_F11: return SMK_F11; - case GLFW_KEY_F12: return SMK_F12; - default: return -1; - } - return -1; -} diff --git a/smelt/glfw_m/makefile b/smelt/glfw_m/makefile deleted file mode 100644 index d487454..0000000 --- a/smelt/glfw_m/makefile +++ /dev/null @@ -1,27 +0,0 @@ -CC= g++ -CXXFLAGS= -c -g -O2 -std=c++11 -Wall -I../../include -D_LINUX -fPIC -TARGET= libsmelt.a - -all: objects-normal archive-normal - -dumb: CXXFLAGS += -DENABLE_DUMB -dumb: TARGET= libsmelt-dumb.a -dumb: all - -objects-normal: gfx inp sfx sys - -gfx: - $(CC) gfx_glfw.cpp $(CXXFLAGS) -sfx: - $(CC) sfx_oal.cpp $(CXXFLAGS) -inp: - $(CC) inp_glfw.cpp $(CXXFLAGS) -sys: - $(CC) sys_glfw.cpp $(CXXFLAGS) -archive-normal: - $(AR) rcs $(TARGET) gfx_glfw.o sfx_oal.o inp_glfw.o sys_glfw.o - -clean: - rm -f *.o -clean-all: clean - rm *.a diff --git a/smelt/glfw_m/sfx_dumb.cpp b/smelt/glfw_m/sfx_dumb.cpp deleted file mode 100644 index 4464da1..0000000 --- a/smelt/glfw_m/sfx_dumb.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// -*- C++ -*- -/* - * Simple MultimEdia LiTerator(SMELT) - * by Chris Xiong 2015 - * SFX dumb implementation - * This dumb implementation has everything stubbed, useful if you don't - * use the audio routines here. - * - * WARNING: This file is not intended to be used on its own! - * - */ - -SMSFX SMELT_IMPL::smSFXLoad(const char *path) -{return 0;} -SMSFX SMELT_IMPL::smSFXLoadFromMemory(const char *ptr,DWORD size) -{return 0;} -SMCHN SMELT_IMPL::smSFXPlay(SMSFX fx,int vol,int pan,float pitch,bool loop) -{return 0;} -float SMELT_IMPL::smSFXGetLengthf(SMSFX fx) -{return 0.0;} -DWORD SMELT_IMPL::smSFXGetLengthd(SMSFX fx) -{return -1;} -void SMELT_IMPL::smSFXSetLoopPoint(SMSFX fx,DWORD l,DWORD r) -{} -void SMELT_IMPL::smSFXFree(SMSFX fx) -{} -void SMELT_IMPL::smChannelVol(SMCHN chn,int vol) -{} -void SMELT_IMPL::smChannelPan(SMCHN chn,int pan) -{} -void SMELT_IMPL::smChannelPitch(SMCHN chn,float pitch) -{} -void SMELT_IMPL::smChannelPause(SMCHN chn) -{} -void SMELT_IMPL::smChannelResume(SMCHN chn) -{} -void SMELT_IMPL::smChannelStop(SMCHN chn) -{} -void SMELT_IMPL::smChannelPauseAll() -{} -void SMELT_IMPL::smChannelResumeAll() -{} -void SMELT_IMPL::smChannelStopAll() -{} -bool SMELT_IMPL::smChannelIsPlaying(SMCHN chn) -{return false;} -float SMELT_IMPL::smChannelGetPosf(SMCHN chn) -{return -1.;} -void SMELT_IMPL::smChannelSetPosf(SMCHN chn,float pos) -{} -int SMELT_IMPL::smChannelGetPosd(SMCHN chn) -{return -1;} -void SMELT_IMPL::smChannelSetPosd(SMCHN chn,int pos) -{} - -bool SMELT_IMPL::initOAL() -{ - smLog("%s:" SLINE ": I'm dumb!\n",SFX_OAL_SRCFN); - return true; -} -void SMELT_IMPL::finiOAL() -{ -} diff --git a/smelt/glfw_m/sfx_oal.cpp b/smelt/glfw_m/sfx_oal.cpp deleted file mode 100644 index 5b8d135..0000000 --- a/smelt/glfw_m/sfx_oal.cpp +++ /dev/null @@ -1,368 +0,0 @@ -// -*- C++ -*- -/* - * Simple MultimEdia LiTerator(SMELT) - * by Chris Xiong 2015 - * GFX implementation based on OpenAL - * - * WARNING: This library is in development and interfaces would be very - * unstable. - * - */ -#include "smelt_internal.hpp" - -static const char* SFX_OAL_SRCFN="smelt/glfw/sfx_oal.cpp"; -#ifndef ENABLE_DUMB -#ifdef ENABLE_OGG_SUPPORT -struct oggdata{const BYTE *data;DWORD size,pos;}; -static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); -#endif -static void* readRiffWv(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq); -SMSFX SMELT_IMPL::smSFXLoad(const char *path) -{ - FILE *pFile;DWORD size,rsize; char *buff; - pFile=fopen(path,"rb"); - if(!pFile)return 0; - fseek(pFile,0,SEEK_END);size=ftell(pFile);rewind(pFile); - buff=(char*)malloc(sizeof(char)*size); - if(!buff)return 0; - rsize=fread(buff,1,size,pFile); - if(rsize!=size)return 0; - SMSFX ret=smSFXLoadFromMemory(buff,size); - free(buff); - fclose(pFile); - return ret; -} -SMSFX SMELT_IMPL::smSFXLoadFromMemory(const char *ptr,DWORD size) -{ - if(pOpenALDevice&&!mute) - { -#ifdef ENABLE_OGG_SUPPORT - bool isOgg=size>4&&ptr[0]=='O'&&ptr[1]=='g'&&ptr[2]=='g'&&ptr[3]=='S'; -#endif - void *decompdata=NULL,*decomp=NULL; - ALsizei decompsize=0,freq=0; - ALenum fmt=AL_FORMAT_STEREO16; - decompdata=readRiffWv((const BYTE*)ptr,size,&decompsize,&fmt,&freq); -#ifdef ENABLE_OGG_SUPPORT - if(!decompdata) - { - if(!isOgg)return 0; - else decompdata=readVorbis((const BYTE*)ptr,size,&decompsize,&fmt,&freq); - } -#endif - if(!decompdata)return 0; - decomp=decompdata; - ALuint buff=0;alGenBuffers(1,&buff); - alBufferData(buff,fmt,decomp,decompsize,freq); - free(decompdata);return(SMSFX)buff; - } - return 0; -} -SMCHN SMELT_IMPL::smSFXPlay(SMSFX fx,int vol,int pan,float pitch,bool loop) -{ - if(pOpenALDevice) - { - ALuint src=getSource(); - if(src) - { - if(vol<0)vol=0;if(vol>100)vol=100; - if(pan<-100)pan=-100;if(pan>100)pan=100; - alSourceStop(src); - alSourcei(src,AL_BUFFER,(ALint)fx); - alSourcef(src,AL_GAIN,((ALfloat)vol)/100.); - alSourcef(src,AL_PITCH,pitch); - alSource3f(src,AL_POSITION,((ALfloat)pan)/100.,.0,.0); - alSourcei(src,AL_LOOPING,loop?AL_TRUE:AL_FALSE); - alSourcePlay(src); - } - return src; - } - return 0; -} -float SMELT_IMPL::smSFXGetLengthf(SMSFX fx) -{ - ALuint buff=(ALuint)fx; - ALint freq; - DWORD lend=smSFXGetLengthd(fx); - alGetBufferi(buff,AL_FREQUENCY,&freq); - float ret=lend/(float)freq; - return ret; -} -DWORD SMELT_IMPL::smSFXGetLengthd(SMSFX fx) -{ - if(pOpenALDevice) - { - ALint size_b,chnc,bit; - ALuint buff=(ALuint)fx; - alGetBufferi(buff,AL_SIZE,&size_b); - alGetBufferi(buff,AL_CHANNELS,&chnc); - alGetBufferi(buff,AL_BITS,&bit); - DWORD ret=size_b*8/(chnc*bit); - return ret; - } - return -1; -} -void SMELT_IMPL::smSFXSetLoopPoint(SMSFX fx,DWORD l,DWORD r) -{ - if(pOpenALDevice) - { - ALint pt[2];pt[0]=l;pt[1]=r; - alBufferiv((ALuint)fx,AL_LOOP_POINTS_SOFT,pt); - } -} -void SMELT_IMPL::smSFXFree(SMSFX fx) -{ - if(pOpenALDevice) - { - ALuint buff=(ALuint)fx; - alDeleteBuffers(1,&buff); - } -} -void SMELT_IMPL::smChannelVol(SMCHN chn,int vol) -{ - if(pOpenALDevice) - { - if(vol<0)vol=0;if(vol>100)vol=100; - alSourcef((ALuint)chn,AL_GAIN,((ALfloat)vol)/100.); - } -} -void SMELT_IMPL::smChannelPan(SMCHN chn,int pan) -{ - if(pOpenALDevice) - { - if(pan<-100)pan=-100;if(pan>100)pan=100; - alSource3f((ALuint)chn,AL_POSITION,((ALfloat)pan)/100.,.0,.0); - } -} -void SMELT_IMPL::smChannelPitch(SMCHN chn,float pitch) -{ - if(pOpenALDevice)alSourcef((ALuint)chn,AL_PITCH,pitch); -} -void SMELT_IMPL::smChannelPause(SMCHN chn) -{ - if(pOpenALDevice)alSourcePause((ALuint)chn); -} -void SMELT_IMPL::smChannelResume(SMCHN chn) -{ - if(pOpenALDevice)alSourcePlay((ALuint)chn); -} -void SMELT_IMPL::smChannelStop(SMCHN chn) -{ - if(pOpenALDevice)alSourceStop((ALuint)chn); -} -void SMELT_IMPL::smChannelPauseAll() -{ - if(pOpenALDevice) - { - ALCcontext *ctx=alcGetCurrentContext(); - alcSuspendContext(ctx); - } -} -void SMELT_IMPL::smChannelResumeAll() -{ - if(pOpenALDevice) - { - ALCcontext *ctx=alcGetCurrentContext(); - alcProcessContext(ctx); - } -} -void SMELT_IMPL::smChannelStopAll() -{ - if(pOpenALDevice) - { - for(int i=0;isize-data->pos; - size_t want=nmemb*size; - if(want>avail)want=avail-(avail%size); - if(want>0) - { - memcpy(ptr,data->data+data->pos,want); - data->pos+=want; - } - return want/size; -} -static int oggSeek(void *ds,ogg_int64_t offset,int whence) -{ - oggdata *data=(oggdata*)ds; - ogg_int64_t pos=0; - switch(whence) - { - case SEEK_SET:pos=offset;break; - case SEEK_CUR:pos=((ogg_int64_t)data->pos)+offset;break; - case SEEK_END:pos=((ogg_int64_t)data->size)+offset;break; - default: return -1; - } - if((pos<0)||(pos>((ogg_int64_t)data->size)))return -1; - data->pos=(DWORD)pos; - return 0; -} -static long oggLocate(void *ds) -{ - oggdata* data=(oggdata*)ds; - return (long)data->pos; -} -static int oggClose(void *ds){return 0;} - -static ov_callbacks oggrt={oggRead,oggSeek,oggClose,oggLocate}; -static void* readVorbis(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq) -{ - oggdata adata={data,size,0}; - OggVorbis_File vf; - memset(&vf,0,sizeof(vf)); - if(ov_open_callbacks(&adata,&vf,NULL,0,oggrt)==0) - { - int bs=0; - vorbis_info *info=ov_info(&vf,-1); - *decomp_size=0; - *fmt=(info->channels==1)?AL_FORMAT_MONO16:AL_FORMAT_STEREO16; - *freq=info->rate; - if(!(info->channels==1||info->channels==2)){ov_clear(&vf);return NULL;} - char buf[1024*16];long rc=0;size_t allocated=1024*16; - BYTE *ret=(ALubyte*)malloc(allocated); - while((rc=ov_read(&vf,buf,sizeof(buf),0,2,1,&bs))!=0) - { - if(rc>0) - { - *decomp_size+=rc; - if((unsigned)*decomp_size>=allocated) - { - allocated<<=1; - ALubyte *tmp=(ALubyte*)realloc(ret,allocated); - if(!tmp){free(ret);ret=NULL;break;} - ret=tmp; - } - memcpy(ret+(*decomp_size-rc),buf,rc); - } - } - ov_clear(&vf); - return ret; - } - return NULL; -} -#endif -static void* readRiffWv(const BYTE *data,const DWORD size, ALsizei *decomp_size,ALenum *fmt,ALsizei *freq) -{ - if(data[0x0]!='R'||data[0x1]!='I'||data[0x2]!='F'||data[0x3]!='F')return NULL; - if(data[0x8]!='W'||data[0x9]!='A'||data[0xA]!='V'||data[0xB]!='E')return NULL; - if(data[0xC]!='f'||data[0xD]!='m'||data[0xE]!='t'||data[0xF]!=' ')return NULL; - if(data[0x16]==2) - { - if(data[0x22]==16)*fmt=AL_FORMAT_STEREO16; - else if(data[0x22]==8)*fmt=AL_FORMAT_STEREO8; - else return NULL; - } - else if(data[0x16]==1) - { - if(data[0x22]==16)*fmt=AL_FORMAT_MONO16; - else if(data[0x22]==8)*fmt=AL_FORMAT_MONO8; - else return NULL; - }else return NULL; - *decomp_size=(ALsizei)(data[0x28]|(data[0x29]<<8L)|(data[0x2A]<<16L)|(data[0x2B]<<24L)); - *freq=(ALsizei)(data[0x18]|(data[0x19]<<8L)|(data[0x1A]<<16L)|(data[0x1B]<<24L)); - ALubyte *ret=(ALubyte*)malloc(*decomp_size); - memcpy(ret,data+44,*decomp_size); - return ret; -} -ALuint SMELT_IMPL::getSource() -{ - for(int i=0;i=SRC_MAX)return 0; - ALuint ret=0; - alGenSources(1,&ret);if(!ret)return 0; - src[scnt++]=ret;return ret; -} -bool SMELT_IMPL::initOAL() -{ - if(pOpenALDevice)return true; - scnt=0;memset(src,0,sizeof(src)); - smLog("%s:" SLINE ": Initializing OpenAL...\n",SFX_OAL_SRCFN); - ALCdevice *dev=alcOpenDevice(NULL); - if(!dev) - { - smLog("%s:" SLINE ": alcOpenDevice() failed.\n",SFX_OAL_SRCFN); - return mute=true; - } - ALint caps[]={ALC_FREQUENCY,44100,0}; - ALCcontext *ctx=alcCreateContext(dev,caps); - if(!ctx) - { - smLog("%s:" SLINE ": alcCreateContext() failed.\n",SFX_OAL_SRCFN); - return mute=true; - } - alcMakeContextCurrent(ctx);alcProcessContext(ctx); - smLog("%s:" SLINE ": Done OpenAL initialization\n",SFX_OAL_SRCFN); - smLog("%s:" SLINE ": AL_VENDOR: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_VENDOR)); - smLog("%s:" SLINE ": AL_RENDERER: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_RENDERER)); - smLog("%s:" SLINE ": AL_VERSION: %s\n",SFX_OAL_SRCFN,(char*)alGetString(AL_VERSION)); - const char* ext=(const char*)alGetString(AL_EXTENSIONS); - lpp=strstr(ext,"AL_SOFT_loop_points")!=NULL; - if(!lpp)smLog("%s:" SLINE ": Warning: loop points not supported. Please recompile with OpenAL Soft.\n",SFX_OAL_SRCFN); - pOpenALDevice=(void*)dev; - return true; -} -void SMELT_IMPL::finiOAL() -{ - if(pOpenALDevice) - { - for(int i=0;i -#include -#include -#include -#include -#include -#include -#define GLEW_STATIC -#include -#include -#ifndef ENABLE_DUMB -#include -#include -#include -#ifdef ENABLE_OGG_SUPPORT -#include -#include -#endif -#endif -#ifdef WIN32 -#include -#include -#endif - -#define xstr(s) str(s) -#define str(s) #s -#define SLINE xstr(__LINE__) - -class TOpenGLDevice -{ -public: - bool have_base_opengl; -}; - -struct glTexture; -class TRenderTargetList -{ -public: - int w,h,ms; - SMTEX tex; - GLuint depth,frame,colorms,sframe,sdepth,scolor; - TRenderTargetList *next; -}; -class TTextureList -{ -public: - SMTEX tex; - int w,h; - TTextureList *next; -}; -class TInputEventList -{ -public: - smInpEvent e; - TInputEventList *next; -}; - -class SMELT_IMPL:public SMELT -{ -public: - virtual void smRelease(); - virtual bool smInit(); - virtual void smFinale(); - virtual void smMainLoop(); - virtual void smUpdateFunc(smHook func); - virtual void smUpdateFunc(smHandler* h); - virtual void smUnFocFunc(smHook func); - virtual void smUnFocFunc(smHandler* h); - virtual void smFocFunc(smHook func); - virtual void smFocFunc(smHandler* h); - virtual void smQuitFunc(smHook func); - virtual void smQuitFunc(smHandler* h); - virtual void smWinTitle(const char* title); - virtual bool smIsActive(); - virtual void smNoSuspend(bool para); - virtual void smVidMode(int resX,int resY,bool _windowed); - virtual void smLogFile(const char* path); - virtual void smLog(const char* format,...); - virtual void smScreenShot(const char* path); - - virtual void smSetFPS(int fps); - virtual float smGetFPS(); - virtual float smGetDelta(); - virtual float smGetTime(); - - virtual SMSFX smSFXLoad(const char *path); - virtual SMSFX smSFXLoadFromMemory(const char *ptr,DWORD size); - virtual SMCHN smSFXPlay(SMSFX fx,int vol=100,int pan=0,float pitch=1.,bool loop=0); - virtual float smSFXGetLengthf(SMSFX fx); - virtual DWORD smSFXGetLengthd(SMSFX fx); - virtual void smSFXSetLoopPoint(SMSFX fx,DWORD l,DWORD r); - virtual void smSFXFree(SMSFX fx); - - virtual void smChannelVol(SMCHN chn,int vol); - virtual void smChannelPan(SMCHN chn,int pan); - virtual void smChannelPitch(SMCHN chn,float pitch); - virtual void smChannelPause(SMCHN chn); - virtual void smChannelResume(SMCHN chn); - virtual void smChannelStop(SMCHN chn); - virtual void smChannelPauseAll(); - virtual void smChannelResumeAll(); - virtual void smChannelStopAll(); - virtual bool smChannelIsPlaying(SMCHN chn); - virtual float smChannelGetPosf(SMCHN chn); - virtual void smChannelSetPosf(SMCHN chn,float pos); - virtual int smChannelGetPosd(SMCHN chn); - virtual void smChannelSetPosd(SMCHN chn,int pos); - - virtual void smGetMouse2f(float *x,float *y); - virtual void smSetMouse2f(float x,float y); - virtual void smSetMouseGrab(bool enabled); - virtual int smGetWheel(); - virtual bool smIsMouseOver(); - virtual int smGetKeyState(int key); - virtual int smGetKey(); - virtual bool smGetInpEvent(smInpEvent *e); - - virtual bool smRenderBegin2D(bool ztest=0,SMTRG trg=0); - virtual bool smRenderBegin3D(float fov,bool ztest=0,SMTRG trg=0); - virtual bool smRenderEnd(); - virtual void sm3DCamera6f2v(float *pos,float *rot); - virtual void sm2DCamera5f3v(float *pos,float *dpos,float *rot); - virtual void smMultViewMatrix(float *mat); - virtual void smClrscr(DWORD color,bool clearcol=true,bool cleardep=true); - virtual void smRenderLinefd(float x1,float y1,float z1,float x2,float y2,float z2,DWORD color); - virtual void smRenderLinefvd(float *p1,float *p2,DWORD color); - virtual void smRenderTriangle(smTriangle *t); - virtual void smRenderQuad(smQuad *q); - virtual smVertex* smGetVertArray(); - virtual void smDrawVertArray(int prim,SMTEX texture,int blend,int _primcnt); - virtual void smDrawCustomIndexedVertices(smVertex* vb,WORD* ib,int vbc,int ibc,int blend,SMTEX texture); - - virtual SMTRG smTargetCreate(int w,int h,int ms=0); - virtual SMTEX smTargetTexture(SMTRG targ); - virtual void smTargetFree(SMTRG targ); - - virtual SMTEX smTextureCreate(int w,int h); - virtual SMTEX smTextureLoad(const char *path); - virtual SMTEX smTextureLoadFromMemory(const char *ptr,DWORD size); - virtual void smTextureFree(SMTEX tex); - virtual void smTextureOpt(int potopt=TPOT_NONPOT,int filter=TFLT_LINEAR); - virtual int smTextureGetWidth(SMTEX tex,bool original=false); - virtual int smTextureGetHeight(SMTEX tex,bool original=false); - virtual DWORD* smTextureLock(SMTEX tex,int l,int t,int w,int h,bool ro=true); - virtual void smTexutreUnlock(SMTEX tex); -//internal routines&variables... - static SMELT_IMPL* getInterface(); - void focusChange(bool actif); - - void *hwnd; - bool Active; - char curError[256]; - - bool (*pUpdateFunc)(); - bool (*pUnFocFunc)(); - bool (*pFocFunc)(); - bool (*pQuitFunc)(); - smHandler *updateHandler,*unFocHandler,*focHandler,*quitHandler; - const char *Icon; - char winTitle[256]; - int scrw,scrh; - int dispw,disph; - bool windowed,vsync; - char logFile[256]; - int limfps; - bool hideMouse,noSuspend; - - TOpenGLDevice *pOpenGLDevice; - smVertex *vertexArray; - smVertex *vertexBuf; - GLushort *indexBuf; - GLuint IndexBufferObject; - GLuint VertexBufferObject; - GLuint VertexArrayObject; - GLuint ShaderProgram; - GLuint fragshader,vertshader; - int loc_tex,loc_mmodv,loc_mproj; - float mmodv[16],mproj[16]; - TRenderTargetList *targets; - TRenderTargetList *curTarget; - TTextureList *textures; - bool tdmode; - int primcnt,primType,primBlend,filtermode; - SMTEX primTex,emptyTex; - bool zbufenabled; - bool checkGLExtension(const char *extlist,const char *ext); - void unloadGLEntryPoints(); - bool loadGLEntryPoints(); - bool initOGL(); - void finiOGL(); - bool restOGL(); - bool confOGL(); - void batchOGL(bool endScene=false); - void configTexture(glTexture *t,int w,int h,DWORD *px,bool compress=true); - void bindTexture(glTexture *t); - bool buildTarget(TRenderTargetList *pTarget,GLuint texid,int w,int h,int ms); - SMTEX buildTexture(int w,int h,DWORD *px); - void setBlend(int blend); - void configProjectionMatrix2D(int w,int h); - void configProjectionMatrix3D(int w,int h,float fov); - DWORD* decodeImage(BYTE *data,const char *fn,DWORD size,int &w,int &h); - - void *pOpenALDevice; - bool mute,lpp; - bool initOAL(); - void finiOAL(); -#ifndef ENABLE_DUMB - int scnt; - ALuint src[SRC_MAX]; - ALuint getSource(); -#endif - - int posz,lkey; - float posx,posy; - int keymods; - bool mouseOver,captured; - char keyz[256]; - bool keylst[256]; - TInputEventList *inpQueue; - void initInput(); - void clearQueue(); - void buildEvent(int type,int k,int scan,int flags,int x,int y); - bool procGLFWEvent(); - int GLFWKeyToSMKey(int glfwkey); - - float timeDelta,updateFPSDelay,fps,timeS; - DWORD fixDelta,t0; - int fcnt; - DWORD dt; -private: - SMELT_IMPL(); -}; -extern SMELT_IMPL *pSM; -#endif diff --git a/smelt/glfw_m/smmath_priv.hpp b/smelt/glfw_m/smmath_priv.hpp deleted file mode 100644 index 90f0e2a..0000000 --- a/smelt/glfw_m/smmath_priv.hpp +++ /dev/null @@ -1,165 +0,0 @@ -// -*- C++ -*- -/* - * Simple MultimEdia LiTerator(SMELT) - * by Chris Xiong 2015 - * Math header & implementation for the core - * - * WARNING: This library is in development and interfaces would be very - * unstable. - * - */ -#ifndef SMMATH_H -#define SMMATH_H -#include -#include -#define sqr(x) ((x)*(x)) -#define EPS 1e-6 -#ifndef PI -#define PI 3.14159265358979323846f -#endif - -class smMath -{ -public: - static double deg2rad(double deg){return deg/180.*PI;} - static double rad2deg(double rad){return rad/PI*180.;} - static double clamprad(double a){while(a<0)a+=2*PI;while(a>2*PI)a-=2*PI;return a;} - static double clampdeg(double a){while(a<0)a+=360.;while(a>360)a-=360.;return a;} -}; -class smvec2d -{ -public: - float x,y; - smvec2d(float _x,float _y){x=_x;y=_y;} - smvec2d(){x=y=.0;} - float l(){return sqrtf(sqr(x)+sqr(y));} - void normalize(){float L=l();if(L=0&&s<4)return m+s*4;else return NULL;} - void clear(){for(int i=0;i<16;++i)m[i]=.0;} - void loadIdentity(){clear();m[0]=m[5]=m[10]=m[15]=1.;} - void translate(float x,float y,float z) - { - smMatrix tmp;tmp.loadIdentity(); - tmp.m[12]=x;tmp.m[13]=y;tmp.m[14]=z; - *this=*this*tmp; - } - void rotate(float a,float x,float y,float z) - { - if(smvec3d(x,y,z).l()<=EPS)return; - if(fabsf(smvec3d(x,y,z).l()-1)>EPS) - { - smvec3d a(x,y,z);a.normalize(); - x=a.x;y=a.y;z=a.z; - } - smMatrix tmp; - float c=cosf(a),s=sinf(a); - tmp.m[ 0]=x*x*(1-c)+c; - tmp.m[ 4]=x*y*(1-c)-z*s; - tmp.m[ 8]=x*z*(1-c)+y*s; - tmp.m[ 1]=y*x*(1-c)+z*s; - tmp.m[ 5]=y*y*(1-c)+c; - tmp.m[ 9]=y*z*(1-c)-x*s; - tmp.m[ 2]=x*z*(1-c)-y*s; - tmp.m[ 6]=y*z*(1-c)+x*s; - tmp.m[10]=z*z*(1-c)+c; - tmp.m[15]=1; - *this=*this*tmp; - } - void lookat(smvec3d eye,smvec3d at,smvec3d up) - { - smvec3d f=at-eye;f.normalize();up.normalize(); - smvec3d s=f*up;smvec3d u=s.getNormalized()*f; - m[0]= s.x;m[4]= s.y;m[ 8]= s.z;m[12]=0; - m[1]= u.x;m[5]= u.y;m[ 9]= u.z;m[13]=0; - m[2]=-f.x;m[6]=-f.y;m[10]=-f.z;m[14]=0; - m[3]= 0;m[7]= 0;m[11]= 0;m[15]=1; - } - friend smMatrix operator *(smMatrix a,smMatrix b) - { - smMatrix ret; - for(int i=0;i<4;++i) - for(int j=0;j<4;++j) - for(int k=0;k<4;++k) - ret[j][i]+=a[k][i]*b[j][k]; - return ret; - } - friend smvec3d operator *(smMatrix a,smvec3d b) - { - return smvec3d(a[0][0]*b.x+a[1][0]*b.y+a[2][0]*b.z, - a[0][1]*b.x+a[1][1]*b.y+a[2][1]*b.z, - a[0][2]*b.x+a[1][2]*b.y+a[2][2]*b.z); - } - friend smvec4d operator *(smMatrix a,smvec4d b) - { - return smvec4d(a[0][0]*b.x+a[1][0]*b.y+a[2][0]*b.z+a[3][0]*b.w, - a[0][1]*b.x+a[1][1]*b.y+a[2][1]*b.z+a[3][1]*b.w, - a[0][2]*b.x+a[1][2]*b.y+a[2][2]*b.z+a[3][2]*b.w, - a[0][3]*b.x+a[1][3]*b.y+a[2][3]*b.z+a[3][3]*b.w); - } -}; -#endif diff --git a/smelt/glfw_m/sys_glfw.cpp b/smelt/glfw_m/sys_glfw.cpp deleted file mode 100644 index a5829f3..0000000 --- a/smelt/glfw_m/sys_glfw.cpp +++ /dev/null @@ -1,334 +0,0 @@ -// -*- C++ -*- -/* - * Simple MultimEdia LiTerator(SMELT) - * by Chris Xiong 2015 - * SMELT system implementation - * - * WARNING: This library is in development and interfaces would be very - * unstable. - * - */ -#include "smelt_internal.hpp" -#include -#include -static const char* SYS_GLFW_SRCFN="smelt/glfw_m/sys_glfw.cpp"; -int refcnt=0; -SMELT_IMPL *pSM=0; -char lasterr[1024]; - -void glfwErrorHandler(int err,const char* desc); -void glfwFocChangeHandler(GLFWwindow*,int foc); -void glfwCursorEnterHandler(GLFWwindow*,int ent); -void glfwKBEventHandler(GLFWwindow* window,int key,int scancode,int action,int mods); -void glfwMouseButtonHandler(GLFWwindow* w,int btn,int action,int mods); -void glfwMouseMotionHandler(GLFWwindow*,double x,double y); -void glfwMouseWheelHandler(GLFWwindow* w,double x,double y); - -SMELT* smGetInterface(int apilevel) -{ - if(apilevel==SMELT_APILEVEL) - return(SMELT*)SMELT_IMPL::getInterface(); - else return 0; -} - -SMELT_IMPL* SMELT_IMPL::getInterface() -{ - if(!pSM)pSM=new SMELT_IMPL(); - ++refcnt;return pSM; -} - -void SMELT_IMPL::smRelease() -{ - --refcnt; - if(!refcnt) - { - if(pSM->hwnd)pSM->smFinale(); - delete pSM;pSM=0; - } -} - -bool SMELT_IMPL::smInit() -{ - smLog("%s:" SLINE ": Initalizing SMELT...\n",SYS_GLFW_SRCFN); - smLog("%s:" SLINE ": SMELT api version %d\n",SYS_GLFW_SRCFN,SMELT_APILEVEL); - time_t t=time(NULL); - smLog("%s:" SLINE ": Date %s",SYS_GLFW_SRCFN,asctime(localtime(&t))); -#ifdef WIN32 - OSVERSIONINFO os_ver; MEMORYSTATUS mem_st; - os_ver.dwOSVersionInfoSize=sizeof(os_ver); - GetVersionEx(&os_ver); - smLog("%s:" SLINE ": OS: Windows %ld.%ld.%ld\n", SYS_GLFW_SRCFN,os_ver.dwMajorVersion,os_ver.dwMinorVersion,os_ver.dwBuildNumber); - - int CPUInfo[4]={-1}; - __cpuid(CPUInfo,0x80000000); - unsigned int nExIds=CPUInfo[0]; - char *cpuName,*loced;cpuName=(char*)calloc(0x40,sizeof(char));loced=cpuName; - for(unsigned int i=0x80000000;i<=nExIds;++i) - { - __cpuid(CPUInfo, i); - if(i==0x80000002) - memcpy(cpuName,CPUInfo,sizeof(CPUInfo)); - else if(i==0x80000003) - memcpy(cpuName+16,CPUInfo,sizeof(CPUInfo)); - else if(i==0x80000004) - memcpy(cpuName+32, CPUInfo, sizeof(CPUInfo)); - } - while(*cpuName==' ')++cpuName; - smLog("%s:" SLINE ": CPU: %s\n", SYS_GLFW_SRCFN,cpuName); - free(loced); - - GlobalMemoryStatus(&mem_st); - smLog("%s:" SLINE ": Memory: %ldK total, %ldK free\n", SYS_GLFW_SRCFN,mem_st.dwTotalPhys/1024L,mem_st.dwAvailPhys/1024L); -#else - system("uname -svm > /tmp/os.out"); - char osv[100];FILE* a=fopen("/tmp/os.out","r");fgets(osv,100,a);fclose(a); - osv[strlen(osv)-1]='\0'; - smLog("%s:" SLINE ": OS: %s\n",SYS_GLFW_SRCFN,osv); - system("rm /tmp/os.out"); - - system("cat /proc/cpuinfo | grep name -m 1 > /tmp/cpu.out"); - a=fopen("/tmp/cpu.out","r");fgets(osv,100,a);fclose(a); - osv[strlen(osv)-1]='\0';char *ptr=osv;while(*ptr!=':')++ptr;ptr+=2; - smLog("%s:" SLINE ": CPU: %s\n",SYS_GLFW_SRCFN,osv); - system("rm /tmp/cpu.out"); - - a=fopen("/proc/meminfo","r"); - unsigned totalm,freem; - fscanf(a,"MemTotal: %u kB\n",&totalm); - fscanf(a,"MemFree: %u kB\n",&freem); - smLog("%s:" SLINE ": RAM: %ukB installed, %ukB free\n",SYS_GLFW_SRCFN,totalm,freem); - fclose(a); -#endif - glfwSetErrorCallback(glfwErrorHandler); - if(!glfwInit()) - { - smLog("%s:" SLINE ": glfwInit() failed with error %s\n",SYS_GLFW_SRCFN,lasterr); - return false; - } - GLFWmonitor *moninfo=glfwGetPrimaryMonitor(); - dispw=glfwGetVideoMode(moninfo)->width; - disph=glfwGetVideoMode(moninfo)->height; - smLog("%s:" SLINE ": Screen: %d x %d\n",SYS_GLFW_SRCFN,dispw,disph); - glfwWindowHint(GLFW_RED_BITS,8); - glfwWindowHint(GLFW_GREEN_BITS,8); - glfwWindowHint(GLFW_BLUE_BITS,8); - glfwWindowHint(GLFW_ALPHA_BITS,8); - glfwWindowHint(GLFW_DEPTH_BITS,16); - glfwWindowHint(GLFW_DOUBLEBUFFER,1); - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3); - glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE); - GLFWwindow *screen=glfwCreateWindow(windowed?scrw:dispw,windowed?scrh:disph,winTitle,NULL,NULL); - hwnd=(void*)screen; - if(!hwnd) - { - smLog("%s:" SLINE ": glfwCreateWindow() failed with error %s\n",SYS_GLFW_SRCFN,lasterr); - glfwTerminate(); - return false; - } - glfwMakeContextCurrent(screen); - glfwSwapInterval(vsync?1:0); - if(!windowed) - { - mouseOver=true; - if(!pSM->Active)pSM->focusChange(true); - } - if(hideMouse)glfwSetInputMode(screen,GLFW_CURSOR,GLFW_CURSOR_HIDDEN); - glfwSetWindowFocusCallback(screen,glfwFocChangeHandler); - glfwSetCursorEnterCallback(screen,glfwCursorEnterHandler); - glfwSetKeyCallback(screen,glfwKBEventHandler); - glfwSetCursorPosCallback(screen,glfwMouseMotionHandler); - glfwSetMouseButtonCallback(screen,glfwMouseButtonHandler); - glfwSetScrollCallback(screen,glfwMouseWheelHandler); - initInput(); - if(!initOGL()){smFinale();return false;} - if(!initOAL()){smFinale();return false;} - t0=DWORD(glfwGetTime()*1000.);dt=fcnt=0;fps=.0; - updateFPSDelay=.0; - return true; -} - -void SMELT_IMPL::smFinale() -{ - smLog("%s:" SLINE ": Cleaning up...\n",SYS_GLFW_SRCFN); - clearQueue();finiOAL();finiOGL(); - glfwDestroyWindow((GLFWwindow*)hwnd);glfwTerminate();hwnd=0; -} - -void SMELT_IMPL::smMainLoop() -{ - if(!hwnd)return smLog("%s:" SLINE ": Error: SMELT is not initialized.\n",SYS_GLFW_SRCFN); - if(!pUpdateFunc&&!updateHandler) return smLog("%s:" SLINE ": UpdateFunc is not defined.\n",SYS_GLFW_SRCFN); - Active=true; - for(;;) - { - glfwPollEvents(); - bool loopcont=true; - loopcont=procGLFWEvent(); - if(!loopcont)break; - if(Active||noSuspend) - { - DWORD ticks; - do{ticks=DWORD(glfwGetTime()*1000.);dt=ticks-t0;}while(dt<1); - if(dt>=fixDelta) - { - timeDelta=dt/1000.; - if(timeDelta>0.2)timeDelta=fixDelta?fixDelta/1000.:.01; - ++fcnt;updateFPSDelay+=timeDelta;t0=ticks;timeS+=timeDelta; - if(updateFPSDelay>1){fps=fcnt/updateFPSDelay;updateFPSDelay=.0;fcnt=0;} - if(pUpdateFunc){if(pUpdateFunc())break;} - if(updateHandler){if(updateHandler->handlerFunc())break;} - for(int i=1;i<=255;++i)keylst[i]=((keyz[i]&4)!=0); - clearQueue(); - } - else - if(fixDelta&&dt+3Active)pSM->focusChange(true);} - } -} -void SMELT_IMPL::smLogFile(const char* path) -{ - strcpy(logFile,path); - FILE *tf=fopen(logFile,"w"); - if(!tf)*logFile=0;else fclose(tf); -} -void SMELT_IMPL::smLog(const char* format,...) -{ - va_list ap; - va_start(ap,format);vfprintf(stderr,format,ap);va_end(ap); - FILE *logf=fopen(logFile,"a");if(!logf)return; - va_start(ap,format);vfprintf(logf,format,ap);va_end(ap); - fclose(logf); -} -void SMELT_IMPL::smScreenShot(const char* path) -{ - if(pOpenGLDevice) - { - //glFinish(); - //glReadPixels(0,0,screen->w,screen->h,GL_RGB,GL_UNSIGNED_BYTE,surface->pixels); - } -} -void SMELT_IMPL::smSetFPS(int fps) -{ - vsync=(fps==FPS_VSYNC); - if(pOpenGLDevice)glfwSwapInterval(vsync?1:0); - if(fps>0)fixDelta=1000./fps;else fixDelta=0; -} -float SMELT_IMPL::smGetFPS(){return fps;} -float SMELT_IMPL::smGetDelta(){return timeDelta;} -float SMELT_IMPL::smGetTime(){return timeS;} - -SMELT_IMPL::SMELT_IMPL() -{ - hwnd=NULL;Active=false;memset(curError,0,sizeof(curError)); - pUpdateFunc=pUnFocFunc=pFocFunc=pQuitFunc=NULL; - updateHandler=unFocHandler=focHandler=quitHandler=NULL; - Icon=NULL;strcpy(winTitle,"untitled");scrw=dispw=800;scrh=disph=600; - windowed=vsync=false;memset(logFile,0,sizeof(logFile)); - limfps=0;hideMouse=true;noSuspend=false; - pOpenGLDevice=NULL;targets=NULL;curTarget=NULL; - textures=NULL;vertexArray=NULL;vertexBuf=NULL;indexBuf=NULL;primTex=0; - pOpenALDevice=NULL;mute=false;inpQueue=NULL;posz=0;posx=posy=.0; - mouseOver=true;captured=false;keymods=0;zbufenabled=false; - timeDelta=updateFPSDelay=fps=.0;fcnt=dt=fixDelta=0; -} -void SMELT_IMPL::focusChange(bool actif) -{ - Active=actif; - if(actif){pFocFunc?pFocFunc():0;focHandler?focHandler->handlerFunc():0;} - else {pUnFocFunc?pUnFocFunc():0;unFocHandler?unFocHandler->handlerFunc():0;}; -} -bool SMELT_IMPL::procGLFWEvent() -{ - if(glfwWindowShouldClose((GLFWwindow*)hwnd)) - { - bool accepted=true; - if(pSM->pQuitFunc&&pSM->pQuitFunc())accepted=false; - if(pSM->quitHandler&&quitHandler->handlerFunc())accepted=false; - if(accepted)return false; - } - return true; -} -void glfwErrorHandler(int err,const char* desc) -{ - strcpy(lasterr,desc); -} -void glfwFocChangeHandler(GLFWwindow*,int foc) -{ - pSM->focusChange(foc); -} -void glfwCursorEnterHandler(GLFWwindow*,int ent) -{ - pSM->mouseOver=ent; -} -void glfwKBEventHandler(GLFWwindow* window,int key,int scancode,int action,int mods) -{ - if(action==GLFW_RELEASE) - { - pSM->keymods=mods; - pSM->buildEvent(INPUT_KEYUP,key,0,0,-1,-1); - } - else - { - pSM->keymods=mods; - if((pSM->keymods&GLFW_MOD_ALT)&&((key==GLFW_KEY_ENTER)||(key==GLFW_KEY_KP_ENTER))) - pSM->smVidMode(pSM->scrw,pSM->scrh,!pSM->windowed); - pSM->buildEvent(INPUT_KEYDOWN,key,0,0,-1,-1); - } -} -void glfwMouseButtonHandler(GLFWwindow* w,int btn,int action,int mods) -{ - double x,y;glfwGetCursorPos(w,&x,&y); - if(action==GLFW_PRESS) - { - if(btn==GLFW_MOUSE_BUTTON_LEFT) - pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_LBUTTON,0,0,x,y); - if(btn==GLFW_MOUSE_BUTTON_RIGHT) - pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_RBUTTON,0,0,x,y); - if(btn==GLFW_MOUSE_BUTTON_MIDDLE) - pSM->buildEvent(INPUT_MBUTTONDOWN,SMK_MBUTTON,0,0,x,y); - } - else - { - if(btn==GLFW_MOUSE_BUTTON_LEFT) - pSM->buildEvent(INPUT_MBUTTONUP,SMK_LBUTTON,0,0,x,y); - if(btn==GLFW_MOUSE_BUTTON_RIGHT) - pSM->buildEvent(INPUT_MBUTTONUP,SMK_RBUTTON,0,0,x,y); - if(btn==GLFW_MOUSE_BUTTON_MIDDLE) - pSM->buildEvent(INPUT_MBUTTONUP,SMK_MBUTTON,0,0,x,y); - } -} -void glfwMouseMotionHandler(GLFWwindow*,double x,double y) -{ - pSM->buildEvent(INPUT_MOUSEMOVE,0,0,0,x,y); -} -void glfwMouseWheelHandler(GLFWwindow* w,double x,double y) -{ - double cx,cy;glfwGetCursorPos(w,&cx,&cy); - if(y>0)pSM->buildEvent(INPUT_MOUSEWHEEL,1,0,0,cx,cy); - if(y<0)pSM->buildEvent(INPUT_MOUSEWHEEL,-1,0,0,cx,cy); -} -- cgit v1.2.3