2014-06-01 17:55:23 +00:00
|
|
|
/*
|
2018-09-02 00:57:29 +00:00
|
|
|
* This file is part of the DXX-Rebirth project <https://www.dxx-rebirth.com/>.
|
2014-06-01 17:55:23 +00:00
|
|
|
* It is copyright by its individual contributors, as recorded in the
|
|
|
|
* project's Git history. See COPYING.txt at the top level for license
|
|
|
|
* terms and a link to the Git history.
|
|
|
|
*/
|
2006-03-20 17:12:09 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* OGL video functions. - Added 9/15/99 Matthew Mueller
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2007-06-11 15:54:09 +00:00
|
|
|
#define DECLARE_VARS
|
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
|
|
|
// extra libraries for the Raspberry Pi
|
2015-03-20 20:34:43 +00:00
|
|
|
#include <bcm_host.h>
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(_MSC_VER) && !defined(macintosh)
|
|
|
|
#include <unistd.h>
|
|
|
|
#endif
|
|
|
|
#if !defined(macintosh)
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2012-11-11 22:12:51 +00:00
|
|
|
#include <algorithm>
|
2006-03-20 17:12:09 +00:00
|
|
|
#include <errno.h>
|
2013-06-30 02:22:56 +00:00
|
|
|
#include <SDL.h>
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "hudmsg.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "text.h"
|
|
|
|
#include "gr.h"
|
|
|
|
#include "gamefont.h"
|
|
|
|
#include "grdef.h"
|
|
|
|
#include "palette.h"
|
|
|
|
#include "u_mem.h"
|
2012-07-07 18:35:06 +00:00
|
|
|
#include "dxxerror.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
#include "inferno.h"
|
|
|
|
#include "screens.h"
|
|
|
|
#include "strutil.h"
|
|
|
|
#include "args.h"
|
|
|
|
#include "key.h"
|
|
|
|
#include "physfsx.h"
|
2007-06-10 16:21:53 +00:00
|
|
|
#include "internal.h"
|
2007-10-18 14:44:02 +00:00
|
|
|
#include "render.h"
|
2008-04-06 20:23:28 +00:00
|
|
|
#include "console.h"
|
|
|
|
#include "config.h"
|
2008-04-13 00:28:36 +00:00
|
|
|
#include "playsave.h"
|
2008-04-19 19:11:32 +00:00
|
|
|
#include "vers_id.h"
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
#if defined(__APPLE__) && defined(__MACH__)
|
|
|
|
#include <OpenGL/glu.h>
|
2006-10-10 14:57:10 +00:00
|
|
|
#else
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2013-01-21 23:34:06 +00:00
|
|
|
#include <EGL/egl.h>
|
2011-01-06 11:43:58 +00:00
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
2013-06-30 02:22:56 +00:00
|
|
|
#include <SDL_syswm.h>
|
2011-01-06 11:43:58 +00:00
|
|
|
#else
|
2006-10-10 14:57:10 +00:00
|
|
|
#include <GL/glu.h>
|
2006-03-20 17:12:09 +00:00
|
|
|
#endif
|
2011-01-06 11:43:58 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-03-22 20:19:06 +00:00
|
|
|
#include "ogl_sync.h"
|
2015-03-22 19:32:14 +00:00
|
|
|
|
2014-11-30 22:09:19 +00:00
|
|
|
#include "compiler-make_unique.h"
|
|
|
|
|
2019-07-27 20:32:32 +00:00
|
|
|
using std::min;
|
2012-11-11 22:12:51 +00:00
|
|
|
using std::max;
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dcx {
|
2015-12-13 18:00:48 +00:00
|
|
|
|
2015-03-22 18:49:21 +00:00
|
|
|
static int ogl_brightness_r, ogl_brightness_g, ogl_brightness_b;
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2015-03-22 18:49:21 +00:00
|
|
|
static int sdl_video_flags;
|
2013-01-21 23:34:06 +00:00
|
|
|
|
|
|
|
#ifdef RPI
|
|
|
|
static EGL_DISPMANX_WINDOW_T nativewindow;
|
|
|
|
static DISPMANX_ELEMENT_HANDLE_T dispman_element=DISPMANX_NO_HANDLE;
|
|
|
|
static DISPMANX_DISPLAY_HANDLE_T dispman_display=DISPMANX_NO_HANDLE;
|
|
|
|
#endif
|
|
|
|
|
2011-02-10 14:30:08 +00:00
|
|
|
#else
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2015-03-22 18:49:21 +00:00
|
|
|
static int sdl_video_flags = SDL_OPENGL;
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
SDL_Window *g_pRebirthSDLMainWindow;
|
|
|
|
static int g_iRebirthWindowX, g_iRebirthWindowY;
|
|
|
|
#endif
|
2011-02-10 14:30:08 +00:00
|
|
|
#endif
|
2016-11-03 20:59:11 +00:00
|
|
|
static ogl_sync sync_helper;
|
2015-03-22 18:49:21 +00:00
|
|
|
static int gr_installed;
|
|
|
|
static int gl_initialized;
|
2008-11-09 14:31:30 +00:00
|
|
|
int linedotscale=1; // scalar of glLinewidth and glPointSize - only calculated once when resolution changes
|
2013-03-03 01:03:33 +00:00
|
|
|
#ifdef RPI
|
2015-03-22 18:49:21 +00:00
|
|
|
static int sdl_no_modeswitch;
|
2013-03-03 01:03:33 +00:00
|
|
|
#else
|
|
|
|
enum { sdl_no_modeswitch = 0 };
|
|
|
|
#endif
|
2008-04-19 19:11:32 +00:00
|
|
|
|
2015-12-13 18:00:48 +00:00
|
|
|
}
|
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
namespace dsx {
|
|
|
|
|
|
|
|
#if SDL_MAJOR_VERSION == 1
|
|
|
|
void gr_set_mode_from_window_size()
|
|
|
|
{
|
|
|
|
gr_set_mode(Game_screen_mode);
|
|
|
|
}
|
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
static void gr_set_mode_from_window_size(SDL_Window *const SDLWindow)
|
|
|
|
{
|
|
|
|
assert(SDLWindow);
|
|
|
|
int w, h;
|
|
|
|
SDL_GL_GetDrawableSize(SDLWindow, &w, &h);
|
|
|
|
gr_set_mode(screen_mode(w, h));
|
|
|
|
}
|
|
|
|
|
|
|
|
void gr_set_mode_from_window_size()
|
|
|
|
{
|
|
|
|
gr_set_mode_from_window_size(g_pRebirthSDLMainWindow);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2015-03-22 18:49:21 +00:00
|
|
|
static EGLDisplay eglDisplay=EGL_NO_DISPLAY;
|
|
|
|
static EGLConfig eglConfig;
|
|
|
|
static EGLSurface eglSurface=EGL_NO_SURFACE;
|
|
|
|
static EGLContext eglContext=EGL_NO_CONTEXT;
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2015-03-18 20:05:34 +00:00
|
|
|
static bool TestEGLError(const char* pszLocation)
|
2011-01-06 11:43:58 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* eglGetError returns the last error that has happened using egl,
|
|
|
|
* not the status of the last called function. The user has to
|
|
|
|
* check after every single egl call or at least once every frame.
|
|
|
|
*/
|
|
|
|
EGLint iErr = eglGetError();
|
|
|
|
if (iErr != EGL_SUCCESS)
|
|
|
|
{
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "%s failed (%d).", pszLocation, iErr);
|
2011-01-06 11:43:58 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dsx {
|
2015-12-13 18:00:48 +00:00
|
|
|
|
2008-04-19 19:11:32 +00:00
|
|
|
void ogl_swap_buffers_internal(void)
|
|
|
|
{
|
2016-11-03 20:59:11 +00:00
|
|
|
sync_helper.before_swap();
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
eglSwapBuffers(eglDisplay, eglSurface);
|
|
|
|
#else
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2008-04-19 19:11:32 +00:00
|
|
|
SDL_GL_SwapBuffers();
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
SDL_GL_SwapWindow(g_pRebirthSDLMainWindow);
|
|
|
|
#endif
|
2011-01-06 11:43:58 +00:00
|
|
|
#endif
|
2016-11-03 20:59:11 +00:00
|
|
|
sync_helper.after_swap();
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
|
|
|
|
|
|
|
// MH: I got the following constants for vc_dispmanx_element_change_attributes() from:
|
|
|
|
// http://qt.gitorious.org/qt/qtbase/commit/5933205cfcd73481cb0645fa6183103063fe3e0d
|
|
|
|
// I do not know where they got them from, but OTOH, they are quite obvious.
|
|
|
|
|
|
|
|
// these constants are not in any headers (yet)
|
|
|
|
#define ELEMENT_CHANGE_LAYER (1<<0)
|
|
|
|
#define ELEMENT_CHANGE_OPACITY (1<<1)
|
|
|
|
#define ELEMENT_CHANGE_DEST_RECT (1<<2)
|
|
|
|
#define ELEMENT_CHANGE_SRC_RECT (1<<3)
|
|
|
|
#define ELEMENT_CHANGE_MASK_RESOURCE (1<<4)
|
|
|
|
#define ELEMENT_CHANGE_TRANSFORM (1<<5)
|
|
|
|
|
2015-03-20 03:30:20 +00:00
|
|
|
static void rpi_destroy_element()
|
2013-01-21 23:34:06 +00:00
|
|
|
{
|
|
|
|
if (dispman_element != DISPMANX_NO_HANDLE) {
|
|
|
|
DISPMANX_UPDATE_HANDLE_T dispman_update;
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: destroying display manager element");
|
2013-01-21 23:34:06 +00:00
|
|
|
dispman_update = vc_dispmanx_update_start( 0 );
|
|
|
|
if (vc_dispmanx_element_remove( dispman_update, dispman_element)) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "RPi: failed to remove dispmanx element!");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
vc_dispmanx_update_submit_sync( dispman_update );
|
|
|
|
dispman_element = DISPMANX_NO_HANDLE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-18 20:07:57 +00:00
|
|
|
static int rpi_setup_element(int x, int y, Uint32 video_flags, int update)
|
2013-01-21 23:34:06 +00:00
|
|
|
{
|
|
|
|
// this code is based on the work of Ben O'Steen
|
|
|
|
// http://benosteen.wordpress.com/2012/04/27/using-opengl-es-2-0-on-the-raspberry-pi-without-x-windows/
|
|
|
|
// https://github.com/benosteen/opengles-book-samples/tree/master/Raspi
|
|
|
|
DISPMANX_UPDATE_HANDLE_T dispman_update;
|
|
|
|
VC_RECT_T dst_rect;
|
|
|
|
VC_RECT_T src_rect;
|
|
|
|
VC_DISPMANX_ALPHA_T alpha_descriptor;
|
|
|
|
|
|
|
|
uint32_t rpi_display_device=DISPMANX_ID_MAIN_LCD;
|
|
|
|
uint32_t display_width;
|
|
|
|
uint32_t display_height;
|
|
|
|
int success;
|
|
|
|
|
|
|
|
success = graphics_get_display_size(rpi_display_device, &display_width, &display_height);
|
|
|
|
if ( success < 0 ) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "Could not get RPi display size, assuming 640x480");
|
2013-01-21 23:34:06 +00:00
|
|
|
display_width=640;
|
|
|
|
display_height=480;
|
|
|
|
}
|
|
|
|
|
2016-06-05 01:04:26 +00:00
|
|
|
if (static_cast<uint32_t>(x) > display_width) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "RPi: Requested width %d exceeds display width %u, scaling down!",
|
2013-01-21 23:34:06 +00:00
|
|
|
x,display_width);
|
2016-06-05 01:04:26 +00:00
|
|
|
x=static_cast<int>(display_width);
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2016-06-05 01:04:26 +00:00
|
|
|
if (static_cast<uint32_t>(y) > display_height) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "RPi: Requested height %d exceeds display height %u, scaling down!",
|
2013-01-21 23:34:06 +00:00
|
|
|
y,display_height);
|
2016-06-05 01:04:26 +00:00
|
|
|
y=static_cast<int>(display_height);
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: display resolution %ux%u, game resolution: %dx%d (%s)", display_width, display_height, x, y, (video_flags & SDL_FULLSCREEN)?"fullscreen":"windowed");
|
2013-01-21 23:34:06 +00:00
|
|
|
if (video_flags & SDL_FULLSCREEN) {
|
|
|
|
/* scale to the full display size... */
|
|
|
|
dst_rect.x = 0;
|
|
|
|
dst_rect.y = 0;
|
|
|
|
dst_rect.width = display_width;
|
|
|
|
dst_rect.height= display_height;
|
|
|
|
} else {
|
|
|
|
/* TODO: we could query the position of the X11 window here
|
|
|
|
and try to place the ovelray exactly above that...,
|
|
|
|
we would have to track window movements, though ... */
|
|
|
|
dst_rect.x = 0;
|
|
|
|
dst_rect.y = 0;
|
2016-06-05 01:04:26 +00:00
|
|
|
dst_rect.width = static_cast<uint32_t>(x);
|
|
|
|
dst_rect.height= static_cast<uint32_t>(y);
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
src_rect.x = 0;
|
|
|
|
src_rect.y = 0;
|
2016-06-05 01:04:26 +00:00
|
|
|
src_rect.width = (static_cast<uint32_t>(x))<< 16;
|
|
|
|
src_rect.height =(static_cast<uint32_t>(y))<< 16;
|
2013-01-21 23:34:06 +00:00
|
|
|
|
|
|
|
/* we do not want our overlay to be blended against the background */
|
|
|
|
alpha_descriptor.flags=DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
|
|
|
|
alpha_descriptor.opacity=0xffffffff;
|
|
|
|
alpha_descriptor.mask=0;
|
|
|
|
|
|
|
|
// open display, if we do not already have one ...
|
|
|
|
if (dispman_display == DISPMANX_NO_HANDLE) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: opening display: %u",rpi_display_device);
|
2013-01-21 23:34:06 +00:00
|
|
|
dispman_display = vc_dispmanx_display_open(rpi_display_device);
|
|
|
|
if (dispman_display == DISPMANX_NO_HANDLE) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT,"RPi: failed to open display: %u",rpi_display_device);
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dispman_element != DISPMANX_NO_HANDLE) {
|
|
|
|
if (!update) {
|
|
|
|
// if the element already exists, and we cannot update it, so recreate it
|
|
|
|
rpi_destroy_element();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// if the element does not exist, we cannot do an update
|
|
|
|
update=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dispman_update = vc_dispmanx_update_start( 0 );
|
|
|
|
|
|
|
|
if (update) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: updating display manager element");
|
2013-01-21 23:34:06 +00:00
|
|
|
vc_dispmanx_element_change_attributes ( dispman_update, nativewindow.element,
|
|
|
|
ELEMENT_CHANGE_DEST_RECT | ELEMENT_CHANGE_SRC_RECT,
|
|
|
|
0 /*layer*/, 0 /*opacity*/,
|
|
|
|
&dst_rect, &src_rect,
|
2015-03-18 20:30:50 +00:00
|
|
|
0 /*mask*/,
|
|
|
|
static_cast<DISPMANX_TRANSFORM_T>(VC_IMAGE_ROT0) /*transform*/);
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
|
|
|
// create a new element
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: creating display manager element");
|
2013-01-21 23:34:06 +00:00
|
|
|
dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display,
|
|
|
|
0 /*layer*/, &dst_rect, 0 /*src*/,
|
|
|
|
&src_rect, DISPMANX_PROTECTION_NONE,
|
|
|
|
&alpha_descriptor, NULL /*clamp*/,
|
2015-03-18 20:30:50 +00:00
|
|
|
static_cast<DISPMANX_TRANSFORM_T>(VC_IMAGE_ROT0) /*transform*/);
|
2013-01-21 23:34:06 +00:00
|
|
|
if (dispman_element == DISPMANX_NO_HANDLE) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT,"RPi: failed to creat display manager elemenr");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
nativewindow.element = dispman_element;
|
|
|
|
}
|
|
|
|
nativewindow.width = display_width;
|
|
|
|
nativewindow.height = display_height;
|
|
|
|
vc_dispmanx_update_submit_sync( dispman_update );
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // RPI
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2015-03-20 03:30:20 +00:00
|
|
|
static void ogles_destroy()
|
2013-01-21 23:34:06 +00:00
|
|
|
{
|
|
|
|
if( eglDisplay != EGL_NO_DISPLAY ) {
|
|
|
|
eglMakeCurrent(eglDisplay, NULL, NULL, EGL_NO_CONTEXT);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eglContext != EGL_NO_CONTEXT) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: destroyig context");
|
2013-01-21 23:34:06 +00:00
|
|
|
eglDestroyContext(eglDisplay, eglContext);
|
|
|
|
eglContext = EGL_NO_CONTEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eglSurface != EGL_NO_SURFACE) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: destroyig surface");
|
2013-01-21 23:34:06 +00:00
|
|
|
eglDestroySurface(eglDisplay, eglSurface);
|
|
|
|
eglSurface = EGL_NO_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eglDisplay != EGL_NO_DISPLAY) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: terminating");
|
2013-01-21 23:34:06 +00:00
|
|
|
eglTerminate(eglDisplay);
|
|
|
|
eglDisplay = EGL_NO_DISPLAY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
static int ogl_init_window(int w, int h)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
SDL_SysWMinfo info;
|
|
|
|
Window x11Window = 0;
|
|
|
|
Display* x11Display = 0;
|
|
|
|
EGLint ver_maj, ver_min;
|
2011-03-27 23:57:18 +00:00
|
|
|
EGLint configAttribs[] =
|
|
|
|
{
|
|
|
|
EGL_RED_SIZE, 5,
|
|
|
|
EGL_GREEN_SIZE, 6,
|
|
|
|
EGL_BLUE_SIZE, 5,
|
|
|
|
EGL_DEPTH_SIZE, 16,
|
|
|
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
|
2013-01-21 23:34:06 +00:00
|
|
|
EGL_NONE, EGL_NONE
|
2011-03-27 23:57:18 +00:00
|
|
|
};
|
2013-01-21 23:34:06 +00:00
|
|
|
|
|
|
|
// explicitely request an OpenGL ES 1.x context
|
|
|
|
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE, EGL_NONE };
|
|
|
|
// explicitely request a doublebuffering window
|
|
|
|
EGLint winAttribs[] = { EGL_RENDER_BUFFER, EGL_BACK_BUFFER, EGL_NONE, EGL_NONE };
|
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
int iConfigs;
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif // OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2011-02-10 14:30:08 +00:00
|
|
|
if (gl_initialized)
|
2008-11-09 14:31:30 +00:00
|
|
|
ogl_smash_texture_list_internal();//if we are or were fullscreen, changing vid mode will invalidate current textures
|
2008-04-19 19:11:32 +00:00
|
|
|
|
2013-03-03 01:03:33 +00:00
|
|
|
SDL_WM_SetCaption(DESCENT_VERSION, DXX_SDL_WINDOW_CAPTION);
|
2018-07-28 23:22:58 +00:00
|
|
|
if (const auto window_icon = SDL_LoadBMP(DXX_SDL_WINDOW_ICON_BITMAP))
|
|
|
|
SDL_WM_SetIcon(window_icon, nullptr);
|
2011-02-10 14:30:08 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
int use_x = w;
|
|
|
|
int use_y = h;
|
|
|
|
int use_bpp = CGameArg.DbgBpp;
|
|
|
|
int use_flags = sdl_video_flags;
|
2013-01-21 23:34:06 +00:00
|
|
|
if (sdl_no_modeswitch) {
|
|
|
|
const SDL_VideoInfo *vinfo=SDL_GetVideoInfo();
|
|
|
|
if (vinfo) {
|
|
|
|
use_x=vinfo->current_w;
|
|
|
|
use_y=vinfo->current_h;
|
|
|
|
use_bpp=vinfo->vfmt->BitsPerPixel;
|
|
|
|
use_flags=SDL_SWSURFACE | SDL_ANYFORMAT;
|
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "Could not query video info");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!SDL_SetVideoMode(use_x, use_y, use_bpp, use_flags))
|
2011-01-06 11:43:58 +00:00
|
|
|
{
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
|
|
|
con_printf(CON_URGENT, "Could not set %dx%dx%d opengl video mode: %s\n (Ignored for RPI)",
|
2018-07-28 23:22:58 +00:00
|
|
|
w, h, CGameArg.DbgBpp, SDL_GetError());
|
2013-01-21 23:34:06 +00:00
|
|
|
#else
|
2018-07-28 23:22:58 +00:00
|
|
|
Error("Could not set %dx%dx%d opengl video mode: %s\n", w, h, CGameArg.DbgBpp, SDL_GetError());
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
const auto SDLWindow = g_pRebirthSDLMainWindow;
|
|
|
|
if (!(SDL_GetWindowFlags(SDLWindow) & SDL_WINDOW_FULLSCREEN))
|
|
|
|
SDL_SetWindowSize(SDLWindow, w, h);
|
|
|
|
#endif
|
2011-02-10 14:30:08 +00:00
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifndef RPI
|
|
|
|
// NOTE: on the RPi, the EGL stuff is not connected to the X11 window,
|
|
|
|
// so there is no need to destroy and recreate this
|
|
|
|
ogles_destroy();
|
|
|
|
#endif
|
2011-03-27 23:57:18 +00:00
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
SDL_VERSION(&info.version);
|
|
|
|
|
|
|
|
if (SDL_GetWMInfo(&info) > 0) {
|
|
|
|
if (info.subsystem == SDL_SYSWM_X11) {
|
|
|
|
x11Display = info.info.x11.display;
|
|
|
|
x11Window = info.info.x11.window;
|
2016-10-29 23:51:44 +00:00
|
|
|
con_printf (CON_DEBUG, "Display: %p, Window: %i ===", x11Display, static_cast<int>(x11Window));
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
|
|
|
}
|
2013-01-21 23:34:06 +00:00
|
|
|
|
|
|
|
if (eglDisplay == EGL_NO_DISPLAY) {
|
|
|
|
#ifdef RPI
|
|
|
|
eglDisplay = eglGetDisplay((EGLNativeDisplayType)EGL_DEFAULT_DISPLAY);
|
|
|
|
#else
|
|
|
|
eglDisplay = eglGetDisplay((EGLNativeDisplayType)x11Display);
|
|
|
|
#endif
|
|
|
|
if (eglDisplay == EGL_NO_DISPLAY) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error querying EGL Display");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!eglInitialize(eglDisplay, &ver_maj, &ver_min)) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error initializing EGL");
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: Initialized, version: major %i minor %i", ver_maj, ver_min);
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
2013-01-21 23:34:06 +00:00
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
2018-07-28 23:22:58 +00:00
|
|
|
if (rpi_setup_element(w,h,sdl_video_flags,1)) {
|
|
|
|
Error("RPi: Could not set up a %dx%d element\n", w, h);
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (eglSurface == EGL_NO_SURFACE) {
|
|
|
|
if (!eglChooseConfig(eglDisplay, configAttribs, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error choosing config");
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: config chosen");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RPI
|
2016-10-29 23:51:44 +00:00
|
|
|
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, static_cast<EGLNativeWindowType>(&nativewindow), winAttribs);
|
2013-01-21 23:34:06 +00:00
|
|
|
#else
|
2016-10-29 23:51:44 +00:00
|
|
|
eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, static_cast<NativeWindowType>(x11Window), winAttribs);
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif
|
|
|
|
if ((!TestEGLError("eglCreateWindowSurface")) || eglSurface == EGL_NO_SURFACE) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error creating window surface");
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: Created window surface");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
if (eglContext == EGL_NO_CONTEXT) {
|
|
|
|
eglContext = eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT, contextAttribs);
|
|
|
|
if ((!TestEGLError("eglCreateContext")) || eglContext == EGL_NO_CONTEXT) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error creating context");
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: Created context");
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);
|
|
|
|
if (!TestEGLError("eglMakeCurrent")) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT, "EGL: Error making current");
|
2011-01-06 11:43:58 +00:00
|
|
|
} else {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "EGL: made context current");
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
|
|
|
#endif
|
2008-04-19 19:11:32 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
const auto w640 = w / 640;
|
|
|
|
const auto h480 = h / 480;
|
|
|
|
const auto min_wh = std::min(w640, h480);
|
|
|
|
linedotscale = min_wh < 1 ? 1 : min_wh;
|
2008-11-09 14:31:30 +00:00
|
|
|
|
|
|
|
gl_initialized=1;
|
2008-04-19 19:11:32 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-12-18 04:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace dcx {
|
|
|
|
|
2008-04-19 19:11:32 +00:00
|
|
|
int gr_check_fullscreen(void)
|
|
|
|
{
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2016-10-18 02:26:30 +00:00
|
|
|
return !!(sdl_video_flags & SDL_FULLSCREEN);
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
return !!(SDL_GetWindowFlags(g_pRebirthSDLMainWindow) & SDL_WINDOW_FULLSCREEN);
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2015-03-22 18:49:21 +00:00
|
|
|
void gr_toggle_fullscreen()
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2016-05-22 17:49:31 +00:00
|
|
|
const auto local_sdl_video_flags = (sdl_video_flags ^= SDL_FULLSCREEN);
|
2008-04-19 19:11:32 +00:00
|
|
|
if (gl_initialized)
|
|
|
|
{
|
2013-01-21 23:34:06 +00:00
|
|
|
if (sdl_no_modeswitch == 0) {
|
2015-05-14 02:23:13 +00:00
|
|
|
auto gsm = Game_screen_mode;
|
2015-12-18 04:08:23 +00:00
|
|
|
const auto DbgBpp = CGameArg.DbgBpp;
|
2016-05-22 17:49:31 +00:00
|
|
|
if (!SDL_VideoModeOK(gsm.width, gsm.height, DbgBpp, local_sdl_video_flags))
|
2013-01-21 23:34:06 +00:00
|
|
|
{
|
2015-05-14 02:23:13 +00:00
|
|
|
con_printf(CON_URGENT, "Cannot set %ix%i. Fallback to 640x480", gsm.width, gsm.height);
|
|
|
|
gsm.width = 640;
|
|
|
|
gsm.height = 480;
|
|
|
|
Game_screen_mode = gsm;
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2016-05-22 17:49:31 +00:00
|
|
|
if (!SDL_SetVideoMode(gsm.width, gsm.height, DbgBpp, local_sdl_video_flags))
|
2013-01-21 23:34:06 +00:00
|
|
|
{
|
2015-12-18 04:08:23 +00:00
|
|
|
Error("Could not set %dx%dx%d opengl video mode: %s\n", gsm.width, gsm.height, DbgBpp, SDL_GetError());
|
2013-01-21 23:34:06 +00:00
|
|
|
}
|
2011-02-10 14:30:08 +00:00
|
|
|
}
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
2016-05-22 17:49:31 +00:00
|
|
|
if (rpi_setup_element(SM_W(Game_screen_mode), SM_H(Game_screen_mode), local_sdl_video_flags, 1)) {
|
2013-01-21 23:34:06 +00:00
|
|
|
Error("RPi: Could not set up %dx%d element\n", SM_W(Game_screen_mode), SM_H(Game_screen_mode));
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
2013-01-21 23:34:06 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2008-04-06 20:23:28 +00:00
|
|
|
gr_remap_color_fonts();
|
2007-05-09 09:44:45 +00:00
|
|
|
|
2010-07-29 20:19:52 +00:00
|
|
|
if (gl_initialized) // update viewing values for menus
|
2007-05-09 09:44:45 +00:00
|
|
|
{
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
glOrthof(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
|
|
|
|
#else
|
|
|
|
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
|
|
|
|
#endif
|
2007-05-09 09:44:45 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();//clear matrix
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2011-04-10 10:29:06 +00:00
|
|
|
ogl_smash_texture_list_internal();//if we are or were fullscreen, changing vid mode will invalidate current textures
|
2007-05-09 09:44:45 +00:00
|
|
|
}
|
2016-05-22 17:49:31 +00:00
|
|
|
CGameCfg.WindowMode = !(local_sdl_video_flags & SDL_FULLSCREEN);
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
const auto SDLWindow = g_pRebirthSDLMainWindow;
|
|
|
|
const auto is_fullscreen_before_change = SDL_GetWindowFlags(SDLWindow) & SDL_WINDOW_FULLSCREEN;
|
|
|
|
CGameCfg.WindowMode = !!is_fullscreen_before_change;
|
|
|
|
if (!is_fullscreen_before_change)
|
|
|
|
SDL_GetWindowPosition(SDLWindow, &g_iRebirthWindowX, &g_iRebirthWindowY);
|
|
|
|
SDL_SetWindowFullscreen(SDLWindow, is_fullscreen_before_change ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
|
|
|
|
if (is_fullscreen_before_change)
|
|
|
|
{
|
|
|
|
const auto mode = Game_screen_mode;
|
|
|
|
SDL_SetWindowPosition(SDLWindow, g_iRebirthWindowX, g_iRebirthWindowY);
|
|
|
|
SDL_SetWindowSize(SDLWindow, SM_W(mode), SM_H(mode));
|
|
|
|
}
|
|
|
|
gr_set_mode_from_window_size(SDLWindow);
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2012-11-02 16:51:24 +00:00
|
|
|
static void ogl_init_state(void)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
/* select clearing (background) color */
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
|
|
|
|
/* initialize viewing values */
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
glOrthof(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
|
|
|
|
#else
|
|
|
|
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
|
|
|
|
#endif
|
2007-03-21 11:32:33 +00:00
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glLoadIdentity();//clear matrix
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
2006-03-20 17:12:09 +00:00
|
|
|
gr_palette_step_up(0,0,0);//in case its left over from in game
|
|
|
|
|
2015-03-22 18:49:21 +00:00
|
|
|
ogl_init_pixel_buffers(grd_curscreen->get_screen_width(), grd_curscreen->get_screen_height());
|
2007-03-21 11:32:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-18 04:08:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace dsx {
|
|
|
|
|
2016-11-03 20:59:11 +00:00
|
|
|
static void ogl_tune_for_current(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2015-03-22 18:49:21 +00:00
|
|
|
const auto gl_vendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
|
|
|
|
const auto gl_renderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
|
|
|
|
const auto gl_version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2017-08-26 19:47:51 +00:00
|
|
|
con_printf(CON_VERBOSE, "DXX-Rebirth: OpenGL: vendor: %s", gl_vendor);
|
|
|
|
con_printf(CON_VERBOSE, "DXX-Rebirth: OpenGL: renderer: %s", gl_renderer);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
if (gl_renderer)
|
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
//add driver specific hacks here. whee.
|
2012-05-18 23:36:43 +00:00
|
|
|
if ((d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.0\n")==0 || d_stricmp(gl_renderer,"Mesa NVIDIA RIVA 1.2\n")==0) && d_stricmp(gl_version,"1.2 Mesa 3.0")==0)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2017-08-26 19:47:51 +00:00
|
|
|
con_puts(CON_VERBOSE, "DXX-Rebirth: OpenGL renderer is blacklisted for GL intensity, GL read pixel, and GL GetTexLevel");
|
2015-12-18 04:08:23 +00:00
|
|
|
CGameArg.DbgGlIntensity4Ok = false; //ignores alpha, always black background instead of transparent.
|
2015-12-18 04:08:24 +00:00
|
|
|
CGameArg.DbgGlReadPixelsOk = false; //either just returns all black, or kills the X server entirely
|
2015-12-18 04:08:24 +00:00
|
|
|
CGameArg.DbgGlGetTexLevelParamOk = false; //returns random data..
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2012-05-18 23:36:43 +00:00
|
|
|
if (d_stricmp(gl_vendor,"Matrox Graphics Inc.")==0)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2017-08-26 19:47:51 +00:00
|
|
|
con_puts(CON_VERBOSE, "DXX-Rebirth: OpenGL renderer is blacklisted for GL intensity");
|
2006-03-20 17:12:09 +00:00
|
|
|
//displays garbage. reported by
|
|
|
|
// redomen@crcwnet.com (render="Matrox G400" version="1.1.3 5.52.015")
|
|
|
|
// orulz (Matrox G200)
|
2015-12-18 04:08:23 +00:00
|
|
|
CGameArg.DbgGlIntensity4Ok = 0;
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
#ifdef macintosh
|
2012-05-18 23:36:43 +00:00
|
|
|
if (d_stricmp(gl_renderer,"3dfx Voodoo 3")==0) // strangely, includes Voodoo 2
|
2015-12-18 04:08:24 +00:00
|
|
|
CGameArg.DbgGlGetTexLevelParamOk = false; // Always returns 0
|
2006-03-20 17:12:09 +00:00
|
|
|
#endif
|
2018-07-28 23:22:58 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2009-11-17 14:27:39 +00:00
|
|
|
#ifndef NDEBUG
|
2017-08-26 19:47:51 +00:00
|
|
|
con_printf(CON_VERBOSE, "DXX-Rebirth: OpenGL: gl_intensity4:%i gl_luminance4_alpha4:%i gl_rgba2:%i gl_readpixels:%i gl_gettexlevelparam:%i", CGameArg.DbgGlIntensity4Ok, CGameArg.DbgGlLuminance4Alpha4Ok, CGameArg.DbgGlRGBA2Ok, CGameArg.DbgGlReadPixelsOk, CGameArg.DbgGlGetTexLevelParamOk);
|
2009-11-17 14:27:39 +00:00
|
|
|
#endif
|
2017-08-26 19:47:51 +00:00
|
|
|
if (ogl_maxanisotropy < 1.0f && CGameCfg.TexAnisotropy)
|
|
|
|
{
|
|
|
|
con_puts(CON_VERBOSE, "DXX-Rebirth: OpenGL: anisotropic texture filter not supported");
|
2016-11-03 20:59:11 +00:00
|
|
|
CGameCfg.TexAnisotropy = false;
|
2011-01-16 00:50:42 +00:00
|
|
|
}
|
2009-11-17 14:27:39 +00:00
|
|
|
}
|
|
|
|
|
2015-12-13 18:00:48 +00:00
|
|
|
}
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dcx {
|
2015-12-13 18:00:48 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2010-06-24 09:29:11 +00:00
|
|
|
// returns possible (fullscreen) resolutions if any.
|
2015-05-14 02:23:13 +00:00
|
|
|
uint_fast32_t gr_list_modes(array<screen_mode, 50> &gsmodes)
|
2010-06-24 09:29:11 +00:00
|
|
|
{
|
|
|
|
SDL_Rect** modes;
|
2014-09-26 02:42:13 +00:00
|
|
|
int modesnum = 0;
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2011-01-06 11:43:58 +00:00
|
|
|
int sdl_check_flags = SDL_FULLSCREEN; // always use Fullscreen as lead.
|
|
|
|
#else
|
2010-06-24 09:29:11 +00:00
|
|
|
int sdl_check_flags = SDL_OPENGL | SDL_FULLSCREEN; // always use Fullscreen as lead.
|
2011-01-06 11:43:58 +00:00
|
|
|
#endif
|
2010-06-24 09:29:11 +00:00
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
if (sdl_no_modeswitch) {
|
|
|
|
/* TODO: we could use the tvservice to list resolutions on the RPi */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-24 09:29:11 +00:00
|
|
|
modes = SDL_ListModes(NULL, sdl_check_flags);
|
|
|
|
|
2016-07-06 01:54:24 +00:00
|
|
|
if (modes == reinterpret_cast<SDL_Rect **>(0)) // check if we get any modes - if not, return 0
|
2010-06-24 09:29:11 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
2016-07-06 01:54:24 +00:00
|
|
|
if (modes == reinterpret_cast<SDL_Rect**>(-1))
|
2010-06-24 09:29:11 +00:00
|
|
|
{
|
|
|
|
return 0; // can obviously use any resolution... strange!
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-09-26 02:42:13 +00:00
|
|
|
for (int i = 0; modes[i]; ++i)
|
2010-06-24 09:29:11 +00:00
|
|
|
{
|
2010-07-25 00:49:33 +00:00
|
|
|
if (modes[i]->w > 0xFFF0 || modes[i]->h > 0xFFF0 // resolutions saved in 32bits. so skip bigger ones (unrealistic in 2010) (changed to 0xFFF0 to fix warning)
|
2010-06-24 09:29:11 +00:00
|
|
|
|| modes[i]->w < 320 || modes[i]->h < 200) // also skip everything smaller than 320x200
|
|
|
|
continue;
|
2015-05-14 02:23:13 +00:00
|
|
|
gsmodes[modesnum].width = modes[i]->w;
|
|
|
|
gsmodes[modesnum].height = modes[i]->h;
|
2010-06-24 09:29:11 +00:00
|
|
|
modesnum++;
|
2015-05-14 02:23:13 +00:00
|
|
|
if (modesnum >= gsmodes.size()) // that really seems to be enough big boy.
|
2010-06-24 09:29:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return modesnum;
|
|
|
|
}
|
|
|
|
}
|
2018-07-28 23:22:58 +00:00
|
|
|
#endif
|
2010-06-24 09:29:11 +00:00
|
|
|
|
2015-12-13 18:00:48 +00:00
|
|
|
}
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dsx {
|
2015-12-13 18:00:48 +00:00
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2015-05-14 02:23:13 +00:00
|
|
|
static int gr_check_mode(const screen_mode mode)
|
2009-11-17 14:27:39 +00:00
|
|
|
{
|
2013-01-21 23:34:06 +00:00
|
|
|
if (sdl_no_modeswitch == 0) {
|
2015-12-18 04:08:23 +00:00
|
|
|
return SDL_VideoModeOK(SM_W(mode), SM_H(mode), CGameArg.DbgBpp, sdl_video_flags);
|
2013-01-21 23:34:06 +00:00
|
|
|
} else {
|
|
|
|
// just tell the caller that any mode is valid...
|
|
|
|
return 32;
|
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2018-07-28 23:22:58 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-05-14 02:23:13 +00:00
|
|
|
int gr_set_mode(screen_mode mode)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2013-08-05 00:00:07 +00:00
|
|
|
unsigned char *gr_bm_data;
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2011-01-06 11:43:58 +00:00
|
|
|
if (!gr_check_mode(mode))
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2015-05-14 02:23:13 +00:00
|
|
|
con_printf(CON_URGENT, "Cannot set %ix%i. Fallback to 640x480", mode.width, mode.height);
|
|
|
|
mode.width = 640;
|
|
|
|
mode.height = 480;
|
|
|
|
Game_screen_mode = mode;
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
2018-07-28 23:22:58 +00:00
|
|
|
#endif
|
2015-05-14 02:23:13 +00:00
|
|
|
const uint_fast32_t w = SM_W(mode), h = SM_H(mode);
|
2007-07-15 15:23:45 +00:00
|
|
|
|
2014-12-02 03:24:38 +00:00
|
|
|
gr_bm_data = grd_curscreen->sc_canvas.cv_bitmap.get_bitmap_data();//since we use realloc, we want to keep this pointer around.
|
2016-09-04 00:02:53 +00:00
|
|
|
auto gr_new_bm_data = reinterpret_cast<uint8_t *>(d_realloc(gr_bm_data, w * h));
|
2013-08-05 00:00:07 +00:00
|
|
|
if (!gr_new_bm_data)
|
|
|
|
return 0;
|
2014-07-04 03:47:03 +00:00
|
|
|
*grd_curscreen = {};
|
2015-03-22 18:49:21 +00:00
|
|
|
grd_curscreen->set_screen_width_height(w, h);
|
|
|
|
grd_curscreen->sc_aspect = fixdiv(grd_curscreen->get_screen_width() * GameCfg.AspectX, grd_curscreen->get_screen_height() * GameCfg.AspectY);
|
2016-05-28 17:31:26 +00:00
|
|
|
gr_init_canvas(grd_curscreen->sc_canvas, gr_new_bm_data, bm_mode::ogl, w, h);
|
2017-11-05 20:49:08 +00:00
|
|
|
gr_set_default_canvas();
|
2009-11-17 14:27:39 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
ogl_init_window(w,h);//platform specific code
|
2015-03-22 20:19:06 +00:00
|
|
|
ogl_extensions_init();
|
2016-11-03 20:59:11 +00:00
|
|
|
ogl_tune_for_current();
|
2015-12-24 04:01:27 +00:00
|
|
|
sync_helper.init(CGameArg.OglSyncMethod, CGameArg.OglSyncWait);
|
2014-08-06 18:42:55 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
OGL_VIEWPORT(0,0,w,h);
|
2007-03-21 11:32:33 +00:00
|
|
|
ogl_init_state();
|
2008-02-24 14:41:27 +00:00
|
|
|
gamefont_choose_game_font(w,h);
|
2008-04-06 20:23:28 +00:00
|
|
|
gr_remap_color_fonts();
|
2006-10-09 21:44:24 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-18 23:36:43 +00:00
|
|
|
#define GLstrcmptestr(a,b) if (d_stricmp(a,#b)==0 || d_stricmp(a,"GL_" #b)==0)return GL_ ## b;
|
2007-06-10 16:21:53 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
#ifdef _WIN32
|
2016-07-16 16:52:04 +00:00
|
|
|
constexpr char OglLibPath[]="opengl32.dll";
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2013-06-22 21:36:28 +00:00
|
|
|
static int ogl_rt_loaded=0;
|
|
|
|
static int ogl_init_load_library(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
int retcode=0;
|
2008-04-19 19:11:32 +00:00
|
|
|
if (!ogl_rt_loaded)
|
|
|
|
{
|
2013-06-22 21:36:28 +00:00
|
|
|
retcode = OpenGL_LoadLibrary(true, OglLibPath);
|
2006-03-20 17:12:09 +00:00
|
|
|
if(retcode)
|
|
|
|
{
|
|
|
|
if(!glEnd)
|
|
|
|
{
|
|
|
|
Error("Opengl: Functions not imported\n");
|
|
|
|
}
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-06-11 15:54:09 +00:00
|
|
|
Error("Opengl: error loading %s\n", OglLibPath);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
ogl_rt_loaded=1;
|
|
|
|
}
|
|
|
|
return retcode;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-04-22 08:29:29 +00:00
|
|
|
void gr_set_attributes(void)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGLES
|
2008-04-19 19:11:32 +00:00
|
|
|
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE,0);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE,0);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE,0);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE,0);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE,0);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2015-07-18 03:49:47 +00:00
|
|
|
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, CGameCfg.VSync);
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
SDL_GL_SetSwapInterval(CGameCfg.VSync ? 1 : 0);
|
|
|
|
#endif
|
2016-10-02 19:35:34 +00:00
|
|
|
int buffers, samples;
|
2016-10-02 19:35:33 +00:00
|
|
|
if (CGameCfg.Multisample)
|
2008-04-22 08:29:29 +00:00
|
|
|
{
|
2016-10-02 19:35:34 +00:00
|
|
|
buffers = 1;
|
|
|
|
samples = 4;
|
2008-04-22 08:29:29 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-10-02 19:35:34 +00:00
|
|
|
buffers = samples = 0;
|
2008-04-22 08:29:29 +00:00
|
|
|
}
|
2016-10-02 19:35:34 +00:00
|
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, buffers);
|
|
|
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, samples);
|
2011-01-06 11:43:58 +00:00
|
|
|
#endif
|
2008-04-22 08:29:29 +00:00
|
|
|
ogl_smash_texture_list_internal();
|
2008-04-22 12:57:06 +00:00
|
|
|
gr_remap_color_fonts();
|
2008-04-22 08:29:29 +00:00
|
|
|
}
|
|
|
|
|
2015-05-14 02:23:13 +00:00
|
|
|
int gr_init()
|
2008-04-22 08:29:29 +00:00
|
|
|
{
|
2009-11-17 14:27:39 +00:00
|
|
|
// Only do this function once!
|
2008-04-22 08:29:29 +00:00
|
|
|
if (gr_installed==1)
|
|
|
|
return -1;
|
|
|
|
|
2013-01-21 23:34:06 +00:00
|
|
|
#ifdef RPI
|
|
|
|
// Initialize the broadcom host library
|
|
|
|
// we have to call this before we can create an OpenGL ES context
|
|
|
|
bcm_host_init();
|
|
|
|
|
|
|
|
// Check if we are running with SDL directfb driver ...
|
2015-03-22 18:49:21 +00:00
|
|
|
char sdl_driver[32];
|
|
|
|
if (auto sdl_driver_ret = SDL_VideoDriverName(sdl_driver, sizeof(sdl_driver)))
|
|
|
|
{
|
2013-01-21 23:34:06 +00:00
|
|
|
if (strcmp(sdl_driver_ret,"x11")) {
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_URGENT,"RPi: activating hack for console driver");
|
2013-01-21 23:34:06 +00:00
|
|
|
sdl_no_modeswitch=1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-04-22 08:29:29 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
ogl_init_load_library();
|
|
|
|
#endif
|
|
|
|
|
2018-07-28 23:22:58 +00:00
|
|
|
#if SDL_MAJOR_VERSION == 1
|
2015-12-24 04:01:27 +00:00
|
|
|
if (!CGameCfg.WindowMode && !CGameArg.SysWindow)
|
2011-02-10 14:30:08 +00:00
|
|
|
sdl_video_flags|=SDL_FULLSCREEN;
|
|
|
|
|
2015-12-24 04:01:27 +00:00
|
|
|
if (CGameArg.SysNoBorders)
|
2011-02-10 14:30:08 +00:00
|
|
|
sdl_video_flags|=SDL_NOFRAME;
|
2018-07-28 23:22:58 +00:00
|
|
|
#elif SDL_MAJOR_VERSION == 2
|
|
|
|
assert(!g_pRebirthSDLMainWindow);
|
|
|
|
unsigned sdl_window_flags = SDL_WINDOW_OPENGL;
|
|
|
|
if (CGameArg.SysNoBorders)
|
|
|
|
sdl_window_flags |= SDL_WINDOW_BORDERLESS;
|
|
|
|
if (!CGameCfg.WindowMode && !CGameArg.SysWindow)
|
|
|
|
sdl_window_flags |= SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
const auto mode = Game_screen_mode;
|
|
|
|
const auto SDLWindow = SDL_CreateWindow(DESCENT_VERSION, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SM_W(mode), SM_H(mode), sdl_window_flags);
|
|
|
|
if (!SDLWindow)
|
|
|
|
return -1;
|
|
|
|
SDL_GetWindowPosition(SDLWindow, &g_iRebirthWindowX, &g_iRebirthWindowY);
|
|
|
|
g_pRebirthSDLMainWindow = SDLWindow;
|
|
|
|
SDL_GL_CreateContext(SDLWindow);
|
|
|
|
if (const auto window_icon = SDL_LoadBMP(DXX_SDL_WINDOW_ICON_BITMAP))
|
|
|
|
SDL_SetWindowIcon(SDLWindow, window_icon);
|
|
|
|
#endif
|
2008-04-22 08:29:29 +00:00
|
|
|
|
|
|
|
gr_set_attributes();
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
ogl_init_texture_list_internal();
|
2008-04-22 08:29:29 +00:00
|
|
|
|
2016-08-06 19:55:24 +00:00
|
|
|
grd_curscreen = make_unique<grs_screen>();
|
|
|
|
*grd_curscreen = {};
|
2006-03-20 17:12:09 +00:00
|
|
|
grd_curscreen->sc_canvas.cv_bitmap.bm_data = NULL;
|
|
|
|
|
|
|
|
// Set the mode.
|
2011-02-23 16:46:39 +00:00
|
|
|
grd_curscreen->sc_canvas.cv_fade_level = GR_FADE_OFF;
|
2006-03-20 17:12:09 +00:00
|
|
|
grd_curscreen->sc_canvas.cv_font = NULL;
|
|
|
|
grd_curscreen->sc_canvas.cv_font_fg_color = 0;
|
|
|
|
grd_curscreen->sc_canvas.cv_font_bg_color = 0;
|
2017-11-05 20:49:08 +00:00
|
|
|
gr_set_current_canvas(grd_curscreen->sc_canvas);
|
2009-11-17 14:27:39 +00:00
|
|
|
|
|
|
|
ogl_init_pixel_buffers(256, 128); // for gamefont_init
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
gr_installed = 1;
|
2010-06-24 09:29:11 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void gr_close()
|
|
|
|
{
|
|
|
|
ogl_brightness_r = ogl_brightness_g = ogl_brightness_b = 0;
|
|
|
|
|
2008-04-19 19:11:32 +00:00
|
|
|
if (gl_initialized)
|
|
|
|
{
|
|
|
|
ogl_smash_texture_list_internal();
|
2015-03-22 20:19:06 +00:00
|
|
|
sync_helper.deinit();
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (grd_curscreen)
|
|
|
|
{
|
2014-12-02 03:24:38 +00:00
|
|
|
if (grd_curscreen->sc_canvas.cv_bitmap.bm_mdata)
|
|
|
|
d_free(grd_curscreen->sc_canvas.cv_bitmap.bm_mdata);
|
Clear canvas to fix missing exit tunnel movie
Global variable `grd_curcanv` is set to a variety of canvases, some of
which are local stack variables. Use of global variables in this way is
fragile, but works as long as the global is not used beyond the life of
the backing local.
Unfortunately, some existing uses do access the canvas beyond the
lifetime of the backing local. Playing movies sets the font of the
current canvas. If the current canvas is an expired stack variable,
setting the font overwrites other stack data. This data corruption
causes various symptoms, such as inability to play the escape tunnel
movie.
Prior to 03cca2b3dce62ae29c1ab7509df5105423365b4a, the corruption on
playing the endlevel movie had no user-visible effect. That commit
created a large local variable, which changed stack layout. Starting
with that commit, the corruption causes the movie to play as all black.
Fix this, and protect against some other data corruption possiblities,
by clearing the global when the local goes out of scope.
Reported-by: Havner <https://github.com/dxx-rebirth/dxx-rebirth/issues/345> (only as cutscene failure to play, not as the underlying corruption issue)
2017-11-05 20:49:08 +00:00
|
|
|
/* Resetting grd_curscreen frees the default canvas, so set
|
|
|
|
* grd_curcanv to nullptr since no canvas is available after
|
|
|
|
* this block ends.
|
|
|
|
*/
|
|
|
|
grd_curcanv = nullptr;
|
2014-11-30 22:09:19 +00:00
|
|
|
grd_curscreen.reset();
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2006-12-29 09:50:21 +00:00
|
|
|
ogl_close_pixel_buffers();
|
2007-07-18 20:13:17 +00:00
|
|
|
#ifdef _WIN32
|
2006-03-20 17:12:09 +00:00
|
|
|
if (ogl_rt_loaded)
|
2013-10-26 03:40:36 +00:00
|
|
|
OpenGL_LoadLibrary(false, OglLibPath);
|
2006-03-20 17:12:09 +00:00
|
|
|
#endif
|
2013-01-21 23:34:06 +00:00
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if DXX_USE_OGLES
|
2013-01-21 23:34:06 +00:00
|
|
|
ogles_destroy();
|
|
|
|
#ifdef RPI
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: cleanuing up");
|
2013-01-21 23:34:06 +00:00
|
|
|
if (dispman_display != DISPMANX_NO_HANDLE) {
|
|
|
|
rpi_destroy_element();
|
2013-12-07 00:47:27 +00:00
|
|
|
con_printf(CON_DEBUG, "RPi: closing display");
|
2013-01-21 23:34:06 +00:00
|
|
|
vc_dispmanx_display_close(dispman_display);
|
|
|
|
dispman_display = DISPMANX_NO_HANDLE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2008-04-19 19:11:32 +00:00
|
|
|
|
2015-12-13 18:00:48 +00:00
|
|
|
}
|
|
|
|
|
2015-12-13 18:00:49 +00:00
|
|
|
namespace dcx {
|
2015-12-13 18:00:48 +00:00
|
|
|
|
2017-03-11 19:56:23 +00:00
|
|
|
void ogl_upixelc(const grs_bitmap &cv_bitmap, unsigned x, unsigned y, unsigned c)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2017-07-08 18:17:49 +00:00
|
|
|
array<GLfloat, 2> vertices = {{
|
2017-03-11 19:56:23 +00:00
|
|
|
(x + cv_bitmap.bm_x) / static_cast<float>(last_width),
|
|
|
|
static_cast<GLfloat>(1.0 - (y + cv_bitmap.bm_y) / static_cast<float>(last_height))
|
2017-07-08 18:17:49 +00:00
|
|
|
}};
|
2016-05-28 17:31:26 +00:00
|
|
|
const auto cr = static_cast<GLfloat>(CPAL2Tr(c));
|
|
|
|
const auto cg = static_cast<GLfloat>(CPAL2Tg(c));
|
|
|
|
const auto cb = static_cast<GLfloat>(CPAL2Tb(c));
|
2013-10-09 01:54:12 +00:00
|
|
|
GLfloat color_array[] = {
|
2016-05-28 17:31:26 +00:00
|
|
|
cr, cg, cb, 1.0,
|
|
|
|
cr, cg, cb, 1.0,
|
|
|
|
cr, cg, cb, 1.0,
|
|
|
|
cr, cg, cb, 1.0
|
2013-10-09 01:54:12 +00:00
|
|
|
};
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2007-06-10 16:21:53 +00:00
|
|
|
OGL_DISABLE(TEXTURE_2D);
|
2008-11-09 14:31:30 +00:00
|
|
|
glPointSize(linedotscale);
|
2011-01-06 11:43:58 +00:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
2017-07-08 18:17:49 +00:00
|
|
|
glVertexPointer(2, GL_FLOAT, 0, vertices.data());
|
2011-01-06 11:43:58 +00:00
|
|
|
glColorPointer(4, GL_FLOAT, 0, color_array);
|
|
|
|
glDrawArrays(GL_POINTS, 0, 1);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2007-06-10 16:21:53 +00:00
|
|
|
|
2014-11-30 22:09:18 +00:00
|
|
|
unsigned char ogl_ugpixel(const grs_bitmap &bitmap, unsigned x, unsigned y)
|
2012-04-15 05:45:45 +00:00
|
|
|
{
|
|
|
|
ubyte buf[4];
|
|
|
|
|
2016-09-24 18:06:11 +00:00
|
|
|
#if !DXX_USE_OGLES
|
2015-04-04 20:58:02 +00:00
|
|
|
GLint gl_draw_buffer;
|
2012-04-15 05:45:45 +00:00
|
|
|
glGetIntegerv(GL_DRAW_BUFFER, &gl_draw_buffer);
|
|
|
|
glReadBuffer(gl_draw_buffer);
|
|
|
|
#endif
|
|
|
|
|
2014-11-30 22:09:18 +00:00
|
|
|
glReadPixels(bitmap.bm_x + x, SHEIGHT - bitmap.bm_y - y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, buf);
|
2012-04-15 05:45:45 +00:00
|
|
|
|
|
|
|
return gr_find_closest_color(buf[0]/4, buf[1]/4, buf[2]/4);
|
|
|
|
}
|
|
|
|
|
2016-12-29 03:27:08 +00:00
|
|
|
void ogl_urect(grs_canvas &canvas, const int left, const int top, const int right, const int bot, const int c)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2011-01-06 11:43:58 +00:00
|
|
|
GLfloat xo, yo, xf, yf, color_r, color_g, color_b, color_a;
|
2010-06-24 09:29:11 +00:00
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
2016-12-29 03:27:08 +00:00
|
|
|
xo = (left + canvas.cv_bitmap.bm_x) / static_cast<float>(last_width);
|
|
|
|
xf = (right + 1 + canvas.cv_bitmap.bm_x) / static_cast<float>(last_width);
|
|
|
|
yo = 1.0 - (top + canvas.cv_bitmap.bm_y) / static_cast<float>(last_height);
|
|
|
|
yf = 1.0 - (bot + 1 + canvas.cv_bitmap.bm_y) / static_cast<float>(last_height);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
OGL_DISABLE(TEXTURE_2D);
|
2011-01-06 11:43:58 +00:00
|
|
|
|
|
|
|
color_r = CPAL2Tr(c);
|
|
|
|
color_g = CPAL2Tg(c);
|
|
|
|
color_b = CPAL2Tb(c);
|
|
|
|
|
2016-12-29 03:27:08 +00:00
|
|
|
if (canvas.cv_fade_level >= GR_FADE_OFF)
|
2011-01-06 11:43:58 +00:00
|
|
|
color_a = 1.0;
|
2006-03-20 17:12:09 +00:00
|
|
|
else
|
2016-12-29 03:27:08 +00:00
|
|
|
color_a = 1.0 - static_cast<float>(canvas.cv_fade_level) / (static_cast<float>(GR_FADE_LEVELS) - 1.0);
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2016-12-29 03:27:08 +00:00
|
|
|
array<GLfloat, 16> color_array;
|
2011-01-06 11:43:58 +00:00
|
|
|
color_array[0] = color_array[4] = color_array[8] = color_array[12] = color_r;
|
|
|
|
color_array[1] = color_array[5] = color_array[9] = color_array[13] = color_g;
|
|
|
|
color_array[2] = color_array[6] = color_array[10] = color_array[14] = color_b;
|
|
|
|
color_array[3] = color_array[7] = color_array[11] = color_array[15] = color_a;
|
|
|
|
|
2017-07-08 18:17:49 +00:00
|
|
|
array<GLfloat, 8> vertices;
|
|
|
|
vertices[0] = xo;
|
|
|
|
vertices[1] = yo;
|
|
|
|
vertices[2] = xo;
|
|
|
|
vertices[3] = yf;
|
|
|
|
vertices[4] = xf;
|
|
|
|
vertices[5] = yf;
|
|
|
|
vertices[6] = xf;
|
|
|
|
vertices[7] = yo;
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, vertices.data());
|
2016-12-29 03:27:08 +00:00
|
|
|
glColorPointer(4, GL_FLOAT, 0, color_array.data());
|
2011-01-06 11:43:58 +00:00
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
2018-04-23 06:31:27 +00:00
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2007-06-10 16:21:53 +00:00
|
|
|
|
2016-12-29 03:27:09 +00:00
|
|
|
void ogl_ulinec(grs_canvas &canvas, const int left, const int top, const int right, const int bot, const int c)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
GLfloat xo,yo,xf,yf;
|
2016-12-29 03:27:09 +00:00
|
|
|
GLfloat fade_alpha = (canvas.cv_fade_level >= GR_FADE_OFF)
|
|
|
|
? 1.0
|
|
|
|
: 1.0 - static_cast<float>(canvas.cv_fade_level) / (static_cast<float>(GR_FADE_LEVELS) - 1.0);
|
2013-10-09 01:54:12 +00:00
|
|
|
GLfloat color_array[] = {
|
|
|
|
static_cast<GLfloat>(CPAL2Tr(c)), static_cast<GLfloat>(CPAL2Tg(c)), static_cast<GLfloat>(CPAL2Tb(c)), fade_alpha,
|
|
|
|
static_cast<GLfloat>(CPAL2Tr(c)), static_cast<GLfloat>(CPAL2Tg(c)), static_cast<GLfloat>(CPAL2Tb(c)), fade_alpha,
|
|
|
|
static_cast<GLfloat>(CPAL2Tr(c)), static_cast<GLfloat>(CPAL2Tg(c)), static_cast<GLfloat>(CPAL2Tb(c)), 1.0,
|
|
|
|
static_cast<GLfloat>(CPAL2Tr(c)), static_cast<GLfloat>(CPAL2Tg(c)), static_cast<GLfloat>(CPAL2Tb(c)), fade_alpha
|
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
|
|
|
|
2016-12-29 03:27:09 +00:00
|
|
|
xo = (left + canvas.cv_bitmap.bm_x) / static_cast<float>(last_width);
|
|
|
|
xf = (right + canvas.cv_bitmap.bm_x) / static_cast<float>(last_width);
|
|
|
|
yo = 1.0 - (top + canvas.cv_bitmap.bm_y + 0.5) / static_cast<float>(last_height);
|
|
|
|
yf = 1.0 - (bot + canvas.cv_bitmap.bm_y + 0.5) / static_cast<float>(last_height);
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
OGL_DISABLE(TEXTURE_2D);
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2017-07-08 18:17:49 +00:00
|
|
|
array<GLfloat, 4> vertices = {{
|
|
|
|
xo,
|
|
|
|
yo,
|
|
|
|
xf,
|
|
|
|
yf,
|
|
|
|
}};
|
2011-01-06 11:43:58 +00:00
|
|
|
|
2017-07-08 18:17:49 +00:00
|
|
|
glVertexPointer(2, GL_FLOAT, 0, vertices.data());
|
2011-01-06 11:43:58 +00:00
|
|
|
glColorPointer(4, GL_FLOAT, 0, color_array);
|
|
|
|
glDrawArrays(GL_LINES, 0, 2);
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
2015-03-22 18:49:21 +00:00
|
|
|
static GLfloat last_r, last_g, last_b;
|
|
|
|
static int do_pal_step;
|
2007-06-10 16:21:53 +00:00
|
|
|
|
2008-04-19 19:11:32 +00:00
|
|
|
void ogl_do_palfx(void)
|
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
OGL_DISABLE(TEXTURE_2D);
|
2008-03-20 23:23:46 +00:00
|
|
|
|
2011-01-06 11:43:58 +00:00
|
|
|
glEnableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glEnableClientState(GL_COLOR_ARRAY);
|
2019-07-28 09:47:24 +00:00
|
|
|
|
|
|
|
GLfloat alast_r = last_r;
|
|
|
|
GLfloat alast_g = last_g;
|
|
|
|
GLfloat alast_b = last_b;
|
|
|
|
|
|
|
|
if (!do_pal_step) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else if (last_r <= 0 && last_g <= 0 && last_b <= 0)
|
|
|
|
{
|
2019-07-27 21:42:37 +00:00
|
|
|
// scale negative effect by 2.5 to match D1/D2 on GL
|
2019-07-27 21:49:30 +00:00
|
|
|
// also make values positive to actually have an effect
|
2019-07-28 09:47:24 +00:00
|
|
|
alast_r = last_r * -2.5;
|
|
|
|
alast_g = last_g * -2.5;
|
|
|
|
alast_b = last_b * -2.5;
|
|
|
|
|
2019-07-27 21:42:37 +00:00
|
|
|
glEnable(GL_BLEND);
|
|
|
|
glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR);
|
|
|
|
}
|
2019-07-28 09:47:24 +00:00
|
|
|
else
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2008-03-20 23:23:46 +00:00
|
|
|
glEnable(GL_BLEND);
|
2019-07-27 21:42:37 +00:00
|
|
|
glBlendFunc(GL_ONE,GL_ONE);
|
2008-04-19 19:11:32 +00:00
|
|
|
}
|
2019-07-28 09:47:24 +00:00
|
|
|
|
|
|
|
GLfloat color_array[] = {
|
|
|
|
alast_r, alast_g, alast_b, 1.0,
|
|
|
|
alast_r, alast_g, alast_b, 1.0,
|
|
|
|
alast_r, alast_g, alast_b, 1.0,
|
|
|
|
alast_r, alast_g, alast_b, 1.0
|
|
|
|
};
|
2017-07-08 18:17:49 +00:00
|
|
|
|
|
|
|
array<GLfloat, 8> vertices = {{
|
|
|
|
0, 0, 0, 1, 1, 1, 1, 0
|
|
|
|
}};
|
|
|
|
glVertexPointer(2, GL_FLOAT, 0, vertices.data());
|
2011-01-06 11:43:58 +00:00
|
|
|
glColorPointer(4, GL_FLOAT, 0, color_array);
|
|
|
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);//replaced GL_QUADS
|
|
|
|
glDisableClientState(GL_VERTEX_ARRAY);
|
|
|
|
glDisableClientState(GL_COLOR_ARRAY);
|
2010-06-24 09:29:11 +00:00
|
|
|
glEnable(GL_BLEND);
|
2006-03-20 17:12:09 +00:00
|
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
}
|
|
|
|
|
2015-03-22 18:49:21 +00:00
|
|
|
static int ogl_brightness_ok;
|
|
|
|
static int old_b_r, old_b_g, old_b_b;
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2019-07-28 09:47:24 +00:00
|
|
|
inline int gr_apply_gamma_clamp(int v)
|
|
|
|
{
|
|
|
|
if (v >= 0)
|
|
|
|
return max(v + gr_palette_gamma, 0);
|
|
|
|
else
|
|
|
|
return min(v + gr_palette_gamma, 0);
|
|
|
|
}
|
|
|
|
|
2006-03-20 17:12:09 +00:00
|
|
|
void gr_palette_step_up(int r, int g, int b)
|
|
|
|
{
|
|
|
|
old_b_r = ogl_brightness_r;
|
|
|
|
old_b_g = ogl_brightness_g;
|
|
|
|
old_b_b = ogl_brightness_b;
|
|
|
|
|
2019-07-28 09:47:24 +00:00
|
|
|
ogl_brightness_r = gr_apply_gamma_clamp(r);
|
|
|
|
ogl_brightness_g = gr_apply_gamma_clamp(g);
|
|
|
|
ogl_brightness_b = gr_apply_gamma_clamp(b);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2008-01-13 13:27:58 +00:00
|
|
|
if (!ogl_brightness_ok)
|
2006-03-20 17:12:09 +00:00
|
|
|
{
|
|
|
|
last_r = ogl_brightness_r / 63.0;
|
|
|
|
last_g = ogl_brightness_g / 63.0;
|
|
|
|
last_b = ogl_brightness_b / 63.0;
|
|
|
|
|
|
|
|
do_pal_step = (r || g || b || gr_palette_gamma);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
do_pal_step = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-06 21:03:57 +00:00
|
|
|
void gr_palette_load( palette_array_t &pal )
|
2013-01-06 20:07:36 +00:00
|
|
|
{
|
2013-12-17 22:14:43 +00:00
|
|
|
copy_bound_palette(gr_current_pal, pal);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
gr_palette_step_up(0, 0, 0); // make ogl_setbrightness_internal get run so that menus get brightened too.
|
2007-06-10 16:21:53 +00:00
|
|
|
init_computed_colors();
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#define GL_BGR_EXT 0x80E0
|
|
|
|
|
2013-12-22 22:03:07 +00:00
|
|
|
struct TGA_header
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
unsigned char TGAheader[12];
|
|
|
|
unsigned char header[6];
|
2013-12-22 22:03:07 +00:00
|
|
|
};
|
2006-03-20 17:12:09 +00:00
|
|
|
|
|
|
|
//writes out an uncompressed RGB .tga file
|
|
|
|
//if we got really spiffy, we could optionally link in libpng or something, and use that.
|
2018-02-18 00:42:42 +00:00
|
|
|
#if DXX_USE_SCREENSHOT_FORMAT_LEGACY
|
|
|
|
void write_bmp(PHYSFS_File *const TGAFile, const unsigned w, const unsigned h)
|
2008-04-19 19:11:32 +00:00
|
|
|
{
|
2006-03-20 17:12:09 +00:00
|
|
|
TGA_header TGA;
|
|
|
|
GLbyte HeightH,HeightL,WidthH,WidthL;
|
2015-01-28 03:42:53 +00:00
|
|
|
RAIIdmem<uint8_t[]> buf;
|
2016-10-02 00:34:49 +00:00
|
|
|
const unsigned buffer_size_TGA = w * h * 3;
|
|
|
|
CALLOC(buf, uint8_t[], buffer_size_TGA);
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-01-28 03:42:53 +00:00
|
|
|
RAIIdmem<uint8_t[]> rgbaBuf;
|
|
|
|
CALLOC(rgbaBuf, uint8_t[], w * h * 4);
|
2015-02-17 03:52:59 +00:00
|
|
|
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaBuf.get());
|
2014-09-26 02:42:13 +00:00
|
|
|
for(unsigned int pixel = 0; pixel < w * h; pixel++) {
|
2015-02-17 03:52:59 +00:00
|
|
|
buf[pixel * 3] = rgbaBuf[pixel * 4 + 2];
|
|
|
|
buf[pixel * 3 + 1] = rgbaBuf[pixel * 4 + 1];
|
|
|
|
buf[pixel * 3 + 2] = rgbaBuf[pixel * 4];
|
2011-01-06 11:43:58 +00:00
|
|
|
}
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2016-09-04 00:02:51 +00:00
|
|
|
HeightH = static_cast<GLbyte>(h / 256);
|
|
|
|
HeightL = static_cast<GLbyte>(h % 256);
|
|
|
|
WidthH = static_cast<GLbyte>(w / 256);
|
|
|
|
WidthL = static_cast<GLbyte>(w % 256);
|
2006-03-20 17:12:09 +00:00
|
|
|
// Write TGA Header
|
|
|
|
TGA.TGAheader[0] = 0;
|
|
|
|
TGA.TGAheader[1] = 0;
|
|
|
|
TGA.TGAheader[2] = 2;
|
|
|
|
TGA.TGAheader[3] = 0;
|
|
|
|
TGA.TGAheader[4] = 0;
|
|
|
|
TGA.TGAheader[5] = 0;
|
|
|
|
TGA.TGAheader[6] = 0;
|
|
|
|
TGA.TGAheader[7] = 0;
|
|
|
|
TGA.TGAheader[8] = 0;
|
|
|
|
TGA.TGAheader[9] = 0;
|
|
|
|
TGA.TGAheader[10] = 0;
|
|
|
|
TGA.TGAheader[11] = 0;
|
2016-08-17 04:44:22 +00:00
|
|
|
TGA.header[0] = WidthL;
|
|
|
|
TGA.header[1] = WidthH;
|
|
|
|
TGA.header[2] = HeightL;
|
|
|
|
TGA.header[3] = HeightH;
|
2016-09-04 00:02:51 +00:00
|
|
|
TGA.header[4] = static_cast<GLbyte>(24);
|
2006-03-20 17:12:09 +00:00
|
|
|
TGA.header[5] = 0;
|
2006-10-19 09:38:07 +00:00
|
|
|
PHYSFS_write(TGAFile,&TGA,sizeof(TGA_header),1);
|
2016-10-02 00:34:49 +00:00
|
|
|
PHYSFS_write(TGAFile,buf, buffer_size_TGA * sizeof(unsigned char),1);
|
2006-03-20 17:12:09 +00:00
|
|
|
}
|
2018-02-18 00:42:42 +00:00
|
|
|
#endif
|
2006-03-20 17:12:09 +00:00
|
|
|
|
2015-12-13 18:00:48 +00:00
|
|
|
}
|