2017-10-19 6 views
2

私はMacでPyOpenGLを使用しています。デフォルトでは、OpenGL 2.1が使用されています。しかし、私の研究とOpenGL Extension Viewerによると、私はOpenGL 4.1を使用できるはずです。 私はQGLFormatをQGLWidgetに渡そうとしていますが、ここでは多くのスレッドで行われていますが、コンテキストのバージョンは変更されません。私がそれを強制しようとすると、コンテキストが有効でないことがわかります。 - 私は多くのことを試してきた ここでは私の問題を示して非常に単純な例である:ここではMacOS上でQGLFormatを使ってOpenGLのバージョンを変更するには?

from PyQt4 import QtGui, QtCore, QtOpenGL 
import sys 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 

    glFormat = QtOpenGL.QGLFormat() 
    glFormat.setVersion(4,1) 
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile) 
    glFormat.setSampleBuffers(True) 
    glFormat.setDefaultFormat(glFormat) 
    print("Format version: " + str(glFormat.majorVersion())) 
    myW = QtOpenGL.QGLWidget(glFormat) 
    print ("Widget context valid: " + str(myW.context().isValid())) 
    print ("Widget format version: " + str(myW.format().majorVersion())) 
    print ("Widget context format version: " + str(myW.context().format().majorVersion())) 
    myW.context().setFormat(glFormat) 
    print ("Forced format valid: " + str(myW.context().isValid())) 
    print ("Forced format version: " + str(myW.format().majorVersion())) 
    myW.show() 
    sys.exit(app.exec_()) 

出力されます:

Format version: 4 
Widget context valid: True 
Widget format version: 1 
Widget context format version: 1 
Forced format valid: False 
Forced format version: 4 

私の問題がある任意のアイデア?私は何か間違っているのですか? 私はmacOS Sierraバージョン10.12.6を使用しています。 Qtバージョン4.8.7、sipバージョン4.19.3、pyqtバージョン4.12を使用します。 こちらはwhat OpenGL Extension Viewer tells meです。

ご協力いただければ幸いです!

編集

私はここにC++と同様の問題がどのように見えるかを発見しました。ソリューションをPyQtに翻訳する方法がわかりませんが、私はこれを調べます: Changing the OpenGL Context Version for QGLWidgets in Qt 4.8.6 on OS X

編集3:(第二版)@ekhumoroが提供するパッチをしようとしたとき、私は次の出力を得る

正しくパッチが適用されqpyopengl.pro
patching file qpy/QtOpenGL/core_profile_attributes.mm 
patching file qpy/QtOpenGL/qpyopengl.pro 
patching file sip/QtOpenGL/qgl.sip 
patch unexpectedly ends in middle of line 
Hunk #3 FAILED at 493. 
1 out of 3 hunks FAILED -- saving rejects to file sip/QtOpenGL/qgl.sip.rej 

、それqgl.sipではまだ失敗します。

更新:ここ

がqgl.sipため拒否ファイルの内容です:好奇心のうち

*************** 
*** 478,481 **** 

    %ModuleHeaderCode 
    #include <qpyopengl_api.h> 

--- 493,498 ---- 

    %ModuleHeaderCode 
    #include <qpyopengl_api.h> 
+ typedef struct GDevice** GDHandle; 
+ void* select_3_2_mac_visual(); 

、私はconfigure-ng.py走ってコンパイルしてみました。私は次のエラーを取得する:

