olso4539
Posts: 30
Joined: Mon Feb 03, 2014 9:02 pm

OpenVG bug?

Wed Jul 02, 2014 8:49 pm

I found a possible bug in the raspberry pi openVG implementation. I'm using vguPolygon() to draw plot lines. When I exceed 500 points on a single vguPolygon call, the behavior becomes unpredictable. At first extraneous lines appear, as the number of points increases not all of the points are plotted, and at 2000 points the axis appear to switch.

Can anyone tell me why this is happening?

For 500 data points plotted 1000 times "./HSDMPi 1000 500
out.png
500 plot points
out.png (58.55 KiB) Viewed 3958 times
For 505 data points plotted 1000 times "./HSDMPi 1000 505
out2.png
505 plot points
out2.png (59.73 KiB) Viewed 3958 times
For 2000 data points plotted 1000 times "./HSDMPi 1000 2000
out3.png
2000 plot points
out3.png (58.28 KiB) Viewed 3958 times
My source code is below.

Code: Select all

// HSDMPi
// Jonathan Olson (ols[email protected])
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
//#include <string.h>
//#include <unistd.h>

//#include <bcm_host.h>
//#include <vgfont.h>

#include "VG/openvg.h"
#include "VG/vgu.h"
#include "EGL/egl.h"
#include "GLES/gl.h"

typedef struct {
	uint32_t screen_width;
	uint32_t screen_height;
	// OpenGL|ES objects
	EGLDisplay display;
	EGLSurface surface;
	EGLContext context;
} STATE_T;

static void exit_func(void);
static STATE_T _state, *state=&_state;

// init_ogl sets the display, OpenGL|ES context and screen information
// state holds the OGLES model information
static void init_ogl(STATE_T *state) {
	int32_t success = 0;
	EGLBoolean result;
	EGLint num_config;

	static EGL_DISPMANX_WINDOW_T nativewindow;

	DISPMANX_ELEMENT_HANDLE_T dispman_element;
	DISPMANX_DISPLAY_HANDLE_T dispman_display;
	DISPMANX_UPDATE_HANDLE_T dispman_update;
	VC_RECT_T dst_rect;
	VC_RECT_T src_rect;

	static const EGLint attribute_list[] = {
		EGL_RED_SIZE, 8,
		EGL_GREEN_SIZE, 8,
		EGL_BLUE_SIZE, 8,
		EGL_ALPHA_SIZE, 8,
		EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
		EGL_NONE
	};

	EGLConfig config;

	// get an EGL display connection
	state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
	assert(state->display!=EGL_NO_DISPLAY);

	// initialize the EGL display connection
	result = eglInitialize(state->display, NULL, NULL);
	assert(EGL_FALSE != result);

	// bind OpenVG API
	eglBindAPI(EGL_OPENVG_API);

	// get an appropriate EGL frame buffer configuration
	result = eglChooseConfig(state->display, attribute_list, &config, 1, &num_config);
	assert(EGL_FALSE != result);

	// create an EGL rendering context
	state->context = eglCreateContext(state->display, config, EGL_NO_CONTEXT, NULL);
	assert(state->context!=EGL_NO_CONTEXT);

	// create an EGL window surface
	success = graphics_get_display_size(0 /* LCD */, &state->screen_width, &state->screen_height);
	assert( success >= 0 );

	dst_rect.x = 0;
	dst_rect.y = 0;
	dst_rect.width = state->screen_width;
	dst_rect.height = state->screen_height;

	src_rect.x = 0;
	src_rect.y = 0;
	src_rect.width = state->screen_width << 16;
	src_rect.height = state->screen_height << 16;

	dispman_display = vc_dispmanx_display_open( 0 /* LCD */);
	dispman_update = vc_dispmanx_update_start( 0 );

	dispman_element = vc_dispmanx_element_add ( dispman_update, dispman_display, 0/*layer*/, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, 0 /*alpha*/, 0/*clamp*/, 0/*transform*/);

	nativewindow.element = dispman_element;
	nativewindow.width = state->screen_width;
	nativewindow.height = state->screen_height;
	vc_dispmanx_update_submit_sync( dispman_update );

	state->surface = eglCreateWindowSurface( state->display, config, &nativewindow, NULL );
	assert(state->surface != EGL_NO_SURFACE);

	// connect the context to the surface
	result = eglMakeCurrent(state->display, state->surface, state->surface, state->context);
	assert(EGL_FALSE != result);

	//DAVE - Set up screen ratio
	glViewport(0, 0, (GLsizei)state->screen_width, (GLsizei)state->screen_height);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();

	float ratio = (float)state->screen_width / (float)state->screen_height;
	glFrustumf(-ratio, ratio, -1.0f, 1.0f, 1.0f, 10.0f);
}


