User avatar
Posts: 219
Joined: Wed Jan 25, 2012 9:39 pm


Fri Nov 30, 2012 10:16 pm

I looked up into firmware repository today and found out WF directory has been introduced there. Are you getting along on that OpenWF finally?

Of course I tried to run a test program, instead of "creating" a device it writes out these errors:

Code: Select all

wfcipc: wfc_client_ipc_init: could not open vchiq service: -1
wfc_client_func: wfcCreateDevice: failed to connect to server
The device enumeration code works all right though. Perhaps I have an outdated firmware? I'll try with newer firmware tomorrow.

User avatar
Posts: 219
Joined: Wed Jan 25, 2012 9:39 pm

Re: OpenWF

Sat Dec 01, 2012 12:48 pm

Did not fix. Maybe I should give you some time for implementing OpenWF, or even help you.

I find it better than entirely coming up with my own protocol.

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

Re: OpenWF

Sat Dec 01, 2012 3:35 pm

Do other vchiq services work?
(e.g. try "vcgencmd version")

WFC is implemented in the main Broadcom tree that Raspberry Pi branches off.
I haven't disabled it, as it could be interesting on the Pi, but I haven't actively tested it.
It is more like to work on "next" firmware tree, than the "master".

If you are intersted, post your test code, and I'll check if there's any simple build options that will make it work.

User avatar
Posts: 219
Joined: Wed Jan 25, 2012 9:39 pm

Re: OpenWF

Sat Dec 01, 2012 4:02 pm

This gist contains the test program that failed with that given error:

I'm unsure about how WFC work, or how to connect it to EGL. But I guess things start from accessing a device.

Code: Select all

[email protected] ~ $ vcgencmd version
Oct 25 2012 16:37:21 
Copyright (c) 2012 Broadcom
version 346337 (release)

User avatar
Posts: 219
Joined: Wed Jan 25, 2012 9:39 pm

Re: OpenWF

Sun Dec 02, 2012 12:17 am

I perhaps understood on my own how OpenWF is supposed to work. Here's pseudocode of a program that draws a single element to the screen:

Code: Select all

device = wfc.createDevice()

// screenNumber can be apparently retrieved from OpenWF Display API.
context = wfc.createOnScreenContext(device, screenNumber);

// how to get the stream isn't defined by OpenWF.
// this may cause gray hairs for people who port stuff, it's a missing piece in this specification.
stream = getNativeStream();
source = wfc.createSourceFromStream(device, context, stream);

// elements source seems to be mutable afterwards.
element = wfc.createElement(device, context, {
    "source": source,
    "destination_rectangle": [x, y, width, height]

// inserts the element into bottom of the scene graph.
wfc.insertElement(device, element, wfc.INVALID_HANDLE);

// starts up autonomous compositing.
wfc.activate(device, context);
OpenWF is supposed to work seamlessly with OpenGL. So apparently you're supposed to be able of setting NativeStream to texture target any time.

The current API around EGL and dispmanx is messed up bundle of failure. Therefore I wholeheartly propose you to switch on OpenWF if you can, even if it's very early for that API. It can help avoid lots of gray hairs even if there's missing piece in the overalls.

Posts: 6
Joined: Tue Jan 08, 2013 8:36 am

Re: OpenWF

Thu Feb 07, 2013 5:17 pm

I'm trying to build my own graphics stack on top of EGL/OpenWF and got stuck just as you did.

I thought I would post my findings here, maybe there is someone out there who knows the way forward.

From the OpenWF spec, I learned that I needed to create the following objects:

1. wfcDevice
2. wfcContext (created with wfcCreateOnScreenContext)
3. wfcSource (created with wfcCreateSourceFromStream)
4. wfcElement

so I did.

The wfcContext was wfcSetContextAttrib-ed with the following settings:

Code: Select all

The wfcCreateSourceFromStream constructor needs a "WFCNativeStreamType stream" parameter which - according to the spec - must be provided by the platform. As there were no docs, I tried grepping the source and found this (interface/khronos/egl/egl_client_surface.c):

Code: Select all

EGL_SURFACE_T *egl_surface_create(...) {
   // Create stream for this window
   if(type != PBUFFER)
      WFCNativeStreamType stream = (WFCNativeStreamType) surface->internal_handle;
      vcos_assert(stream != WFC_INVALID_HANDLE);
      uint32_t failure = wfc_stream_create(stream, WFC_STREAM_FLAGS_EGL);
      vcos_log_trace("Creating stream with handle %X", stream);
      vcos_assert(failure == 0);
   } // if
Btw, this function is the work horse of eglCreateWindowSurface().

It seems that if KHRONOS_EGL_PLATFORM_OPENWFC is defined, then the code creates a WFC stream for every EGL surface we create. I theorized that probably this stream could be used as the "stream" parameter of the wfcCreateSourceFromStream call, thereby connecting EGL to WFC in a nice and clean way.

(I had to recompile userland with -DKHRONOS_EGL_PLATFORM_OPENWFC=openwfc to pull in this code - it was not enabled by default.)

A search for the source of surface->internal_handle revealed that this value is the same as the result of platform_get_handle(EGLDisplay dpy, EGLNativeWindowType win), where dpy and win are the first and third parameters passed to eglCreateWindowSurface (see the code of eglCreateWindowSurface in egl_client.c for details)

So I created the wfcSource like this:

Code: Select all

wfcCreateSourceFromStream(dev,ctx, (WFCNativeStreamType) platform_get_handle(dpy,NULL), NULL)
then created a wfcElement with wfcCreateElement and wfcSetElementAttrib-ed it like this:

Code: Select all

WFC_ELEMENT_SOURCE: the wfcSource I created before
(everything else was left at defaults)

then I inserted the element into the context (with wfcInsertElement), committed the changes (wfcCommit), activated the context (wfcActivate), created two EGL contexts (one for OpenGL ES, one for OpenVG), drew something on the surface with them and finally called eglSwapBuffers().

I found this in the eglSwapBuffers code:

Code: Select all

               wfc_stream_await_buffer((WFCNativeStreamType) surface->internal_handle);
from which I guessed that every time I call eglSwapBuffers, the code will pass on the rendered frame to WFC for composition, and thanks to wfcActivate, I won't have to do anything else to enjoy my continuous stream of frames on the HDMI TV.

But unfortunately, this didn't work out. :-(

As soon as I try to create the EGL surface with eglCreateWindowSurface, something called wfc_client_ipc_send() kicks in saying that the vchiq service is not active or something (return code -1)

I found that bcm_host_init() - which I call at the beginning, as I should - does initialize vchiq, so I don't really understand what the problem is.

Return to “General discussion”