[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:269:5: error: 'virtual' can only appear on non-static member functions 
    virtual void* chooseMacVisual(GDHandle handle) 
    ^
[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:271:16: error: use of undeclared identifier 'select_3_2_mac_visual' 
     return select_3_2_mac_visual(); 
      ^
[...]/PyQt4_gpl_mac-4.12.1/sip/QtOpenGL/qgl.sip:269:44: warning: unused parameter 'handle' [-Wunused-parameter] 
    virtual void* chooseMacVisual(GDHandle handle) 
+0

あなたはOSX上_forward-compatible_コンテキストを作成する必要があります。 – derhass

+0

@derhass:あなたはもっと具体的になりますか? – Elensil

答えて

1

それは価値があるものについては、私のWindows 10のラップトップ上で、あなたのコードを実行すると、次の出力できます:

Format version: 4 
Widget context valid: True 
Widget format version: 4 
Widget context format version: 4 
Forced format valid: False 
Forced format version: 4 

をので、私はあなたの問題は、実際にではないかもしれないことを疑いますプラットフォーム固有のものですが、あなたのmyW.context().setFormat(glFormat)コールを使用してください。興味深いことに、私はPyQt documentation for QGLWidgetを見て、それはかなり役に立たないsetFormat()には欠けているようです!

setFormat()が実際にいずれかQGLWidget itself、またはその子QGLContextオブジェクトから呼び出すことができるように対応するC++のドキュメントで代わりに見ると、それが見えます。 QGLContextから呼び出すので、コンテキストがリセットで無効になっていることがわかります。解決策は、フォーマットを設定した後にmyW.context().create()を呼び出して、新しいパラメータで有効なフォーマットオブジェクトを作成することです。その変更は次のようになります。

from PyQt4 import QtGui, QtCore, QtOpenGL 
import sys 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 

    glFormat = QtOpenGL.QGLFormat() 
    glFormat.setVersion(4,1) 
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile) 
    glFormat.setSampleBuffers(True) 
    glFormat.setDefaultFormat(glFormat) 
    print("Format version: " + str(glFormat.majorVersion())) 
    myW = QtOpenGL.QGLWidget(glFormat) 
    print ("Widget context valid: " + str(myW.context().isValid())) 
    print ("Widget format version: " + str(myW.format().majorVersion())) 
    print ("Widget context format version: " + str(myW.context().format().majorVersion())) 
    myW.context().setFormat(glFormat) 
    myW.context().create() 
    print ("Forced format valid: " + str(myW.context().isValid())) 
    print ("Forced format version: " + str(myW.format().majorVersion())) 
    myW.show() 
    sys.exit(app.exec_()) 

他の代替は、ちょうどこの結果として、自動的に新しいコンテキストを作成QGLWidgetレベルでsetFormat()を呼び出すことです:

from PyQt4 import QtGui, QtCore, QtOpenGL 
import sys 

if __name__ == '__main__': 

    app = QtGui.QApplication(sys.argv) 

    glFormat = QtOpenGL.QGLFormat() 
    glFormat.setVersion(4,1) 
    glFormat.setProfile(QtOpenGL.QGLFormat.CoreProfile) 
    glFormat.setSampleBuffers(True) 
    glFormat.setDefaultFormat(glFormat) 
    print("Format version: " + str(glFormat.majorVersion())) 
    myW = QtOpenGL.QGLWidget(glFormat) 
    print ("Widget context valid: " + str(myW.context().isValid())) 
    print ("Widget format version: " + str(myW.format().majorVersion())) 
    print ("Widget context format version: " + str(myW.context().format().majorVersion())) 
    myW.setFormat(glFormat) 
    print ("Forced format valid: " + str(myW.context().isValid())) 
    print ("Forced format version: " + str(myW.format().majorVersion())) 
    myW.show() 
    sys.exit(app.exec_()) 

言われていること、私はこのコードをテストすることができるMacを持っていないので、これはすべて推測です。これで問題が解決したら助かりますか?

+1

ありがとう!少なくとも、私はなぜあなたのおかげでコンテキストが無効になるのか知っています。 実際、私は既にウィジェットレベルでsetFormat()を呼び出そうとしましたが、何も変更しません。つまり、コンテキストは有効ですが、バージョンは1のままです。あなたの最初の提案も試みましたが、私は同じ結果を得ました:私は有効な文脈で終わりますが、依然として間違ったOpenGLバージョン – Elensil

+0

@Elensil質問の編集で追加したリンクを見ました。PyQt5へのアップグレードがオプションではない場合(あなたの問題を修正する可能性があります)、C++オプションをどうにか翻訳する必要があるようです。たくさんのオプション(ctypes、cython、またはCの拡張機能)がありますが、最も単純なのはおそらく最初にctypesを使うようになるでしょう。うまくいけば、賞金を追加すると、私は実際にはMacの笑なしに何かをテストすることはできませんので、この質問にいくつかの注意をもたらすでしょう... – CodeSurgeon

+0

私はPyQt5を試して、それは問題を解決します。これはバックアップソリューションですが、私のアプリケーションをPyQt5にアップグレードするには大量の作業が必要です。 ほとんどの場合、ミックスに投げ込まれたレガシーOpenGLが少しあるので、PyQt5に切り替えるともう動作しません。 私はオリジナルの開発者ではなく、OpenGLとそのさまざまなバージョンに関する知識は限られています。 一方、私はユーザーに簡単に何かをインストールしたいと思っています。パッチをダウンロードして実行すると、いくつかのことが妨げられる可能性があります。 :( – Elensil

1

のPythonへのMac固有のソリューションを翻訳に関する具体的な質問に答えるために:PyQtはバインディングは仮想メソッドchooseMacVisualをラップしていないので、これは、直接をを行うことはできませんが。これがなければ、再実装する方法はありません。なぜなら、QtはPyQtが仮想として事前定義されていないPythonメソッドを見ることができないからです。

これを動作させる唯一の方法は、PyQt4をパッチして再コンパイルすることです。幸いなことに、誰かがすでにこれを行っている、とここにコードを提供:

しかし、ビルド手順を完全には明らかではない、とPyQtは-4.9.4を目的としています。だから、私はdiffを用意しました。私はMacシステムにアクセスできないので、コンパイルしようとしていません。

パッチを適用するには、latest PyQt4 OSX sourcesのアンパックを行い、ディレクトリにcdします。そして、下の差分をコピーしてmacgl.diffとして保存し、次のコマンドを実行します。

patch -Np1 -i macgl.diff 

その後、ここに示す手順を使用して、あなたのパッチを適用PyQt4をコンパイルすることができます

を更新

以前は、 PyQt-4.9.4はすべての新しいPyQt4バージョンに対して完全に適用されますが、私は間違っていました。私はPyQt-4.12.1 mac source codeに適合させた下記の改訂版でこれを修正しようとしました。ここで

は差分です:

diff -Naur c/qpy/QtOpenGL/core_profile_attributes.mm d/qpy/QtOpenGL/core_profile_attributes.mm 
--- c/qpy/QtOpenGL/core_profile_attributes.mm 1970-01-01 01:00:00.000000000 +0100 
+++ d/qpy/QtOpenGL/core_profile_attributes.mm 2017-10-22 20:11:53.000000000 +0100 
@@ -0,0 +1,22 @@ 
+#include <QGLContext> 
+ 
+ 
+void* select_3_2_mac_visual() 
+{ 
+ static const int Max = 40; 
+ NSOpenGLPixelFormatAttribute attribs[Max]; 
+ int cnt = 0; 
+ 
+ attribs[cnt++] = NSOpenGLPFAOpenGLProfile; 
+ attribs[cnt++] = NSOpenGLProfileVersion3_2Core; 
+ 
+ attribs[cnt++] = NSOpenGLPFADoubleBuffer; 
+ 
+ attribs[cnt++] = NSOpenGLPFADepthSize; 
+ attribs[cnt++] = (NSOpenGLPixelFormatAttribute)16; 
+ 
+ attribs[cnt] = 0; 
+ Q_ASSERT(cnt < Max); 
+ 
+ return [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; 
+} 
diff -Naur c/qpy/QtOpenGL/qpyopengl.pro d/qpy/QtOpenGL/qpyopengl.pro 
--- c/qpy/QtOpenGL/qpyopengl.pro 2017-06-30 09:47:26.000000000 +0100 
+++ d/qpy/QtOpenGL/qpyopengl.pro 2017-10-31 17:07:37.694805459 +0000 
@@ -24,6 +24,11 @@ 
TARGET  = qpyopengl 
TEMPLATE = lib 

+mac { 
+  OBJECTIVE_SOURCES += core_profile_attributes.mm 
+  LIBS += -framework Foundation -framework Cocoa 
+ } 
+ 
SOURCES = \ 
      qpyopengl_attribute_array.cpp \ 
      qpyopengl_uniform_value_array.cpp 
diff -Naur c/sip/QtOpenGL/qgl.sip d/sip/QtOpenGL/qgl.sip 
--- c/sip/QtOpenGL/qgl.sip 2017-06-30 09:47:26.000000000 +0100 
+++ d/sip/QtOpenGL/qgl.sip 2017-10-31 17:30:26.025295693 +0000 
@@ -20,6 +20,14 @@ 
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 


+%ModuleCode 
+#include <qgl.h> 
+ 
+typedef struct GDevice** GDHandle; 
+void* select_3_2_mac_visual(); 
+ 
+%End 
+ 
namespace QGL 
{ 
%TypeHeaderCode 
@@ -257,6 +265,13 @@ 
%End 
%End 

+%TypeCode 
+ virtual void* chooseMacVisual(GDHandle handle) 
+ { 
+  return select_3_2_mac_visual(); 
+ } 
+%End 
+ 
public: 
    void deleteTexture(GLuint tx_id); 
    static void setTextureCacheLimit(int size); 
@@ -478,4 +493,6 @@ 

%ModuleHeaderCode 
#include <qpyopengl_api.h> 
+typedef struct GDevice** GDHandle; 
+void* select_3_2_mac_visual(); 
%End 
+0

これは偉大に見える、徹底的な答えのおかげで!私もこれをテストする方法がないので、OPが返信してPyQt4の新しいバージョンで動作することを確認できれば幸いです。 – CodeSurgeon

+1

@ CodeSurgeon。私たちはここの暗闇の中にいるようですが、うまくいけばうまくいきます。 – ekhumoro

+0

@ekhumoro お返事ありがとうございます、これは有望です! 私はしばらくお世話になりましたが、問題を取り返しました。 あなたのパッチは、あなたが提供したcoregl-pythonのリンクを完全に置き換えます。 私はあなたの指示を試しましたが、エラーメッセージが表示されます。これを引き起こす原因は何ですか? 残念ながら、私はここであなたの指示に盲目的に従っています。 – Elensil

関連する問題