// setfill sets the fill color
void setfill(float color[4]) {
	VGPaint fillPaint = vgCreatePaint();
	vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
	vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color);
	vgSetPaint(fillPaint, VG_FILL_PATH);
	vgDestroyPaint(fillPaint);
}


// setstroke sets the stroke color and width
void setstroke(float color[4], float width) {
	VGPaint strokePaint = vgCreatePaint();
	vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
	vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color);
	vgSetPaint(strokePaint, VG_STROKE_PATH);
	vgSetf(VG_STROKE_LINE_WIDTH, width);
	vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
	vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
	vgDestroyPaint(strokePaint);
}


// Start begins the picture, clearing a rectangluar region with a specified color
void Start(int width, int height, float fill[4]) {
	vgSetfv(VG_CLEAR_COLOR, 4, fill);
	vgClear(0, 0, width, height);
	vgLoadIdentity();
}


// End checks for errors, and renders to the display
void End() {
	assert(vgGetError() == VG_NO_ERROR);
	eglSwapBuffers(state->display, state->surface);
	assert(eglGetError() == EGL_SUCCESS);
}


// rshapes draws shapes (rect and ellipse) with random colors, strokes, and sizes.
void plot(int width, int height, int n, int p) {
	float color1[4] = {0,0,1,1};
	float color2[4] = {0,1,0,1};
	float color3[4] = {0,1,1,1};
	float color4[4] = {1,0,0,1};
	float color5[4] = {1,0,1,1};
	float color6[4] = {1,1,0,1};
	float color7[4] = {1,1,1,1};
	float color8[4] = {0.5,0.5,0.5,1};
	float bgcolor[4] = {0,0,0,1};

	int i,j;
	int leftborder=width/10;
	int plotwidth = width - leftborder;
	int points=p;
	float dp1[10000],dp2[10000],dp3[10000],dp4[10000],dp5[10000],dp6[10000],dp7[10000],dp8[10000];

	if (points>5000) points=5000;
	Start(width, height, bgcolor);
	srand(time(NULL));

	VGPath path1 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path2 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path3 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path4 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path5 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path6 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path7 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);
	VGPath path8 = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL);


	for (i=0;i<(2*points);i+=2) {
		dp1[i]=dp2[i]=dp3[i]=dp4[i]=dp5[i]=dp6[i]=dp7[i]=dp8[i]=i/2.0*plotwidth/points+leftborder;
//		printf("%f\n",dp1[i]);
	}

	for (j=0;j<n;++j) {


		vgClear(0, 0, width, height);

		for (i=1;i<(2*points);i+=2) {
			dp1[i]=(rand()%height)/9+height/9;
			dp2[i]=(rand()%height)/9+2*height/9;
			dp3[i]=(rand()%height)/9+3*height/9;
			dp4[i]=(rand()%height)/9+4*height/9;
			dp5[i]=(rand()%height)/9+5*height/9;
			dp6[i]=(rand()%height)/9+6*height/9;
			dp7[i]=(rand()%height)/9+7*height/9;
			dp8[i]=(rand()%height)/9+8*height/9;
/*
			dp1[i]=(rand()%height)*8/9+height/9;
			dp2[i]=(rand()%height)*8/9+height/9;
			dp3[i]=(rand()%height)*8/9+height/9;
			dp4[i]=(rand()%height)*8/9+height/9;
			dp5[i]=(rand()%height)*8/9+height/9;
			dp6[i]=(rand()%height)*8/9+height/9;
			dp7[i]=(rand()%height)*8/9+height/9;
			dp8[i]=(rand()%height)*8/9+height/9;
*/
		}

		vguPolygon(path1,& dp1[0], points, 0);
		vguPolygon(path2,& dp2[0], points, 0);
		vguPolygon(path3,& dp3[0], points, 0);
		vguPolygon(path4,& dp4[0], points, 0);
		vguPolygon(path5,& dp5[0], points, 0);
		vguPolygon(path6,& dp6[0], points, 0);
		vguPolygon(path7,& dp7[0], points, 0);
		vguPolygon(path8,& dp8[0], points, 0);

		setstroke(color1, 1);
		vgDrawPath(path1, VG_STROKE_PATH);
		vgClearPath(path1,VG_PATH_CAPABILITY_ALL);

		setstroke(color2, 1);
		vgDrawPath(path2, VG_STROKE_PATH);
		vgClearPath(path2,VG_PATH_CAPABILITY_ALL);

		setstroke(color3, 1);
		vgDrawPath(path3, VG_STROKE_PATH);
		vgClearPath(path3,VG_PATH_CAPABILITY_ALL);

		setstroke(color4, 1);
		vgDrawPath(path4, VG_STROKE_PATH);
		vgClearPath(path4,VG_PATH_CAPABILITY_ALL);

		setstroke(color5, 1);
		vgDrawPath(path5, VG_STROKE_PATH);
		vgClearPath(path5,VG_PATH_CAPABILITY_ALL);

		setstroke(color6, 1);
		vgDrawPath(path6, VG_STROKE_PATH);
		vgClearPath(path6,VG_PATH_CAPABILITY_ALL);

		setstroke(color7, 1);
		vgDrawPath(path7, VG_STROKE_PATH);
		vgClearPath(path7,VG_PATH_CAPABILITY_ALL);

		setstroke(color8, 1);
		vgDrawPath(path8, VG_STROKE_PATH);
		vgClearPath(path8,VG_PATH_CAPABILITY_ALL);

		eglSwapBuffers(state->display, state->surface);
	}
	End();
	printf("points %u ",points);
}


