LoginSignup
13
10

More than 5 years have passed since last update.

QPA(Qt Platform Abstraction) メモ

Last updated at Posted at 2014-03-15

QPAとは

QPAはQt5(正確にはQt4.8)から導入された、プラットフォーム依存部(描画、ユーザー入力等)を隠蔽する仕組み。
Linuxでは.so、Windowsでは.dllの形で提供される。
xcb(X Window System), windows, directfb, linuxfb, eglfsなどのプラグインが用意されている。

普段ユーザーが意識することは無いが、Qtアプリが動作する際はいずれかのQPAプラグインが必ず使用されている。

QPAプラグインの使用方法

環境変数QT_QPA_PLATFORMもしくは、Qtアプリケーション起動時の引数-platformでQPAプラグインを指定することができる。
ただしここで指定するのは、プラグインのファイル名ではなくプラグインが返すキー値(例えばlibqxcb.soではxcb)であることに注意。
指定がない場合はシステムデフォルトのプラグインが使用される。

なおプラグインファイルが置いてあるパスは、QT_QPA_PLATFORM_PLUGIN_PATHで指定できる。

QPAプラグインの作成

参考
http://qt5.jp/learn-qpa-01.html

QPlatformIntegrationPluginとQPlatformIntegrationをそれぞれ継承したクラスを作る。

QPlatformIntegrationはプラットフォーム依存部分を抽象化したクラスを返すメソッドを持っており、それらのメソッドをオーバーライドし、プラットフォームに応じたクラスを返すことでプラットフォーム依存部分を実装する。
QPlatformIntegrationPluginを継承したクラスは少なくとも以下の3メソッドをオーバーライドする必要がある。

    virtual QPlatformWindow *createPlatformWindow(QWindow *window) const = 0;
    virtual QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const = 0;
    virtual QAbstractEventDispatcher *guiThreadEventDispatcher() const = 0;

QPlatformIntegrationPluginに記述するQ_PLUGIN_METADATAには対応するQtの"マイナーバージョン"まで指定する必要があるので要注意。

Q_PLUGIN_METADATAでインターフェイスを指定する必要がある。Qtのバージョンごとに対応するインターフェイスのバージョンは違っており、異なったバージョンのプラグインは認識されない。
(Qt5.1は5.1, Qt5.2/5.3は5.2が対応しているもよう)

Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.1" FILE "hoge.json")

上記指定ではプラグインはQt5.1のみで動作し、それ以外(Qt5.2やQt5.0等)では認識されない。

また上で説明したプラグインを指定するキー値は上記メタデータのFILEで設定される。

hoge.json
{
    "Keys":[ "hoge" ]
}

QPAプラグインが返すクラスについて

参考
http://qforever.wordpress.com/2012/04/10/qt-platform-abstraction-starter-guide/

QPlatformIntegrationのメソッドが返すクラスについて解説する。
(網羅はしていない)

QPlatformWindow

QPlatformWindowはQWindowから使われ、raise()/lower(), setWindowTitle(), geometry()/setGeometory()といったウィンドウに関するアクションをプラットフォームに伝える。

なおDirectFBプラグインにおいて、ウィンドウのアクションはQt5.1ではDirectFBが持っているcompositorへ通知されていたが、Qt5.2ではプラグインが自前でcompositeしているもよう。

QPlatformBackingStore

ウィンドウの描画エリアクラス。
QPaintDeviceを返すpaintDevice()を持っており、このメソッドでプラットフォーム依存のペイントデバイスを返すことで描画処理を最適化できる。

QPlatformPixmap

QPixmapのプラットフォーム依存部分を抽象化したクラス。
QPaintEngineを返すpaintEngine()を持っており、このメソッドでプラットフォーム依存のペイントエンジンを返すことで描画処理を最適化できる。

ペイントデバイスやペイントエンジンといったQtのPaint Systemについては以下を参照
http://qt-project.org/doc/qt-5/paintsystem.html

DirectFBプラグインについて

参考
http://qt-project.org/wiki/DirectFBAndQt

DirectFBプラグインではQBlittablePlatformPixmapを経由してQBlitterPaintEngineをペイントエンジンとして描画を行う。
QBlitterPaintEngineはQPaintEngineの一部(drawPixmap, fillRect)のみを実装している。
それ以外の処理についてはQBlitterPaintEngineの親クラスであるQRasterPaintEngineに移譲されている。

QBlitterPaintEngineで実装されている描画処理ではQDirectFbBlitterを経由してDirectFBのAPIが呼ばれているため、GPUアクセラレーションが期待できる。
しかしQRasterPaintEnginenに移譲された描画処理はDirectFBのSurfaceをLockして取得したメモリ領域に対して(そこから生成したQImageを介して)描画処理をおこなうため、GPUアクセラレーションは期待できない。

EglFSプラグインについて

EglFSプラグインはX11等のウィンドウシステムを使用せず、EGLを用いて直接フレームバッファへの描画を行うプラグインである。
QEGLPlatformBackingStore::paintDevice()が返すpaint deviceはただのQImageであり、またQPlatformIntegration::createPlatformPixmap()のオーバーライドもないため、描画処理は全てCPUにて行われ、GPUによるパフォーマンス改善は見込めない。
MinimalEglプラグインのようにpaint deviceとしてQOpenGLContextを返してしまうとGL関連のWidgetにて問題が発生するためだと思われる。

13
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10