X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8c14cbc98c1bb94c1f5a264694b8cf439b4f7729..9afa58e3b924dbef7fd0d45bb0bbee68fe3aac7d:/tests/benchmarks/graphics.cpp?ds=sidebyside diff --git a/tests/benchmarks/graphics.cpp b/tests/benchmarks/graphics.cpp index 5ee262844d..19ebbb6a25 100644 --- a/tests/benchmarks/graphics.cpp +++ b/tests/benchmarks/graphics.cpp @@ -14,9 +14,38 @@ #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() @@ -27,10 +56,12 @@ struct GraphicsBenchmarkOptions width = 800; height = 600; - numLines = 10000; + numIters = 1000; testBitmaps = + testImages = testLines = + testRawBitmaps = testRectangles = false; usePaint = @@ -38,17 +69,20 @@ struct GraphicsBenchmarkOptions useMemory = false; useDC = - useGC = false; + useGC = + useGL = false; } long mapMode, penWidth, width, height, - numLines; + numIters; bool testBitmaps, + testImages, testLines, + testRawBitmaps, testRectangles; bool usePaint, @@ -56,7 +90,8 @@ struct GraphicsBenchmarkOptions useMemory; bool useDC, - useGC; + useGC, + useGL; } opts; class GraphicsBenchmarkFrame : public wxFrame @@ -65,16 +100,117 @@ public: GraphicsBenchmarkFrame() : wxFrame(NULL, wxID_ANY, "wxWidgets Graphics Benchmark") { - Connect(wxEVT_PAINT, - wxPaintEventHandler(GraphicsBenchmarkFrame::OnPaint)); + 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(); - SetClientSize(opts.width, opts.height); } +#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 ) @@ -112,9 +248,11 @@ private: void BenchmarkAll(const wxString& msg, wxDC& dc) { + BenchmarkBitmaps(msg, dc); + BenchmarkImages(msg, dc); BenchmarkLines(msg, dc); + BenchmarkRawBitmaps(msg, dc); BenchmarkRectangles(msg, dc); - BenchmarkBitmaps(msg, dc); } void BenchmarkLines(const wxString& msg, wxDC& dc) @@ -133,7 +271,7 @@ private: wxStopWatch sw; int x = 0, y = 0; - for ( int n = 0; n < opts.numLines; n++ ) + for ( int n = 0; n < opts.numIters; n++ ) { int x1 = rand() % opts.width, y1 = rand() % opts.height; @@ -147,7 +285,7 @@ private: const long t = sw.Time(); wxPrintf("%ld lines done in %ldms = %gus/line\n", - opts.numLines, t, (1000. * t)/opts.numLines); + opts.numIters, t, (1000. * t)/opts.numIters); } @@ -167,7 +305,7 @@ private: fflush(stdout); wxStopWatch sw; - for ( int n = 0; n < opts.numLines; n++ ) + for ( int n = 0; n < opts.numIters; n++ ) { int x = rand() % opts.width, y = rand() % opts.height; @@ -178,7 +316,7 @@ private: const long t = sw.Time(); wxPrintf("%ld rects done in %ldms = %gus/rect\n", - opts.numLines, t, (1000. * t)/opts.numLines); + opts.numIters, t, (1000. * t)/opts.numIters); } void BenchmarkBitmaps(const wxString& msg, wxDC& dc) @@ -195,7 +333,7 @@ private: fflush(stdout); wxStopWatch sw; - for ( int n = 0; n < opts.numLines; n++ ) + for ( int n = 0; n < opts.numIters; n++ ) { int x = rand() % opts.width, y = rand() % opts.height; @@ -206,11 +344,90 @@ private: const long t = sw.Time(); wxPrintf("%ld bitmaps done in %ldms = %gus/bitmap\n", - opts.numLines, t, (1000. * t)/opts.numLines); + 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 @@ -221,18 +438,24 @@ public: 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, "L", "lines", "", 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 }, }; @@ -250,17 +473,22 @@ public: return false; if ( parser.Found("h", &opts.height) && opts.height < 1 ) return false; - if ( parser.Found("L", &opts.numLines) && opts.numLines < 1 ) + 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.testLines || opts.testRectangles) ) + 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; } @@ -276,10 +504,24 @@ public: opts.useDC = parser.Found("dc"); opts.useGC = parser.Found("gc"); - if ( !(opts.useDC || opts.useGC) ) +#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 { - opts.useDC = - opts.useGC = true; + if ( !(opts.useDC || opts.useGC) ) + { + opts.useDC = + opts.useGC = true; + } } return true;