Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/3D-graphics.html

Issue 140993006: [NaCl SDK Docs] Check in the generated NaCl SDK Documentation. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: try without pepper_{dev,beta,stable} Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/3D-graphics.html
diff --git a/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/3D-graphics.html b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/3D-graphics.html
new file mode 100644
index 0000000000000000000000000000000000000000..0e7cdb183833e7fcc98df960f44c4376c83f73ef
--- /dev/null
+++ b/native_client_sdk/src/doc/_developer.chrome.com_generated/devguide/coding/3D-graphics.html
@@ -0,0 +1,442 @@
+{{+bindTo:partials.standard_nacl_article}}
+
+<section id="d-graphics">
+<span id="devguide-coding-3d-graphics"></span><h1 id="d-graphics"><span id="devguide-coding-3d-graphics"></span>3D Graphics</h1>
+<p>Native Client applications use the <a class="reference external" href="http://en.wikipedia.org/wiki/OpenGL_ES">OpenGL ES 2.0</a> API for 3D rendering. This document
+describes how to call the OpenGL ES 2.0 interface in a Native Client module and
+how to build an efficient rendering loop. It also explains how to validate GPU
+drivers and test for specific GPU capabilities, and provides tips to help ensure
+your rendering code runs efficiently.</p>
+<aside class="note">
+<strong>Note</strong>: 3D drawing and OpenGL are complex topics. This document deals only
+with issues directly related to programming in the Native Client
+environment. To learn more about OpenGL ES 2.0 itself, see the <a class="reference external" href="http://opengles-book.com/">OpenGL ES 2.0
+Programming Guide</a>.
+</aside>
+<section id="validating-the-client-graphics-platform">
+<h2 id="validating-the-client-graphics-platform">Validating the client graphics platform</h2>
+<p>Native Client is a software technology that lets you code an application once
+and run it on multiple platforms without worrying about the implementation
+details on every possible target platform. It&#8217;s difficult to provide the same
+support at the hardware level. Graphics hardware comes from many different
+manufacturers and is controlled by drivers of varying quality. A particular GPU
+driver may not support every OpenGL ES 2.0 feature, and some drivers are known
+to have vulnerabilities that can be exploited.</p>
+<p>Even if the GPU driver is safe to use, your program should perform a validation
+check before you launch your application to ensure that the driver supports all
+the features you need.</p>
+<section id="vetting-the-driver-in-javascript">
+<h3 id="vetting-the-driver-in-javascript">Vetting the driver in JavaScript</h3>
+<p>At startup, the application should perform a few additional tests that can be
+implemented in JavaScript on its hosting web page. The script that performs
+these tests should be included before the module&#8217;s <code>embed</code> tag, and ideally
+the <code>embed</code> tag should appear on the hosting page only if these tests succeed.</p>
+<p>The first thing to check is whether you can create a graphics context. If you
+can, use the context to confirm the existence of any required OpenGL ES 2.0
+extensions. You may want to refer to the <a class="reference external" href="http://www.khronos.org/registry/webgl/extensions/">extension registry</a> and include <a class="reference external" href="https://developer.mozilla.org/en-US/docs/WebGL/Using_Extensions">vendor
+prefixes</a>
+when checking for extensions.</p>
+</section><section id="vetting-the-driver-in-native-client">
+<h3 id="vetting-the-driver-in-native-client">Vetting the driver in Native Client</h3>
+<section id="create-a-context">
+<h4 id="create-a-context">Create a context</h4>
+<p>Once you&#8217;ve passed the JavaScript validation tests, it&#8217;s safe to add a Native
+Client embed tag to the hosting web page and load the module. As part of the
+module initialization code, you must create a graphics context for the app by
+either creating a C++ <code>Graphics3D</code> object or calling <code>PPB_Graphics3D</code> API
+function <code>Create</code>. Don&#8217;t assume this will always succeed; you still might have
+problems creating the context. If you are in development mode and can&#8217;t create
+the context, try creating a simpler version to see if you&#8217;re asking for an
+unsupported feature or exceeding a driver resource limit. Your production code
+should always check that the context was created and fail gracefully if that&#8217;s
+not the case.</p>
+</section><section id="check-for-extensions-and-capabilities">
+<h4 id="check-for-extensions-and-capabilities">Check for extensions and capabilities</h4>
+<p>Not every GPU supports every extension or has the same amount of texture units,
+vertex attributes, etc. On startup, call <code>glGetString(GL_EXTENSIONS)</code> and
+check for the extensions and the features you need. For example:</p>
+<ul class="small-gap">
+<li>If you are using non power-of-2 texture with mipmaps, make sure
+<code>GL_OES_texture_npot</code> exists.</li>
+<li>If you are using floating point textures, make sure <code>GL_OES_texture_float</code>
+exists.</li>
+<li>If you are using DXT1, DXT3, or DXT5 textures, make sure the corresponding
+extensions <code>EXT_texture_compression_dxt1</code>,
+<code>GL_CHROMIUM_texture_compression_dxt3</code>, and
+<code>GL_CHROMIUM_texture_compression_dxt5</code> exist.</li>
+<li>If you are using the functions <code>glDrawArraysInstancedANGLE</code>,
+<code>glDrawElementsInstancedANGLE</code>, <code>glVertexAttribDivisorANGLE</code>, or the PPAPI
+interface <code>PPB_OpenGLES2InstancedArrays</code>, make sure the corresponding
+extension <code>GL_ANGLE_instanced_arrays</code> exists.</li>
+<li>If you are using the function <code>glRenderbufferStorageMultisampleEXT</code>, or the
+PPAPI interface <code>PPB_OpenGLES2FramebufferMultisample</code>, make sure the
+corresponding extension <code>GL_CHROMIUM_framebuffer_multisample</code> exists.</li>
+<li>If you are using the functions <code>glGenQueriesEXT</code>, <code>glDeleteQueriesEXT</code>,
+<code>glIsQueryEXT</code>, <code>glBeginQueryEXT</code>, <code>glEndQueryEXT</code>, <code>glGetQueryivEXT</code>,
+<code>glGetQueryObjectuivEXT</code>, or the PPAPI interface <code>PPB_OpenGLES2Query</code>,
+make sure the corresponding extension <code>GL_EXT_occlusion_query_boolean</code>
+exists.</li>
+<li>If you are using the functions <code>glMapBufferSubDataCHROMIUM</code>,
+<code>glUnmapBufferSubDataCHROMIUM</code>, <code>glMapTexSubImage2DCHROMIUM</code>,
+<code>glUnmapTexSubImage2DCHROMIUM</code>, or the PPAPI interface
+<code>PPB_OpenGLES2ChromiumMapSub</code>, make sure the corresponding extension
+<code>GL_CHROMIUM_map_sub</code> exists.</li>
+</ul>
+<p>Check for system capabilites with <code>glGetIntegerv</code> and adjust shader programs
+as well as texture and vertex data accordingly:</p>
+<ul class="small-gap">
+<li>If you are using textures in vertex shaders, make sure
+<code>glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, ...)</code> and
+<code>glGetIntegerv(GL_MAX_TEXTURE_SIZE, ...)</code> return values greater than 0.</li>
+<li>If you are using more than 8 textures in a single shader, make sure
+<code>glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, ...)</code> returns a value greater
+than or equal to the number of simultaneous textures you need.</li>
+</ul>
+</section></section><section id="vetting-the-driver-in-the-chrome-web-store">
+<h3 id="vetting-the-driver-in-the-chrome-web-store">Vetting the driver in the Chrome Web Store</h3>
+<p>If you choose to place your application in the <a class="reference external" href="https://developers.google.com/chrome/web-store/docs/">Chrome Web
+Store</a>, its Web Store
+<a class="reference external" href="http://code.google.com/chrome/extensions/manifest.html">manifest file</a> can
+include the <code>webgl</code> feature in the requirements parameter. It looks like this:</p>
+<pre class="prettyprint">
+&quot;requirements&quot;: {
+ &quot;3D&quot;: {
+ &quot;features&quot;: [&quot;webgl&quot;]
+ }
+}
+</pre>
+<p>While WebGL is technically a JavaScript API, specifying the <code>webgl</code> feature
+also works for OpenGL ES 2.0 because both interfaces use the same driver.</p>
+<p>This manifest item is not required, but if you include it, the Chrome Web Store
+will prevent a user from installing the application if the browser is running on
+a machine that does not support OpenGL ES 2.0 or that is using a known
+blacklisted GPU driver that could invite an attack.</p>
+<p>If the Web Store determines that the user&#8217;s driver is deficient, the app won&#8217;t
+appear on the store&#8217;s tile display. However, it will appear in store search
+results or if the user links to it directly, in which case the user could still
+download it. But the manifest requirements will be checked when the user reaches
+the install page, and if there is a problem, the browser will display the
+message &#8220;This application is not supported on this computer. Installation has
+been disabled.&#8221;</p>
+<p>The manifest-based check applies only to downloads directly from the Chrome Web
+Store. It is not performed when an application is loaded via <a class="reference external" href="https://developers.google.com/chrome/web-store/docs/inline_installation">inline
+installation</a>.</p>
+</section><section id="what-to-do-when-there-are-problems">
+<h3 id="what-to-do-when-there-are-problems">What to do when there are problems</h3>
+<p>Using the vetting procedure described above, you should be able to detect the
+most common problems before your application runs. If there are problems, your
+code should describe the issue as clearly as possible. That&#8217;s easy if there is a
+missing feature. Failure to create a graphics context is tougher to diagnose. At
+the very least, you can suggest that the user try to update the driver. You
+might want to linke to the Chrome page that describes <a class="reference external" href="http://support.google.com/chrome/bin/answer.py?hl=en&amp;answer=1202946">how to do updates</a>.</p>
+<p>If a user can&#8217;t update the driver, or their problem persists, be sure to gather
+information about their graphics environment. Ask for the contents of the Chrome
+<code>about:gpu</code> page.</p>
+</section><section id="document-unreliable-drivers">
+<h3 id="document-unreliable-drivers">Document unreliable drivers</h3>
+<p>It can be helpful to include information about known dubious drivers in your
+user documentation. This might help identify if a rogue driver is the cause of a
+problem. There are many sources of GPU driver blacklists. Two such lists can be
+found at the <a class="reference external" href="http://src.chromium.org/viewvc/chrome/trunk/deps/gpu/software_rendering_list/software_rendering_list.json">Chromium project</a>
+and <a class="reference external" href="http://www.khronos.org/webgl/wiki/BlacklistsAndWhitelists">Khronos</a>. You
+can use these lists to include information in your documentation that warns
+users about dangerous drivers.</p>
+</section><section id="test-your-defenses">
+<h3 id="test-your-defenses">Test your defenses</h3>
+<p>You can test your driver validation code by running Chrome with the following
+flags (all at once) and watching how your application responds:</p>
+<ul class="small-gap">
+<li><code>--disable-webgl</code></li>
+<li><code>--disable-pepper-3d</code></li>
+<li><code>--disable-gl-multisampling</code></li>
+<li><code>--disable-accelerated-compositing</code></li>
+<li><code>--disable-accelerated-2d-canvas</code></li>
+</ul>
+</section></section><section id="calling-opengl-es-2-0-commands">
+<h2 id="calling-opengl-es-2-0-commands">Calling OpenGL ES 2.0 commands</h2>
+<p>There are three ways to write OpenGL ES 2.0 calls in Native Client.</p>
+<section id="use-pure-opengl-es-2-0-function-calls">
+<h3 id="use-pure-opengl-es-2-0-function-calls">Use &#8220;pure&#8221; OpenGL ES 2.0 function calls</h3>
+<p>You can make OpenGL ES 2.0 calls through a Pepper extension library. The SDK
+example <code>examples/api/graphics_3d</code> works this way. In the file
+<code>graphics_3d.cc</code>, the key initialization steps are as follows:</p>
+<ul class="small-gap">
+<li><p class="first">Add these includes at the top of the file:</p>
+<pre class="prettyprint">
+#include &lt;GLES2/gl2.h&gt;
+#include &quot;ppapi/lib/gl/gles2/gl2ext_ppapi.h&quot;
+</pre>
+</li>
+<li><p class="first">Define the function <code>InitGL</code>. The exact specification of <code>attrib_list</code>
+will be application specific.</p>
+<pre class="prettyprint">
+bool InitGL(int32_t new_width, int32_t new_height) {
+ if (!glInitializePPAPI(pp::Module::Get()-&gt;get_browser_interface())) {
+ fprintf(stderr, &quot;Unable to initialize GL PPAPI!\n&quot;);
+ return false;
+ }
+
+ const int32_t attrib_list[] = {
+ PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
+ PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
+ PP_GRAPHICS3DATTRIB_WIDTH, new_width,
+ PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
+ PP_GRAPHICS3DATTRIB_NONE
+ };
+
+ context_ = pp::Graphics3D(this, attrib_list);
+ if (!BindGraphics(context_)) {
+ fprintf(stderr, &quot;Unable to bind 3d context!\n&quot;);
+ context_ = pp::Graphics3D();
+ glSetCurrentContextPPAPI(0);
+ return false;
+ }
+
+ glSetCurrentContextPPAPI(context_.pp_resource());
+ return true;
+}
+</pre>
+</li>
+<li>Include logic in <code>Instance::DidChangeView</code> to call <code>InitGL</code> whenever
+necessary: upon application launch (when the graphics context is NULL) and
+whenever the module&#8217;s View changes size.</li>
+</ul>
+</section><section id="use-regal">
+<h3 id="use-regal">Use Regal</h3>
+<p>If you are porting an OpenGL ES 2.0 application, or are comfortable writing in
+OpenGL ES 2.0, you should stick with the Pepper APIs or pure OpenGL ES 2.0 calls
+described above. If you are porting an application that uses features not in
+OpenGL ES 2.0, consider using Regal. Regal is an open source library that
+supports many versions of OpenGL. Regal recently added support for Native
+Client. Regal forwards most OpenGL calls directly to the underlying graphics
+library, but it can also emulate other calls that are not included (when
+hardware support exists). See <a class="reference external" href="http://www.altdevblogaday.com/2012/09/04/bringing-regal-opengl-to-native-client/">libregal</a>
+for more info.</p>
+</section><section id="use-the-pepper-api">
+<h3 id="use-the-pepper-api">Use the Pepper API</h3>
+<p>Your code can call the Pepper <a class="reference external" href="https://developers.google.com/native-client/pepperc/struct_p_p_b___open_g_l_e_s2">PPB_OpenGLES2</a>
+API directly, as with any Pepper interface. When you write in this way, each
+invocation of an OpenGL ES 2.0 function must begin with a reference to the
+Pepper interface, and the first argument is the graphics context. To invoke the
+function <code>glCompileShader</code>, your code might look like:</p>
+<pre class="prettyprint">
+ppb_g3d_interface-&gt;CompileShader(graphicsContext, shader);
+</pre>
+<p>This approach specifically targets the Pepper APIs. Each call corresponds to a
+OpenGL ES 2.0 function, but the syntax is unique to Native Client, so the source
+file is not portable.</p>
+</section></section><section id="implementing-a-rendering-loop">
+<h2 id="implementing-a-rendering-loop">Implementing a rendering loop</h2>
+<p>Graphics applications require a continuous frame render-and-redraw cycle that
+runs at a high frequency. To achieve the best frame rate, is important to
+understand how the OpenGL ES 2.0 code in a Native Client module interacts with
+Chrome.</p>
+<section id="the-chrome-and-native-client-processes">
+<h3 id="the-chrome-and-native-client-processes">The Chrome and Native Client processes</h3>
+<p>Chrome is a multi-process browser. Each Chrome tab is a separate process that is
+running an application with its own main thread (we&#8217;ll call it the Chrome main
+thread). When an application launches a Native Client module, the module runs in
+a new, separate sandboxed process. The module&#8217;s process has its own main thread
+(the Native Client thread). The Chrome and Native Client processes communicate
+with each other using Pepper API calls on their main threads.</p>
+<p>When the Chrome main thread calls the Native Client thread (keyboard and mouse
+callbacks, for example), the Chrome main thread will block. This means that
+lengthy operations on the Native Client thread can steal cycles from Chrome, and
+performing blocking operations on the Native Client thread can bring your app to
+a standstill.</p>
+<p>Native Client uses callback functions to synchronize the main threads of the two
+processes. Only certain Pepper functions use callbacks; <a class="reference external" href="https://developers.google.com/native-client/pepperc/struct_p_p_b___graphics3_d__1__0#a293c6941c0da084267ffba3954793497">SwapBuffers</a>
+is one.</p>
+</section><section id="swapbuffers-and-its-callback-function">
+<h3 id="swapbuffers-and-its-callback-function"><code>SwapBuffers</code> and its callback function</h3>
+<p><code>SwapBuffers</code> is non-blocking; it is called from the Native Client thread and
+returns immediately. When <code>SwapBuffers</code> is called, it runs asynchronously on
+the Chrome main thread. It switches the graphics data buffers, handles any
+needed compositing operations, and redraws the screen. When the screen update is
+complete, the callback function that was included as one of <code>SwapBuffer</code>&#8216;s
+arguments will be called from the Chrome thread and executed on the Native
+Client thread.</p>
+<p>To create a rendering loop, your Native Client module should include a function
+that does the rendering work and then executes <code>SwapBuffers</code>, passing itself
+as the <code>SwapBuffer</code> callback. If your rendering code is efficient and runs
+quickly, this scheme will achieve the highest frame rate possible. The
+documentation for <code>SwapBuffers</code> explains why this is optimal: because the
+callback is executed only when the plugin&#8217;s current state is actually on the
+screen, this function provides a way to rate-limit animations. By waiting until
+the image is on the screen before painting the next frame, you can ensure you&#8217;re
+not generating updates faster than the screen can be updated.</p>
+<p>The following diagram illustrates the interaction between the Chrome and Native
+Client processes. The application-specific rendering code runs in the function
+called <code>Draw</code> on the Native Client thread. Blue down-arrows are blocking calls
+from the main thread to Native Client, green up-arrows are non-blocking
+<code>SwapBuffers</code> calls from Native Client to the main thread. All OpenGL ES 2.0
+calls are made from <code>Draw</code> in the Native Client thread.</p>
+<img alt="/native-client/images/3d-graphics-render-loop.png" src="/native-client/images/3d-graphics-render-loop.png" />
+</section><section id="sdk-example-graphics-3d">
+<h3 id="sdk-example-graphics-3d">SDK example <code>graphics_3d</code></h3>
+<p>The SDK example <code>graphics_3d</code> uses the function <code>MainLoop</code> (in
+<code>hello_world.cc</code>) to create a rendering loop as described above. <code>MainLoop</code>
+calls <code>Render</code> to do the rendering work, and then invokes <code>SwapBuffers</code>,
+passing itself as the callback.</p>
+<pre class="prettyprint">
+void MainLoop(void* foo, int bar) {
+ if (g_LoadCnt == 3) {
+ InitProgram();
+ g_LoadCnt++;
+ }
+ if (g_LoadCnt &gt; 3) {
+ Render();
+ PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
+ ppb_g3d_interface-&gt;SwapBuffers(g_context, cc);
+ } else {
+ PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
+ ppb_core_interface-&gt;CallOnMainThread(0, cc, 0);
+ }
+}
+</pre>
+</section></section><section id="managing-the-opengl-es-2-0-pipeline">
+<h2 id="managing-the-opengl-es-2-0-pipeline">Managing the OpenGL ES 2.0 pipeline</h2>
+<p>OpenGL ES 2.0 commands do not run in the Chrome or Native Client processes. They
+are passed into a FIFO queue in shared memory which is best understood as a <a class="reference external" href="http://www.chromium.org/developers/design-documents/gpu-command-buffer">GPU
+command buffer</a>. The
+command buffer is shared by a dedicated GPU process. By using a separate GPU
+process, Chrome implements another layer of runtime security, vetting all OpenGL
+ES 2.0 commands and their arguments before they are sent on to the
+GPU. Buffering commands through the FIFO also speeds up your code, since each
+OpenGL ES 2.0 call in your Native Client thread returns immediately, while the
+processing may be delayed as the GPU works down the commands queued up in the
+FIFO.</p>
+<p>Before the screen is updated, all the intervening OpenGL ES 2.0 commands must be
+processed by the GPU. Programmers often try to ensure this by using the
+<code>glFlush</code> and <code>glFinish</code> commands in their rendering code. In the case of
+Native Client this is usually unnecessary. The <code>SwapBuffers</code> command does an
+implicit flush, and the Chrome team is continually tweaking the GPU code to
+consume the OpenGL ES 2.0 FIFO as fast as possible.</p>
+<p>Sometimes a 3D application can write to the FIFO in a way that&#8217;s difficult to
+handle. The command pipeline may fill up and your code will have to wait for the
+GPU to flush the FIFO. If this is the case, you may be able to add <code>glFlush</code>
+calls to speed up the flow of the OpenGL ES 2.0 command FIFO. Before you start
+to add your own flushes, first try to determine if pipeline saturation is really
+the problem by monitoring the rendering time per frame and looking for irregular
+spikes that do not consistently fall on the same OpenGL ES 2.0 call. If you&#8217;re
+convinced the pipeline needs to be accelerated, insert <code>glFlush</code> calls in your
+code before starting blocks of processing that do not generate OpenGL ES 2.0
+commands. For example, issue a flush before you begin any multithreaded particle
+work, so that the command buffer will be clear when you start doing OpenGL ES
+2.0 calls again. Determining where and how often to call <code>glFlush</code> can be
+tricky, you will need to experiment to find the sweet spot.</p>
+</section><section id="rendering-and-inactive-tabs">
+<h2 id="rendering-and-inactive-tabs">Rendering and inactive tabs</h2>
+<p>Users will often switch between tabs in a multi-tab browser. A well-behaved
+application that&#8217;s performing 3D rendering should pause any real-time processing
+and yield cycles to other processes when its tab becomes inactive.</p>
+<p>In Chrome, an inactive tab will continue to execute timed functions (such as
+<code>setInterval</code> and <code>setTimeout</code>) but the timer interval will be automatically
+overridden and limited to not less than one second while the tab is inactive. In
+addition, any callback associated with a <code>SwapBuffers</code> call will not be sent
+until the tab is active again. You may receive asynchronous callbacks from
+functions other than <code>SwapBuffers</code> while a tab is inactive. Depending on the
+design of your application, you might choose to handle them as they arrive, or
+to queue them in a buffer and process them when the tab becomes active.</p>
+<p>The time that passes while a tab is inactive can be considerable. If your main
+thread pulse is based on the <code>SwapBuffers</code> callback, your app won&#8217;t update
+while a tab is inactive. A Native Client module should be able to detect and
+respond to the state of the tab in which it&#8217;s running. For example, when a tab
+becomes inactive, you can set an atomic flag in the Native Client thread that
+will skip the 3D rendering and <code>SwapBuffers</code> calls and continue to call the
+main thread every 30 msec or so. This provides time to update features that
+should still run in the background, like audio. It may also be helpful to call
+<code>sched_yield</code> or <code>usleep</code> on any worker threads to release resources and
+cede cycles to the OS.</p>
+<section id="handling-tab-activation-from-the-main-thread">
+<h3 id="handling-tab-activation-from-the-main-thread">Handling tab activation from the main thread</h3>
+<p>You can detect and respond to the activation or deactivation of a tab with
+JavaScript on your hosting page. Add an EventListener for <code>visibilitychange</code>
+that sends a message to the Native Client module, as in this example:</p>
+<pre class="prettyprint">
+document.addEventListener('visibilitychange', function(){
+ if (document.hidden) {
+ // PostMessage to your Native Client module
+ document.nacl_module.postMessage('INACTIVE');
+ } else {
+ // PostMessage to your Native Client module
+ document.nacl_module.postMessage('ACTIVE');
+ }
+
+}, false);
+</pre>
+</section><section id="handling-tab-activation-from-the-native-client-thread">
+<h3 id="handling-tab-activation-from-the-native-client-thread">Handling tab activation from the Native Client thread</h3>
+<p>You can also detect and respond to the activation or deactivation of a tab
+directly from your Native Client module by including code in the function
+<code>pp::Instance::DidChangeView</code>, which is called whenever a change in the
+module&#8217;s view occurs. The code can call <code>ppb::View::IsPageVisible</code> to
+determine if the page is visible or not. The most common cause of invisible
+pages is that the page is in a background tab.</p>
+</section></section><section id="tips-and-best-practices">
+<h2 id="tips-and-best-practices">Tips and best practices</h2>
+<p>Here are some suggestions for writing safe code and getting the maximum
+performance with the Pepper 3D API.</p>
+<section id="do-s">
+<h3 id="do-s">Do&#8217;s</h3>
+<ul class="small-gap">
+<li><p class="first"><strong>Make sure to enable attrib 0.</strong> OpenGL requires that you enable attrib 0,
+but OpenGL ES 2.0 does not. For example, you can define a vertex shader with 2
+attributes, numbered like this:</p>
+<pre class="prettyprint">
+glBindAttribLocation(program, &quot;positions&quot;, 1);
+glBindAttribLocation(program, &quot;normals&quot;, 2);
+</pre>
+<p>In this case the shader is not using attrib 0 and Chrome may have to perform
+some additional work if it is emulating OpenGL ES 2.0 on top of OpenGL. It&#8217;s
+always more efficient to enable attrib 0, even if you do not use it.</p>
+</li>
+<li><strong>Check how shaders compile.</strong> Shaders can compile differently on different
+systems, which can result in <code>glGetAttrib*</code> functions returning different
+results. Be sure that the vertex attribute indices match the corresponding
+name each time you recompile a shader.</li>
+<li><strong>Update indices sparingly.</strong> For security reasons, all indices must be
+validated. If you change indices, Native Client will validate them
+again. Structure your code so indices are not updated often.</li>
+<li><strong>Use a smaller plugin and let CSS scale it.</strong> If you&#8217;re running into fillrate
+issues, it may be beneficial to perform scaling via CSS. The size your plugin
+renders is determined by the width and height attributes of the <code>&lt;embed&gt;</code>
+element for the module. The actual size displayed on the web page is
+controlled by the CSS styles applied to the element.</li>
+<li><strong>Avoid matrix-to-matrix conversions.</strong> With some versions of Mac OS, there is
+a driver problem when compiling shaders. If you get compiler errors for matrix
+transforms, avoid matrix-to-matrix conversions. For instance, upres a vec3 to
+a vec4 before transforming it by a mat4, rather than converting the mat4 to a
+mat3.</li>
+</ul>
+</section><section id="don-ts">
+<h3 id="don-ts">Don&#8217;ts</h3>
+<ul class="small-gap">
+<li><strong>Don&#8217;t use client side buffers.</strong> OpenGL ES 2.0 can use client side data with
+<code>glVertexAttribPointer</code> and <code>glDrawElements</code>, but this is really slow. Try
+to avoid client side buffers. Use Vertex Buffer Objects (VBOs) instead.</li>
+<li><strong>Don&#8217;t mix vertex data and index data.</strong> By default, Pepper 3D binds buffers
+to a single point. You could create a buffer and bind it to both
+<code>GL_ARRAY_BUFFER</code> and <code>GL_ELEMENT_ARRAY_BUFFER</code>, but that would be
+expensive overhead and it is not recommended.</li>
+<li><strong>Don&#8217;t call ``glGet*`` or ``glCheck*`` during rendering.</strong> This is normal
+advice for OpenGL programs, but is particularly important for 3D on
+Chrome. Calls to any OpenGL ES 2.0 function whose name begins with these
+strings blocks the Native Client thread. This includes <code>glGetError</code>; avoid
+calling it in release builds.</li>
+<li><strong>Don&#8217;t use fixed point (``GL_FIXED``) vertex attributes.</strong> Fixed point
+attributes are not supported in OpenGL ES 2.0, so emulating them in OpenGL ES
+2.0 is slow. By default, <code>GL_FIXED</code> support is turned off in the Pepper 3D
+API.</li>
+<li><strong>Don&#8217;t read data from the GPU.</strong> Don&#8217;t call <code>glReadPixels</code>, as it is slow.</li>
+<li><strong>Don&#8217;t update a small portion of a large buffer.</strong> In the current OpenGL ES
+2.0 implementation when you update a portion of a buffer (with
+<code>glSubBufferData</code> for example) the entire buffer must be reprocessed. To
+avoid this problem, keep static and dynamic data in different buffers.</li>
+<li><strong>Don&#8217;t call ``glDisable(GL_TEXTURE_2D)``.</strong> This is an OpenGL ES 2.0
+error. Each time it is called, an error messages will appear in Chrome&#8217;s
+<code>about:gpu</code> tab.</li>
+</ul>
+</section></section></section>
+
+{{/partials.standard_nacl_article}}

Powered by Google App Engine
This is Rietveld 408576698