来自内存缓冲区的 DirectFB 数据
Posted
技术标签:
【中文标题】来自内存缓冲区的 DirectFB 数据【英文标题】:DirectFB data from memory buffer 【发布时间】:2011-10-25 11:02:32 【问题描述】:我需要一种在屏幕上显示数据缓冲区的非常快速的方法。我首先尝试访问 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 渲染到帧缓冲区?
谢谢。
【问题讨论】:
【参考方案1】:帮助您可能有点晚了,但为了其他尝试此操作的人的利益,这里有一个答案。
它实际上比你想象的要简单(有一个问题)——我正在做你想做的事,使用 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() 来调整它的大小。
我希望这会有所帮助。
【讨论】:
【参考方案2】:上面来自 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 是具有数组大小的无符号整数。创建的surface可以blit到屏幕上,或者您可以一次“渲染”到显示表面。
【讨论】:
这对我来说失败了,但我认为这是因为我将原始 ARGB 数据转储到了一个没有元信息的文件中,例如可能有的 PNG/JPEG/BMP 文件。我也必须尝试这个解决方案,这样我才能使我的应用程序更便携,谢谢分享。 这行得通。谢谢,我在ddsc.memory.data
中插入了一个 png 图像,它可以工作。以上是关于来自内存缓冲区的 DirectFB 数据的主要内容,如果未能解决你的问题,请参考以下文章