1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: Some benchmarks for measuring graphics operations performance
4 // Author: Vadim Zeitlin
7 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
13 #include "wx/cmdline.h"
14 #include "wx/dcclient.h"
15 #include "wx/dcmemory.h"
16 #include "wx/dcgraph.h"
18 #include "wx/rawbmp.h"
19 #include "wx/stopwatch.h"
22 struct GraphicsBenchmarkOptions
24 GraphicsBenchmarkOptions()
38 testRectangles
= false;
68 class GraphicsBenchmarkFrame
: public wxFrame
71 GraphicsBenchmarkFrame()
72 : wxFrame(NULL
, wxID_ANY
, "wxWidgets Graphics Benchmark")
75 wxPaintEventHandler(GraphicsBenchmarkFrame
::OnPaint
));
77 m_bitmap
.Create(64, 64, 32);
80 SetClientSize(opts
.width
, opts
.height
);
84 // Just change the image in some (quick) way to show that it's really being
86 void UpdateRGB(unsigned char* data
, int n
)
88 for ( int y
= 0; y
< opts
.height
; ++y
)
90 memset(data
, n
% 256, 3*opts
.width
);
96 void OnPaint(wxPaintEvent
& WXUNUSED(event
))
102 BenchmarkDCAndGC("paint", dc
, gcdc
);
105 if ( opts
.useClient
)
109 BenchmarkDCAndGC("client", dc
, gcdc
);
112 if ( opts
.useMemory
)
114 wxBitmap
bmp(opts
.width
, opts
.height
);
117 BenchmarkDCAndGC("memory", dc
, gcdc
);
120 wxTheApp
->ExitMainLoop();
123 void BenchmarkDCAndGC(const char* dckind
, wxDC
& dc
, wxGCDC
& gcdc
)
126 BenchmarkAll(wxString
::Format("%6s DC", dckind
), dc
);
128 BenchmarkAll(wxString
::Format("%6s GC", dckind
), gcdc
);
131 void BenchmarkAll(const wxString
& msg
, wxDC
& dc
)
133 BenchmarkBitmaps(msg
, dc
);
134 BenchmarkImages(msg
, dc
);
135 BenchmarkLines(msg
, dc
);
136 BenchmarkRawBitmaps(msg
, dc
);
137 BenchmarkRectangles(msg
, dc
);
140 void BenchmarkLines(const wxString
& msg
, wxDC
& dc
)
142 if ( !opts
.testLines
)
145 if ( opts
.mapMode
!= 0 )
146 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
147 if ( opts
.penWidth
!= 0 )
148 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
150 wxPrintf("Benchmarking %s: ", msg
);
156 for ( int n
= 0; n
< opts
.numIters
; n
++ )
158 int x1
= rand() % opts
.width
,
159 y1
= rand() % opts
.height
;
161 dc
.DrawLine(x
, y
, x1
, y1
);
167 const long t
= sw
.Time();
169 wxPrintf("%ld lines done in %ldms = %gus/line\n",
170 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
174 void BenchmarkRectangles(const wxString
& msg
, wxDC
& dc
)
176 if ( !opts
.testRectangles
)
179 if ( opts
.mapMode
!= 0 )
180 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
181 if ( opts
.penWidth
!= 0 )
182 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
184 dc
.SetBrush( *wxRED_BRUSH
);
186 wxPrintf("Benchmarking %s: ", msg
);
190 for ( int n
= 0; n
< opts
.numIters
; n
++ )
192 int x
= rand() % opts
.width
,
193 y
= rand() % opts
.height
;
195 dc
.DrawRectangle(x
, y
, 32, 32);
198 const long t
= sw
.Time();
200 wxPrintf("%ld rects done in %ldms = %gus/rect\n",
201 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
204 void BenchmarkBitmaps(const wxString
& msg
, wxDC
& dc
)
206 if ( !opts
.testBitmaps
)
209 if ( opts
.mapMode
!= 0 )
210 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
211 if ( opts
.penWidth
!= 0 )
212 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
214 wxPrintf("Benchmarking %s: ", msg
);
218 for ( int n
= 0; n
< opts
.numIters
; n
++ )
220 int x
= rand() % opts
.width
,
221 y
= rand() % opts
.height
;
223 dc
.DrawBitmap(m_bitmap
, x
, y
, true);
226 const long t
= sw
.Time();
228 wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
229 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
232 void BenchmarkImages(const wxString
& msg
, wxDC
& dc
)
234 if ( !opts
.testImages
)
237 if ( opts
.mapMode
!= 0 )
238 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
240 wxPrintf("Benchmarking %s: ", msg
);
243 wxImage
image(wxSize(opts
.width
, opts
.height
), false /* don't clear */);
246 for ( int n
= 0; n
< opts
.numIters
; n
++ )
248 UpdateRGB(image
.GetData(), n
);
249 dc
.DrawBitmap(image
, 0, 0);
252 const long t
= sw
.Time();
254 wxPrintf("%ld images done in %ldms = %gus/image or %d FPS\n",
255 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
256 (1000*opts
.numIters
+ t
- 1)/t
);
259 void BenchmarkRawBitmaps(const wxString
& msg
, wxDC
& dc
)
261 if ( !opts
.testRawBitmaps
)
264 if ( opts
.mapMode
!= 0 )
265 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
267 wxPrintf("Benchmarking %s: ", msg
);
270 wxBitmap
bitmap(opts
.width
, opts
.height
, 24);
271 wxNativePixelData
data(bitmap
);
274 for ( int n
= 0; n
< opts
.numIters
; n
++ )
276 unsigned char c
= n
% 256;
278 wxNativePixelData
::Iterator
p(data
);
279 for ( int y
= 0; y
< opts
.height
; ++y
)
281 wxNativePixelData
::Iterator rowStart
= p
;
283 for ( int x
= 0; x
< opts
.width
; ++x
)
297 dc
.DrawBitmap(bitmap
, 0, 0);
300 const long t
= sw
.Time();
302 wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %d FPS\n",
303 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
304 (1000*opts
.numIters
+ t
- 1)/t
);
311 class GraphicsBenchmarkApp
: public wxApp
314 virtual void OnInitCmdLine(wxCmdLineParser
& parser
)
316 static const wxCmdLineEntryDesc desc
[] =
318 { wxCMD_LINE_SWITCH
, "", "bitmaps" },
319 { wxCMD_LINE_SWITCH
, "", "images" },
320 { wxCMD_LINE_SWITCH
, "", "lines" },
321 { wxCMD_LINE_SWITCH
, "", "rawbmp" },
322 { wxCMD_LINE_SWITCH
, "", "rectangles" },
323 { wxCMD_LINE_SWITCH
, "", "paint" },
324 { wxCMD_LINE_SWITCH
, "", "client" },
325 { wxCMD_LINE_SWITCH
, "", "memory" },
326 { wxCMD_LINE_SWITCH
, "", "dc" },
327 { wxCMD_LINE_SWITCH
, "", "gc" },
328 { wxCMD_LINE_OPTION
, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER
},
329 { wxCMD_LINE_OPTION
, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER
},
330 { wxCMD_LINE_OPTION
, "w", "width", "", wxCMD_LINE_VAL_NUMBER
},
331 { wxCMD_LINE_OPTION
, "h", "height", "", wxCMD_LINE_VAL_NUMBER
},
332 { wxCMD_LINE_OPTION
, "I", "images", "", wxCMD_LINE_VAL_NUMBER
},
333 { wxCMD_LINE_OPTION
, "N", "number-of-iterations", "", wxCMD_LINE_VAL_NUMBER
},
337 parser
.SetDesc(desc
);
340 virtual bool OnCmdLineParsed(wxCmdLineParser
& parser
)
342 if ( parser
.Found("m", &opts
.mapMode
) &&
343 (opts
.mapMode
< 1 || opts
.mapMode
> wxMM_METRIC
) )
345 if ( parser
.Found("p", &opts
.penWidth
) && opts
.penWidth
< 1 )
347 if ( parser
.Found("w", &opts
.width
) && opts
.width
< 1 )
349 if ( parser
.Found("h", &opts
.height
) && opts
.height
< 1 )
351 if ( parser
.Found("N", &opts
.numIters
) && opts
.numIters
< 1 )
354 opts
.testBitmaps
= parser
.Found("bitmaps");
355 opts
.testImages
= parser
.Found("images");
356 opts
.testLines
= parser
.Found("lines");
357 opts
.testRawBitmaps
= parser
.Found("rawbmp");
358 opts
.testRectangles
= parser
.Found("rectangles");
359 if ( !(opts
.testBitmaps
|| opts
.testImages
|| opts
.testLines
360 || opts
.testRawBitmaps
|| opts
.testRectangles
) )
362 // Do everything by default.
366 opts
.testRawBitmaps
=
367 opts
.testRectangles
= true;
370 opts
.usePaint
= parser
.Found("paint");
371 opts
.useClient
= parser
.Found("client");
372 opts
.useMemory
= parser
.Found("memory");
373 if ( !(opts
.usePaint
|| opts
.useClient
|| opts
.useMemory
) )
377 opts
.useMemory
= true;
380 opts
.useDC
= parser
.Found("dc");
381 opts
.useGC
= parser
.Found("gc");
382 if ( !(opts
.useDC
|| opts
.useGC
) )
391 virtual bool OnInit()
393 if ( !wxApp
::OnInit() )
396 new GraphicsBenchmarkFrame
;
402 IMPLEMENT_APP_CONSOLE(GraphicsBenchmarkApp
)