DirectFB data from memory buffer

John S picture John S · Oct 25, 2011 · Viewed 8.5k times · Source

I need a very fast way of displaying a data buffer to screen. I first tried accessing the linux framebuffer and that proved to be quite good. Then I learned about directFB and I liked the extra features it provides (like fast memcpy, resizing the images on the fly, no need for extra code etc.). But then I hit a snag - all examples are for images that are loaded from files. As far as I can tell there are no examples/tutorials for its 'DataBuffer' type. After peering through the documentation and source code I've managed to compile something that goes like this:

DFBSurfaceDescription sdsc;
DFBDataBufferDescription ddsc;
DFBDataBufferDescriptionFlags ddscf = (DFBDataBufferDescriptionFlags)DBDESC_MEMORY;
IDirectFBDataBuffer *dbuffer;
IDirectFBImageProvider *provider;

ddsc.flags = ddscf;
ddsc.file = NULL;
ddsc.memory.data = m_z;
ddsc.memory.length = 640*480;

DFBCHECK (DirectFBInit (&argc, &argv));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
sdsc.flags = DSDESC_CAPS;
sdsc.caps  = (DFBSurfaceCapabilities)(DSCAPS_PRIMARY | DSCAPS_FLIPPING);
DFBCHECK (dfb->CreateSurface( dfb, &sdsc, &primary ));
DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

DFBCHECK (dfb->CreateDataBuffer(dfb, &ddsc, &dbuffer));
DFBCHECK (dbuffer->CreateImageProvider(dbuffer, &provider));
DFBCHECK (provider->GetSurfaceDescription (provider, &sdsc));

DFBCHECK (dfb->CreateSurface( dfb, &sdsc, &fbwindow ));
DFBCHECK (provider->RenderTo (provider, fbwindow, NULL));
provider->Release (provider);

So basically I'm creating a DataBuffer from the DFB, then an ImageProvider from the DataBuffer and set it to render on a surface. When I run it however, it throws the error:

(#) DirectFBError [dbuffer->CreateImageProvider(dbuffer, &provider)]: No (suitable) implementation found!

Is the method really not implemented? I'm currently using DirectFB 1.4, from the API documentation the function should be there. That being said, does anyone know how to get a buffer (char*640*480*4 RGBA) from memory to render to the framebuffer using DirectFB?

Thanks.

Answer

MartinP picture MartinP · Mar 16, 2012

Maybe a bit late to help you, but for the benefit of anyone else trying this, here is an answer.

It is actually more simple than you think (with one gotcha) - I am doing exactly what you want, using DirectFb 1.4.11.

Once you have the primary suface, don't bother with the DataBuffer. Create another surface, using the DSDESC_PREALLOCATED flasg and your buffer as the preallocated data. Then Blit() the data from your new surface onto the primary surface and Flip() the primary surface onto the screen. The one gotcha is that your data needs to be in a format that DirectFB understands: 32 bit RGBA is not one of them, but 32 bit ARGB is - I had to parse my buffer to swap the bytes around.

Example code:

  dsc.width = screen_width;
  dsc.height = screen_height;
  dsc.flags = DSDESC_HEIGHT | DSDESC_WIDTH | DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT;
  dsc.caps = DSCAPS_NONE;
  dsc.pixelformat = DSPF_ARGB;
  dsc.preallocated[0].data = buffer;      // Buffer is your data
  dsc.preallocated[0].pitch = dsc.width*4;
  dsc.preallocated[1].data = NULL;
  dsc.preallocated[1].pitch = 0;

  DFBCHECK (dfb->CreateSurface( dfb, &dsc, &imageSurface ));
  DFBCHECK (primary->Blit(primary, imageSurface, NULL, 0, 0));
  DFBCHECK (primary->Flip(primary, NULL, DSFLIP_ONSYNC));

If your buffer is not the same size/shape as your screen, you can use StretchBlit() instead to resize it.

I hope this helps.