1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 - 2012 Research In Motion <blackberry-qt@qnx.com>
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module 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 The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/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 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 // #define QBBWINDOW_DEBUG
43
44 #include "qbbwindow.h"
45 #include "qbbglcontext.h"
46 #include "qbbscreen.h"
47
48 #include <QtGui/QWidget>
49 #include <QDebug>
50 #include <QtGui/QPlatformWindowFormat>
51 #include <QtGui/QWindowSystemInterface>
52
53 #include <errno.h>
54
55 QT_BEGIN_NAMESPACE
56
QBBWindow(QWidget * window,screen_context_t context,QBBScreen * screen)57 QBBWindow::QBBWindow(QWidget *window, screen_context_t context, QBBScreen *screen)
58 : QPlatformWindow(window),
59 mContext(context),
60 mCurrentBufferIndex(-1),
61 mPreviousBufferIndex(-1),
62 mPlatformGlContext(NULL),
63 mScreen(NULL),
64 mParent(NULL),
65 mVisible(true)
66 {
67 #if defined(QBBWINDOW_DEBUG)
68 qDebug() << "QBBWindow::QBBWindow - w=" << window << ", s=" << window->size();
69 #endif
70 int result;
71
72 // create child QNX window
73 errno = 0;
74 result = screen_create_window_type(&mWindow, mContext, SCREEN_CHILD_WINDOW);
75 if (result != 0) {
76 qFatal("QBBWindow: failed to create window, errno=%d", errno);
77 }
78
79 // set window buffer usage based on rendering API
80 int val;
81 QPlatformWindowFormat format = widget()->platformWindowFormat();
82 switch (format.windowApi()) {
83 case QPlatformWindowFormat::Raster:
84 val = SCREEN_USAGE_NATIVE | SCREEN_USAGE_READ | SCREEN_USAGE_WRITE;
85 break;
86 case QPlatformWindowFormat::OpenGL:
87 val = SCREEN_USAGE_OPENGL_ES2;
88 break;
89 default:
90 qFatal("QBBWindow: unsupported window API");
91 break;
92 }
93
94 errno = 0;
95 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_USAGE, &val);
96 if (result != 0) {
97 qFatal("QBBWindow: failed to set window buffer usage, errno=%d", errno);
98 }
99
100 // alpha channel is always pre-multiplied if present
101 errno = 0;
102 val = SCREEN_PRE_MULTIPLIED_ALPHA;
103 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_ALPHA_MODE, &val);
104 if (result != 0) {
105 qFatal("QBBWindow: failed to set window alpha mode, errno=%d", errno);
106 }
107
108 // make the window opaque
109 errno = 0;
110 val = SCREEN_TRANSPARENCY_NONE;
111 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_TRANSPARENCY, &val);
112 if (result != 0) {
113 qFatal("QBBWindow: failed to set window transparency, errno=%d", errno);
114 }
115
116 // set the window swap interval
117 errno = 0;
118 val = 1;
119 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
120 if (result != 0) {
121 qFatal("QBBWindow: failed to set window swap interval, errno=%d", errno);
122 }
123
124 // Set the screen to the primary display (this is the default specified by screen).
125 setScreen(screen);
126
127 // Qt somtimes doesn't call these setters after creating the window, so we need to do that
128 // ourselves here
129 if (window->parentWidget() && window->parentWidget()->platformWindow())
130 setParent(window->parentWidget()->platformWindow());
131 setGeometry(window->geometry());
132 setVisible(window->isVisible());
133 }
134
~QBBWindow()135 QBBWindow::~QBBWindow()
136 {
137 #if defined(QBBWINDOW_DEBUG)
138 qDebug() << "QBBWindow::~QBBWindow - w=" << widget();
139 #endif
140
141 // Qt should have already deleted the children before deleting the parent.
142 Q_ASSERT(mChildren.size() == 0);
143
144 // Remove from parent's Hierarchy.
145 removeFromParent();
146 mScreen->updateHierarchy();
147
148 // cleanup OpenGL/OpenVG context if it exists
149 if (mPlatformGlContext != NULL) {
150 delete mPlatformGlContext;
151 }
152
153 // cleanup QNX window and its buffers
154 screen_destroy_window(mWindow);
155 }
156
setGeometry(const QRect & rect)157 void QBBWindow::setGeometry(const QRect &rect)
158 {
159 int val[2];
160
161 #if defined(QBBWINDOW_DEBUG)
162 qDebug() << "QBBWindow::setGeometry - w=" << widget() << ", (" << rect.x() << "," << rect.y() << "," << rect.width() << "," << rect.height() << ")";
163 #endif
164
165 QRect oldGeometry = geometry();
166
167 // call parent method
168 QPlatformWindow::setGeometry(rect);
169
170 // set window geometry equal to widget geometry
171 errno = 0;
172 val[0] = rect.x();
173 val[1] = rect.y();
174 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_POSITION, val);
175 if (result != 0) {
176 qFatal("QBBWindow: failed to set window position, errno=%d", errno);
177 }
178
179 errno = 0;
180 val[0] = rect.width();
181 val[1] = rect.height();
182 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_SIZE, val);
183 if (result != 0) {
184 qFatal("QBBWindow: failed to set window size, errno=%d", errno);
185 }
186
187 // set viewport size equal to window size
188 errno = 0;
189 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_SOURCE_SIZE, val);
190 if (result != 0) {
191 qFatal("QBBWindow: failed to set window source size, errno=%d", errno);
192 }
193
194 // Now move all children.
195 QPoint offset;
196 if (!oldGeometry.isEmpty()) {
197 offset = rect.topLeft();
198 offset -= oldGeometry.topLeft();
199
200 QList<QBBWindow*>::iterator it;
201 for (it = mChildren.begin(); it != mChildren.end(); it++) {
202 (*it)->offset(offset);
203 }
204 }
205 }
206
offset(const QPoint & offset)207 void QBBWindow::offset(const QPoint &offset)
208 {
209 // Move self and then children.
210 QRect newGeometry = geometry();
211 newGeometry.translate(offset);
212
213 // call the base class
214 QPlatformWindow::setGeometry(newGeometry);
215
216 int val[2];
217
218 errno = 0;
219 val[0] = newGeometry.x();
220 val[1] = newGeometry.y();
221 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_POSITION, val);
222 if (result != 0) {
223 qFatal("QBBWindow: failed to set window position, errno=%d", errno);
224 }
225
226 QList<QBBWindow*>::iterator it;
227 for (it = mChildren.begin(); it != mChildren.end(); it++) {
228 (*it)->offset(offset);
229 }
230 }
231
setVisible(bool visible)232 void QBBWindow::setVisible(bool visible)
233 {
234 #if defined(QBBWINDOW_DEBUG)
235 qDebug() << "QBBWindow::setVisible - w=" << widget() << ", v=" << visible;
236 #endif
237
238 mVisible = visible;
239
240 QBBWindow* root = this;
241 while (root->mParent)
242 root = root->mParent;
243
244 root->updateVisibility(root->mVisible);
245
246 widget()->activateWindow();
247
248 // Flush the context when invisible, otherwise it won't disappear immediately,
249 // but still allow navigator to capture screenshot (thumbnail) when minimized
250 if (!visible && !(widget()->windowState() & Qt::WindowMinimized))
251 screen_flush_context(mContext, 0);
252 }
253
updateVisibility(bool parentVisible)254 void QBBWindow::updateVisibility(bool parentVisible)
255 {
256 // set window visibility
257 errno = 0;
258 int val = (mVisible && parentVisible) ? 1 : 0;
259 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_VISIBLE, &val);
260 if (result != 0) {
261 qFatal("QBBWindow: failed to set window visibility, errno=%d", errno);
262 }
263
264 QList<QBBWindow*>::iterator it;
265 for (it = mChildren.begin(); it != mChildren.end(); it++) {
266 (*it)->updateVisibility(mVisible && parentVisible);
267 }
268 }
269
setOpacity(qreal level)270 void QBBWindow::setOpacity(qreal level)
271 {
272 #if defined(QBBWINDOW_DEBUG)
273 qDebug() << "QBBWindow::setOpacity - w=" << widget() << ", o=" << level;
274 #endif
275
276 // set window global alpha
277 errno = 0;
278 int val = (int)(level * 255);
279 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_GLOBAL_ALPHA, &val);
280 if (result != 0) {
281 qFatal("QBBWindow: failed to set window global alpha, errno=%d", errno);
282 }
283
284 // TODO: How to handle children of this window? If we change all the visibilities, then
285 // the transparency will look wrong...
286 }
287
setBufferSize(const QSize & size)288 void QBBWindow::setBufferSize(const QSize &size)
289 {
290 #if defined(QBBWINDOW_DEBUG)
291 qDebug() << "QBBWindow::setBufferSize - w=" << widget() << ", s=" << size;
292 #endif
293
294 // set window buffer size
295 errno = 0;
296 int val[2] = { size.width(), size.height() };
297 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_BUFFER_SIZE, val);
298 if (result != 0) {
299 qFatal("QBBWindow: failed to set window buffer size, errno=%d", errno);
300 }
301
302 // create window buffers if they do not exist
303 if (!hasBuffers()) {
304 #if defined(QBBWINDOW_DEBUG)
305 qDebug() << "QBBWindow::setBufferSize - create buffers";
306 #endif
307
308 // get pixel format from EGL config if using OpenGL;
309 // otherwise inherit pixel format of window's screen
310 if (mPlatformGlContext != NULL) {
311 val[0] = platformWindowFormatToNativeFormat(mPlatformGlContext->platformWindowFormat());
312 } else {
313 val[0] = mScreen->nativeFormat();
314 }
315
316 errno = 0;
317 result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_FORMAT, val);
318 if (result != 0) {
319 qFatal("QBBWindow: failed to set window pixel format, errno=%d", errno);
320 }
321
322 errno = 0;
323 result = screen_create_window_buffers(mWindow, MAX_BUFFER_COUNT);
324 if (result != 0) {
325 qFatal("QBBWindow: failed to create window buffers, errno=%d", errno);
326 }
327
328 // check if there are any buffers available
329 int bufferCount = 0;
330 result = screen_get_window_property_iv(mWindow, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount);
331
332 if (result != 0) {
333 qFatal("QBBWindow: failed to query window buffer count, errno=%d", errno);
334 }
335
336 if (bufferCount != MAX_BUFFER_COUNT) {
337 qFatal("QBBWindow: invalid buffer count. Expected = %d, got = %d", MAX_BUFFER_COUNT, bufferCount);
338 }
339 }
340
341 // cache new buffer size
342 mBufferSize = size;
343
344 // buffers were destroyed; reacquire them
345 mCurrentBufferIndex = -1;
346 mPreviousDirty = QRegion();
347 mScrolled = QRegion();
348 }
349
renderBuffer()350 QBBBuffer &QBBWindow::renderBuffer()
351 {
352 #if defined(QBBWINDOW_DEBUG)
353 qDebug() << "QBBWindow::renderBuffer - w=" << widget();
354 #endif
355
356 return buffer(BACK_BUFFER);
357 }
358
frontBuffer()359 QBBBuffer &QBBWindow::frontBuffer()
360 {
361 #if defined(QBBWINDOW_DEBUG)
362 qDebug() << "QBBWindow::frontBuffer - w=" << widget();
363 #endif
364
365 return buffer(FRONT_BUFFER);
366 }
367
buffer(QBBWindow::Buffer bufferIndex)368 QBBBuffer &QBBWindow::buffer(QBBWindow::Buffer bufferIndex)
369 {
370 #if defined(QBBWINDOW_DEBUG)
371 qDebug() << "QBBWindow::buffer - w=" << widget();
372 #endif
373
374 // check if render buffer is invalid
375 if (mCurrentBufferIndex == -1) {
376 // get all buffers available for rendering
377 errno = 0;
378 screen_buffer_t buffers[MAX_BUFFER_COUNT];
379 const int result = screen_get_window_property_pv(mWindow, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers);
380 if (result != 0) {
381 qFatal("QBBWindow: failed to query window buffers, errno=%d", errno);
382 }
383
384 // wrap each buffer
385 for (int i = 0; i < MAX_BUFFER_COUNT; i++) {
386 mBuffers[i] = QBBBuffer(buffers[i]);
387 }
388
389 // use the first available render buffer
390 mCurrentBufferIndex = 0;
391 mPreviousBufferIndex = -1;
392 }
393
394 if (bufferIndex == BACK_BUFFER) {
395 return mBuffers[mCurrentBufferIndex];
396 } else if (bufferIndex == FRONT_BUFFER) {
397 int buf = mCurrentBufferIndex - 1;
398
399 if (buf < 0)
400 buf = MAX_BUFFER_COUNT - 1;
401
402 return mBuffers[buf];
403 }
404
405 qFatal("QBBWindow::buffer() - invalid buffer index. Aborting");
406
407 // never happens
408 return mBuffers[mCurrentBufferIndex];
409 }
410
scroll(const QRegion & region,int dx,int dy,bool flush)411 void QBBWindow::scroll(const QRegion ®ion, int dx, int dy, bool flush)
412 {
413 copyBack(region, dx, dy, flush);
414 mScrolled += region;
415 }
416
post(const QRegion & dirty)417 void QBBWindow::post(const QRegion &dirty)
418 {
419 // check if render buffer exists and something was rendered
420 if (mCurrentBufferIndex != -1 && !dirty.isEmpty()) {
421
422 #if defined(QBBWINDOW_DEBUG)
423 qDebug() << "QBBWindow::post - w=" << widget();
424 #endif
425 QBBBuffer ¤tBuffer = mBuffers[mCurrentBufferIndex];
426
427 // copy unmodified region from old render buffer to new render buffer;
428 // required to allow partial updates
429 QRegion preserve = mPreviousDirty - dirty - mScrolled;
430 copyBack(preserve, 0, 0);
431
432 // calculate region that changed
433 QRegion modified = preserve + dirty + mScrolled;
434 QRect rect = modified.boundingRect();
435 int dirtyRect[4] = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() };
436
437 // update the display with contents of render buffer
438 errno = 0;
439 int result = screen_post_window(mWindow, currentBuffer.nativeBuffer(), 1, dirtyRect, 0);
440 if (result != 0) {
441 qFatal("QBBWindow: failed to post window buffer, errno=%d", errno);
442 }
443
444 // advance to next nender buffer
445 mPreviousBufferIndex = mCurrentBufferIndex++;
446 if (mCurrentBufferIndex >= MAX_BUFFER_COUNT) {
447 mCurrentBufferIndex = 0;
448 }
449
450 // save modified region and clear scrolled region
451 mPreviousDirty = dirty;
452 mScrolled = QRegion();
453
454 // notify screen that window posted
455 if (mScreen != NULL) {
456 mScreen->onWindowPost(this);
457 }
458 }
459 }
460
glContext() const461 QPlatformGLContext *QBBWindow::glContext() const
462 {
463 #if defined(QBBWINDOW_DEBUG)
464 qDebug() << "QBBWindow::glContext - w=" << widget();
465 #endif
466 // create opengl context on first access if rendering API is correct
467 QPlatformWindowFormat format = widget()->platformWindowFormat();
468 if (mPlatformGlContext == NULL && format.windowApi() == QPlatformWindowFormat::OpenGL) {
469 mPlatformGlContext = new QBBGLContext( const_cast<QBBWindow*>(this) );
470 }
471 return mPlatformGlContext;
472 }
473
setScreen(QBBScreen * platformScreen)474 void QBBWindow::setScreen(QBBScreen *platformScreen)
475 {
476 #if defined(QBBWINDOW_DEBUG)
477 qDebug() << "QBBWindow::setScreen - w=" << widget();
478 #endif
479
480 if (mScreen == platformScreen)
481 return;
482
483 if (mScreen)
484 mScreen->removeWindow(this);
485 platformScreen->addWindow(this);
486 mScreen = platformScreen;
487
488 // The display may not have a root (desktop) window yet so we must ensure that one has been
489 // created before we can join its group or get its native display property.
490 mScreen->ensureDisplayCreated();
491
492 // move window to proper display
493 errno = 0;
494 screen_display_t display = platformScreen->nativeDisplay();
495 int result = screen_set_window_property_pv(mWindow, SCREEN_PROPERTY_DISPLAY, (void **)&display);
496 if (result != 0) {
497 qFatal("QBBWindow: failed to set window display, errno=%d", errno);
498 }
499
500 // add window to display's window group
501 errno = 0;
502 result = screen_join_window_group(mWindow, platformScreen->windowGroupName());
503 if (result != 0) {
504 qFatal("QBBWindow: failed to join window group, errno=%d", errno);
505 }
506
507 QList<QBBWindow*>::iterator it;
508 for (it = mChildren.begin(); it != mChildren.end(); it++) {
509 // Only subwindows and tooltips need necessarily be moved to another display with
510 // the window.
511 if ((widget()->windowType() & Qt::WindowType_Mask) == Qt::SubWindow ||
512 (widget()->windowType() & Qt::WindowType_Mask) == Qt::ToolTip)
513 (*it)->setScreen(platformScreen);
514 }
515
516 mScreen->updateHierarchy();
517 }
518
removeFromParent()519 void QBBWindow::removeFromParent()
520 {
521 // Remove from old Hierarchy position
522 if (mParent) {
523 if (mParent->mChildren.removeAll(this))
524 mParent = 0;
525 else
526 qFatal("QBBWindow: Window Hierarchy broken; window has parent, but parent hasn't got child.");
527 } else {
528 mScreen->removeWindow(this);
529 }
530 }
531
setParent(const QPlatformWindow * window)532 void QBBWindow::setParent(const QPlatformWindow *window)
533 {
534 #if defined(QBBWINDOW_DEBUG)
535 qDebug() << "QBBWindow::setParent - w=" << widget() << " p=" << window;
536 #endif
537
538 // Cast away the const, we need to modify the Hierarchy.
539 QBBWindow* newParent = 0;
540
541 if (window)
542 newParent = static_cast<QBBWindow*>((QPlatformWindow *)window);
543
544 if (newParent == mParent)
545 return;
546
547 removeFromParent();
548 mParent = newParent;
549
550 // Add to new Hierarchy position.
551 if (mParent) {
552 if (mParent->mScreen != mScreen)
553 setScreen(mParent->mScreen);
554
555 mParent->mChildren.push_back(this);
556 } else {
557 mScreen->addWindow(this);
558 }
559
560 mScreen->updateHierarchy();
561 }
562
raise()563 void QBBWindow::raise()
564 {
565 #if defined(QBBWINDOW_DEBUG)
566 qDebug() << "QBBWindow::raise - w=" << widget();
567 #endif
568
569 if (mParent) {
570 mParent->mChildren.removeAll(this);
571 mParent->mChildren.push_back(this);
572 } else {
573 mScreen->raiseWindow(this);
574 }
575
576 mScreen->updateHierarchy();
577 }
578
lower()579 void QBBWindow::lower()
580 {
581 #if defined(QBBWINDOW_DEBUG)
582 qDebug() << "QBBWindow::lower - w=" << widget();
583 #endif
584
585 if (mParent) {
586 mParent->mChildren.removeAll(this);
587 mParent->mChildren.push_front(this);
588 } else {
589 mScreen->lowerWindow(this);
590 }
591
592 mScreen->updateHierarchy();
593 }
594
requestActivateWindow()595 void QBBWindow::requestActivateWindow()
596 {
597 #if defined(QBBWINDOW_DEBUG)
598 qDebug() << "QBBWindow::requestActivateWindow - w=" << widget();
599 #endif
600
601 // TODO: Tell screen to set keyboard focus to this window.
602
603 // Notify that we gained focus.
604 gainedFocus();
605 }
606
gainedFocus()607 void QBBWindow::gainedFocus()
608 {
609 #if defined(QBBWINDOW_DEBUG)
610 qDebug() << "QBBWindow::gainedFocus - w=" << widget();
611 #endif
612
613 // Got focus
614 QWindowSystemInterface::handleWindowActivated(widget());
615 }
616
findWindow(screen_window_t windowHandle)617 QBBWindow *QBBWindow::findWindow(screen_window_t windowHandle)
618 {
619 if (mWindow == windowHandle)
620 return this;
621
622 Q_FOREACH (QBBWindow *window, mChildren) {
623 QBBWindow * const result = window->findWindow(windowHandle);
624 if (result)
625 return result;
626 }
627
628 return 0;
629 }
630
updateZorder(int & topZorder)631 void QBBWindow::updateZorder(int &topZorder)
632 {
633 errno = 0;
634 int result = screen_set_window_property_iv(mWindow, SCREEN_PROPERTY_ZORDER, &topZorder);
635 topZorder++;
636
637 if (result != 0)
638 qFatal("QBBWindow: failed to set window z-order=%d, errno=%d, mWindow=0x%08x", topZorder, errno, mWindow);
639
640 QList<QBBWindow*>::const_iterator it;
641
642 for (it = mChildren.begin(); it != mChildren.end(); it++)
643 (*it)->updateZorder(topZorder);
644 }
645
copyBack(const QRegion & region,int dx,int dy,bool flush)646 void QBBWindow::copyBack(const QRegion ®ion, int dx, int dy, bool flush)
647 {
648 int result;
649
650 // abort if previous buffer is invalid
651 if (mPreviousBufferIndex == -1) {
652 return;
653 }
654
655 // abort if nothing to copy
656 if (region.isEmpty()) {
657 return;
658 }
659
660 QBBBuffer ¤tBuffer = mBuffers[mCurrentBufferIndex];
661 QBBBuffer &previousBuffer = mBuffers[mPreviousBufferIndex];
662
663 // break down region into non-overlapping rectangles
664 QVector<QRect> rects = region.rects();
665 for (int i = rects.size() - 1; i >= 0; i--) {
666
667 // clip rectangle to bounds of target
668 QRect rect = rects[i].intersected( currentBuffer.rect() );
669
670 if (rect.isEmpty())
671 continue;
672
673 // setup blit operation
674 int attribs[] = { SCREEN_BLIT_SOURCE_X, rect.x(),
675 SCREEN_BLIT_SOURCE_Y, rect.y(),
676 SCREEN_BLIT_SOURCE_WIDTH, rect.width(),
677 SCREEN_BLIT_SOURCE_HEIGHT, rect.height(),
678 SCREEN_BLIT_DESTINATION_X, rect.x() + dx,
679 SCREEN_BLIT_DESTINATION_Y, rect.y() + dy,
680 SCREEN_BLIT_DESTINATION_WIDTH, rect.width(),
681 SCREEN_BLIT_DESTINATION_HEIGHT, rect.height(),
682 SCREEN_BLIT_END };
683
684 // queue blit operation
685 errno = 0;
686 result = screen_blit(mContext, currentBuffer.nativeBuffer(), previousBuffer.nativeBuffer(), attribs);
687 if (result != 0) {
688 qFatal("QBBWindow: failed to blit buffers, errno=%d", errno);
689 }
690 }
691
692 // check if flush requested
693 if (flush) {
694
695 // wait for all blits to complete
696 errno = 0;
697 result = screen_flush_blits(mContext, SCREEN_WAIT_IDLE);
698 if (result != 0) {
699 qFatal("QBBWindow: failed to flush blits, errno=%d", errno);
700 }
701
702 // buffer was modified outside the CPU
703 currentBuffer.invalidateInCache();
704 }
705 }
706
platformWindowFormatToNativeFormat(const QPlatformWindowFormat & format)707 int QBBWindow::platformWindowFormatToNativeFormat(const QPlatformWindowFormat &format)
708 {
709 // extract size of colour channels from window format
710 int redSize = format.redBufferSize();
711 if (redSize == -1) {
712 qFatal("QBBWindow: red size not defined");
713 }
714
715 int greenSize = format.greenBufferSize();
716 if (greenSize == -1) {
717 qFatal("QBBWindow: green size not defined");
718 }
719
720 int blueSize = format.blueBufferSize();
721 if (blueSize == -1) {
722 qFatal("QBBWindow: blue size not defined");
723 }
724
725 // select matching native format
726 if (redSize == 5 && greenSize == 6 && blueSize == 5) {
727 return SCREEN_FORMAT_RGB565;
728 } else if (redSize == 8 && greenSize == 8 && blueSize == 8) {
729 return SCREEN_FORMAT_RGBA8888;
730 } else {
731 qFatal("QBBWindow: unsupported pixel format");
732 return 0;
733 }
734 }
735
736 QT_END_NAMESPACE
737