BlackBerry_Java_SDK-Development_Guide--1246411-0802092654-001-6.0-US

Page 1

BlackBerry Java SDK Graphics and Animation Version: 6.0

Development Guide


Published: 2010-08-16 SWD-1246411-0816113432-001


Contents 1

Graphics........................................................................................................................................................................................ OpenGL ES....................................................................................................................................................................................... JSR 239 overview.................................................................................................................................................................... JSR 239 packages................................................................................................................................................................... EGL API - Native Platform Graphics Interface................................................................................................................... Set up EGL............................................................................................................................................................................... Native I/O............................................................................................................................................................................... 3-D math utilities................................................................................................................................................................... Naming conventions.............................................................................................................................................................. Data type mappings............................................................................................................................................................... OpenGL ES 1.1 core extensions............................................................................................................................................. OpenGL ES utilities................................................................................................................................................................ OpenGL ES code samples...................................................................................................................................................... OpenVG........................................................................................................................................................................................... Code sample: Drawing a triangle by using OpenVG.........................................................................................................

2 2 2 3 3 4 5 7 8 9 9 10 11 28 28

2 Animation..................................................................................................................................................................................... Animation API................................................................................................................................................................................. Key frames....................................................................................................................................................................................... Easing curves................................................................................................................................................................................... Predefined classes that implement the Animatable interface.................................................................................................. Create a custom class that implements the Animatable interface........................................................................................... Code sample: Animating a dropping ball in one-dimension.....................................................................................................

35 35 37 38 40 40 43

3 Related resources........................................................................................................................................................................

46

4 Glossary.........................................................................................................................................................................................

47

5 Provide feedback.........................................................................................................................................................................

48

6 Document revision history.........................................................................................................................................................

49

7 Legal notice..................................................................................................................................................................................

50


Development Guide

Graphics

Graphics

1

You can display graphics on a BlackBerry® device in a few different ways. For many types of applications, you can use predefined UI components that you add to a Screen object. Using this approach, you can add text, input controls, and images to your application screens. If you need to do custom drawing on a screen, you have two alternatives. You can override the paint() method of the class that represents the screen and use methods of the Graphics object to draw on the screen, or you can use OpenGL® ES or OpenVG™. Both OpenGL ES and OpenVG are optimized to use the graphics hardware to provide the best possible performance. If your custom drawing requirements are modest, you can override paint() and use methods of the Graphics object. If you have demanding 2-D drawing requirements, you should use OpenGL ES or OpenVG. If your application involves 3-D drawing, you should use OpenGL ES.

OpenGL ES OpenGL® is a graphics library that is designed to work closely with graphic display hardware to produce high-quality, real-time graphics. OpenGL provides very rudimentary mechanisms for describing the geometry of 3-D objects. It is not designed to help you create models of objects and doesn't have an associated model file format. Instead, it is designed to take a low-level description of 3-D modeled objects, textures to apply to those objects, lighting source descriptions, and the viewing perspective, and turn all of that 3-D input into a 2-D image to display on the screen. OpenGL solves this problem by using a series of steps that is sometimes called the OpenGL pipeline. What exactly happens during each step is affected by a number of settings that you can configure. These settings make up what is called the OpenGL state. It can be useful to think of OpenGL as a finite state machine. For example, when you change a setting, it stays in the state that you specify for all subsequent operations until you change it again. You create an environment that OpenGL operations take place in. At any time, you can alter that environment and that alters the effect of subsequent OpenGL operations. OpenGL® ES is a simplified version of OpenGL that is designed to run on less powerful, more resource-constrained devices, such as smartphones. OpenGL ES is specified as a set of differences from standard OpenGL. The primary difference between the two versions is that OpenGL ES offers you fewer options. However, OpenGL ES does include some extensions that are not available in standard OpenGL.

JSR 239 overview OpenGL® ES is specified as a C API. The JSR 239 specification describes a Java® API that is a thin layer over the C API that is described in the specification. You can use the APIs that are described in the JSR-239 specification to develop OpenGL ES applications on BlackBerry® devices.

2


OpenGL ES

Development Guide

JSR 239 packages Package

Description

javax.microedition.khronos.egl

provides bindings for EGL 1.0 and 1.1 provides bindings for OpenGL ES 1.0 and 1.1, including core profile extensions, optional profile extensions, and the extensions that are defined in the OpenGL ES 1.1 Extension Pack provides buffer classes that are modeled after those in the java.nio.Buffer package in Java® SE to use to store data on the native heap, which is required by some APIs that are described in the JSR 239 specification.

javax.microedition.khronos.opengles

java.nio

EGL API - Native Platform Graphics Interface You can use the javax.microedition.khronos.egl package to provide bindings for EGL™ 1.0 and 1.1 for the OpenGL® ES API. The rendering contexts that are supported provide a container for the OpenGL ES rendering state. The rendering surfaces that are supported include the following: • • •

Window surfaces: onscreen rendering Pbuffer surfaces: offscreen rendering of pixel buffers Pixmap surfaces: offscreen rendering to client buffers

The most commonly used feature of this package is the EGL10 interface. This interface contains the programming language bindings for EGL 1.0. All OpenGL ES drawing except to Pbuffer surfaces must be preceded by a call to eglWaitNative (EGL10.EGL_CORE_NATIVE_ENGINE, target) where target is an object that describes the rendering target. This must be followed by a call to eglWaitGL(). When drawing to an image, the results are not guaranteed to appear in the image pixels until eglWaitGL() has returned. Pbuffer surfaces are created using EGL10.eglCreatePbufferSurface() and are accessible only from EGL-based APIs.

Code sample: Rendering a single frame using EGL10 private void render() { if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { int error = egl.eglGetError();

3


Development Guide

}

OpenGL ES

if ( error == EGL11.EGL_CONTEXT_LOST ) handleContextLost(); else handleError("eglMakeCurrent failed: " + error);

// Signal that we're about to begin GL rendering egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, graphics); // Check for a viewport change if (vpWidth != getWidth() || vpHeight != getHeight()) { vpWidth = getWidth(); vpHeight = getHeight(); renderer.sizeChanged(gl, vpWidth, vpHeight); } renderer.render(gl);

}

// Signal that we're finish GL rendering egl.eglWaitGL();

Set up EGL 1.

Get an object that implements the EGL™ 1.1 interface. EGL11 egl = (EGL11)EGLContext.getEGL();

2.

Get and initialize the default EGL display. EGLDisplay eglDisplay = egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); egl.eglInitialize(eglDisplay, null);

3.

Specify the configuration attributes that you want. int[] configAttributes = { EGL11.EGL_RED_SIZE, 5, EGL11.EGL_GREEN_SIZE, 6, EGL11.EGL_BLUE_SIZE, 5, EGL11.EGL_ALPHA_SIZE, EGL11.EGL_DONT_CARE, EGL11.EGL_DEPTH_SIZE, EGL11.EGL_DONT_CARE, EGL11.EGL_STENCIL_SIZE, EGL11.EGL_DONT_CARE, EGL11.EGL_NONE}

4.

4

Create an integer array with one element to hold the return value that indicates the number of EGL configurations that matched the attributes specified by the configAttributes array. Create an EGLConfig array with one element to store the first EGL configuration that matches the attributes. Invoke eglChooseConfig() and provide, as arguments, the EGLDisplay object that you initialized in step 2, the array that specifies the configuration attributes to match, a


Development Guide

OpenGL ES

placeholder for the first matching EGLConfig object, the size of the EGLConfig placeholder (1), and the num_configs array to store the number of configurations that matched. Store the single configuration from the eglConfigs array in the EGLConfig variable eglConfig. int[] num_configs = new int[1]; EGLConfig[] eglConfigs = new EGLConfigs[1]; egl.eglChooseConfig(eglDisplay,configAttributes,eglConfigs,1, num_configs); EGLConfig eglConfig = eglConfigs[0];

5.

Invoke eglCreateWindowSurface() to create an EGL surface and provide, as arguments, eglDisplay and eglConfig, which are the instances of EGLDisplay and EGLConfig that you set up in steps 2 and 4. In the following code sample, eglCreateWindowSurface() is invoked from a class that is derived from the Screen class, and the this argument binds the EGLSurface object to the current screen. EGLSurface eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, this, null);

6.

Invoke eglCreateContext() to create an EGL context. EGLContext eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, null);

7.

Invoke eglMakeCurrent() to bind the EGL context to the EGL surface and EGL display. egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext);

You can now use the statement gl = (GL11)eglContext.getGL(); to get an object that implements the GL11 interface, which lets you start working with OpenGL ES 1.1.

