El Capitanにて起動時にエラー発生
エラー発生時の処理ルートは以下の通り。
[MTMainView thread_DrawScene] [MTMainView thread_DrawProc] OGLRenderer::RenderScene MTSceneTitle::Draw MTSceneTitle::Transform MTLogo::Transform MTLogo::_SetGradationColor OGLPrimitive::UnlockVertex glBufferSubData ここでエラー発生起動画面のMIDITrailロゴ描画処理で、頂点バッファの書き換えのため OpenGLのglBufferSubDataを呼び出したときにエラーが発生していた。 glGetErrorの返却値は1282(GL_INVALID_OPERATION)。
しかし、MTLogo::_SetGradationColorが戻り値を返さないメソッドとして定義されていたため、 検出されたエラーが握りつぶされてしまった。 OGLPrimitive::UnlockVertexが失敗したことで、ロックフラグがONのまま処理が続行した後に、 次の箇所でエラーを検出した。
[MTMainView thread_DrawScene] [MTMainView thread_DrawProc] OGLRenderer::RenderScene MTSceneTitle::Draw MTLogo::Draw OGLPrimitive::Draw ここでエラー検出描画処理OGLPrimitive::Drawで、ロックフラグがONのままであったため、 プログラムエラーと判断してエラーメッセージを表示した。
El Capitan において、NSOpenGLViewの動作が変更されていた。 prepareOpenGLの呼び出しタイミングが非同期になったことで、 OpenGLの処理で異常が発生した。
MIDITrail起動時の初期化処理で、メインウィンドウ表示を実行する時に prepareOpenGLが同期実行される。
MIDITrail起動時の初期化処理で、メインウィンドウ表示を実行しても、 prepareOpenGLが同期実行されない。 初期化処理が完了してイベントループに戻った後、 別のイベントでprepareOpneGLが実行される。
MIDITrail起動時の初期化処理において、メインウィンドウ表示の直後に シーンオブジェクトの生成を行っており、この中で頂点バッファを生成していた。 El Capitanの環境では、メインウィンドウ表示でprepareOpenGLは実行されず、 OpenGLコンテキストが生成されない。この状態で頂点バッファを生成することになった。 そしてOpenGLコンテキスト生成後の頂点バッファ書き換え処理でエラーが発生した。
参考情報: OSX El CapitanでのNSOpenGLViewの挙動の変化 http://ysflight.in.coocan.jp/programming/macosx/20151004/j.html
MTMainView::prepareOpenGLが実行されるタイミングは以下の通り。
ウィンドウ表示を実行する時点でprepareOpenGLが同期実行されていた。
[NSApplication run] [NSApplication finishLaunching] ... MIDITrailApp::Initialize MIDITrailApp::_CreateWindow [MTMainWindowCtrl showWindow] [NSWindowController showWindow] ... [NSOpenGLContext makeCurrentContext] [MTMainView prepareOpenGL]
イベントループに戻った後でprepareOpneGLが実行される。
[NSApplication run] [NSApplication nextEventMatchingEvnetMask:untilDate:inMode:dequeue] ... [NSOpenGLContext makeCurrentContext] [MTMainVIew prepareOpenGL]
シーンオブジェクト生成を、prepareOpenGLが実行された後に移動する。 なお、本件のEl Capitan環境での検証のため、開発環境をXcode7に移行した。 (#35750 OS X版の開発環境をXcode7に変更)
OpenGLコンテキスト準備完了通知を受け取るよう、通知先を登録する。
OpenGLコンテキスト準備完了通知受信処理を新規追加。 MIDITrailApp::OnPreparedOpenGLを呼びだす。
OpenGLコンテキスト準備完了を通知する処理を追加。
シーンオブジェクト生成処理_CreateSceneを削除。 MIDITrailApp::OnPreparedOpenGLに移動。
OpenGLコンテキスト準備完了イベント処理を新規追加。 シーンオブジェクト生成とシーン描画開始(スレッド起動)を行う。 コマンドライン処理を起動直後の1回のみ実行する。
シーン描画開始(スレッド起動)を削除。 これにより本メソッドは何も処理を行わなくなった。
ウィンドウサイズ変更時に、メインウィンドウを作成しなおしたとき 非同期でonPreparedOpenGLが実行されるため、 シーンオブジェクト生成とシーン描画開(スレッド起動)を削除する。 この処理は、MIDITrailApp::OnPreparedOpenGLに任せる。
コマンドライン処理済みフラグm_isCmdLineProccessedを追加。
戻り値を返すように修正する。
ファイルドロップイベント発生タイミングがOpenGL準備完了前であれば、処理をスキップする。 ファイルドロップイベントは、アプリアイコンにファイルをドロップしてアプリが起動した時にも発生する。 しかしOnDropFileが呼び出されることで、OpenGL準備前にファイル読み込みとシーンの生成処理が実行されてしまう。 ファイルドロップによるアプリ起動については、コマンドライン解析処理に任せる。
これまで、コマンドラインでファイルパスを指定して起動した場合、 コマンドライン解析処理とドロップイベントにより、二回のファイル読み込みが発生していたようだ。 しかし無駄な処理をしているだけで、エラーにはならない。
OS X 10.11 (El Capitan)にて MIDITrail Ver.1.2.1を起動すると、 次のエラーが発生してアプリを利用できない。