Dev:Source/Architecture/CocoaBlender
Cocoa Blender
Status
Port to Cocoa is now complete!
64bit version can be built using the 10.5 libs (darwin-9.x.universal folder).
--Damien78
It is finally possible to keep the Blender main loop mechanism, and use a standard event polling mechanism with Cocoa.
So port to Cocoa is possible without changing Blender event loop.
Status: A first version of GHOST_SystemCocoa (initialization and event polling) and GHOST_DisplayManagerCocoa is done. GHOST_WindowCocoa is scheduled for next week.
--Damien78 - 03 oct. 2009
Proposal
After an IRC meeting with Blender/Cocoa developers, we've made a proposal for how to port Blender to Cocoa. Although we'd preferably like to only make changes in GHOST, it seems as is we need to make a few changes elsewhere to get this working nicely, as shown below.
To do this, we will need to work in an SVN branch, so that we can make these changes isolated from trunk, and not break compatibilities with other OSs.
This is what we need:
- A new branch (branches/cocoa, for example)
- Commit access for the three main cocoa devs, MrRage (Dustin Martin), Damien78 (Damien Plisson) and ender_saka (Marco)
- Possibly a special mailing list? Or is it ok to pollute bf-committers with cocoa discussions?
Main Cocoa issue
Current Blender event architecture controls an event loop that polls the os through ghost for events, dispatches them, and finally performs the redraw operations.
void WM_main(bContext *C)
{
while(1) {
/* get events from ghost, handle window events, add to window queues */
wm_window_process_events(C);
/* per window, all events to the window, screen, area and region handlers */
wm_event_do_handlers(C);
/* events have left notes about changes, we handle and cache it */
wm_event_do_notifiers(C);
/* execute cached changes draw */
wm_draw_update(C);
}
}
Cocoa has its own event loop, and Apple does not provide any documentation to override it and take control of the event loop.
Incorporate Blender runloop into Cocoa runloop
- Move WM_main() into GHOST_system::run() to have same behavior as today (for other platforms), and have it redefined in the child class for Cocoa
- Cocoa controller class receives input events and add them to the corresponding blender windows queues (as done today by ghost upon wm_window_process_events() call in the main loop).
- The other loop functions are called by the Cocoa loop through the "observer" Cocoa mechanism
Other option would have been to have both main loops work in parallel, and use thread-safe queues to mimic an event polling mechanism. But it increases architectural complexity and inefficiency.
Startup synchronization
Currently all startup is conducted in the main() function in creator.c, in three main phases :
- Variables, callbacks, operators, ... initialization/registration
- Ghost and windowing system init (call to WM_init())
- Last inits placing window manager calls, needing ghost complete init
- Start the main loop
The issue is that Cocoa initialization is hidden inside the same function call that runs the Cocoa loop. So it is asynchronous.
Solution:
- Split main(), having a completeStartupPhaseAfterGhostinit() including the startup phase 3 (last inits)
- Have the GHOST_system::run() be called to end phase 2, and call completeStartupPhaseAfterGhostinit() before starting the main loop
- Cocoa implementation uses the awakeFromNib message that tells views and windows have been setup to call Mr completeStartupPhaseAfterGhostinit()
Note that for background execution of Blender, the completeStartupPhaseAfterGhostinit is called directly from main().
Status : I've coded as a proof of concept these changes in current implementation (not yet Cocoa), and it works with these few changes.
Open points
- How to best fit into the new event/WM architecture ?
- Does it imply to change some ghost exposed API?
- What kind of approach in terms of development? incremental steps?
- How far do we move stuff at ghost level (e.g. fileMenu)?
Misc
- Cocoa port will be based on 10.5, with compatibility with 10.6 checked (no deprecated funcs)
- Objective C support classes used for the Cocoa side (application delegate and views)
- Ghost wrapper classes written in ObjC++, and only used to interact with the ObjC support classes
- Keep carbon stuff around for those who want to use it (e.g. the 10.3, 10.4 (...) users)
Previous work
Snow Leopard Update
I do apologize that I have not been able to give this project as much attention as it deserves, but my time has been limited. I’ve been running various versions of Snow Leopard over the last few months and blender still works in 10.6 when blender is built against the 10.6 or older SDK in 32 bit mode. 10.6 does produce a lot of warnings but still looks to work.
Getting blender to build against 10.5 or 10.6 SDK in 64 bit mode will require Cocoa.
Summary
Apple has maintained three sets of API for use with OSX. Classic, Carbon and Cocoa. Blender currently uses Carbon which up till recently was the ideal path for any application being ported to OSX. Carbon began to show its age when Apple decided to pull 64-bit support for Carbon in OS 10.5. So in order for Blender to enjoy the benefits of OSX its important to port parts of GHOST from Carbon to Cocoa.
Status
Ok getting back to this. It ended up taking longer to get all of my other stuff in order.
Dependencies built as Universal Binaries:
- jpeg
- png
- tiff
- freetype
- gettext
Items still remaining:
- Update build systems to allow for Cocoa and built as a Universal Binary (CMake done, others close behind)
- Finish writing Ghost Cocoa Wrapper methods (working on this now...)
- Write Ghost File menu API (pending)
Wish-list items:
- Important:
- Use of OSX ~Library and home directory when appropriate (for saving data outside of the blender package)
- Mac OSX Key bindings (for those pesky mac keyboards)
- Smooth window resizing (perhaps using NSOpenGLView?)
- Less important:
- Preferences panel (Might do this as native Cocoa... not sure)
- Native file browser (As an option)
- OpenGL Multi-Threading (Looking into this one)
Project Dependences:
- Audio System Clenaup for 64-bit support in Leopard, 32-bit unaffected. (This looks like it has been done)
Releases
I've missed a few release dates but I'm trying to get this done by the end of the year so I can move onto a few other projects I need to address.
Issues
There is no easy path going from Carbon to Cocoa because Cocoa is an Objective C based library with no C++ interface available to it. There is some overlap between Cocoa and Carbon and this overlap can stay, but the UI tool kit have been removed. Blender primarily used the UI tool kit so this was the section that needed to be redone.
I recently found a few more areas in the code that are Carbon bound and need to be updated. There is a dynamic section that currently uses the old style methods that needs to be updated.
Plan of Attack
- Replace Carbon C++ classes from Ghost with Cocoa Objective C++ wrapper classes
- Insert into creator.c a function call to start the Cocoa Event Loop, this function will have to block until an awakeFromNib call is issued by the NIB file. Once that is done it may unblock and continue.
Supported Platforms
This change will not effects blenders current support for 10.3 or 10.4. These platforms will be built using 32-bit mode. 10.5 will support 32/64-bit PPC and Intel using a unified package.
64 bit Issues
Unfortunately only 10.5 will be supporting 64-bit. This due to Cocoa being 64-bit on 10.5 and above.
There are some setbacks with getting 64-bit working with Blender and OSX. SDL is not ready and has to be removed, this currently effects fluids, game engine keyboard support, sound and the sequencer. Fluids because it uses SDL_Threads instead of BLI_threads. I've patched that part of it using pthreads and going to go back and replace it with BLI_threads, for better cross-platform support. The sequencer uses the SDL mixer directly so this is why it was an issue.
Due to the SDL issues initial experimental builds will not support sound or the use of a joystick.
Quicktime might also be another hot button issue because its API were effected by the 32 to 64-bit migration.