Mercurial > sdl-ios-xcode
comparison docs/html/guidevideoopengl.html @ 55:55f1f1b3e27d
Added new docs for SDL 1.2.1
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Sun, 10 Jun 2001 19:31:57 +0000 |
parents | |
children | 355632dca928 |
comparison
equal
deleted
inserted
replaced
54:028447a8a758 | 55:55f1f1b3e27d |
---|---|
1 <HTML | |
2 ><HEAD | |
3 ><TITLE | |
4 >Using OpenGL With SDL</TITLE | |
5 ><META | |
6 NAME="GENERATOR" | |
7 CONTENT="Modular DocBook HTML Stylesheet Version 1.64 | |
8 "><LINK | |
9 REL="HOME" | |
10 TITLE="SDL Library Documentation" | |
11 HREF="index.html"><LINK | |
12 REL="UP" | |
13 TITLE="Graphics and Video" | |
14 HREF="guidevideo.html"><LINK | |
15 REL="PREVIOUS" | |
16 TITLE="Graphics and Video" | |
17 HREF="guidevideo.html"><LINK | |
18 REL="NEXT" | |
19 TITLE="Input handling" | |
20 HREF="guideinput.html"></HEAD | |
21 ><BODY | |
22 CLASS="SECT1" | |
23 BGCOLOR="#FFF8DC" | |
24 TEXT="#000000" | |
25 LINK="#0000ee" | |
26 VLINK="#551a8b" | |
27 ALINK="#ff0000" | |
28 ><DIV | |
29 CLASS="NAVHEADER" | |
30 ><TABLE | |
31 WIDTH="100%" | |
32 BORDER="0" | |
33 CELLPADDING="0" | |
34 CELLSPACING="0" | |
35 ><TR | |
36 ><TH | |
37 COLSPAN="3" | |
38 ALIGN="center" | |
39 >SDL Library Documentation</TH | |
40 ></TR | |
41 ><TR | |
42 ><TD | |
43 WIDTH="10%" | |
44 ALIGN="left" | |
45 VALIGN="bottom" | |
46 ><A | |
47 HREF="guidevideo.html" | |
48 >Prev</A | |
49 ></TD | |
50 ><TD | |
51 WIDTH="80%" | |
52 ALIGN="center" | |
53 VALIGN="bottom" | |
54 >Chapter 2. Graphics and Video</TD | |
55 ><TD | |
56 WIDTH="10%" | |
57 ALIGN="right" | |
58 VALIGN="bottom" | |
59 ><A | |
60 HREF="guideinput.html" | |
61 >Next</A | |
62 ></TD | |
63 ></TR | |
64 ></TABLE | |
65 ><HR | |
66 ALIGN="LEFT" | |
67 WIDTH="100%"></DIV | |
68 ><DIV | |
69 CLASS="SECT1" | |
70 ><H1 | |
71 CLASS="SECT1" | |
72 ><A | |
73 NAME="GUIDEVIDEOOPENGL" | |
74 >Using OpenGL With SDL</A | |
75 ></H1 | |
76 ><P | |
77 >SDL has the ability to create and use OpenGL contexts on several platforms(Linux/X11, Win32, BeOS, MacOS Classic/Toolbox, MacOS X, FreeBSD/X11 and Solaris/X11). This allows you to use SDL's audio, event handling, threads and times in your OpenGL applications (a function often performed by GLUT).</P | |
78 ><DIV | |
79 CLASS="SECT2" | |
80 ><H2 | |
81 CLASS="SECT2" | |
82 ><A | |
83 NAME="AEN103" | |
84 >Initialisation</A | |
85 ></H2 | |
86 ><P | |
87 >Initialising SDL to use OpenGL is not very different to initialising SDL normally. There are three differences; you must pass <TT | |
88 CLASS="LITERAL" | |
89 >SDL_OPENGL</TT | |
90 > to <A | |
91 HREF="sdlsetvideomode.html" | |
92 ><TT | |
93 CLASS="FUNCTION" | |
94 >SDL_SetVideoMode</TT | |
95 ></A | |
96 >, you must specify several GL attributes (depth buffer size, framebuffer sizes) using <A | |
97 HREF="sdlglsetattribute.html" | |
98 ><TT | |
99 CLASS="FUNCTION" | |
100 >SDL_GL_SetAttribute</TT | |
101 ></A | |
102 > and finally, if you wish to use double buffering you must specify it as a GL attribute, <I | |
103 CLASS="EMPHASIS" | |
104 >not</I | |
105 > by passing the <TT | |
106 CLASS="LITERAL" | |
107 >SDL_DOUBLEBUF</TT | |
108 > flag to <TT | |
109 CLASS="FUNCTION" | |
110 >SDL_SetVideoMode</TT | |
111 >.</P | |
112 ><DIV | |
113 CLASS="EXAMPLE" | |
114 ><A | |
115 NAME="AEN114" | |
116 ></A | |
117 ><P | |
118 ><B | |
119 >Example 2-7. Initializing SDL with OpenGL</B | |
120 ></P | |
121 ><PRE | |
122 CLASS="PROGRAMLISTING" | |
123 > /* Information about the current video settings. */ | |
124 const SDL_VideoInfo* info = NULL; | |
125 /* Dimensions of our window. */ | |
126 int width = 0; | |
127 int height = 0; | |
128 /* Color depth in bits of our window. */ | |
129 int bpp = 0; | |
130 /* Flags we will pass into SDL_SetVideoMode. */ | |
131 int flags = 0; | |
132 | |
133 /* First, initialize SDL's video subsystem. */ | |
134 if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { | |
135 /* Failed, exit. */ | |
136 fprintf( stderr, "Video initialization failed: %s\n", | |
137 SDL_GetError( ) ); | |
138 quit_tutorial( 1 ); | |
139 } | |
140 | |
141 /* Let's get some video information. */ | |
142 info = SDL_GetVideoInfo( ); | |
143 | |
144 if( !info ) { | |
145 /* This should probably never happen. */ | |
146 fprintf( stderr, "Video query failed: %s\n", | |
147 SDL_GetError( ) ); | |
148 quit_tutorial( 1 ); | |
149 } | |
150 | |
151 /* | |
152 * Set our width/height to 640/480 (you would | |
153 * of course let the user decide this in a normal | |
154 * app). We get the bpp we will request from | |
155 * the display. On X11, VidMode can't change | |
156 * resolution, so this is probably being overly | |
157 * safe. Under Win32, ChangeDisplaySettings | |
158 * can change the bpp. | |
159 */ | |
160 width = 640; | |
161 height = 480; | |
162 bpp = info->vfmt->BitsPerPixel; | |
163 | |
164 /* | |
165 * Now, we want to setup our requested | |
166 * window attributes for our OpenGL window. | |
167 * We want *at least* 5 bits of red, green | |
168 * and blue. We also want at least a 16-bit | |
169 * depth buffer. | |
170 * | |
171 * The last thing we do is request a double | |
172 * buffered window. '1' turns on double | |
173 * buffering, '0' turns it off. | |
174 * | |
175 * Note that we do not use SDL_DOUBLEBUF in | |
176 * the flags to SDL_SetVideoMode. That does | |
177 * not affect the GL attribute state, only | |
178 * the standard 2D blitting setup. | |
179 */ | |
180 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); | |
181 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); | |
182 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); | |
183 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); | |
184 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); | |
185 | |
186 /* | |
187 * We want to request that SDL provide us | |
188 * with an OpenGL window, in a fullscreen | |
189 * video mode. | |
190 * | |
191 * EXERCISE: | |
192 * Make starting windowed an option, and | |
193 * handle the resize events properly with | |
194 * glViewport. | |
195 */ | |
196 flags = SDL_OPENGL | SDL_FULLSCREEN; | |
197 | |
198 /* | |
199 * Set the video mode | |
200 */ | |
201 if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { | |
202 /* | |
203 * This could happen for a variety of reasons, | |
204 * including DISPLAY not being set, the specified | |
205 * resolution not being available, etc. | |
206 */ | |
207 fprintf( stderr, "Video mode set failed: %s\n", | |
208 SDL_GetError( ) ); | |
209 quit_tutorial( 1 ); | |
210 }</PRE | |
211 ></DIV | |
212 ></DIV | |
213 ><DIV | |
214 CLASS="SECT2" | |
215 ><H2 | |
216 CLASS="SECT2" | |
217 ><A | |
218 NAME="AEN117" | |
219 >Drawing</A | |
220 ></H2 | |
221 ><P | |
222 >Apart from initialisation, using OpenGL within SDL is the same as using OpenGL | |
223 with any other API, e.g. GLUT. You still use all the same function calls and | |
224 data types. However if you are using a double-buffered display, then you must | |
225 use | |
226 <A | |
227 HREF="sdlglswapbuffers.html" | |
228 ><TT | |
229 CLASS="FUNCTION" | |
230 >SDL_GL_SwapBuffers()</TT | |
231 ></A | |
232 > | |
233 to swap the buffers and update the display. To request double-buffering | |
234 with OpenGL, use | |
235 <A | |
236 HREF="sdlglsetattribute.html" | |
237 ><TT | |
238 CLASS="FUNCTION" | |
239 >SDL_GL_SetAttribute</TT | |
240 ></A | |
241 > | |
242 with <TT | |
243 CLASS="LITERAL" | |
244 >SDL_GL_DOUBLEBUFFER</TT | |
245 >, and use | |
246 <A | |
247 HREF="sdlglgetattribute.html" | |
248 ><TT | |
249 CLASS="FUNCTION" | |
250 >SDL_GL_GetAttribute</TT | |
251 ></A | |
252 > | |
253 to see if you actually got it.</P | |
254 ><P | |
255 >A full example code listing is now presented below.</P | |
256 ><DIV | |
257 CLASS="EXAMPLE" | |
258 ><A | |
259 NAME="AEN128" | |
260 ></A | |
261 ><P | |
262 ><B | |
263 >Example 2-8. SDL and OpenGL</B | |
264 ></P | |
265 ><PRE | |
266 CLASS="PROGRAMLISTING" | |
267 >/* | |
268 * SDL OpenGL Tutorial. | |
269 * (c) Michael Vance, 2000 | |
270 * briareos@lokigames.com | |
271 * | |
272 * Distributed under terms of the LGPL. | |
273 */ | |
274 | |
275 #include <SDL/SDL.h> | |
276 #include <GL/gl.h> | |
277 #include <GL/glu.h> | |
278 | |
279 #include <stdio.h> | |
280 #include <stdlib.h> | |
281 | |
282 static GLboolean should_rotate = GL_TRUE; | |
283 | |
284 static void quit_tutorial( int code ) | |
285 { | |
286 /* | |
287 * Quit SDL so we can release the fullscreen | |
288 * mode and restore the previous video settings, | |
289 * etc. | |
290 */ | |
291 SDL_Quit( ); | |
292 | |
293 /* Exit program. */ | |
294 exit( code ); | |
295 } | |
296 | |
297 static void handle_key_down( SDL_keysym* keysym ) | |
298 { | |
299 | |
300 /* | |
301 * We're only interested if 'Esc' has | |
302 * been presssed. | |
303 * | |
304 * EXERCISE: | |
305 * Handle the arrow keys and have that change the | |
306 * viewing position/angle. | |
307 */ | |
308 switch( keysym->sym ) { | |
309 case SDLK_ESCAPE: | |
310 quit_tutorial( 0 ); | |
311 break; | |
312 case SDLK_SPACE: | |
313 should_rotate = !should_rotate; | |
314 break; | |
315 default: | |
316 break; | |
317 } | |
318 | |
319 } | |
320 | |
321 static void process_events( void ) | |
322 { | |
323 /* Our SDL event placeholder. */ | |
324 SDL_Event event; | |
325 | |
326 /* Grab all the events off the queue. */ | |
327 while( SDL_PollEvent( &event ) ) { | |
328 | |
329 switch( event.type ) { | |
330 case SDL_KEYDOWN: | |
331 /* Handle key presses. */ | |
332 handle_key_down( &event.key.keysym ); | |
333 break; | |
334 case SDL_QUIT: | |
335 /* Handle quit requests (like Ctrl-c). */ | |
336 quit_tutorial( 0 ); | |
337 break; | |
338 } | |
339 | |
340 } | |
341 | |
342 } | |
343 | |
344 static void draw_screen( void ) | |
345 { | |
346 /* Our angle of rotation. */ | |
347 static float angle = 0.0f; | |
348 | |
349 /* | |
350 * EXERCISE: | |
351 * Replace this awful mess with vertex | |
352 * arrays and a call to glDrawElements. | |
353 * | |
354 * EXERCISE: | |
355 * After completing the above, change | |
356 * it to use compiled vertex arrays. | |
357 * | |
358 * EXERCISE: | |
359 * Verify my windings are correct here ;). | |
360 */ | |
361 static GLfloat v0[] = { -1.0f, -1.0f, 1.0f }; | |
362 static GLfloat v1[] = { 1.0f, -1.0f, 1.0f }; | |
363 static GLfloat v2[] = { 1.0f, 1.0f, 1.0f }; | |
364 static GLfloat v3[] = { -1.0f, 1.0f, 1.0f }; | |
365 static GLfloat v4[] = { -1.0f, -1.0f, -1.0f }; | |
366 static GLfloat v5[] = { 1.0f, -1.0f, -1.0f }; | |
367 static GLfloat v6[] = { 1.0f, 1.0f, -1.0f }; | |
368 static GLfloat v7[] = { -1.0f, 1.0f, -1.0f }; | |
369 static GLubyte red[] = { 255, 0, 0, 255 }; | |
370 static GLubyte green[] = { 0, 255, 0, 255 }; | |
371 static GLubyte blue[] = { 0, 0, 255, 255 }; | |
372 static GLubyte white[] = { 255, 255, 255, 255 }; | |
373 static GLubyte yellow[] = { 0, 255, 255, 255 }; | |
374 static GLubyte black[] = { 0, 0, 0, 255 }; | |
375 static GLubyte orange[] = { 255, 255, 0, 255 }; | |
376 static GLubyte purple[] = { 255, 0, 255, 0 }; | |
377 | |
378 /* Clear the color and depth buffers. */ | |
379 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); | |
380 | |
381 /* We don't want to modify the projection matrix. */ | |
382 glMatrixMode( GL_MODELVIEW ); | |
383 glLoadIdentity( ); | |
384 | |
385 /* Move down the z-axis. */ | |
386 glTranslatef( 0.0, 0.0, -5.0 ); | |
387 | |
388 /* Rotate. */ | |
389 glRotatef( angle, 0.0, 1.0, 0.0 ); | |
390 | |
391 if( should_rotate ) { | |
392 | |
393 if( ++angle > 360.0f ) { | |
394 angle = 0.0f; | |
395 } | |
396 | |
397 } | |
398 | |
399 /* Send our triangle data to the pipeline. */ | |
400 glBegin( GL_TRIANGLES ); | |
401 | |
402 glColor4ubv( red ); | |
403 glVertex3fv( v0 ); | |
404 glColor4ubv( green ); | |
405 glVertex3fv( v1 ); | |
406 glColor4ubv( blue ); | |
407 glVertex3fv( v2 ); | |
408 | |
409 glColor4ubv( red ); | |
410 glVertex3fv( v0 ); | |
411 glColor4ubv( blue ); | |
412 glVertex3fv( v2 ); | |
413 glColor4ubv( white ); | |
414 glVertex3fv( v3 ); | |
415 | |
416 glColor4ubv( green ); | |
417 glVertex3fv( v1 ); | |
418 glColor4ubv( black ); | |
419 glVertex3fv( v5 ); | |
420 glColor4ubv( orange ); | |
421 glVertex3fv( v6 ); | |
422 | |
423 glColor4ubv( green ); | |
424 glVertex3fv( v1 ); | |
425 glColor4ubv( orange ); | |
426 glVertex3fv( v6 ); | |
427 glColor4ubv( blue ); | |
428 glVertex3fv( v2 ); | |
429 | |
430 glColor4ubv( black ); | |
431 glVertex3fv( v5 ); | |
432 glColor4ubv( yellow ); | |
433 glVertex3fv( v4 ); | |
434 glColor4ubv( purple ); | |
435 glVertex3fv( v7 ); | |
436 | |
437 glColor4ubv( black ); | |
438 glVertex3fv( v5 ); | |
439 glColor4ubv( purple ); | |
440 glVertex3fv( v7 ); | |
441 glColor4ubv( orange ); | |
442 glVertex3fv( v6 ); | |
443 | |
444 glColor4ubv( yellow ); | |
445 glVertex3fv( v4 ); | |
446 glColor4ubv( red ); | |
447 glVertex3fv( v0 ); | |
448 glColor4ubv( white ); | |
449 glVertex3fv( v3 ); | |
450 | |
451 glColor4ubv( yellow ); | |
452 glVertex3fv( v4 ); | |
453 glColor4ubv( white ); | |
454 glVertex3fv( v3 ); | |
455 glColor4ubv( purple ); | |
456 glVertex3fv( v7 ); | |
457 | |
458 glColor4ubv( white ); | |
459 glVertex3fv( v3 ); | |
460 glColor4ubv( blue ); | |
461 glVertex3fv( v2 ); | |
462 glColor4ubv( orange ); | |
463 glVertex3fv( v6 ); | |
464 | |
465 glColor4ubv( white ); | |
466 glVertex3fv( v3 ); | |
467 glColor4ubv( orange ); | |
468 glVertex3fv( v6 ); | |
469 glColor4ubv( purple ); | |
470 glVertex3fv( v7 ); | |
471 | |
472 glColor4ubv( green ); | |
473 glVertex3fv( v1 ); | |
474 glColor4ubv( red ); | |
475 glVertex3fv( v0 ); | |
476 glColor4ubv( yellow ); | |
477 glVertex3fv( v4 ); | |
478 | |
479 glColor4ubv( green ); | |
480 glVertex3fv( v1 ); | |
481 glColor4ubv( yellow ); | |
482 glVertex3fv( v4 ); | |
483 glColor4ubv( black ); | |
484 glVertex3fv( v5 ); | |
485 | |
486 glEnd( ); | |
487 | |
488 /* | |
489 * EXERCISE: | |
490 * Draw text telling the user that 'Spc' | |
491 * pauses the rotation and 'Esc' quits. | |
492 * Do it using vetors and textured quads. | |
493 */ | |
494 | |
495 /* | |
496 * Swap the buffers. This this tells the driver to | |
497 * render the next frame from the contents of the | |
498 * back-buffer, and to set all rendering operations | |
499 * to occur on what was the front-buffer. | |
500 * | |
501 * Double buffering prevents nasty visual tearing | |
502 * from the application drawing on areas of the | |
503 * screen that are being updated at the same time. | |
504 */ | |
505 SDL_GL_SwapBuffers( ); | |
506 } | |
507 | |
508 static void setup_opengl( int width, int height ) | |
509 { | |
510 float ratio = (float) width / (float) height; | |
511 | |
512 /* Our shading model--Gouraud (smooth). */ | |
513 glShadeModel( GL_SMOOTH ); | |
514 | |
515 /* Culling. */ | |
516 glCullFace( GL_BACK ); | |
517 glFrontFace( GL_CCW ); | |
518 glEnable( GL_CULL_FACE ); | |
519 | |
520 /* Set the clear color. */ | |
521 glClearColor( 0, 0, 0, 0 ); | |
522 | |
523 /* Setup our viewport. */ | |
524 glViewport( 0, 0, width, height ); | |
525 | |
526 /* | |
527 * Change to the projection matrix and set | |
528 * our viewing volume. | |
529 */ | |
530 glMatrixMode( GL_PROJECTION ); | |
531 glLoadIdentity( ); | |
532 /* | |
533 * EXERCISE: | |
534 * Replace this with a call to glFrustum. | |
535 */ | |
536 gluPerspective( 60.0, ratio, 1.0, 1024.0 ); | |
537 } | |
538 | |
539 int main( int argc, char* argv[] ) | |
540 { | |
541 /* Information about the current video settings. */ | |
542 const SDL_VideoInfo* info = NULL; | |
543 /* Dimensions of our window. */ | |
544 int width = 0; | |
545 int height = 0; | |
546 /* Color depth in bits of our window. */ | |
547 int bpp = 0; | |
548 /* Flags we will pass into SDL_SetVideoMode. */ | |
549 int flags = 0; | |
550 | |
551 /* First, initialize SDL's video subsystem. */ | |
552 if( SDL_Init( SDL_INIT_VIDEO ) < 0 ) { | |
553 /* Failed, exit. */ | |
554 fprintf( stderr, "Video initialization failed: %s\n", | |
555 SDL_GetError( ) ); | |
556 quit_tutorial( 1 ); | |
557 } | |
558 | |
559 /* Let's get some video information. */ | |
560 info = SDL_GetVideoInfo( ); | |
561 | |
562 if( !info ) { | |
563 /* This should probably never happen. */ | |
564 fprintf( stderr, "Video query failed: %s\n", | |
565 SDL_GetError( ) ); | |
566 quit_tutorial( 1 ); | |
567 } | |
568 | |
569 /* | |
570 * Set our width/height to 640/480 (you would | |
571 * of course let the user decide this in a normal | |
572 * app). We get the bpp we will request from | |
573 * the display. On X11, VidMode can't change | |
574 * resolution, so this is probably being overly | |
575 * safe. Under Win32, ChangeDisplaySettings | |
576 * can change the bpp. | |
577 */ | |
578 width = 640; | |
579 height = 480; | |
580 bpp = info->vfmt->BitsPerPixel; | |
581 | |
582 /* | |
583 * Now, we want to setup our requested | |
584 * window attributes for our OpenGL window. | |
585 * We want *at least* 5 bits of red, green | |
586 * and blue. We also want at least a 16-bit | |
587 * depth buffer. | |
588 * | |
589 * The last thing we do is request a double | |
590 * buffered window. '1' turns on double | |
591 * buffering, '0' turns it off. | |
592 * | |
593 * Note that we do not use SDL_DOUBLEBUF in | |
594 * the flags to SDL_SetVideoMode. That does | |
595 * not affect the GL attribute state, only | |
596 * the standard 2D blitting setup. | |
597 */ | |
598 SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 5 ); | |
599 SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 5 ); | |
600 SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 5 ); | |
601 SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 ); | |
602 SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); | |
603 | |
604 /* | |
605 * We want to request that SDL provide us | |
606 * with an OpenGL window, in a fullscreen | |
607 * video mode. | |
608 * | |
609 * EXERCISE: | |
610 * Make starting windowed an option, and | |
611 * handle the resize events properly with | |
612 * glViewport. | |
613 */ | |
614 flags = SDL_OPENGL | SDL_FULLSCREEN; | |
615 | |
616 /* | |
617 * Set the video mode | |
618 */ | |
619 if( SDL_SetVideoMode( width, height, bpp, flags ) == 0 ) { | |
620 /* | |
621 * This could happen for a variety of reasons, | |
622 * including DISPLAY not being set, the specified | |
623 * resolution not being available, etc. | |
624 */ | |
625 fprintf( stderr, "Video mode set failed: %s\n", | |
626 SDL_GetError( ) ); | |
627 quit_tutorial( 1 ); | |
628 } | |
629 | |
630 /* | |
631 * At this point, we should have a properly setup | |
632 * double-buffered window for use with OpenGL. | |
633 */ | |
634 setup_opengl( width, height ); | |
635 | |
636 /* | |
637 * Now we want to begin our normal app process-- | |
638 * an event loop with a lot of redrawing. | |
639 */ | |
640 while( 1 ) { | |
641 /* Process incoming events. */ | |
642 process_events( ); | |
643 /* Draw the screen. */ | |
644 draw_screen( ); | |
645 } | |
646 | |
647 /* | |
648 * EXERCISE: | |
649 * Record timings using SDL_GetTicks() and | |
650 * and print out frames per second at program | |
651 * end. | |
652 */ | |
653 | |
654 /* Never reached. */ | |
655 return 0; | |
656 }</PRE | |
657 ></DIV | |
658 ></DIV | |
659 ></DIV | |
660 ><DIV | |
661 CLASS="NAVFOOTER" | |
662 ><HR | |
663 ALIGN="LEFT" | |
664 WIDTH="100%"><TABLE | |
665 WIDTH="100%" | |
666 BORDER="0" | |
667 CELLPADDING="0" | |
668 CELLSPACING="0" | |
669 ><TR | |
670 ><TD | |
671 WIDTH="33%" | |
672 ALIGN="left" | |
673 VALIGN="top" | |
674 ><A | |
675 HREF="guidevideo.html" | |
676 >Prev</A | |
677 ></TD | |
678 ><TD | |
679 WIDTH="34%" | |
680 ALIGN="center" | |
681 VALIGN="top" | |
682 ><A | |
683 HREF="index.html" | |
684 >Home</A | |
685 ></TD | |
686 ><TD | |
687 WIDTH="33%" | |
688 ALIGN="right" | |
689 VALIGN="top" | |
690 ><A | |
691 HREF="guideinput.html" | |
692 >Next</A | |
693 ></TD | |
694 ></TR | |
695 ><TR | |
696 ><TD | |
697 WIDTH="33%" | |
698 ALIGN="left" | |
699 VALIGN="top" | |
700 >Graphics and Video</TD | |
701 ><TD | |
702 WIDTH="34%" | |
703 ALIGN="center" | |
704 VALIGN="top" | |
705 ><A | |
706 HREF="guidevideo.html" | |
707 >Up</A | |
708 ></TD | |
709 ><TD | |
710 WIDTH="33%" | |
711 ALIGN="right" | |
712 VALIGN="top" | |
713 >Input handling</TD | |
714 ></TR | |
715 ></TABLE | |
716 ></DIV | |
717 ></BODY | |
718 ></HTML | |
719 > |