Code sample: Drawing a triangle by using OpenVG
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.system.*;
import java.nio.*;
import javax.microedition.khronos.egl.*;
import net.rim.device.api.egl.*;
import net.rim.device.api.openvg.*;
public class OpenVGScreen extends MainScreen
{
// EGL
private EGL12 _egl;
private EGLDisplay _display;
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)
{
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();
}
_context = _egl.eglCreateContext(_display, _config, EGL11.EGL_NO_CONTEXT, null);
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))
{
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)
{
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
_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);
}
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();
}
}
Next topic: Animation
Previous topic: OpenVG