1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
19 #include "screenarea.h"
20
21 #include <cstring>
22
23 namespace VBA
24 {
25
ScreenArea(int _iWidth,int _iHeight,int _iScale)26 ScreenArea::ScreenArea(int _iWidth, int _iHeight, int _iScale) :
27 m_iFilterScale(1),
28 m_vFilter2x(NULL),
29 m_vFilterIB(NULL),
30 m_puiPixels(NULL),
31 m_puiDelta(NULL),
32 m_iScaledWidth(_iWidth),
33 m_iScaledHeight(_iHeight),
34 m_bEnableRender(true),
35 m_bShowCursor(true)
36 {
37 g_assert(_iWidth >= 1 && _iHeight >= 1 && _iScale >= 1);
38
39 m_iWidth = _iWidth;
40 m_iHeight = _iHeight;
41 m_iScale = _iScale;
42
43 set_events(Gdk::EXPOSURE_MASK
44 | Gdk::POINTER_MOTION_MASK
45 | Gdk::ENTER_NOTIFY_MASK
46 | Gdk::LEAVE_NOTIFY_MASK);
47
48 char aiEmptyData[8];
49 memset(aiEmptyData, 0, sizeof(aiEmptyData));
50 Glib::RefPtr<Gdk::Bitmap> poSource = Gdk::Bitmap::create(aiEmptyData, 8, 8);
51 Glib::RefPtr<Gdk::Bitmap> poMask = Gdk::Bitmap::create(aiEmptyData, 8, 8);
52 Gdk::Color oFg;
53 Gdk::Color oBg;
54 oFg.set_rgb(0, 0, 0);
55 oBg.set_rgb(0, 0, 0);
56
57 m_poEmptyCursor = new Gdk::Cursor(poSource, poMask, oFg, oBg, 0, 0);
58 }
59
~ScreenArea()60 ScreenArea::~ScreenArea()
61 {
62 if (m_puiPixels)
63 {
64 delete[] m_puiPixels;
65 }
66
67 if (m_puiDelta)
68 {
69 delete[] m_puiDelta;
70 }
71
72 if (m_poEmptyCursor != NULL)
73 {
74 delete m_poEmptyCursor;
75 }
76 }
77
vSetSize(int _iWidth,int _iHeight)78 void ScreenArea::vSetSize(int _iWidth, int _iHeight)
79 {
80 g_return_if_fail(_iWidth >= 1 && _iHeight >= 1);
81
82 if (_iWidth != m_iWidth || _iHeight != m_iHeight)
83 {
84 m_iWidth = _iWidth;
85 m_iHeight = _iHeight;
86 vUpdateSize();
87 }
88 }
89
vSetScale(int _iScale)90 void ScreenArea::vSetScale(int _iScale)
91 {
92 g_return_if_fail(_iScale >= 1);
93
94 if (_iScale == 1)
95 {
96 vSetFilter(FilterNone);
97 }
98
99 m_iScale = _iScale;
100 vUpdateSize();
101 }
102
vSetFilter(EFilter _eFilter)103 void ScreenArea::vSetFilter(EFilter _eFilter)
104 {
105 m_vFilter2x = pvGetFilter(_eFilter, FilterDepth32);
106
107 m_iFilterScale = 1;
108 if (m_vFilter2x != NULL)
109 {
110 m_iFilterScale = 2;
111 }
112
113 vUpdateSize();
114 }
115
vSetFilterIB(EFilterIB _eFilterIB)116 void ScreenArea::vSetFilterIB(EFilterIB _eFilterIB)
117 {
118 m_vFilterIB = pvGetFilterIB(_eFilterIB, FilterDepth32);
119 }
120
vStartCursorTimeout()121 void ScreenArea::vStartCursorTimeout()
122 {
123 m_oCursorSig.disconnect();
124 m_oCursorSig = Glib::signal_timeout().connect(
125 sigc::mem_fun(*this, &ScreenArea::bOnCursorTimeout),
126 2000);
127 }
128
vStopCursorTimeout()129 void ScreenArea::vStopCursorTimeout()
130 {
131 m_oCursorSig.disconnect();
132 }
133
vHideCursor()134 void ScreenArea::vHideCursor()
135 {
136 get_window()->set_cursor(*m_poEmptyCursor);
137 m_bShowCursor = false;
138 }
139
vShowCursor()140 void ScreenArea::vShowCursor()
141 {
142 get_window()->set_cursor();
143 m_bShowCursor = true;
144 }
145
on_motion_notify_event(GdkEventMotion * _pstEvent)146 bool ScreenArea::on_motion_notify_event(GdkEventMotion * _pstEvent)
147 {
148 if (! m_bShowCursor)
149 {
150 vShowCursor();
151 }
152 vStartCursorTimeout();
153 return false;
154 }
155
on_enter_notify_event(GdkEventCrossing * _pstEvent)156 bool ScreenArea::on_enter_notify_event(GdkEventCrossing * _pstEvent)
157 {
158 vStartCursorTimeout();
159 return false;
160 }
161
on_leave_notify_event(GdkEventCrossing * _pstEvent)162 bool ScreenArea::on_leave_notify_event(GdkEventCrossing * _pstEvent)
163 {
164 vStopCursorTimeout();
165 if (! m_bShowCursor)
166 {
167 vShowCursor();
168 }
169 return false;
170 }
171
bOnCursorTimeout()172 bool ScreenArea::bOnCursorTimeout()
173 {
174 vHideCursor();
175 return false;
176 }
177
vDrawPixels(u8 * _puiData)178 void ScreenArea::vDrawPixels(u8 * _puiData)
179 {
180 const int iSrcPitch = (m_iWidth + 1) * sizeof(u32);
181 const int iScaledPitch = (m_iScaledWidth + 1) * sizeof(u32);
182
183 if (m_vFilterIB != NULL)
184 {
185 m_vFilterIB(_puiData + iSrcPitch,
186 iSrcPitch,
187 m_iWidth,
188 m_iHeight);
189 }
190
191 if (m_vFilter2x != NULL)
192 {
193 m_vFilter2x(_puiData + iSrcPitch,
194 iSrcPitch,
195 m_puiDelta,
196 (u8 *)m_puiPixels,
197 iScaledPitch,
198 m_iWidth,
199 m_iHeight);
200 }
201 else
202 {
203 memcpy(m_puiPixels, _puiData + iSrcPitch, m_iHeight * iSrcPitch);
204 }
205 }
206
vUpdateSize()207 void ScreenArea::vUpdateSize()
208 {
209 if (m_puiPixels)
210 {
211 delete[] m_puiPixels;
212 }
213
214 if (m_puiDelta)
215 {
216 delete[] m_puiDelta;
217 }
218
219 m_iScaledWidth = m_iFilterScale * m_iWidth;
220 m_iScaledHeight = m_iFilterScale * m_iHeight;
221
222 m_puiPixels = new u32[(m_iScaledWidth + 1) * m_iScaledHeight];
223 m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * sizeof(u32)];
224 memset(m_puiPixels, 0, (m_iScaledWidth + 1) * m_iScaledHeight * sizeof(u32));
225 memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * sizeof(u32));
226
227 vOnSizeUpdated();
228
229 set_size_request(m_iScale * m_iWidth, m_iScale * m_iHeight);
230 }
231
on_configure_event(GdkEventConfigure * event)232 bool ScreenArea::on_configure_event(GdkEventConfigure * event)
233 {
234 vOnWidgetResize();
235
236 return true;
237 }
238
vSetEnableRender(bool _bEnable)239 void ScreenArea::vSetEnableRender(bool _bEnable)
240 {
241 m_bEnableRender = _bEnable;
242 }
243
244 } // namespace VBA
245