]>
git.saurik.com Git - wxWidgets.git/blob - tests/benchmarks/graphics.cpp
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"
23 #include "wx/glcanvas.h"
25 #pragma comment(lib, "opengl32")
27 #endif // wxUSE_GLCANVAS
34 void InitializeTexture(int w
, int h
)
36 glGenTextures(1, &g_texture
);
37 glBindTexture(GL_TEXTURE_2D
, g_texture
);
39 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
41 g_image
.Create(w
, h
, false /* don't clear */);
42 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
43 glTexImage2D(GL_TEXTURE_2D
, 0,
44 GL_RGB
, g_image
.GetWidth(), g_image
.GetHeight(), 0,
45 GL_RGB
, GL_UNSIGNED_BYTE
, g_image
.GetData());
47 #endif // wxUSE_GLCANVAS
49 struct GraphicsBenchmarkOptions
51 GraphicsBenchmarkOptions()
65 testRectangles
= false;
97 class GraphicsBenchmarkFrame
: public wxFrame
100 GraphicsBenchmarkFrame()
101 : wxFrame(NULL
, wxID_ANY
, "wxWidgets Graphics Benchmark")
103 SetClientSize(opts
.width
, opts
.height
);
110 m_glCanvas
= new wxGLCanvas(this, wxID_ANY
, NULL
,
112 wxSize(opts
.width
, opts
.height
));
113 m_glContext
= new wxGLContext(m_glCanvas
);
114 m_glContext
->SetCurrent(*m_glCanvas
);
116 glViewport(0, 0, opts
.width
, opts
.height
);
117 glMatrixMode(GL_PROJECTION
);
119 glOrtho(-1, 1, -1, 1, -1, 1);
120 glMatrixMode(GL_MODELVIEW
);
123 InitializeTexture(opts
.width
, opts
.height
);
127 wxPaintEventHandler(GraphicsBenchmarkFrame::OnGLRender
),
132 else // Not using OpenGL
133 #endif // wxUSE_GLCANVAS
136 wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint
));
139 Connect(wxEVT_SIZE
, wxSizeEventHandler(GraphicsBenchmarkFrame::OnSize
));
141 m_bitmap
.Create(64, 64, 32);
147 virtual ~GraphicsBenchmarkFrame()
151 #endif // wxUSE_GLCANVAS
154 // Just change the image in some (quick) way to show that it's really being
155 // updated on screen.
156 void UpdateRGB(unsigned char* data
, int n
)
158 for ( int y
= 0; y
< opts
.height
; ++y
)
160 memset(data
, n
% 256, 3*opts
.width
);
162 data
+= 3*opts
.width
;
168 void OnGLRender(wxPaintEvent
& WXUNUSED(event
))
170 m_glContext
->SetCurrent(*m_glCanvas
);
171 glEnable(GL_TEXTURE_2D
);
173 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
174 glClear(GL_COLOR_BUFFER_BIT
);
176 wxPrintf("Benchmarking %s: ", "OpenGL images");
180 for ( int n
= 0; n
< opts
.numIters
; n
++ )
182 UpdateRGB(g_image
.GetData(), n
);
184 glTexSubImage2D(GL_TEXTURE_2D
, 0,
185 0, 0, opts
.width
, opts
.height
,
186 GL_RGB
, GL_UNSIGNED_BYTE
, g_image
.GetData());
189 glVertex2f(-1.0, -1.0);
192 glVertex2f(-1.0, 1.0);
195 glVertex2f(1.0, 1.0);
198 glVertex2f(1.0, -1.0);
201 m_glCanvas
->SwapBuffers();
204 const long t
= sw
.Time();
206 wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
207 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
208 (1000*opts
.numIters
+ t
- 1)/t
);
210 wxTheApp
->ExitMainLoop();
212 #endif // wxUSE_GLCANVAS
214 void OnPaint(wxPaintEvent
& WXUNUSED(event
))
220 BenchmarkDCAndGC("paint", dc
, gcdc
);
223 if ( opts
.useClient
)
227 BenchmarkDCAndGC("client", dc
, gcdc
);
230 if ( opts
.useMemory
)
232 wxBitmap
bmp(opts
.width
, opts
.height
);
235 BenchmarkDCAndGC("memory", dc
, gcdc
);
238 wxTheApp
->ExitMainLoop();
241 void BenchmarkDCAndGC(const char* dckind
, wxDC
& dc
, wxGCDC
& gcdc
)
244 BenchmarkAll(wxString::Format("%6s DC", dckind
), dc
);
246 BenchmarkAll(wxString::Format("%6s GC", dckind
), gcdc
);
249 void BenchmarkAll(const wxString
& msg
, wxDC
& dc
)
251 BenchmarkBitmaps(msg
, dc
);
252 BenchmarkImages(msg
, dc
);
253 BenchmarkLines(msg
, dc
);
254 BenchmarkRawBitmaps(msg
, dc
);
255 BenchmarkRectangles(msg
, dc
);
258 void BenchmarkLines(const wxString
& msg
, wxDC
& dc
)
260 if ( !opts
.testLines
)
263 if ( opts
.mapMode
!= 0 )
264 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
265 if ( opts
.penWidth
!= 0 )
266 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
268 wxPrintf("Benchmarking %s: ", msg
);
274 for ( int n
= 0; n
< opts
.numIters
; n
++ )
276 int x1
= rand() % opts
.width
,
277 y1
= rand() % opts
.height
;
279 dc
.DrawLine(x
, y
, x1
, y1
);
285 const long t
= sw
.Time();
287 wxPrintf("%ld lines done in %ldms = %gus/line\n",
288 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
292 void BenchmarkRectangles(const wxString
& msg
, wxDC
& dc
)
294 if ( !opts
.testRectangles
)
297 if ( opts
.mapMode
!= 0 )
298 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
299 if ( opts
.penWidth
!= 0 )
300 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
302 dc
.SetBrush( *wxRED_BRUSH
);
304 wxPrintf("Benchmarking %s: ", msg
);
308 for ( int n
= 0; n
< opts
.numIters
; n
++ )
310 int x
= rand() % opts
.width
,
311 y
= rand() % opts
.height
;
313 dc
.DrawRectangle(x
, y
, 32, 32);
316 const long t
= sw
.Time();
318 wxPrintf("%ld rects done in %ldms = %gus/rect\n",
319 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
322 void BenchmarkBitmaps(const wxString
& msg
, wxDC
& dc
)
324 if ( !opts
.testBitmaps
)
327 if ( opts
.mapMode
!= 0 )
328 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
329 if ( opts
.penWidth
!= 0 )
330 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
332 wxPrintf("Benchmarking %s: ", msg
);
336 for ( int n
= 0; n
< opts
.numIters
; n
++ )
338 int x
= rand() % opts
.width
,
339 y
= rand() % opts
.height
;
341 dc
.DrawBitmap(m_bitmap
, x
, y
, true);
344 const long t
= sw
.Time();
346 wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
347 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
350 void BenchmarkImages(const wxString
& msg
, wxDC
& dc
)
352 if ( !opts
.testImages
)
355 if ( opts
.mapMode
!= 0 )
356 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
358 wxPrintf("Benchmarking %s: ", msg
);
361 wxImage
image(wxSize(opts
.width
, opts
.height
), false /* don't clear */);
364 for ( int n
= 0; n
< opts
.numIters
; n
++ )
366 UpdateRGB(image
.GetData(), n
);
367 dc
.DrawBitmap(image
, 0, 0);
370 const long t
= sw
.Time();
372 wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
373 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
374 (1000*opts
.numIters
+ t
- 1)/t
);
377 void BenchmarkRawBitmaps(const wxString
& msg
, wxDC
& dc
)
379 if ( !opts
.testRawBitmaps
)
382 if ( opts
.mapMode
!= 0 )
383 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
385 wxPrintf("Benchmarking %s: ", msg
);
388 wxBitmap
bitmap(opts
.width
, opts
.height
, 24);
389 wxNativePixelData
data(bitmap
);
392 for ( int n
= 0; n
< opts
.numIters
; n
++ )
394 unsigned char c
= n
% 256;
396 wxNativePixelData::Iterator
p(data
);
397 for ( int y
= 0; y
< opts
.height
; ++y
)
399 wxNativePixelData::Iterator rowStart
= p
;
401 for ( int x
= 0; x
< opts
.width
; ++x
)
415 dc
.DrawBitmap(bitmap
, 0, 0);
418 const long t
= sw
.Time();
420 wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %ld FPS\n",
421 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
422 (1000*opts
.numIters
+ t
- 1)/t
);
428 wxGLCanvas
* m_glCanvas
;
429 wxGLContext
* m_glContext
;
430 #endif // wxUSE_GLCANVAS
433 class GraphicsBenchmarkApp
: public wxApp
436 virtual void OnInitCmdLine(wxCmdLineParser
& parser
)
438 static const wxCmdLineEntryDesc desc
[] =
440 { wxCMD_LINE_SWITCH
, "", "bitmaps" },
441 { wxCMD_LINE_SWITCH
, "", "images" },
442 { wxCMD_LINE_SWITCH
, "", "lines" },
443 { wxCMD_LINE_SWITCH
, "", "rawbmp" },
444 { wxCMD_LINE_SWITCH
, "", "rectangles" },
445 { wxCMD_LINE_SWITCH
, "", "paint" },
446 { wxCMD_LINE_SWITCH
, "", "client" },
447 { wxCMD_LINE_SWITCH
, "", "memory" },
448 { wxCMD_LINE_SWITCH
, "", "dc" },
449 { wxCMD_LINE_SWITCH
, "", "gc" },
451 { wxCMD_LINE_SWITCH
, "", "gl" },
452 #endif // wxUSE_GLCANVAS
453 { wxCMD_LINE_OPTION
, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER
},
454 { wxCMD_LINE_OPTION
, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER
},
455 { wxCMD_LINE_OPTION
, "w", "width", "", wxCMD_LINE_VAL_NUMBER
},
456 { wxCMD_LINE_OPTION
, "h", "height", "", wxCMD_LINE_VAL_NUMBER
},
457 { wxCMD_LINE_OPTION
, "I", "images", "", wxCMD_LINE_VAL_NUMBER
},
458 { wxCMD_LINE_OPTION
, "N", "number-of-iterations", "", wxCMD_LINE_VAL_NUMBER
},
462 parser
.SetDesc(desc
);
465 virtual bool OnCmdLineParsed(wxCmdLineParser
& parser
)
467 if ( parser
.Found("m", &opts
.mapMode
) &&
468 (opts
.mapMode
< 1 || opts
.mapMode
> wxMM_METRIC
) )
470 if ( parser
.Found("p", &opts
.penWidth
) && opts
.penWidth
< 1 )
472 if ( parser
.Found("w", &opts
.width
) && opts
.width
< 1 )
474 if ( parser
.Found("h", &opts
.height
) && opts
.height
< 1 )
476 if ( parser
.Found("N", &opts
.numIters
) && opts
.numIters
< 1 )
479 opts
.testBitmaps
= parser
.Found("bitmaps");
480 opts
.testImages
= parser
.Found("images");
481 opts
.testLines
= parser
.Found("lines");
482 opts
.testRawBitmaps
= parser
.Found("rawbmp");
483 opts
.testRectangles
= parser
.Found("rectangles");
484 if ( !(opts
.testBitmaps
|| opts
.testImages
|| opts
.testLines
485 || opts
.testRawBitmaps
|| opts
.testRectangles
) )
487 // Do everything by default.
491 opts
.testRawBitmaps
=
492 opts
.testRectangles
= true;
495 opts
.usePaint
= parser
.Found("paint");
496 opts
.useClient
= parser
.Found("client");
497 opts
.useMemory
= parser
.Found("memory");
498 if ( !(opts
.usePaint
|| opts
.useClient
|| opts
.useMemory
) )
502 opts
.useMemory
= true;
505 opts
.useDC
= parser
.Found("dc");
506 opts
.useGC
= parser
.Found("gc");
508 opts
.useGL
= parser
.Found("gl");
511 if ( opts
.useDC
|| opts
.useGC
)
513 wxLogError("Can't use both OpenGL and normal graphics.");
517 else // Not using OpenGL
518 #endif // wxUSE_GLCANVAS
520 if ( !(opts
.useDC
|| opts
.useGC
) )
530 virtual bool OnInit()
532 if ( !wxApp::OnInit() )
535 new GraphicsBenchmarkFrame
;
541 IMPLEMENT_APP_CONSOLE(GraphicsBenchmarkApp
)