From a7029d7b4d113ab6c0f9b87f447794c1338fe7a2 Mon Sep 17 00:00:00 2001 From: bgk Date: Thu, 19 Mar 2009 10:20:42 +0000 Subject: [PATCH] GTK: Rewrote the OpenGL code. The old code used a software path with Mesa drivers. The new one (taken from the SDL port) is much faster with these drivers. git-svn-id: https://svn.code.sf.net/p/vbam/code/trunk@857 a31d4220-a93d-0410-bf67-fe4944624d44 --- src/gtk/screenarea-opengl.cpp | 74 +++++++++++++++++++++++++++++------ src/gtk/screenarea-opengl.h | 6 ++- src/gtk/screenarea.cpp | 6 +++ src/gtk/screenarea.h | 2 + src/gtk/window.cpp | 10 +++++ src/gtk/window.h | 2 + src/gtk/windowcallbacks.cpp | 20 ++++++++++ 7 files changed, 106 insertions(+), 14 deletions(-) diff --git a/src/gtk/screenarea-opengl.cpp b/src/gtk/screenarea-opengl.cpp index ee96ecb3..e6557aa9 100644 --- a/src/gtk/screenarea-opengl.cpp +++ b/src/gtk/screenarea-opengl.cpp @@ -27,7 +27,9 @@ template T min( T x, T y ) { return x < y ? x : y; } template T max( T x, T y ) { return x > y ? x : y; } ScreenAreaGl::ScreenAreaGl(int _iWidth, int _iHeight, int _iScale) : - ScreenArea(_iWidth, _iHeight, _iScale) + ScreenArea(_iWidth, _iHeight, _iScale), + m_uiScreenTexture(0), + m_iTextureSize(256) { Glib::RefPtr glconfig; @@ -52,7 +54,13 @@ void ScreenAreaGl::on_realize() if (!glwindow->gl_begin(get_gl_context())) return; - glViewport(0, 0, get_width(), get_height()); + glDisable(GL_CULL_FACE); + glEnable(GL_TEXTURE_2D); + + if (glIsTexture(m_uiScreenTexture)) + glDeleteTextures(1, &m_uiScreenTexture); + + glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -62,7 +70,28 @@ void ScreenAreaGl::on_realize() glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + glGenTextures(1, &m_uiScreenTexture); + glBindTexture(GL_TEXTURE_2D, m_uiScreenTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + // Calculate texture size as a the smallest working power of two + float n1 = log10((float)m_iScaledWidth ) / log10( 2.0f); + float n2 = log10((float)m_iScaledHeight ) / log10( 2.0f); + float n = (n1 > n2)? n1 : n2; + + // round up + if (((float)((int)n)) != n) + n = ((float)((int)n)) + 1.0f; + + m_iTextureSize = (int)pow(2.0f, n); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_iTextureSize, m_iTextureSize, 0, + GL_BGRA, GL_UNSIGNED_BYTE, NULL); + glClearColor(0.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); glwindow->gl_end(); } @@ -87,32 +116,53 @@ void ScreenAreaGl::vOnWidgetResize() { Glib::RefPtr glwindow = get_gl_window(); + int iWidth = get_width(); + int iHeight = get_height(); + + float fScreenAspect = (float) m_iScaledWidth / m_iScaledHeight, + fWindowAspect = (float) iWidth / iHeight; + if (!glwindow->gl_begin(get_gl_context())) return; - glViewport(0, 0, get_width(), get_height()); + if (fWindowAspect == fScreenAspect) + glViewport(0, 0, iWidth, iHeight); + else if (fWindowAspect < fScreenAspect) { + int iAspectHeight = (int)(iWidth / fScreenAspect); + glViewport(0, (iHeight - iAspectHeight) / 2, iWidth, iAspectHeight); + } else { + int iAspectWidth = (int)(iHeight * fScreenAspect); + glViewport((iWidth - iAspectWidth) / 2, 0, iAspectWidth, iHeight); + } glwindow->gl_end(); - - m_dScaleFactor = min(get_height() / (double)m_iScaledHeight, get_width() / (double)m_iScaledWidth); - m_dAreaTop = (1 - m_dScaleFactor * m_iScaledHeight / (double)get_height()) / 2; - m_dAreaLeft = (1 - m_dScaleFactor * m_iScaledWidth / (double)get_width()) / 2; } bool ScreenAreaGl::on_expose_event(GdkEventExpose * _pstEvent) { - glPixelZoom(m_dScaleFactor, -m_dScaleFactor); - glRasterPos2f(m_dAreaLeft, m_dAreaTop); - - glPixelStorei(GL_UNPACK_ROW_LENGTH, m_iScaledWidth + 1); + if (!m_bEnableRender) + return true; Glib::RefPtr glwindow = get_gl_window(); if (!glwindow->gl_begin(get_gl_context())) return false; glClear( GL_COLOR_BUFFER_BIT ); + glPixelStorei(GL_UNPACK_ROW_LENGTH, m_iScaledWidth + 1); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_iScaledWidth + 1, m_iScaledHeight, + GL_RGBA, GL_UNSIGNED_BYTE, m_puiPixels); - glDrawPixels(m_iScaledWidth, m_iScaledHeight, GL_RGBA, GL_UNSIGNED_BYTE, m_puiPixels); + glBegin(GL_TRIANGLE_STRIP); + glTexCoord2f(0.0f, 0.0f); + glVertex3i(0, 0, 0); + glTexCoord2f(m_iScaledWidth / (GLfloat) m_iTextureSize, 0.0f); + glVertex3i(1, 0, 0); + glTexCoord2f(0.0f, m_iScaledHeight / (GLfloat) m_iTextureSize); + glVertex3i(0, 1, 0); + glTexCoord2f(m_iScaledWidth / (GLfloat) m_iTextureSize, + m_iScaledHeight / (GLfloat) m_iTextureSize); + glVertex3i(1, 1, 0); + glEnd(); glwindow->swap_buffers(); diff --git a/src/gtk/screenarea-opengl.h b/src/gtk/screenarea-opengl.h index d8e3870b..c7d70539 100644 --- a/src/gtk/screenarea-opengl.h +++ b/src/gtk/screenarea-opengl.h @@ -40,9 +40,11 @@ protected: void vOnWidgetResize(); private: - double m_dAreaTop; + GLuint m_uiScreenTexture; + int m_iTextureSize; +/* double m_dAreaTop; double m_dAreaLeft; - double m_dScaleFactor; + double m_dScaleFactor;*/ }; } // namespace VBA diff --git a/src/gtk/screenarea.cpp b/src/gtk/screenarea.cpp index 8148bcfa..4efbe133 100644 --- a/src/gtk/screenarea.cpp +++ b/src/gtk/screenarea.cpp @@ -31,6 +31,7 @@ ScreenArea::ScreenArea(int _iWidth, int _iHeight, int _iScale) : m_puiDelta(NULL), m_iScaledWidth(_iWidth), m_iScaledHeight(_iHeight), + m_bEnableRender(true), m_bShowCursor(true) { g_assert(_iWidth >= 1 && _iHeight >= 1 && _iScale >= 1); @@ -233,4 +234,9 @@ bool ScreenArea::on_configure_event(GdkEventConfigure * event) return true; } +void ScreenArea::vSetEnableRender(bool _bEnable) +{ + m_bEnableRender = _bEnable; +} + } // namespace VBA diff --git a/src/gtk/screenarea.h b/src/gtk/screenarea.h index f43a6dfd..a83f5ff2 100644 --- a/src/gtk/screenarea.h +++ b/src/gtk/screenarea.h @@ -38,6 +38,7 @@ public: void vSetScale(int _iScale); void vSetFilter(EFilter _eFilter); void vSetFilterIB(EFilterIB _eFilterIB); + void vSetEnableRender(bool _bEnable); virtual void vDrawPixels(u8 * _puiData); virtual void vDrawBlackScreen() = 0; @@ -60,6 +61,7 @@ protected: u8 * m_puiDelta; int m_iScaledWidth; int m_iScaledHeight; + bool m_bEnableRender; bool m_bShowCursor; Gdk::Cursor * m_poEmptyCursor; diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index a99fb3d6..8401b124 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -155,6 +155,16 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr & _poXml) : // Menu bar m_poMenuBar = dynamic_cast(_poXml->get_widget("MenuBar")); + m_poMenuBar->signal_deactivate().connect(sigc::mem_fun(*this, &Window::vOnMenuExit)); + + poMI = dynamic_cast(_poXml->get_widget("FileMenu")); + poMI->signal_activate().connect(sigc::mem_fun(*this, &Window::vOnMenuEnter)); + poMI = dynamic_cast(_poXml->get_widget("EmulationMenu")); + poMI->signal_activate().connect(sigc::mem_fun(*this, &Window::vOnMenuEnter)); + poMI = dynamic_cast(_poXml->get_widget("OptionsMenu")); + poMI->signal_activate().connect(sigc::mem_fun(*this, &Window::vOnMenuEnter)); + poMI = dynamic_cast(_poXml->get_widget("HelpMenu")); + poMI->signal_activate().connect(sigc::mem_fun(*this, &Window::vOnMenuEnter)); // File menu // diff --git a/src/gtk/window.h b/src/gtk/window.h index 528d6d9e..78a5f71f 100644 --- a/src/gtk/window.h +++ b/src/gtk/window.h @@ -135,6 +135,8 @@ protected: ColorFormatBGR }; + virtual void vOnMenuEnter(); + virtual void vOnMenuExit(); virtual void vOnFileOpen(); virtual void vOnFileLoad(); virtual void vOnFileSave(); diff --git a/src/gtk/windowcallbacks.cpp b/src/gtk/windowcallbacks.cpp index 4ed3fb3e..a1ed5e11 100644 --- a/src/gtk/windowcallbacks.cpp +++ b/src/gtk/windowcallbacks.cpp @@ -44,6 +44,26 @@ namespace VBA { +void Window::vOnMenuEnter() +{ + if (emulating && ! m_bPaused) + { + m_poScreenArea->vSetEnableRender(false); + vStopEmu(); + soundPause(); + } +} + +void Window::vOnMenuExit() +{ + if (emulating && ! m_bPaused) + { + m_poScreenArea->vSetEnableRender(true); + vStartEmu(); + soundResume(); + } +} + void Window::vOnFileOpen() { while (m_poFileOpenDialog->run() == Gtk::RESPONSE_OK)