Native I/O You can use the java.nio package to read and write data using block I/O operations. These operations let you send native, contiguous data to OpenGL速 ES. In contrast, arrays in Java速are not contiguous and require a lot of copying. The java.nio package provides direct buffers to communicate with OpenGL速 pointer functions, and wrapped buffers to access underlying Java arrays that cannot be passed to OpenGL pointer functions. Data types that are supported by the java.nio package include byte, short, int, and float.

Code sample: Defining the geometry for a 3D cube by using the java.nio package final class Cube { static FloatBuffer createVertexBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect (vertices.length * 4).asFloatBuffer(); buffer.put(vertices); buffer.rewind(); return buffer; }

5


Development Guide

static FloatBuffer createNormalBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect (normals.length * 4).asFloatBuffer(); buffer.put(normals); buffer.rewind(); return buffer; } static FloatBuffer createTexCoordBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect (texCoords.length * 4).asFloatBuffer(); buffer.put(texCoords); buffer.rewind(); return buffer; } private static float[] vertices = { // front -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, // right 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, // back 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, // left -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, // top -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,

};

// bottom -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f

private static float[] normals = { /* front */ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, /* right */ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, /* back */ 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, /* left */ -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, /* top */ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,

6

OpenGL ES


Development Guide

};

}

OpenGL ES

/* bottom */ 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0

private static float[] texCoords = { /* front */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, /* right */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, /* back */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, /* left */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, /* top */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, /* bottom */ 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1 };

3-D math utilities You can use methods in the net.rim.device.api.math package to enhance the speed and versatility of BlackBerry速 device applications that you create. You can use the math.Fixed32 class for a collection of fixed-point math routines that use the 16.16 convention to fix the decimal point. This convention means that the most significant 16 bits of a 32-bit integer is used for the fixed-point component of the value, and the remainder is used for the mantissa. Addition and subtraction operations are performed with regular integer + and - operators to help keep this library small. The numbers are signed, so negative numbers can be represented. The largest positive number in 16.16 format is just over 32767.9999, and the closest number to negative infinity is -32768.0. The smallest increment between consecutive numbers is 1/65536. You can use the math.Matrix4f class to create a 4-by-4 matrix of floating point numbers that represents a 3-D transformation. The math.Matrix4f class is directly compatible with OpenGL速 because its elements are stored in memory in the same manner that is used by OpenGL. You can use the math.Quaternion4f class to create a quaternion number that represents the orientation of an object in space. Quaternions are typically used as a replacement for Euler angles and rotation matrices as a way to achieve smooth interpolation and avoid gimbal lock. The math.Quaternion4f class does not keep the quaternion normalized, and you must normalize the quaternion when neccessary by invokingnormalize(). You can use the math.Vector3f class to create a 3-element vector of floating-point numbers. When you use a vector to represent a surface normal, the vector should typically be normalized. In other applications of directional vectors, you might want to leave the magnitude of the vector intact. When you use a vector to represent a point, the elements of the vector represent a position in 3-D space.

Code sample: Using Fixed32() import net.rim.device.api.math.*; public class demoFixed32 { demoFixed32()

7


Development Guide

{

OpenGL ES

// convert an integer to fixed-point int n = Fixed32.toFP(7); // 7.0 // convert a quantity in ten-thousandths to fixed-point int m = Fixed32.tenThouToFP(70625); // 7.0625 // convert from fixed-point, truncate fractional component int trunc = Fixed32.toInt(m); // 7 // multiply by ten thousand int mult = Fixed32.toIntTenThou(m); // 70625 // add, subtract, negate, and compare int result = m - n; // 7.0625 - 7.0 == 0.0625 result = -result; // -0.0625 result -= n; // -0.0625 - 7.0 == -7.0625 boolean b = (result == -m); // true boolean bb = (m < n); // false // do not use increment and decrement operators result = Fixed32.toFP(2); ++result; // WRONG! result will NOT be 3 result = Fixed32.toFP(2); result += Fixed32.toFP(1); // Correct: result will be 3 // Use * and / when multiplying or dividing by an integer scalar // Use mul to multiply 2 fixed-point numbers // Use div to divide 2 fixed-point numbers m = Fixed32.tenThouToFP(12500); // 1.25 m *= 3; // OK: 1.25 * 3 == 3.75 m /= 2; // OK: 3.75 / 2 == 1.875 m = Fixed32.mul(m, Fixed32.tenThouToFP(15000)); // 1.875 * 1.5000 == 2.8125 m = Fixed32.div(m, m); // 2.8125 / 2.8125 == 1.0

}

}

// mul, div, sqrt, sind, cosd, tand, and atand2 // all work with 16.16 fixed-point numbers m = Fixed32.tenThouToFP(172500); // 17.2500 n = Fixed32.sqrt(m); // sqrt(17.25) n = Fixed32.sind(m); // sine of 17.25 degrees n = Fixed32.cosd(m); // cosine of 17.25 degrees result = Fixed32.atand2(-m, -m); // -135.0 degrees in fixed-point

Naming conventions The naming conventions for OpenGL速 ES methods are the same as those for standard OpenGL速. For example:

8


OpenGL ES

Development Guide

• •

javax.microedition.khronos.opengles.GL10.glClear(int mask) javax.microedition.khronos.opengles.GL10.glLoadMatrixf(FloatBuffer m)

Fixed-point methods are named with an x suffix. For example: •

javax.microedition.khronos.opengles.GL10.glLoadMatrixx(IntBuffer m)

Constants are named using the same syntax and values as standard OpenGL. For example: •

javax.microedition.khronos.opengles.GL10.GL_TEXTURE0

Data type mappings Type Mappings Native data type All 8-bit integral types All 16-bit integral types All 32-bit integral types All 32-bit float types Pointer Mappings Native pointer

Java data type byte short int float

Java class

void*

java.nio.Buffer

int*

java.nio.IntBuffer

float*

java.nio.FloatBuffer

OpenGL ES 1.1 core extensions Extension

Description

GL_OES_byte_coordinates

lets you use the byte data type for vertex and texture coordinates implements an integer-based fixed-point data type that you can use when you define vertex data adds single-precision versions of glDepthRangef(), glFrustrumf(), glOrthof(), and glClearDepthf() lets you read matrix state lets you query for the optimal type and format combinations to use with glReadPixels()

GL_OES_fixed_point GL_OES_single_precision GL_OES_matrix_get GL_OES_read_format

9


OpenGL ES

Development Guide

Extension

Description

GL_OES_compressed_paletted_texture

lets you specify compressed texture images in color index formats, along with a color palette. lets you use point sprites lets you query the model view matrix, texture matrix, and projection matrix lets you draw a texture to a rectangular region on the screen lets you perform vertex skinning

GL_OES_point_sprite GL_OES_query_matrix GL_OES_draw_texture GL_OES_matrix_palette

OpenGL ES utilities You can use the net.rim.device.api.opengles.GLUtils class for higher-level functionality that is not provided by OpenGL® ES. Some of the methods that are provided include the following: • • • • • •

static boolean isSupported(): Determine if a BlackBerry® device supports OpenGL ES. static void gluPerspective(): Load a 3-D perspective projection matrix. static void gluLookAt(): Load a view transformation matrix. static void gluOrtho2D(): Define a 2-D orthographic projection matrix. static void glTexImage2D(): Load a texture from a Bitmap image. static boolean freeBuffer(): Free any native memory that is currently allocated for a direct buffer.

Code sample: Using gluPerspective() public void sizeChanged(GL10 gl, int width, int height) { // Update our viewport to reflect the new size gl.glViewport(0, 0, width, height); // Setup a perspective projection gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity();

}

10

net.rim.device.api.opengles.GLUtils.gluPerspective (gl, 45.0f, (float)width/(float)height, 0.15f, 100.0f);


OpenGL ES

Development Guide

OpenGL ES code samples Code sample: Determining OpenGL ES support import import import import import import

net.rim.device.api.ui.*; net.rim.device.api.ui.container.*; net.rim.device.api.ui.component.*; net.rim.device.api.opengles.*; javax.microedition.khronos.egl.*; javax.microedition.khronos.opengles.*;

