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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 {{+bindTo:partials.standard_nacl_article}}
2
3 <section id="d-graphics">
4 <span id="devguide-coding-3d-graphics"></span><h1 id="d-graphics"><span id="devg uide-coding-3d-graphics"></span>3D Graphics</h1>
5 <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 d ocument
6 describes how to call the OpenGL ES 2.0 interface in a Native Client module and
7 how to build an efficient rendering loop. It also explains how to validate GPU
8 drivers and test for specific GPU capabilities, and provides tips to help ensure
9 your rendering code runs efficiently.</p>
10 <aside class="note">
11 <strong>Note</strong>: 3D drawing and OpenGL are complex topics. This document d eals only
12 with issues directly related to programming in the Native Client
13 environment. To learn more about OpenGL ES 2.0 itself, see the <a class="referen ce external" href="http://opengles-book.com/">OpenGL ES 2.0
14 Programming Guide</a>.
15 </aside>
16 <section id="validating-the-client-graphics-platform">
17 <h2 id="validating-the-client-graphics-platform">Validating the client graphics platform</h2>
18 <p>Native Client is a software technology that lets you code an application once
19 and run it on multiple platforms without worrying about the implementation
20 details on every possible target platform. It&#8217;s difficult to provide the s ame
21 support at the hardware level. Graphics hardware comes from many different
22 manufacturers and is controlled by drivers of varying quality. A particular GPU
23 driver may not support every OpenGL ES 2.0 feature, and some drivers are known
24 to have vulnerabilities that can be exploited.</p>
25 <p>Even if the GPU driver is safe to use, your program should perform a validati on
26 check before you launch your application to ensure that the driver supports all
27 the features you need.</p>
28 <section id="vetting-the-driver-in-javascript">
29 <h3 id="vetting-the-driver-in-javascript">Vetting the driver in JavaScript</h3>
30 <p>At startup, the application should perform a few additional tests that can be
31 implemented in JavaScript on its hosting web page. The script that performs
32 these tests should be included before the module&#8217;s <code>embed</code> tag, and ideally
33 the <code>embed</code> tag should appear on the hosting page only if these tests succeed.</p>
34 <p>The first thing to check is whether you can create a graphics context. If you
35 can, use the context to confirm the existence of any required OpenGL ES 2.0
36 extensions. You may want to refer to the <a class="reference external" href="ht tp://www.khronos.org/registry/webgl/extensions/">extension registry</a> and incl ude <a class="reference external" href="https://developer.mozilla.org/en-US/docs /WebGL/Using_Extensions">vendor
37 prefixes</a>
38 when checking for extensions.</p>
39 </section><section id="vetting-the-driver-in-native-client">
40 <h3 id="vetting-the-driver-in-native-client">Vetting the driver in Native Client </h3>
41 <section id="create-a-context">
42 <h4 id="create-a-context">Create a context</h4>
43 <p>Once you&#8217;ve passed the JavaScript validation tests, it&#8217;s safe to add a Native
44 Client embed tag to the hosting web page and load the module. As part of the
45 module initialization code, you must create a graphics context for the app by
46 either creating a C++ <code>Graphics3D</code> object or calling <code>PPB_Graphi cs3D</code> API
47 function <code>Create</code>. Don&#8217;t assume this will always succeed; you s till might have
48 problems creating the context. If you are in development mode and can&#8217;t cr eate
49 the context, try creating a simpler version to see if you&#8217;re asking for an
50 unsupported feature or exceeding a driver resource limit. Your production code
51 should always check that the context was created and fail gracefully if that&#82 17;s
52 not the case.</p>
53 </section><section id="check-for-extensions-and-capabilities">
54 <h4 id="check-for-extensions-and-capabilities">Check for extensions and capabili ties</h4>
55 <p>Not every GPU supports every extension or has the same amount of texture unit s,
56 vertex attributes, etc. On startup, call <code>glGetString(GL_EXTENSIONS)</code> and
57 check for the extensions and the features you need. For example:</p>
58 <ul class="small-gap">
59 <li>If you are using non power-of-2 texture with mipmaps, make sure
60 <code>GL_OES_texture_npot</code> exists.</li>
61 <li>If you are using floating point textures, make sure <code>GL_OES_texture_flo at</code>
62 exists.</li>
63 <li>If you are using DXT1, DXT3, or DXT5 textures, make sure the corresponding
64 extensions <code>EXT_texture_compression_dxt1</code>,
65 <code>GL_CHROMIUM_texture_compression_dxt3</code>, and
66 <code>GL_CHROMIUM_texture_compression_dxt5</code> exist.</li>
67 <li>If you are using the functions <code>glDrawArraysInstancedANGLE</code>,
68 <code>glDrawElementsInstancedANGLE</code>, <code>glVertexAttribDivisorANGLE</cod e>, or the PPAPI
69 interface <code>PPB_OpenGLES2InstancedArrays</code>, make sure the corresponding
70 extension <code>GL_ANGLE_instanced_arrays</code> exists.</li>
71 <li>If you are using the function <code>glRenderbufferStorageMultisampleEXT</cod e>, or the
72 PPAPI interface <code>PPB_OpenGLES2FramebufferMultisample</code>, make sure the
73 corresponding extension <code>GL_CHROMIUM_framebuffer_multisample</code> exists. </li>
74 <li>If you are using the functions <code>glGenQueriesEXT</code>, <code>glDeleteQ ueriesEXT</code>,
75 <code>glIsQueryEXT</code>, <code>glBeginQueryEXT</code>, <code>glEndQueryEXT</co de>, <code>glGetQueryivEXT</code>,
76 <code>glGetQueryObjectuivEXT</code>, or the PPAPI interface <code>PPB_OpenGLES2Q uery</code>,
77 make sure the corresponding extension <code>GL_EXT_occlusion_query_boolean</code >
78 exists.</li>
79 <li>If you are using the functions <code>glMapBufferSubDataCHROMIUM</code>,
80 <code>glUnmapBufferSubDataCHROMIUM</code>, <code>glMapTexSubImage2DCHROMIUM</cod e>,
81 <code>glUnmapTexSubImage2DCHROMIUM</code>, or the PPAPI interface
82 <code>PPB_OpenGLES2ChromiumMapSub</code>, make sure the corresponding extension
83 <code>GL_CHROMIUM_map_sub</code> exists.</li>
84 </ul>
85 <p>Check for system capabilites with <code>glGetIntegerv</code> and adjust shade r programs
86 as well as texture and vertex data accordingly:</p>
87 <ul class="small-gap">
88 <li>If you are using textures in vertex shaders, make sure
89 <code>glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, ...)</code> and
90 <code>glGetIntegerv(GL_MAX_TEXTURE_SIZE, ...)</code> return values greater than 0.</li>
91 <li>If you are using more than 8 textures in a single shader, make sure
92 <code>glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, ...)</code> returns a value grea ter
93 than or equal to the number of simultaneous textures you need.</li>
94 </ul>
95 </section></section><section id="vetting-the-driver-in-the-chrome-web-store">
96 <h3 id="vetting-the-driver-in-the-chrome-web-store">Vetting the driver in the Ch rome Web Store</h3>
97 <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
98 Store</a>, its Web Store
99 <a class="reference external" href="http://code.google.com/chrome/extensions/man ifest.html">manifest file</a> can
100 include the <code>webgl</code> feature in the requirements parameter. It looks l ike this:</p>
101 <pre class="prettyprint">
102 &quot;requirements&quot;: {
103 &quot;3D&quot;: {
104 &quot;features&quot;: [&quot;webgl&quot;]
105 }
106 }
107 </pre>
108 <p>While WebGL is technically a JavaScript API, specifying the <code>webgl</code > feature
109 also works for OpenGL ES 2.0 because both interfaces use the same driver.</p>
110 <p>This manifest item is not required, but if you include it, the Chrome Web Sto re
111 will prevent a user from installing the application if the browser is running on
112 a machine that does not support OpenGL ES 2.0 or that is using a known
113 blacklisted GPU driver that could invite an attack.</p>
114 <p>If the Web Store determines that the user&#8217;s driver is deficient, the ap p won&#8217;t
115 appear on the store&#8217;s tile display. However, it will appear in store searc h
116 results or if the user links to it directly, in which case the user could still
117 download it. But the manifest requirements will be checked when the user reaches
118 the install page, and if there is a problem, the browser will display the
119 message &#8220;This application is not supported on this computer. Installation has
120 been disabled.&#8221;</p>
121 <p>The manifest-based check applies only to downloads directly from the Chrome W eb
122 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_inst allation">inline
123 installation</a>.</p>
124 </section><section id="what-to-do-when-there-are-problems">
125 <h3 id="what-to-do-when-there-are-problems">What to do when there are problems</ h3>
126 <p>Using the vetting procedure described above, you should be able to detect the
127 most common problems before your application runs. If there are problems, your
128 code should describe the issue as clearly as possible. That&#8217;s easy if ther e is a
129 missing feature. Failure to create a graphics context is tougher to diagnose. At
130 the very least, you can suggest that the user try to update the driver. You
131 might want to linke to the Chrome page that describes <a class="reference extern al" href="http://support.google.com/chrome/bin/answer.py?hl=en&amp;answer=120294 6">how to do updates</a>.</p>
132 <p>If a user can&#8217;t update the driver, or their problem persists, be sure t o gather
133 information about their graphics environment. Ask for the contents of the Chrome
134 <code>about:gpu</code> page.</p>
135 </section><section id="document-unreliable-drivers">
136 <h3 id="document-unreliable-drivers">Document unreliable drivers</h3>
137 <p>It can be helpful to include information about known dubious drivers in your
138 user documentation. This might help identify if a rogue driver is the cause of a
139 problem. There are many sources of GPU driver blacklists. Two such lists can be
140 found at the <a class="reference external" href="http://src.chromium.org/viewvc/ chrome/trunk/deps/gpu/software_rendering_list/software_rendering_list.json">Chro mium project</a>
141 and <a class="reference external" href="http://www.khronos.org/webgl/wiki/Blackl istsAndWhitelists">Khronos</a>. You
142 can use these lists to include information in your documentation that warns
143 users about dangerous drivers.</p>
144 </section><section id="test-your-defenses">
145 <h3 id="test-your-defenses">Test your defenses</h3>
146 <p>You can test your driver validation code by running Chrome with the following
147 flags (all at once) and watching how your application responds:</p>
148 <ul class="small-gap">
149 <li><code>--disable-webgl</code></li>
150 <li><code>--disable-pepper-3d</code></li>
151 <li><code>--disable-gl-multisampling</code></li>
152 <li><code>--disable-accelerated-compositing</code></li>
153 <li><code>--disable-accelerated-2d-canvas</code></li>
154 </ul>
155 </section></section><section id="calling-opengl-es-2-0-commands">
156 <h2 id="calling-opengl-es-2-0-commands">Calling OpenGL ES 2.0 commands</h2>
157 <p>There are three ways to write OpenGL ES 2.0 calls in Native Client.</p>
158 <section id="use-pure-opengl-es-2-0-function-calls">
159 <h3 id="use-pure-opengl-es-2-0-function-calls">Use &#8220;pure&#8221; OpenGL ES 2.0 function calls</h3>
160 <p>You can make OpenGL ES 2.0 calls through a Pepper extension library. The SDK
161 example <code>examples/api/graphics_3d</code> works this way. In the file
162 <code>graphics_3d.cc</code>, the key initialization steps are as follows:</p>
163 <ul class="small-gap">
164 <li><p class="first">Add these includes at the top of the file:</p>
165 <pre class="prettyprint">
166 #include &lt;GLES2/gl2.h&gt;
167 #include &quot;ppapi/lib/gl/gles2/gl2ext_ppapi.h&quot;
168 </pre>
169 </li>
170 <li><p class="first">Define the function <code>InitGL</code>. The exact specific ation of <code>attrib_list</code>
171 will be application specific.</p>
172 <pre class="prettyprint">
173 bool InitGL(int32_t new_width, int32_t new_height) {
174 if (!glInitializePPAPI(pp::Module::Get()-&gt;get_browser_interface())) {
175 fprintf(stderr, &quot;Unable to initialize GL PPAPI!\n&quot;);
176 return false;
177 }
178
179 const int32_t attrib_list[] = {
180 PP_GRAPHICS3DATTRIB_ALPHA_SIZE, 8,
181 PP_GRAPHICS3DATTRIB_DEPTH_SIZE, 24,
182 PP_GRAPHICS3DATTRIB_WIDTH, new_width,
183 PP_GRAPHICS3DATTRIB_HEIGHT, new_height,
184 PP_GRAPHICS3DATTRIB_NONE
185 };
186
187 context_ = pp::Graphics3D(this, attrib_list);
188 if (!BindGraphics(context_)) {
189 fprintf(stderr, &quot;Unable to bind 3d context!\n&quot;);
190 context_ = pp::Graphics3D();
191 glSetCurrentContextPPAPI(0);
192 return false;
193 }
194
195 glSetCurrentContextPPAPI(context_.pp_resource());
196 return true;
197 }
198 </pre>
199 </li>
200 <li>Include logic in <code>Instance::DidChangeView</code> to call <code>InitGL</ code> whenever
201 necessary: upon application launch (when the graphics context is NULL) and
202 whenever the module&#8217;s View changes size.</li>
203 </ul>
204 </section><section id="use-regal">
205 <h3 id="use-regal">Use Regal</h3>
206 <p>If you are porting an OpenGL ES 2.0 application, or are comfortable writing i n
207 OpenGL ES 2.0, you should stick with the Pepper APIs or pure OpenGL ES 2.0 calls
208 described above. If you are porting an application that uses features not in
209 OpenGL ES 2.0, consider using Regal. Regal is an open source library that
210 supports many versions of OpenGL. Regal recently added support for Native
211 Client. Regal forwards most OpenGL calls directly to the underlying graphics
212 library, but it can also emulate other calls that are not included (when
213 hardware support exists). See <a class="reference external" href="http://www.alt devblogaday.com/2012/09/04/bringing-regal-opengl-to-native-client/">libregal</a>
214 for more info.</p>
215 </section><section id="use-the-pepper-api">
216 <h3 id="use-the-pepper-api">Use the Pepper API</h3>
217 <p>Your code can call the Pepper <a class="reference external" href="https://dev elopers.google.com/native-client/pepperc/struct_p_p_b___open_g_l_e_s2">PPB_OpenG LES2</a>
218 API directly, as with any Pepper interface. When you write in this way, each
219 invocation of an OpenGL ES 2.0 function must begin with a reference to the
220 Pepper interface, and the first argument is the graphics context. To invoke the
221 function <code>glCompileShader</code>, your code might look like:</p>
222 <pre class="prettyprint">
223 ppb_g3d_interface-&gt;CompileShader(graphicsContext, shader);
224 </pre>
225 <p>This approach specifically targets the Pepper APIs. Each call corresponds to a
226 OpenGL ES 2.0 function, but the syntax is unique to Native Client, so the source
227 file is not portable.</p>
228 </section></section><section id="implementing-a-rendering-loop">
229 <h2 id="implementing-a-rendering-loop">Implementing a rendering loop</h2>
230 <p>Graphics applications require a continuous frame render-and-redraw cycle that
231 runs at a high frequency. To achieve the best frame rate, is important to
232 understand how the OpenGL ES 2.0 code in a Native Client module interacts with
233 Chrome.</p>
234 <section id="the-chrome-and-native-client-processes">
235 <h3 id="the-chrome-and-native-client-processes">The Chrome and Native Client pro cesses</h3>
236 <p>Chrome is a multi-process browser. Each Chrome tab is a separate process that is
237 running an application with its own main thread (we&#8217;ll call it the Chrome main
238 thread). When an application launches a Native Client module, the module runs in
239 a new, separate sandboxed process. The module&#8217;s process has its own main t hread
240 (the Native Client thread). The Chrome and Native Client processes communicate
241 with each other using Pepper API calls on their main threads.</p>
242 <p>When the Chrome main thread calls the Native Client thread (keyboard and mous e
243 callbacks, for example), the Chrome main thread will block. This means that
244 lengthy operations on the Native Client thread can steal cycles from Chrome, and
245 performing blocking operations on the Native Client thread can bring your app to
246 a standstill.</p>
247 <p>Native Client uses callback functions to synchronize the main threads of the two
248 processes. Only certain Pepper functions use callbacks; <a class="reference exte rnal" href="https://developers.google.com/native-client/pepperc/struct_p_p_b___g raphics3_d__1__0#a293c6941c0da084267ffba3954793497">SwapBuffers</a>
249 is one.</p>
250 </section><section id="swapbuffers-and-its-callback-function">
251 <h3 id="swapbuffers-and-its-callback-function"><code>SwapBuffers</code> and its callback function</h3>
252 <p><code>SwapBuffers</code> is non-blocking; it is called from the Native Client thread and
253 returns immediately. When <code>SwapBuffers</code> is called, it runs asynchrono usly on
254 the Chrome main thread. It switches the graphics data buffers, handles any
255 needed compositing operations, and redraws the screen. When the screen update is
256 complete, the callback function that was included as one of <code>SwapBuffer</co de>&#8216;s
257 arguments will be called from the Chrome thread and executed on the Native
258 Client thread.</p>
259 <p>To create a rendering loop, your Native Client module should include a functi on
260 that does the rendering work and then executes <code>SwapBuffers</code>, passing itself
261 as the <code>SwapBuffer</code> callback. If your rendering code is efficient and runs
262 quickly, this scheme will achieve the highest frame rate possible. The
263 documentation for <code>SwapBuffers</code> explains why this is optimal: because the
264 callback is executed only when the plugin&#8217;s current state is actually on t he
265 screen, this function provides a way to rate-limit animations. By waiting until
266 the image is on the screen before painting the next frame, you can ensure you&#8 217;re
267 not generating updates faster than the screen can be updated.</p>
268 <p>The following diagram illustrates the interaction between the Chrome and Nati ve
269 Client processes. The application-specific rendering code runs in the function
270 called <code>Draw</code> on the Native Client thread. Blue down-arrows are block ing calls
271 from the main thread to Native Client, green up-arrows are non-blocking
272 <code>SwapBuffers</code> calls from Native Client to the main thread. All OpenGL ES 2.0
273 calls are made from <code>Draw</code> in the Native Client thread.</p>
274 <img alt="/native-client/images/3d-graphics-render-loop.png" src="/native-client /images/3d-graphics-render-loop.png" />
275 </section><section id="sdk-example-graphics-3d">
276 <h3 id="sdk-example-graphics-3d">SDK example <code>graphics_3d</code></h3>
277 <p>The SDK example <code>graphics_3d</code> uses the function <code>MainLoop</co de> (in
278 <code>hello_world.cc</code>) to create a rendering loop as described above. <cod e>MainLoop</code>
279 calls <code>Render</code> to do the rendering work, and then invokes <code>SwapB uffers</code>,
280 passing itself as the callback.</p>
281 <pre class="prettyprint">
282 void MainLoop(void* foo, int bar) {
283 if (g_LoadCnt == 3) {
284 InitProgram();
285 g_LoadCnt++;
286 }
287 if (g_LoadCnt &gt; 3) {
288 Render();
289 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
290 ppb_g3d_interface-&gt;SwapBuffers(g_context, cc);
291 } else {
292 PP_CompletionCallback cc = PP_MakeCompletionCallback(MainLoop, 0);
293 ppb_core_interface-&gt;CallOnMainThread(0, cc, 0);
294 }
295 }
296 </pre>
297 </section></section><section id="managing-the-opengl-es-2-0-pipeline">
298 <h2 id="managing-the-opengl-es-2-0-pipeline">Managing the OpenGL ES 2.0 pipeline </h2>
299 <p>OpenGL ES 2.0 commands do not run in the Chrome or Native Client processes. T hey
300 are passed into a FIFO queue in shared memory which is best understood as a <a c lass="reference external" href="http://www.chromium.org/developers/design-docume nts/gpu-command-buffer">GPU
301 command buffer</a>. The
302 command buffer is shared by a dedicated GPU process. By using a separate GPU
303 process, Chrome implements another layer of runtime security, vetting all OpenGL
304 ES 2.0 commands and their arguments before they are sent on to the
305 GPU. Buffering commands through the FIFO also speeds up your code, since each
306 OpenGL ES 2.0 call in your Native Client thread returns immediately, while the
307 processing may be delayed as the GPU works down the commands queued up in the
308 FIFO.</p>
309 <p>Before the screen is updated, all the intervening OpenGL ES 2.0 commands must be
310 processed by the GPU. Programmers often try to ensure this by using the
311 <code>glFlush</code> and <code>glFinish</code> commands in their rendering code. In the case of
312 Native Client this is usually unnecessary. The <code>SwapBuffers</code> command does an
313 implicit flush, and the Chrome team is continually tweaking the GPU code to
314 consume the OpenGL ES 2.0 FIFO as fast as possible.</p>
315 <p>Sometimes a 3D application can write to the FIFO in a way that&#8217;s diffic ult to
316 handle. The command pipeline may fill up and your code will have to wait for the
317 GPU to flush the FIFO. If this is the case, you may be able to add <code>glFlush </code>
318 calls to speed up the flow of the OpenGL ES 2.0 command FIFO. Before you start
319 to add your own flushes, first try to determine if pipeline saturation is really
320 the problem by monitoring the rendering time per frame and looking for irregular
321 spikes that do not consistently fall on the same OpenGL ES 2.0 call. If you&#821 7;re
322 convinced the pipeline needs to be accelerated, insert <code>glFlush</code> call s in your
323 code before starting blocks of processing that do not generate OpenGL ES 2.0
324 commands. For example, issue a flush before you begin any multithreaded particle
325 work, so that the command buffer will be clear when you start doing OpenGL ES
326 2.0 calls again. Determining where and how often to call <code>glFlush</code> ca n be
327 tricky, you will need to experiment to find the sweet spot.</p>
328 </section><section id="rendering-and-inactive-tabs">
329 <h2 id="rendering-and-inactive-tabs">Rendering and inactive tabs</h2>
330 <p>Users will often switch between tabs in a multi-tab browser. A well-behaved
331 application that&#8217;s performing 3D rendering should pause any real-time proc essing
332 and yield cycles to other processes when its tab becomes inactive.</p>
333 <p>In Chrome, an inactive tab will continue to execute timed functions (such as
334 <code>setInterval</code> and <code>setTimeout</code>) but the timer interval wil l be automatically
335 overridden and limited to not less than one second while the tab is inactive. In
336 addition, any callback associated with a <code>SwapBuffers</code> call will not be sent
337 until the tab is active again. You may receive asynchronous callbacks from
338 functions other than <code>SwapBuffers</code> while a tab is inactive. Depending on the
339 design of your application, you might choose to handle them as they arrive, or
340 to queue them in a buffer and process them when the tab becomes active.</p>
341 <p>The time that passes while a tab is inactive can be considerable. If your mai n
342 thread pulse is based on the <code>SwapBuffers</code> callback, your app won&#82 17;t update
343 while a tab is inactive. A Native Client module should be able to detect and
344 respond to the state of the tab in which it&#8217;s running. For example, when a tab
345 becomes inactive, you can set an atomic flag in the Native Client thread that
346 will skip the 3D rendering and <code>SwapBuffers</code> calls and continue to ca ll the
347 main thread every 30 msec or so. This provides time to update features that
348 should still run in the background, like audio. It may also be helpful to call
349 <code>sched_yield</code> or <code>usleep</code> on any worker threads to release resources and
350 cede cycles to the OS.</p>
351 <section id="handling-tab-activation-from-the-main-thread">
352 <h3 id="handling-tab-activation-from-the-main-thread">Handling tab activation fr om the main thread</h3>
353 <p>You can detect and respond to the activation or deactivation of a tab with
354 JavaScript on your hosting page. Add an EventListener for <code>visibilitychange </code>
355 that sends a message to the Native Client module, as in this example:</p>
356 <pre class="prettyprint">
357 document.addEventListener('visibilitychange', function(){
358 if (document.hidden) {
359 // PostMessage to your Native Client module
360 document.nacl_module.postMessage('INACTIVE');
361 } else {
362 // PostMessage to your Native Client module
363 document.nacl_module.postMessage('ACTIVE');
364 }
365
366 }, false);
367 </pre>
368 </section><section id="handling-tab-activation-from-the-native-client-thread">
369 <h3 id="handling-tab-activation-from-the-native-client-thread">Handling tab acti vation from the Native Client thread</h3>
370 <p>You can also detect and respond to the activation or deactivation of a tab
371 directly from your Native Client module by including code in the function
372 <code>pp::Instance::DidChangeView</code>, which is called whenever a change in t he
373 module&#8217;s view occurs. The code can call <code>ppb::View::IsPageVisible</co de> to
374 determine if the page is visible or not. The most common cause of invisible
375 pages is that the page is in a background tab.</p>
376 </section></section><section id="tips-and-best-practices">
377 <h2 id="tips-and-best-practices">Tips and best practices</h2>
378 <p>Here are some suggestions for writing safe code and getting the maximum
379 performance with the Pepper 3D API.</p>
380 <section id="do-s">
381 <h3 id="do-s">Do&#8217;s</h3>
382 <ul class="small-gap">
383 <li><p class="first"><strong>Make sure to enable attrib 0.</strong> OpenGL requi res that you enable attrib 0,
384 but OpenGL ES 2.0 does not. For example, you can define a vertex shader with 2
385 attributes, numbered like this:</p>
386 <pre class="prettyprint">
387 glBindAttribLocation(program, &quot;positions&quot;, 1);
388 glBindAttribLocation(program, &quot;normals&quot;, 2);
389 </pre>
390 <p>In this case the shader is not using attrib 0 and Chrome may have to perform
391 some additional work if it is emulating OpenGL ES 2.0 on top of OpenGL. It&#8217 ;s
392 always more efficient to enable attrib 0, even if you do not use it.</p>
393 </li>
394 <li><strong>Check how shaders compile.</strong> Shaders can compile differently on different
395 systems, which can result in <code>glGetAttrib*</code> functions returning diffe rent
396 results. Be sure that the vertex attribute indices match the corresponding
397 name each time you recompile a shader.</li>
398 <li><strong>Update indices sparingly.</strong> For security reasons, all indices must be
399 validated. If you change indices, Native Client will validate them
400 again. Structure your code so indices are not updated often.</li>
401 <li><strong>Use a smaller plugin and let CSS scale it.</strong> If you&#8217;re running into fillrate
402 issues, it may be beneficial to perform scaling via CSS. The size your plugin
403 renders is determined by the width and height attributes of the <code>&lt;embed& gt;</code>
404 element for the module. The actual size displayed on the web page is
405 controlled by the CSS styles applied to the element.</li>
406 <li><strong>Avoid matrix-to-matrix conversions.</strong> With some versions of M ac OS, there is
407 a driver problem when compiling shaders. If you get compiler errors for matrix
408 transforms, avoid matrix-to-matrix conversions. For instance, upres a vec3 to
409 a vec4 before transforming it by a mat4, rather than converting the mat4 to a
410 mat3.</li>
411 </ul>
412 </section><section id="don-ts">
413 <h3 id="don-ts">Don&#8217;ts</h3>
414 <ul class="small-gap">
415 <li><strong>Don&#8217;t use client side buffers.</strong> OpenGL ES 2.0 can use client side data with
416 <code>glVertexAttribPointer</code> and <code>glDrawElements</code>, but this is really slow. Try
417 to avoid client side buffers. Use Vertex Buffer Objects (VBOs) instead.</li>
418 <li><strong>Don&#8217;t mix vertex data and index data.</strong> By default, Pep per 3D binds buffers
419 to a single point. You could create a buffer and bind it to both
420 <code>GL_ARRAY_BUFFER</code> and <code>GL_ELEMENT_ARRAY_BUFFER</code>, but that would be
421 expensive overhead and it is not recommended.</li>
422 <li><strong>Don&#8217;t call ``glGet*`` or ``glCheck*`` during rendering.</stron g> This is normal
423 advice for OpenGL programs, but is particularly important for 3D on
424 Chrome. Calls to any OpenGL ES 2.0 function whose name begins with these
425 strings blocks the Native Client thread. This includes <code>glGetError</code>; avoid
426 calling it in release builds.</li>
427 <li><strong>Don&#8217;t use fixed point (``GL_FIXED``) vertex attributes.</stron g> Fixed point
428 attributes are not supported in OpenGL ES 2.0, so emulating them in OpenGL ES
429 2.0 is slow. By default, <code>GL_FIXED</code> support is turned off in the Pepp er 3D
430 API.</li>
431 <li><strong>Don&#8217;t read data from the GPU.</strong> Don&#8217;t call <code> glReadPixels</code>, as it is slow.</li>
432 <li><strong>Don&#8217;t update a small portion of a large buffer.</strong> In th e current OpenGL ES
433 2.0 implementation when you update a portion of a buffer (with
434 <code>glSubBufferData</code> for example) the entire buffer must be reprocessed. To
435 avoid this problem, keep static and dynamic data in different buffers.</li>
436 <li><strong>Don&#8217;t call ``glDisable(GL_TEXTURE_2D)``.</strong> This is an O penGL ES 2.0
437 error. Each time it is called, an error messages will appear in Chrome&#8217;s
438 <code>about:gpu</code> tab.</li>
439 </ul>
440 </section></section></section>
441
442 {{/partials.standard_nacl_article}}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698