]>
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
6 // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
12 #include "wx/cmdline.h"
13 #include "wx/dcclient.h"
14 #include "wx/dcmemory.h"
15 #include "wx/dcgraph.h"
17 #include "wx/rawbmp.h"
18 #include "wx/stopwatch.h"
22 #include "wx/glcanvas.h"
24 #pragma comment(lib, "opengl32")
26 #endif // wxUSE_GLCANVAS
33 void InitializeTexture(int w
, int h
)
35 glGenTextures(1, &g_texture
);
36 glBindTexture(GL_TEXTURE_2D
, g_texture
);
38 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
40 g_image
.Create(w
, h
, false /* don't clear */);
41 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
42 glTexImage2D(GL_TEXTURE_2D
, 0,
43 GL_RGB
, g_image
.GetWidth(), g_image
.GetHeight(), 0,
44 GL_RGB
, GL_UNSIGNED_BYTE
, g_image
.GetData());
46 #endif // wxUSE_GLCANVAS
48 struct GraphicsBenchmarkOptions
50 GraphicsBenchmarkOptions()
64 testRectangles
= false;
96 class GraphicsBenchmarkFrame
: public wxFrame
99 GraphicsBenchmarkFrame()
100 : wxFrame(NULL
, wxID_ANY
, "wxWidgets Graphics Benchmark")
102 SetClientSize(opts
.width
, opts
.height
);
109 m_glCanvas
= new wxGLCanvas(this, wxID_ANY
, NULL
,
111 wxSize(opts
.width
, opts
.height
));
112 m_glContext
= new wxGLContext(m_glCanvas
);
113 m_glContext
->SetCurrent(*m_glCanvas
);
115 glViewport(0, 0, opts
.width
, opts
.height
);
116 glMatrixMode(GL_PROJECTION
);
118 glOrtho(-1, 1, -1, 1, -1, 1);
119 glMatrixMode(GL_MODELVIEW
);
122 InitializeTexture(opts
.width
, opts
.height
);
126 wxPaintEventHandler(GraphicsBenchmarkFrame::OnGLRender
),
131 else // Not using OpenGL
132 #endif // wxUSE_GLCANVAS
135 wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint
));
138 Connect(wxEVT_SIZE
, wxSizeEventHandler(GraphicsBenchmarkFrame::OnSize
));
140 m_bitmap
.Create(64, 64, 32);
146 virtual ~GraphicsBenchmarkFrame()
150 #endif // wxUSE_GLCANVAS
153 // Just change the image in some (quick) way to show that it's really being
154 // updated on screen.
155 void UpdateRGB(unsigned char* data
, int n
)
157 for ( int y
= 0; y
< opts
.height
; ++y
)
159 memset(data
, n
% 256, 3*opts
.width
);
161 data
+= 3*opts
.width
;
167 void OnGLRender(wxPaintEvent
& WXUNUSED(event
))
169 m_glContext
->SetCurrent(*m_glCanvas
);
170 glEnable(GL_TEXTURE_2D
);
172 glClearColor(0.0f
, 0.0f
, 0.0f
, 0.0f
);
173 glClear(GL_COLOR_BUFFER_BIT
);
175 wxPrintf("Benchmarking %s: ", "OpenGL images");
179 for ( int n
= 0; n
< opts
.numIters
; n
++ )
181 UpdateRGB(g_image
.GetData(), n
);
183 glTexSubImage2D(GL_TEXTURE_2D
, 0,
184 0, 0, opts
.width
, opts
.height
,
185 GL_RGB
, GL_UNSIGNED_BYTE
, g_image
.GetData());
188 glVertex2f(-1.0, -1.0);
191 glVertex2f(-1.0, 1.0);
194 glVertex2f(1.0, 1.0);
197 glVertex2f(1.0, -1.0);
200 m_glCanvas
->SwapBuffers();
203 const long t
= sw
.Time();
205 wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
206 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
207 (1000*opts
.numIters
+ t
- 1)/t
);
209 wxTheApp
->ExitMainLoop();
211 #endif // wxUSE_GLCANVAS
213 void OnPaint(wxPaintEvent
& WXUNUSED(event
))
219 BenchmarkDCAndGC("paint", dc
, gcdc
);
222 if ( opts
.useClient
)
226 BenchmarkDCAndGC("client", dc
, gcdc
);
229 if ( opts
.useMemory
)
231 wxBitmap
bmp(opts
.width
, opts
.height
);
234 BenchmarkDCAndGC("memory", dc
, gcdc
);
237 wxTheApp
->ExitMainLoop();
240 void BenchmarkDCAndGC(const char* dckind
, wxDC
& dc
, wxGCDC
& gcdc
)
243 BenchmarkAll(wxString::Format("%6s DC", dckind
), dc
);
245 BenchmarkAll(wxString::Format("%6s GC", dckind
), gcdc
);
248 void BenchmarkAll(const wxString
& msg
, wxDC
& dc
)
250 BenchmarkBitmaps(msg
, dc
);
251 BenchmarkImages(msg
, dc
);
252 BenchmarkLines(msg
, dc
);
253 BenchmarkRawBitmaps(msg
, dc
);
254 BenchmarkRectangles(msg
, dc
);
257 void BenchmarkLines(const wxString
& msg
, wxDC
& dc
)
259 if ( !opts
.testLines
)
262 if ( opts
.mapMode
!= 0 )
263 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
264 if ( opts
.penWidth
!= 0 )
265 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
267 wxPrintf("Benchmarking %s: ", msg
);
273 for ( int n
= 0; n
< opts
.numIters
; n
++ )
275 int x1
= rand() % opts
.width
,
276 y1
= rand() % opts
.height
;
278 dc
.DrawLine(x
, y
, x1
, y1
);
284 const long t
= sw
.Time();
286 wxPrintf("%ld lines done in %ldms = %gus/line\n",
287 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
291 void BenchmarkRectangles(const wxString
& msg
, wxDC
& dc
)
293 if ( !opts
.testRectangles
)
296 if ( opts
.mapMode
!= 0 )
297 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
298 if ( opts
.penWidth
!= 0 )
299 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
301 dc
.SetBrush( *wxRED_BRUSH
);
303 wxPrintf("Benchmarking %s: ", msg
);
307 for ( int n
= 0; n
< opts
.numIters
; n
++ )
309 int x
= rand() % opts
.width
,
310 y
= rand() % opts
.height
;
312 dc
.DrawRectangle(x
, y
, 32, 32);
315 const long t
= sw
.Time();
317 wxPrintf("%ld rects done in %ldms = %gus/rect\n",
318 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
321 void BenchmarkBitmaps(const wxString
& msg
, wxDC
& dc
)
323 if ( !opts
.testBitmaps
)
326 if ( opts
.mapMode
!= 0 )
327 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
328 if ( opts
.penWidth
!= 0 )
329 dc
.SetPen(wxPen(*wxWHITE
, opts
.penWidth
));
331 wxPrintf("Benchmarking %s: ", msg
);
335 for ( int n
= 0; n
< opts
.numIters
; n
++ )
337 int x
= rand() % opts
.width
,
338 y
= rand() % opts
.height
;
340 dc
.DrawBitmap(m_bitmap
, x
, y
, true);
343 const long t
= sw
.Time();
345 wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
346 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
);
349 void BenchmarkImages(const wxString
& msg
, wxDC
& dc
)
351 if ( !opts
.testImages
)
354 if ( opts
.mapMode
!= 0 )
355 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
357 wxPrintf("Benchmarking %s: ", msg
);
360 wxImage
image(wxSize(opts
.width
, opts
.height
), false /* don't clear */);
363 for ( int n
= 0; n
< opts
.numIters
; n
++ )
365 UpdateRGB(image
.GetData(), n
);
366 dc
.DrawBitmap(image
, 0, 0);
369 const long t
= sw
.Time();
371 wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
372 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
373 (1000*opts
.numIters
+ t
- 1)/t
);
376 void BenchmarkRawBitmaps(const wxString
& msg
, wxDC
& dc
)
378 if ( !opts
.testRawBitmaps
)
381 if ( opts
.mapMode
!= 0 )
382 dc
.SetMapMode((wxMappingMode
)opts
.mapMode
);
384 wxPrintf("Benchmarking %s: ", msg
);
387 wxBitmap
bitmap(opts
.width
, opts
.height
, 24);
388 wxNativePixelData
data(bitmap
);
391 for ( int n
= 0; n
< opts
.numIters
; n
++ )
393 unsigned char c
= n
% 256;
395 wxNativePixelData::Iterator
p(data
);
396 for ( int y
= 0; y
< opts
.height
; ++y
)
398 wxNativePixelData::Iterator rowStart
= p
;
400 for ( int x
= 0; x
< opts
.width
; ++x
)
414 dc
.DrawBitmap(bitmap
, 0, 0);
417 const long t
= sw
.Time();
419 wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %ld FPS\n",
420 opts
.numIters
, t
, (1000. * t
)/opts
.numIters
,
421 (1000*opts
.numIters
+ t
- 1)/t
);
427 wxGLCanvas
* m_glCanvas
;
428 wxGLContext
* m_glContext
;
429 #endif // wxUSE_GLCANVAS
432 class GraphicsBenchmarkApp
: public wxApp
435 virtual void OnInitCmdLine(wxCmdLineParser
& parser
)
437 static const wxCmdLineEntryDesc desc
[] =
439 { wxCMD_LINE_SWITCH
, "", "bitmaps" },
440 { wxCMD_LINE_SWITCH
, "", "images" },
441 { wxCMD_LINE_SWITCH
, "", "lines" },
442 { wxCMD_LINE_SWITCH
, "", "rawbmp" },
443 { wxCMD_LINE_SWITCH
, "", "rectangles" },
444 { wxCMD_LINE_SWITCH
, "", "paint" },
445 { wxCMD_LINE_SWITCH
, "", "client" },
446 { wxCMD_LINE_SWITCH
, "", "memory" },
447 { wxCMD_LINE_SWITCH
, "", "dc" },
448 { wxCMD_LINE_SWITCH
, "", "gc" },
450 { wxCMD_LINE_SWITCH
, "", "gl" },
451 #endif // wxUSE_GLCANVAS
452 { wxCMD_LINE_OPTION
, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER
},
453 { wxCMD_LINE_OPTION
, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER
},
454 { wxCMD_LINE_OPTION
, "w", "width", "", wxCMD_LINE_VAL_NUMBER
},
455 { wxCMD_LINE_OPTION
, "h", "height", "", wxCMD_LINE_VAL_NUMBER
},
456 { wxCMD_LINE_OPTION
, "I", "images", "", wxCMD_LINE_VAL_NUMBER
},
457 { wxCMD_LINE_OPTION
, "N", "number-of-iterations", "", wxCMD_LINE_VAL_NUMBER
},
461 parser
.SetDesc(desc
);
464 virtual bool OnCmdLineParsed(wxCmdLineParser
& parser
)
466 if ( parser
.Found("m", &opts
.mapMode
) &&
467 (opts
.mapMode
< 1 || opts
.mapMode
> wxMM_METRIC
) )
469 if ( parser
.Found("p", &opts
.penWidth
) && opts
.penWidth
< 1 )
471 if ( parser
.Found("w", &opts
.width
) && opts
.width
< 1 )
473 if ( parser
.Found("h", &opts
.height
) && opts
.height
< 1 )
475 if ( parser
.Found("N", &opts
.numIters
) && opts
.numIters
< 1 )
478 opts
.testBitmaps
= parser
.Found("bitmaps");
479 opts
.testImages
= parser
.Found("images");
480 opts
.testLines
= parser
.Found("lines");
481 opts
.testRawBitmaps
= parser
.Found("rawbmp");
482 opts
.testRectangles
= parser
.Found("rectangles");
483 if ( !(opts
.testBitmaps
|| opts
.testImages
|| opts
.testLines
484 || opts
.testRawBitmaps
|| opts
.testRectangles
) )
486 // Do everything by default.
490 opts
.testRawBitmaps
=
491 opts
.testRectangles
= true;
494 opts
.usePaint
= parser
.Found("paint");
495 opts
.useClient
= parser
.Found("client");
496 opts
.useMemory
= parser
.Found("memory");
497 if ( !(opts
.usePaint
|| opts
.useClient
|| opts
.useMemory
) )
501 opts
.useMemory
= true;
504 opts
.useDC
= parser
.Found("dc");
505 opts
.useGC
= parser
.Found("gc");
507 opts
.useGL
= parser
.Found("gl");
510 if ( opts
.useDC
|| opts
.useGC
)
512 wxLogError("Can't use both OpenGL and normal graphics.");
516 else // Not using OpenGL
517 #endif // wxUSE_GLCANVAS
519 if ( !(opts
.useDC
|| opts
.useGC
) )
529 virtual bool OnInit()
531 if ( !wxApp::OnInit() )
534 new GraphicsBenchmarkFrame
;
540 IMPLEMENT_APP_CONSOLE(GraphicsBenchmarkApp
)