public class OpenGLSupport extends UiApplication { public static void main( String[] args ) { OpenGLSupport app = new OpenGLSupport(); app.enterEventDispatcher(); } public OpenGLSupport() { pushScreen(new InfoScreen()); } } class InfoScreen extends MainScreen { private LabelField labelSupportMsg; private LabelField labelVendor; private LabelField labelRenderer; private LabelField labelVersion; private LabelField labelExtensions; private private private private private private

EGL11 _egl; EGLDisplay _eglDisplay; EGLSurface _eglSurface; EGLConfig _eglConfig; EGLContext _eglContext; GL10 _gl;

public InfoScreen() { boolean isSup = GLUtils.isSupported(); if(GLUtils.isSupported()) { labelSupportMsg = new LabelField("OpenGL ES is supported on this device."); _egl = (EGL11)EGLContext.getEGL();

11


OpenGL ES

Development Guide

_eglDisplay = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); int[] versionInfo = new int[2]; _egl.eglInitialize(_eglDisplay, versionInfo); EGLConfig[] configs = new EGLConfig[1]; int[] numConfigs = new int[1]; int[] attrs = { EGL11.EGL_RED_SIZE, 5, EGL11.EGL_GREEN_SIZE, 6, EGL11.EGL_BLUE_SIZE, 5, EGL11.EGL_NONE }; _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs); _eglConfig = configs[0]; _eglContext = _egl.eglCreateContext(_eglDisplay, _eglConfig, EGL10.EGL_NO_CONTEXT, null); _eglSurface = _egl.eglCreateWindowSurface(_eglDisplay, _eglConfig, this, null); _egl.eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext); _gl = (GL10)_eglContext.getGL(); labelVendor (GL10.GL_VENDOR)); labelRenderer (GL10.GL_RENDERER)); labelVersion (GL10.GL_VERSION)); labelExtensions (GL10.GL_EXTENSIONS));

