This thread is going to be about OGRE port to Google's native platform. Open the page in the screenshot
Or the same page as a Chrome Web Store App
Google native platform – NaCl – it a new and exciting way to share software on the web.
The idea is to compile c and c++ and in a special way, a protected way, a cross platform way.
Google released an SDK for NaCl that includes a compiler, "c run time" h files and libraries –in a form that is similar to Linux gcc and its accompanied files, so compiling existing project that already compile for Linux is not that hard.
What makes the NaCl's compiler special is that the resulted "exe" can be run in a "sandbox" on multiple platforms as a browser plug-in. Think about is as an ActiveX but one that is platform independent and safe from hackers.
In simple terms - the idea behind the "sandbox" is a new concept that NaCl introduced – when the compilers compile the c++ code to native code (assembly) – it adds extra assembly instruction before any memory access assembly command to check that the target memory valid – meaning data memory and not the part of the memory that holds the program commands, same goes for goto commands – they will never go to the data memory. Meaning hackers can use buffer overruns.
Regular file access API is disabled and NaCl provides its own class to access files – this stops any possibility for system files hacks.
Assembly commands in c++ (__asm__) are not allowed.
To preserve platform portability and security – you can't access any platform specific API – like windows API and such.
The bottom line – you can compile c and c++ code to run in the browser that have the same system access as javascript code.
The advantages of NaCl over javascript are that native assembly code will always run faster then javascript and you can reuse existing code that you wrote for game in c++ to run safely in the browser.
The biggest disadvantage that NaCl currently has is that it doesn't have a debugger, more over – if you do bad things like using an uninitialized pointer – it exists without any message, call stuck or any way for you to know WHERE the error is.
One other disadvantage is that it wasn't released even in Chrome, and none of the other browsers intend to support it for now, but who cares, the idea of having a safe and cross-platformed browser plug-in written in c++ is a good idea.
Sinbad and I tweeted lots of tweets that from the alternatives (flash, javascript's WebGL, Silverlight and such) – NaCl is the best option.
Last week when Google announced that they want to include NaCl in their next release of Chrome I decided to port OGRE to NaCl.
The main reason was just to check out how good is NaCl, can it run my favorite pet, an ogre.
The secondary reason was that I searched the web for any other 3d open source project that ported its code to NaCl and couldn't find one.
Moreover – I didn't find any webpage, blog post and such that shows off even a simple NaCl OpenGL cube. Later when I was deep in I did found a reference and a "how to compile and run" of a basic OpenGL sample that runs on NaCl – but not even a single webpage you can just open and see some 3d rendering using NaCl.
The first thing I wanted to do is to compile the OGRE dependencies, Google ported most of them in a project called NaClPorts (http://code.google.com/p/naclports/).
My biggest issue here was that Google does provides all the SDK tools like the compile and link program and such as win32 exes that can run without Cygwin, but for the projects they converted for NaCl you have to use Cygwin and a complex system that downloads zip files, patch them then compile using make.
This was very complicated for me. I use visual studio as my main IDE, I love it, used to it, I love windows, I wanted to use visual studio, I hate complex hand written scripts to compile a few files. I like to open files in the IDE, edit them, compile, re-compile until no error. I don't like writing command lines and searching for files in the directory tree. The thing that bugs me must is that I have visual studio projects for OGRE and all of its dependencies, so why not compile the same project to a new platform using visual studio. Well, visual studio doesn't support compiling for NaCl, so you can't, Google worked on a project that should have added NaCl as a new target to visual studio but dropped it in the end of 2010. So I am stuck. But am I? After thinking about it and testing a few tests I decided that is too complicated to change the visual studio projects by hand.
I decided to write a tool that converts an existing visual studio project that compiles for windows to a new project with the same files, includes, defines and such – but one that compiles for NaCl.
I based the tool on an open source project called vspc that converts visual studio projects between versions, in a way is resembles what I wanted to do.
I changed the tool that the result project will contain the same files but for all the source file instead of compiling using Microsoft compiler will be considered a "Custom Build Tool" with a command line to compile using the NaCl compiler.
I had to translate all the defines and includes to be in the command line, find the right parameters and such, but it wasn't that hard, and the result saved me lots of time later on because I could use visual studio and translate existing projects that I already have.
Basically what I needed to do next was to compile and link the visual studio projects until there were no error – then start to debug the OGRE plug-in in Chrome.
Compiling the dependencies was not that hard after I wrote the solution convertor. I learned how to compile using the NaCl SDK tools by seeing the command prompt commands when I compiled the samples that comes with the SDK, there was no samples how to create static libs (.a extension) – but I searched Google and the process is the same as in linux (you use a special program called ar that merge .o file in to .a files). Also there is a naming convention that you need to prefix the static library name with "lib".
To link everything into an exe (.nexe extension) you use gcc, one thing I notices is that when you link an exe – the NaCl nexe function that is like the "main" function in normal programs called "CreateModule" must be linked in an o. file (and not in a static library .a file), easy to sort out because 99% of the time you don't have the main function in a library. In OGRE sample browser this is not an issue.
Getting OGRE to compile wasn't that hard, most of the work was to add the NaCl specific code to OpenGL ES 2 render system and to adapt the init process for NaCl.
I based my init code on the sample from the NaCl SDK.
When I started to debug the plug-in in the browser it was hard, the plug-in failed to load, NaCl plugins can't be debugged – so I needed to add lots of
Code: Select all
return NULL; //ASSAF HACK
With the input I first took a direction of using SDL that is already ported to NaCl and using it to feed the input to OIS (it has SDL support). But SDL crashed when I tried to init it, and also I didn't what to add a new dependency, so I wrote the needed code to add NaCl support to OIS. The hard part here was translating the key codes one by one from the javascript convention (used by NaCl) to the windows convention(used by OIS).
File access was more work then I expected, NaCl file and download API just didn't work correctly and it took me ages to find the right order of commands. I wrote once code that embed a zip file into an exe – but I don't think that this will be an option in real applications – and I wanted to demonstrate a real application – so I worked more and got it to work. I download the files and save them to the browser cache to save time the second time you open the page with the NaCl exe.
Here is the result of all my work – a webpage that shows off the OGRE sample browser.
All the OGRE code I wrote for this is checked in to OGRE's trunk.
Running the sample browser with Google Chrome beta isn't simple; you have to add flags, environment variables and such. Moreover - Google Chrome warns you if you have nexe files that they are risky and recommend you to delete them! Renaming the extension to anything without the substring "exe" solves the issue and the NaCl plug-in still works.
Google people that are reading this long post, if you got to this part you care about NaCl, and if that is true, mark my word - you need to make thing easier!
I have posted the link in twitter and it seems to work on most windows machines. I did found out about some issues:
A 32bit XP computer gets a blue screen every time you start the second sample.
A 32bit win7 computer doesn’t start the nexe with a "bad ELF file" message.
A 32bit OSX mac doesn't load the nexe without any reason or error.
The download sometimes doesn't work without any reason.
The progress callback from the nexe download only return in 0% and 100%, that is not so good when the nexe file size is 20MB. I think I can workaround this by downloading the file in javascript – with progress, then using it and it will be in the cache.
Here are some open issues I still have:
I need to output the resource files download progress.
The mouse wheel doesn't work – seems something easy to fix.
I want to write a new OGRE Archive to download files using the NaCl API, that also check hash codes, basically something that will allow you to only download the used files on the fly – to reduce loading time.
A big issue – unlike OpenGL – NaCl version on OpenGL ES 2 can have "lost device" issues, if the screen saver is up, the computer goes to sleep or you lock the screen – you lose your context and need to recreate the window and all of the resource similar to what happens in DirectX 9 on XP. Seems like hard work, moreover I don’t see how I can support render to texture results and such.
I will be happy for any help with this port. Feel free to contact me and offer it.
I guess that some of you will want to compile OGRE for NaCl.
For nun-linux people – I was able to compile OGRE using cmake with gcc output by changing the cmake parameters releated to gcc to use NaCl tools (they are the same names as in gcc but with "NaCl_" prefix). You will also need to mix in the dependencies compile, but if you are a Linux person - I guess you know what to do. Try to get it working on your own for now, I don't think I will get to it in the near future. I will be happy for any related patches.
For windows people – follow the following steps:
1. Download the NaCl SDK and install it.
2. Set an environment variable called NACL_SDK_ROOT that directs to the NaCl SDK dir. (ex: c:\nacl_sdk\pepper_20)
3. Download this dependencies zip and unzip it.
4. Get OGRE trunk.
5. CMake a solution for VS 2010
Use the dependencies from step 1 as the dependencies folder.
OGRE_BUILD_PLATFORM_NACL = true
OGRE_STATIC = true
OGRE_BUILD_TOOLS = false
OGRE_CONFIG_THREADS = 0
OGRE_BUILD_RENDERSYSTEM_D3D11 = false
OGRE_BUILD_RENDERSYSTEM_D3D9 = false
OGRE_BUILD_RENDERSYSTEM_GL = false
OGRE_BUILD_RENDERSYSTEM_GLES2 = true
OGRE_CONFIG_ALLOCATOR = 1 (check the CMake advanced checkbox to see this option.)
OGRE_USE_BOOST = false
meaning static build, no DX and GL render system, yes GLES2 render system, no boost, thread config 0, no tools.
6. Download my solution convertor tool and use it on the Ogre.sln solution you created in stage 5 and the dependencies sln.
7. Open the OgreDependencies_NaCl.sln (make sure you created it in stage 6) with visual studio (it is in the "src" the folder in the dependencies folder you unzipped in step 3), compile it for both 32 and 64 platforms, Copy the created .a file from the dependencies folder "src\out " to a sub folder named "out" under your new solution folder. If you have issues opening up the visual studio solution - this may be your issue.
8. Open the Ogre_nacl.sln that will be created next to the Ogre.sln.
9. Find the project SampleBrowser, find the item "Link NaCl", right click, properties, custom build tool, select "All platforms" from the "platform" combo box at the top of the window, "command line" line (top one in custom build), select it, click on the combo box button, <edit…>, an edit window opens, go to the end of the line of the last line in the edit window for the command line and paste the following text to be the end of the line instead of the "-lppapi -lppapi_cpp -lnosys" at the end there (BTW: there should be a space before the "-L$(SolutionDir)out"):
Code: Select all
"-L$(SolutionDir)out" -lOgreTerrain_x86_$(PlatformArchitecture) -lSample_BezierPatch_x86_$(PlatformArchitecture) -lSample_BSP_x86_$(PlatformArchitecture) -lSample_CameraTrack_x86_$(PlatformArchitecture) -lSample_CelShading_x86_$(PlatformArchitecture) -lSample_Character_x86_$(PlatformArchitecture) -lSample_Compositor_x86_$(PlatformArchitecture) -lSample_CubeMapping_x86_$(PlatformArchitecture) -lSample_DeferredShading_x86_$(PlatformArchitecture) -lSample_Dot3Bump_x86_$(PlatformArchitecture) -lSample_DynTex_x86_$(PlatformArchitecture) -lSample_FacialAnimation_x86_$(PlatformArchitecture) -lSample_Fresnel_x86_$(PlatformArchitecture) -lSample_Grass_x86_$(PlatformArchitecture) -lSample_Instancing_x86_$(PlatformArchitecture) -lSample_Isosurf_x86_$(PlatformArchitecture) -lSample_Lighting_x86_$(PlatformArchitecture) -lSample_NewInstancing_x86_$(PlatformArchitecture) -lSample_Ocean_x86_$(PlatformArchitecture) -lSample_ParticleFX_x86_$(PlatformArchitecture) -lSample_ParticleGS_x86_$(PlatformArchitecture) -lSample_ShaderSystem_x86_$(PlatformArchitecture) -lSample_Shadows_x86_$(PlatformArchitecture) -lSample_SkeletalAnimation_x86_$(PlatformArchitecture) -lSample_SkyBox_x86_$(PlatformArchitecture) -lSample_SkyDome_x86_$(PlatformArchitecture) -lSample_SkyPlane_x86_$(PlatformArchitecture) -lSample_Smoke_x86_$(PlatformArchitecture) -lSample_SphereMapping_x86_$(PlatformArchitecture) -lSample_Terrain_x86_$(PlatformArchitecture) -lSample_TextureArray_x86_$(PlatformArchitecture) -lSample_TextureFX_x86_$(PlatformArchitecture) -lSample_Transparency_x86_$(PlatformArchitecture) -lSample_VolumeTex_x86_$(PlatformArchitecture) -lSample_Water_x86_$(PlatformArchitecture) -lSample_EndlessWorld_x86_$(PlatformArchitecture) -lSample_VolumeCSG_x86_$(PlatformArchitecture) -lSample_VolumeCSG_x86_$(PlatformArchitecture) -lOgrePaging_x86_$(PlatformArchitecture) -lPlugin_BSPSceneManager_x86_$(PlatformArchitecture) -lPlugin_OctreeSceneManager_x86_$(PlatformArchitecture) -lPlugin_OctreeZone_x86_$(PlatformArchitecture) -lPlugin_ParticleFX_x86_$(PlatformArchitecture) -lPlugin_PCZSceneManager_x86_$(PlatformArchitecture) -lOgreRTShaderSystem_x86_$(PlatformArchitecture) -lRenderSystem_GLES2_x86_$(PlatformArchitecture) -lOgreOverlay_x86_$(PlatformArchitecture) -lOgreMain_x86_$(PlatformArchitecture) -lfreetype_NaCl_x86_$(PlatformArchitecture) -lOIS_NaCl_x86_$(PlatformArchitecture) -lzziplib_NaCl_x86_$(PlatformArchitecture) -lFreeImageLib_x86_$(PlatformArchitecture) -lOpenEXR_x86_$(PlatformArchitecture) -lLibJPEG_x86_$(PlatformArchitecture) -lLibMNG_x86_$(PlatformArchitecture) -lLibOpenJPEG_x86_$(PlatformArchitecture) -lLibPNG_x86_$(PlatformArchitecture) -lLibRawLite_x86_$(PlatformArchitecture) -lLibTIFF_x86_$(PlatformArchitecture) -lZLib-FreeImage_x86_$(PlatformArchitecture) -lppapi_gles2 -ldl -lppapi -lppapi_cpp -lnosys
11. Build the solution for both "Win32" and "x64" platforms. (meaning two solution builds…)
12. Copy the nexe files that were created in the "out" directory that is under the folder the solution exist in – into a directory with this template (use SVN to get it). Override the existing files that you see there.
13. You need to create an SampleBrowser.nmf file (Sorry, this is Google's idea and not me...) http://www.chromium.org/nativeclient/de ... -for-glibc
After creating the SampleBrowser.nmf file - override the one in the folder from stage 12.
To create an nmf file first run something like this:
Code: Select all
%NACL_SDK_ROOT%\toolchain\win_x86_glibc\bin\x86_64-nacl-objdump -p SampleBrowser_x86_64.nexe
For example, I got this output when running x86_64-nacl-objdump:
Code: Select all
.....
NEEDED libppapi_gles2.so
NEEDED libdl.so.11652996
NEEDED libpthread.so.11652996
NEEDED libppapi_cpp.so
NEEDED libstdc++.so.6
NEEDED libm.so.11652996
NEEDED libgcc_s.so.1
NEEDED libc.so.11652996
....
Code: Select all
{ "program": {
"x86-64": {"url": "lib64/runnable-ld.so"},
"x86-32": {"url": "lib32/runnable-ld.so"}
},
"files": {
"libpthread.so.11652996" : {
"x86-64": {"url": "lib64/libpthread.so.11652996"},
"x86-32": {"url": "lib32/libpthread.so.11652996"}
},
"libppapi_gles2.so" : {
"x86-64": {"url": "lib64/libppapi_gles2.so"},
"x86-32": {"url": "lib32/libppapi_gles2.so"}
},
"libdl.so.11652996" : {
"x86-64": {"url": "lib64/libdl.so.11652996"},
"x86-32": {"url": "lib32/libdl.so.11652996"}
},
"libpthread.so.11652996" : {
"x86-64": {"url": "lib64/libpthread.so.11652996"},
"x86-32": {"url": "lib32/libpthread.so.11652996"}
},
"libppapi_cpp.so" : {
"x86-64": {"url": "lib64/libppapi_cpp.so"},
"x86-32": {"url": "lib32/libppapi_cpp.so"}
},
"libstdc++.so.6" : {
"x86-64": {"url": "lib64/libstdc++.so.6"},
"x86-32": {"url": "lib32/libstdc++.so.6"}
},
"libm.so.11652996" : {
"x86-64": {"url": "lib64/libm.so.11652996"},
"x86-32": {"url": "lib32/libm.so.11652996"}
},
"libgcc_s.so.1" : {
"x86-64": {"url": "lib64/libgcc_s.so.1"},
"x86-32": {"url": "lib32/libgcc_s.so.1"}
},
"libc.so.11652996" : {
"x86-64": {"url": "lib64/libc.so.11652996"},
"x86-32": {"url": "lib32/libc.so.11652996"}
},
"main.nexe" : {
"x86-64": {"url": "SampleBrowser_x86_64.nexe"},
"x86-32": {"url": "SampleBrowser_x86_32.nexe"}
}
}
}
You will also need to copy later all the content of %NACL_SDK_ROOT%\toolchain\win_x86_glibc\x86_64-nacl\lib to a sub folder named lib64 in the folder from stage 12.
need to copy later all the content of %NACL_SDK_ROOT%\toolchain\win_x86_glibc\x86_64-nacl\lib32 to a sub folder named lib32 in the folder from stage 12.
This is an annoying stage that Google added, sorry about it...
14. Upload to a web server or use the local web server that comes with the NaCl SDK to test the sample out. Note – NaCl doesn't work from a local folder – you have to access a NaCl page with HTTP protocol for it to work – meaning TCP, meaning a web server of some sort.
A few pointers:
1. You can save time by only compiling to the platform you are using (32 or 64).
2. Use the javascript console to view OGRE log.
3. If you re-generate the solution with cmake – make sure to make the changes in the list above – from stage 9.
4. If NaCl doesn't work on a computer – try out the basic OpenGL NaCl that comes with NaCl SDK and see if you see the cube there.
5. If you have issues opening the converted visual studio solution - this may be your issue.
This is about it, lots of work, hopes it will turn into something good.

Feel free to comment.