From 66dd396d85746dd50b3dd44b99c50a3926ea7d2e Mon Sep 17 00:00:00 2001 From: bgk Date: Fri, 25 Apr 2008 18:21:39 +0000 Subject: [PATCH] GTK GUI : Replaced GTK/GDK display by GTK/Cairo, now the window can be resized with all the video modules. --- CMakeLists.txt | 6 +- debian/control | 2 +- src/gtk/screenarea-cairo.cpp | 163 +++++++++++++++++ .../{screenarea-gtk.h => screenarea-cairo.h} | 20 +- src/gtk/screenarea-gtk.cpp | 173 ------------------ src/gtk/window.cpp | 20 +- src/gtk/window.h | 2 +- 7 files changed, 190 insertions(+), 196 deletions(-) create mode 100644 src/gtk/screenarea-cairo.cpp rename src/gtk/{screenarea-gtk.h => screenarea-cairo.h} (72%) delete mode 100644 src/gtk/screenarea-gtk.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1dda9115..6846bd17 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,8 +46,8 @@ ADD_DEFINITIONS (-DHAVE_NETINET_IN_H -DHAVE_ARPA_INET_H -DHAVE_ZLIB_H -DFINAL_VE ADD_DEFINITIONS (-DVERSION='"${VERSION}"' -DPKGDATADIR='"${PKGDATADIR}"' -DPACKAGE='') SET( CMAKE_ASM_FLAGS "-Isrc/hq/asm/ -O1 -DELF") -SET( CMAKE_C_FLAGS "-O3") -SET( CMAKE_CXX_FLAGS "-O3") +SET( CMAKE_C_FLAGS "-O3 -Wall") +SET( CMAKE_CXX_FLAGS "-O3 -Wall") SET(SRC_MAIN src/2xSaI.cpp @@ -142,7 +142,7 @@ SET(SRC_GTK src/gtk/filters.cpp src/gtk/joypadconfig.cpp src/gtk/screenarea.cpp - src/gtk/screenarea-gtk.cpp + src/gtk/screenarea-cairo.cpp src/gtk/screenarea-xvideo.cpp src/gtk/screenarea-opengl.cpp src/gtk/tools.cpp diff --git a/debian/control b/debian/control index 1a949fd8..2fae418a 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: vbam Section: games Priority: extra Maintainer: Bastien Bouclet -Build-Depends: debhelper (>= 5), zlib1g-dev, libpng12-dev, libsdl1.2-dev, libgl1-mesa-dev, libgtkmm-2.4-dev, libglademm-2.4-dev, cmake, portaudio19-dev +Build-Depends: debhelper (>= 5), zlib1g-dev, libpng12-dev, libsdl1.2-dev, libgl1-mesa-dev, libgtkmm-2.4-dev, libglademm-2.4-dev, cmake, portaudio19-dev, libgtkglextmm-x11-dev, libxv-dev Standards-Version: 3.7.2 Package: vbam diff --git a/src/gtk/screenarea-cairo.cpp b/src/gtk/screenarea-cairo.cpp new file mode 100644 index 00000000..f14b94cb --- /dev/null +++ b/src/gtk/screenarea-cairo.cpp @@ -0,0 +1,163 @@ +// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. +// Copyright (C) 1999-2003 Forgotten +// Copyright (C) 2004 Forgotten and the VBA development team + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2, or(at your option) +// any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software Foundation, +// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#include "screenarea-cairo.h" + +#include + +namespace VBA +{ + +template T min( T x, T y ) { return x < y ? x : y; } +template T max( T x, T y ) { return x > y ? x : y; } + +ScreenAreaCairo::ScreenAreaCairo(int _iWidth, int _iHeight, int _iScale) : + ScreenArea(_iWidth, _iHeight, _iScale), + m_puiPixels(NULL), + m_puiDelta(NULL), + m_iScaledWidth(_iWidth), + m_iScaledHeight(_iHeight) +{ + vUpdateSize(); +} + +ScreenAreaCairo::~ScreenAreaCairo() +{ +} + +void ScreenAreaCairo::vDrawPixels(u8 * _puiData) +{ + const int iSrcPitch = (m_iWidth + 1) * sizeof(u32); + const int iScaledPitch = (m_iScaledWidth + 1) * sizeof(u32); + + if (m_vFilterIB != NULL) + { + m_vFilterIB(_puiData + iSrcPitch, + iSrcPitch, + m_iWidth, + m_iHeight); + } + + if (m_vFilter2x != NULL) + { + m_vFilter2x(_puiData + iSrcPitch, + iSrcPitch, + m_puiDelta, + (u8 *)m_puiPixels, + iScaledPitch, + m_iWidth, + m_iHeight); + } + else + { + // TODO : Find a way to use systemXXXShift cleanly to avoid this loop + u32 * puiPixel = m_puiPixels; + u8 * puiSrc = _puiData + iSrcPitch; + for (int i = 0; i < (m_iWidth + 1) * m_iHeight; i++) + { + u8 iR = *puiSrc++; + u8 iG = *puiSrc++; + u8 iB = *puiSrc++; + puiSrc++; + *puiPixel++ = (iR << 16) + (iG << 8) + iB; + } + } + + queue_draw(); +} + +bool ScreenAreaCairo::on_expose_event(GdkEventExpose * _pstEvent) +{ + DrawingArea::on_expose_event(_pstEvent); + Cairo::RefPtr< Cairo::ImageSurface > poImage; + Cairo::RefPtr< Cairo::SurfacePattern > poPattern; + Cairo::RefPtr< Cairo::Context > poContext; + Cairo::Matrix oMatrix; + const int iScaledPitch = (m_iScaledWidth + 1) * sizeof(u32); + + poContext = get_window()->create_cairo_context(); + + poContext->set_identity_matrix(); + poContext->scale(m_dScaleFactor, m_dScaleFactor); + + poImage = Cairo::ImageSurface::create((u8 *)m_puiPixels, Cairo::FORMAT_RGB24, + m_iScaledWidth, m_iScaledHeight, iScaledPitch); + + cairo_matrix_init_translate(&oMatrix, -m_iAreaLeft, -m_iAreaTop); + poPattern = Cairo::SurfacePattern::create(poImage); + poPattern->set_filter(Cairo::FILTER_NEAREST); + poPattern->set_matrix (oMatrix); + poContext->set_source_rgb(0.0, 0.0, 0.0); + poContext->paint(); + + poContext->set_source(poPattern); + poContext->paint(); + + return true; +} + +void ScreenAreaCairo::vDrawBlackScreen() +{ + if (m_puiPixels && is_realized()) + { + memset(m_puiPixels, 0, m_iHeight * (m_iWidth + 1) * sizeof(u32)); + queue_draw_area(0, 0, get_width(), get_height()); + } +} + +void ScreenAreaCairo::vUpdateSize() +{ + if (m_puiPixels) + { + delete[] m_puiPixels; + } + + if (m_puiDelta) + { + delete[] m_puiDelta; + } + + m_iScaledWidth = m_iFilterScale * m_iWidth; + m_iScaledHeight = m_iFilterScale * m_iHeight; + + vOnWidgetResize(); + + m_puiPixels = new u32[(m_iScaledWidth + 1) * m_iScaledHeight]; + m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * sizeof(u32)]; + memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * sizeof(u32)); + + set_size_request(m_iScale * m_iWidth, m_iScale * m_iHeight); +} + +void ScreenAreaCairo::vOnWidgetResize() +{ + m_dScaleFactor = min(get_height() / (double)m_iHeight, get_width() / (double)m_iWidth); + m_dScaleFactor /= m_iFilterScale; + + m_iAreaTop = (get_height() / m_dScaleFactor - m_iHeight * m_iFilterScale) / 2; + m_iAreaLeft = (get_width() / m_dScaleFactor - m_iWidth * m_iFilterScale) / 2; +} + +bool ScreenAreaCairo::on_configure_event(GdkEventConfigure * event) +{ + vOnWidgetResize(); + + return true; +} + +} // namespace VBA diff --git a/src/gtk/screenarea-gtk.h b/src/gtk/screenarea-cairo.h similarity index 72% rename from src/gtk/screenarea-gtk.h rename to src/gtk/screenarea-cairo.h index efa18491..96508a19 100644 --- a/src/gtk/screenarea-gtk.h +++ b/src/gtk/screenarea-cairo.h @@ -17,34 +17,40 @@ // along with this program; if not, write to the Free Software Foundation, // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -#ifndef __VBA_SCREENAREA_GTK_H__ -#define __VBA_SCREENAREA_GTK_H__ +#ifndef __VBA_SCREENAREA_CAIRO_H__ +#define __VBA_SCREENAREA_CAIRO_H__ #include "screenarea.h" namespace VBA { -class ScreenAreaGtk : public ScreenArea +class ScreenAreaCairo : public ScreenArea { public: - ScreenAreaGtk(int _iWidth, int _iHeight, int _iScale = 1); - virtual ~ScreenAreaGtk(); + ScreenAreaCairo(int _iWidth, int _iHeight, int _iScale = 1); + virtual ~ScreenAreaCairo(); void vDrawPixels(u8 * _puiData); void vDrawBlackScreen(); protected: + bool on_configure_event(GdkEventConfigure * event); bool on_expose_event(GdkEventExpose * _pstEvent); private: - int m_iRowStride; + double m_dScaleFactor; + int m_iAreaTop; + int m_iAreaLeft; u32 * m_puiPixels; u8 * m_puiDelta; + int m_iScaledWidth; + int m_iScaledHeight; void vUpdateSize(); + void vOnWidgetResize(); }; } // namespace VBA -#endif // __VBA_SCREENAREA_GTK_H__ +#endif // __VBA_SCREENAREA_CAIRO_H__ diff --git a/src/gtk/screenarea-gtk.cpp b/src/gtk/screenarea-gtk.cpp deleted file mode 100644 index 9400d12c..00000000 --- a/src/gtk/screenarea-gtk.cpp +++ /dev/null @@ -1,173 +0,0 @@ -// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator. -// Copyright (C) 1999-2003 Forgotten -// Copyright (C) 2004 Forgotten and the VBA development team - -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2, or(at your option) -// any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - -#include "screenarea-gtk.h" - -#include - -namespace VBA -{ - -ScreenAreaGtk::ScreenAreaGtk(int _iWidth, int _iHeight, int _iScale) : - ScreenArea(_iWidth, _iHeight, _iScale), - m_puiPixels(NULL), - m_puiDelta(NULL) -{ - vUpdateSize(); -} - -ScreenAreaGtk::~ScreenAreaGtk() -{ - if (m_puiPixels != NULL) - { - delete[] m_puiPixels; - } - - if (m_puiDelta != NULL) - { - delete[] m_puiDelta; - } -} - -void ScreenAreaGtk::vDrawPixels(u8 * _puiData) -{ - if (m_vFilterIB != NULL) - { - m_vFilterIB(_puiData + m_iAreaWidth * 2 + 4, - m_iAreaWidth * 2 + 4, - m_iWidth, - m_iHeight); - } - - if (m_iScale == 1) - { - u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1; - u32 * puiPixel = m_puiPixels; - for (int y = 0; y < m_iHeight; y++) - { - for (int x = 0; x < m_iWidth; x++) - { - *puiPixel++ = *puiSrc++; - } - puiSrc++; - } - } - else if (m_iScale == 2 && m_vFilter2x != NULL) - { - m_vFilter2x(_puiData + m_iAreaWidth * 2 + 4, - m_iAreaWidth * 2 + 4, - m_puiDelta, - (u8 *)m_puiPixels, - m_iRowStride, - m_iWidth, - m_iHeight); - } - else - { - u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1; - u32 * puiSrc2; - u32 * puiPixel = m_puiPixels; - for (int y = 0; y < m_iHeight; y++) - { - for (int j = 0; j < m_iScale; j++) - { - puiSrc2 = puiSrc; - for (int x = 0; x < m_iWidth; x++) - { - for (int i = 0; i < m_iScale; i++) - { - *puiPixel++ = *puiSrc2; - } - puiSrc2++; - } - } - puiSrc = puiSrc2 + 1; - } - } - - queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight); -} - -void ScreenAreaGtk::vDrawBlackScreen() -{ - u32 * puiPixel = m_puiPixels; - u32 * puiEnd = m_puiPixels + m_iAreaWidth * m_iAreaHeight; - while (puiPixel != puiEnd) - { - *puiPixel++ = 0; - } - - queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight); -} - -void ScreenAreaGtk::vUpdateSize() -{ - if (m_puiPixels != NULL) - { - delete[] m_puiPixels; - } - - if (m_puiDelta != NULL) - { - delete[] m_puiDelta; - } - - m_iAreaWidth = m_iScale * m_iWidth; - m_iAreaHeight = m_iScale * m_iHeight; - m_iRowStride = m_iAreaWidth * 4; - - m_puiPixels = new u32[m_iAreaWidth * m_iAreaHeight]; - - m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * 4]; - memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * 4); - - set_size_request(m_iAreaWidth, m_iAreaHeight); -} - -bool ScreenAreaGtk::on_expose_event(GdkEventExpose * _pstEvent) -{ - if (_pstEvent->area.x + _pstEvent->area.width > m_iAreaWidth - || _pstEvent->area.y + _pstEvent->area.height > m_iAreaHeight) - { - return false; - } - - guchar * puiAreaPixels = (guchar *)m_puiPixels; - - if (_pstEvent->area.x != 0) - { - puiAreaPixels += _pstEvent->area.x << 2; - } - - if (_pstEvent->area.y != 0) - { - puiAreaPixels += _pstEvent->area.y * m_iRowStride; - } - - get_window()->draw_rgb_32_image(get_style()->get_fg_gc(get_state()), - _pstEvent->area.x, - _pstEvent->area.y, - _pstEvent->area.width, - _pstEvent->area.height, - Gdk::RGB_DITHER_MAX, - puiAreaPixels, - m_iRowStride); - return true; -} - -} // namespace VBA diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 6445dd9b..e237d91c 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -33,7 +33,7 @@ #include "menuitem.h" #include "tools.h" #include "intl.h" -#include "screenarea-gtk.h" +#include "screenarea-cairo.h" #include "screenarea-xvideo.h" #ifdef USE_OPENGL @@ -89,7 +89,7 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr & _poXml) : m_iFilterIBMax (LastFilterIB), m_iJoypadMin (1), m_iJoypadMax (4), - m_iVideoOutputMin (OutputGtk), + m_iVideoOutputMin (OutputCairo), m_iVideoOutputMax (OutputXvideo) { m_poXml = _poXml; @@ -141,7 +141,7 @@ Window::Window(GtkWindow * _pstWindow, const Glib::RefPtr & _poXml) : astVideoOutput[] = { { "VideoOpenGL", OutputOpenGL }, - { "VideoCairo", OutputGtk }, + { "VideoCairo", OutputCairo }, { "VideoXv", OutputXvideo } }; EVideoOutput eDefaultVideoOutput = (EVideoOutput)m_poDisplayConfig->oGetKey("output"); @@ -892,7 +892,7 @@ void Window::vInitScreenArea(EVideoOutput _eVideoOutput) poC = dynamic_cast(m_poXml->get_widget("ScreenContainer")); poC->remove(); - poC->set(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 0.0, 0.0); + poC->set(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 1.0, 1.0); try { @@ -901,23 +901,21 @@ void Window::vInitScreenArea(EVideoOutput _eVideoOutput) #ifdef USE_OPENGL case OutputOpenGL: m_poScreenArea = Gtk::manage(new ScreenAreaGl(m_iScreenWidth, m_iScreenHeight)); - poC->set(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 1.0, 1.0); break; #endif // USE_OPENGL case OutputXvideo: m_poScreenArea = Gtk::manage(new ScreenAreaXv(m_iScreenWidth, m_iScreenHeight)); - poC->set(Gtk::ALIGN_CENTER, Gtk::ALIGN_CENTER, 1.0, 1.0); break; - case OutputGtk: + case OutputCairo: default: - m_poScreenArea = Gtk::manage(new ScreenAreaGtk(m_iScreenWidth, m_iScreenHeight)); + m_poScreenArea = Gtk::manage(new ScreenAreaCairo(m_iScreenWidth, m_iScreenHeight)); break; } } catch (std::exception e) { - fprintf(stderr, "Unable to initialise output, falling back to GTK+\n"); - m_poScreenArea = Gtk::manage(new ScreenAreaGtk(m_iScreenWidth, m_iScreenHeight)); + fprintf(stderr, "Unable to initialise output, falling back to Cairo\n"); + m_poScreenArea = Gtk::manage(new ScreenAreaCairo(m_iScreenWidth, m_iScreenHeight)); } poC->add(*m_poScreenArea); @@ -1039,7 +1037,7 @@ void Window::vInitConfig() #ifdef USE_OPENGL m_poDisplayConfig->vSetKey("output", OutputOpenGL ); #else - m_poDisplayConfig->vSetKey("output", OutputGtk ); + m_poDisplayConfig->vSetKey("output", OutputCairo ); #endif // USE_OPENGL diff --git a/src/gtk/window.h b/src/gtk/window.h index a1d71993..ba14c603 100644 --- a/src/gtk/window.h +++ b/src/gtk/window.h @@ -133,7 +133,7 @@ protected: enum EVideoOutput { - OutputGtk, + OutputCairo, OutputOpenGL, OutputXvideo };