6

我需要一种将数据缓冲区显示到屏幕的非常快速的方法。我首先尝试访问 linux 帧缓冲区,结果证明非常好。然后我了解了 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渲染到帧缓冲区?

谢谢。

4

2 回答 2

8

也许帮助你有点晚了,但为了其他尝试这个的人的利益,这里有一个答案。

它实际上比你想象的要简单(有一个陷阱)——我正在做你想做的事,使用 DirectFb 1.4.11。

一旦你有了主表面,就不要打扰 DataBuffer。创建另一个表面,使用 DSDESC_PREALLOCATED 标志和您的缓冲区作为预分配数据。然后将新曲面中的数据 Blit() 到主曲面上,然后将主曲面 Flip() 到屏幕上。一个问题是您的数据需要采用 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() 来调整它的大小。

我希望这有帮助。

于 2012-03-16T08:59:05.580 回答
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是一个无符号整数,具有数组的大小。创建的表面可以blit到屏幕上,或者您可以一次“渲染”显示表面。

于 2014-03-31T17:13:51.480 回答