2 * OpenGL ES 2.0 memory performance estimator
3 * Copyright (C) 2009 Nokia
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * \author Sami Kyöstilä <sami.kyostila@nokia.com>
21 #include <GLES2/gl2.h>
22 #include <GLES2/gl2ext.h>
23 #include <X11/Xutil.h>
38 #include "cleartest.h"
39 #include "pixmapblittest.h"
40 #include "fboblittest.h"
41 #include "shaderblittest.h"
42 #include "cpuinterleavingtest.h"
45 #if defined(HAVE_LIBOSSO)
50 * Command line options
58 std::list<std::string> includedTests;
59 std::list<std::string> excludedTests;
62 /** Shared EGL objects */
65 #if defined(HAVE_LIBOSSO)
66 osso_context_t* ossoContext;
69 bool initializeEgl(int width, int height, const EGLint* configAttrs, const EGLint* contextAttrs)
71 EGLint configCount = 0;
73 #if defined(HAVE_LIBOSSO)
74 ossoContext = osso_initialize("com.nokia.memperf", "1.0", FALSE, NULL);
77 printf("Warning: osso_initialize failed\n");
81 ctx.dpy = eglGetDisplay(ctx.nativeDisplay);
84 eglInitialize(ctx.dpy, NULL, NULL);
85 eglChooseConfig(ctx.dpy, configAttrs, &ctx.config, 1, &configCount);
90 printf("Config not found\n");
96 printf("Config attributes:\n");
97 dumpConfig(ctx.dpy, ctx.config);
100 if (!nativeCreateWindow(ctx.nativeDisplay, ctx.dpy, ctx.config, __FILE__,
101 width, height, &ctx.win))
103 printf("Unable to create a window\n");
107 ctx.context = eglCreateContext(ctx.dpy, ctx.config, EGL_NO_CONTEXT, contextAttrs);
111 printf("Unable to create a context\n");
115 ctx.surface = eglCreateWindowSurface(ctx.dpy, ctx.config, ctx.win, NULL);
119 printf("Unable to create a surface\n");
123 eglMakeCurrent(ctx.dpy, ctx.surface, ctx.surface, ctx.context);
126 eglSwapInterval(ctx.dpy, 0);
130 eglMakeCurrent(ctx.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
131 eglDestroySurface(ctx.dpy, ctx.surface);
132 eglDestroyContext(ctx.dpy, ctx.context);
133 eglTerminate(ctx.dpy);
134 nativeDestroyWindow(ctx.nativeDisplay, ctx.win);
135 nativeDestroyDisplay(ctx.nativeDisplay);
141 eglMakeCurrent(ctx.dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
142 eglDestroySurface(ctx.dpy, ctx.surface);
143 eglDestroyContext(ctx.dpy, ctx.context);
144 eglTerminate(ctx.dpy);
145 nativeDestroyWindow(ctx.nativeDisplay, ctx.win);
146 nativeDestroyDisplay(ctx.nativeDisplay);
148 #if defined(HAVE_LIBOSSO)
149 osso_deinitialize(ossoContext);
154 int64_t timeDiff(const struct timespec& start, const struct timespec& end)
156 int64_t s = start.tv_sec * (1000 * 1000 * 1000LL) + start.tv_nsec;
157 int64_t e = end.tv_sec * (1000 * 1000 * 1000LL) + end.tv_nsec;
161 bool shouldRunTest(const std::string& testName)
163 std::list<std::string>::iterator i;
166 if (options.includedTests.size())
169 for (i = options.includedTests.begin(); i != options.includedTests.end(); ++i)
171 if (testName.find(*i) != std::string::npos)
179 for (i = options.excludedTests.begin(); i != options.excludedTests.end(); ++i)
181 if (testName.find(*i) != std::string::npos)
191 void runTest(Test& test)
194 int frameLimit = 100;
196 int64_t minTime = options.minTime * 1000 * 1000 * 1000LL;
197 struct timespec res, start, end;
199 if (options.listTests)
201 printf("%s\n", test.name().c_str());
205 if (!shouldRunTest(test.name()))
210 clock_getres(CLOCK_REALTIME, &res);
211 //printf("Timer resolution: %d.%09d s\n", res.tv_sec, res.tv_nsec);
212 printf("%-40s", (test.name() + ":").c_str());
220 } catch (const std::exception& e)
222 printf("%s\n", e.what());
235 #if defined(HAVE_LIBOSSO)
236 osso_display_blanking_pause(ossoContext);
239 clock_gettime(CLOCK_REALTIME, &start);
240 while (frames < frameLimit)
244 clock_gettime(CLOCK_REALTIME, &end);
246 if (frames >= frameLimit && timeDiff(start, end) < minTime)
259 int64_t diff = timeDiff(start, end);
260 int fps = static_cast<int>((1000 * 1000 * 1000LL * frames) / diff);
261 //printf("%d frames in %6.2f ms (%3d fps) ", frames, diff / (1000.0f * 1000.0f), fps);
262 printf("%3d fps ", fps);
272 void getScreenSize(int& width, int& height)
274 Window rootWindow = DefaultRootWindow(ctx.nativeDisplay);
275 XWindowAttributes rootAttrs;
277 XGetWindowAttributes(ctx.nativeDisplay, rootWindow, &rootAttrs);
279 width = rootAttrs.width;
280 height = rootAttrs.height;
286 "GLMemPerf v" PACKAGE_VERSION " - OpenGL ES 2.0 memory performance benchmark\n"
287 "Copyright (C) 2009 Nokia Corporation. GLMemPerf comes with ABSOLUTELY\n"
288 "NO WARRANTY; This is free software, and you are welcome to redistribute\n"
289 "it under certain conditions.\n"
297 " glmemperf [OPTIONS]\n"
301 " -l List all tests without running them\n"
302 " -i TEST Include a specific test (full name or substring)\n"
303 " -e TEST Exclude a specific test (full name or substring)\n"
304 " -t SECS Minimum time to run each test\n"
305 " -b BPP Bits per pixel\n";
308 void parseArguments(const std::list<std::string>& args)
310 std::list<std::string>::const_iterator i;
313 options.verbose = false;
315 options.bitsPerPixel = 16;
316 options.listTests = false;
318 for (i = args.begin(), i++; i != args.end(); ++i)
320 if (*i == "-h" || *i == "--help")
325 else if (*i == "-i" && ++i != args.end())
327 options.includedTests.push_back(*i);
329 else if (*i == "-e" && ++i != args.end())
331 options.excludedTests.push_back(*i);
333 else if (*i == "-t" && ++i != args.end())
335 options.minTime = atoi((*i).c_str());
337 else if (*i == "-b" && ++i != args.end())
339 options.bitsPerPixel = atoi((*i).c_str());
343 options.verbose = true;
347 options.listTests = true;
351 std::cerr << "Invalid option: " << *i << std::endl;
358 void findDataDirectory()
361 if (stat("data", &st) == 0)
365 chdir(PREFIX "/share/glmemperf/");
366 assert(stat("data", &st) == 0);
369 #define ADD_TEST(TEST) runTest(*std::auto_ptr<Test>(new TEST));
371 int main(int argc, char** argv)
373 std::list<std::string> args(argv, argv + argc);
376 parseArguments(args);
379 const EGLint configAttrs[] =
381 EGL_BUFFER_SIZE, options.bitsPerPixel,
382 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
386 const EGLint configAttrs32[] =
392 const EGLint contextAttrs[] =
394 EGL_CONTEXT_CLIENT_VERSION, 2,
399 const float w = winWidth, h = winHeight;
400 EGLConfig config32 = 0;
401 EGLint configCount = 0;
403 bool result = nativeCreateDisplay(&ctx.nativeDisplay);
406 getScreenSize(winWidth, winHeight);
407 result = initializeEgl(winWidth, winHeight, configAttrs, contextAttrs);
410 eglChooseConfig(ctx.dpy, configAttrs32, &config32, 1, &configCount);
414 printf("32bpp config not found\n");
417 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
421 ADD_TEST(ClearTest());
424 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 800, 480, "data/water2_800x480_rgba8888.raw"));
425 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_BYTE, 800, 480, "data/water2_800x480_rgb888.raw"));
426 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 1024, 512, "data/digital_nature2_1024x512_rgba8888.raw", false, 800.0 / 1024, 480.0 / 512));
427 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 800, 480, "data/water2_800x480_rgb565.raw"));
428 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1024, 512, "data/digital_nature2_1024x512_rgb565.raw", false, 800.0 / 1024, 480.0 / 512));
429 ADD_TEST(BlitTest(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 0, 1024, 512, "data/abstract3_1024x512_pvrtc4.raw", false, 800.0 / 1024, 480.0 / 512));
430 ADD_TEST(BlitTest(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 0, 1024, 512, "data/abstract3_1024x512_pvrtc2.raw", false, 800.0 / 1024, 480.0 / 512));
431 ADD_TEST(BlitTest(GL_ETC1_RGB8_OES, 0, 1024, 512, "data/abstract3_1024x512_etc1.raw", false, 800.0 / 1024, 480.0 / 512));
432 ADD_TEST(PixmapBlitTest(w, h, ctx.config));
433 ADD_TEST(PixmapBlitTest(w, h, config32));
434 ADD_TEST(FBOBlitTest(GL_RGBA, GL_UNSIGNED_BYTE, w, h));
435 ADD_TEST(FBOBlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 1024, 512, false, w / 1024, h / 512));
436 ADD_TEST(FBOBlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, w, h));
437 ADD_TEST(FBOBlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1024, 512, false, w / 1042, h / 512));
440 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 480, 800, "data/water2_480x800_rgba8888.raw", true));
441 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_BYTE, 480, 800, "data/water2_480x800_rgb888.raw", true));
442 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 512, 1024, "data/digital_nature2_512x1024_rgba8888.raw", true, 480.0 / 512, 800.0 / 1024));
443 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 480, 800, "data/water2_480x800_rgb565.raw", true));
444 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 512, 1024, "data/digital_nature2_512x1024_rgb565.raw", true, 480.0 / 512, 800.0 / 1024));
445 ADD_TEST(BlitTest(GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG, 0, 512, 1024, "data/abstract3_512x1024_pvrtc4.raw", true, 480.0 / 512, 800.0 / 1024));
446 ADD_TEST(BlitTest(GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG, 0, 512, 1024, "data/abstract3_512x1024_pvrtc2.raw", true, 480.0 / 512, 800.0 / 1024));
447 ADD_TEST(BlitTest(GL_ETC1_RGB8_OES, 0, 512, 1024, "data/abstract3_512x1024_etc1.raw", true, 480.0 / 512, 800.0 / 1024));
448 ADD_TEST(PixmapBlitTest(h, w, ctx.config, true));
449 ADD_TEST(PixmapBlitTest(h, w, config32, true));
450 ADD_TEST(FBOBlitTest(GL_RGBA, GL_UNSIGNED_BYTE, w, h, true, h / w, w / h));
451 ADD_TEST(FBOBlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 1024, 512, true, h / 512, w / 1024));
452 ADD_TEST(FBOBlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, w, h, true, h / w, w / h));
453 ADD_TEST(FBOBlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 1024, 512, true, h / 512, w / 1024));
457 float w2 = winWidth / gridW;
458 float h2 = winHeight / gridH;
461 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
463 // Small blended blits
464 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, 128, 128, "data/xorg_128x128_rgba4444.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
465 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 127, 127, "data/xorg_127x127_rgba8888.raw", false, gridW, gridH, 127.0 / w2, 127.0 / h2));
466 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 128, 128, "data/xorg_128x128_rgba8888.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
467 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 127, 127, "data/xorg_127x127_rgb565.raw", false, gridW, gridH, 127.0 / w2, 127.0 / h2));
468 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 128, 128, "data/xorg_128x128_rgb565.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
469 ADD_TEST(BlitTest(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 0, 128, 128, "data/xorg_128x128_pvrtc4.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
470 ADD_TEST(BlitTest(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 0, 128, 128, "data/xorg_128x128_pvrtc2.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
471 ADD_TEST(BlitTest(GL_ETC1_RGB8_OES, 0, 128, 128, "data/xorg_128x128_etc1.raw", false, gridW, gridH, 128.0 / w2, 128.0 / h2));
472 ADD_TEST(ShaderBlitTest("mask", 128, 128, gridW, gridH * 0.5f, 128.0 / w2, 128.0 / h2));
474 // Rotated small blended blits
475 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 127, 127, "data/xorg_127x127_rgba8888.raw", true, gridH, gridW, 127.0 / w2, 127.0 / h2));
476 ADD_TEST(BlitTest(GL_RGBA, GL_UNSIGNED_BYTE, 128, 128, "data/xorg_128x128_rgba8888.raw", true, gridH, gridW, 128.0 / w2, 128.0 / h2));
477 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 127, 127, "data/xorg_127x127_rgb565.raw", true, gridH, gridW, 127.0 / w2, 127.0 / h2));
478 ADD_TEST(BlitTest(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 128, 128, "data/xorg_128x128_rgb565.raw", true, gridH, gridW, 128.0 / w2, 128.0 / h2));
479 ADD_TEST(BlitTest(GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG, 0, 128, 128, "data/xorg_128x128_pvrtc4.raw", true, gridH, gridW, 128.0 / w2, 128.0 / h2));
480 ADD_TEST(BlitTest(GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG, 0, 128, 128, "data/xorg_128x128_pvrtc2.raw", true, gridH, gridW, 128.0 / w2, 128.0 / h2));
481 ADD_TEST(BlitTest(GL_ETC1_RGB8_OES, 0, 128, 128, "data/xorg_128x128_etc1.raw", true, gridH, gridW, 128.0 / w2, 128.0 / h2));
486 ADD_TEST(ShaderBlitTest("const", w, h));
487 ADD_TEST(ShaderBlitTest("lingrad", w, h));
488 ADD_TEST(ShaderBlitTest("radgrad", w, h));
489 ADD_TEST(ShaderBlitTest("palette", w, h));
492 ADD_TEST(CPUInterleavingTest(CPUI_XSHM_IMAGE, 2, 16, winWidth, winHeight));
493 ADD_TEST(CPUInterleavingTest(CPUI_XSHM_IMAGE, 2, 32, winWidth, winHeight));
494 ADD_TEST(CPUInterleavingTest(CPUI_TEXTURE_UPLOAD, 2, 16, winWidth, winHeight));
495 ADD_TEST(CPUInterleavingTest(CPUI_TEXTURE_UPLOAD, 2, 32, winWidth, winHeight));