| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540 |
- /////////////////////////////////////////////////////////////////////////////
- // Name: graphics.cpp
- // Purpose: Some benchmarks for measuring graphics operations performance
- // Author: Vadim Zeitlin
- // Created: 2008-04-13
- // Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
- // Licence: wxWindows licence
- /////////////////////////////////////////////////////////////////////////////
- #include "wx/app.h"
- #include "wx/frame.h"
- #include "wx/cmdline.h"
- #include "wx/dcclient.h"
- #include "wx/dcmemory.h"
- #include "wx/dcgraph.h"
- #include "wx/image.h"
- #include "wx/rawbmp.h"
- #include "wx/stopwatch.h"
- #include "wx/crt.h"
- #if wxUSE_GLCANVAS
- #include "wx/glcanvas.h"
- #ifdef _MSC_VER
- #pragma comment(lib, "opengl32")
- #endif
- #endif // wxUSE_GLCANVAS
- #if wxUSE_GLCANVAS
- GLuint g_texture;
- wxImage g_image;
- void InitializeTexture(int w, int h)
- {
- glGenTextures(1, &g_texture);
- glBindTexture(GL_TEXTURE_2D, g_texture);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- g_image.Create(w, h, false /* don't clear */);
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- glTexImage2D(GL_TEXTURE_2D, 0,
- GL_RGB, g_image.GetWidth(), g_image.GetHeight(), 0,
- GL_RGB, GL_UNSIGNED_BYTE, g_image.GetData());
- }
- #endif // wxUSE_GLCANVAS
- struct GraphicsBenchmarkOptions
- {
- GraphicsBenchmarkOptions()
- {
- mapMode = 0;
- penWidth = 0;
- width = 800;
- height = 600;
- numIters = 1000;
- testBitmaps =
- testImages =
- testLines =
- testRawBitmaps =
- testRectangles = false;
- usePaint =
- useClient =
- useMemory = false;
- useDC =
- useGC =
- useGL = false;
- }
- long mapMode,
- penWidth,
- width,
- height,
- numIters;
- bool testBitmaps,
- testImages,
- testLines,
- testRawBitmaps,
- testRectangles;
- bool usePaint,
- useClient,
- useMemory;
- bool useDC,
- useGC,
- useGL;
- } opts;
- class GraphicsBenchmarkFrame : public wxFrame
- {
- public:
- GraphicsBenchmarkFrame()
- : wxFrame(NULL, wxID_ANY, "wxWidgets Graphics Benchmark")
- {
- SetClientSize(opts.width, opts.height);
- #if wxUSE_GLCANVAS
- m_glCanvas = NULL;
- if ( opts.useGL )
- {
- m_glCanvas = new wxGLCanvas(this, wxID_ANY, NULL,
- wxPoint(0, 0),
- wxSize(opts.width, opts.height));
- m_glContext = new wxGLContext(m_glCanvas);
- m_glContext->SetCurrent(*m_glCanvas);
- glViewport(0, 0, opts.width, opts.height);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrtho(-1, 1, -1, 1, -1, 1);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- InitializeTexture(opts.width, opts.height);
- m_glCanvas->Connect(
- wxEVT_PAINT,
- wxPaintEventHandler(GraphicsBenchmarkFrame::OnGLRender),
- NULL,
- this
- );
- }
- else // Not using OpenGL
- #endif // wxUSE_GLCANVAS
- {
- Connect(wxEVT_PAINT,
- wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint));
- }
- Connect(wxEVT_SIZE, wxSizeEventHandler(GraphicsBenchmarkFrame::OnSize));
- m_bitmap.Create(64, 64, 32);
- Show();
- }
- #if wxUSE_GLCANVAS
- virtual ~GraphicsBenchmarkFrame()
- {
- delete m_glContext;
- }
- #endif // wxUSE_GLCANVAS
- private:
- // Just change the image in some (quick) way to show that it's really being
- // updated on screen.
- void UpdateRGB(unsigned char* data, int n)
- {
- for ( int y = 0; y < opts.height; ++y )
- {
- memset(data, n % 256, 3*opts.width);
- data += 3*opts.width;
- n++;
- }
- }
- #if wxUSE_GLCANVAS
- void OnGLRender(wxPaintEvent& WXUNUSED(event))
- {
- m_glContext->SetCurrent(*m_glCanvas);
- glEnable(GL_TEXTURE_2D);
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
- glClear(GL_COLOR_BUFFER_BIT);
- wxPrintf("Benchmarking %s: ", "OpenGL images");
- fflush(stdout);
- wxStopWatch sw;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- UpdateRGB(g_image.GetData(), n);
- glTexSubImage2D(GL_TEXTURE_2D, 0,
- 0, 0, opts.width, opts.height,
- GL_RGB, GL_UNSIGNED_BYTE, g_image.GetData());
- glBegin(GL_QUADS);
- glTexCoord2f(0, 0);
- glVertex2f(-1.0, -1.0);
- glTexCoord2f(0, 1);
- glVertex2f(-1.0, 1.0);
- glTexCoord2f(1, 1);
- glVertex2f(1.0, 1.0);
- glTexCoord2f(1, 0);
- glVertex2f(1.0, -1.0);
- glEnd();
- m_glCanvas->SwapBuffers();
- }
- const long t = sw.Time();
- wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
- opts.numIters, t, (1000. * t)/opts.numIters,
- (1000*opts.numIters + t - 1)/t);
- wxTheApp->ExitMainLoop();
- }
- #endif // wxUSE_GLCANVAS
- void OnPaint(wxPaintEvent& WXUNUSED(event))
- {
- if ( opts.usePaint )
- {
- wxPaintDC dc(this);
- wxGCDC gcdc(dc);
- BenchmarkDCAndGC("paint", dc, gcdc);
- }
- if ( opts.useClient )
- {
- wxClientDC dc(this);
- wxGCDC gcdc(dc);
- BenchmarkDCAndGC("client", dc, gcdc);
- }
- if ( opts.useMemory )
- {
- wxBitmap bmp(opts.width, opts.height);
- wxMemoryDC dc(bmp);
- wxGCDC gcdc(dc);
- BenchmarkDCAndGC("memory", dc, gcdc);
- }
- wxTheApp->ExitMainLoop();
- }
- void BenchmarkDCAndGC(const char* dckind, wxDC& dc, wxGCDC& gcdc)
- {
- if ( opts.useDC )
- BenchmarkAll(wxString::Format("%6s DC", dckind), dc);
- if ( opts.useGC )
- BenchmarkAll(wxString::Format("%6s GC", dckind), gcdc);
- }
- void BenchmarkAll(const wxString& msg, wxDC& dc)
- {
- BenchmarkBitmaps(msg, dc);
- BenchmarkImages(msg, dc);
- BenchmarkLines(msg, dc);
- BenchmarkRawBitmaps(msg, dc);
- BenchmarkRectangles(msg, dc);
- }
- void BenchmarkLines(const wxString& msg, wxDC& dc)
- {
- if ( !opts.testLines )
- return;
- if ( opts.mapMode != 0 )
- dc.SetMapMode((wxMappingMode)opts.mapMode);
- if ( opts.penWidth != 0 )
- dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
- wxPrintf("Benchmarking %s: ", msg);
- fflush(stdout);
- wxStopWatch sw;
- int x = 0,
- y = 0;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- int x1 = rand() % opts.width,
- y1 = rand() % opts.height;
- dc.DrawLine(x, y, x1, y1);
- x = x1;
- y = y1;
- }
- const long t = sw.Time();
- wxPrintf("%ld lines done in %ldms = %gus/line\n",
- opts.numIters, t, (1000. * t)/opts.numIters);
- }
- void BenchmarkRectangles(const wxString& msg, wxDC& dc)
- {
- if ( !opts.testRectangles )
- return;
- if ( opts.mapMode != 0 )
- dc.SetMapMode((wxMappingMode)opts.mapMode);
- if ( opts.penWidth != 0 )
- dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
- dc.SetBrush( *wxRED_BRUSH );
- wxPrintf("Benchmarking %s: ", msg);
- fflush(stdout);
- wxStopWatch sw;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- int x = rand() % opts.width,
- y = rand() % opts.height;
- dc.DrawRectangle(x, y, 32, 32);
- }
- const long t = sw.Time();
- wxPrintf("%ld rects done in %ldms = %gus/rect\n",
- opts.numIters, t, (1000. * t)/opts.numIters);
- }
- void BenchmarkBitmaps(const wxString& msg, wxDC& dc)
- {
- if ( !opts.testBitmaps )
- return;
- if ( opts.mapMode != 0 )
- dc.SetMapMode((wxMappingMode)opts.mapMode);
- if ( opts.penWidth != 0 )
- dc.SetPen(wxPen(*wxWHITE, opts.penWidth));
- wxPrintf("Benchmarking %s: ", msg);
- fflush(stdout);
- wxStopWatch sw;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- int x = rand() % opts.width,
- y = rand() % opts.height;
- dc.DrawBitmap(m_bitmap, x, y, true);
- }
- const long t = sw.Time();
- wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n",
- opts.numIters, t, (1000. * t)/opts.numIters);
- }
- void BenchmarkImages(const wxString& msg, wxDC& dc)
- {
- if ( !opts.testImages )
- return;
- if ( opts.mapMode != 0 )
- dc.SetMapMode((wxMappingMode)opts.mapMode);
- wxPrintf("Benchmarking %s: ", msg);
- fflush(stdout);
- wxImage image(wxSize(opts.width, opts.height), false /* don't clear */);
- wxStopWatch sw;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- UpdateRGB(image.GetData(), n);
- dc.DrawBitmap(image, 0, 0);
- }
- const long t = sw.Time();
- wxPrintf("%ld images done in %ldms = %gus/image or %ld FPS\n",
- opts.numIters, t, (1000. * t)/opts.numIters,
- (1000*opts.numIters + t - 1)/t);
- }
- void BenchmarkRawBitmaps(const wxString& msg, wxDC& dc)
- {
- if ( !opts.testRawBitmaps )
- return;
- if ( opts.mapMode != 0 )
- dc.SetMapMode((wxMappingMode)opts.mapMode);
- wxPrintf("Benchmarking %s: ", msg);
- fflush(stdout);
- wxBitmap bitmap(opts.width, opts.height, 24);
- wxNativePixelData data(bitmap);
- wxStopWatch sw;
- for ( int n = 0; n < opts.numIters; n++ )
- {
- unsigned char c = n % 256;
- {
- wxNativePixelData::Iterator p(data);
- for ( int y = 0; y < opts.height; ++y )
- {
- wxNativePixelData::Iterator rowStart = p;
- for ( int x = 0; x < opts.width; ++x )
- {
- p.Red() =
- p.Green() =
- p.Blue() = c;
- ++p;
- }
- p = rowStart;
- p.OffsetY(data, 1);
- c++;
- }
- }
- dc.DrawBitmap(bitmap, 0, 0);
- }
- const long t = sw.Time();
- wxPrintf("%ld raw bitmaps done in %ldms = %gus/bitmap or %ld FPS\n",
- opts.numIters, t, (1000. * t)/opts.numIters,
- (1000*opts.numIters + t - 1)/t);
- }
- wxBitmap m_bitmap;
- #if wxUSE_GLCANVAS
- wxGLCanvas* m_glCanvas;
- wxGLContext* m_glContext;
- #endif // wxUSE_GLCANVAS
- };
- class GraphicsBenchmarkApp : public wxApp
- {
- public:
- virtual void OnInitCmdLine(wxCmdLineParser& parser)
- {
- static const wxCmdLineEntryDesc desc[] =
- {
- { wxCMD_LINE_SWITCH, "", "bitmaps" },
- { wxCMD_LINE_SWITCH, "", "images" },
- { wxCMD_LINE_SWITCH, "", "lines" },
- { wxCMD_LINE_SWITCH, "", "rawbmp" },
- { wxCMD_LINE_SWITCH, "", "rectangles" },
- { wxCMD_LINE_SWITCH, "", "paint" },
- { wxCMD_LINE_SWITCH, "", "client" },
- { wxCMD_LINE_SWITCH, "", "memory" },
- { wxCMD_LINE_SWITCH, "", "dc" },
- { wxCMD_LINE_SWITCH, "", "gc" },
- #if wxUSE_GLCANVAS
- { wxCMD_LINE_SWITCH, "", "gl" },
- #endif // wxUSE_GLCANVAS
- { wxCMD_LINE_OPTION, "m", "map-mode", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_OPTION, "p", "pen-width", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_OPTION, "w", "width", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_OPTION, "h", "height", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_OPTION, "I", "images", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_OPTION, "N", "number-of-iterations", "", wxCMD_LINE_VAL_NUMBER },
- { wxCMD_LINE_NONE },
- };
- parser.SetDesc(desc);
- }
- virtual bool OnCmdLineParsed(wxCmdLineParser& parser)
- {
- if ( parser.Found("m", &opts.mapMode) &&
- (opts.mapMode < 1 || opts.mapMode > wxMM_METRIC) )
- return false;
- if ( parser.Found("p", &opts.penWidth) && opts.penWidth < 1 )
- return false;
- if ( parser.Found("w", &opts.width) && opts.width < 1 )
- return false;
- if ( parser.Found("h", &opts.height) && opts.height < 1 )
- return false;
- if ( parser.Found("N", &opts.numIters) && opts.numIters < 1 )
- return false;
- opts.testBitmaps = parser.Found("bitmaps");
- opts.testImages = parser.Found("images");
- opts.testLines = parser.Found("lines");
- opts.testRawBitmaps = parser.Found("rawbmp");
- opts.testRectangles = parser.Found("rectangles");
- if ( !(opts.testBitmaps || opts.testImages || opts.testLines
- || opts.testRawBitmaps || opts.testRectangles) )
- {
- // Do everything by default.
- opts.testBitmaps =
- opts.testImages =
- opts.testLines =
- opts.testRawBitmaps =
- opts.testRectangles = true;
- }
- opts.usePaint = parser.Found("paint");
- opts.useClient = parser.Found("client");
- opts.useMemory = parser.Found("memory");
- if ( !(opts.usePaint || opts.useClient || opts.useMemory) )
- {
- opts.usePaint =
- opts.useClient =
- opts.useMemory = true;
- }
- opts.useDC = parser.Found("dc");
- opts.useGC = parser.Found("gc");
- #if wxUSE_GLCANVAS
- opts.useGL = parser.Found("gl");
- if ( opts.useGL )
- {
- if ( opts.useDC || opts.useGC )
- {
- wxLogError("Can't use both OpenGL and normal graphics.");
- return false;
- }
- }
- else // Not using OpenGL
- #endif // wxUSE_GLCANVAS
- {
- if ( !(opts.useDC || opts.useGC) )
- {
- opts.useDC =
- opts.useGC = true;
- }
- }
- return true;
- }
- virtual bool OnInit()
- {
- if ( !wxApp::OnInit() )
- return false;
- new GraphicsBenchmarkFrame;
- return true;
- }
- };
- IMPLEMENT_APP_CONSOLE(GraphicsBenchmarkApp)
|