= new LabelField("Vendor: " + _gl.glGetString = new LabelField("Renderer: " + _gl.glGetString = new LabelField("Version: " + _gl.glGetString = new LabelField("Extensions:\n" + _gl.glGetString

add(labelSupportMsg); add(labelVendor); add(labelRenderer); add(labelVersion); add(labelExtensions);

} else { device."); } } }

12

labelSupportMsg = new LabelField("OpenGL ES is not supported on this add(labelSupportMsg);


Development Guide

OpenGL ES

Code sample: Drawing a 3-D cube You can use the GL10 interface to draw a 3-D cube. import java.nio.ByteBuffer; import java.nio.FloatBuffer; import import import import import import import

javax.microedition.khronos.egl.EGL10; javax.microedition.khronos.egl.EGL11; javax.microedition.khronos.egl.EGLConfig; javax.microedition.khronos.egl.EGLContext; javax.microedition.khronos.egl.EGLDisplay; javax.microedition.khronos.egl.EGLSurface; javax.microedition.khronos.opengles.GL10;

import net.rim.device.api.system.Bitmap; import net.rim.device.api.ui.Graphics; import net.rim.device.api.ui.container.FullScreen; class ThreeDCube extends FullScreen implements Runnable { private EGL11 _egl; private EGLDisplay _eglDisplay; private EGLConfig _eglConfig; private EGLSurface _eglSurface; private EGLContext _eglContext; private GL10 _gl; private Bitmap _offscreenBitmap; private Graphics _offscreenGraphics; private boolean _running; private boolean _paused; private FloatBuffer _cubeVertices, _cubeNormals, _cubeColors; float _angle = 45f; private int _vertexCount; private static final float[] _vertices = { // front -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, // right 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f,

13


OpenGL ES

Development Guide

// back 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, // left -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, // top -0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f,

};

// bottom -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f

private static final float[] _normals = { /* front */ 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, /* right */ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, /* back */ 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, /* left */ -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, /* top */ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, /* bottom */ 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0 }; private static final float[] _colors = { /* front – white */ 1,1,1,1, 1,1,1,1, 1,1,1,1, /* right – red */ 1,0,0,1, 1,0,0,1, 1,0,0,1, /* back – green */ 0,1,0,1, 0,1,0,1, 0,1,0,1, /* left – blue */ 0,0,1,1, 0,0,1,1, 0,0,1,1, /* top - yellow */ 1,1,0,1, 1,1,0,1, /* bottom - magenta*/ 1,0,1,1, 1,0,1,1, };

1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,1, 1,0,0,1, 1,0,0,1, 0,1,0,1, 0,1,0,1, 0,1,0,1, 0,0,1,1, 0,0,1,1, 0,0,1,1, 1,1,0,1, 1,1,0,1, 1,1,0,1, 1,1,0,1, 1,0,1,1, 1,0,1,1, 1,0,1,1, 1,0,1,1

ThreeDCube() { super(FullScreen.DEFAULT_MENU | FullScreen.DEFAULT_CLOSE); } private void initialize() { // Get EGL interface _egl = (EGL11)EGLContext.getEGL();

14


Development Guide

OpenGL ES

// Get the EGL display _eglDisplay = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); //

// Initialize the display for EGL, null since we don't really need the version. _egl.eglInitialize(_eglDisplay, null); // Choose an EGL config EGLConfig[] configs = new EGLConfig[1]; int[] numConfigs = new int[1]; int[] attrs = { EGL11.EGL_RED_SIZE, 5, EGL11.EGL_GREEN_SIZE, 6, EGL11.EGL_BLUE_SIZE, 5, EGL11.EGL_NONE }; _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs); _eglConfig = configs[0]; // Create an EGL window surface _eglSurface = _egl.eglCreateWindowSurface (_eglDisplay, _eglConfig, this, null); // Create an EGL context createEGLContext(); _cubeVertices = createVertexBuffer(); _cubeNormals = createNormalBuffer(); _cubeColors = createColorBuffer(); }

_vertexCount = _vertices.length / 3;

private FloatBuffer createVertexBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect(_vertices.length * 4).asFloatBuffer(); buffer.put(_vertices); buffer.rewind(); return buffer; } private FloatBuffer createNormalBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect(_normals.length * 4).asFloatBuffer(); buffer.put(_normals); buffer.rewind(); return buffer; }

15


Development Guide

private FloatBuffer createColorBuffer() { FloatBuffer buffer = ByteBuffer.allocateDirect(_colors.length * 4).asFloatBuffer(); buffer.put(_colors); buffer.rewind(); return buffer; } private void createEGLContext() { // Create an EGL context _eglContext = _egl.eglCreateContext (_eglDisplay, _eglConfig, EGL10.EGL_NO_CONTEXT, null); // Get the GL interface for our new context _gl = (GL10)_eglContext.getGL();

}

// Make our new context current _egl.eglMakeCurrent (_eglDisplay, _eglSurface, _eglSurface, _eglContext);

private void destroyEGL() { _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); _egl.eglDestroyContext(_eglDisplay, _eglContext); _egl.eglDestroySurface(_eglDisplay, _eglSurface); } private void handleContextLost() { // Destroy our EGL context _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); _egl.eglDestroyContext(_eglDisplay, _eglContext); _eglContext = EGL10.EGL_NO_CONTEXT;

}

// Re-create our EGL context createEGLContext();

/** * Main render loop. */ public void run() { initialize(); int throttle = 0;

16

OpenGL ES


OpenGL ES

Development Guide

while (_running) { throttle = (int)System.currentTimeMillis(); // Idle If we are in the background if (_paused) { synchronized (this) { try { wait(); } catch (InterruptedException x) { } } } updateBackBuffer(); renderFrame(); ++_angle; if (_angle >= 360f) { _angle = 0f; } //Determine how long the frame took to render. throttle = (int)System.currentTimeMillis() - throttle; //Throttle to 30 FPS to control CPU usage. throttle = 33 - throttle;

} }

if (throttle > 0) { // Throttle cpu usage try { Thread.sleep(throttle); } catch (InterruptedException x) { } }

destroyEGL();

private void renderFrame() { // Make our context and surface current and check for EGL_CONTEXT_LOST if (!_egl.eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface,

17


Development Guide

_eglContext)) { if (_egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) handleContextLost(); } // Signal that we are about to begin OpenGL rendering _egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, _offscreenGraphics); render(_gl); // Signal that OpenGL ES rendering is complete _egl.eglWaitGL();

}

// Swap the window surface to the display _egl.eglSwapBuffers(_eglDisplay, _eglSurface);

private void render(GL10 gl) { // Set our GL viewport gl.glViewport(0, 0, getWidth(), getHeight()); // Clear the surface gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); net.rim.device.api.opengles.GLUtils.gluPerspective(gl, 45.0f, (float)getWidth()/(float)getHeight(), 0.15f, 100.0f); gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); // Setup drawing state gl.glEnable(GL10.GL_DEPTH_TEST); gl.glEnable(GL10.GL_LIGHTING); gl.glEnable(GL10.GL_LIGHT0); gl.glEnable(GL10.GL_COLOR_MATERIAL);

}

18

// Draw our cube gl.glTranslatef(0, 0, -3.5f); gl.glRotatef(_angle, 1.0f, 1.0f, 0.0f); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_NORMAL_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _cubeVertices); gl.glNormalPointer(GL10.GL_FLOAT, 0, _cubeNormals); gl.glColorPointer(4, GL10.GL_FLOAT, 0, _cubeColors); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, _vertexCount);

OpenGL ES


Development Guide

OpenGL ES

/** * Called by the UI system to paint the screen. */ protected void paint(Graphics g) { if (_offscreenBitmap != null) g.drawBitmap(0, 0, _offscreenBitmap.getWidth(), _offscreenBitmap.getHeight(), _offscreenBitmap, 0, 0); } /** * Called when the visibility of our screen changes. * * @param visible true if our screen is being made visible, * false if it's being hidden */ protected void onVisibilityChange(boolean visible) { if (visible) { resume(); } else { pause(); } } /** * Called when the screen is closing. */ public void close() { _running = false; synchronized (this) { notifyAll(); } }

super.close();

/** * Keeps the back buffer in sync with the screen size. */ private void updateBackBuffer() { if (_offscreenBitmap != null) { if (_offscreenBitmap.getWidth() == getWidth() && _offscreenBitmap.getHeight() == getHeight()) return; // no change needed }

19


Development Guide

}

_offscreenBitmap = new Bitmap(getWidth(), getHeight()); _offscreenGraphics = Graphics.create(_offscreenBitmap);

private void pause() { _paused = true; }

}

private void resume() { if (_running) { // Pause the render loop _paused = false; synchronized (this) { notifyAll(); } } else { // Start the render thread. _running = true; new Thread(this).start(); } }

Code sample: Drawing a multicolored triangle import import import import import import import

java.nio.*; javax.microedition.khronos.egl.*; javax.microedition.khronos.opengles.*; net.rim.device.api.ui.*; net.rim.device.api.ui.container.*; net.rim.device.api.system.*; net.rim.device.api.opengles.*;

public final class MultiColoredOpenGLTriangle extends UiApplication { public MultiColoredOpenGLTriangle() { pushScreen(new DrawScreen()); } public static void main(String[] args) { new MultiColoredOpenGLTriangle().enterEventDispatcher(); }

} class DrawScreen extends FullScreen implements Runnable {

20

OpenGL ES


OpenGL ES

Development Guide

private private private private private private private private private private private private

EGL11 _egl; EGLDisplay _eglDisplay; EGLConfig _eglConfig; EGLSurface _eglSurface; EGLContext _eglContext; GL10 _gl; Bitmap _offscreenBitmap; Graphics _offscreenGraphics; FloatBuffer _vertexArray; FloatBuffer _colorArray; boolean _running; boolean _paused;

DrawScreen() { super(FullScreen.DEFAULT_MENU | FullScreen.DEFAULT_CLOSE); } private void initialize() { _egl = (EGL11)EGLContext.getEGL(); // Get the EGL display _eglDisplay = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); // Initialize the display for EGL setting the version to null _egl.eglInitialize(_eglDisplay, null); // Choose an EGL config EGLConfig[] configs = new EGLConfig[1]; int[] numConfigs = new int[1]; int[] attrs = { EGL11.EGL_RED_SIZE, 5, EGL11.EGL_GREEN_SIZE, 6, EGL11.EGL_BLUE_SIZE, 5, EGL11.EGL_NONE }; _egl.eglChooseConfig(_eglDisplay, attrs, configs, 1, numConfigs); _eglConfig = configs[0]; // Create an EGL window surface _eglSurface = _egl.eglCreateWindowSurface(_eglDisplay, _eglConfig, this, null); // Create an EGL context createEGLContext(); float[] vertices = { -0.5f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; float[] colors = { 0.0f, 1.0f, 0.0f, 1.0f,

21


Development Guide

}

1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f }; _vertexArray = ByteBuffer.allocateDirect(3 * 3 * 4).asFloatBuffer(); _vertexArray.put(vertices); _vertexArray.rewind(); _colorArray = ByteBuffer.allocateDirect(4 * 3 * 4).asFloatBuffer(); _colorArray.put(colors); _colorArray.rewind();

private void createEGLContext() { // Create an EGL context _eglContext = _egl.eglCreateContext (_eglDisplay, _eglConfig, EGL10.EGL_NO_CONTEXT, null); // Get the GL interface for the new context _gl = (GL10)_eglContext.getGL(); // Make the new context current _egl.eglMakeCurrent (_eglDisplay, _eglSurface, _eglSurface, _eglContext); } private void destroyEGL() { _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);

}

_egl.eglDestroyContext(_eglDisplay, _eglContext); _egl.eglDestroySurface(_eglDisplay, _eglSurface);

private void handleContextLost() { // Destroy the EGL context _egl.eglMakeCurrent(_eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); _egl.eglDestroyContext(_eglDisplay, _eglContext); _eglContext = EGL10.EGL_NO_CONTEXT; // Re-create the EGL context createEGLContext(); } /** * Main render loop. */ public void run() { initialize(); while (_running) { // Idle if this thread is in the background if (_paused)

22

OpenGL ES


Development Guide

{

}

OpenGL ES

synchronized (this) { try { wait(); } catch (InterruptedException x) { } }

} updateBackBuffer(); renderFrame(); // Throttle cpu usage try { Thread.sleep(20); } catch (InterruptedException x) { } } destroyEGL();

private void renderFrame() { // Make the context and surface current and check for EGL_CONTEXT_LOST if (!_egl.eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext)) { if (_egl.eglGetError() == EGL11.EGL_CONTEXT_LOST) handleContextLost(); } // Signal that OpenGL rendering is about to begin _egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, _offscreenGraphics); render(_gl); // Signal that OpenGL ES rendering is complete _egl.eglWaitGL(); // Swap the window surface to the display _egl.eglSwapBuffers(_eglDisplay, _eglSurface);

} private void render(GL10 gl) { // Set the GL viewport gl.glViewport(0, 0, getWidth(), getHeight()); // Clear the surface gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); // Set the projection matrix gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); GLUtils.gluPerspective (gl, 45.0f, (float)getWidth()/(float)getHeight(), 0.15f, 10.0f); // Draw the triangle

23


Development Guide

gl.glMatrixMode(GL10.GL_MODELVIEW); gl.glLoadIdentity(); gl.glTranslatef(0.0f, 0.0f, -3.0f); gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); gl.glEnableClientState(GL10.GL_COLOR_ARRAY); gl.glVertexPointer(3, GL10.GL_FLOAT, 0, _vertexArray); gl.glColorPointer(4, GL10.GL_FLOAT, 0, _colorArray); gl.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

} /** * Called by the UI system to paint the screen. */ protected void paint(Graphics g) { if (_offscreenBitmap != null) g.drawBitmap(0, 0, _offscreenBitmap.getWidth(), _offscreenBitmap.getHeight(), _offscreenBitmap, 0, 0); } /** * Called when the visibility of the screen changes. * * @param visible true if the screen is being made visible, * false if hidden */ protected void onVisibilityChange(boolean visible) { if (visible) { resume(); } else { pause(); } } /** * Called when the screen is closing. */ public void close() { _running = false; synchronized (this) { notifyAll(); } super.close(); } /** * Keeps the back buffer in sync with the screen size. */ private void updateBackBuffer() { if (_offscreenBitmap != null) { if (_offscreenBitmap.getWidth() == getWidth() &&

24

OpenGL ES


Development Guide

OpenGL ES

_offscreenBitmap.getHeight() == getHeight()) return; // no change needed

} _offscreenBitmap = new Bitmap(getWidth(), getHeight()); _offscreenGraphics = Graphics.create(_offscreenBitmap);

} private void pause() { _paused = true; } private void resume() { if (_running) { _paused = false; synchronized (this) { notifyAll(); } } else { // Start the render thread. _running = true; new Thread(this).start(); } } }

Code sample: Drawing a texture on a GLField The following code sample requires a 256-by-256 pixed .png file named bg.png in the top level of the project folder structure. import import import import import import import

net.rim.device.api.system.Bitmap; net.rim.device.api.ui.*; net.rim.device.api.ui.container.*; net.rim.device.api.ui.component.*; net.rim.device.api.opengles.*; javax.microedition.khronos.opengles.*; javax.microedition.khronos.egl.*;

public final class GLFieldDemo extends UiApplication { public GLFieldDemo() { pushScreen(new HomeScreen()); } public static void main(String[] args) { GLFieldDemo app = new GLFieldDemo(); app.enterEventDispatcher(); }

25


Development Guide

OpenGL ES

} class MyGLField extends GLField { protected void layout(int width, int height) { setExtent(256, 256); } protected void initialize(GL gl) { GL11 gl11 = (GL11)gl; gl11.glClearColor(0, 0, 0, 1); int textureNames[] = new int[1]; gl11.glGenTextures(1,textureNames,0); gl11.glBindTexture(GL11.GL_TEXTURE_2D, textureNames[0]); Bitmap img = Bitmap.getBitmapResource("bg.png"); GLUtils.glTexImage2D(gl11,0,GL11.GL_RGB, GL11.GL_UNSIGNED_BYTE, img, null); gl11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); gl11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); }

gl11.glEnable(GL11.GL_TEXTURE_2D);

protected void render(GL gl) { GL11 gl11 = (GL11)gl; gl11.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT); }

}

((GL11Ext)gl11).glDrawTexiOES(0, 0, 0, 256,256);

public MyGLField(int ver) { super(ver); }

class HomeScreen extends MainScreen { public HomeScreen() { add(new MyGLField(GLField.VERSION_1_1)); add(new LabelField("OpenGL ES field")); } }

26


Development Guide

OpenGL ES

Code sample: Loading a 3-D perspective projection matrix You can use the GLUtils class to load a 3-D perspective projection matrix. public void sizeChanged(GL10 gl, int width, int height) { // Update our viewport to reflect the new size gl.glViewport(0, 0, width, height);

}

// Setup a perspective projection gl.glMatrixMode(GL10.GL_PROJECTION); gl.glLoadIdentity(); net.rim.device.api.opengles.GLUtils.gluPerspective (gl, 45.0f, (float)width/(float)height, 0.15f, 100.0f);

Code sample: Using fixed-point arithmetic The following code sample demonstrates how you can and cannot use the Fixed32 class for addition, subtraction, multiplication, division, value conversion, and trigonometry. import net.rim.device.api.math.*; public class demoFixed32 { demoFixed32() { // convert an integer to fixed-point int n = Fixed32.toFP(7); // 7.0 // convert a quantity in ten-thousandths to fixed-point int m = Fixed32.tenThouToFP(70625); // 7.0625 // convert from fixed-point, truncate fractional component int trunc = Fixed32.toInt(m); // 7 // multiply by ten thousand int mult = Fixed32.toIntTenThou(m); // 70625 // add, subtract, negate, and compare int result = m - n; // 7.0625 - 7.0 == 0.0625 result = -result; // -0.0625 result -= n; // -0.0625 - 7.0 == -7.0625 boolean b = (result == -m); // true boolean bb = (m < n); // false

27


Development Guide

OpenVG

// do not use increment and decrement operators result = Fixed32.toFP(2); ++result; // WRONG! result will NOT be 3 result = Fixed32.toFP(2); result += Fixed32.toFP(1); // Correct: result will be 3 // Use * and / when multiplying or dividing by an integer scalar // Use mul to multiply 2 fixed-point numbers // Use div to divide 2 fixed-point numbers m = Fixed32.tenThouToFP(12500); // 1.25 m *= 3; // OK: 1.25 * 3 == 3.75 m /= 2; // OK: 3.75 / 2 == 1.875 m = Fixed32.mul(m, Fixed32.tenThouToFP(15000)); // 1.875 * 1.5000 == 2.8125 m = Fixed32.div(m, m); // 2.8125 / 2.8125 == 1.0

}

}

// mul, div, sqrt, sind, cosd, tand, and atand2 // all work with 16.16 fixed-point numbers m = Fixed32.tenThouToFP(172500); // 17.2500 n = Fixed32.sqrt(m); // sqrt(17.25) n = Fixed32.sind(m); // sine of 17.25 degrees n = Fixed32.cosd(m); // cosine of 17.25 degrees result = Fixed32.atand2(-m, -m); // -135.0 degrees in fixed-point

OpenVG OpenVG™ is a vector graphics library that is designed to work closely with graphic display hardware to produce high-quality 2D graphics. OpenVG is built on EGL™, the same native platform graphics interface that OpenGL® ES uses. OpenVG is designed to support the drawing operations of a renderer that complies with the SVG Tiny 1.2 specification.

Code sample: Drawing a triangle by using OpenVG import import import import import import import

net.rim.device.api.ui.*; net.rim.device.api.ui.container.*; net.rim.device.api.system.*; java.nio.*; javax.microedition.khronos.egl.*; net.rim.device.api.egl.*; net.rim.device.api.openvg.*;

public class OpenVGScreen extends MainScreen { // EGL private EGL12 _egl; private EGLDisplay _display;

28


Development Guide

OpenVG

private EGLConfig _config; private EGLContext _context; private EGLSurface _surface; // Surface type. private int _surfaceType = EGL10.EGL_WINDOW_BIT; // System private int[] _version = new int[2]; private Bitmap _pixmap; private ByteBuffer _pathSegments; private FloatBuffer _pathData; // OpenVG private VG11 _vg; private int _fillPaint; private int _strokePaint; private int _path; private boolean _testInitialized; public OpenVGScreen() { super(); setTitle("OpenVGScreen Test"); initialize(); } public void paint(Graphics g) { frame(g); if (_pixmap != null) { g.drawBitmap(0, 0, _pixmap.getWidth(), _pixmap.getHeight(), _pixmap, 0, 0); } } private void initialize() { // Get EGL _egl = (EGL12)EGLContext.getEGL(); // Get the display from the primary DisplayInstance _display = _egl.eglGetDisplay(EGL11.EGL_DEFAULT_DISPLAY); if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } // Initialize EGL _egl.eglInitialize(_display, _version); if (_egl.eglGetError() != EGL10.EGL_SUCCESS)

29


OpenVG

Development Guide

{ }

throw new RuntimeException();

// Describe our config criteria attributes. int[] attribs = { EGL11.EGL_RED_SIZE, 8, EGL11.EGL_GREEN_SIZE, 8, EGL11.EGL_BLUE_SIZE, 8, EGL11.EGL_ALPHA_SIZE, 8, EGL11.EGL_SURFACE_TYPE, _surfaceType, EGL12.EGL_RENDERABLE_TYPE, EGL12.EGL_OPENVG_BIT, EGL11.EGL_NONE }; // Choose the first config found. EGLConfig[] configs = new EGLConfig[1]; int[] num_configs = new int[1]; _egl.eglChooseConfig(_display, attribs, configs, 1, num_configs); if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } _config = configs[0]; }

createContext();

private void createContext() { _egl.eglBindAPI(EGL12.EGL_OPENVG_API); if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } null);

}

_context = _egl.eglCreateContext(_display, _config, EGL11.EGL_NO_CONTEXT, if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } _vg = (VG11)VGUtils.getVG(_context);

private void contextLost() { createContext(); if (!_egl.eglMakeCurrent(_display, _surface, _surface, _context))

30


OpenVG

Development Guide

{ " + }

throw new RuntimeException("eglMakeCurrent failed after EGL_CONTEXT_LOST:

}

_egl.eglGetError());

public void frame(Graphics g) { bindTarget(g); update(g); render(g); releaseTarget(g); } private void bindTarget(Graphics g) { if (_surface == null) { switch(_surfaceType) { case EGL10.EGL_WINDOW_BIT: _surface = _egl.eglCreateWindowSurface(_display, _config, g, null); if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } break; case EGL10.EGL_PBUFFER_BIT: int[] surfaceAttribs = surfaceAttribs = new int[] { EGL11.EGL_WIDTH, Display.getWidth(), EGL11.EGL_HEIGHT, Display.getHeight(), EGL11.EGL_NONE }; _surface = _egl.eglCreatePbufferSurface(_display, _config, surfaceAttribs); if (_egl.eglGetError() != EGL10.EGL_SUCCESS) { throw new RuntimeException(); } _pixmap = new Bitmap(Bitmap.ROWWISE_16BIT_COLOR, Display.getWidth(), Display.getHeight()); break; } } if (!_egl.eglMakeCurrent(_display, _surface, _surface, _context)) { if ( _egl.eglGetError() == EGL11.EGL_CONTEXT_LOST)

31


OpenVG

Development Guide

{

contextLost();

} else { }

}

throw new RuntimeException("eglMakeCurrent error");

if (_surfaceType == EGL10.EGL_WINDOW_BIT || _surfaceType == EGL10.EGL_PIXMAP_BIT) { _egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, g); } } private void releaseTarget(Graphics g) { switch(_surfaceType) { case EGL10.EGL_WINDOW_BIT: _egl.eglWaitClient(); break; case EGL10.EGL_PBUFFER_BIT: // You can either copy the surface to Graphics or a mutable Bitmap/ Image here. _egl.eglCopyBuffers(_display, _surface, _pixmap); break; } } private void setup() { _vg.vgSeti(VG10.VG_MATRIX_MODE, VG10.VG_MATRIX_PATH_USER_TO_SURFACE); _vg.vgLoadIdentity(); _vg.vgSeti(VG10.VG_MATRIX_MODE, VG10.VG_MATRIX_FILL_PAINT_TO_USER); _vg.vgLoadIdentity(); _vg.vgSeti(VG10.VG_MATRIX_MODE, VG10.VG_MATRIX_STROKE_PAINT_TO_USER); _vg.vgLoadIdentity(); // Set clear color float[] clearColor = new float[] { 0.6f, 0.8f, 1.0f, 1.0f }; _vg.vgSetfv(VG10.VG_CLEAR_COLOR, 4, clearColor, 0); // Create fill paint _fillPaint = _vg.vgCreatePaint(); _vg.vgSetParameteri(_fillPaint, VG10.VG_PAINT_TYPE, VG10.VG_PAINT_TYPE_COLOR); _vg.vgSetColor(_fillPaint, 0xFFFF00FF); // Create stroke paint

32


Development Guide

OpenVG

_strokePaint = _vg.vgCreatePaint(); _vg.vgSetParameteri(_strokePaint, VG10.VG_PAINT_TYPE, VG10.VG_PAINT_TYPE_COLOR); _vg.vgSetColor(_strokePaint, 0x000000FF); _vg.vgSetf(VG10.VG_STROKE_LINE_WIDTH, 3.0f);

}

// Create path _path = _vg.vgCreatePath(VG10.VG_PATH_FORMAT_STANDARD,VG10.VG_PATH_DATATYPE_F, 1.0f, 0.0f, 4, 3, VG10.VG_PATH_CAPABILITY_ALL); // Subdata the path with its segments and coordinate data using java.nio buffers _pathSegments = ByteBuffer.wrap( new byte[] { VG10.VG_MOVE_TO_ABS, VG10.VG_LINE_TO_ABS, VG10.VG_LINE_TO_ABS, VG10.VG_CLOSE_PATH }); _pathData = FloatBuffer.wrap( new float[] { -100.0f, -86.60254f, 100.0f, -86.60254f, 0.0f, 86.60254f }); _vg.vgAppendPathData(_path, _pathSegments, _pathData);

private void render(Graphics g) { // Clear the surface _vg.vgClear(0, 0, Display.getWidth(), Display.getHeight()); _vg.vgSeti(VG10.VG_MATRIX_MODE, VG10.VG_MATRIX_PATH_USER_TO_SURFACE); _vg.vgLoadIdentity();

}

// Move the triangle to the center of the screen. _vg.vgTranslate(Display.getWidth() >> 1, Display.getHeight() >> 1); _vg.vgSetPaint(_fillPaint, VG10.VG_FILL_PATH); _vg.vgSetPaint(_strokePaint, VG10.VG_STROKE_PATH); _vg.vgDrawPath(_path, VG10.VG_FILL_PATH | VG10.VG_STROKE_PATH);

private void teardown() { _vg.vgDestroyPaint(_fillPaint); _vg.vgDestroyPaint(_strokePaint); _vg.vgDestroyPath(_path); }

33


Development Guide

OpenVG

private void update(Graphics g) { // Make sure we run setup for the first pass if (!_testInitialized) { setup(); _testInitialized = true; } } public boolean onClose() { teardown(); _egl.eglMakeCurrent(_display, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT); _egl.eglDestroyContext(_display, _context); _egl.eglDestroySurface(_display, _surface); return super.onClose(); } }

34


Development Guide

Animation

Animation

2

It is common to think of an animation as a series of images that change over time, but to understand the framework of the Animation API for BlackBerry速 device applications, you need to think of animation in a more abstract way. Animation is the change, over time, of any property or set of properties according to specified rules. The changing property might be the location of an image that is displayed on the screen, in which case the animation is an object moving on the screen. But the properties might be color or opacity, in which case the animation might be a pulsating object that constantly changes color or one that cycles between being transparent and opaque. A framework that supports this more abstract type of animation requires object properties to animate. These objects are called Animatable objects. Objects that you want to animate have to expose one or more of their properties to be updated by the animation framework. They do this either by using one of the predefined Animatable objects or by creating their own classes that implement the Animatable interface. The rendering of the animation is treated as a separate task that is not handled automatically by the animation engine. The animation engine updates the animatable property values periodically according to rules that you specify by using the API. You must write your own rendering code and register a listener to be notified when an update occurs so that you can render the current state of the animation, whether that update is images in updated locations, images with different colors, or something even more creative. The animation engine has to be supplied with rules that tell it how to change the animatable property values under its control. The animation framework uses the traditional animation concepts of key frames and easing curves. The key frames specify the values that the properties should have at various points during the animation. The easing curves specify the dynamics of how transitions are made from one key frame to the next. The animation framework uses an AnimationKeyframeSequence object to specify key frames and an Animation object lets you specify various easing curves. The animation framework also lets you group animations together so that you can control them as a group and it lets you set up triggers that cause an animation to start and stop.

Animation API The primary classes in the Animation API are Animator and Animation. To use the primary classes, you will also work with the AnimationKeyFrameSequence class and the AnimatedScalar class or AnimatedVector class. You create and control animations by using the Animator class. You invoke one of its addAnimation() methods, which returns an Animation object. The target of your animation has to implement the Animatable interface. In most cases, you can use either AnimatedScalar or AnimatedVector to represent the animatable properties of the object that you want to animate. If you can't use these classes to represent the properties, there are also classes in the net.rim.device.api.math package that implement Animatable. If none of the predefined classes work for your application, you can build a custom animatable object by creating a class that implements Animatable.

35


Animation API

Development Guide

Class or interface

Description

Animator

This class represents the root node of the set of animations that you want to manage. You can invoke one of its addAnimation() methods to create an animation. You can invoke begin() and end() to start and stop the animation that you create. This class represents an animation and lets you manage the animation. This interface describes the set of methods you have to implement to create your own Animatable object. This class implements a predefined, animatable scalar property. This class implements a predefined, animatable vector property. This class represents a sequence of key frames and lets you specify reference points in an animation sequence. The animation framework interpolates between the reference points that you specify. This class represents a group of animations and lets you control these animations as a group instead of individually.

Animation

Animatable AnimatedScalar AnimatedVector AnimationKeyFrameSequence

AnimationGroup

36


Key frames

Development Guide

Class or interface

Description

AnimationTrigger

This class represents an object that you can add to an animation and later use to trigger the animation to start or stop. This class provides a wrapper for the value of an animatable property that is being animated. This class defines the basic functionality for animations and animation groups.

AnimationValue AbstractAnimation

Code sample: Creating and starting a basic animation The following code sample doesn't create a complete animation. It illustrates the key steps that are required to set up a simple animation of a vector animatable object. To enhance the code sample to make it a working animation, you would have to do the following: • add code to draw an object on the screen at the location that is specified by the position variable. • set up a listener for the animation engine to invoke each time it updates the position of the object. • in response to each call, draw your object on the screen at the current position Animator animator = new Animator(25); AnimatedVector position = new AnimatedVector( new float[] { 0.0f, 0.0f }, 0 ); Animation animation = animator.addAnimationTo( position, AnimatedVector.ANIMATION_PROPERTY_VECTOR, new float[] { 100.0f, 100.0f }, 0, Animation.EASINGCURVE_LINEAR, 1000L); animation.setRepeatCount(1.0f); animation.begin(1000L);

Key frames Animations are created by presenting a series of images quickly enough that the human eye doesn't sense an abrupt transition between the images. If the differences between adjacent images in the series are kept small enough, someone viewing the animation sees it as a smooth, changing scene instead of a series of images. Each static image in an animation is called a frame. The term originated from film technology. A strip of film is partitioned into a series of images that are separated from each other by thin, unused portions of film called frame lines. Together, the unused portions of the film and the edges of the film appear like a picture frame around each individual image.

37


Development Guide

Easing curves

One method of creating an animation is to create each of the frames that you want to present individually. This method is called keyframing. It gives the animator precise control over the animation, but it is very labor-intensive. Another method is to create only some of the most important frames. The frames that you choose to create are called key frames and are pivotal or complex members of the series of images. In classical animation, a senior animator might create the key frames and junior animators would fill in the in-between frames. In computer animation, the animator can specify the key frames and the computer can use interpolating algorithms to generate the in-between frames. The interpolation process is called tweening. With the Animation API, you specify the key frames by using the KeyFrameSequence class and the animation framework uses interpolation to calculate the values of the animatable properties of the animation between the key frames.

Easing curves Easing curves are functions that specify the speed of an animation. You can use them to make animations look more realistic without requiring you to do physics calculations. For example, when you animate a dropping ball, you want the ball to speed up as it drops. An easing curve that eases out would create that effect. The domain of an easing function is the completed fraction of the total duration of the animation. The range is the completed fraction of the total animating that is required. If e(t) is an easing function and the position of an animatable object changes from p1 to p2 over a time period of d milliseconds, then at an intermediate time, t, the object is at position p = p2 - p1*e(t) + p1. Easing curve plots help you visualize the effect of an easing curve on an animation. The following plot uses a normalized domain of [0,1] to represent the entire duration of the animation and displays a EASINGCURVE_BOUNCE_IN easing curve.

38


Easing curves

Development Guide

There are several terms that are used to classify easing curves. Term

Definition

Ease in Ease out Ease in-out Ease out-in

The animation accelerates. The animation decelerates. The first half of the animation accelerates and the second half decelerates. The first half of the animation decelerates and the second half accelerates.

The Animation API supports nearly 50 easing curves. If none of these curves work for your application, you can specify a custom easing curve by using cubic BĂŠzier splines.

39


Predefined classes that implement the Animatable interface

Development Guide

Predefined classes that implement the Animatable interface Animatable class

Description net.rim.device.api.animation defines a scalar value defines a vector value net.rim.device.api.math defines a 2-element vector of floating point numbers defines a 3-element vector of floating point numbers defines a 4-element vector of floating point numbers defines a color made up of red, green, and blue components defines a color made up of red, green, blue, and alpha components defines a 4-element quaternion that represents the orientation of an object in space defines a 2-D transformation defines a 3-D transformation

AnimatedScalar AnimatedVector Vector2f Vector3f Vector4f Color3f Color4f Quaternion4f Transform2D Transform3D

Create a custom class that implements the Animatable interface 1.

Import the required classes and interfaces. import net.rim.device.api.animation.*;

2.

Create a class that implements the Animatable interface. public class PositionSizeAnimatable implements Animatable

3.

Create integer constants to represent each of the properties of the class and create an integer array to store the number of components in each property. Declare variables to hold the data for all of the components of the class. public public public public private

static static static static static

final final final final final

int int int int int[]

ANIMATION_PROPERTY_XY = 0; ANIMATION_PROPERTY_WIDTH = 1; ANIMATION_PROPERTY_HEIGHT = 2; ANIMATION_PROPERTY_COUNT = 3; ANIMATION_PROPERTY_COMPONENT_COUNTS = { 2, 1, 1 };

public float x, y, width, height;

4.

40

Create a constructor that accepts and sets values of all of the components of the animatible properties.


Development Guide

Create a custom class that implements the Animatable interface

public MyAnimatable(float x, float y, float height, float width) { this.x = x; this.y = y; this.width = width; this.height = height; }

5.

Implement getAnimationValue(). The AnimationValue class is used by the animation framework to encapsulate the values of animatable objects it is animating. Invoke setFloat() to store the component values of this particular animatable object in value. public void getAnimationValue(int property, AnimationValue value) { switch(property) { case ANIMATION_PROPERTY_XY: value.setFloat(0, this.x); value.setFloat(1, this.y); break; case ANIMATION_PROPERTY_WIDTH: value.setFloat(0, this.width); break;

}

6.

}

case ANIMATION_PROPERTY_HEIGHT: value.setFloat(0, this.height); break;

Implement setAnimationValue(). Invoke getFloat() to retrieve the updated component values for this animatable object from value. public void setAnimationValue(int property, AnimationValue value) { switch(property) { case ANIMATION_PROPERTY_XY: this.x = value.getFloat(0); this.y = value.getFloat(1); break; case ANIMATION_PROPERTY_WIDTH: this.width = value.getFloat(0); break; case ANIMATION_PROPERTY_HEIGHT: this.height = value.getFloat(0);

41


Create a custom class that implements the Animatable interface

Development Guide

}

7.

}

break;

Implement getAnimationPropertyComponentCount(). In the following code sample, a check is performed to make sure that the integer property parameter is valid, and then the count that is stored in the ANIMATION_PROPERTY_COMPONENT_COUNTS array is returned. public int getAnimationPropertyComponentCount(int property) { if (property >= 0 && property < ANIMATION_PROPERTY_COUNT) return ANIMATION_PROPERTY_COMPONENT_COUNTS[property]; return 0; } }

Code sample import net.rim.device.api.animation.*; public class MyAnimatable implements Animatable { public static final int ANIMATION_PROPERTY_XY = 0; public static final int ANIMATION_PROPERTY_WIDTH = 1; public static final int ANIMATION_PROPERTY_HEIGHT = 2; public static final int ANIMATION_PROPERTY_COUNT = 3; private static final int[] ANIMATION_PROPERTY_COMPONENT_COUNTS = { 2, 1, 1 }; public float x, y, width, height; public MyAnimatable(float x, float y, float height, float width) { this.x = x; this.y = y; this.width = width; this.height = height; } public void getAnimationValue(int property, AnimationValue value) { switch(property) { case ANIMATION_PROPERTY_XY: value.setFloat(0, this.x); value.setFloat(1, this.y); break; case ANIMATION_PROPERTY_WIDTH: value.setFloat(0, this.width); break; case ANIMATION_PROPERTY_HEIGHT: value.setFloat(0, this.height);

42


Code sample: Animating a dropping ball in one-dimension

Development Guide

}

}

break;

public void setAnimationValue(int property, AnimationValue value) { switch(property) { case ANIMATION_PROPERTY_XY: this.x = value.getFloat(0); this.y = value.getFloat(1); break; case ANIMATION_PROPERTY_WIDTH: this.width = value.getFloat(0); break; case ANIMATION_PROPERTY_HEIGHT: this.height = value.getFloat(0); break; } } public int getAnimationPropertyComponentCount(int property) { if (property >= 0 && property < ANIMATION_PROPERTY_COUNT) return ANIMATION_PROPERTY_COMPONENT_COUNTS[property]; return 0; }

}

Code sample: Animating a dropping ball in one-dimension import import import import import

net.rim.device.api.animation.*; net.rim.device.api.system.*; net.rim.device.api.ui.*; net.rim.device.api.ui.container.*; net.rim.device.api.animation.*;

public class SimpleAnimation extends UiApplication { public static void main( String[] args ) { SimpleAnimation app = new SimpleAnimation(); app.enterEventDispatcher(); } public SimpleAnimation() { pushScreen(new AnimationScreen());

43


Development Guide

Code sample: Animating a dropping ball in one-dimension

} } class AnimationScreen extends MainScreen implements AnimatorListener { private RectangleToMove _rect; private Animator _animator; private Animation _xanimation; private Animation _yanimation; private boolean _bAnimating; public static final int BALL_WIDTH = 50; public AnimationScreen() { _bAnimating = false; int midScreen = Display.getWidth()/2; int endScreen = Display.getHeight(); _rect = new RectangleToMove(midScreen,BALL_WIDTH); _animator = new Animator(30); _animator.setAnimatorListener(this); _yanimation = _animator.addAnimationFromTo(_rect.getY(), AnimatedScalar.ANIMATION_PROPERTY_SCALAR, BALL_WIDTH, endScreen-BALL_WIDTH, Animation.EASINGCURVE_BOUNCE_OUT, 6000L); _yanimation.setRepeatCount(5f); _yanimation.begin(0); } protected void paint(Graphics g) { if(_bAnimating) { _rect.draw(g); } } public void animatorUpdate() { invalidate(); doPaint(); }

}

public void animatorProcessing(boolean processing) { _bAnimating = processing; }

class RectangleToMove { private int xPos; private AnimatedScalar yPos;

44


Development Guide

Code sample: Animating a dropping ball in one-dimension

public void draw(Graphics g) { g.setBackgroundColor(Color.BLACK); g.clear(); g.setColor(Color.SLATEGRAY); g.fillEllipse(xPos,yPos.getInt(),xPos+AnimationScreen.BALL_WIDTH,yPos.getInt (),xPos,yPos.getInt()+AnimationScreen.BALL_WIDTH,0,360); } public int getX() { return xPos; } public AnimatedScalar getY() { return yPos; }

}

RectangleToMove(int x,int y) { xPos = x; yPos = new AnimatedScalar(y); }

45


Related resources

Development Guide

Related resources

3

For more information on graphics and animation development on BlackBerry® devices, see the following resources: Resource

Information

API reference for the BlackBerry® Java® Development Environment

• • • • •

OpenGL® ES package overview Animation package overview OpenVG™ package overview EGL™ package overview Graphics

Khronos OpenGL® ES API Registry

OpenGL® ES specifications

46


Development Guide

Glossary

Glossary

4

2-D two-dimensional 3-D three-dimensional API application programming interface I/O input/output JSR Java速 Specification Request Java SE Java速 Platform, Standard Edition SVG Scalable Vector Graphics

47


Development Guide

Provide feedback To provide feedback on this deliverable, visit www.blackberry.com/docsfeedback.

48

Provide feedback

5


Document revision history

Development Guide

Document revision history Date

Description

3 August 2010 16 August 2010

First draft released. Minor edits.

6

49


Development Guide

Legal notice

Legal notice

7

©2010 Research In Motion Limited. All rights reserved. BlackBerry®, RIM®, Research In Motion®, SureType®, SurePress™ and related trademarks, names, and logos are the property of Research In Motion Limited and are registered and/or used in the U.S. and countries around the world. Java is a trademark of Sun Microsystems, Inc. OpenGL is a trademark of Silicon Graphics, Inc. EGL and OpenVG are trademarks of Khronos Group.All other trademarks are the property of their respective owners. This documentation including all documentation incorporated by reference herein such as documentation provided or made available at www.blackberry.com/go/docs is provided or made accessible "AS IS" and "AS AVAILABLE" and without condition, endorsement, guarantee, representation, or warranty of any kind by Research In Motion Limited and its affiliated companies ("RIM") and RIM assumes no responsibility for any typographical, technical, or other inaccuracies, errors, or omissions in this documentation. In order to protect RIM proprietary and confidential information and/or trade secrets, this documentation may describe some aspects of RIM technology in generalized terms. RIM reserves the right to periodically change information that is contained in this documentation; however, RIM makes no commitment to provide any such changes, updates, enhancements, or other additions to this documentation to you in a timely manner or at all. This documentation might contain references to third-party sources of information, hardware or software, products or services including components and content such as content protected by copyright and/or third-party web sites (collectively the "Third Party Products and Services"). RIM does not control, and is not responsible for, any Third Party Products and Services including, without limitation the content, accuracy, copyright compliance, compatibility, performance, trustworthiness, legality, decency, links, or any other aspect of Third Party Products and Services. The inclusion of a reference to Third Party Products and Services in this documentation does not imply endorsement by RIM of the Third Party Products and Services or the third party in any way. EXCEPT TO THE EXTENT SPECIFICALLY PROHIBITED BY APPLICABLE LAW IN YOUR JURISDICTION, ALL CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS, OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF DURABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, MERCHANTABILITY, MERCHANTABLE QUALITY, NONINFRINGEMENT, SATISFACTORY QUALITY, OR TITLE, OR ARISING FROM A STATUTE OR CUSTOM OR A COURSE OF DEALING OR USAGE OF TRADE, OR RELATED TO THE DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN, ARE HEREBY EXCLUDED. YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY BY STATE OR PROVINCE. SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES AND CONDITIONS. TO THE EXTENT PERMITTED BY LAW, ANY IMPLIED WARRANTIES OR CONDITIONS RELATING TO THE DOCUMENTATION TO THE EXTENT THEY CANNOT BE EXCLUDED AS SET OUT ABOVE, BUT CAN BE LIMITED, ARE HEREBY LIMITED TO NINETY (90) DAYS FROM THE DATE YOU FIRST ACQUIRED THE DOCUMENTATION OR THE ITEM THAT IS THE SUBJECT OF THE CLAIM. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, IN NO EVENT SHALL RIM BE LIABLE FOR ANY TYPE OF DAMAGES RELATED TO THIS DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NONPERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN INCLUDING WITHOUT LIMITATION ANY OF THE FOLLOWING DAMAGES: DIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR AGGRAVATED DAMAGES, DAMAGES FOR LOSS OF PROFITS OR REVENUES, FAILURE TO REALIZE ANY EXPECTED SAVINGS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF

50


Development Guide

Legal notice

BUSINESS OPPORTUNITY, OR CORRUPTION OR LOSS OF DATA, FAILURES TO TRANSMIT OR RECEIVE ANY DATA, PROBLEMS ASSOCIATED WITH ANY APPLICATIONS USED IN CONJUNCTION WITH RIM PRODUCTS OR SERVICES, DOWNTIME COSTS, LOSS OF THE USE OF RIM PRODUCTS OR SERVICES OR ANY PORTION THEREOF OR OF ANY AIRTIME SERVICES, COST OF SUBSTITUTE GOODS, COSTS OF COVER, FACILITIES OR SERVICES, COST OF CAPITAL, OR OTHER SIMILAR PECUNIARY LOSSES, WHETHER OR NOT SUCH DAMAGES WERE FORESEEN OR UNFORESEEN, AND EVEN IF RIM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, RIM SHALL HAVE NO OTHER OBLIGATION, DUTY, OR LIABILITY WHATSOEVER IN CONTRACT, TORT, OR OTHERWISE TO YOU INCLUDING ANY LIABILITY FOR NEGLIGENCE OR STRICT LIABILITY. THE LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS HEREIN SHALL APPLY: (A) IRRESPECTIVE OF THE NATURE OF THE CAUSE OF ACTION, DEMAND, OR ACTION BY YOU INCLUDING BUT NOT LIMITED TO BREACH OF CONTRACT, NEGLIGENCE, TORT, STRICT LIABILITY OR ANY OTHER LEGAL THEORY AND SHALL SURVIVE A FUNDAMENTAL BREACH OR BREACHES OR THE FAILURE OF THE ESSENTIAL PURPOSE OF THIS AGREEMENT OR OF ANY REMEDY CONTAINED HEREIN; AND (B) TO RIM AND ITS AFFILIATED COMPANIES, THEIR SUCCESSORS, ASSIGNS, AGENTS, SUPPLIERS (INCLUDING AIRTIME SERVICE PROVIDERS), AUTHORIZED RIM DISTRIBUTORS (ALSO INCLUDING AIRTIME SERVICE PROVIDERS) AND THEIR RESPECTIVE DIRECTORS, EMPLOYEES, AND INDEPENDENT CONTRACTORS. IN ADDITION TO THE LIMITATIONS AND EXCLUSIONS SET OUT ABOVE, IN NO EVENT SHALL ANY DIRECTOR, EMPLOYEE, AGENT, DISTRIBUTOR, SUPPLIER, INDEPENDENT CONTRACTOR OF RIM OR ANY AFFILIATES OF RIM HAVE ANY LIABILITY ARISING FROM OR RELATED TO THE DOCUMENTATION. Prior to subscribing for, installing, or using any Third Party Products and Services, it is your responsibility to ensure that your airtime service provider has agreed to support all of their features. Some airtime service providers might not offer Internet browsing functionality with a subscription to the BlackBerry速 Internet Service. Check with your service provider for availability, roaming arrangements, service plans and features. Installation or use of Third Party Products and Services with RIM's products and services may require one or more patent, trademark, copyright, or other licenses in order to avoid infringement or violation of third party rights. You are solely responsible for determining whether to use Third Party Products and Services and if any third party licenses are required to do so. If required you are responsible for acquiring them. You should not install or use Third Party Products and Services until all necessary licenses have been acquired. Any Third Party Products and Services that are provided with RIM's products and services are provided as a convenience to you and are provided "AS IS" with no express or implied conditions, endorsements, guarantees, representations, or warranties of any kind by RIM and RIM assumes no liability whatsoever, in relation thereto. Your use of Third Party Products and Services shall be governed by and subject to you agreeing to the terms of separate licenses and other agreements applicable thereto with third parties, except to the extent expressly covered by a license or other agreement with RIM. Certain features outlined in this documentation require a minimum version of BlackBerry速 Enterprise Server, BlackBerry速 Desktop Software, and/or BlackBerry速 Device Software. The terms of use of any RIM product or service are set out in a separate license or other agreement with RIM applicable thereto. NOTHING IN THIS DOCUMENTATION IS INTENDED TO SUPERSEDE ANY EXPRESS WRITTEN AGREEMENTS OR WARRANTIES PROVIDED BY RIM FOR PORTIONS OF ANY RIM PRODUCT OR SERVICE OTHER THAN THIS DOCUMENTATION. Research In Motion Limited 295 Phillip Street Waterloo, ON N2L 3W8

51


Development Guide

Canada Research In Motion UK Limited Centrum House 36 Station Road Egham, Surrey TW20 9LF United Kingdom Published in Canada

52

Legal notice


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.