From 4a59928484b93a6c3876c0c8b065f6d313640804 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 4 Jun 2011 14:12:55 +0000 Subject: [PATCH] CMake option 'WITH_HEADLESS' to build blender in headless mode (no x11/xlib) with NULL ghost classe. --- CMakeLists.txt | 27 ++++-- intern/ghost/CMakeLists.txt | 37 ++++++- .../ghost/intern/GHOST_DisplayManagerNULL.h | 51 ++++++++++ intern/ghost/intern/GHOST_ISystem.cpp | 8 +- intern/ghost/intern/GHOST_NDOFManager.cpp | 4 +- intern/ghost/intern/GHOST_SystemNULL.h | 93 ++++++++++++++++++ intern/ghost/intern/GHOST_WindowNULL.h | 96 +++++++++++++++++++ source/creator/CMakeLists.txt | 4 + source/creator/creator.c | 2 +- 9 files changed, 310 insertions(+), 12 deletions(-) create mode 100644 intern/ghost/intern/GHOST_DisplayManagerNULL.h create mode 100644 intern/ghost/intern/GHOST_SystemNULL.h create mode 100644 intern/ghost/intern/GHOST_WindowNULL.h diff --git a/CMakeLists.txt b/CMakeLists.txt index dae8a37e572..4f99136097c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,6 +98,10 @@ option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effect option(WITH_BULLET "Enable Bullet (Physics Engine)" ON) option(WITH_GAMEENGINE "Enable Game Engine" ON) option(WITH_PLAYER "Build Player" OFF) + +option(WITH_HEADLESS "Build without graphical support (renderfarm, server mode only)" OFF) +mark_as_advanced(WITH_HEADLESS) + # (unix defaults to OpenMP On) if(UNIX AND NOT APPLE) option(WITH_OPENMP "Enable OpenMP (has to be supported by the compiler)" ON) @@ -205,6 +209,11 @@ if(WITH_PYTHON_MODULE AND WITH_PYTHON_INSTALL) message(FATAL_ERROR "WITH_PYTHON_MODULE requires WITH_PYTHON_INSTALL to be OFF") endif() +# may as well build python module without a UI +if(WITH_PYTHON_MODULE) + set(WITH_HEADLESS ON) +endif() + # remove old vars unset(WITH_INSTALL CACHE) @@ -409,15 +418,19 @@ if(UNIX AND NOT APPLE) unset(JEMALLOC) endif() - find_package(X11 REQUIRED) - find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH}) - mark_as_advanced(X11_XF86keysym_INCLUDE_PATH) - # OpenSuse needs lutil, ArchLinux not, for now keep, can avoid by using --as-needed - set(LLIBS "-lutil -lc -lm -lpthread -lstdc++ ${X11_X11_LIB}") + set(LLIBS "-lutil -lc -lm -lpthread -lstdc++") - if(WITH_X11_XINPUT) - list(APPEND LLIBS ${X11_Xinput_LIB}) + if(NOT WITH_HEADLESS) + find_package(X11 REQUIRED) + find_path(X11_XF86keysym_INCLUDE_PATH X11/XF86keysym.h ${X11_INC_SEARCH_PATH}) + mark_as_advanced(X11_XF86keysym_INCLUDE_PATH) + + list(APPEND LLIBS ${X11_X11_LIB}) + + if(WITH_X11_XINPUT) + list(APPEND LLIBS ${X11_Xinput_LIB}) + endif() endif() if(CMAKE_SYSTEM_NAME MATCHES "Linux") diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 065aa68dd3d..922f6918392 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -89,7 +89,42 @@ set(SRC intern/GHOST_WindowManager.h ) -if(APPLE) +if(WITH_HEADLESS) + list(APPEND SRC + intern/GHOST_DisplayManagerNULL.h + intern/GHOST_SystemNULL.h + intern/GHOST_WindowNULL.h + ) + add_definitions(-DWITH_HEADLESS) + + # ack, this is still system dependant + if(APPLE) + if(WITH_COCOA) + list(APPEND SRC + intern/GHOST_SystemPathsCocoa.mm + intern/GHOST_SystemPathsCocoa.h + ) + else() + list(APPEND SRC + intern/GHOST_SystemPathsCarbon.cpp + intern/GHOST_SystemPathsCarbon.h + ) + endif() + elseif(UNIX) + list(APPEND SRC + intern/GHOST_SystemPathsX11.cpp + intern/GHOST_SystemPathsX11.h + ) + elseif(WIN32) + + list(APPEND SRC + intern/GHOST_SystemPathsWin32.cpp + + intern/GHOST_SystemPathsWin32.h + ) + endif() + +elseif(APPLE) if(WITH_COCOA) list(APPEND SRC intern/GHOST_DisplayManagerCocoa.mm diff --git a/intern/ghost/intern/GHOST_DisplayManagerNULL.h b/intern/ghost/intern/GHOST_DisplayManagerNULL.h new file mode 100644 index 00000000000..e2902afd29b --- /dev/null +++ b/intern/ghost/intern/GHOST_DisplayManagerNULL.h @@ -0,0 +1,51 @@ +/* + * $Id: + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_DisplayManagerNULL.h + * \ingroup GHOST + * Declaration of GHOST_DisplayManagerNULL class. + */ + +#ifndef _GHOST_DISPLAY_MANAGER_NULL_H_ +#define _GHOST_DISPLAY_MANAGER_NULL_H_ + +#include "GHOST_DisplayManager.h" +#include "GHOST_SystemNULL.h" + +class GHOST_SystemNULL; + +class GHOST_DisplayManagerNULL : public GHOST_DisplayManager +{ +public: + GHOST_DisplayManagerNULL( GHOST_SystemNULL *system ) : GHOST_DisplayManager(), m_system(system) { /* nop */ } + GHOST_TSuccess getNumDisplays( GHOST_TUns8& numDisplays ) const { return GHOST_kFailure; } + GHOST_TSuccess getNumDisplaySettings( GHOST_TUns8 display, GHOST_TInt32& numSettings ) const{ return GHOST_kFailure; } + GHOST_TSuccess getDisplaySetting( GHOST_TUns8 display, GHOST_TInt32 index, GHOST_DisplaySetting& setting ) const { return GHOST_kFailure; } + GHOST_TSuccess getCurrentDisplaySetting( GHOST_TUns8 display, GHOST_DisplaySetting& setting ) const { return getDisplaySetting(display,GHOST_TInt32(0),setting); } + GHOST_TSuccess setCurrentDisplaySetting( GHOST_TUns8 display, const GHOST_DisplaySetting& setting ){ return GHOST_kSuccess; } + +private : + GHOST_SystemNULL * m_system; +}; + +#endif /* _GHOST_DISPLAY_MANAGER_NULL_H_ */ diff --git a/intern/ghost/intern/GHOST_ISystem.cpp b/intern/ghost/intern/GHOST_ISystem.cpp index 040164e2c40..7f170d2e876 100644 --- a/intern/ghost/intern/GHOST_ISystem.cpp +++ b/intern/ghost/intern/GHOST_ISystem.cpp @@ -41,7 +41,9 @@ #include "GHOST_ISystem.h" -#ifdef WIN32 +#ifdef WITH_HEADLESS +# include "GHOST_SystemNULL.h" +#elif defined(WIN32) # include "GHOST_SystemWin32.h" #else # ifdef __APPLE__ @@ -63,7 +65,9 @@ GHOST_TSuccess GHOST_ISystem::createSystem() { GHOST_TSuccess success; if (!m_system) { -#ifdef WIN32 +#ifdef WITH_HEADLESS + m_system = new GHOST_SystemNULL(); +#elif defined(WIN32) m_system = new GHOST_SystemWin32 (); #else # ifdef __APPLE__ diff --git a/intern/ghost/intern/GHOST_NDOFManager.cpp b/intern/ghost/intern/GHOST_NDOFManager.cpp index 95626ec26ea..7721b1708f9 100644 --- a/intern/ghost/intern/GHOST_NDOFManager.cpp +++ b/intern/ghost/intern/GHOST_NDOFManager.cpp @@ -81,7 +81,9 @@ GHOST_NDOFManager::deviceOpen(GHOST_IWindow* window, #if 0 printf("%i client \n", Pid); #endif - #if defined(_WIN32) || defined(__APPLE__) + #if defined(WITH_HEADLESS) + /* do nothing */ + #elif defined(_WIN32) || defined(__APPLE__) m_DeviceHandle = ndofDeviceOpen((void *)¤tNdofValues); #else GHOST_SystemX11 *sys; diff --git a/intern/ghost/intern/GHOST_SystemNULL.h b/intern/ghost/intern/GHOST_SystemNULL.h new file mode 100644 index 00000000000..00277449ceb --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemNULL.h @@ -0,0 +1,93 @@ +/* + * $Id: + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SystemNULL.h + * \ingroup GHOST + * Declaration of GHOST_SystemNULL class. + */ + +#ifndef _GHOST_SYSTEM_NULL_H_ +#define _GHOST_SYSTEM_NULL_H_ + +#include "GHOST_System.h" +#include "../GHOST_Types.h" +#include "GHOST_DisplayManagerNULL.h" +#include "GHOST_WindowNULL.h" + +class GHOST_WindowNULL; + +class GHOST_SystemNULL : public GHOST_System { +public: + + GHOST_SystemNULL( ) : GHOST_System() { /* nop */ } + ~GHOST_SystemNULL() { /* nop */ } + bool processEvents(bool waitForEvent) { return false; } + int toggleConsole(int action) { return 0; } + GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys& keys) const { return GHOST_kSuccess; } + GHOST_TSuccess getButtons(GHOST_Buttons& buttons) const { return GHOST_kSuccess; } + GHOST_TUns8 *getClipboard(bool selection) const { return NULL; } + void putClipboard(GHOST_TInt8 *buffer, bool selection) const { /* nop */ } + GHOST_TUns64 getMilliSeconds( ) const { return 0; } + GHOST_TUns8 getNumDisplays( ) const { return GHOST_TUns8(1); } + GHOST_TSuccess getCursorPosition( GHOST_TInt32& x, GHOST_TInt32& y ) const { return GHOST_kFailure; } + GHOST_TSuccess setCursorPosition( GHOST_TInt32 x, GHOST_TInt32 y ) { return GHOST_kFailure; } + void getMainDisplayDimensions( GHOST_TUns32& width, GHOST_TUns32& height ) const { /* nop */ } + + GHOST_TSuccess init() { + GHOST_TSuccess success = GHOST_System::init(); + + if (success) { + m_displayManager = new GHOST_DisplayManagerNULL(this); + + if (m_displayManager) { + return GHOST_kSuccess; + } + } + + return GHOST_kFailure; + } + + GHOST_IWindow* createWindow( + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + GHOST_TDrawingContextType type, + bool stereoVisual, + const GHOST_TUns16 numOfAASamples, + const GHOST_TEmbedderWindowID parentWindow + ) { + return new GHOST_WindowNULL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1); + } +}; + +#endif + + + + + + + diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h new file mode 100644 index 00000000000..c0162f412c5 --- /dev/null +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -0,0 +1,96 @@ +/* + * $Id: + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_WindowNULL.h + * \ingroup GHOST + * Declaration of GHOST_WindowNULL class. + */ + +#ifndef _GHOST_WINDOWNULL_H_ +#define _GHOST_WINDOWNULL_H_ + +#include "GHOST_Window.h" + +#include + +class STR_String; +class GHOST_SystemNULL; + +class GHOST_WindowNULL : public GHOST_Window +{ +public: + const GHOST_TabletData* GetTabletData() { return NULL; } + + GHOST_WindowNULL( + GHOST_SystemNULL *system, + const STR_String& title, + GHOST_TInt32 left, + GHOST_TInt32 top, + GHOST_TUns32 width, + GHOST_TUns32 height, + GHOST_TWindowState state, + const GHOST_TEmbedderWindowID parentWindow, + GHOST_TDrawingContextType type, + const bool stereoVisual, + const GHOST_TUns16 numOfAASamples + ) : + GHOST_Window(title,left,top,width,height,state,type,stereoVisual,numOfAASamples), + m_system (system) + { + setTitle(title); + } + +protected: + GHOST_TSuccess installDrawingContext( GHOST_TDrawingContextType type ){ return GHOST_kSuccess; } + GHOST_TSuccess removeDrawingContext( ){ return GHOST_kSuccess; } + GHOST_TSuccess setWindowCursorGrab( GHOST_TGrabCursorMode mode ){ return GHOST_kSuccess; } + GHOST_TSuccess setWindowCursorShape( GHOST_TStandardCursor shape ){ return GHOST_kSuccess; } + GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 bitmap[16][2], GHOST_TUns8 mask[16][2], int hotX, int hotY ) { return GHOST_kSuccess; } + GHOST_TSuccess setWindowCustomCursorShape( GHOST_TUns8 *bitmap, GHOST_TUns8 *mask, int sizex, int sizey, int hotX, int hotY, int fg_color, int bg_color ){ return GHOST_kSuccess; } + + bool getValid( ) const { return true; } + void setTitle( const STR_String& title ){ /* nothing */ } + void getTitle( STR_String& title ) const { title= "untitled"; } + void getWindowBounds( GHOST_Rect& bounds ) const { getClientBounds(bounds); } + void getClientBounds( GHOST_Rect& bounds ) const { /* nothing */ } + GHOST_TSuccess setClientWidth( GHOST_TUns32 width ){ return GHOST_kFailure; } + GHOST_TSuccess setClientHeight( GHOST_TUns32 height ){ return GHOST_kFailure; } + GHOST_TSuccess setClientSize( GHOST_TUns32 width, GHOST_TUns32 height ){ return GHOST_kFailure; } + void screenToClient( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const { outX = inX; outY = inY; } + void clientToScreen( GHOST_TInt32 inX, GHOST_TInt32 inY, GHOST_TInt32& outX, GHOST_TInt32& outY ) const { outX = inX; outY = inY; } + GHOST_TSuccess swapBuffers( ){ return GHOST_kFailure; } + GHOST_TSuccess activateDrawingContext( ){ return GHOST_kFailure; } + ~GHOST_WindowNULL( ){ /* nothing */ } + GHOST_TSuccess setWindowCursorVisibility( bool visible ){ return GHOST_kSuccess; } + GHOST_TSuccess setState(GHOST_TWindowState state) { return GHOST_kSuccess; } + GHOST_TWindowState getState() const { return GHOST_kWindowStateNormal; } + GHOST_TSuccess invalidate() { return GHOST_kSuccess; } + GHOST_TSuccess setOrder(GHOST_TWindowOrder order) { return GHOST_kSuccess; } + + +private : + GHOST_SystemNULL * m_system; +}; + + +#endif // _GHOST_WINDOWNULL_H_ diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c3eae586599..db467eebb5c 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -81,6 +81,10 @@ if(WITH_PYTHON) endif() endif() +if(WITH_HEADLESS) + add_definitions(-DWITH_HEADLESS) +endif() + if(WITH_GAMEENGINE) blender_include_dirs(../gameengine/BlenderRoutines) diff --git a/source/creator/creator.c b/source/creator/creator.c index 6e9ecf234fc..fe9bd57d035 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -1215,7 +1215,7 @@ int main(int argc, const char **argv) setuid(getuid()); /* end superuser */ #endif -#ifdef WITH_PYTHON_MODULE +#if defined(WITH_PYTHON_MODULE) || defined(WITH_HEADLESS) G.background= 1; /* python module mode ALWAYS runs in background mode (for now) */ #else /* for all platforms, even windos has it! */