// exit_func cleans up
static void exit_func(void) {
	// clear screen
	glClear( GL_COLOR_BUFFER_BIT );
	eglSwapBuffers(state->display, state->surface);

	// Release OpenGL resources
	eglMakeCurrent( state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
	eglDestroySurface( state->display, state->surface );
	eglDestroyContext( state->display, state->context );
	eglTerminate( state->display );
}


// main initializes the system and shows the picture,
// exit and clean up when you hit [RETURN].
int main (int argc, char **argv) {
	int w, h, n, p;
	bcm_host_init();
	memset( state, 0, sizeof( *state ) ); // clear application state
	init_ogl(state); // Start OGLES
	w = state->screen_width;
	h = state->screen_height;
	n = 1000;
	p = 1000;
	if (argc > 1) {
		n = atoi(argv[1]);
	}
	if (argc > 2) {
		p = atoi(argv[2]);
	}
	plot(w, h, n, p);
	printf("n %u w %u h %u\n",n,w,h);
//	while (getchar() != '\n') {
//		;
//	}
	exit_func(); return 0;
}

olso4539
Posts: 30
Joined: Mon Feb 03, 2014 9:02 pm

Re: OpenVG bug?

Thu Jul 03, 2014 7:43 pm

It seems like this is only a problem with the vguPolygon() function as vgAppendPathData can handle tens of thousands of entries in one call and is a nice alternative.

dom
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 5144
Joined: Wed Aug 17, 2011 7:41 pm
Location: Cambridge

Re: OpenVG bug?

Thu Jul 28, 2016 12:11 pm

Actually this bug has been fixed in latest (rpi-update) firmware.
See: https://github.com/raspberrypi/firmware/issues/633

Return to “OpenVG”

Who is online

Users browsing this forum: No registered users and 1 guest