【保存版】Mac向けQt GUIとOpenGLプログラミング:QCocoaGLContext::fromNative()の使い方とサンプルコード


QCocoaGLContext::fromNative() は、Qt GUI における macOS 上の OpenGL コンテキストを扱うための静的関数です。この関数は、ネイティブな NSOpenGLContext オブジェクトをラップして、QOpenGLContext オブジェクトに変換します。

機能

QCocoaGLContext::fromNative() は、以下の機能を提供します。

  • 共有コンテキストを指定することで、複数の OpenGL コンテキスト間でリソースを共有できます。
  • ネイティブな NSOpenGLContext オブジェクトをラップして、Qt の OpenGL コンテキスト API で使用できるようにします。

構文

static QOpenGLContext* QCocoaGLContext::fromNative(
    NSOpenGLContext* context,
    QOpenGLContext* shareContext = nullptr
);

引数

  • shareContext: 共有コンテキストとなる QOpenGLContext オブジェクト (省略可)
  • context: ラップするネイティブな NSOpenGLContext オブジェクト

戻り値

ラップされた QOpenGLContext オブジェクト。ラップに失敗した場合は nullptr を返します。

詳細

  • 共有コンテキストを指定することで、複数の OpenGL コンテキスト間でテクスチャやシェーダーなどのリソースを共有できます。これは、パフォーマンスを向上させるのに役立ちます。
  • QCocoaGLContext::fromNative() は、ネイティブな NSOpenGLContext オブジェクトの所有権を引き継ぎます。つまり、この関数を呼び出した後に、context パラメータで渡されたオブジェクトを直接破棄してはなりません。

NSOpenGLContext* nativeContext = ...; // ネイティブな NSOpenGLContext オブジェクトを取得

// 共有コンテキストなしでラップ
QOpenGLContext* context1 = QCocoaGLContext::fromNative(nativeContext);

// 共有コンテキストを使用してラップ
QOpenGLContext* context2 = QCocoaGLContext::fromNative(nativeContext, context1);
  • ネイティブな NSOpenGLContext オブジェクトは、Qt 以外のアプリケーションによって作成されたものであっても使用できます。
  • QCocoaGLContext::fromNative() は、macOS 上でのみ使用できます。


例 1: 共有コンテキストなしでラップ

#include <QApplication>
#include <QGLWidget>

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  // ネイティブな NSOpenGLContext オブジェクトを取得
  NSOpenGLContext* nativeContext = [[NSOpenGLContext alloc] initWithAttributes:nil];

  // 共有コンテキストなしでラップ
  QOpenGLContext* context = QCocoaGLContext::fromNative(nativeContext);

  // QGLWidget を作成して OpenGL コンテキストを設定
  QGLWidget widget;
  widget.setContext(context);
  widget.show();

  return app.exec();
}

例 2: 共有コンテキストを使用してラップ

#include <QApplication>
#include <QGLWidget>

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  // ネイティブな NSOpenGLContext オブジェクトを取得
  NSOpenGLContext* nativeContext = [[NSOpenGLContext alloc] initWithAttributes:nil];

  // 共有コンテキストを作成
  QOpenGLContext* shareContext = QCocoaGLContext::fromNative(nativeContext);

  // 1 つ目の QGLWidget を作成して OpenGL コンテキストを設定
  QGLWidget widget1;
  widget1.setContext(shareContext);
  widget1.show();

  // 2 つ目の QGLWidget を作成して共有コンテキストを使用
  QGLWidget widget2;
  widget2.setContext(shareContext);
  widget2.show();

  return app.exec();
}
  • 例 2 では、ネイティブな NSOpenGLContext オブジェクトを取得し、共有コンテキストを作成します。その後、2 つの QGLWidget を作成し、共有コンテキストを使用してそれぞれ OpenGL コンテキストを設定します。
  • 例 1 では、ネイティブな NSOpenGLContext オブジェクトを取得し、共有コンテキストなしで QOpenGLContext オブジェクトにラップします。


QCocoaGLContext::fromNative() は、macOS 上の OpenGL コンテキストをラップするための便利な関数ですが、状況によっては代替方法の方が適切な場合もあります。

代替方法

  • QOpenGLContext::setNativeHandle()`
    • ネイティブな OpenGL コンテキストハンドルを直接設定できます。
    • 低レベルな制御が必要な場合に役立ちますが、QCocoaGLContext::fromNative()QOpenGLContext::create() よりもコードが複雑になります。
    • 共有コンテキストを作成するには、ネイティブなコードを使用する必要があります。
  • QOpenGLContext::create()`
    • QCocoaGLContext::fromNative() と同様に、ネイティブな OpenGL コンテキストをラップできます。
    • QCocoaGLContext::fromNative() よりも汎用性が高く、WindowsLinux などの他のプラットフォームでも使用できます。
    • 共有コンテキストを作成する場合は、QOpenGLContext::setShareContext() メソッドを使用する必要があります。

例 1: QOpenGLContext::create() を使用してラップ

#include <QApplication>
#include <QGLWidget>

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  // ネイティブな NSOpenGLContext オブジェクトを取得
  NSOpenGLContext* nativeContext = [[NSOpenGLContext alloc] initWithAttributes:nil];

  // QOpenGLContext を作成してネイティブなコンテキストハンドルを設定
  QOpenGLContext context;
  context.setNativeHandle(nativeContext);

  // QGLWidget を作成して OpenGL コンテキストを設定
  QGLWidget widget;
  widget.setContext(&context);
  widget.show();

  return app.exec();
}

例 2: QOpenGLContext::setNativeHandle() を使用してラップ

#include <QApplication>
#include <QGLWidget>

int main(int argc, char* argv[]) {
  QApplication app(argc, argv);

  // ネイティブな NSOpenGLContext オブジェクトを取得
  NSOpenGLContext* nativeContext = [[NSOpenGLContext alloc] initWithAttributes:nil];

  // QOpenGLContext オブジェクトを作成
  QOpenGLContext context;

  // ネイティブなコンテキストハンドルを取得
  CGDirectDisplayID displayID = CGMainDisplayID();
  CGLContextObj cglContext = CGLCreateContext(displayID, NULL, NULL);

  // ネイティブなコンテキストハンドルを QOpenGLContext に設定
  context.setNativeHandle(cglContext);

  // QGLWidget を作成して OpenGL コンテキストを設定
  QGLWidget widget;
  widget.setContext(&context);
  widget.show();

  return app.exec();
}
  • QOpenGLContext::setNativeHandle() は、低レベルな OpenGL API に関する知識が必要となります。
  • QOpenGLContext::create() は、macOS 上でのみ使用できます。