]> git.saurik.com Git - wxWidgets.git/blob - tests/benchmarks/graphics.cpp
95965dc3fd65b415667f9725a8764c912ab8adec
[wxWidgets.git] / tests / benchmarks / graphics.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: graphics.cpp
3 // Purpose: Some benchmarks for measuring graphics operations performance
4 // Author: Vadim Zeitlin
5 // Created: 2008-04-13
6 // RCS-ID: $Id$
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #include "wx/app.h"
12 #include "wx/frame.h"
13 #include "wx/cmdline.h"
14 #include "wx/dcclient.h"
15 #include "wx/dcmemory.h"
16 #include "wx/dcgraph.h"
17 #include "wx/image.h"
18 #include "wx/rawbmp.h"
19 #include "wx/stopwatch.h"
20 #include "wx/crt.h"
21
22 struct GraphicsBenchmarkOptions
23 {
24 GraphicsBenchmarkOptions()
25 {
26 mapMode = 0;
27 penWidth = 0;
28
29 width = 800;
30 height = 600;
31
32 numLines = 10000;
33
34 testBitmaps =
35 testImages =
36 testLines =
37 testRawBitmaps =
38 testRectangles = false;
39
40 usePaint =
41 useClient =
42 useMemory = false;
43
44 useDC =
45 useGC = false;
46 }
47
48 long mapMode,
49 penWidth,
50 width,
51 height,
52 numLines;
53
54 bool testBitmaps,
55 testImages,
56 testLines,
57 testRawBitmaps,
58 testRectangles;
59
60 bool usePaint,
61 useClient,
62 useMemory;
63
64 bool useDC,
65 useGC;
66 } opts;
67
68 class GraphicsBenchmarkFrame : public wxFrame
69 {
70 public:
71 GraphicsBenchmarkFrame()
72 : wxFrame(NULL, wxID_ANY, "wxWidgets Graphics Benchmark")
73 {
74 Connect(wxEVT_PAINT,
75 wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint));
76
77 m_bitmap.Create(64, 64, 32);
78
79 Show();
80 SetClientSize(opts.width, opts.height);
81 }
82
83 private:
84 void OnPaint(wxPaintEvent& WXUNUSED(event))
85 {
86 if ( opts.usePaint )
87 {
88 wxPaintDC dc(this);
89 wxGCDC gcdc(dc);
90 BenchmarkDCAndGC("paint", dc, gcdc);
91 }
92
93 if ( opts.useClient )
94 {
95 wxClientDC dc(this);
96 wxGCDC gcdc(dc);
97 BenchmarkDCAndGC("client", dc, gcdc);
98 }
99
100 if ( opts.useMemory )
101 {
102 wxBitmap bmp(opts.width, opts.height);
103 wxMemoryDC dc(bmp);
104 wxGCDC gcdc(dc);
105 BenchmarkDCAndGC("memory", dc, gcdc);
106 }
107
108 wxTheApp->ExitMainLoop();
109 }
110
111 void BenchmarkDCAndGC(const char* dckind, wxDC& dc, wxGCDC& gcdc)
112 {
113 if ( opts.useDC )
114 BenchmarkAll(wxString::Format("%6s DC", dckind), dc);
115 if ( opts.useGC )
116 BenchmarkAll(wxString::Format("%6s GC", dckind), gcdc);
117 }
118
119 void BenchmarkAll(const wxString& msg, wxDC& dc)
120 {
121 BenchmarkBitmaps(msg, dc);
122 BenchmarkImages(msg, dc);
123 BenchmarkLines(msg, dc);
124 BenchmarkRawBitmaps(msg, dc);
125 BenchmarkRectangles(msg, dc);
126 }
127
128 void BenchmarkLines(const wxString& msg, wxDC& dc)
129 {
130 if ( !opts.testLines )
131 return;
132
133 if ( opts.mapMode != 0 )
134 dc.SetMapMode((wxMappingMode)opts.mapMode);
135 if ( opts.penWidth != 0 )
136 dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
137
138 wxPrintf("Benchmarking %s: ", msg);
139 fflush(stdout);
140
141 wxStopWatch sw;
142 int x = 0,
143 y = 0;
144 for ( int n = 0; n < opts.numLines; n++ )
145 {
146 int x1 = rand() % opts.width,
147 y1 = rand() % opts.height;
148
149 dc.DrawLine(x, y, x1, y1);
150
151 x = x1;
152 y = y1;
153 }
154
155 const long t = sw.Time();
156
157 wxPrintf("%ld lines done in %ldms = %gus/line\n",
158 opts.numLines, t, (1000. * t)/opts.numLines);
159 }
160
161
162 void BenchmarkRectangles(const wxString& msg, wxDC& dc)
163 {
164 if ( !opts.testRectangles )
165 return;
166
167 if ( opts.mapMode != 0 )
168 dc.SetMapMode((wxMappingMode)opts.mapMode);
169 if ( opts.penWidth != 0 )
170 dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
171
172 dc.SetBrush( *wxRED_BRUSH );
173
174 wxPrintf("Benchmarking %s: ", msg);
175 fflush(stdout);
176
177 wxStopWatch sw;
178 for ( int n = 0; n < opts.numLines; n++ )
179 {
180 int x = rand() % opts.width,
181 y = rand() % opts.height;
182
183 dc.DrawRectangle(x, y, 32, 32);
184 }
185
186 const long t = sw.Time();
187
188 wxPrintf("%ld rects done in %ldms = %gus/rect\n",
189 opts.numLines, t, (1000. * t)/opts.numLines);
190 }
191
192 void BenchmarkBitmaps(const wxString& msg, wxDC& dc)
193 {
194 if ( !opts.testBitmaps )
195 return;
196
197 if ( opts.mapMode != 0 )
198 dc.SetMapMode((wxMappingMode)opts.mapMode);
199 if ( opts.penWidth != 0 )
200 dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
201
202 wxPrintf("Benchmarking %s: ", msg);
203 fflush(stdout);
204
205 wxStopWatch sw;
206 for ( int n = 0; n < opts.numLines; n++ )
207 {
208 int x = rand() % opts.width,
209 y = rand() % opts.height;
210
211 dc.DrawBitmap(m_bitmap, x, y, true);
212 }
213
214 const long t = sw.Time();
215
216 wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
217 opts.numLines, t, (1000. * t)/opts.numLines);
218 }
219
220 void BenchmarkImages(const wxString& msg, wxDC& dc)
221 {
222 if ( !opts.testImages )
223 return;
224
225 if ( opts.mapMode != 0 )
226 dc.SetMapMode((wxMappingMode)opts.mapMode);
227
228 wxPrintf("Benchmarking %s: ", msg);
229 fflush(stdout);
230
231 wxImage image(wxSize(opts.width, opts.height), false /* don't clear */);
232
233 wxStopWatch sw;
234 const int numImages = opts.numLines;
235 for ( int n = 0; n < numImages; n++ )
236 {
237 image.Clear(n % 256);
238 dc.DrawBitmap(image, 0, 0);
239 }
240
241 const long t = sw.Time();
242
243 wxPrintf("%ld images done in %ldms = %gus/image or %d FPS\n",
244 numImages, t, (1000. * t)/numImages,
245 (1000*numImages + t - 1)/t);
246 }
247
248 void BenchmarkRawBitmaps(const wxString& msg, wxDC& dc)
249 {
250 if ( !opts.testRawBitmaps )
251 return;
252
253 if ( opts.mapMode != 0 )
254 dc.SetMapMode((wxMappingMode)opts.mapMode);
255
256 wxPrintf("Benchmarking %s: ", msg);
257 fflush(stdout);
258
259 wxBitmap bitmap(opts.width, opts.height, 24);
260 wxNativePixelData data(bitmap);
261
262 wxStopWatch sw;
263 const int numImages = opts.numLines;
264 for ( int n = 0; n < numImages; n++ )
265 {
266 const unsigned char c = n % 256;
267 {
268 wxNativePixelData::Iterator p(data);
269 for ( int y = 0; y < opts.height; ++y )
270 {
271 wxNativePixelData::Iterator rowStart = p;
272
273 for ( int x = 0; x < opts.width; ++x )
274 {
275 p.Red() =
276 p.Green() =
277 p.Blue() = c;
278 ++p;
279 }
280
281 p = rowStart;
282 p.OffsetY(data, 1);
283 }
284 }
285
286 dc.DrawBitmap(bitmap, 0, 0);
287 }
288
289 const long t = sw.Time();
290
291 wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %d FPS\n",
292 numImages, t, (1000. * t)/numImages,
293 (1000*numImages + t - 1)/t);
294 }
295
296
297 wxBitmap m_bitmap;
298 };
299
300 class GraphicsBenchmarkApp : public wxApp
301 {
302 public:
303 virtual void OnInitCmdLine(wxCmdLineParser& parser)
304 {
305 static const wxCmdLineEntryDesc desc[] =
306 {
307 { wxCMD_LINE_SWITCH, "", "bitmaps" },
308 { wxCMD_LINE_SWITCH, "", "images" },
309 { wxCMD_LINE_SWITCH, "", "lines" },
310 { wxCMD_LINE_SWITCH, "", "rawbmp" },
311 { wxCMD_LINE_SWITCH, "", "rectangles" },
312 { wxCMD_LINE_SWITCH, "", "paint" },
313 { wxCMD_LINE_SWITCH, "", "client" },
314 { wxCMD_LINE_SWITCH, "", "memory" },
315 { wxCMD_LINE_SWITCH, "", "dc" },
316 { wxCMD_LINE_SWITCH, "", "gc" },
317 { wxCMD_LINE_OPTION, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER },
318 { wxCMD_LINE_OPTION, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER },
319 { wxCMD_LINE_OPTION, "w", "width", "", wxCMD_LINE_VAL_NUMBER },
320 { wxCMD_LINE_OPTION, "h", "height", "", wxCMD_LINE_VAL_NUMBER },
321 { wxCMD_LINE_OPTION, "L", "lines", "", wxCMD_LINE_VAL_NUMBER },
322 { wxCMD_LINE_NONE },
323 };
324
325 parser.SetDesc(desc);
326 }
327
328 virtual bool OnCmdLineParsed(wxCmdLineParser& parser)
329 {
330 if ( parser.Found("m", &opts.mapMode) &&
331 (opts.mapMode < 1 || opts.mapMode > wxMM_METRIC) )
332 return false;
333 if ( parser.Found("p", &opts.penWidth) && opts.penWidth < 1 )
334 return false;
335 if ( parser.Found("w", &opts.width) && opts.width < 1 )
336 return false;
337 if ( parser.Found("h", &opts.height) && opts.height < 1 )
338 return false;
339 if ( parser.Found("L", &opts.numLines) && opts.numLines < 1 )
340 return false;
341
342 opts.testBitmaps = parser.Found("bitmaps");
343 opts.testImages = parser.Found("images");
344 opts.testLines = parser.Found("lines");
345 opts.testRawBitmaps = parser.Found("rawbmp");
346 opts.testRectangles = parser.Found("rectangles");
347 if ( !(opts.testBitmaps || opts.testImages || opts.testLines
348 || opts.testRawBitmaps || opts.testRectangles) )
349 {
350 // Do everything by default.
351 opts.testBitmaps =
352 opts.testImages =
353 opts.testLines =
354 opts.testRawBitmaps =
355 opts.testRectangles = true;
356 }
357
358 opts.usePaint = parser.Found("paint");
359 opts.useClient = parser.Found("client");
360 opts.useMemory = parser.Found("memory");
361 if ( !(opts.usePaint || opts.useClient || opts.useMemory) )
362 {
363 opts.usePaint =
364 opts.useClient =
365 opts.useMemory = true;
366 }
367
368 opts.useDC = parser.Found("dc");
369 opts.useGC = parser.Found("gc");
370 if ( !(opts.useDC || opts.useGC) )
371 {
372 opts.useDC =
373 opts.useGC = true;
374 }
375
376 return true;
377 }
378
379 virtual bool OnInit()
380 {
381 if ( !wxApp::OnInit() )
382 return false;
383
384 new GraphicsBenchmarkFrame;
385
386 return true;
387 }
388 };
389
390 IMPLEMENT_APP_CONSOLE(GraphicsBenchmarkApp)