2018-10-26 10:07:25 +00:00
// Why?
# define _WIN32_WINNT 0x0502
// The standard Windows includes.
# define WIN32_LEAN_AND_MEAN
# define NOMINMAX
# include <Windows.h>
# include <shellapi.h>
# include <wchar.h>
2019-04-12 10:16:44 +00:00
2020-04-29 08:50:28 +00:00
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2019-08-16 14:17:37 +00:00
extern " C "
{
// Let the NVIDIA and AMD know we want to use their graphics card
// on a dual graphics card system.
__declspec ( dllexport ) DWORD NvOptimusEnablement = 0x00000001 ;
__declspec ( dllexport ) int AmdPowerXpressRequestHighPerformance = 1 ;
2019-06-13 15:42:55 +00:00
}
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2018-10-26 10:07:25 +00:00
# include <stdlib.h>
# include <stdio.h>
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2019-08-16 14:17:37 +00:00
# include <GL/GL.h>
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2018-10-26 10:07:25 +00:00
# include <string>
# include <vector>
2018-10-26 14:25:27 +00:00
# include <boost/algorithm/string/split.hpp>
# include <boost/algorithm/string/classification.hpp>
2019-01-09 09:43:17 +00:00
# include <stdio.h>
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2018-10-26 14:25:27 +00:00
class OpenGLVersionCheck
{
public :
2019-08-16 14:17:37 +00:00
std : : string version ;
std : : string glsl_version ;
std : : string vendor ;
std : : string renderer ;
HINSTANCE hOpenGL = nullptr ;
bool success = false ;
bool load_opengl_dll ( )
{
MSG msg = { 0 } ;
WNDCLASS wc = { 0 } ;
wc . lpfnWndProc = OpenGLVersionCheck : : supports_opengl2_wndproc ;
wc . hInstance = ( HINSTANCE ) GetModuleHandle ( nullptr ) ;
wc . hbrBackground = ( HBRUSH ) ( COLOR_BACKGROUND ) ;
wc . lpszClassName = L " PrusaSlicer_opengl_version_check " ;
wc . style = CS_OWNDC ;
if ( RegisterClass ( & wc ) ) {
HWND hwnd = CreateWindowW ( wc . lpszClassName , L " PrusaSlicer_opengl_version_check " , WS_OVERLAPPEDWINDOW , 0 , 0 , 640 , 480 , 0 , 0 , wc . hInstance , ( LPVOID ) this ) ;
if ( hwnd ) {
message_pump_exit = false ;
while ( GetMessage ( & msg , NULL , 0 , 0 ) > 0 & & ! message_pump_exit )
DispatchMessage ( & msg ) ;
}
}
return this - > success ;
}
2022-05-24 08:20:02 +00:00
bool unload_opengl_dll ( )
2019-08-16 14:17:37 +00:00
{
2022-05-24 08:20:02 +00:00
if ( this - > hOpenGL ! = nullptr ) {
if ( : : FreeLibrary ( this - > hOpenGL ) ! = FALSE ) {
if ( : : GetModuleHandle ( L " opengl32.dll " ) = = nullptr ) {
printf ( " System OpenGL library successfully released \n " ) ;
this - > hOpenGL = nullptr ;
return true ;
}
else
printf ( " System OpenGL library released but not removed \n " ) ;
}
2019-08-16 14:17:37 +00:00
else
printf ( " System OpenGL library NOT released \n " ) ;
2022-05-24 08:20:02 +00:00
return false ;
2019-08-16 14:17:37 +00:00
}
2022-05-24 08:20:02 +00:00
return true ;
2019-08-16 14:17:37 +00:00
}
bool is_version_greater_or_equal_to ( unsigned int major , unsigned int minor ) const
{
// printf("is_version_greater_or_equal_to, version: %s\n", version.c_str());
std : : vector < std : : string > tokens ;
boost : : split ( tokens , version , boost : : is_any_of ( " " ) , boost : : token_compress_on ) ;
if ( tokens . empty ( ) )
return false ;
std : : vector < std : : string > numbers ;
boost : : split ( numbers , tokens [ 0 ] , boost : : is_any_of ( " . " ) , boost : : token_compress_on ) ;
unsigned int gl_major = 0 ;
unsigned int gl_minor = 0 ;
if ( numbers . size ( ) > 0 )
gl_major = : : atoi ( numbers [ 0 ] . c_str ( ) ) ;
if ( numbers . size ( ) > 1 )
gl_minor = : : atoi ( numbers [ 1 ] . c_str ( ) ) ;
// printf("Major: %d, minor: %d\n", gl_major, gl_minor);
if ( gl_major < major )
return false ;
else if ( gl_major > major )
return true ;
else
return gl_minor > = minor ;
}
2018-10-26 14:25:27 +00:00
protected :
2019-08-16 14:17:37 +00:00
static bool message_pump_exit ;
void check ( HWND hWnd )
{
hOpenGL = LoadLibraryExW ( L " opengl32.dll " , nullptr , 0 ) ;
if ( hOpenGL = = nullptr ) {
printf ( " Failed loading the system opengl32.dll \n " ) ;
return ;
}
typedef HGLRC ( WINAPI * Func_wglCreateContext ) ( HDC ) ;
typedef BOOL ( WINAPI * Func_wglMakeCurrent ) ( HDC , HGLRC ) ;
typedef BOOL ( WINAPI * Func_wglDeleteContext ) ( HGLRC ) ;
typedef GLubyte * ( WINAPI * Func_glGetString ) ( GLenum ) ;
Func_wglCreateContext wglCreateContext = ( Func_wglCreateContext ) GetProcAddress ( hOpenGL , " wglCreateContext " ) ;
Func_wglMakeCurrent wglMakeCurrent = ( Func_wglMakeCurrent ) GetProcAddress ( hOpenGL , " wglMakeCurrent " ) ;
Func_wglDeleteContext wglDeleteContext = ( Func_wglDeleteContext ) GetProcAddress ( hOpenGL , " wglDeleteContext " ) ;
Func_glGetString glGetString = ( Func_glGetString ) GetProcAddress ( hOpenGL , " glGetString " ) ;
if ( wglCreateContext = = nullptr | | wglMakeCurrent = = nullptr | | wglDeleteContext = = nullptr | | glGetString = = nullptr ) {
printf ( " Failed loading the system opengl32.dll: The library is invalid. \n " ) ;
return ;
}
2018-10-26 14:25:27 +00:00
PIXELFORMATDESCRIPTOR pfd =
{
sizeof ( PIXELFORMATDESCRIPTOR ) ,
1 ,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER ,
PFD_TYPE_RGBA , // The kind of framebuffer. RGBA or palette.
32 , // Color depth of the framebuffer.
0 , 0 , 0 , 0 , 0 , 0 ,
0 ,
0 ,
0 ,
0 , 0 , 0 , 0 ,
24 , // Number of bits for the depthbuffer
8 , // Number of bits for the stencilbuffer
0 , // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE ,
0 ,
0 , 0 , 0
} ;
HDC ourWindowHandleToDeviceContext = : : GetDC ( hWnd ) ;
2019-08-16 14:17:37 +00:00
// Gdi32.dll
int letWindowsChooseThisPixelFormat = : : ChoosePixelFormat ( ourWindowHandleToDeviceContext , & pfd ) ;
// Gdi32.dll
2019-01-09 09:43:17 +00:00
SetPixelFormat ( ourWindowHandleToDeviceContext , letWindowsChooseThisPixelFormat , & pfd ) ;
2019-08-16 14:17:37 +00:00
// Opengl32.dll
2018-10-26 14:25:27 +00:00
HGLRC glcontext = wglCreateContext ( ourWindowHandleToDeviceContext ) ;
wglMakeCurrent ( ourWindowHandleToDeviceContext , glcontext ) ;
// Opengl32.dll
2019-08-16 14:17:37 +00:00
const char * data = ( const char * ) glGetString ( GL_VERSION ) ;
if ( data ! = nullptr )
this - > version = data ;
// printf("check -version: %s\n", version.c_str());
data = ( const char * ) glGetString ( 0x8B8C ) ; // GL_SHADING_LANGUAGE_VERSION
if ( data ! = nullptr )
this - > glsl_version = data ;
data = ( const char * ) glGetString ( GL_VENDOR ) ;
if ( data ! = nullptr )
this - > vendor = data ;
data = ( const char * ) glGetString ( GL_RENDERER ) ;
if ( data ! = nullptr )
this - > renderer = data ;
2018-10-26 14:25:27 +00:00
// Opengl32.dll
wglDeleteContext ( glcontext ) ;
2019-08-16 14:17:37 +00:00
: : ReleaseDC ( hWnd , ourWindowHandleToDeviceContext ) ;
2018-10-26 14:25:27 +00:00
this - > success = true ;
2019-08-16 14:17:37 +00:00
}
static LRESULT CALLBACK supports_opengl2_wndproc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam )
{
switch ( message )
{
case WM_CREATE :
{
CREATESTRUCT * pCreate = reinterpret_cast < CREATESTRUCT * > ( lParam ) ;
OpenGLVersionCheck * ogl_data = reinterpret_cast < OpenGLVersionCheck * > ( pCreate - > lpCreateParams ) ;
ogl_data - > check ( hWnd ) ;
DestroyWindow ( hWnd ) ;
return 0 ;
}
case WM_NCDESTROY :
message_pump_exit = true ;
return 0 ;
default :
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
}
2018-10-26 14:25:27 +00:00
} ;
2019-01-09 09:43:17 +00:00
bool OpenGLVersionCheck : : message_pump_exit = false ;
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2019-01-09 09:43:17 +00:00
2018-10-26 16:08:43 +00:00
extern " C " {
2019-08-16 14:17:37 +00:00
typedef int ( __stdcall * Slic3rMainFunc ) ( int argc , wchar_t * * argv ) ;
Slic3rMainFunc slic3r_main = nullptr ;
2018-10-26 16:08:43 +00:00
}
2018-10-26 10:07:25 +00:00
2019-08-16 14:17:37 +00:00
extern " C " {
2018-10-26 10:07:25 +00:00
# ifdef SLIC3R_WRAPPER_NOCONSOLE
2019-01-03 17:54:45 +00:00
int APIENTRY wWinMain ( HINSTANCE /* hInstance */ , HINSTANCE /* hPrevInstance */ , PWSTR /* lpCmdLine */ , int /* nCmdShow */ )
2018-10-26 10:07:25 +00:00
{
2019-08-16 14:17:37 +00:00
int argc ;
wchar_t * * argv = : : CommandLineToArgvW ( : : GetCommandLineW ( ) , & argc ) ;
2018-10-26 10:07:25 +00:00
# else
int wmain ( int argc , wchar_t * * argv )
{
# endif
2021-04-08 13:29:40 +00:00
// Allow the asserts to open message box, such message box allows to ignore the assert and continue with the application.
// Without this call, the seemingly same message box is being opened by the abort() function, but that is too late and
// the application will be killed even if "Ignore" button is pressed.
_set_error_mode ( _OUT_TO_MSGBOX ) ;
2019-08-16 14:17:37 +00:00
std : : vector < wchar_t * > argv_extended ;
argv_extended . emplace_back ( argv [ 0 ] ) ;
2019-04-12 10:16:44 +00:00
2020-09-01 14:56:12 +00:00
# ifdef SLIC3R_WRAPPER_GCODEVIEWER
wchar_t gcodeviewer_param [ ] = L " --gcodeviewer " ;
argv_extended . emplace_back ( gcodeviewer_param ) ;
# endif /* SLIC3R_WRAPPER_GCODEVIEWER */
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2019-08-16 14:17:37 +00:00
// Here one may push some additional parameters based on the wrapper type.
bool force_mesa = false ;
2022-11-22 09:40:11 +00:00
bool force_hw = false ;
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2019-08-16 14:17:37 +00:00
for ( int i = 1 ; i < argc ; + + i ) {
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2019-08-16 14:17:37 +00:00
if ( wcscmp ( argv [ i ] , L " --sw-renderer " ) = = 0 )
force_mesa = true ;
else if ( wcscmp ( argv [ i ] , L " --no-sw-renderer " ) = = 0 )
2022-11-22 09:40:11 +00:00
force_hw = true ;
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2019-08-16 14:17:37 +00:00
argv_extended . emplace_back ( argv [ i ] ) ;
}
argv_extended . emplace_back ( nullptr ) ;
2019-01-09 09:43:17 +00:00
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2019-08-16 14:17:37 +00:00
OpenGLVersionCheck opengl_version_check ;
bool load_mesa =
// Forced from the command line.
force_mesa | |
// Running over a rempote desktop, and the RemoteFX is not enabled, therefore Windows will only provide SW OpenGL 1.1 context.
// In that case, use Mesa.
2022-11-22 09:40:11 +00:00
( : : GetSystemMetrics ( SM_REMOTESESSION ) & & ! force_hw ) | |
2019-08-16 14:17:37 +00:00
// Try to load the default OpenGL driver and test its context version.
! opengl_version_check . load_opengl_dll ( ) | | ! opengl_version_check . is_version_greater_or_equal_to ( 2 , 0 ) ;
2019-04-12 10:16:44 +00:00
# endif /* SLIC3R_GUI */
2018-10-26 14:25:27 +00:00
2019-08-16 14:17:37 +00:00
wchar_t path_to_exe [ MAX_PATH + 1 ] = { 0 } ;
: : GetModuleFileNameW ( nullptr , path_to_exe , MAX_PATH ) ;
wchar_t drive [ _MAX_DRIVE ] ;
wchar_t dir [ _MAX_DIR ] ;
wchar_t fname [ _MAX_FNAME ] ;
wchar_t ext [ _MAX_EXT ] ;
_wsplitpath ( path_to_exe , drive , dir , fname , ext ) ;
_wmakepath ( path_to_exe , drive , dir , nullptr , nullptr ) ;
2018-10-26 10:07:25 +00:00
2019-04-12 10:16:44 +00:00
# ifdef SLIC3R_GUI
2018-10-26 10:07:25 +00:00
// https://wiki.qt.io/Cross_compiling_Mesa_for_Windows
// http://download.qt.io/development_releases/prebuilt/llvmpipe/windows/
2019-08-16 14:17:37 +00:00
if ( load_mesa ) {
2022-05-24 08:20:02 +00:00
bool res = opengl_version_check . unload_opengl_dll ( ) ;
if ( ! res ) {
MessageBox ( nullptr , L " PrusaSlicer was unable to automatically switch to MESA OpenGL library \n Please, try to run the application using the '--sw-renderer' option. \n " ,
L " PrusaSlicer Warning " , MB_OK ) ;
return - 1 ;
}
else {
wchar_t path_to_mesa [ MAX_PATH + 1 ] = { 0 } ;
wcscpy ( path_to_mesa , path_to_exe ) ;
wcscat ( path_to_mesa , L " mesa \\ opengl32.dll " ) ;
printf ( " Loading MESA OpenGL library: %S \n " , path_to_mesa ) ;
HINSTANCE hInstance_OpenGL = LoadLibraryExW ( path_to_mesa , nullptr , 0 ) ;
if ( hInstance_OpenGL = = nullptr )
printf ( " MESA OpenGL library was not loaded \n " ) ;
else
printf ( " MESA OpenGL library was loaded sucessfully \n " ) ;
}
2019-08-16 14:17:37 +00:00
}
2019-04-12 11:13:31 +00:00
# endif /* SLIC3R_GUI */
2019-08-16 14:17:37 +00:00
wchar_t path_to_slic3r [ MAX_PATH + 1 ] = { 0 } ;
wcscpy ( path_to_slic3r , path_to_exe ) ;
wcscat ( path_to_slic3r , L " PrusaSlicer.dll " ) ;
2018-10-26 14:25:27 +00:00
// printf("Loading Slic3r library: %S\n", path_to_slic3r);
2019-08-16 14:17:37 +00:00
HINSTANCE hInstance_Slic3r = LoadLibraryExW ( path_to_slic3r , nullptr , 0 ) ;
if ( hInstance_Slic3r = = nullptr ) {
printf ( " PrusaSlicer.dll was not loaded \n " ) ;
return - 1 ;
}
// resolve function address here
slic3r_main = ( Slic3rMainFunc ) GetProcAddress ( hInstance_Slic3r ,
2018-10-26 16:31:50 +00:00
# ifdef _WIN64
2019-08-16 14:17:37 +00:00
// there is just a single calling conversion, therefore no mangling of the function name.
" slic3r_main "
2018-10-26 16:31:50 +00:00
# else // stdcall calling convention declaration
2019-08-16 14:17:37 +00:00
" _slic3r_main@8 "
2018-10-26 16:31:50 +00:00
# endif
2019-08-16 14:17:37 +00:00
) ;
if ( slic3r_main = = nullptr ) {
printf ( " could not locate the function slic3r_main in PrusaSlicer.dll \n " ) ;
return - 1 ;
}
// argc minus the trailing nullptr of the argv
return slic3r_main ( ( int ) argv_extended . size ( ) - 1 , argv_extended . data ( ) ) ;
}
2018-10-26 10:07:25 +00:00
}