Merge pull request #26 from rkitover/mac_hidpi
Mac OS X HiDPI fixes + other misc
This commit is contained in:
commit
db85f54b1c
|
@ -59,7 +59,11 @@ IF( NOT VERSION )
|
||||||
endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||||
ENDIF( NOT VERSION )
|
ENDIF( NOT VERSION )
|
||||||
|
|
||||||
|
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
ADD_DEFINITIONS(-DDEBUG)
|
||||||
|
ELSE()
|
||||||
|
ADD_DEFINITIONS(-NDEBUG)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# Fill in SDLMAIN_LIBRARY on OS X manually to avoid using SDLMain.m
|
# Fill in SDLMAIN_LIBRARY on OS X manually to avoid using SDLMain.m
|
||||||
# OS X users will have to compile and install SDL from source.
|
# OS X users will have to compile and install SDL from source.
|
||||||
|
@ -68,18 +72,38 @@ if( APPLE AND ENABLE_SDL )
|
||||||
SET(SDL2MAIN_LIBRARY "-lSDL2main")
|
SET(SDL2MAIN_LIBRARY "-lSDL2main")
|
||||||
endif( APPLE AND ENABLE_SDL )
|
endif( APPLE AND ENABLE_SDL )
|
||||||
|
|
||||||
# Add support for MacPorts and Homebrew on OS X
|
# Add support for Homebrew, MacPorts and Fink on OS X
|
||||||
# and ObjectiveC code
|
# as well as for ObjectiveC code
|
||||||
IF(APPLE)
|
IF(APPLE)
|
||||||
SET(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};/usr/local/include;/opt/local/include")
|
IF(EXISTS /usr/local/include)
|
||||||
SET(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};/usr/local/lib;/opt/local/lib")
|
SET(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};/usr/local/include")
|
||||||
SET(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};/usr/local/bin;/opt/local/bin")
|
INCLUDE_DIRECTORIES("/usr/local/include")
|
||||||
|
ELSEIF(EXISTS /opt/local/include)
|
||||||
|
SET(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};/opt/local/include")
|
||||||
|
INCLUDE_DIRECTORIES("/opt/local/include")
|
||||||
|
ELSEIF(EXISTS /sw/include)
|
||||||
|
SET(CMAKE_INCLUDE_PATH "${CMAKE_INCLUDE_PATH};/sw/include")
|
||||||
|
INCLUDE_DIRECTORIES("/sw/include")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
link_directories("/usr/local/lib")
|
IF(EXISTS /usr/local/lib)
|
||||||
include_directories("/usr/local/include")
|
SET(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};/usr/local/lib")
|
||||||
|
LINK_DIRECTORIES("/usr/local/lib")
|
||||||
|
ELSEIF(EXISTS /opt/local/lib)
|
||||||
|
SET(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};/opt/local/lib")
|
||||||
|
LINK_DIRECTORIES("/opt/local/lib")
|
||||||
|
ELSEIF(EXISTS /sw/lib)
|
||||||
|
SET(CMAKE_LIBRARY_PATH "${CMAKE_LIBRARY_PATH};/sw/lib")
|
||||||
|
LINK_DIRECTORIES("/sw/lib")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
link_directories("/opt/local/lib")
|
IF(EXISTS /usr/local/bin)
|
||||||
include_directories("/opt/local/include")
|
SET(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};/usr/local/bin")
|
||||||
|
ELSEIF(EXISTS /opt/local/bin)
|
||||||
|
SET(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};/opt/local/bin")
|
||||||
|
ELSEIF(EXISTS /sw/bin)
|
||||||
|
SET(CMAKE_PROGRAM_PATH "${CMAKE_PROGRAM_PATH};/sw/bin")
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
# and compile as Objective-C++ for ObjectiveC #ifdefs
|
# and compile as Objective-C++ for ObjectiveC #ifdefs
|
||||||
SET(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> -x objective-c++ <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
|
SET(CMAKE_CXX_COMPILE_OBJECT "<CMAKE_CXX_COMPILER> -x objective-c++ <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
|
||||||
|
|
|
@ -29,10 +29,15 @@ else(ENABLE_OPENAL)
|
||||||
ADD_DEFINITIONS (-DNO_OAL)
|
ADD_DEFINITIONS (-DNO_OAL)
|
||||||
endif(ENABLE_OPENAL)
|
endif(ENABLE_OPENAL)
|
||||||
|
|
||||||
|
IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
SET(wxWidgets_USE_DEBUG ON) # noop if wx is compiled with --disable-debug, like in Mac Homebrew atm
|
||||||
|
|
||||||
IF(CMAKE_BUILD_TYPE EQUAL "Debug")
|
# and if this is the case, we can't set debug level without link failing
|
||||||
SET(wxWidgets_USE_DEBUG ON)
|
IF(NOT wxWidgets_DEFINITIONS MATCHES "-DwxDEBUG_LEVEL=0")
|
||||||
|
ADD_DEFINITIONS(-DwxDEBUG_LEVEL=1)
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET(wxWidgets_USE_UNICODE ON)
|
SET(wxWidgets_USE_UNICODE ON)
|
||||||
# adv is for wxAboutBox
|
# adv is for wxAboutBox
|
||||||
# xml, html is for xrc
|
# xml, html is for xrc
|
||||||
|
|
|
@ -47,13 +47,11 @@ protected:
|
||||||
{
|
{
|
||||||
PaintEv(ev);
|
PaintEv(ev);
|
||||||
}
|
}
|
||||||
void OnSize(wxSizeEvent&);
|
|
||||||
void DrawArea(wxWindowDC& dc);
|
void DrawArea(wxWindowDC& dc);
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
wxGLContext ctx;
|
wxGLContext* ctx;
|
||||||
#endif
|
#endif
|
||||||
bool did_init;
|
void DrawingPanelInit();
|
||||||
void Init();
|
|
||||||
GLuint texid, vlist;
|
GLuint texid, vlist;
|
||||||
int texsize;
|
int texsize;
|
||||||
|
|
||||||
|
@ -81,8 +79,7 @@ protected:
|
||||||
PaintEv(ev);
|
PaintEv(ev);
|
||||||
}
|
}
|
||||||
void DrawArea(wxWindowDC&);
|
void DrawArea(wxWindowDC&);
|
||||||
bool did_init;
|
void DrawingPanelInit();
|
||||||
void Init();
|
|
||||||
|
|
||||||
DECLARE_CLASS()
|
DECLARE_CLASS()
|
||||||
DECLARE_EVENT_TABLE()
|
DECLARE_EVENT_TABLE()
|
||||||
|
|
|
@ -2522,6 +2522,8 @@ bool MainFrame::BindControls()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
panel->SetMainFrame(this);
|
||||||
|
|
||||||
panel->AdjustSize(false);
|
panel->AdjustSize(false);
|
||||||
// only the panel does idle events (the emulator loop)
|
// only the panel does idle events (the emulator loop)
|
||||||
// however, do not enable until end of init, since errors will start
|
// however, do not enable until end of init, since errors will start
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
{ \
|
{ \
|
||||||
wxT(c), (n), d, NULL, &v, NULL, min, max \
|
wxT(c), (n), d, NULL, &v, NULL, min, max \
|
||||||
}
|
}
|
||||||
|
#define DOUBLEOPT(c, n, d, v, min, max) \
|
||||||
|
{ \
|
||||||
|
wxT(c), (n), d, NULL, NULL, NULL, min, max, NULL, &v \
|
||||||
|
}
|
||||||
#define BOOLOPT(c, n, d, v) \
|
#define BOOLOPT(c, n, d, v) \
|
||||||
{ \
|
{ \
|
||||||
wxT(c), (n), d, NULL, NULL, NULL, 0, 0, &v \
|
wxT(c), (n), d, NULL, NULL, NULL, 0, 0, &v \
|
||||||
|
@ -156,7 +160,7 @@ opt_desc opts[] = {
|
||||||
#else
|
#else
|
||||||
ENUMOPT("Display/RenderMethod", "", wxTRANSLATE("Render method; if unsupported, simple method will be used"), gopts.render_method, wxTRANSLATE("simple|opengl|cairo")),
|
ENUMOPT("Display/RenderMethod", "", wxTRANSLATE("Render method; if unsupported, simple method will be used"), gopts.render_method, wxTRANSLATE("simple|opengl|cairo")),
|
||||||
#endif
|
#endif
|
||||||
INTOPT("Display/Scale", "", wxTRANSLATE("Default scale factor"), gopts.video_scale, 1, 6),
|
DOUBLEOPT("Display/Scale", "", wxTRANSLATE("Default scale factor"), gopts.video_scale, 1, 6),
|
||||||
BOOLOPT("Display/Stretch", "RetainAspect", wxTRANSLATE("Retain aspect ratio when resizing"), gopts.retain_aspect),
|
BOOLOPT("Display/Stretch", "RetainAspect", wxTRANSLATE("Retain aspect ratio when resizing"), gopts.retain_aspect),
|
||||||
|
|
||||||
/// GB
|
/// GB
|
||||||
|
@ -523,6 +527,13 @@ void load_opts()
|
||||||
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), opt.curint, opt.opt, opt.min, opt.max);
|
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), opt.curint, opt.opt, opt.min, opt.max);
|
||||||
} else
|
} else
|
||||||
*opt.intopt = opt.curint;
|
*opt.intopt = opt.curint;
|
||||||
|
} else if (opt.doubleopt) {
|
||||||
|
cfg->Read(opt.opt, &opt.curdouble, *opt.doubleopt);
|
||||||
|
|
||||||
|
if (opt.curdouble < opt.min || opt.curdouble > opt.max) {
|
||||||
|
wxLogWarning(_("Invalid value %f for option %s; valid values are %f - %f"), opt.curdouble, opt.opt, opt.min, opt.max);
|
||||||
|
} else
|
||||||
|
*opt.doubleopt = opt.curdouble;
|
||||||
} else if (opt.boolopt) {
|
} else if (opt.boolopt) {
|
||||||
cfg->Read(opt.opt, opt.boolopt, *opt.boolopt);
|
cfg->Read(opt.opt, opt.boolopt, *opt.boolopt);
|
||||||
opt.curbool = *opt.boolopt;
|
opt.curbool = *opt.boolopt;
|
||||||
|
@ -648,6 +659,9 @@ void update_opts()
|
||||||
} else if (opt.intopt) {
|
} else if (opt.intopt) {
|
||||||
if (*opt.intopt != opt.curint)
|
if (*opt.intopt != opt.curint)
|
||||||
cfg->Write(opt.opt, (opt.curint = *opt.intopt));
|
cfg->Write(opt.opt, (opt.curint = *opt.intopt));
|
||||||
|
} else if (opt.doubleopt) {
|
||||||
|
if (*opt.doubleopt != opt.curdouble)
|
||||||
|
cfg->Write(opt.opt, (opt.curdouble = *opt.doubleopt));
|
||||||
} else if (opt.boolopt) {
|
} else if (opt.boolopt) {
|
||||||
if (*opt.boolopt != opt.curbool)
|
if (*opt.boolopt != opt.curbool)
|
||||||
cfg->Write(opt.opt, (opt.curbool = *opt.boolopt));
|
cfg->Write(opt.opt, (opt.curbool = *opt.boolopt));
|
||||||
|
@ -805,6 +819,14 @@ bool opt_set(const wxChar* name, const wxChar* val)
|
||||||
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), ival, name, opt->min, opt->max);
|
wxLogWarning(_("Invalid value %d for option %s; valid values are %d - %d"), ival, name, opt->min, opt->max);
|
||||||
else
|
else
|
||||||
*opt->intopt = ival;
|
*opt->intopt = ival;
|
||||||
|
} else if (opt->doubleopt) {
|
||||||
|
const wxString s(val);
|
||||||
|
double dval;
|
||||||
|
|
||||||
|
if (!s.ToDouble(&dval) || dval < opt->min || dval > opt->max)
|
||||||
|
wxLogWarning(_("Invalid value %f for option %s; valid values are %f - %f"), dval, name, opt->min, opt->max);
|
||||||
|
else
|
||||||
|
*opt->doubleopt = dval;
|
||||||
} else {
|
} else {
|
||||||
// GB/Palette[0-2] is virtual
|
// GB/Palette[0-2] is virtual
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ extern struct opts_t {
|
||||||
wxVideoMode fs_mode;
|
wxVideoMode fs_mode;
|
||||||
int max_threads;
|
int max_threads;
|
||||||
int render_method;
|
int render_method;
|
||||||
int video_scale;
|
double video_scale;
|
||||||
bool retain_aspect;
|
bool retain_aspect;
|
||||||
bool keep_on_top;
|
bool keep_on_top;
|
||||||
|
|
||||||
|
@ -90,11 +90,13 @@ extern struct opt_desc {
|
||||||
wxString* stropt;
|
wxString* stropt;
|
||||||
int* intopt;
|
int* intopt;
|
||||||
const wxChar* enumvals;
|
const wxChar* enumvals;
|
||||||
int min, max;
|
double min, max;
|
||||||
bool* boolopt;
|
bool* boolopt;
|
||||||
|
double* doubleopt;
|
||||||
// current configured value
|
// current configured value
|
||||||
wxString curstr;
|
wxString curstr;
|
||||||
int curint;
|
int curint;
|
||||||
|
double curdouble;
|
||||||
#define curbool curint
|
#define curbool curint
|
||||||
} opts[];
|
} opts[];
|
||||||
extern const int num_opts;
|
extern const int num_opts;
|
||||||
|
|
182
src/wx/panel.cpp
182
src/wx/panel.cpp
|
@ -1,5 +1,10 @@
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
|
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "../../version.h"
|
#include "../../version.h"
|
||||||
#include "../common/ConfigManager.h"
|
#include "../common/ConfigManager.h"
|
||||||
#include "../common/Patch.h"
|
#include "../common/Patch.h"
|
||||||
|
@ -13,6 +18,19 @@
|
||||||
|
|
||||||
int emulating;
|
int emulating;
|
||||||
|
|
||||||
|
double HiDPIAware::HiDPIScaleFactor()
|
||||||
|
{
|
||||||
|
if (hidpi_scale_factor == 0) {
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
hidpi_scale_factor = [[(NSView*)GetWindow()->GetHandle() window] backingScaleFactor];
|
||||||
|
#else
|
||||||
|
hidpi_scale_factor = 1.0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return hidpi_scale_factor;
|
||||||
|
}
|
||||||
|
|
||||||
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
IMPLEMENT_DYNAMIC_CLASS(GameArea, wxPanel)
|
||||||
|
|
||||||
GameArea::GameArea()
|
GameArea::GameArea()
|
||||||
|
@ -704,9 +722,12 @@ void GameArea::DelBorder()
|
||||||
void GameArea::AdjustMinSize()
|
void GameArea::AdjustMinSize()
|
||||||
{
|
{
|
||||||
wxWindow* frame = wxGetApp().frame;
|
wxWindow* frame = wxGetApp().frame;
|
||||||
|
double hidpi_scale_factor = HiDPIScaleFactor();
|
||||||
|
|
||||||
// note: could safely set min size to 1x or less regardless of video_scale
|
// note: could safely set min size to 1x or less regardless of video_scale
|
||||||
// but setting it to scaled size makes resizing to default easier
|
// but setting it to scaled size makes resizing to default easier
|
||||||
wxSize sz(basic_width * gopts.video_scale, basic_height * gopts.video_scale);
|
wxSize sz((std::ceil(basic_width * gopts.video_scale) / hidpi_scale_factor),
|
||||||
|
(std::ceil(basic_height * gopts.video_scale) / hidpi_scale_factor));
|
||||||
SetMinSize(sz);
|
SetMinSize(sz);
|
||||||
#if wxCHECK_VERSION(2, 8, 8)
|
#if wxCHECK_VERSION(2, 8, 8)
|
||||||
sz = frame->ClientToWindowSize(sz);
|
sz = frame->ClientToWindowSize(sz);
|
||||||
|
@ -719,7 +740,11 @@ void GameArea::AdjustMinSize()
|
||||||
void GameArea::LowerMinSize()
|
void GameArea::LowerMinSize()
|
||||||
{
|
{
|
||||||
wxWindow* frame = wxGetApp().frame;
|
wxWindow* frame = wxGetApp().frame;
|
||||||
wxSize sz(basic_width, basic_height);
|
double hidpi_scale_factor = HiDPIScaleFactor();
|
||||||
|
|
||||||
|
wxSize sz(std::ceil(basic_width / hidpi_scale_factor),
|
||||||
|
std::ceil(basic_height / hidpi_scale_factor));
|
||||||
|
|
||||||
SetMinSize(sz);
|
SetMinSize(sz);
|
||||||
// do not take decorations into account
|
// do not take decorations into account
|
||||||
frame->SetMinSize(sz);
|
frame->SetMinSize(sz);
|
||||||
|
@ -732,7 +757,9 @@ void GameArea::AdjustSize(bool force)
|
||||||
if (fullscreen)
|
if (fullscreen)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const wxSize newsz(basic_width * gopts.video_scale, basic_height * gopts.video_scale);
|
double hidpi_scale_factor = HiDPIScaleFactor();
|
||||||
|
const wxSize newsz((std::ceil(basic_width * gopts.video_scale) / hidpi_scale_factor),
|
||||||
|
(std::ceil(basic_height * gopts.video_scale) / hidpi_scale_factor));
|
||||||
|
|
||||||
if (!force) {
|
if (!force) {
|
||||||
wxSize sz = GetSize();
|
wxSize sz = GetSize();
|
||||||
|
@ -756,6 +783,15 @@ void GameArea::ShowFullScreen(bool full)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some kbd accels can send a menu open event without a close event,
|
||||||
|
// this happens on Mac in HiDPI mode for the fullscreen toggle accel.
|
||||||
|
main_frame->SetMenusOpened(false);
|
||||||
|
|
||||||
|
// on Mac maximize is native fullscreen, so ignore fullscreen requests
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
if (full && main_frame->IsMaximized()) return;
|
||||||
|
#endif
|
||||||
|
|
||||||
fullscreen = full;
|
fullscreen = full;
|
||||||
|
|
||||||
// just in case screen mode is going to change, go ahead and preemptively
|
// just in case screen mode is going to change, go ahead and preemptively
|
||||||
|
@ -1300,12 +1336,12 @@ DrawingPanel::DrawingPanel(int _width, int _height)
|
||||||
// unused (as is rpi->Handle)
|
// unused (as is rpi->Handle)
|
||||||
_rpi->Output = (RENDPLUG_Output)filt_plugin.GetSymbol(wxT("RenderPluginOutput"));
|
_rpi->Output = (RENDPLUG_Output)filt_plugin.GetSymbol(wxT("RenderPluginOutput"));
|
||||||
|
|
||||||
scale = (_rpi->Flags & RPI_OUT_SCLMSK) >> RPI_OUT_SCLSH;
|
scale *= (_rpi->Flags & RPI_OUT_SCLMSK) >> RPI_OUT_SCLSH;
|
||||||
rpi = _rpi;
|
rpi = _rpi;
|
||||||
gopts.filter = FF_PLUGIN; // now that there is a valid plugin
|
gopts.filter = FF_PLUGIN; // now that there is a valid plugin
|
||||||
} while (0);
|
} while (0);
|
||||||
} else {
|
} else {
|
||||||
scale = builtin_ff_scale(gopts.filter);
|
scale *= builtin_ff_scale(gopts.filter);
|
||||||
#define out_16 (systemColorDepth == 16)
|
#define out_16 (systemColorDepth == 16)
|
||||||
systemColorDepth = 32;
|
systemColorDepth = 32;
|
||||||
}
|
}
|
||||||
|
@ -1336,6 +1372,11 @@ DrawingPanel::DrawingPanel(int _width, int _height)
|
||||||
utilUpdateSystemColorMaps(false);
|
utilUpdateSystemColorMaps(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DrawingPanel::DrawingPanelInit()
|
||||||
|
{
|
||||||
|
did_init = true;
|
||||||
|
}
|
||||||
|
|
||||||
void DrawingPanel::PaintEv(wxPaintEvent& ev)
|
void DrawingPanel::PaintEv(wxPaintEvent& ev)
|
||||||
{
|
{
|
||||||
wxPaintDC dc(GetWindow());
|
wxPaintDC dc(GetWindow());
|
||||||
|
@ -1388,7 +1429,8 @@ public:
|
||||||
|
|
||||||
// Set these params before running
|
// Set these params before running
|
||||||
int nthreads, threadno;
|
int nthreads, threadno;
|
||||||
int width, height, scale;
|
int width, height;
|
||||||
|
double scale;
|
||||||
const RENDER_PLUGIN_INFO* rpi;
|
const RENDER_PLUGIN_INFO* rpi;
|
||||||
uint8_t *dst, *delta;
|
uint8_t *dst, *delta;
|
||||||
|
|
||||||
|
@ -1407,10 +1449,10 @@ public:
|
||||||
int instride = (width + inrb) * inbpp;
|
int instride = (width + inrb) * inbpp;
|
||||||
int outbpp = out_16 ? 2 : systemColorDepth == 24 ? 3 : 4;
|
int outbpp = out_16 ? 2 : systemColorDepth == 24 ? 3 : 4;
|
||||||
int outrb = systemColorDepth == 24 ? 0 : 4;
|
int outrb = systemColorDepth == 24 ? 0 : 4;
|
||||||
int outstride = width * outbpp * scale + outrb;
|
int outstride = std::ceil(width * outbpp * scale) + outrb;
|
||||||
delta += instride * procy;
|
delta += instride * procy;
|
||||||
// + 1 for stupid top border
|
// + 1 for stupid top border
|
||||||
dst += outstride * (procy + 1) * scale;
|
dst += (int)std::ceil(outstride * (procy + 1) * scale);
|
||||||
|
|
||||||
while (nthreads == 1 || sig.Wait() == wxCOND_NO_ERROR) {
|
while (nthreads == 1 || sig.Wait() == wxCOND_NO_ERROR) {
|
||||||
if (!src /* && nthreads > 1 */) {
|
if (!src /* && nthreads > 1 */) {
|
||||||
|
@ -1561,10 +1603,10 @@ public:
|
||||||
outdesc.SrcH = height; // + scale / 2
|
outdesc.SrcH = height; // + scale / 2
|
||||||
outdesc.DstPtr = dst;
|
outdesc.DstPtr = dst;
|
||||||
outdesc.DstPitch = outstride;
|
outdesc.DstPitch = outstride;
|
||||||
outdesc.DstW = width * scale;
|
outdesc.DstW = std::ceil(width * scale);
|
||||||
// on the other hand, there is at least 1 line below, so I'll add
|
// on the other hand, there is at least 1 line below, so I'll add
|
||||||
// that to dest in case safety checks in plugin use < instead of <=
|
// that to dest in case safety checks in plugin use < instead of <=
|
||||||
outdesc.DstH = height * scale + 1; // + scale * (scale / 2)
|
outdesc.DstH = std::ceil(height * scale) + 1; // + scale * (scale / 2)
|
||||||
rpi->Output(&outdesc);
|
rpi->Output(&outdesc);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1588,18 +1630,18 @@ void DrawingPanel::DrawArea(uint8_t** data)
|
||||||
// if not filtering, we still retain current image for redraws
|
// if not filtering, we still retain current image for redraws
|
||||||
int outbpp = out_16 ? 2 : systemColorDepth == 24 ? 3 : 4;
|
int outbpp = out_16 ? 2 : systemColorDepth == 24 ? 3 : 4;
|
||||||
int outrb = systemColorDepth == 24 ? 0 : 4;
|
int outrb = systemColorDepth == 24 ? 0 : 4;
|
||||||
int outstride = width * outbpp * scale + outrb;
|
int outstride = std::ceil(width * outbpp * scale) + outrb;
|
||||||
|
|
||||||
if (!pixbuf2) {
|
if (!pixbuf2) {
|
||||||
int allocstride = outstride, alloch = height;
|
int allocstride = outstride, alloch = height;
|
||||||
|
|
||||||
// gb may write borders, so allocate enough for them
|
// gb may write borders, so allocate enough for them
|
||||||
if (width == GameArea::GBWidth && height == GameArea::GBHeight) {
|
if (width == GameArea::GBWidth && height == GameArea::GBHeight) {
|
||||||
allocstride = GameArea::SGBWidth * outbpp * scale + outrb;
|
allocstride = std::ceil(GameArea::SGBWidth * outbpp * scale) + outrb;
|
||||||
alloch = GameArea::SGBHeight;
|
alloch = GameArea::SGBHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixbuf2 = (uint8_t*)calloc(allocstride, (alloch + 2) * scale);
|
pixbuf2 = (uint8_t*)calloc(allocstride, std::ceil((alloch + 2) * scale));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gopts.filter == FF_NONE) {
|
if (gopts.filter == FF_NONE) {
|
||||||
|
@ -1701,7 +1743,7 @@ void DrawingPanel::DrawArea(uint8_t** data)
|
||||||
if (!disableStatusMessages && !panel->osdtext.empty()) {
|
if (!disableStatusMessages && !panel->osdtext.empty()) {
|
||||||
if (systemGetClock() - panel->osdtime < OSD_TIME) {
|
if (systemGetClock() - panel->osdtime < OSD_TIME) {
|
||||||
std::string message = ToString(panel->osdtext);
|
std::string message = ToString(panel->osdtext);
|
||||||
int linelen = (width * scale - 20) / 8;
|
int linelen = std::ceil(width * scale - 20) / 8;
|
||||||
int nlines = (message.length() + linelen - 1) / linelen;
|
int nlines = (message.length() + linelen - 1) / linelen;
|
||||||
int cury = height - 14 - nlines * 10;
|
int cury = height - 14 - nlines * 10;
|
||||||
char* ptr = const_cast<char*>(message.c_str());
|
char* ptr = const_cast<char*>(message.c_str());
|
||||||
|
@ -1862,6 +1904,7 @@ BasicDrawingPanel::BasicDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
if (gopts.filter == FF_NONE && gopts.ifb == IFB_NONE)
|
if (gopts.filter == FF_NONE && gopts.ifb == IFB_NONE)
|
||||||
// changing from 32 to 24 does not require regenerating color tables
|
// changing from 32 to 24 does not require regenerating color tables
|
||||||
systemColorDepth = 24;
|
systemColorDepth = 24;
|
||||||
|
if (!did_init) DrawingPanelInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
|
@ -1874,12 +1917,12 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
bm = new wxBitmap(im);
|
bm = new wxBitmap(im);
|
||||||
} else if (out_16) {
|
} else if (out_16) {
|
||||||
// scaled by filters, top/right borders, transform to 24-bit
|
// scaled by filters, top/right borders, transform to 24-bit
|
||||||
wxImage im(width * scale, height * scale, false);
|
wxImage im(std::ceil(width * scale), std::ceil(height * scale), false);
|
||||||
uint16_t* src = (uint16_t*)todraw + (width + 2) * scale; // skip top border
|
uint16_t* src = (uint16_t*)todraw + (int)std::ceil((width + 2) * scale); // skip top border
|
||||||
uint8_t* dst = im.GetData();
|
uint8_t* dst = im.GetData();
|
||||||
|
|
||||||
for (int y = 0; y < height * scale; y++) {
|
for (int y = 0; y < std::ceil(height * scale); y++) {
|
||||||
for (int x = 0; x < width * scale; x++, src++) {
|
for (int x = 0; x < std::ceil(width * scale); x++, src++) {
|
||||||
*dst++ = ((*src >> systemRedShift) & 0x1f) << 3;
|
*dst++ = ((*src >> systemRedShift) & 0x1f) << 3;
|
||||||
*dst++ = ((*src >> systemGreenShift) & 0x1f) << 3;
|
*dst++ = ((*src >> systemGreenShift) & 0x1f) << 3;
|
||||||
*dst++ = ((*src >> systemBlueShift) & 0x1f) << 3;
|
*dst++ = ((*src >> systemBlueShift) & 0x1f) << 3;
|
||||||
|
@ -1892,12 +1935,12 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
} else // 32-bit
|
} else // 32-bit
|
||||||
{
|
{
|
||||||
// scaled by filters, top/right borders, transform to 24-bit
|
// scaled by filters, top/right borders, transform to 24-bit
|
||||||
wxImage im(width * scale, height * scale, false);
|
wxImage im(std::ceil(width * scale), std::ceil(height * scale), false);
|
||||||
uint32_t* src = (uint32_t*)todraw + (width + 1) * scale; // skip top border
|
uint32_t* src = (uint32_t*)todraw + (int)std::ceil((width + 1) * scale); // skip top border
|
||||||
uint8_t* dst = im.GetData();
|
uint8_t* dst = im.GetData();
|
||||||
|
|
||||||
for (int y = 0; y < height * scale; y++) {
|
for (int y = 0; y < std::ceil(height * scale); y++) {
|
||||||
for (int x = 0; x < width * scale; x++, src++) {
|
for (int x = 0; x < std::ceil(width * scale); x++, src++) {
|
||||||
*dst++ = *src >> (systemRedShift - 3);
|
*dst++ = *src >> (systemRedShift - 3);
|
||||||
*dst++ = *src >> (systemGreenShift - 3);
|
*dst++ = *src >> (systemGreenShift - 3);
|
||||||
*dst++ = *src >> (systemBlueShift - 3);
|
*dst++ = *src >> (systemBlueShift - 3);
|
||||||
|
@ -1912,8 +1955,8 @@ void BasicDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
int w, h;
|
int w, h;
|
||||||
GetClientSize(&w, &h);
|
GetClientSize(&w, &h);
|
||||||
sx = (double)w / (double)(width * scale);
|
sx = w / (width * scale);
|
||||||
sy = (double)h / (double)(height * scale);
|
sy = h / (height * scale);
|
||||||
dc.SetUserScale(sx, sy);
|
dc.SetUserScale(sx, sy);
|
||||||
dc.DrawBitmap(*bm, 0, 0);
|
dc.DrawBitmap(*bm, 0, 0);
|
||||||
delete bm;
|
delete bm;
|
||||||
|
@ -1936,7 +1979,6 @@ IMPLEMENT_CLASS2(GLDrawingPanel, DrawingPanel, wxGLCanvas)
|
||||||
// this would be easier in 2.9
|
// this would be easier in 2.9
|
||||||
BEGIN_EVENT_TABLE(GLDrawingPanel, wxGLCanvas)
|
BEGIN_EVENT_TABLE(GLDrawingPanel, wxGLCanvas)
|
||||||
EVT_PAINT(GLDrawingPanel::PaintEv2)
|
EVT_PAINT(GLDrawingPanel::PaintEv2)
|
||||||
EVT_SIZE(GLDrawingPanel::OnSize)
|
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
// This is supposed to be the default, but DOUBLEBUFFER doesn't seem to be
|
// This is supposed to be the default, but DOUBLEBUFFER doesn't seem to be
|
||||||
|
@ -1945,7 +1987,7 @@ static int glopts[] = {
|
||||||
WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0
|
WX_GL_RGBA, WX_GL_DOUBLEBUFFER, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
#define glc wxGLCanvas
|
#define glc wxGLCanvas
|
||||||
#else
|
#else
|
||||||
// shuffled parms for 2.9 indicates non-auto glcontext
|
// shuffled parms for 2.9 indicates non-auto glcontext
|
||||||
|
@ -1957,23 +1999,30 @@ GLDrawingPanel::GLDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
: glc(parent, wxID_ANY, glopts, wxPoint(0, 0), parent->GetSize(),
|
: glc(parent, wxID_ANY, glopts, wxPoint(0, 0), parent->GetSize(),
|
||||||
wxFULL_REPAINT_ON_RESIZE)
|
wxFULL_REPAINT_ON_RESIZE)
|
||||||
, DrawingPanel(_width, _height)
|
, DrawingPanel(_width, _height)
|
||||||
, did_init(false)
|
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
|
||||||
, ctx(this)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
|
#ifdef __WXMAC__
|
||||||
|
[(NSView *)GetHandle() setWantsBestResolutionOpenGLSurface:YES];
|
||||||
|
#endif
|
||||||
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
|
ctx = new wxGLContext(this);
|
||||||
|
SetCurrent(*ctx);
|
||||||
|
#endif
|
||||||
|
if (!did_init) DrawingPanelInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLDrawingPanel::~GLDrawingPanel()
|
GLDrawingPanel::~GLDrawingPanel()
|
||||||
{
|
{
|
||||||
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
|
delete ctx;
|
||||||
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
// this should be automatically deleted w/ context
|
// this should be automatically deleted w/ context
|
||||||
// it's also unsafe if panel no longer displayed
|
// it's also unsafe if panel no longer displayed
|
||||||
if (did_init)
|
if (did_init)
|
||||||
{
|
{
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
SetContext(ctx);
|
SetContext(*ctx);
|
||||||
#else
|
#else
|
||||||
SetContext();
|
SetContext();
|
||||||
#endif
|
#endif
|
||||||
|
@ -1984,8 +2033,21 @@ GLDrawingPanel::~GLDrawingPanel()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDrawingPanel::Init()
|
void GLDrawingPanel::DrawingPanelInit()
|
||||||
{
|
{
|
||||||
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
|
SetCurrent(*ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DrawingPanel::DrawingPanelInit();
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// you can use this to check that the gl surface is indeed high res
|
||||||
|
GLint m_viewport[4];
|
||||||
|
glGetIntegerv(GL_VIEWPORT, m_viewport);
|
||||||
|
vbamDebug("GL VIEWPORT: %d, %d, %d, %d", m_viewport[0], m_viewport[1], m_viewport[2], m_viewport[3]);
|
||||||
|
#endif
|
||||||
|
|
||||||
// taken from GTK front end almost verbatim
|
// taken from GTK front end almost verbatim
|
||||||
glDisable(GL_CULL_FACE);
|
glDisable(GL_CULL_FACE);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
@ -2013,12 +2075,13 @@ void GLDrawingPanel::Init()
|
||||||
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
|
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||||
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
|
gopts.bilinear ? GL_LINEAR : GL_NEAREST);
|
||||||
|
|
||||||
#define int_fmt out_16 ? GL_RGB5 : GL_RGB
|
#define int_fmt out_16 ? GL_RGB5 : GL_RGB
|
||||||
#define tex_fmt out_16 ? GL_BGRA : GL_RGBA, \
|
#define tex_fmt out_16 ? GL_BGRA : GL_RGBA, \
|
||||||
out_16 ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_BYTE
|
out_16 ? GL_UNSIGNED_SHORT_1_5_5_5_REV : GL_UNSIGNED_BYTE
|
||||||
#if 0
|
#if 0
|
||||||
texsize = width > height ? width : height;
|
texsize = width > height ? width : height;
|
||||||
texsize *= scale;
|
texsize = std::ceil(texsize * scale);
|
||||||
// texsize = 1 << ffs(texsize);
|
// texsize = 1 << ffs(texsize);
|
||||||
texsize = texsize | (texsize >> 1);
|
texsize = texsize | (texsize >> 1);
|
||||||
texsize = texsize | (texsize >> 2);
|
texsize = texsize | (texsize >> 2);
|
||||||
|
@ -2029,7 +2092,7 @@ void GLDrawingPanel::Init()
|
||||||
#else
|
#else
|
||||||
// but really, most cards support non-p2 and rect
|
// but really, most cards support non-p2 and rect
|
||||||
// if not, use cairo or wx renderer
|
// if not, use cairo or wx renderer
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, width * scale, height * scale, 0, tex_fmt, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, std::ceil(width * scale), std::ceil(height * scale), 0, tex_fmt, NULL);
|
||||||
#endif
|
#endif
|
||||||
glClearColor(0.0, 0.0, 0.0, 1.0);
|
glClearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
// non-portable vsync code
|
// non-portable vsync code
|
||||||
|
@ -2062,22 +2125,21 @@ void GLDrawingPanel::Init()
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
did_init = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
{
|
{
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
#if wxCHECK_VERSION(2, 9, 0)
|
||||||
SetCurrent(ctx);
|
SetCurrent(*ctx);
|
||||||
#else
|
#else
|
||||||
SetCurrent();
|
SetCurrent();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!did_init)
|
if (!did_init)
|
||||||
Init();
|
DrawingPanelInit();
|
||||||
|
|
||||||
if (todraw) {
|
if (todraw) {
|
||||||
int rowlen = width * scale + (out_16 ? 2 : 1);
|
int rowlen = std::ceil(width * scale) + (out_16 ? 2 : 1);
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlen);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlen);
|
||||||
#if wxBYTE_ORDER == wxBIG_ENDIAN
|
#if wxBYTE_ORDER == wxBIG_ENDIAN
|
||||||
|
|
||||||
|
@ -2086,30 +2148,14 @@ void GLDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, width * scale, height * scale,
|
glTexImage2D(GL_TEXTURE_2D, 0, int_fmt, std::ceil(width * scale), (int)std::ceil(height * scale),
|
||||||
0, tex_fmt, todraw + rowlen * (out_16 ? 2 : 4) * scale);
|
0, tex_fmt, todraw + (int)std::ceil(rowlen * (out_16 ? 2 : 4) * scale));
|
||||||
glCallList(vlist);
|
glCallList(vlist);
|
||||||
} else
|
} else
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
SwapBuffers();
|
SwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDrawingPanel::OnSize(wxSizeEvent& ev)
|
|
||||||
{
|
|
||||||
if (!did_init)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int w, h;
|
|
||||||
GetClientSize(&w, &h);
|
|
||||||
#if wxCHECK_VERSION(2, 9, 0) || !defined(__WXMAC__)
|
|
||||||
SetCurrent(ctx);
|
|
||||||
#else
|
|
||||||
SetCurrent();
|
|
||||||
#endif
|
|
||||||
glViewport(0, 0, w, h);
|
|
||||||
ev.Skip(); // propagate to parent
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NO_CAIRO
|
#ifndef NO_CAIRO
|
||||||
|
@ -2141,6 +2187,8 @@ CairoDrawingPanel::CairoDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
|
|
||||||
// FIXME: should be "true" for GBA carts if lcd mode selected
|
// FIXME: should be "true" for GBA carts if lcd mode selected
|
||||||
utilUpdateSystemColorMaps(false);
|
utilUpdateSystemColorMaps(false);
|
||||||
|
|
||||||
|
if (!did_init) DrawingPanelInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
CairoDrawingPanel::~CairoDrawingPanel()
|
CairoDrawingPanel::~CairoDrawingPanel()
|
||||||
|
@ -2194,8 +2242,8 @@ void CairoDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
else {
|
else {
|
||||||
if (!conv_surf)
|
if (!conv_surf)
|
||||||
conv_surf = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
|
conv_surf = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
|
||||||
width * scale,
|
std::ceil(width * scale),
|
||||||
height * scale);
|
std::ceil(height * scale));
|
||||||
|
|
||||||
if (!conv_surf) {
|
if (!conv_surf) {
|
||||||
wxLogError(_("Cannot create conversion buffer"));
|
wxLogError(_("Cannot create conversion buffer"));
|
||||||
|
@ -2203,11 +2251,11 @@ void CairoDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
}
|
}
|
||||||
|
|
||||||
surf = cairo_surface_reference(conv_surf);
|
surf = cairo_surface_reference(conv_surf);
|
||||||
uint16_t* src = (uint16_t*)todraw + (width + 2) * scale; // skip top border
|
uint16_t* src = (uint16_t*)todraw + (int)std::ceil((width + 2) * scale); // skip top border
|
||||||
uint32_t* dst = (uint32_t*)cairo_image_surface_get_data(surf);
|
uint32_t* dst = (uint32_t*)cairo_image_surface_get_data(surf);
|
||||||
|
|
||||||
for (int y = 0; y < height * scale; y++) {
|
for (int y = 0; y < std::ceil(height * scale); y++) {
|
||||||
for (int x = 0; x < width * scale; x++, src++) {
|
for (int x = 0; x < std::ceil(width * scale); x++, src++) {
|
||||||
*dst++ = (((*src >> systemRedShift) & 0x1f) << 19) | (((*src >> systemGreenShift) & 0x1f) << 11) | (((*src >> systemBlueShift) & 0x1f) << 3);
|
*dst++ = (((*src >> systemRedShift) & 0x1f) << 19) | (((*src >> systemGreenShift) & 0x1f) << 11) | (((*src >> systemBlueShift) & 0x1f) << 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2222,8 +2270,8 @@ void CairoDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
double sx, sy;
|
double sx, sy;
|
||||||
int w, h;
|
int w, h;
|
||||||
GetClientSize(&w, &h);
|
GetClientSize(&w, &h);
|
||||||
sx = (double)width / (double)w;
|
sx = (double)width / w;
|
||||||
sy = (double)height / (double)h;
|
sy = (double)height / h;
|
||||||
cairo_matrix_t mat;
|
cairo_matrix_t mat;
|
||||||
cairo_matrix_init_scale(&mat, sx, sy);
|
cairo_matrix_init_scale(&mat, sx, sy);
|
||||||
cairo_pattern_set_matrix(pat, &mat);
|
cairo_pattern_set_matrix(pat, &mat);
|
||||||
|
@ -2253,6 +2301,7 @@ DXDrawingPanel::DXDrawingPanel(wxWindow* parent, int _width, int _height)
|
||||||
, DrawingPanel(_width, _height)
|
, DrawingPanel(_width, _height)
|
||||||
{
|
{
|
||||||
// FIXME: implement
|
// FIXME: implement
|
||||||
|
if (!did_init) DrawingPanelInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DXDrawingPanel::DrawArea(wxWindowDC& dc)
|
void DXDrawingPanel::DrawArea(wxWindowDC& dc)
|
||||||
|
@ -2401,7 +2450,8 @@ void GameArea::HidePointer()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// FIXME: make time configurable
|
// FIXME: make time configurable
|
||||||
if (fullscreen || (systemGetClock() - mouse_active_time) > 3000) {
|
if ((fullscreen || (systemGetClock() - mouse_active_time) > 3000) &&
|
||||||
|
!(main_frame && (main_frame->MenusOpened() || main_frame->DialogOpened()))) {
|
||||||
pointer_blanked = true;
|
pointer_blanked = true;
|
||||||
SetCursor(wxCursor(wxCURSOR_BLANK));
|
SetCursor(wxCursor(wxCURSOR_BLANK));
|
||||||
|
|
||||||
|
|
|
@ -30,9 +30,31 @@
|
||||||
IMPLEMENT_APP(wxvbamApp)
|
IMPLEMENT_APP(wxvbamApp)
|
||||||
IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame)
|
IMPLEMENT_DYNAMIC_CLASS(MainFrame, wxFrame)
|
||||||
|
|
||||||
|
// For spewing stuff to terminal when debugging
|
||||||
|
void vbamDebug(const char* format, ...) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
wxLog *active_log = wxLog::GetActiveTarget();
|
||||||
|
|
||||||
|
wxLogStderr log_to_stderr;
|
||||||
|
|
||||||
|
wxLog::SetActiveTarget(&log_to_stderr);
|
||||||
|
|
||||||
|
va_list argptr;
|
||||||
|
va_start(argptr, format);
|
||||||
|
wxVLogDebug(format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
|
||||||
|
wxLog::SetActiveTarget(active_log);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// generate config file path
|
// generate config file path
|
||||||
static void get_config_path(wxPathList& path, bool exists = true)
|
static void get_config_path(wxPathList& path, bool exists = true)
|
||||||
{
|
{
|
||||||
|
// we want paths with "visualboyadvance-m" not "vbam", so change appname temporarily
|
||||||
|
wxString current_app_name = wxGetApp().GetAppName();
|
||||||
|
wxGetApp().SetAppName(_("visualboyadvance-m"));
|
||||||
|
|
||||||
// local config dir first, then global
|
// local config dir first, then global
|
||||||
// locale-specific res first, then main
|
// locale-specific res first, then main
|
||||||
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
wxStandardPathsBase& stdp = wxStandardPaths::Get();
|
||||||
|
@ -44,6 +66,15 @@ static void get_config_path(wxPathList& path, bool exists = true)
|
||||||
if ((wxDirExists(s) && wxIsWritable(s)) || ((!exists || !wxDirExists(s)) && parent.IsDirWritable())) \
|
if ((wxDirExists(s) && wxIsWritable(s)) || ((!exists || !wxDirExists(s)) && parent.IsDirWritable())) \
|
||||||
path.Add(s); \
|
path.Add(s); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
vbamDebug("GetUserLocalDataDir(): %s", static_cast<const char*>(stdp.GetUserLocalDataDir().utf8_str()));
|
||||||
|
vbamDebug("GetUserDataDir(): %s", static_cast<const char*>(stdp.GetUserDataDir().utf8_str()));
|
||||||
|
vbamDebug("GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()): %s", static_cast<const char*>(stdp.GetLocalizedResourcesDir(wxGetApp().locale.GetCanonicalName()).utf8_str()));
|
||||||
|
vbamDebug("GetResourcesDir(): %s", static_cast<const char*>(stdp.GetResourcesDir().utf8_str()));
|
||||||
|
vbamDebug("GetDataDir(): %s", static_cast<const char*>(stdp.GetDataDir().utf8_str()));
|
||||||
|
vbamDebug("GetLocalDataDir(): %s", static_cast<const char*>(stdp.GetLocalDataDir().utf8_str()));
|
||||||
|
vbamDebug("GetPluginsDir(): %s", static_cast<const char*>(stdp.GetPluginsDir().utf8_str()));
|
||||||
|
|
||||||
// NOTE: this does not support XDG (freedesktop.org) paths
|
// NOTE: this does not support XDG (freedesktop.org) paths
|
||||||
add_path(GetUserLocalDataDir());
|
add_path(GetUserLocalDataDir());
|
||||||
add_path(GetUserDataDir());
|
add_path(GetUserDataDir());
|
||||||
|
@ -52,6 +83,8 @@ static void get_config_path(wxPathList& path, bool exists = true)
|
||||||
add_path(GetDataDir());
|
add_path(GetDataDir());
|
||||||
add_path(GetLocalDataDir());
|
add_path(GetLocalDataDir());
|
||||||
add_path(GetPluginsDir());
|
add_path(GetPluginsDir());
|
||||||
|
|
||||||
|
wxGetApp().SetAppName(current_app_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tack_full_path(wxString& s, const wxString& app = wxEmptyString)
|
static void tack_full_path(wxString& s, const wxString& app = wxEmptyString)
|
||||||
|
@ -459,7 +492,7 @@ bool wxvbamApp::OnCmdLineParsed(wxCmdLineParser& cl)
|
||||||
|
|
||||||
for (int i = 0; i < num_opts; i++) {
|
for (int i = 0; i < num_opts; i++) {
|
||||||
wxPrintf(wxT("%s (%s"), opts[i].opt,
|
wxPrintf(wxT("%s (%s"), opts[i].opt,
|
||||||
opts[i].boolopt ? (const wxChar*)wxT("flag") : opts[i].stropt ? (const wxChar*)wxT("string") : opts[i].enumvals ? opts[i].enumvals : opts[i].intopt ? (const wxChar*)wxT("int") : (const wxChar*)wxT("string"));
|
opts[i].boolopt ? (const wxChar*)wxT("flag") : opts[i].stropt ? (const wxChar*)wxT("string") : opts[i].enumvals ? opts[i].enumvals : opts[i].intopt ? (const wxChar*)wxT("int") : opts[i].doubleopt ? (const wxChar*)wxT("decimal") : (const wxChar*)wxT("string"));
|
||||||
|
|
||||||
if (opts[i].enumvals) {
|
if (opts[i].enumvals) {
|
||||||
const wxChar* evx = wxGetTranslation(opts[i].enumvals);
|
const wxChar* evx = wxGetTranslation(opts[i].enumvals);
|
||||||
|
@ -557,6 +590,7 @@ EVT_DROP_FILES(MainFrame::OnDropFile)
|
||||||
// pause game if menu pops up
|
// pause game if menu pops up
|
||||||
EVT_MENU_OPEN(MainFrame::MenuPopped)
|
EVT_MENU_OPEN(MainFrame::MenuPopped)
|
||||||
EVT_MENU_CLOSE(MainFrame::MenuPopped)
|
EVT_MENU_CLOSE(MainFrame::MenuPopped)
|
||||||
|
EVT_MENU_HIGHLIGHT_ALL(MainFrame::MenuPopped)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
|
|
||||||
void MainFrame::OnActivate(wxActivateEvent& event)
|
void MainFrame::OnActivate(wxActivateEvent& event)
|
||||||
|
@ -950,7 +984,7 @@ int MainFrame::newest_state_slot()
|
||||||
// Removing the nesting counter may help, but on wxGTK I still get lockups.
|
// Removing the nesting counter may help, but on wxGTK I still get lockups.
|
||||||
void MainFrame::MenuPopped(wxMenuEvent& evt)
|
void MainFrame::MenuPopped(wxMenuEvent& evt)
|
||||||
{
|
{
|
||||||
bool popped = evt.GetEventType() == wxEVT_MENU_OPEN;
|
bool popped = evt.GetEventType() != wxEVT_MENU_CLOSE;
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
if (popped)
|
if (popped)
|
||||||
|
@ -985,6 +1019,21 @@ void MainFrame::MenuPopped(wxMenuEvent& evt)
|
||||||
panel->Resume();
|
panel->Resume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainFrame::SetMenusOpened(bool state)
|
||||||
|
{
|
||||||
|
if (state) {
|
||||||
|
menus_opened = 1;
|
||||||
|
paused = true;
|
||||||
|
panel->Pause();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
menus_opened = 0;
|
||||||
|
paused = false;
|
||||||
|
pause_next = false;
|
||||||
|
panel->Resume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ShowModal that also disables emulator loop
|
// ShowModal that also disables emulator loop
|
||||||
// uses dialog_opened as a nesting counter
|
// uses dialog_opened as a nesting counter
|
||||||
int MainFrame::ShowModal(wxDialog* dlg)
|
int MainFrame::ShowModal(wxDialog* dlg)
|
||||||
|
|
|
@ -38,6 +38,9 @@ void CheckPointer(T pointer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For spewing stuff to terminal
|
||||||
|
void vbamDebug(const char* format, ...);
|
||||||
|
|
||||||
/// Helper functions to convert WX's crazy string types to std::string
|
/// Helper functions to convert WX's crazy string types to std::string
|
||||||
|
|
||||||
inline std::string ToString(wxCharBuffer aString)
|
inline std::string ToString(wxCharBuffer aString)
|
||||||
|
@ -278,6 +281,12 @@ public:
|
||||||
// Check for online updates to the emulator
|
// Check for online updates to the emulator
|
||||||
bool CheckForUpdates();
|
bool CheckForUpdates();
|
||||||
|
|
||||||
|
virtual bool MenusOpened() { return menus_opened != 0; }
|
||||||
|
|
||||||
|
virtual void SetMenusOpened(bool state);
|
||||||
|
|
||||||
|
virtual bool DialogOpened() { return dialog_opened != 0; }
|
||||||
|
|
||||||
// required for building from xrc
|
// required for building from xrc
|
||||||
DECLARE_DYNAMIC_CLASS();
|
DECLARE_DYNAMIC_CLASS();
|
||||||
// required for event handling
|
// required for event handling
|
||||||
|
@ -333,6 +342,15 @@ private:
|
||||||
#include "cmdhandlers.h"
|
#include "cmdhandlers.h"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// helper class to add HiDPI awareness (mostly for Mac OS X)
|
||||||
|
class HiDPIAware {
|
||||||
|
public:
|
||||||
|
double HiDPIScaleFactor();
|
||||||
|
virtual wxWindow* GetWindow() = 0;
|
||||||
|
private:
|
||||||
|
double hidpi_scale_factor = 0;
|
||||||
|
};
|
||||||
|
|
||||||
// a helper class to avoid forgetting StopModal()
|
// a helper class to avoid forgetting StopModal()
|
||||||
class ModalPause {
|
class ModalPause {
|
||||||
public:
|
public:
|
||||||
|
@ -420,11 +438,13 @@ enum audioapi { AUD_SDL,
|
||||||
|
|
||||||
class DrawingPanel;
|
class DrawingPanel;
|
||||||
|
|
||||||
class GameArea : public wxPanel {
|
class GameArea : public wxPanel, public HiDPIAware {
|
||||||
public:
|
public:
|
||||||
GameArea();
|
GameArea();
|
||||||
virtual ~GameArea();
|
virtual ~GameArea();
|
||||||
|
|
||||||
|
virtual void SetMainFrame(MainFrame* parent) { main_frame = parent; }
|
||||||
|
|
||||||
// set to game title + link info
|
// set to game title + link info
|
||||||
void SetFrameTitle();
|
void SetFrameTitle();
|
||||||
|
|
||||||
|
@ -540,7 +560,11 @@ public:
|
||||||
void StartGamePlayback(const wxString& fname);
|
void StartGamePlayback(const wxString& fname);
|
||||||
void StopGamePlayback();
|
void StopGamePlayback();
|
||||||
|
|
||||||
|
virtual wxWindow* GetWindow() { return this; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
MainFrame* main_frame;
|
||||||
|
|
||||||
// set minsize of frame & panel to unscaled screen size
|
// set minsize of frame & panel to unscaled screen size
|
||||||
void LowerMinSize();
|
void LowerMinSize();
|
||||||
// set minsize of frame & panel to scaled screen size
|
// set minsize of frame & panel to scaled screen size
|
||||||
|
@ -599,7 +623,7 @@ extern bool cmditem_lt(const struct cmditem& cmd1, const struct cmditem& cmd2);
|
||||||
|
|
||||||
class FilterThread;
|
class FilterThread;
|
||||||
|
|
||||||
class DrawingPanel : public wxObject {
|
class DrawingPanel : public wxObject, public HiDPIAware {
|
||||||
public:
|
public:
|
||||||
DrawingPanel(int _width, int _height);
|
DrawingPanel(int _width, int _height);
|
||||||
~DrawingPanel();
|
~DrawingPanel();
|
||||||
|
@ -611,7 +635,10 @@ public:
|
||||||
protected:
|
protected:
|
||||||
virtual void DrawArea(wxWindowDC&) = 0;
|
virtual void DrawArea(wxWindowDC&) = 0;
|
||||||
virtual void DrawOSD(wxWindowDC&);
|
virtual void DrawOSD(wxWindowDC&);
|
||||||
int width, height, scale;
|
int width, height;
|
||||||
|
double scale;
|
||||||
|
virtual void DrawingPanelInit();
|
||||||
|
bool did_init = false;
|
||||||
uint8_t* todraw;
|
uint8_t* todraw;
|
||||||
uint8_t *pixbuf1, *pixbuf2;
|
uint8_t *pixbuf1, *pixbuf2;
|
||||||
FilterThread* threads;
|
FilterThread* threads;
|
||||||
|
|
Loading…
Reference in New Issue