Pages

Apr 30, 2012

Porting to Native Client with Visual Studio pt.2

This article series shows you how to port to Native Client via a Chrome Trusted Plugin. This will allow you port your platform code over to Chrome's Pepper APIs while using Visual Studio for debugging. 


WARNING:
As of 10.1.2012, there's an official version of a Visual Studio 2010 plugin. Only some subset of this article series is accurate, please see the official documentation at gonacl.com for more.


Episode 2: The platform-specific hope

In the 2nd installment of my soon-to-be-peabody-nominated-series I'll walk you through how to call platform-specific code from our trusted plugin, and get it running alongside our pepper api; This will be a setup for article 3, which will talk about how to port us from the platform specific API code to Pepper. Less pictures this time, more code ;)


I'm assuming that you've already grabbed the first article's code from github, and that you've properly read through the first article such that I don't need to repeat any of that.
The Waffle Burger. The Unholy alliance of breakfast and dinner that fueled the 200 year war.
It is from this brave delicacy that we draw our inspiration in this article.

Getting some Platform-Specific code
Most of my work with Native Client developers includes game devs specifically, and their biggest pain points revolve around file IO and rendering; as such, it makes sense that we should target something difficult, yet easy to deal with.

As such, go grab a nice openGL sample which covers both OpenGL, and file IO from Codesampler.com, download it and unpack it somewhere.

Once done, copy the entire contents of ogl_glslang_simple_vs2ps.cpp from the sample and paste it at the TOP of our existing plugin-port0\main.cpp file;

In addition to the file contents, you'll also need to copy over the following additional files:
  • glext.h - This is a file containing headers needed for this OpenGL example
  • vertex_shader.vert
  • fragment_shader.frag
Place these files alongside your plugin-port0\index.html file


Getting it compiling
Assuming you've pasted the code starting at line 0, you can easily make the following changes:
line 29: //#include "gluax.h"
line 30: //#include "resource.h"
Note you should set your characters from unicode to multibyte in the project settings, otherwise the first time you compile you'll get erros relating to LPCWSTR; Be aware that this isn't NaCl specific, it's just how this particular plugin is being handled.



Adding the GL libraries
OpenGL requires us to link to specific precompiled libraries to render properly; Let's link to them, and celebrate our ability to use Visual Studio in the same breath by using some nice VS magic that keeps us from having to modify the properties pages. Add these lines after the includes of your file.

#pragma comment(lib,"opengl32.lib")
#pragma comment(lib,"glu32.lib")

It compiles! Let's get it doing something!

Updating the main function
What we're going to do here, is modify the source code we have to pop up the existing code window that we would expect to see and run it side-by-side with our Chrome window. As such, we need to change the function header for the window creation online line 112:


init WINAPI WinMain(HINSTANCE hInstance,HISNTANCE hPrevInstance, LPSTR lpCmdLine, int nCMDShow)

with:
int initInstance()

"Simplicity is a dish best served with nothing on it"

Calling the main function
Now that we've modified the main function, we need to call it from somewhere. Place a call to the window creation inside of Instance_DidCreate in order to launch the window

static PP_Bool Instance_DidCreate(...){
   PP_Var v = CStrToVar("Hello a World (NEWLIB)");
   ppb_messaging_interface->;PostMessage(instance,v);

   initInstance();
   ..
}


Reading files from disk

This project reads in 3 files from disk, a texture and two shaders. There's a proper way to do this, via Pepper, but we're not to the point of caring about pepper just yet. Instead we're going to cheat here, and use a bit of dark voodoo magic. Although we're serving our html content from a webserver, we can define this nice flag --no-sandbox as a command line argument that will allow us to read files directly from the local disk, bypassing the sandbox security restrictions.

So in your project's settings set
Debugging > Command Arguments:

--no-sandbox --single-process --register-pepper-plugins=$(TargetPath);application/x-nacl "localhost:5103/index.html"

From here, we can access the files directly on disk, but it's a bit of hand-wavy issue about what directory these files exist in to access them; If you run the project a few times, and move the files around, it's difficult to pin down the exact spot that a relative path reads from.So for the sake of simplicity for this tutorial we're going to prepend all the files paths with the absolute path of the location. Yes. This works.


FILE* f = fopen("\\plugin-port1\\plugin-port1\\test.raw" ,"rb");

Note you'll need to do this for both the texture, and two shader files that are explicitly referenced in the code.

Booyah

From there, Run the Compile, httpd.py server, Run and see the awesome:
The fruits of our labor. An OpenGL window will launch alongside of our chrome module. It renders and responds to input quite well. We've done the Waffle Burger proud!
When you run, note that you webpage will not respond in parallel with your window being opened. This is because our main thread that the browser runs on is actually running a spin loop for servicing the window popup, and not allowing any events for the page to be serviced. To fix this, you can do all of the window logic on another thread, and communicate back to the main thread with a producer-consumer FIFO, but that's a bit beyond the scope of this article.

Notes about the provided code
The original source referenced gluax.h to decode the .bmp image has been removed, as the gluax library is depriciated at best, so rather than adding complexity, I instead converted the test.bmp file to a test.raw, and modified the texture loading code in the init(..) function to simply memcpy load the raw data. I figure that has little and less to do with Native Client, so I omitted the code discussion for the article ;)



Note, you can download the source code for this series @ my github repo.

The rest of the series - 
Part 1 : Setting up visual studio
Part 2 : Using platform-specific code 
Part 3 : Porting to Pepper
Part 4 : Compile to NaCl




You can find me here:

  

~Main

No comments:

Post a Comment