1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the plugins of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qscreenahi_qws.h"
46 #include <QtGui/qcolor.h>
47 #include <QtGui/qapplication.h>
48 #include <QtCore/qvector.h>
49 #include <QtCore/qvarlengtharray.h>
50 #include <private/qwssignalhandler_p.h>
54 //#define QAHISCREEN_DEBUG
56 static int depthForPixelFormat(const AhiPixelFormat_t format)
65 case AhiPix8bpp_332RGB:
68 case AhiPix16bpp_444RGB:
70 case AhiPix16bpp_555RGB:
72 case AhiPix16bpp_565RGB:
74 case AhiPix32bpp_8888ARGB:
75 case AhiPix32bpp_8888BGRA:
82 static AhiPixelFormat_t pixelFormatForImageFormat(const QImage::Format format)
85 case QImage::Format_Mono:
86 case QImage::Format_MonoLSB:
88 case QImage::Format_Indexed8:
90 case QImage::Format_RGB32:
91 case QImage::Format_ARGB32:
92 case QImage::Format_ARGB32_Premultiplied:
93 return AhiPix32bpp_8888ARGB;
94 case QImage::Format_RGB16:
95 return AhiPix16bpp_565RGB;
96 case QImage::Format_RGB555:
97 return AhiPix16bpp_555RGB;
98 case QImage::Format_ARGB4444_Premultiplied:
99 case QImage::Format_RGB444:
100 return AhiPix16bpp_444RGB;
102 return AhiPixelFormatMax;
106 class QAhiScreenCursor : public QScreenCursor
109 QAhiScreenCursor(QScreen *screen, AhiDevCtx_t context);
111 void set(const QImage &image, int hotx, int hoty);
112 void move(int x, int y);
121 QAhiScreenCursor::QAhiScreenCursor(QScreen *s, AhiDevCtx_t c)
122 : QScreenCursor(), screen(s), context(c)
125 supportsAlpha = true;
133 void QAhiScreenCursor::set(const QImage &image, int hotx, int hoty)
135 if (image.isNull()) {
136 QScreenCursor::set(image, hotx, hoty);
140 if (image.format() != QImage::Format_MonoLSB) {
141 set(image.convertToFormat(QImage::Format_MonoLSB), hotx, hoty);
145 AhiPixelFormat_t pixFmt = pixelFormatForImageFormat(image.format());
147 if (pixFmt >= AhiPixelFormatMax) { // generic fallback
148 QImage::Format toFormat = screen->pixelFormat();
149 if (toFormat == QImage::Format_Invalid)
150 toFormat = QImage::Format_ARGB32;
151 set(image.convertToFormat(toFormat), hotx, hoty);
155 AhiPoint_t hotSpot = { hotx, hoty };
156 AhiSize_t bitmapSize = { image.width(), image.height() };
157 AhiBitmap_t bitmap = { bitmapSize, (void*)(image.bits()),
158 image.bytesPerLine(), pixFmt };
161 status = AhiDispCursorSet(context, AhiCursor1, &bitmap, &hotSpot,
162 image.serialNumber(), 0);
163 if (status != AhiStsOk)
164 qWarning("QAhiScreenCursor::set(): AhiDispCursorSet failed: %x",
167 QScreenCursor::set(image, hotx, hoty);
170 void QAhiScreenCursor::move(int x, int y)
172 AhiPoint_t pos = { x, y };
173 AhiSts_t status = AhiDispCursorPos(context, AhiCursor1, &pos, 0);
174 if (status != AhiStsOk)
175 qWarning("QAhiScreenCursor::move(): error setting mouse position: %x",
177 QScreenCursor::move(x, y);
180 void QAhiScreenCursor::show()
183 status = AhiDispCursorState(context, AhiCursor1, AhiCursorStateOn, 0);
184 if (status != AhiStsOk)
185 qWarning("QAhiScreenCursor::show(): error setting state: %x", status);
186 QScreenCursor::show();
189 void QAhiScreenCursor::hide()
191 AhiDispCursorState(context, AhiCursor1, AhiCursorStateOff, 0);
192 QScreenCursor::hide();
195 class QAhiScreenPrivate : public QObject
199 ~QAhiScreenPrivate();
201 bool setMode(AhiDispMode_t mode);
205 QAhiScreenCursor *cursor;
210 QAhiScreenPrivate::QAhiScreenPrivate()
211 : context(0), surface(0), cursor(0)
213 #ifndef QT_NO_QWS_SIGNALHANDLER
214 QWSSignalHandler::instance()->addObject(this);
218 QAhiScreenPrivate::~QAhiScreenPrivate()
223 AhiSurfFree(context, surface);
227 AhiDevClose(context);
233 bool QAhiScreenPrivate::setMode(AhiDispMode_t mode)
237 status = AhiDispModeSet(context, &mode, 0);
238 if (status != AhiStsOk) {
239 qCritical("QAhiScreenPrivate::setMode(): AhiDispModeSet failed: %x",
245 AhiSurfFree(context, surface);
248 status = AhiSurfAlloc(context, &surface, &mode.size, mode.pixFmt,
250 if (status != AhiStsOk) {
251 qCritical("QAhiScreenPrivate::setMode(): AhisurfAlloc failed: %x",
256 status = AhiDispSurfSet(context, surface, 0);
257 if (status != AhiStsOk) {
258 qCritical("QAhiScreenPrivate::setMode(): AhiDispSurfSet failed: %x",
266 QAhiScreen::QAhiScreen(int displayId)
267 : QScreen(displayId), d_ptr(new QAhiScreenPrivate)
271 QAhiScreen::~QAhiScreen()
276 bool QAhiScreen::configure()
278 AhiSurfInfo_t surfaceInfo;
281 status = AhiSurfInfo(d_ptr->context, d_ptr->surface, &surfaceInfo);
282 if (status != AhiStsOk) {
283 qCritical("QAhiScreen::configure(): AhiSurfInfo failed: %x", status);
288 QScreen::w = QScreen::dw = surfaceInfo.size.cx;
289 QScreen::h = QScreen::dh = surfaceInfo.size.cy;
290 QScreen::lstep = surfaceInfo.stride;
291 QScreen::size = surfaceInfo.sizeInBytes;
293 switch (surfaceInfo.pixFmt) {
295 setPixelFormat(QImage::Format_Mono);
301 case AhiPix8bpp_332RGB:
305 case AhiPix16bpp_444RGB:
306 setPixelFormat(QImage::Format_RGB444);
309 case AhiPix16bpp_555RGB:
310 setPixelFormat(QImage::Format_RGB555);
313 case AhiPix16bpp_565RGB:
314 setPixelFormat(QImage::Format_RGB16);
320 case AhiPix32bpp_8888ARGB:
321 setPixelFormat(QImage::Format_ARGB32);
323 case AhiPix32bpp_8888BGRA:
327 qCritical("QAhiScreen::configure(): Unknown pixel format: %x",
333 QScreen::physWidth = qRound(QScreen::dw * 25.4 / dpi);
334 QScreen::physHeight = qRound(QScreen::dh * 25.4 / dpi);
339 bool QAhiScreen::connect(const QString &displaySpec)
341 Q_UNUSED(displaySpec);
346 if (status != AhiStsOk) {
347 qCritical("QAhiScreen::connect(): AhiInit failed: %x", status);
354 status = AhiDevEnum(&device, &info, 0);
355 if (status != AhiStsOk) {
356 qCritical("QAhiScreen::connect(): AhiDevEnum failed: %x", status);
359 #ifdef QAHISCREEN_DEBUG
362 AhiDevInfo_t dispInfo = info;
363 qDebug("AHI supported devices:");
365 qDebug(" %2i: %s, sw version: %s (rev %u)\n"
366 " chip: 0x%x (rev %u), mem: %i (%i/%i), bus: 0x%x",
367 displayNo, dispInfo.name,
368 dispInfo.swVersion, uint(dispInfo.swRevision),
369 uint(dispInfo.chipId), uint(dispInfo.revisionId),
370 uint(dispInfo.totalMemory),
371 uint(dispInfo.internalMemSize),
372 uint(dispInfo.externalMemSize),
373 uint(dispInfo.cpuBusInterfaceMode));
374 status = AhiDevEnum(&device, &info, ++displayNo);
375 } while (status == AhiStsOk);
379 status = AhiDevOpen(&d_ptr->context, device, "qscreenahi",
381 if (status != AhiStsOk) {
382 qCritical("QAhiScreen::connect(): AhiDevOpen failed: %x", status);
388 status = AhiDispModeEnum(d_ptr->context, &mode, 0);
389 if (status != AhiStsOk) {
390 qCritical("QAhiScreen::connect(): AhiDispModeEnum failed: %x", status);
394 #ifdef QAHISCREEN_DEBUG
397 AhiDispMode_t modeInfo = mode;
398 qDebug("AHI supported modes:");
400 qDebug(" %2i: %ux%u, fmt: %i, %u Hz, rot: %i, mirror: %i",
401 modeNo, uint(modeInfo.size.cx), uint(modeInfo.size.cy),
402 modeInfo.pixFmt, uint(modeInfo.frequency),
403 modeInfo.rotation, modeInfo.mirror);
404 status = AhiDispModeEnum(d_ptr->context, &modeInfo, ++modeNo);
405 } while (status == AhiStsOk);
409 if (QApplication::type() == QApplication::GuiServer) {
410 if (!d_ptr->setMode(mode))
413 status = AhiDispSurfGet(d_ptr->context, &d_ptr->surface);
414 if (status != AhiStsOk) {
415 qCritical("QAhiScreen::connect(): AhiDispSurfGet failed: %x",
420 status = AhiDispModeGet(d_ptr->context, &mode);
421 if (status != AhiStsOk) {
422 qCritical("QAhiScreen::context(): AhiDispModeGet failed: %x",
431 void QAhiScreen::disconnect()
433 AhiSurfFree(d_ptr->context, d_ptr->surface);
435 AhiDevClose(d_ptr->context);
440 bool QAhiScreen::initDevice()
442 QScreenCursor::initSoftwareCursor();
444 AhiSts_t status = AhiDispState(d_ptr->context, AhiDispStateOn, 0);
445 if (status != AhiStsOk) {
446 qCritical("QAhiScreen::connect(): AhiDispState failed: %x", status);
453 void QAhiScreen::shutdownDevice()
455 AhiDispState(d_ptr->context, AhiDispStateOff, 0);
458 void QAhiScreen::setMode(int width, int height, int depth)
462 AhiSts_t status = AhiStsOk;
464 while (status == AhiStsOk) {
465 status = AhiDispModeEnum(d_ptr->context, &mode, modeNo);
466 if (mode.size.cx == uint(width) &&
467 mode.size.cy == uint(height) &&
468 depthForPixelFormat(mode.pixFmt) == depth)
470 d_ptr->setMode(mode);
477 void QAhiScreen::blit(const QImage &image, const QPoint &topLeft,
480 AhiPixelFormat_t pixFmt = pixelFormatForImageFormat(image.format());
482 if (pixFmt >= AhiPixelFormatMax) { // generic fallback
483 QImage::Format toFormat = pixelFormat();
484 if (toFormat == QImage::Format_Invalid)
485 toFormat = QImage::Format_ARGB32;
486 blit(image.convertToFormat(toFormat), topLeft, reg);
492 status = AhiDrawSurfDstSet(d_ptr->context, d_ptr->surface, 0);
493 if (status != AhiStsOk) {
494 qWarning("QAhiScreen::blit(): AhiDrawSurfDstSet failed: %x", status);
498 const QVector<QRect> rects = (reg & region()).rects();
499 const int numRects = rects.size();
500 QVarLengthArray<AhiPoint_t, 8> src(numRects);
501 QVarLengthArray<AhiRect_t, 8> dest(numRects);
503 for (int i = 0; i < numRects; ++i) {
504 const QRect rect = rects.at(i);
506 src[i].x = rect.x() - topLeft.x();
507 src[i].y = rect.y() - topLeft.y();
508 dest[i].left = rect.left();
509 dest[i].top = rect.top();
510 dest[i].right = rect.x() + rect.width();
511 dest[i].bottom = rect.y() + rect.height();
514 AhiSize_t bitmapSize = { image.width(), image.height() };
515 AhiBitmap_t bitmap = { bitmapSize, (void*)(image.bits()),
516 image.bytesPerLine(), pixFmt };
518 status = AhiDrawRopSet(d_ptr->context, AHIMAKEROP3(AHIROPSRCCOPY));
519 if (status != AhiStsOk) {
520 qWarning("QAhiScreen::blit(): AhiDrawRopSet failed: %x", status);
524 for (int i = 0; i < numRects; ++i) {
525 status = AhiDrawBitmapBlt(d_ptr->context, &dest[i], &src[i],
527 if (status != AhiStsOk) {
528 qWarning("QAhiScreen::blit(): AhiDrawBitmapBlt failed: %x",
535 void QAhiScreen::solidFill(const QColor &color, const QRegion ®)
537 AhiSts_t status = AhiStsOk;
539 switch (pixelFormat()) {
540 case QImage::Format_ARGB32_Premultiplied:
541 case QImage::Format_ARGB32:
542 case QImage::Format_RGB32:
543 status = AhiDrawBrushFgColorSet(d_ptr->context, color.rgba());
545 case QImage::Format_RGB16:
546 status = AhiDrawBrushFgColorSet(d_ptr->context, qt_convRgbTo16(color.rgb()));
549 qFatal("QAhiScreen::solidFill(): Not implemented for pixel format %d",
554 if (status != AhiStsOk) {
555 qWarning("QAhiScreen::solidFill(): AhiDrawBrushFgColorSet failed: %x",
560 status = AhiDrawBrushSet(d_ptr->context, 0, 0, 0, AHIFLAG_BRUSHSOLID);
561 if (status != AhiStsOk) {
562 qWarning("QAhiScreen::solidFill(): AhiDrawBrushSet failed: %x",
567 status = AhiDrawRopSet(d_ptr->context, AHIMAKEROP3(AHIROPPATCOPY));
568 if (status != AhiStsOk) {
569 qWarning("QAhiScreen::solidFill(): AhiDrawRopSet failed: %x", status);
573 status = AhiDrawSurfDstSet(d_ptr->context, d_ptr->surface, 0);
574 if (status != AhiStsOk) {
575 qWarning("QAhiScreen::solidFill(): AhiDrawSurfDst failed: %x", status);
579 const QVector<QRect> rects = (reg & region()).rects();
580 QVarLengthArray<AhiRect_t> ahiRects(rects.size());
582 for (int i = 0; i < rects.size(); ++i) {
583 const QRect rect = rects.at(i);
584 ahiRects[i].left = rect.left();
585 ahiRects[i].top = rect.top();
586 ahiRects[i].right = rect.x() + rect.width();
587 ahiRects[i].bottom = rect.y() + rect.height();
590 status = AhiDrawBitBltMulti(d_ptr->context, ahiRects.data(),
592 if (status != AhiStsOk)
593 qWarning("QAhiScreen::solidFill(): AhiDrawBitBlt failed: %x", status);
598 #endif // QT_NO_QWS_AHI