diff options
author | Eugene Sandulenko | 2010-07-29 19:53:02 +0000 |
---|---|---|
committer | Eugene Sandulenko | 2010-10-12 21:38:20 +0000 |
commit | a683a420a9e43705c972b5e74d55e319729e1a81 (patch) | |
tree | bde6e4abd417bdfaec120aa951da9a19be36b654 /engines/sword25/util/glsprites/internal | |
parent | 7723d91c957d07205c51be32498d45cd0a78568f (diff) | |
download | scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.gz scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.tar.bz2 scummvm-rg350-a683a420a9e43705c972b5e74d55e319729e1a81.zip |
SWORD25: Importing original sources
svn-id: r53171
Diffstat (limited to 'engines/sword25/util/glsprites/internal')
-rwxr-xr-x | engines/sword25/util/glsprites/internal/core.c | 212 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/core.h | 40 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/glinclude.h | 36 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/glswindow.c | 449 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/glswindow.h | 42 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite.c | 156 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite.h | 40 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_pow2.c | 170 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_pow2.h | 27 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_rectangle.c | 164 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_rectangle.h | 27 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_tiled.c | 370 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/sprite_tiled.h | 41 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/util.c | 77 | ||||
-rwxr-xr-x | engines/sword25/util/glsprites/internal/util.h | 42 |
15 files changed, 1893 insertions, 0 deletions
diff --git a/engines/sword25/util/glsprites/internal/core.c b/engines/sword25/util/glsprites/internal/core.c new file mode 100755 index 0000000000..deb1dcbd3d --- /dev/null +++ b/engines/sword25/util/glsprites/internal/core.c @@ -0,0 +1,212 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + +#include "glinclude.h" +#include "core.h" +#include "glswindow.h" + + +/* -------------------------------------------------------------------------- + GLOBALS + -------------------------------------------------------------------------- */ + +GLS_OGLCaps GLS_TheOGLCaps; +static GLS_Window * window = 0; +static GLS_Bool vsyncActive = GLS_False; +typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int ); +static PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0; + + +/* -------------------------------------------------------------------------- */ + +void InitGL(GLS_UInt32 width, GLS_UInt32 height) +{ + if (height == 0) height = 1; + + glViewport(0, 0, width, height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, width, height, 0, 1, -1); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glShadeModel(GL_SMOOTH); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); +} + +/* -------------------------------------------------------------------------- */ + +void InitGLCaps(GLS_OGLCaps * OGLCaps) +{ + if (strstr(glGetString(GL_EXTENSIONS), "GL_ARB_texture_rectangle") != 0 || + strstr(glGetString(GL_EXTENSIONS), "GL_EXT_texture_rectangle") != 0 || + strstr(glGetString(GL_EXTENSIONS), "GL_NV_texture_rectangle") != 0) + { + OGLCaps->textureRectanglesSupported = GLS_True; + glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &(OGLCaps->maxTextureRectangleSize)); + } + else + OGLCaps->textureRectanglesSupported = GLS_False; + + if (strstr(glGetString(GL_EXTENSIONS), "WGL_EXT_swap_control") != 0) + { + wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC) wglGetProcAddress("wglSwapIntervalEXT"); + } + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &(OGLCaps->maxTextureSize)); +} + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_Init(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, const char * windowTitle, GLS_Bool allowCloseWindow) +{ + GLS_Result Result; + + Result = GLS_CreateGLWindow(width, height, fullscreen, windowTitle, allowCloseWindow, &window); + if (Result != GLS_OK) return Result; + InitGL(width, height); + InitGLCaps(&GLS_TheOGLCaps); + + return GLS_OK; +} + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_InitExternalWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, void * windowHandle) +{ + GLS_Result Result; + + Result = GLS_CreateGLExternalWindow(width, height, fullscreen, windowHandle, &window); + if (Result != GLS_OK) return Result; + InitGL(width, height); + InitGLCaps(&GLS_TheOGLCaps); + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_Quit() +{ + if (window) GLS_CloseGLWindow(window); + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_StartFrame() +{ + glClear(GL_COLOR_BUFFER_BIT); + return GLS_ProcessWindowMessages(window); +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_EndFrame() +{ + if (GLS_WindowFlip(window)) + return GLS_OK; + else + return GLS_COULD_NOT_FLIP; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_GetWindowHandle(void ** pWindowHandle) +{ + if (window) + { + *pWindowHandle = window->hwnd; + return GLS_OK; + } + else + { + return GLS_NO_WINDOW; + } +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_SetVSync(GLS_Bool status) +{ + if (wglSwapIntervalEXT) + { + if (wglSwapIntervalEXT(status ? 1 : 0)) + { + vsyncActive = status; + return GLS_OK; + } + else + return GLS_OPENGL_ERROR; + } + else + return GLS_NO_DRIVER_SUPPORT_FOR_VSYNC; +} + +GLS_Result GLS_IsVsync(GLS_Bool * pStatus) +{ + if (wglSwapIntervalEXT) + { + *pStatus = vsyncActive; + return GLS_OK; + } + else + return GLS_NO_DRIVER_SUPPORT_FOR_VSYNC; +} + + +/* -------------------------------------------------------------------------- */ + +#define GLRS(ERR) case GLS_##ERR: return #ERR; +const char * GLS_ResultString(GLS_Result ResultCode) +{ + switch (ResultCode) + { + GLRS(OK) + GLRS(OUT_OF_MEMORY) + GLRS(WINDOW_CREATION_FAILED) + GLRS(WINDOW_PREPARATION_FAILED) + GLRS(DISPLAY_MODE_CHANGE_FAILED) + GLRS(WINDOW_WAS_CLOSED) + GLRS(OPENGL_CONTEXT_CREATION_FAILED) + GLRS(COULD_NOT_FLIP) + GLRS(TEXTURE_CREATION_FAILED) + GLRS(NO_WINDOW) + GLRS(INVALID_SPRITE_OBJECT) + GLRS(INVALID_SPRITE_DIMENSIONS) + GLRS(NO_DRIVER_SUPPORT_FOR_VSYNC) + GLRS(OPENGL_ERROR) + GLRS(INVALID_DATA_DIMENSIONS) + GLRS(INVALID_DATA_POINTER) + GLRS(INVALID_SUB_IMAGE) + default: + return "unknown result code"; + } +} +#undef GLRS diff --git a/engines/sword25/util/glsprites/internal/core.h b/engines/sword25/util/glsprites/internal/core.h new file mode 100755 index 0000000000..9baa3e1c98 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/core.h @@ -0,0 +1,40 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_CORE_H +#define GLS_CORE_H + +#include "../glsprites.h" + +/* GL_ARB_texture_rectangle / GL_EXT_texture_rectangle / GL_NV_texture_rectangle */ +#define GL_TEXTURE_RECTANGLE_ARB 0x84F5 +#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6 +#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7 +#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8 + +typedef struct +{ + GLS_UInt32 maxTextureSize; + GLS_Bool textureRectanglesSupported; + GLS_UInt32 maxTextureRectangleSize; +} GLS_OGLCaps; + +extern GLS_OGLCaps GLS_TheOGLCaps; + +#endif diff --git a/engines/sword25/util/glsprites/internal/glinclude.h b/engines/sword25/util/glsprites/internal/glinclude.h new file mode 100755 index 0000000000..0ac11cccb2 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/glinclude.h @@ -0,0 +1,36 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_GL_INCLUDE_H +#define GLS_GL_INCLUDE_H + +/* This header is included by all GLS files that need OpenGL. */ + +#ifdef WIN32 + #define WIN32_LEAN_AND_MEAN + #include <windows.h> +#endif + +#include <GL/gl.h> + +#ifndef GL_CLAMP_TO_EDGE + #define GL_CLAMP_TO_EDGE 0x812F +#endif + +#endif diff --git a/engines/sword25/util/glsprites/internal/glswindow.c b/engines/sword25/util/glsprites/internal/glswindow.c new file mode 100755 index 0000000000..dcb8424d73 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/glswindow.c @@ -0,0 +1,449 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <malloc.h> + +#include "glswindow.h" + + +/* -------------------------------------------------------------------------- + CONSTANTS + -------------------------------------------------------------------------- */ + +static const char * WINDOW_CLASSNAME = "GLsprites class"; +static const GLS_UInt32 BITS_PER_PIXEL = 32; + + +/* -------------------------------------------------------------------------- */ + +static LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_SYSCOMMAND: + { + switch (wParam) + { + case SC_SCREENSAVE: + case SC_MONITORPOWER: + return 0; + } + break; + } + + case WM_CLOSE: + { + if (GetWindowLong(hWnd, GWL_USERDATA)) PostQuitMessage(0); + return 0; + } + } + + return DefWindowProc(hWnd,uMsg,wParam,lParam); +} + +/* -------------------------------------------------------------------------- */ + +static GLS_Bool RegisterWindowClass() +{ + WNDCLASS wc; + + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(NULL); + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = "OpenGL"; + + if (RegisterClass(&wc)) + return GLS_True; + else + return GLS_False; +} + +/* -------------------------------------------------------------------------- */ + +static void CenterWindow(RECT * pWR, int * pX, int * pY) +{ + int screenX, screenY; + + screenX = GetSystemMetrics(SM_CXSCREEN); + screenY = GetSystemMetrics(SM_CYSCREEN); + + if (screenX == 0 || screenY == 0) + { + *pX = 0; + *pY = 0; + } + else + { + *pX = (screenX - (pWR->right - pWR->left)) / 2; + *pY = (screenY - (pWR->bottom - pWR->top)) / 2; + } +} + +/* -------------------------------------------------------------------------- */ + +static GLS_Bool CreateTheWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, const char * windowTitle, GLS_Bool allowCloseWindow, HWND * pHwnd) +{ + DWORD style; + DWORD exStyle; + RECT windowRect; + int x, y; + + if (fullscreen) + { + exStyle = WS_EX_APPWINDOW; + style = WS_POPUP; + } + else + { + exStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; + style = WS_CAPTION; + if (allowCloseWindow) style |= WS_SYSMENU; + } + + windowRect.left = 0; + windowRect.right = width; + windowRect.top= 0; + windowRect.bottom = height; + if (!AdjustWindowRectEx(&windowRect, style, FALSE, exStyle)) return GLS_False; + + if (fullscreen) + { + x = 0; + y = 0; + } + else + CenterWindow(&windowRect, &x, &y); + + *pHwnd = CreateWindowEx( + exStyle, + "OpenGL", + windowTitle, + style | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE, + x, y, + windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, + NULL, + NULL, + GetModuleHandle(NULL), + NULL); + + if (!*pHwnd) return GLS_False; + + SetWindowLong(*pHwnd, GWL_USERDATA, (allowCloseWindow == GLS_True) ? 1 : 0); + + return GLS_True; +} + +/* -------------------------------------------------------------------------- */ + +static void SetWindowClientSize(HWND hwnd, int cx, int cy) +{ + HMENU hmenu = GetMenu(hwnd); + RECT rcWindow = { 0, 0, cx, cy }; + + /* + * First convert the client rectangle to a window rectangle the + * menu-wrap-agnostic way. + */ + AdjustWindowRectEx(&rcWindow, GetWindowLong(hwnd, GWL_STYLE), hmenu != NULL, GetWindowLong(hwnd, GWL_EXSTYLE)); + + /* + * If there is a menu, then check how much wrapping occurs + * when we set a window to the width specified by AdjustWindowRect + * and an infinite amount of height. An infinite height allows + * us to see every single menu wrap. + */ + if (hmenu) { + RECT rcTemp = rcWindow; + rcTemp.bottom = 0x7FFF; /* "Infinite" height */ + SendMessage(hwnd, WM_NCCALCSIZE, FALSE, (LPARAM)&rcTemp); + + /* + * Adjust our previous calculation to compensate for menu + * wrapping. + */ + rcWindow.bottom += rcTemp.top; + } + + SetWindowPos(hwnd, NULL, 0, 0, rcWindow.right - rcWindow.left, + rcWindow.bottom - rcWindow.top, SWP_NOMOVE | SWP_NOZORDER); + +} + +/* ---------------------------------------------------------------------------- */ + +static GLS_Bool PrepareWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, HWND hwnd) +{ + if (fullscreen) + { + SetWindowLong(hwnd, GWL_STYLE, WS_POPUP); + SetWindowLong(hwnd, GWL_EXSTYLE, WS_EX_TOPMOST); + SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOSIZE); + } + + SetWindowClientSize(hwnd, width, height); + ShowWindow(hwnd, SW_SHOW); + + return GLS_True; +} + +/* -------------------------------------------------------------------------- */ + +static GLS_Bool ChangeDisplayMode(GLS_UInt32 width, GLS_UInt32 height) +{ + DEVMODE dmScreenSettings; + memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); + dmScreenSettings.dmSize = sizeof(dmScreenSettings); + dmScreenSettings.dmPelsWidth = width; + dmScreenSettings.dmPelsHeight = height; + dmScreenSettings.dmBitsPerPel = BITS_PER_PIXEL; + dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) + return GLS_True; + else + return GLS_False; +} + +/* -------------------------------------------------------------------------- */ + +static GLS_Bool CreateOpenGLContext(HWND hwnd, HGLRC * pHrc) +{ + HDC hdc; + int pixelformat; + PIXELFORMATDESCRIPTOR pfd = + { + sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | + PFD_SUPPORT_OPENGL | + PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + BITS_PER_PIXEL, + 0, 0, 0, 0, 0, 0, + 0, + 0, + 0, + 0, 0, 0, 0, + 0, + 0, + 0, + PFD_MAIN_PLANE, + 0, + 0, 0, 0 + }; + + hdc = GetDC(hwnd); + if (!hdc) return GLS_False; + + pixelformat = ChoosePixelFormat(hdc, &pfd); + if (!pixelformat) + { + ReleaseDC(hwnd, hdc); + return GLS_False; + } + + if (!SetPixelFormat(hdc, pixelformat, &pfd)) + { + ReleaseDC(hwnd, hdc); + return GLS_False; + } + + *pHrc = wglCreateContext(hdc); + if (!*pHrc) + { + ReleaseDC(hwnd, hdc); + return GLS_False; + } + + if (!wglMakeCurrent(hdc, *pHrc)) + { + wglDeleteContext(*pHrc); + *pHrc = 0; + ReleaseDC(hwnd, hdc); + return GLS_False; + } + + ReleaseDC(hwnd, hdc); + return GLS_True; +} + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_CreateGLWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, const char * windowTitle, GLS_Bool allowCloseWindow, GLS_Window ** pWindow) +{ + *pWindow = (GLS_Window *) malloc(sizeof(GLS_Window)); + if (!*pWindow) return GLS_OUT_OF_MEMORY; + + (*pWindow)->hrc = 0; + (*pWindow)->hwnd = 0; + (*pWindow)->fullscreen = GLS_False; + (*pWindow)->ownHwnd = GLS_True; + + if (!RegisterWindowClass()) + { + GLS_CloseGLWindow(*pWindow); + return GLS_WINDOW_CREATION_FAILED; + } + + if (!CreateTheWindow(width, height, fullscreen, windowTitle, allowCloseWindow, &((*pWindow)->hwnd))) + { + GLS_CloseGLWindow(*pWindow); + return GLS_WINDOW_CREATION_FAILED; + } + + if (fullscreen) + { + if (!ChangeDisplayMode(width, height)) + { + return GLS_DISPLAY_MODE_CHANGE_FAILED; + } + (*pWindow)->fullscreen = GLS_True; + } + + if (!CreateOpenGLContext((*pWindow)->hwnd, &((*pWindow)->hrc))) + { + GLS_CloseGLWindow(*pWindow); + return GLS_OPENGL_CONTEXT_CREATION_FAILED; + } + + return GLS_OK; +} + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_CreateGLExternalWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, void * windowHandle, GLS_Window ** pWindow) +{ + *pWindow = (GLS_Window *) malloc(sizeof(GLS_Window)); + if (!*pWindow) return GLS_OUT_OF_MEMORY; + + (*pWindow)->hrc = 0; + (*pWindow)->hwnd = windowHandle; + (*pWindow)->fullscreen = GLS_False; + (*pWindow)->ownHwnd = GLS_False; + + if (!PrepareWindow(width, height, fullscreen, (*pWindow)->hwnd)) + { + GLS_CloseGLWindow(*pWindow); + return GLS_WINDOW_PREPARATION_FAILED; + } + + if (fullscreen) + { + if (!ChangeDisplayMode(width, height)) + { + return GLS_DISPLAY_MODE_CHANGE_FAILED; + } + (*pWindow)->fullscreen = GLS_True; + } + + if (!CreateOpenGLContext((*pWindow)->hwnd, &((*pWindow)->hrc))) + { + GLS_CloseGLWindow(*pWindow); + return GLS_OPENGL_CONTEXT_CREATION_FAILED; + } + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_CloseGLWindow(GLS_Window * window) +{ + if (window) + { + if (window->hrc) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(window->hrc); + } + + if (window->fullscreen) ChangeDisplaySettings(NULL, 0); + if (window->ownHwnd) + { + if (window->hwnd) DestroyWindow(window->hwnd); + UnregisterClass(WINDOW_CLASSNAME, GetModuleHandle(NULL)); + } + + free(window); + } + + return GLS_True; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_ProcessWindowMessages(GLS_Window * window) +{ + MSG msg; + GLS_Result Result = GLS_OK; + + if (window->ownHwnd) + { + while (PeekMessage(&msg, window->hwnd, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + { + Result = GLS_WINDOW_WAS_CLOSED; + } + + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + return Result; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_WindowFlip(GLS_Window * window) +{ + HDC hdc; + + hdc = GetDC(window->hwnd); + if (!hdc) return GLS_False; + + if (SwapBuffers(hdc)) + { + ReleaseDC(window->hwnd, hdc); + return GLS_True; + } + else + { + ReleaseDC(window->hwnd, hdc); + return GLS_False; + } +} diff --git a/engines/sword25/util/glsprites/internal/glswindow.h b/engines/sword25/util/glsprites/internal/glswindow.h new file mode 100755 index 0000000000..1311513e45 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/glswindow.h @@ -0,0 +1,42 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_WINDOW_H +#define GLS_WINDOW_H + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include "../glsprites.h" + +typedef struct +{ + HWND hwnd; + HGLRC hrc; + GLS_Bool fullscreen; + GLS_Bool ownHwnd; +} GLS_Window; + +GLS_Result GLS_CreateGLWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, const char * windowTitle, GLS_Bool allowCloseWindow, GLS_Window ** pWindow); +GLS_Result GLS_CreateGLExternalWindow(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool fullscreen, void * windowHandle, GLS_Window ** pWindow); +GLS_Result GLS_CloseGLWindow(GLS_Window * window); +GLS_Result GLS_ProcessWindowMessages(GLS_Window * window); +GLS_Result GLS_WindowFlip(GLS_Window * window); + +#endif diff --git a/engines/sword25/util/glsprites/internal/sprite.c b/engines/sword25/util/glsprites/internal/sprite.c new file mode 100755 index 0000000000..261ce207e6 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite.c @@ -0,0 +1,156 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + + +#include <malloc.h> + +#include "glinclude.h" +#include "util.h" +#include "core.h" +#include "sprite.h" +#include "sprite_rectangle.h" +#include "sprite_pow2.h" +#include "sprite_tiled.h" + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + /* These first three members are present at the start of each sprite type. + Therefore it is safe to cast all sprite to this. */ + GLS_spriteFunctionTable * functionTable; + GLS_UInt32 width; + GLS_UInt32 height; +} spriteBase; + +/* -------------------------------------------------------------------------- */ + +#define MAX_WASTED_TEXTURE_MEMORY_PERCENT 30 + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_NewSprite(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite) +{ + //* The sprite needs to be at least 1x1 pixel in size */ + if (width == 0 || height == 0) return GLS_INVALID_SPRITE_DIMENSIONS; + + /* If both dimensions are powers of 2 a power of 2 texture will be used for the sprite */ + if (GLS_IsPowerOf2(width) && GLS_IsPowerOf2(height)) return GLS_NewSpritePow2(width, height, useAlphachannel, data, pSprite); + + /* Use TEXTURE_RECTANGLE_ARB for non power of 2 dimensions whenever possible */ + if (GLS_TheOGLCaps.textureRectanglesSupported && + GLS_TheOGLCaps.maxTextureRectangleSize >= width && + GLS_TheOGLCaps.maxTextureRectangleSize >= height) + return GLS_NewSpriteRectangle(width, height, useAlphachannel, data, pSprite); + + /* Use a power of 2 texture if TEXTURE_RECTANGLE_ARB is not possible, the image is small enough and the amount of wasted texture memory + is not too big */ + if ((width <= GLS_TheOGLCaps.maxTextureSize && height <= GLS_TheOGLCaps.maxTextureSize) && + (GLS_NextPowerOf2(width) * GLS_NextPowerOf2(height) * 100) / (width * height) <= MAX_WASTED_TEXTURE_MEMORY_PERCENT) + return GLS_NewSpritePow2(width, height, useAlphachannel, data, pSprite); + + /* Otherwise use tiled power of 2 textures */ + return GLS_NewSpriteTiled(width, height, useAlphachannel, data, pSprite); +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_DeleteSprite(GLS_Sprite * sprite) +{ + /* Poor mans polymorphism. */ + spriteBase * s = (spriteBase *) sprite; + return s->functionTable->Delete(sprite); +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_Blit(GLS_Sprite * sprite, + GLS_SInt32 x, GLS_SInt32 y, + const GLS_Rect * subImage, + const GLS_Color * color, + GLS_Bool flipH, GLS_Bool flipV, + GLS_Float scaleX, GLS_Float scaleY) +{ + spriteBase * s = (spriteBase *) sprite; + GLS_Rect localSubImage; + const GLS_Rect * subImagePtr; + GLS_Result result; + + /* Check parameters for validity. */ + if (subImage && (subImage->x2 > s->width || subImage->y2 > s->height)) return GLS_INVALID_SUB_IMAGE; + + /* If no subimage was supplied, create one that covers the whole sprite. */ + if (subImage) + subImagePtr = subImage; + else + { + localSubImage.x1 = 0; + localSubImage.y1 = 0; + localSubImage.x2 = s->width; + localSubImage.y2 = s->height; + subImagePtr = &localSubImage; + } + + /* Modify the Modelview-Matrix to reflect the sprites position, flip settings, and scale. */ + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef((GLfloat) x, (GLfloat) y, 0); + if (flipH == GLS_True || flipV == GLS_True || scaleX != 1.0f || scaleY != 1.0f) + { + glScalef(scaleX * (flipH == GLS_True ? -1.0f : 1.0f), scaleY * (flipV == GLS_True ? -1.0f : 1.0f), 1.0f); + glTranslatef(flipH == GLS_True ? (subImagePtr->x2 - subImagePtr->x1) * -1.0f : 0.0f, + flipV == GLS_True ? (subImagePtr->y2 - subImagePtr->y1) * -1.0f : 0.0f, 0.0f); + } + + /* Set the color to be used. Use white if no color was provided. */ + if (color) + glColor4ub(color->r, color->g, color->b, color->a); + else + glColor4ub(255, 255, 255, 255); + + /* Display the sprite by calling the Blit() function of the specific sprite type. */ + result = s->functionTable->Blit(sprite, subImagePtr); + + /* Restore the old matrix. */ + glPopMatrix(); + + return result; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_SetSpriteData(GLS_Sprite sprite, GLS_UInt32 width, GLS_UInt32 height, const void * data, GLS_UInt32 stride) +{ + spriteBase * s = (spriteBase *) sprite; + + /* Check parameters for validity. */ + if (width == 0 || height == 0 || width > s->width || height > s->height) return GLS_INVALID_DATA_DIMENSIONS; + if (data == 0) return GLS_INVALID_DATA_POINTER; + + /* Poor mans polymorphism. */ + return s->functionTable->SetData(sprite, width, height, data, stride); +} diff --git a/engines/sword25/util/glsprites/internal/sprite.h b/engines/sword25/util/glsprites/internal/sprite.h new file mode 100755 index 0000000000..8cb7fd41e7 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite.h @@ -0,0 +1,40 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_SPRITE_H +#define GLS_SPRITE_H + +#include "../glsprites.h" + +typedef enum +{ + ST_POW2, + ST_TILED, + ST_RECTANGLE, +} GLS_spriteType; + +typedef struct +{ + GLS_spriteType type; + GLS_Result (*Delete)(GLS_Sprite *); + GLS_Result (*Blit)(GLS_Sprite *, const GLS_Rect *); + GLS_Result (*SetData)(GLS_Sprite *, GLS_UInt32, GLS_UInt32, const void *, GLS_UInt32); +} GLS_spriteFunctionTable; + +#endif diff --git a/engines/sword25/util/glsprites/internal/sprite_pow2.c b/engines/sword25/util/glsprites/internal/sprite_pow2.c new file mode 100755 index 0000000000..8b4ebe18fe --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_pow2.c @@ -0,0 +1,170 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + +#include <malloc.h> + +#include "glinclude.h" +#include "util.h" +#include "sprite.h" +#include "sprite_pow2.h" + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite *); +static GLS_Result Blit(GLS_Sprite *, const GLS_Rect *); +static GLS_Result SetData(GLS_Sprite *, GLS_UInt32, GLS_UInt32, const void *, GLS_UInt32); +static GLS_spriteFunctionTable pow2FunctionTable = { ST_POW2, Delete, Blit, SetData }; + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + /* These first three members have to be present at the start of each sprite type. */ + GLS_spriteFunctionTable * functionTable; + GLS_UInt32 width; + GLS_UInt32 height; + + GLS_UInt32 widthPow2; + GLS_UInt32 heightPow2; + GLint textureID; +} spritePow2; + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_NewSpritePow2(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite) +{ + GLS_UInt32 widthPow2 = GLS_NextPowerOf2(width); + GLS_UInt32 heightPow2 = GLS_NextPowerOf2(height); + + /* Allocate memory for sprite object */ + spritePow2 * sprite = (spritePow2 *) malloc(sizeof(spritePow2)); + if (!sprite) return GLS_OUT_OF_MEMORY; + + /* Initialize sprite object */ + sprite->functionTable = &pow2FunctionTable; + sprite->textureID = 0; + sprite->width = width; + sprite->height = height; + sprite->widthPow2 = widthPow2; + sprite->heightPow2 = heightPow2; + + /* Create OpenGL texture */ + glGenTextures(1, &(sprite->textureID)); + glBindTexture(GL_TEXTURE_2D, sprite->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, useAlphachannel ? GL_RGBA8 : GL_RGB8, widthPow2, heightPow2, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + /* Fill the texture with the supplied pixel data. + We don't use glTexImage2D for this, because the created sprite might not have power of 2 dimensions and therefore the + supplied pixeldata wouldn't cover the whole texture. */ + if (data) glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + + *pSprite = (GLS_Sprite) sprite; + + if (glGetError()) + { + Delete(*pSprite); + return GLS_TEXTURE_CREATION_FAILED; + } + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite * sprite) +{ + spritePow2 * s = (spritePow2 *) sprite; + + if (s->textureID) glDeleteTextures(1, &s->textureID); + free(s); + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Blit(GLS_Sprite * sprite, + const GLS_Rect * subImage) +{ + GLfloat width, height; + GLfloat texX1, texY1, texX2, texY2; + + spritePow2 * s = (spritePow2 *) sprite; + + width = (float) (subImage->x2 - subImage->x1); + height = (float) (subImage->y2 - subImage->y1); + + texX1 = (GLfloat) subImage->x1 / (GLfloat) s->widthPow2; + texY1 = (GLfloat) subImage->y1 / (GLfloat) s->heightPow2; + texX2 = (GLfloat) subImage->x2 / (GLfloat) s->widthPow2; + texY2 = (GLfloat) subImage->y2 / (GLfloat) s->heightPow2; + + glBindTexture(GL_TEXTURE_2D, s->textureID); + + glEnable(GL_TEXTURE_2D); + + glBegin(GL_QUADS); + glTexCoord2f(texX1, texY1); + glVertex2f(0.0f, 0.0f); + + glTexCoord2f(texX2, texY1); + glVertex2f(width, 0.0f); + + glTexCoord2f(texX2, texY2); + glVertex2f(width, height); + + glTexCoord2f(texX1, texY2); + glVertex2f(0.0f, height); + glEnd(); + + glDisable(GL_TEXTURE_2D); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result SetData(GLS_Sprite * sprite, GLS_UInt32 width, GLS_UInt32 height, const void * data, GLS_UInt32 stride) +{ + spritePow2 * s = (spritePow2 *) sprite; + + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width + stride); + + glBindTexture(GL_TEXTURE_2D, s->textureID); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + + glPopClientAttrib(); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} diff --git a/engines/sword25/util/glsprites/internal/sprite_pow2.h b/engines/sword25/util/glsprites/internal/sprite_pow2.h new file mode 100755 index 0000000000..bbce39c4dc --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_pow2.h @@ -0,0 +1,27 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_SPRITE_POW2_H +#define GLS_SPRITE_POW2_H + +#include "../glsprites.h" + +GLS_Result GLS_NewSpritePow2(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite); + +#endif diff --git a/engines/sword25/util/glsprites/internal/sprite_rectangle.c b/engines/sword25/util/glsprites/internal/sprite_rectangle.c new file mode 100755 index 0000000000..546634eaac --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_rectangle.c @@ -0,0 +1,164 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + +#include <malloc.h> + +#include "glinclude.h" +#include "core.h" +#include "sprite.h" +#include "sprite_rectangle.h" + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite *); +static GLS_Result Blit(GLS_Sprite *, const GLS_Rect *); +static GLS_Result SetData(GLS_Sprite *, GLS_UInt32, GLS_UInt32, const void *, GLS_UInt32); +static GLS_spriteFunctionTable rectangleFunctionTable = { ST_RECTANGLE, Delete, Blit, SetData }; + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + /* These first three members have to be present at the start of each sprite type. */ + GLS_spriteFunctionTable * functionTable; + GLS_UInt32 width; + GLS_UInt32 height; + + GLint textureID; +} spriteRectangle; + + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_NewSpriteRectangle(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite) +{ + /* Allocate memory for sprite object */ + spriteRectangle * sprite = (spriteRectangle *) malloc(sizeof(spriteRectangle)); + if (!sprite) return GLS_OUT_OF_MEMORY; + + /* Initialize sprite object */ + sprite->functionTable = &rectangleFunctionTable; + sprite->textureID = 0; + sprite->width = width; + sprite->height = height; + + /* Create OpenGL texture */ + glGenTextures(1, &(sprite->textureID)); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, sprite->textureID); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, useAlphachannel ? GL_RGBA8 : GL_RGB8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + + *pSprite = (GLS_Sprite) sprite; + + /* The unbind here is not really necessary but some GL drivers (e.g. GeForce 4 488 Go) screw up subsequent GL_TEXTURE_2D + render operations if a GL_TEXTURE_RECTANGLE_ARB texture is still bound. */ + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + if (glGetError()) + { + Delete(*pSprite); + return GLS_TEXTURE_CREATION_FAILED; + } + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite * sprite) +{ + spriteRectangle * s = (spriteRectangle *) sprite; + + if (s->textureID) glDeleteTextures(1, &s->textureID); + free(s); + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Blit(GLS_Sprite * sprite, + const GLS_Rect * subImage) +{ + GLfloat width; + GLfloat height; + + spriteRectangle * s = (spriteRectangle *) sprite; + + width = (float)(subImage->x2 - subImage->x1); + height = (float)(subImage->y2 - subImage->y1); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->textureID); + + glEnable(GL_TEXTURE_RECTANGLE_ARB); + + glBegin(GL_QUADS); + glTexCoord2i(subImage->x1, subImage->y1); + glVertex2f(0.0f, 0.0f); + + glTexCoord2i(subImage->x2, subImage->y1); + glVertex2f(width, 0.0f); + + glTexCoord2i(subImage->x2, subImage->y2); + glVertex2f(width, height); + + glTexCoord2i(subImage->x1, subImage->y2); + glVertex2f(0.0f, height); + glEnd(); + + /* The unbind here is not really necessary but some GL drivers (e.g. GeForce 4 488 Go) screw up subsequent GL_TEXTURE_2D + render operations if a GL_TEXTURE_RECTANGLE_ARB texture is still bound. */ + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glDisable(GL_TEXTURE_RECTANGLE_ARB); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result SetData(GLS_Sprite * sprite, GLS_UInt32 width, GLS_UInt32 height, const void * data, GLS_UInt32 stride) +{ + spriteRectangle * s = (spriteRectangle *) sprite; + + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + + glPixelStorei(GL_UNPACK_ROW_LENGTH, width + stride); + + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, s->textureID); + glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data); + + /* The unbind here is not really necessary but some GL drivers (e.g. GeForce 4 488 Go) screw up subsequent GL_TEXTURE_2D + render operations if a GL_TEXTURE_RECTANGLE_ARB texture is still bound. */ + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + + glPopClientAttrib(); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} diff --git a/engines/sword25/util/glsprites/internal/sprite_rectangle.h b/engines/sword25/util/glsprites/internal/sprite_rectangle.h new file mode 100755 index 0000000000..65bdf6a3ef --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_rectangle.h @@ -0,0 +1,27 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_SPRITE_RECTANGLE_H +#define GLS_SPRITE_RECTANGLE_H + +#include "../glsprites.h" + +GLS_Result GLS_NewSpriteRectangle(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite); + +#endif diff --git a/engines/sword25/util/glsprites/internal/sprite_tiled.c b/engines/sword25/util/glsprites/internal/sprite_tiled.c new file mode 100755 index 0000000000..82435a638e --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_tiled.c @@ -0,0 +1,370 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + +#include <malloc.h> + +#include "glinclude.h" +#include "core.h" +#include "util.h" +#include "sprite.h" +#include "sprite_tiled.h" + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite *); +static GLS_Result Blit(GLS_Sprite *, const GLS_Rect *); +static GLS_Result SetData(GLS_Sprite *, GLS_UInt32, GLS_UInt32, const void *, GLS_UInt32); +static GLS_spriteFunctionTable tiledFunctionTable = { ST_TILED, Delete, Blit, SetData }; + +/* -------------------------------------------------------------------------- */ + +#define MIN_TEXTURE_SIZE_LOG2 6 +#define MIN_TEXTURE_SIZE (1 << MIN_TEXTURE_SIZE_LOG2) + +#define MAX_POSSIBLE_TEXTURE_SIZE_LOG2 31 +#define MAX_POSSIBLE_TEXTURE_SIZE (1 << MAX_POSSIBLE_TEXTURE_SIZE_LOG2) + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + GLint textureID; + GLfloat x; + GLfloat y; + GLfloat width; + GLfloat height; +} tile; + +/* -------------------------------------------------------------------------- */ + +typedef struct +{ + /* These first three members have to be present at the start of each sprite type. */ + GLS_spriteFunctionTable * functionTable; + GLS_UInt32 width; + GLS_UInt32 height; + + GLS_UInt32 widthSubdivisionCount; + GLS_UInt32 heightSubdivisionCount; + tile tiles[1]; /* Has to be last member. */ +} spriteTiled; + +/* -------------------------------------------------------------------------- */ + +static GLS_UInt32 CalculateSubdivisions(GLS_UInt32 value, GLS_UInt32 maxTextureSize, GLS_UInt32 maxTextureSizeLog2, + GLS_UInt32 subdivisions[MAX_POSSIBLE_TEXTURE_SIZE_LOG2 + 1]) +{ + /* This function takes a value and determines how it best can be divided up into pieces of power of 2 length. + The resulting parts are at least MIN_TEXTURE_SIZE long and at most maxTextureSize long. + If we do this for both width and height of a sprite, we can determine how this sprite can be split up into + smaller power of 2 textures using a simple two dimensional loop. + + This returns the number of subdivisions as the return value. + The sizes of the different pieces are encoded in the subdivisions array. The indicies into the array determine the + power of 2 and the values in the array the number of pieces with that size. + E.g. if the array contains the value 3 at index 4 this means you have 3 pieces of size 16 (2^4 = 16). + */ + + GLS_UInt32 subdivisionCount = 0; + GLS_UInt32 maxSizeCount; + GLS_UInt32 counter = 0; + + /* First determine how many pieces of maximal size we can fill and write this into the result array. + Update the value and the subdivision count accordingly. */ + maxSizeCount = value / maxTextureSize; + subdivisions[maxTextureSizeLog2] = maxSizeCount; + subdivisionCount += maxSizeCount; + value -= maxSizeCount * maxTextureSize; + + /* The remaining value is rounded up to a multiple of the minimal texture size. */ + value = ((value + MIN_TEXTURE_SIZE - 1) / MIN_TEXTURE_SIZE) * MIN_TEXTURE_SIZE; + + /* Determine the remaining pieces by using the binary representation of the value. + If a bit is set, we need to add a piece of the according size. */ + while (value) + { + if (value & 1) + { + ++subdivisions[counter]; + ++subdivisionCount; + } + + ++counter; + value >>= 1; + } + + return subdivisionCount; +} + +/* -------------------------------------------------------------------------- */ + +GLS_Result GLS_NewSpriteTiled(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite) +{ + GLS_UInt32 maxTextureSize, maxTextureSizeLog2; + GLS_UInt32 widthSubdivisions[MAX_POSSIBLE_TEXTURE_SIZE_LOG2 + 1] = { 0 }; + GLS_UInt32 widthSubdivisionCount; + GLS_UInt32 heightSubdivisions[MAX_POSSIBLE_TEXTURE_SIZE_LOG2 + 1] = { 0 }; + GLS_UInt32 heightSubdivisionCount; + GLS_UInt32 subdivisonX, subdivisionY, pixelX = 0, pixelY = 0, i; + spriteTiled * sprite; + tile * curTile; + + /* Determine the maximal texture size to be used and make sure it is a power of two. */ + maxTextureSize = GLS_TheOGLCaps.maxTextureSize > MAX_POSSIBLE_TEXTURE_SIZE ? MAX_POSSIBLE_TEXTURE_SIZE : GLS_TheOGLCaps.maxTextureSize; + maxTextureSize = GLS_IsPowerOf2(maxTextureSize) ? maxTextureSize : GLS_NextPowerOf2(maxTextureSize >> 1); + + /* Determine the log2 of the maximal texture size. */ + maxTextureSizeLog2 = GLS_Log2(maxTextureSize); + + /* Determine the subdivisions along the width and the height. */ + widthSubdivisionCount = CalculateSubdivisions(width, maxTextureSize, maxTextureSizeLog2, widthSubdivisions); + heightSubdivisionCount = CalculateSubdivisions(height, maxTextureSize, maxTextureSizeLog2, heightSubdivisions); + + /* Allocate memory for sprite object */ + sprite = (spriteTiled *) calloc(sizeof(spriteTiled) + sizeof(tile) * (widthSubdivisionCount * heightSubdivisionCount - 1), 1); + if (!sprite) return GLS_OUT_OF_MEMORY; + + /* Initialize sprite object. */ + sprite->functionTable = &tiledFunctionTable; + sprite->width = width; + sprite->height = height; + sprite->widthSubdivisionCount = widthSubdivisionCount; + sprite->heightSubdivisionCount = heightSubdivisionCount; + + /* Create the textures. */ + curTile = &sprite->tiles[0]; + for (subdivisionY = MAX_POSSIBLE_TEXTURE_SIZE_LOG2;; --subdivisionY) + { + while (heightSubdivisions[subdivisionY]--) + { + for (subdivisonX = MAX_POSSIBLE_TEXTURE_SIZE_LOG2;; --subdivisonX) + { + for (i = 0; i < widthSubdivisions[subdivisonX]; ++i) + { + /* Initialize tile. Store as GLfloat to avoid unnecessary integer conversions when drawing. */ + curTile->x = (GLfloat) pixelX; + curTile->y = (GLfloat) pixelY; + curTile->width = (GLfloat) (1 << subdivisonX); + curTile->height = (GLfloat) (1 << subdivisionY); + + /* Create OpenGL texture */ + glGenTextures(1, &(curTile->textureID)); + glBindTexture(GL_TEXTURE_2D, curTile->textureID); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glTexImage2D(GL_TEXTURE_2D, 0, useAlphachannel ? GL_RGBA8 : GL_RGB8, 1 << subdivisonX, 1 << subdivisionY, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + + /* Advance to the next empty tile. */ + pixelX += 1 << subdivisonX; + ++curTile; + } + + /* Test for loop end. Prevents underflow of unsigned integer. */ + if (subdivisonX == 0) break; + } + + /* Enter next row. */ + pixelX = 0; + pixelY += 1 << subdivisionY; + } + + /* Test for loop end. Prevents underflow of unsigned integer. */ + if (subdivisionY == 0) break; + } + + *pSprite = (GLS_Sprite) sprite; + + /* Intialize the sprite with the supplied pixel data (if any). */ + if (data) SetData(*pSprite, width, height, data, 0); + + /* If an error occured the sprite is deleted and the function returns with an error. */ + if (glGetError()) + { + Delete(*pSprite); + return GLS_TEXTURE_CREATION_FAILED; + } + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Delete(GLS_Sprite * sprite) +{ + spriteTiled * s = (spriteTiled *) sprite; + GLS_UInt32 tileCount = s->widthSubdivisionCount * s->heightSubdivisionCount; + GLS_UInt32 i; + + /* Delete each texture. */ + for (i = 0; i < tileCount; ++i) + { + if (s->tiles[i].textureID) glDeleteTextures(1, &s->tiles[i].textureID); + } + + /* Free the memory used by the sprite. */ + free(s); + + return GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result Blit(GLS_Sprite * sprite, + const GLS_Rect * subImage) +{ + GLfloat width, height; + GLfloat texX1, texY1, texX2, texY2; + GLS_UInt32 tileIndex = 0; + GLS_UInt32 tileX, tileY; + GLfloat tileRectX1, tileRectY1; + GLfloat tileRectX2, tileRectY2; + GLfloat tileWidth, tileHeight; + GLfloat lastHeight = 0; + GLS_GLfloatRect tileRect, resultRect; + GLfloat x = 0.0f, y = 0.0f; + GLS_GLfloatRect subImageF = { (GLfloat) subImage->x1, (GLfloat) subImage->y1, (GLfloat) subImage->x2, (GLfloat) subImage->y2 }; + + spriteTiled * s = (spriteTiled *) sprite; + + /* Determine width and height of the subimage to display. */ + width = (float)(subImage->x2 - subImage->x1); + height = (float)(subImage->y2 - subImage->y1); + + glEnable(GL_TEXTURE_2D); + + /* Draw all required tiles. */ + for (tileY = 0; tileY < s->heightSubdivisionCount; ++tileY) + { + for (tileX = 0; tileX < s->widthSubdivisionCount; ++tileX) + { + tileRect.x1 = s->tiles[tileIndex].x; + tileRect.y1 = s->tiles[tileIndex].y; + tileRect.x2 = tileRect.x1 + s->tiles[tileIndex].width; + tileRect.y2 = tileRect.y1 + s->tiles[tileIndex].height; + + if (GLS_IntersectGLfloatRects(&tileRect, &subImageF, &resultRect)) + { + tileRectX1 = resultRect.x1; + tileRectY1 = resultRect.y1; + tileRectX2 = resultRect.x2; + tileRectY2 = resultRect.y2; + + glBindTexture(GL_TEXTURE_2D, s->tiles[tileIndex].textureID); + + texX1 = (tileRectX1 - s->tiles[tileIndex].x) / (GLfloat) s->tiles[tileIndex].width; + texY1 = (tileRectY1 - s->tiles[tileIndex].y) / (GLfloat) s->tiles[tileIndex].height; + texX2 = (GLfloat) (tileRectX2 - s->tiles[tileIndex].x) / (GLfloat) s->tiles[tileIndex].width; + texY2 = (GLfloat) (tileRectY2 - s->tiles[tileIndex].y) / (GLfloat) s->tiles[tileIndex].height; + + tileWidth = resultRect.x2 - resultRect.x1; + tileHeight = resultRect.y2 - resultRect.y1; + + glBegin(GL_QUADS); + glTexCoord2f(texX1, texY1); + glVertex2f(x, y); + + glTexCoord2f(texX2, texY1); + glVertex2f(x + tileWidth, y); + + glTexCoord2f(texX2, texY2); + glVertex2f(x + tileWidth, y + tileHeight); + + glTexCoord2f(texX1, texY2); + glVertex2f(x, y + tileHeight); + glEnd(); + + x += tileWidth; + lastHeight = tileHeight; + } + + ++tileIndex; + } + + x = 0; + y += lastHeight; + } + + glDisable(GL_TEXTURE_2D); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} + + +/* -------------------------------------------------------------------------- */ + +static GLS_Result SetData(GLS_Sprite * sprite, GLS_UInt32 width, GLS_UInt32 height, const void * data, GLS_UInt32 stride) +{ + spriteTiled * s = (spriteTiled *) sprite; + GLS_UInt32 x = 0, y = 0, tileIndex = 0; + GLS_UInt32 tileX, tileY; + GLS_UInt32 copyWidth, copyHeight; + const GLS_UInt32 * pixelData = (const GLS_UInt32 *) data; + + /* Set the source image row length and push the original value that it can be restored later. */ + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_UNPACK_ROW_LENGTH, width + stride); + + /* Loop through all tiles width first. */ + for (tileY = 0; tileY < s->heightSubdivisionCount; ++tileY) + { + /* Is there enough pixel data to reach the next tile? */ + if (height > y) + { + for (tileX = 0; tileX < s->widthSubdivisionCount; ++tileX) + { + /* Is the enough pixel data to reach the next tile? */ + if (width > x) + { + /* Determine the amount of pixels to be copied to the current tile. + They might either cover the whole tile, or just part of the tile if not enough + pixel data is left. */ + copyWidth = GLS_MIN(width - x, (GLS_UInt32) s->tiles[tileIndex].width); + copyHeight = GLS_MIN(height - y, (GLS_UInt32) s->tiles[tileIndex].height); + + /* Copy the pixels. */ + glBindTexture(GL_TEXTURE_2D, s->tiles[tileIndex].textureID); + + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, copyWidth, copyHeight, GL_RGBA, GL_UNSIGNED_BYTE, + &pixelData[x + y * (width + stride)]); + } + + /* Update the x position inside the pixel data and advance to the next tile. */ + x += (GLS_UInt32) s->tiles[tileIndex].width; + ++tileIndex; + } + } + + /* Restet the x position inside the pixel data (we have reached another row) and update the y position. */ + x = 0; + y += (GLS_UInt32) s->tiles[tileIndex - 1].height; + } + + glPopClientAttrib(); + + return glGetError() ? GLS_OPENGL_ERROR : GLS_OK; +} diff --git a/engines/sword25/util/glsprites/internal/sprite_tiled.h b/engines/sword25/util/glsprites/internal/sprite_tiled.h new file mode 100755 index 0000000000..8fb0d83ba7 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/sprite_tiled.h @@ -0,0 +1,41 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_SPRITE_TILED_H +#define GLS_SPRITE_TILED_H + +#include "../glsprites.h" + +GLS_Result GLS_NewSpriteTiled(GLS_UInt32 width, GLS_UInt32 height, GLS_Bool useAlphachannel, void * data, GLS_Sprite ** pSprite); +GLS_Result GLS_DeleteSpriteTiled(GLS_Sprite * sprite); + +GLS_Result GLS_BlitTiled(GLS_Sprite * sprite, + GLS_SInt32 x, GLS_SInt32 y, + const GLS_Rect * subImage, + const GLS_Color * color, + GLS_Bool flipH, GLS_Bool flipV, + GLS_Float scaleX, GLS_Float scaleY); + +GLS_Result GLS_SetSpriteDataTiled(GLS_Sprite * sprite, + GLS_UInt32 width, GLS_UInt32 height, + GLS_Bool useAlphachannel, + const void * data, + GLS_UInt32 stride); + +#endif diff --git a/engines/sword25/util/glsprites/internal/util.c b/engines/sword25/util/glsprites/internal/util.c new file mode 100755 index 0000000000..590f7e3459 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/util.c @@ -0,0 +1,77 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +/* -------------------------------------------------------------------------- + INCLUDES + -------------------------------------------------------------------------- */ + +#include "util.h" + + +/* -------------------------------------------------------------------------- */ + +GLS_Bool GLS_IsPowerOf2(GLS_UInt32 value) +{ + return !(value & (value - 1)) && value; +} + + +/* -------------------------------------------------------------------------- */ + +GLS_UInt32 GLS_NextPowerOf2(GLS_UInt32 value) +{ + --value; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + ++value; + + return value; +} + +/* -------------------------------------------------------------------------- */ + +GLS_UInt32 GLS_Log2(GLS_UInt32 value) +{ + GLS_UInt32 result = 0; + while (value >>= 1) ++result; + return result; +} + +/* -------------------------------------------------------------------------- */ + +GLS_Bool GLS_IntersectGLfloatRects(const GLS_GLfloatRect * r1, const GLS_GLfloatRect * r2, GLS_GLfloatRect * result) +{ + GLS_Bool rectsIntersect = (r1->x1 >= r2->x2 || + r1->x2 <= r2->x1 || + r1->y1 >= r2->y2 || + r1->y2 <= r2->y1) ? GLS_False : GLS_True; + + if(rectsIntersect) + { + result->x1 = GLS_MAX(r1->x1, r2->x1); + result->y1 = GLS_MAX(r1->y1, r2->y1); + result->x2 = GLS_MIN(r1->x2, r2->x2); + result->y2 = GLS_MIN(r1->y2, r2->y2); + } + + return rectsIntersect; +} diff --git a/engines/sword25/util/glsprites/internal/util.h b/engines/sword25/util/glsprites/internal/util.h new file mode 100755 index 0000000000..cdd69e2953 --- /dev/null +++ b/engines/sword25/util/glsprites/internal/util.h @@ -0,0 +1,42 @@ +/******************************************************************************/ +/* This file is part of Broken Sword 2.5 */ +/* Copyright (c) Malte Thiesen, Daniel Queteschiner and Michael Elsdörfer */ +/* */ +/* Broken Sword 2.5 is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU General Public License as published by */ +/* the Free Software Foundation; either version 2 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* Broken Sword 2.5 is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU General Public License */ +/* along with Broken Sword 2.5; if not, write to the Free Software */ +/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +/******************************************************************************/ + +#ifndef GLS_UTIL_H +#define GLS_UTIL_H + +#include "../glsprites.h" +#include "glinclude.h" + +typedef struct +{ + GLfloat x1; + GLfloat y1; + GLfloat x2; + GLfloat y2; +} GLS_GLfloatRect; + +GLS_Bool GLS_IsPowerOf2(GLS_UInt32 value); +GLS_UInt32 GLS_NextPowerOf2(GLS_UInt32 value); +GLS_UInt32 GLS_Log2(GLS_UInt32 value); +GLS_Bool GLS_IntersectGLfloatRects(const GLS_GLfloatRect * r1, const GLS_GLfloatRect * r2, GLS_GLfloatRect * result); + +#define GLS_MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define GLS_MIN(a,b) (((a) < (b)) ? (a) : (b)) + +#endif |