Track API change in QPlatformNativeInterface
[profile/ivi/qtbase.git] / src / plugins / gfxdrivers / ahi / qscreenahi_qws.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the plugins of the Qt Toolkit.
8 **
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
14 ** this package.
15 **
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.
23 **
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.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qscreenahi_qws.h"
43
44 #ifndef QT_NO_QWS_AHI
45
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>
51
52 #include <ahi.h>
53
54 //#define QAHISCREEN_DEBUG
55
56 static int depthForPixelFormat(const AhiPixelFormat_t format)
57 {
58     switch (format) {
59     case AhiPix1bpp:
60         return 1;
61     case AhiPix2bpp:
62         return 2;
63     case AhiPix4bpp:
64         return 4;
65     case AhiPix8bpp_332RGB:
66     case AhiPix8bpp:
67         return 8;
68     case AhiPix16bpp_444RGB:
69         return 12;
70     case AhiPix16bpp_555RGB:
71         return 15;
72     case AhiPix16bpp_565RGB:
73         return 16;
74     case AhiPix32bpp_8888ARGB:
75     case AhiPix32bpp_8888BGRA:
76         return 32;
77     default:
78         return 0;
79     }
80 }
81
82 static AhiPixelFormat_t pixelFormatForImageFormat(const QImage::Format format)
83 {
84     switch (format) {
85     case QImage::Format_Mono:
86     case QImage::Format_MonoLSB:
87         return AhiPix1bpp;
88     case QImage::Format_Indexed8:
89         return AhiPix8bpp;
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;
101     default:
102         return AhiPixelFormatMax;
103     }
104 }
105
106 class QAhiScreenCursor : public QScreenCursor
107 {
108 public:
109     QAhiScreenCursor(QScreen *screen, AhiDevCtx_t context);
110
111     void set(const QImage &image, int hotx, int hoty);
112     void move(int x, int y);
113     void show();
114     void hide();
115
116 private:
117     QScreen *screen;
118     AhiDevCtx_t context;
119 };
120
121 QAhiScreenCursor::QAhiScreenCursor(QScreen *s, AhiDevCtx_t c)
122     : QScreenCursor(), screen(s), context(c)
123 {
124     hwaccel = true;
125     supportsAlpha = true;
126
127     if (enable)
128         show();
129     else
130         hide();
131 }
132
133 void QAhiScreenCursor::set(const QImage &image, int hotx, int hoty)
134 {
135     if (image.isNull()) {
136         QScreenCursor::set(image, hotx, hoty);
137         return;
138     }
139
140     if (image.format() != QImage::Format_MonoLSB) {
141         set(image.convertToFormat(QImage::Format_MonoLSB), hotx, hoty);
142         return;
143     }
144
145     AhiPixelFormat_t pixFmt = pixelFormatForImageFormat(image.format());
146
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);
152         return;
153     }
154
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 };
159
160     AhiSts_t status;
161     status = AhiDispCursorSet(context, AhiCursor1, &bitmap, &hotSpot,
162                               image.serialNumber(), 0);
163     if (status != AhiStsOk)
164         qWarning("QAhiScreenCursor::set(): AhiDispCursorSet failed: %x",
165                  status);
166
167     QScreenCursor::set(image, hotx, hoty);
168 }
169
170 void QAhiScreenCursor::move(int x, int y)
171 {
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",
176                  status);
177     QScreenCursor::move(x, y);
178 }
179
180 void QAhiScreenCursor::show()
181 {
182     AhiSts_t status;
183     status = AhiDispCursorState(context, AhiCursor1, AhiCursorStateOn, 0);
184     if (status != AhiStsOk)
185         qWarning("QAhiScreenCursor::show(): error setting state: %x", status);
186     QScreenCursor::show();
187 }
188
189 void QAhiScreenCursor::hide()
190 {
191     AhiDispCursorState(context, AhiCursor1, AhiCursorStateOff, 0);
192     QScreenCursor::hide();
193 }
194
195 class QAhiScreenPrivate : public QObject
196 {
197 public:
198     QAhiScreenPrivate();
199     ~QAhiScreenPrivate();
200
201     bool setMode(AhiDispMode_t mode);
202
203     AhiDevCtx_t context;
204     AhiSurf_t surface;
205     QAhiScreenCursor *cursor;
206 };
207
208 QT_BEGIN_NAMESPACE
209
210 QAhiScreenPrivate::QAhiScreenPrivate()
211     : context(0), surface(0), cursor(0)
212 {
213 #ifndef QT_NO_QWS_SIGNALHANDLER
214     QWSSignalHandler::instance()->addObject(this);
215 #endif
216 }
217
218 QAhiScreenPrivate::~QAhiScreenPrivate()
219 {
220     delete cursor;
221
222     if (surface) {
223         AhiSurfFree(context, surface);
224         surface = 0;
225     }
226     if (context) {
227         AhiDevClose(context);
228         context = 0;
229     }
230     AhiTerm();
231 }
232
233 bool QAhiScreenPrivate::setMode(AhiDispMode_t mode)
234 {
235     AhiSts_t status;
236
237     status = AhiDispModeSet(context, &mode, 0);
238     if (status != AhiStsOk) {
239         qCritical("QAhiScreenPrivate::setMode(): AhiDispModeSet failed: %x",
240                   status);
241         return false;
242     }
243
244     if (surface) {
245         AhiSurfFree(context, surface);
246         surface = 0;
247     }
248     status = AhiSurfAlloc(context, &surface, &mode.size, mode.pixFmt,
249                           AHIFLAG_SURFFIXED);
250     if (status != AhiStsOk) {
251         qCritical("QAhiScreenPrivate::setMode(): AhisurfAlloc failed: %x",
252                   status);
253         return false;
254     }
255
256     status = AhiDispSurfSet(context, surface, 0);
257     if (status != AhiStsOk) {
258         qCritical("QAhiScreenPrivate::setMode(): AhiDispSurfSet failed: %x",
259                   status);
260         return false;
261     }
262
263     return true;
264 }
265
266 QAhiScreen::QAhiScreen(int displayId)
267     : QScreen(displayId), d_ptr(new QAhiScreenPrivate)
268 {
269 }
270
271 QAhiScreen::~QAhiScreen()
272 {
273     delete d_ptr;
274 }
275
276 bool QAhiScreen::configure()
277 {
278     AhiSurfInfo_t surfaceInfo;
279     AhiSts_t status;
280
281     status = AhiSurfInfo(d_ptr->context, d_ptr->surface, &surfaceInfo);
282     if (status != AhiStsOk) {
283         qCritical("QAhiScreen::configure(): AhiSurfInfo failed: %x", status);
284         return false;
285     }
286
287     QScreen::data = 0;
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;
292
293     switch (surfaceInfo.pixFmt) {
294     case AhiPix1bpp:
295         setPixelFormat(QImage::Format_Mono);
296         QScreen::d = 1;
297         break;
298     case AhiPix4bpp:
299         QScreen::d = 4;
300         break;
301     case AhiPix8bpp_332RGB:
302     case AhiPix8bpp:
303         QScreen::d = 8;
304         break;
305     case AhiPix16bpp_444RGB:
306         setPixelFormat(QImage::Format_RGB444);
307         QScreen::d = 12;
308         break;
309     case AhiPix16bpp_555RGB:
310         setPixelFormat(QImage::Format_RGB555);
311         QScreen::d = 15;
312         break;
313     case AhiPix16bpp_565RGB:
314         setPixelFormat(QImage::Format_RGB16);
315         QScreen::d = 16;
316         break;
317     case AhiPix2bpp:
318         QScreen::d = 2;
319         break;
320     case AhiPix32bpp_8888ARGB:
321         setPixelFormat(QImage::Format_ARGB32);
322         // fallthrough
323     case AhiPix32bpp_8888BGRA:
324         QScreen::d = 32;
325         break;
326     default:
327         qCritical("QAhiScreen::configure(): Unknown pixel format: %x",
328                   surfaceInfo.pixFmt);
329         return false;
330     }
331
332     const int dpi = 72;
333     QScreen::physWidth = qRound(QScreen::dw * 25.4 / dpi);
334     QScreen::physHeight = qRound(QScreen::dh * 25.4 / dpi);
335
336     return true;
337 }
338
339 bool QAhiScreen::connect(const QString &displaySpec)
340 {
341     Q_UNUSED(displaySpec);
342
343     AhiSts_t status;
344
345     status = AhiInit(0);
346     if (status != AhiStsOk) {
347         qCritical("QAhiScreen::connect(): AhiInit failed: %x", status);
348         return false;
349     }
350
351     AhiDev_t device;
352     AhiDevInfo_t info;
353
354     status = AhiDevEnum(&device, &info, 0);
355     if (status != AhiStsOk) {
356         qCritical("QAhiScreen::connect(): AhiDevEnum failed: %x", status);
357         return false;
358     }
359 #ifdef QAHISCREEN_DEBUG
360     {
361         int displayNo = 0;
362         AhiDevInfo_t dispInfo = info;
363         qDebug("AHI supported devices:");
364         do {
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);
376     }
377 #endif
378
379     status = AhiDevOpen(&d_ptr->context, device, "qscreenahi",
380                         AHIFLAG_USERLEVEL);
381     if (status != AhiStsOk) {
382         qCritical("QAhiScreen::connect(): AhiDevOpen failed: %x", status);
383         return false;
384     }
385
386     AhiDispMode_t mode;
387
388     status = AhiDispModeEnum(d_ptr->context, &mode, 0);
389     if (status != AhiStsOk) {
390         qCritical("QAhiScreen::connect(): AhiDispModeEnum failed: %x", status);
391         return false;
392     }
393
394 #ifdef QAHISCREEN_DEBUG
395     {
396         int modeNo = 0;
397         AhiDispMode_t modeInfo = mode;
398         qDebug("AHI supported modes:");
399         do {
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);
406     }
407 #endif
408
409     if (QApplication::type() == QApplication::GuiServer) {
410         if (!d_ptr->setMode(mode))
411             return false;
412     } else {
413         status = AhiDispSurfGet(d_ptr->context, &d_ptr->surface);
414         if (status != AhiStsOk) {
415             qCritical("QAhiScreen::connect(): AhiDispSurfGet failed: %x",
416                       status);
417             return false;
418         }
419
420         status = AhiDispModeGet(d_ptr->context, &mode);
421         if (status != AhiStsOk) {
422             qCritical("QAhiScreen::context(): AhiDispModeGet failed: %x",
423                       status);
424             return false;
425         }
426     }
427
428     return configure();
429 }
430
431 void QAhiScreen::disconnect()
432 {
433     AhiSurfFree(d_ptr->context, d_ptr->surface);
434     d_ptr->surface = 0;
435     AhiDevClose(d_ptr->context);
436     d_ptr->context = 0;
437     AhiTerm();
438 }
439
440 bool QAhiScreen::initDevice()
441 {
442     QScreenCursor::initSoftwareCursor();
443
444     AhiSts_t status = AhiDispState(d_ptr->context, AhiDispStateOn, 0);
445     if (status != AhiStsOk) {
446         qCritical("QAhiScreen::connect(): AhiDispState failed: %x", status);
447         return false;
448     }
449
450     return true;
451 }
452
453 void QAhiScreen::shutdownDevice()
454 {
455     AhiDispState(d_ptr->context, AhiDispStateOff, 0);
456 }
457
458 void QAhiScreen::setMode(int width, int height, int depth)
459 {
460     int modeNo = 0;
461     AhiDispMode_t mode;
462     AhiSts_t status = AhiStsOk;
463
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)
469         {
470             d_ptr->setMode(mode);
471             configure();
472             return;
473         }
474     }
475 }
476
477 void QAhiScreen::blit(const QImage &image, const QPoint &topLeft,
478                       const QRegion &reg)
479 {
480     AhiPixelFormat_t pixFmt = pixelFormatForImageFormat(image.format());
481
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);
487         return;
488     }
489
490     AhiSts_t status;
491
492     status = AhiDrawSurfDstSet(d_ptr->context, d_ptr->surface, 0);
493     if (status != AhiStsOk) {
494         qWarning("QAhiScreen::blit(): AhiDrawSurfDstSet failed: %x", status);
495         return;
496     }
497
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);
502
503     for (int i = 0; i < numRects; ++i) {
504         const QRect rect = rects.at(i);
505
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();
512     }
513
514     AhiSize_t bitmapSize = { image.width(), image.height() };
515     AhiBitmap_t bitmap = { bitmapSize, (void*)(image.bits()),
516                            image.bytesPerLine(), pixFmt };
517
518     status = AhiDrawRopSet(d_ptr->context, AHIMAKEROP3(AHIROPSRCCOPY));
519     if (status != AhiStsOk) {
520         qWarning("QAhiScreen::blit(): AhiDrawRopSet failed: %x", status);
521         return;
522     }
523
524     for (int i = 0; i < numRects; ++i) {
525         status = AhiDrawBitmapBlt(d_ptr->context, &dest[i], &src[i],
526                                   &bitmap, 0, 0);
527         if (status != AhiStsOk) {
528             qWarning("QAhiScreen::blit(): AhiDrawBitmapBlt failed: %x",
529                      status);
530             break;
531         }
532     }
533 }
534
535 void QAhiScreen::solidFill(const QColor &color, const QRegion &reg)
536 {
537     AhiSts_t status = AhiStsOk;
538
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());
544         break;
545     case QImage::Format_RGB16:
546         status = AhiDrawBrushFgColorSet(d_ptr->context, qt_convRgbTo16(color.rgb()));
547         break;
548     default:
549         qFatal("QAhiScreen::solidFill(): Not implemented for pixel format %d",
550                int(pixelFormat()));
551         break;
552     }
553
554     if (status != AhiStsOk) {
555         qWarning("QAhiScreen::solidFill(): AhiDrawBrushFgColorSet failed: %x",
556                  status);
557         return;
558     }
559
560     status = AhiDrawBrushSet(d_ptr->context, 0, 0, 0, AHIFLAG_BRUSHSOLID);
561     if (status != AhiStsOk) {
562         qWarning("QAhiScreen::solidFill(): AhiDrawBrushSet failed: %x",
563                  status);
564         return;
565     }
566
567     status = AhiDrawRopSet(d_ptr->context, AHIMAKEROP3(AHIROPPATCOPY));
568     if (status != AhiStsOk) {
569         qWarning("QAhiScreen::solidFill(): AhiDrawRopSet failed: %x", status);
570         return;
571     }
572
573     status = AhiDrawSurfDstSet(d_ptr->context, d_ptr->surface, 0);
574     if (status != AhiStsOk) {
575         qWarning("QAhiScreen::solidFill(): AhiDrawSurfDst failed: %x", status);
576         return;
577     }
578
579     const QVector<QRect> rects = (reg & region()).rects();
580     QVarLengthArray<AhiRect_t> ahiRects(rects.size());
581
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();
588     }
589
590     status = AhiDrawBitBltMulti(d_ptr->context, ahiRects.data(),
591                                 0, ahiRects.size());
592     if (status != AhiStsOk)
593         qWarning("QAhiScreen::solidFill(): AhiDrawBitBlt failed: %x", status);
594 }
595
596 QT_END_NAMESPACE
597
598 #endif // QT_NO_QWS_AHI