使用qvfb在X11下开发framebuffer应用程序
2007-10-18 11:32:59| 分类:Linux |字号 订阅
qvfb是QT virtualframebuffer的缩写,是QT在X11下的一个framebuffer仿真器,有了它我们就可以利用X11下众多便利的工具来开发基于framebuffer的应用程序了。qvfb的原理很简单,它建立了一个systemV共享内存,用户只需将需要显示的图像按像素格式要求放到共享内存里qvfb就可以显示了。
System V共享内存连接的步骤是:
1.通过ftok拿到key
2.使用shmget拿到shmid
3.使用shmat连接到共享内存
这里需要注意的是,key的生成需要向ftok传入一个双方约定好的文件名,对于qvfb屏幕设备,这个文件是/tmp/.qtvfb_mouse-0。
qvfb创建的共享内存包含一个私有的数据头,用于指示像素格式、宽高等信息。这个头结构定义如下:
struct QVFbHeader
{
int width;
int height;
int depth;
int linestep;
int dataoffset;
int update[4];
char dirty;
int numcols;
unsigned int clut[256];
};
其中dataoffset是virtual framebuffer相对于头结构的偏移位置。向偏移后的地址写入数据就可以反应到qvfb上了。以下是一段示例,
int key = ftok("/tmp/.qtvfb_mouse-0", 'b');
int shmid = shmget(key, 0, 0);
if (shmid !=-1)
{
struct QVFbHeader* qvfb_data = shmat(shmid, 0, 0);
if (qvfb_data != NULL)
memset((char*)qvfb_data + qvfb_data->dataoffset, 0xff, 65535);
}
Qtopia 里面的一段代码:
bool QVFbScreen::connect(const QString &displaySpec)
220 {
221 screen_optype=&QVFb_dummy;
222 screen_lastop=&QVFb_dummy;
223
224 if (displaySpec.indexOf(":Gray") >= 0)
225 grayscale = true;
226
227 key_t key = ftok(QByteArray(QT_VFB_MOUSE_PIPE).replace("%1", QByteArray::number(displayId)), 'b');
228
229 if (key == -1)
230 return false;
231
232 int shmId = shmget(key, 0, 0);
233 if (shmId != -1)
234 shmrgn = (unsigned char *)shmat(shmId, 0, 0);
235 else
236 return false;
237
238 if ((long)shmrgn == -1 || shmrgn == 0) {
239 qDebug("No shmrgn %ld", (long)shmrgn);
240 return false;
241 }
hdr = (QVFbHeader *) shmrgn;
244 data = shmrgn + hdr->dataoffset;
245
246 dw = w = hdr->width;
247 dh = h = hdr->height;
248 d = hdr->depth;
249 lstep = hdr->linestep;
250
251 qDebug("Connected to VFB server: %d x %d x %d\n", w, h, d);
252 qDebug("\n\r FILE: %s \tFunction:%s\n",__FILE__,__FUNCTION__);
253
254 size = lstep * h;
255 mapsize = size;
256 screencols = hdr->numcols;
257 memcpy(screenclut, hdr->clut, sizeof(QRgb) * screencols);
if (qApp->type() == QApplication::GuiServer) {
260 // We handle mouse and keyboard here
261 QWSServer::setDefaultMouse("None");
262 QWSServer::setDefaultKeyboard("None");
263 qDebug("\n\r$$$$$$$$$$$$New mouse , New Keyboard$$$$$$$$$$$$$$\n");
264 mouseHandler = new QVFbMouseHandler(displayId);
265 keyboardHandler = new QVFbKeyboardHandler(displayId);
266 if (hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
267 hdr->serverVersion = QT_VERSION;
268 }
269 }
270
271 return true;
272 }
void QVFbScreen::disconnect()
275 {
276 if ((long)shmrgn != -1 && shmrgn) {
277 if (qApp->type() == QApplication::GuiServer && hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
278 hdr->serverVersion = 0;
279 }
280 shmdt((char*)shmrgn);
281 }
282 if (qApp->type() == QApplication::GuiServer) {
283 delete mouseHandler;
284 mouseHandler = 0;
285 delete keyboardHandler;
286 keyboardHandler = 0;
287 }
288 }