来自内存缓冲区的DirectFB数据

时间:2011-10-25 11:02:32

标签: framebuffer directfb

我需要一种非常快速的方法来显示数据缓冲区。我首先尝试访问linux framebuffer,事实证明这是非常好的。然后我了解了directFB,我喜欢它提供的额外功能(如快速memcpy,动态调整图像大小,不需要额外的代码等)。但后来我遇到了麻烦 - 所有的例子都是从文件中加载的图像。据我所知,它的'DataBuffer'类型没有示例/教程。在查看了文档和源代码后,我设法编译了类似这样的内容:

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);

所以基本上我从DFB创建一个DataBuffer,然后从DataBuffer创建一个ImageProvider并将其设置为在曲面上渲染。然而,当我运行它时,它会抛出错误:

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

方法真的没有实现吗?我目前正在使用DirectFB 1.4,从API文档中应该有函数。话虽这么说,有没有人知道如何从内存中获取缓冲区(char * 640 * 480 * 4 RGBA)以使用DirectFB渲染到帧缓冲区?

感谢。

2 个答案:

答案 0 :(得分:7)

也许有点晚来帮助你,但为了其他人尝试这个的好处,这是一个答案。

它实际上比你想象的更简单(有一个问题) - 我正在使用DirectFb 1.4.11做你想要的。

一旦你有了主要的表面,不要打扰DataBuffer。使用DSDESC_PREALLOCATED flasg和缓冲区作为预分配数据创建另一个曲面。然后将新表面的数据Blit()到主表面上,然后将主表面翻转()到屏幕上。一个问题是你的数据需要采用DirectFB理解的格式:32位RGBA不是其中之一,但32位ARGB是 - 我必须解析我的缓冲区来交换字节。

示例代码:

  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));

如果您的缓冲区与屏幕的大小/形状不同,则可以使用StretchBlit()来调整其大小。

我希望这会有所帮助。

答案 1 :(得分:3)

MartinP的上述答案很好,但只有在图像未压缩的情况下才有效。我找到了这个主题,因为我想直接从内存中加载和解码/解压缩png / jpeg图像。

这方面几乎没有任何有用的信息,我一直在努力解决这个问题,但是我们发现了如何做到这一点。虽然这是一个老问题,但它可能会帮助其他人尝试实现同样的目标:

// Variables
DFBDataBufferDescription ddsc;
DFBSurfaceDescription sdsc;
IDirectFBDataBuffer *buffer;
IDirectFBImageProvider *image_provider;

// The surface that will contain the rendered image
IDirectFBSurface *surface;                      

// create a data buffer for memory
ddsc.flags = DBDESC_MEMORY;
ddsc.memory.data = data;
ddsc.memory.length = dataLength;
DFBCHECK(directFB->CreateDataBuffer(directFB, &ddsc, &buffer));

// Create the image provider, surface description and surface itself
DFBCHECK(buffer->CreateImageProvider(buffer, &image_provider));
DFBCHECK(image_provider->GetSurfaceDescription(image_provider, &sdsc));
DFBCHECK(directFB->CreateSurface(directFB, &sdsc, &surface ));

// Now render the image onto the surface
DFBCHECK(image_provider->RenderTo(image_provider, surface, NULL));

// Release 
image_provider->Release(image_provider);
buffer->Release(buffer);

data 变量是指向包含图像的unsigned char数组的指针(提示:您可以使用'xxd -i image.jpg> image.h'创建这样的数组)。 datalength 是一个带有数组大小的unsigned int。创建的曲面可以在屏幕上显示,或者您可以立即“渲染”显示表面。