Qt 4.8
pvrqwsdrawable.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "pvrqwsdrawable_p.h"
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/types.h>
47 #include <sys/mman.h>
48 #include <sys/ioctl.h>
49 #include <linux/fb.h>
50 #include <fcntl.h>
51 #include <unistd.h>
52 
54 
55 static void pvrQwsDestroyDrawableForced(PvrQwsDrawable *drawable);
56 
57 /* Initialize the /dev/fbN device for a specific screen */
58 static int pvrQwsInitFbScreen(int screen)
59 {
60  struct fb_var_screeninfo var;
61  struct fb_fix_screeninfo fix;
62  unsigned long start;
63  unsigned long length;
64  int width, height, stride;
65  PVR2DFORMAT format;
66  void *mapped;
67  int fd, bytesPerPixel;
68  char name[64];
69  PVR2DMEMINFO *memInfo;
70  unsigned long pageAddresses[2];
71 
72  /* Bail out if already initialized, or the number is incorrect */
73  if (screen < 0 || screen >= PVRQWS_MAX_SCREENS)
74  return 0;
75  if (pvrQwsDisplay.screens[screen].initialized)
76  return 1;
77 
78  /* Open the framebuffer and fetch its properties */
79  sprintf(name, "/dev/fb%d", screen);
80  fd = open(name, O_RDWR, 0);
81  if (fd < 0) {
82  perror(name);
83  return 0;
84  }
85  if (ioctl(fd, FBIOGET_VSCREENINFO, &var) < 0) {
86  perror("FBIOGET_VSCREENINFO");
87  close(fd);
88  return 0;
89  }
90  if (ioctl(fd, FBIOGET_FSCREENINFO, &fix) < 0) {
91  perror("FBIOGET_FSCREENINFO");
92  close(fd);
93  return 0;
94  }
95  width = var.xres;
96  height = var.yres;
97  bytesPerPixel = var.bits_per_pixel / 8;
98  stride = fix.line_length;
99  format = PVR2D_1BPP;
100  if (var.bits_per_pixel == 16) {
101  if (var.red.length == 5 && var.green.length == 6 &&
102  var.blue.length == 5 && var.red.offset == 11 &&
103  var.green.offset == 5 && var.blue.offset == 0) {
104  format = PVR2D_RGB565;
105  }
106  if (var.red.length == 4 && var.green.length == 4 &&
107  var.blue.length == 4 && var.transp.length == 4 &&
108  var.red.offset == 8 && var.green.offset == 4 &&
109  var.blue.offset == 0 && var.transp.offset == 12) {
110  format = PVR2D_ARGB4444;
111  }
112  } else if (var.bits_per_pixel == 32) {
113  if (var.red.length == 8 && var.green.length == 8 &&
114  var.blue.length == 8 && var.transp.length == 8 &&
115  var.red.offset == 16 && var.green.offset == 8 &&
116  var.blue.offset == 0 && var.transp.offset == 24) {
117  format = PVR2D_ARGB8888;
118  }
119  }
120  if (format == PVR2D_1BPP) {
121  fprintf(stderr, "%s: could not find a suitable PVR2D pixel format\n", name);
122  close(fd);
123  return 0;
124  }
125  start = fix.smem_start;
126  length = var.xres_virtual * var.yres_virtual * bytesPerPixel;
127 
128  if (screen == 0) {
129  /* We use PVR2DGetFrameBuffer to map the first screen.
130  On some chipsets it is more reliable than using PVR2DMemWrap */
131  mapped = 0;
132  memInfo = 0;
133  } else {
134  /* Other screens: map the framebuffer region into memory */
135  mapped = mmap(0, length, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
136  if (!mapped || mapped == (void *)(-1)) {
137  perror("mmap");
138  close(fd);
139  return 0;
140  }
141 
142  /* Allocate a PVR2D memory region for the framebuffer */
143  memInfo = 0;
144  if (pvrQwsDisplay.context) {
145  pageAddresses[0] = start & 0xFFFFF000;
146  pageAddresses[1] = 0;
147  if (PVR2DMemWrap
148  (pvrQwsDisplay.context, mapped, PVR2D_WRAPFLAG_CONTIGUOUS,
149  length, pageAddresses, &memInfo) != PVR2D_OK) {
150  munmap(mapped, length);
151  close(fd);
152  return 0;
153  }
154  }
155  }
156 
157  /* We don't need the file descriptor any more */
158  close(fd);
159 
160  /* The framebuffer is ready, so initialize the PvrQwsScreenInfo */
161  pvrQwsDisplay.screens[screen].screenRect.x = 0;
162  pvrQwsDisplay.screens[screen].screenRect.y = 0;
163  pvrQwsDisplay.screens[screen].screenRect.width = width;
164  pvrQwsDisplay.screens[screen].screenRect.height = height;
165  pvrQwsDisplay.screens[screen].screenStride = stride;
166  pvrQwsDisplay.screens[screen].pixelFormat = format;
167  pvrQwsDisplay.screens[screen].bytesPerPixel = bytesPerPixel;
168  pvrQwsDisplay.screens[screen].screenDrawable = 0;
169  if (mapped) {
170  /* Don't set these fields if mapped is 0, because PVR2DGetFrameBuffer
171  may have already been called and set them */
172  pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
173  pvrQwsDisplay.screens[screen].mapped = mapped;
174  }
175  pvrQwsDisplay.screens[screen].mappedLength = length;
176  pvrQwsDisplay.screens[screen].screenStart = start;
177  pvrQwsDisplay.screens[screen].needsUnmap = (mapped != 0);
178  pvrQwsDisplay.screens[screen].initialized = 1;
179  return 1;
180 }
181 
182 /* Called when a new drawable is added to ensure that we have a
183  PVR2D context and framebuffer PVR2DMEMINFO blocks */
184 static int pvrQwsAddDrawable(void)
185 {
186  int numDevs, screen;
187  PVR2DDEVICEINFO *devs;
188  unsigned long devId;
189  unsigned long pageAddresses[2];
190  PVR2DMEMINFO *memInfo;
191  PVR2DDISPLAYINFO displayInfo;
192 
193  /* Bail out early if this is not the first drawable */
194  if (pvrQwsDisplay.numDrawables > 0) {
195  ++(pvrQwsDisplay.numDrawables);
196  return 1;
197  }
198 
199  /* Find the first PVR2D device in the system and open it */
200  numDevs = PVR2DEnumerateDevices(0);
201  if (numDevs <= 0)
202  return 0;
203  devs = (PVR2DDEVICEINFO *)malloc(sizeof(PVR2DDEVICEINFO) * numDevs);
204  if (!devs)
205  return 0;
206  if (PVR2DEnumerateDevices(devs) != PVR2D_OK) {
207  free(devs);
208  return 0;
209  }
210  devId = devs[0].ulDevID;
211  free(devs);
212  if (PVR2DCreateDeviceContext(devId, &pvrQwsDisplay.context, 0) != PVR2D_OK)
213  return 0;
214  pvrQwsDisplay.numFlipBuffers = 0;
215  pvrQwsDisplay.flipChain = 0;
216  if (PVR2DGetDeviceInfo(pvrQwsDisplay.context, &displayInfo) == PVR2D_OK) {
217  if (displayInfo.ulMaxFlipChains > 0 && displayInfo.ulMaxBuffersInChain > 0)
218  pvrQwsDisplay.numFlipBuffers = displayInfo.ulMaxBuffersInChain;
219  if (pvrQwsDisplay.numFlipBuffers > PVRQWS_MAX_FLIP_BUFFERS)
220  pvrQwsDisplay.numFlipBuffers = PVRQWS_MAX_FLIP_BUFFERS;
221  }
222 
223  /* Create the PVR2DMEMINFO blocks for the active framebuffers */
224  for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
225  if (screen != 0 && pvrQwsDisplay.screens[screen].mapped) {
226  pageAddresses[0]
227  = pvrQwsDisplay.screens[screen].screenStart & 0xFFFFF000;
228  pageAddresses[1] = 0;
229  if (PVR2DMemWrap
230  (pvrQwsDisplay.context,
231  pvrQwsDisplay.screens[screen].mapped,
232  PVR2D_WRAPFLAG_CONTIGUOUS,
233  pvrQwsDisplay.screens[screen].mappedLength,
234  pageAddresses, &memInfo) != PVR2D_OK) {
235  PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
236  pvrQwsDisplay.context = 0;
237  return 0;
238  }
239  pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
240  } else if (screen == 0) {
241  if (PVR2DGetFrameBuffer
242  (pvrQwsDisplay.context,
243  PVR2D_FB_PRIMARY_SURFACE, &memInfo) != PVR2D_OK) {
244  fprintf(stderr, "QWSWSEGL: could not get the primary framebuffer surface\n");
245  PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
246  pvrQwsDisplay.context = 0;
247  return 0;
248  }
249  pvrQwsDisplay.screens[screen].frameBuffer = memInfo;
250  pvrQwsDisplay.screens[screen].mapped = memInfo->pBase;
251  }
252  }
253 
254  /* Create a flip chain for the screen if supported by the hardware */
255  pvrQwsDisplay.usePresentBlit = 0;
256  if (pvrQwsDisplay.numFlipBuffers > 0) {
257  long stride = 0;
258  unsigned long flipId = 0;
259  unsigned long numBuffers;
260  if (PVR2DCreateFlipChain(pvrQwsDisplay.context, 0,
261  //PVR2D_CREATE_FLIPCHAIN_SHARED |
262  //PVR2D_CREATE_FLIPCHAIN_QUERY,
263  pvrQwsDisplay.numFlipBuffers,
264  pvrQwsDisplay.screens[0].screenRect.width,
265  pvrQwsDisplay.screens[0].screenRect.height,
266  pvrQwsDisplay.screens[0].pixelFormat,
267  &stride, &flipId, &(pvrQwsDisplay.flipChain))
268  == PVR2D_OK) {
269  pvrQwsDisplay.screens[0].screenStride = stride;
270  PVR2DGetFlipChainBuffers(pvrQwsDisplay.context,
271  pvrQwsDisplay.flipChain,
272  &numBuffers,
273  pvrQwsDisplay.flipBuffers);
274  } else {
275  pvrQwsDisplay.flipChain = 0;
276  pvrQwsDisplay.numFlipBuffers = 0;
277  }
278 
279  /* PVR2DPresentBlt is a little more reliable than PVR2DBlt
280  when flip chains are present, even if we cannot create a
281  flip chain at the moment */
282  pvrQwsDisplay.usePresentBlit = 1;
283  }
284 
285  /* The context is ready to go */
286  ++(pvrQwsDisplay.numDrawables);
287  return 1;
288 }
289 
290 /* Called when the last drawable is destroyed. The PVR2D context
291  will be destroyed but the raw framebuffer memory will stay mapped */
292 static void pvrQwsDestroyContext(void)
293 {
294  int screen;
295  for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
296  if (pvrQwsDisplay.screens[screen].frameBuffer) {
297  PVR2DMemFree
298  (pvrQwsDisplay.context,
299  pvrQwsDisplay.screens[screen].frameBuffer);
300  pvrQwsDisplay.screens[screen].frameBuffer = 0;
301  }
302  }
303 
304  if (pvrQwsDisplay.numFlipBuffers > 0)
305  PVR2DDestroyFlipChain(pvrQwsDisplay.context, pvrQwsDisplay.flipChain);
306  PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
307  pvrQwsDisplay.context = 0;
308  pvrQwsDisplay.flipChain = 0;
309  pvrQwsDisplay.numFlipBuffers = 0;
310  pvrQwsDisplay.usePresentBlit = 0;
311 }
312 
314 {
315  int screen;
316 
317  /* If the display is already open, increase reference count and return */
318  if (pvrQwsDisplay.refCount > 0) {
319  ++(pvrQwsDisplay.refCount);
320  return 1;
321  }
322 
323  /* Open the framebuffer and map it directly */
324  if (!pvrQwsInitFbScreen(0)) {
325  --(pvrQwsDisplay.refCount);
326  return 0;
327  }
328 
329  /* Clear the other screens. We will create them if they are referenced */
330  for (screen = 1; screen < PVRQWS_MAX_SCREENS; ++screen)
331  memset(&(pvrQwsDisplay.screens[screen]), 0, sizeof(PvrQwsScreenInfo));
332 
333  /* The display is open and ready */
334  ++(pvrQwsDisplay.refCount);
335  return 1;
336 }
337 
339 {
340  int screen;
341 
342  if (pvrQwsDisplay.refCount == 0)
343  return;
344  if (--(pvrQwsDisplay.refCount) > 0)
345  return;
346 
347  /* Prevent pvrQwsDestroyContext from being called for the time being */
348  ++pvrQwsDisplay.numDrawables;
349 
350  /* Free the screens */
351  for (screen = 0; screen < PVRQWS_MAX_SCREENS; ++screen) {
352  PvrQwsScreenInfo *info = &(pvrQwsDisplay.screens[screen]);
353  if (info->screenDrawable)
355  if (info->frameBuffer)
356  PVR2DMemFree(pvrQwsDisplay.context, info->frameBuffer);
357  if (info->mapped && info->needsUnmap)
358  munmap(info->mapped, info->mappedLength);
359  }
360 
361  /* Now it is safe to destroy the PVR2D context */
362  --pvrQwsDisplay.numDrawables;
363  if (pvrQwsDisplay.context)
364  PVR2DDestroyDeviceContext(pvrQwsDisplay.context);
365 
366  memset(&pvrQwsDisplay, 0, sizeof(pvrQwsDisplay));
367 }
368 
370 {
371  return (pvrQwsDisplay.refCount > 0);
372 }
373 
374 /* Ensure that a specific screen has been initialized */
375 static int pvrQwsEnsureScreen(int screen)
376 {
377  if (screen < 0 || screen >= PVRQWS_MAX_SCREENS)
378  return 0;
379  if (!screen)
380  return 1;
381  return pvrQwsInitFbScreen(screen);
382 }
383 
385 {
386  PvrQwsDrawable *drawable;
387 
388  if (!pvrQwsEnsureScreen(screen))
389  return 0;
390 
391  drawable = pvrQwsDisplay.screens[screen].screenDrawable;
392  if (drawable)
393  return drawable;
394 
395  drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
396  if (!drawable)
397  return 0;
398 
399  drawable->type = PvrQwsScreen;
400  drawable->screen = screen;
401  drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
402  drawable->rect = pvrQwsDisplay.screens[screen].screenRect;
403  drawable->visibleRects[0] = drawable->rect;
404  drawable->numVisibleRects = 1;
405  drawable->isFullScreen = 1;
406 
407  if (!pvrQwsAddDrawable()) {
408  free(drawable);
409  return 0;
410  }
411 
412  pvrQwsDisplay.screens[screen].screenDrawable = drawable;
413 
414  return drawable;
415 }
416 
417 PvrQwsDrawable *pvrQwsCreateWindow(int screen, long winId, const PvrQwsRect *rect)
418 {
419  PvrQwsDrawable *drawable;
420 
421  if (!pvrQwsEnsureScreen(screen))
422  return 0;
423 
424  drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
425  if (!drawable)
426  return 0;
427 
428  drawable->type = PvrQwsWindow;
429  drawable->winId = winId;
430  drawable->refCount = 1;
431  drawable->screen = screen;
432  drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
433  drawable->rect = *rect;
434 
435  if (!pvrQwsAddDrawable()) {
436  free(drawable);
437  return 0;
438  }
439 
440  drawable->nextWinId = pvrQwsDisplay.firstWinId;
441  pvrQwsDisplay.firstWinId = drawable;
442 
443  return drawable;
444 }
445 
447 {
448  PvrQwsDrawable *drawable = pvrQwsDisplay.firstWinId;
449  while (drawable != 0 && drawable->winId != winId)
450  drawable = drawable->nextWinId;
451 
452  if (drawable)
453  ++(drawable->refCount);
454  return drawable;
455 }
456 
458 {
459  if (drawable->type == PvrQwsWindow)
460  return (--(drawable->refCount) <= 0);
461  else
462  return 0;
463 }
464 
465 PvrQwsDrawable *pvrQwsCreatePixmap(int width, int height, int screen)
466 {
467  PvrQwsDrawable *drawable;
468 
469  if (!pvrQwsEnsureScreen(screen))
470  return 0;
471 
472  drawable = (PvrQwsDrawable *)calloc(1, sizeof(PvrQwsDrawable));
473  if (!drawable)
474  return 0;
475 
476  drawable->type = PvrQwsPixmap;
477  drawable->screen = screen;
478  drawable->pixelFormat = pvrQwsDisplay.screens[screen].pixelFormat;
479  drawable->rect.x = 0;
480  drawable->rect.y = 0;
481  drawable->rect.width = width;
482  drawable->rect.height = height;
483 
484  if (!pvrQwsAddDrawable()) {
485  free(drawable);
486  return 0;
487  }
488 
489  return drawable;
490 }
491 
493 {
494  /* Remove the drawable from the display's winId list */
495  PvrQwsDrawable *current = pvrQwsDisplay.firstWinId;
496  PvrQwsDrawable *prev = 0;
497  while (current != 0 && current != drawable) {
498  prev = current;
499  current = current->nextWinId;
500  }
501  if (current != 0) {
502  if (prev)
503  prev->nextWinId = current->nextWinId;
504  else
505  pvrQwsDisplay.firstWinId = current->nextWinId;
506  }
507 
508  pvrQwsFreeBuffers(drawable);
509  free(drawable);
510 
511  --pvrQwsDisplay.numDrawables;
512  if (pvrQwsDisplay.numDrawables == 0)
514 }
515 
517 {
518  if (drawable && drawable->type != PvrQwsScreen)
519  pvrQwsDestroyDrawableForced(drawable);
520 }
521 
523 {
524  return drawable->type;
525 }
526 
528  (PvrQwsDrawable *drawable, const PvrQwsRect *rects, int numRects)
529 {
530  int index, indexOut;
531  PvrQwsRect *rect;
532  PvrQwsRect *screenRect;
533 
534  /* Visible regions don't make sense for pixmaps */
535  if (drawable->type == PvrQwsPixmap)
536  return;
537 
538  /* Restrict the number of rectangles to prevent buffer overflow */
539  if (numRects > PVRQWS_MAX_VISIBLE_RECTS)
540  numRects = PVRQWS_MAX_VISIBLE_RECTS;
541  if (numRects > 0)
542  memcpy(drawable->visibleRects, rects, numRects * sizeof(PvrQwsRect));
543 
544  /* Convert the rectangles into screen-relative co-ordinates and
545  then clamp them to the screen boundaries. If any of the
546  clamped rectangles are empty, remove them from the list */
547  screenRect = &(pvrQwsDisplay.screens[drawable->screen].screenRect);
548  indexOut = 0;
549  for (index = 0, rect = drawable->visibleRects; index < numRects; ++index, ++rect) {
550  if (rect->x < 0) {
551  rect->width += rect->x;
552  rect->x = 0;
553  if (rect->width < 0)
554  rect->width = 0;
555  } else if (rect->x >= screenRect->width) {
556  rect->x = screenRect->width;
557  rect->width = 0;
558  }
559  if ((rect->x + rect->width) > screenRect->width) {
560  rect->width = screenRect->width - rect->x;
561  }
562  if (rect->y < 0) {
563  rect->height += rect->y;
564  rect->y = 0;
565  if (rect->height < 0)
566  rect->height = 0;
567  } else if (rect->y >= screenRect->height) {
568  rect->y = screenRect->height;
569  rect->height = 0;
570  }
571  if ((rect->y + rect->height) > screenRect->height) {
572  rect->height = screenRect->height - rect->y;
573  }
574  if (rect->width > 0 && rect->height > 0) {
575  if (index != indexOut)
576  drawable->visibleRects[indexOut] = *rect;
577  ++indexOut;
578  }
579  }
580  drawable->numVisibleRects = indexOut;
581 }
582 
584 {
585  if (drawable->type != PvrQwsPixmap)
586  drawable->numVisibleRects = 0;
587 }
588 
589 void pvrQwsSetGeometry(PvrQwsDrawable *drawable, const PvrQwsRect *rect)
590 {
591  /* We can only change the geometry of window drawables */
592  if (drawable->type != PvrQwsWindow)
593  return;
594 
595  /* If the position has changed, then clear the visible region */
596  if (drawable->rect.x != rect->x || drawable->rect.y != rect->y) {
597  drawable->rect.x = rect->x;
598  drawable->rect.y = rect->y;
599  drawable->numVisibleRects = 0;
600  }
601 
602  /* If the size has changed, then clear the visible region and
603  invalidate the drawable's buffers. Invalidating the buffers
604  will force EGL to recreate the drawable, which will then
605  allocate new buffers for the new size */
606  if (drawable->rect.width != rect->width ||
607  drawable->rect.height != rect->height) {
608  drawable->rect.width = rect->width;
609  drawable->rect.height = rect->height;
610  drawable->numVisibleRects = 0;
611  pvrQwsInvalidateBuffers(drawable);
612  }
613 }
614 
616 {
617  *rect = drawable->rect;
618 }
619 
621 {
622  if (drawable->rotationAngle != angle) {
623  drawable->rotationAngle = angle;
624 
625  /* Force the buffers to be recreated if the rotation angle changes */
626  pvrQwsInvalidateBuffers(drawable);
627  }
628 }
629 
631 {
632  if (drawable->backBuffersValid)
633  return drawable->strideBytes;
634  else
635  return 0;
636 }
637 
639 {
640  return (PvrQwsPixelFormat)(drawable->pixelFormat);
641 }
642 
644 {
645  if (drawable->backBuffersValid)
646  return drawable->backBuffers[drawable->currentBackBuffer]->pBase;
647  else
648  return 0;
649 }
650 
652 {
653  int index;
654  int numBuffers = PVRQWS_MAX_BACK_BUFFERS;
655  if (drawable->type == PvrQwsPixmap)
656  numBuffers = 1;
657  if (drawable->backBuffers[0]) {
658  if (drawable->backBuffersValid)
659  return 1;
660  if (!drawable->usingFlipBuffers) {
661  for (index = 0; index < numBuffers; ++index)
662  PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
663  }
664  }
665  drawable->stridePixels = (drawable->rect.width + 31) & ~31;
666  drawable->strideBytes =
667  drawable->stridePixels *
668  pvrQwsDisplay.screens[drawable->screen].bytesPerPixel;
669  drawable->usingFlipBuffers =
670  (pvrQwsDisplay.numFlipBuffers > 0 && drawable->isFullScreen);
671  if (drawable->usingFlipBuffers) {
672  if (numBuffers > (int)(pvrQwsDisplay.numFlipBuffers))
673  numBuffers = pvrQwsDisplay.numFlipBuffers;
674  for (index = 0; index < numBuffers; ++index)
675  drawable->backBuffers[index] = pvrQwsDisplay.flipBuffers[index];
676  } else {
677  for (index = 0; index < numBuffers; ++index) {
678  if (PVR2DMemAlloc(pvrQwsDisplay.context,
679  drawable->strideBytes * drawable->rect.height,
680  128, 0,
681  &(drawable->backBuffers[index])) != PVR2D_OK) {
682  while (--index >= 0)
683  PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
684  memset(drawable->backBuffers, 0, sizeof(drawable->backBuffers));
685  drawable->backBuffersValid = 0;
686  return 0;
687  }
688  }
689  }
690  for (index = numBuffers; index < PVRQWS_MAX_BACK_BUFFERS; ++index) {
691  drawable->backBuffers[index] = drawable->backBuffers[0];
692  }
693  drawable->backBuffersValid = 1;
694  drawable->currentBackBuffer = 0;
695  return 1;
696 }
697 
699 {
700  int index;
701  int numBuffers = PVRQWS_MAX_BACK_BUFFERS;
702  if (drawable->type == PvrQwsPixmap)
703  numBuffers = 1;
704  if (!drawable->usingFlipBuffers) {
705  for (index = 0; index < numBuffers; ++index) {
706  if (drawable->backBuffers[index])
707  PVR2DMemFree(pvrQwsDisplay.context, drawable->backBuffers[index]);
708  }
709  }
710  memset(drawable->backBuffers, 0, sizeof(drawable->backBuffers));
711  drawable->backBuffersValid = 0;
712  drawable->usingFlipBuffers = 0;
713 }
714 
716 {
717  drawable->backBuffersValid = 0;
718 }
719 
721  (PvrQwsDrawable *drawable, PVR2DMEMINFO **source, PVR2DMEMINFO **render)
722 {
723  if (!drawable->backBuffersValid)
724  return 0;
725  *render = drawable->backBuffers[drawable->currentBackBuffer];
726  *source = drawable->backBuffers
727  [(drawable->currentBackBuffer + PVRQWS_MAX_BACK_BUFFERS - 1) %
729  return 1;
730 }
731 
732 int pvrQwsSwapBuffers(PvrQwsDrawable *drawable, int repaintOnly)
733 {
734  PVR2DMEMINFO *buffer;
735  PvrQwsRect *rect;
736  int index;
737 
738  /* Bail out if the back buffers have been invalidated */
739  if (!drawable->backBuffersValid)
740  return 0;
741 
742  /* If there is a swap function, then use that instead */
743  if (drawable->swapFunction) {
744  (*(drawable->swapFunction))(drawable, drawable->userData, repaintOnly);
745  if (!repaintOnly) {
746  drawable->currentBackBuffer
747  = (drawable->currentBackBuffer + 1) % PVRQWS_MAX_BACK_BUFFERS;
748  }
749  return 1;
750  }
751 
752  /* Iterate through the visible rectangles and blit them to the screen */
753  if (!repaintOnly) {
754  index = drawable->currentBackBuffer;
755  } else {
756  index = (drawable->currentBackBuffer + PVRQWS_MAX_BACK_BUFFERS - 1)
758  }
759  buffer = drawable->backBuffers[index];
760  rect = drawable->visibleRects;
761  if (drawable->usingFlipBuffers) {
762  PVR2DPresentFlip(pvrQwsDisplay.context, pvrQwsDisplay.flipChain, buffer, 0);
763  } else if (pvrQwsDisplay.usePresentBlit && drawable->numVisibleRects > 0) {
764  PVR2DRECT pvrRects[PVRQWS_MAX_VISIBLE_RECTS];
765  for (index = 0; index < drawable->numVisibleRects; ++index, ++rect) {
766  pvrRects[index].left = rect->x;
767  pvrRects[index].top = rect->y;
768  pvrRects[index].right = rect->x + rect->width;
769  pvrRects[index].bottom = rect->y + rect->height;
770  }
771  for (index = 0; index < drawable->numVisibleRects; index += 4) {
772  int numClip = drawable->numVisibleRects - index;
773  if (numClip > 4) /* No more than 4 clip rects at a time */
774  numClip = 4;
775  PVR2DSetPresentBltProperties
776  (pvrQwsDisplay.context,
777  PVR2D_PRESENT_PROPERTY_SRCSTRIDE |
778  PVR2D_PRESENT_PROPERTY_DSTSIZE |
779  PVR2D_PRESENT_PROPERTY_DSTPOS |
780  PVR2D_PRESENT_PROPERTY_CLIPRECTS,
781  drawable->strideBytes,
782  drawable->rect.width, drawable->rect.height,
783  drawable->rect.x, drawable->rect.y,
784  numClip, pvrRects + index, 0);
785  PVR2DPresentBlt(pvrQwsDisplay.context, buffer, 0);
786  }
787  PVR2DQueryBlitsComplete(pvrQwsDisplay.context, buffer, 1);
788  } else {
789  /* TODO: use PVR2DBltClipped for faster transfers of clipped windows */
790  PVR2DBLTINFO blit;
791  for (index = 0; index < drawable->numVisibleRects; ++index, ++rect) {
792  memset(&blit, 0, sizeof(blit));
793 
794  blit.CopyCode = PVR2DROPcopy;
795  blit.BlitFlags = PVR2D_BLIT_DISABLE_ALL;
796 
797  blit.pSrcMemInfo = buffer;
798  blit.SrcStride = drawable->strideBytes;
799  blit.SrcX = rect->x - drawable->rect.x;
800  blit.SrcY = rect->y - drawable->rect.y;
801  blit.SizeX = rect->width;
802  blit.SizeY = rect->height;
803  blit.SrcFormat = drawable->pixelFormat;
804 
805  blit.pDstMemInfo = pvrQwsDisplay.screens[drawable->screen].frameBuffer;
806  blit.DstStride = pvrQwsDisplay.screens[drawable->screen].screenStride;
807  blit.DstX = rect->x;
808  blit.DstY = rect->y;
809  blit.DSizeX = rect->width;
810  blit.DSizeY = rect->height;
811  blit.DstFormat = pvrQwsDisplay.screens[drawable->screen].pixelFormat;
812 
813  PVR2DBlt(pvrQwsDisplay.context, &blit);
814  }
815  }
816 
817  /* Swap the buffers */
818  if (!repaintOnly) {
819  drawable->currentBackBuffer
820  = (drawable->currentBackBuffer + 1) % PVRQWS_MAX_BACK_BUFFERS;
821  }
822  return 1;
823 }
824 
826  (PvrQwsDrawable *drawable, PvrQwsSwapFunction func, void *userData)
827 {
828  drawable->swapFunction = func;
829  drawable->userData = userData;
830 }
void pvrQwsSetGeometry(PvrQwsDrawable *drawable, const PvrQwsRect *rect)
PVR2DMEMINFO * backBuffers[PVRQWS_MAX_BACK_BUFFERS]
static int pvrQwsInitFbScreen(int screen)
int pvrQwsAllocBuffers(PvrQwsDrawable *drawable)
PvrQwsDrawable * pvrQwsCreatePixmap(int width, int height, int screen)
PvrQwsPixelFormat
PVR2DMEMINFO * frameBuffer
void pvrQwsClearVisibleRegion(PvrQwsDrawable *drawable)
static mach_timebase_info_data_t info
PVR2DFORMAT pixelFormat
void(* PvrQwsSwapFunction)(PvrQwsDrawable *drawable, void *userData, int repaintOnly)
PvrQwsDrawable * pvrQwsFetchWindow(long winId)
PvrQwsDrawableType
PVR2DFLIPCHAINHANDLE flipChain
PVR2DCONTEXTHANDLE context
#define PVRQWS_MAX_BACK_BUFFERS
void pvrQwsFreeBuffers(PvrQwsDrawable *drawable)
static int bytesPerPixel(QImage::Format format)
PvrQwsDisplay pvrQwsDisplay
PvrQwsRect screenRect
int pvrQwsGetBuffers(PvrQwsDrawable *drawable, PVR2DMEMINFO **source, PVR2DMEMINFO **render)
int pvrQwsDisplayOpen(void)
void pvrQwsGetGeometry(PvrQwsDrawable *drawable, PvrQwsRect *rect)
#define PVRQWS_MAX_SCREENS
int pvrQwsGetStride(PvrQwsDrawable *drawable)
PvrQwsRect visibleRects[PVRQWS_MAX_VISIBLE_RECTS]
QFuture< T > mapped(const Sequence &sequence, MapFunction function)
PvrQwsDrawableType type
PvrQwsDrawable * nextWinId
PvrQwsDrawable * pvrQwsCreateWindow(int screen, long winId, const PvrQwsRect *rect)
#define calloc(a, b)
int pvrQwsReleaseWindow(PvrQwsDrawable *drawable)
const char * name
void pvrQwsInvalidateBuffers(PvrQwsDrawable *drawable)
PVR2DMEMINFO * flipBuffers[PVRQWS_MAX_FLIP_BUFFERS]
static void pvrQwsDestroyDrawableForced(PvrQwsDrawable *drawable)
unsigned long screenStart
static void pvrQwsDestroyContext(void)
qreal angle(const QPointF &p1, const QPointF &p2)
void pvrQwsSetRotation(PvrQwsDrawable *drawable, int angle)
unsigned long numFlipBuffers
PvrQwsDrawableType pvrQwsGetDrawableType(PvrQwsDrawable *drawable)
PvrQwsSwapFunction swapFunction
void pvrQwsSetSwapFunction(PvrQwsDrawable *drawable, PvrQwsSwapFunction func, void *userData)
PVR2DFORMAT pixelFormat
quint16 index
int pvrQwsSwapBuffers(PvrQwsDrawable *drawable, int repaintOnly)
#define PVRQWS_MAX_VISIBLE_RECTS
void pvrQwsSetVisibleRegion(PvrQwsDrawable *drawable, const PvrQwsRect *rects, int numRects)
PvrQwsDrawable * pvrQwsScreenWindow(int screen)
#define PVRQWS_MAX_FLIP_BUFFERS
PvrQwsScreenInfo screens[PVRQWS_MAX_SCREENS]
static int pvrQwsAddDrawable(void)
void pvrQwsDestroyDrawable(PvrQwsDrawable *drawable)
PvrQwsDrawable * screenDrawable
PvrQwsPixelFormat pvrQwsGetPixelFormat(PvrQwsDrawable *drawable)
static int pvrQwsEnsureScreen(int screen)
PvrQwsDrawable * firstWinId
#define O_RDWR
int pvrQwsDisplayIsOpen(void)
int open(const char *, int,...)
void pvrQwsDisplayClose(void)
void * pvrQwsGetRenderBuffer(PvrQwsDrawable *drawable)