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

Was this information helpful? Send us your comments.