diff options
Diffstat (limited to 'src/engine/client/graphics.cpp')
| -rw-r--r-- | src/engine/client/graphics.cpp | 202 |
1 files changed, 131 insertions, 71 deletions
diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp index 641f9dfb..2111703e 100644 --- a/src/engine/client/graphics.cpp +++ b/src/engine/client/graphics.cpp @@ -2,21 +2,11 @@ /* If you are missing that file, acquire a complete release at teeworlds.com. */ #include <base/detect.h> +#include <base/math.h> +#include <base/tl/threading.h> #include "SDL.h" - -#ifdef CONF_FAMILY_WINDOWS - #define WIN32_LEAN_AND_MEAN - #include <windows.h> -#endif - -#ifdef CONF_PLATFORM_MACOSX - #include <OpenGL/gl.h> - #include <OpenGL/glu.h> -#else - #include <GL/gl.h> - #include <GL/glu.h> -#endif +#include "SDL_opengl.h" #include <base/system.h> #include <engine/external/pnglite/pnglite.h> @@ -31,13 +21,6 @@ #include "graphics.h" -// compressed textures -#define GL_COMPRESSED_RGB_ARB 0x84ED -#define GL_COMPRESSED_RGBA_ARB 0x84EE -#define GL_COMPRESSED_ALPHA_ARB 0x84E9 - -#define TEXTURE_MAX_ANISOTROPY_EXT 0x84FE - static CVideoMode g_aFakeModes[] = { {320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8}, @@ -119,12 +102,39 @@ void CGraphics_OpenGL::Rotate4(const CPoint &rCenter, CVertex *pPoints) } } -unsigned char CGraphics_OpenGL::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset) +unsigned char CGraphics_OpenGL::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp) +{ + int Value = 0; + for(int x = 0; x < ScaleW; x++) + for(int y = 0; y < ScaleH; y++) + Value += pData[((v+y)*w+(u+x))*Bpp+Offset]; + return Value/(ScaleW*ScaleH); +} + +unsigned char *CGraphics_OpenGL::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData) { - return (pData[(v*w+u)*4+Offset]+ - pData[(v*w+u+1)*4+Offset]+ - pData[((v+1)*w+u)*4+Offset]+ - pData[((v+1)*w+u+1)*4+Offset])/4; + unsigned char *pTmpData; + int ScaleW = Width/NewWidth; + int ScaleH = Height/NewHeight; + + int Bpp = 3; + if(Format == CImageInfo::FORMAT_RGBA) + Bpp = 4; + + pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1); + + int c = 0; + for(int y = 0; y < NewHeight; y++) + for(int x = 0; x < NewWidth; x++, c++) + { + pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp); + pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp); + pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp); + if(Bpp == 4) + pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp); + } + + return pTmpData; } CGraphics_OpenGL::CGraphics_OpenGL() @@ -151,7 +161,16 @@ CGraphics_OpenGL::CGraphics_OpenGL() void CGraphics_OpenGL::ClipEnable(int x, int y, int w, int h) { - //if(no_gfx) return; + if(x < 0) + w += x; + if(y < 0) + h += y; + + x = clamp(x, 0, ScreenWidth()); + y = clamp(y, 0, ScreenHeight()); + w = clamp(w, 0, ScreenWidth()-x); + h = clamp(h, 0, ScreenHeight()-y); + glScissor(x, ScreenHeight()-(y+h), w, h); glEnable(GL_SCISSOR_TEST); } @@ -179,6 +198,18 @@ void CGraphics_OpenGL::BlendAdditive() glBlendFunc(GL_SRC_ALPHA, GL_ONE); } +void CGraphics_OpenGL::WrapNormal() +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); +} + +void CGraphics_OpenGL::WrapClamp() +{ + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +} + int CGraphics_OpenGL::MemoryUsage() const { return m_TextureMemoryUsage; @@ -205,21 +236,21 @@ void CGraphics_OpenGL::GetScreen(float *pTopLeftX, float *pTopLeftY, float *pBot void CGraphics_OpenGL::LinesBegin() { - dbg_assert(m_Drawing == 0, "called begin twice"); + dbg_assert(m_Drawing == 0, "called Graphics()->LinesBegin twice"); m_Drawing = DRAWING_LINES; SetColor(1,1,1,1); } void CGraphics_OpenGL::LinesEnd() { - dbg_assert(m_Drawing == DRAWING_LINES, "called end without begin"); + dbg_assert(m_Drawing == DRAWING_LINES, "called Graphics()->LinesEnd without begin"); Flush(); m_Drawing = 0; } void CGraphics_OpenGL::LinesDraw(const CLineItem *pArray, int Num) { - dbg_assert(m_Drawing == DRAWING_LINES, "called draw without begin"); + dbg_assert(m_Drawing == DRAWING_LINES, "called Graphics()->LinesDraw without begin"); for(int i = 0; i < Num; ++i) { @@ -252,6 +283,18 @@ int CGraphics_OpenGL::UnloadTexture(int Index) return 0; } +int CGraphics_OpenGL::LoadTextureRawSub(int TextureID, int x, int y, int Width, int Height, int Format, const void *pData) +{ + int Oglformat = GL_RGBA; + if(Format == CImageInfo::FORMAT_RGB) + Oglformat = GL_RGB; + else if(Format == CImageInfo::FORMAT_ALPHA) + Oglformat = GL_ALPHA; + + glBindTexture(GL_TEXTURE_2D, m_aTextures[TextureID].m_Tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pData); + return 0; +} int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags) { @@ -272,28 +315,23 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo m_aTextures[Tex].m_Next = -1; // resample if needed - if(!(Flags&TEXLOAD_NORESAMPLE) && g_Config.m_GfxTextureQuality==0) + if(!(Flags&TEXLOAD_NORESAMPLE) && (Format == CImageInfo::FORMAT_RGBA || Format == CImageInfo::FORMAT_RGB)) { - if(Width > 16 && Height > 16 && Format == CImageInfo::FORMAT_RGBA) + if(Width > GL_MAX_TEXTURE_SIZE || Height > GL_MAX_TEXTURE_SIZE) { - unsigned char *pTmpData; - int c = 0; - int x, y; - - pTmpData = (unsigned char *)mem_alloc(Width*Height*4, 1); - - Width/=2; - Height/=2; - - for(y = 0; y < Height; y++) - for(x = 0; x < Width; x++, c++) - { - pTmpData[c*4] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 0); - pTmpData[c*4+1] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 1); - pTmpData[c*4+2] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 2); - pTmpData[c*4+3] = Sample(Width*2, Height*2, pTexData, x*2,y*2, 3); - } + int NewWidth = min(Width, GL_MAX_TEXTURE_SIZE); + int NewHeight = min(Height, GL_MAX_TEXTURE_SIZE); + pTmpData = Rescale(Width, Height, NewWidth, NewHeight, Format, pTexData); pTexData = pTmpData; + Width = NewWidth; + Height = NewHeight; + } + else if(Width > 16 && Height > 16 && g_Config.m_GfxTextureQuality == 0) + { + pTmpData = Rescale(Width, Height, Width/2, Height/2, Format, pTexData); + pTexData = pTmpData; + Width /= 2; + Height /= 2; } } @@ -323,9 +361,19 @@ int CGraphics_OpenGL::LoadTextureRaw(int Width, int Height, int Format, const vo glGenTextures(1, &m_aTextures[Tex].m_Tex); glBindTexture(GL_TEXTURE_2D, m_aTextures[Tex].m_Tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); + + if(Flags&TEXLOAD_NOMIPMAPS) + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pData); + } + else + { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); + gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData); + } // calculate memory usage { @@ -368,6 +416,8 @@ int CGraphics_OpenGL::LoadTexture(const char *pFilename, int StorageType, int St ID = LoadTextureRaw(Img.m_Width, Img.m_Height, Img.m_Format, Img.m_pData, StoreFormat, Flags); mem_free(Img.m_pData); + if(ID != m_InvalidTexture && g_Config.m_Debug) + dbg_msg("graphics/texture", "loaded %s", pFilename); return ID; } @@ -488,7 +538,7 @@ void CGraphics_OpenGL::Clear(float r, float g, float b) void CGraphics_OpenGL::QuadsBegin() { - dbg_assert(m_Drawing == 0, "called quads_begin twice"); + dbg_assert(m_Drawing == 0, "called Graphics()->QuadsBegin twice"); m_Drawing = DRAWING_QUADS; QuadsSetSubset(0,0,1,1); @@ -498,7 +548,7 @@ void CGraphics_OpenGL::QuadsBegin() void CGraphics_OpenGL::QuadsEnd() { - dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_end without begin"); + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsEnd without begin"); Flush(); m_Drawing = 0; } @@ -511,7 +561,7 @@ void CGraphics_OpenGL::QuadsSetRotation(float Angle) void CGraphics_OpenGL::SetColorVertex(const CColorVertex *pArray, int Num) { - dbg_assert(m_Drawing != 0, "called gfx_quads_setcolorvertex without begin"); + dbg_assert(m_Drawing != 0, "called Graphics()->SetColorVertex without begin"); for(int i = 0; i < Num; ++i) { @@ -524,7 +574,7 @@ void CGraphics_OpenGL::SetColorVertex(const CColorVertex *pArray, int Num) void CGraphics_OpenGL::SetColor(float r, float g, float b, float a) { - dbg_assert(m_Drawing != 0, "called gfx_quads_setcolor without begin"); + dbg_assert(m_Drawing != 0, "called Graphics()->SetColor without begin"); CColorVertex Array[4] = { CColorVertex(0, r, g, b, a), CColorVertex(1, r, g, b, a), @@ -570,7 +620,7 @@ void CGraphics_OpenGL::QuadsDrawTL(const CQuadItem *pArray, int Num) CPoint Center; Center.z = 0; - dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw without begin"); + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawTL without begin"); for(int i = 0; i < Num; ++i) { @@ -608,7 +658,7 @@ void CGraphics_OpenGL::QuadsDrawTL(const CQuadItem *pArray, int Num) void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num) { - dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw_freeform without begin"); + dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsDrawFreeform without begin"); for(int i = 0; i < Num; ++i) { @@ -670,7 +720,7 @@ void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, QuadsEnd(); } -bool CGraphics_OpenGL::Init() +int CGraphics_OpenGL::Init() { m_pStorage = Kernel()->RequestInterface<IStorage>(); m_pConsole = Kernel()->RequestInterface<IConsole>(); @@ -706,24 +756,19 @@ bool CGraphics_OpenGL::Init() m_InvalidTexture = LoadTextureRaw(4,4,CImageInfo::FORMAT_RGBA,aNullTextureData,CImageInfo::FORMAT_RGBA,TEXLOAD_NORESAMPLE); - return true; + return 0; } int CGraphics_SDL::TryInit() { - const SDL_VideoInfo *pInfo; - int Flags = SDL_OPENGL; - m_ScreenWidth = g_Config.m_GfxScreenWidth; m_ScreenHeight = g_Config.m_GfxScreenHeight; - pInfo = SDL_GetVideoInfo(); - SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); + const SDL_VideoInfo *pInfo = SDL_GetVideoInfo(); + SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows // set flags - Flags = SDL_OPENGL; - Flags |= SDL_GL_DOUBLEBUFFER; - Flags |= SDL_HWPALETTE; + int Flags = SDL_OPENGL; if(g_Config.m_DbgResizable) Flags |= SDL_RESIZABLE; @@ -809,7 +854,7 @@ CGraphics_SDL::CGraphics_SDL() m_pScreenSurface = 0; } -bool CGraphics_SDL::Init() +int CGraphics_SDL::Init() { { int Systems = SDL_INIT_VIDEO; @@ -823,7 +868,7 @@ bool CGraphics_SDL::Init() if(SDL_Init(Systems) < 0) { dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError()); - return true; + return -1; } } @@ -835,14 +880,14 @@ bool CGraphics_SDL::Init() #endif if(InitWindow() != 0) - return true; + return -1; SDL_ShowCursor(0); CGraphics_OpenGL::Init(); MapScreen(0,0,g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight); - return false; + return 0; } void CGraphics_SDL::Shutdown() @@ -940,4 +985,19 @@ int CGraphics_SDL::GetVideoModes(CVideoMode *pModes, int MaxModes) return NumModes; } +// syncronization +void CGraphics_SDL::InsertSignal(semaphore *pSemaphore) +{ + pSemaphore->signal(); +} + +bool CGraphics_SDL::IsIdle() +{ + return true; +} + +void CGraphics_SDL::WaitForIdle() +{ +} + extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); } |