19c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis/*
29c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * Copyright (C) 2012 The Android Open Source Project
39c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis *
49c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License");
59c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * you may not use this file except in compliance with the License.
69c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * You may obtain a copy of the License at
79c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis *
89c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis *      http://www.apache.org/licenses/LICENSE-2.0
99c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis *
109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * Unless required by applicable law or agreed to in writing, software
119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS,
129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * See the License for the specific language governing permissions and
149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis * limitations under the License.
159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis */
169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#define ATRACE_TAG ATRACE_TAG_ALWAYS
189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <gui/GraphicBufferAlloc.h>
209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <gui/Surface.h>
21b7daa0dadebdb043d63e585975a128c5fc087168Mathias Agopian#include <gui/SurfaceControl.h>
229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <gui/GLConsumer.h>
23e3c697fb929c856b59fa56a8e05a2a7eba187c3dMathias Agopian#include <gui/Surface.h>
249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <ui/Fence.h>
259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <utils/Trace.h>
269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <EGL/egl.h>
289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <GLES2/gl2.h>
299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <math.h>
319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <getopt.h>
329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include "Flatland.h"
349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include "GLHelper.h"
359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisusing namespace ::android;
379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic uint32_t g_SleepBetweenSamplesMs = 0;
399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool     g_PresentToWindow       = false;
409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic size_t   g_BenchmarkNameLen      = 0;
419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstruct BenchmarkDesc {
439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The name of the test.
449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const char* name;
459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The dimensions of the space in which window layers are specified.
479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t width;
489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t height;
499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The screen heights at which to run the test.
519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runHeights[MAX_TEST_RUNS];
529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The list of window layers.
549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    LayerDesc layers[MAX_NUM_LAYERS];
559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic const BenchmarkDesc benchmarks[] = {
589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 Single Static Window",
5963d076e3399c77cc610e81b4b173faa0a89efd23Erik Gilling        2560, 1600, { 800, 1200, 1600, 2400 },
609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Window
629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
76b3fb0ae7fd296031f1fa22f3ac058973a5621ebbRom Lemarchand    { "4:3 Single Static Window",
777bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        2048, 1536, { 1536 },
787bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        {
797bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Window
807bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
817bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    50,     2048,   1440,
827bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
837bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Status bar
847bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
857bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    0,      2048,   50,
867bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
877bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Navigation bar
887bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
897bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    1440,   2048,   96,
907bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
917bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        },
927bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling    },
937bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling
949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 App -> Home Transition",
9563d076e3399c77cc610e81b4b173faa0a89efd23Erik Gilling        2560, 1600, { 800, 1200, 1600, 2400 },
969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Wallpaper
989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Launcher
1029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blend,
1039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing activity
1069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
1079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
1089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
1109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
1129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
1149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
1169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
1199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
120b3fb0ae7fd296031f1fa22f3ac058973a5621ebbRom Lemarchand    { "4:3 App -> Home Transition",
1217bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        2048, 1536, { 1536 },
1227bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        {
1237bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Wallpaper
1247bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
1257bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    50,     2048,   1440,
1267bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1277bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Launcher
1287bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, blend,
1297bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    50,     2048,   1440,
1307bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1317bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Outgoing activity
1327bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, blendShrink,
1337bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                20,    70,     2048,   1400,
1347bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1357bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Status bar
1367bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
1377bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    0,      2048,   50,
1387bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1397bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Navigation bar
1407bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
1417bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    1440,   2048,   96,
1427bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1437bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        },
1447bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling    },
1457bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling
1469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 SurfaceView -> Home Transition",
14763d076e3399c77cc610e81b4b173faa0a89efd23Erik Gilling        2560, 1600, { 800, 1200, 1600, 2400 },
1489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
1499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Wallpaper
1509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Launcher
1549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blend,
1559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing SurfaceView
1589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
1599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
1609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing activity
1629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
1639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
1649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
1669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
1689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
1709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
1729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
1757bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling
176b3fb0ae7fd296031f1fa22f3ac058973a5621ebbRom Lemarchand    { "4:3 SurfaceView -> Home Transition",
1777bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        2048, 1536, { 1536 },
1787bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        {
1797bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Wallpaper
1807bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
1817bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    50,     2048,   1440,
1827bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1837bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Launcher
1847bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, blend,
1857bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    50,     2048,   1440,
1867bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1877bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Outgoing SurfaceView
1887bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, blendShrink,
1897bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                20,    70,     2048,   1400,
1907bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1917bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Outgoing activity
1927bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, blendShrink,
1937bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                20,    70,     2048,   1400,
1947bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1957bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Status bar
1967bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
1977bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    0,      2048,   50,
1987bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
1997bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            {   // Navigation bar
2007bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0, staticGradient, opaque,
2017bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling                0,    1440,   2048,   96,
2027bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling            },
2037bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling        },
2047bfdf27539cb5082e9d11da780d2d24405a008d6Erik Gilling    },
2059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
2069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic const ShaderDesc shaders[] = {
2089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    {
2099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        name: "Blit",
2109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        vertexShader: {
2119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
2129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 position;",
2149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 uv;",
2159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying vec4 texCoords;",
2179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 objToNdc;",
2199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 uvToTex;",
2209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
2229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_Position = objToNdc * position;",
2239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    texCoords = uvToTex * uv;",
2249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
2259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
2269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fragmentShader: {
2279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "#extension GL_OES_EGL_image_external : require",
2289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
2299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying vec4 texCoords;",
2319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform samplerExternalOES blitSrc;",
2339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 modColor;",
2349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
2369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor = texture2D(blitSrc, texCoords.xy);",
2379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor *= modColor;",
2389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
2399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
2409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
2419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    {
2439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        name: "Gradient",
2449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        vertexShader: {
2459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
2469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 position;",
2489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 uv;",
2499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying float interp;",
2519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 objToNdc;",
2539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 uvToInterp;",
2549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
2569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_Position = objToNdc * position;",
2579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    interp = (uvToInterp * uv).x;",
2589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
2599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
2609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fragmentShader: {
2619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
2629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying float interp;",
2649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 color0;",
2669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 color1;",
2679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform sampler2D ditherKernel;",
2699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform float invDitherKernelSize;",
2709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform float invDitherKernelSizeSq;",
2719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
2729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
2739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    float dither = texture2D(ditherKernel,",
2749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "            gl_FragCoord.xy * invDitherKernelSize).a;",
2759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    dither *= invDitherKernelSizeSq;",
2769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    vec4 color = mix(color0, color1, clamp(interp, 0.0, 1.0));",
2779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor = color + vec4(dither, dither, dither, 0.0);",
2789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
2799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
2809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
2819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
2829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisclass Layer {
2849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennispublic:
2869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Layer() :
2889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mFirstFrame(true),
2899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper(NULL),
2909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mSurface(EGL_NO_SURFACE) {
2919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool setUp(const LayerDesc& desc, GLHelper* helper) {
2949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
2959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mDesc = desc;
2979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = helper;
2989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->createSurfaceTexture(mDesc.width, mDesc.height,
3009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                &mGLConsumer, &mSurface, &mTexName);
3019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
3029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mRenderer = desc.rendererFactory();
3069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mRenderer->setUp(helper);
3079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
3089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mComposer = desc.composerFactory();
3129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mComposer->setUp(desc, helper);
3139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
3149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
3189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    void tearDown() {
3219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mComposer != NULL) {
3229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mComposer->tearDown();
3239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mComposer;
3249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mComposer = NULL;
3259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mRenderer != NULL) {
3289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mRenderer->tearDown();
3299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mRenderer;
3309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mRenderer = NULL;
3319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mSurface != EGL_NO_SURFACE) {
3349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->destroySurface(&mSurface);
3359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer->abandon();
3369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = NULL;
3389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLConsumer.clear();
3399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool render() {
3429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return mRenderer->render(mSurface);
3439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool prepareComposition() {
3469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
3479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        err = mGLConsumer->updateTexImage();
3499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (err < 0) {
3509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            fprintf(stderr, "GLConsumer::updateTexImage error: %d\n", err);
3519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
3559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool compose() {
3589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return mComposer->compose(mTexName, mGLConsumer);
3599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisprivate:
3629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool mFirstFrame;
3639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    LayerDesc mDesc;
3659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLHelper* mGLHelper;
3679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLuint mTexName;
3699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<GLConsumer> mGLConsumer;
3709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mSurface;
3719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Renderer* mRenderer;
3739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Composer* mComposer;
3749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
3759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisclass BenchmarkRunner {
3779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennispublic:
3799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    BenchmarkRunner(const BenchmarkDesc& desc, size_t instance) :
3819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mDesc(desc),
3829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mInstance(instance),
3839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mNumLayers(countLayers(desc)),
3849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper(NULL),
3859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mSurface(EGL_NO_SURFACE),
3869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mWindowSurface(EGL_NO_SURFACE) {
3879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool setUp() {
3909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
3919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
3939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        EGLint resulte;
3949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        float scaleFactor = float(mDesc.runHeights[mInstance]) /
3969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            float(mDesc.height);
3979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        uint32_t w = uint32_t(scaleFactor * float(mDesc.width));
3989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        uint32_t h = mDesc.runHeights[mInstance];
3999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = new GLHelper();
4019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->setUp(shaders, NELEMS(shaders));
4029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
4039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
4049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        GLuint texName;
4079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->createSurfaceTexture(w, h, &mGLConsumer, &mSurface,
4089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                &texName);
4099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
4109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
4119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
4149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            // Scale the layer to match the current screen size.
4159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            LayerDesc ld = mDesc.layers[i];
4169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.x = int32_t(scaleFactor * float(ld.x));
4179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.y = int32_t(scaleFactor * float(ld.y));
4189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.width = uint32_t(scaleFactor * float(ld.width));
4199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.height = uint32_t(scaleFactor * float(ld.height));
4209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            // Set up the layer.
4229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].setUp(ld, mGLHelper);
4239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (g_PresentToWindow) {
4299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mGLHelper->createWindowSurface(w, h, &mSurfaceControl,
4309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    &mWindowSurface);
4319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mWindowSurface);
4369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
4429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
4439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    void tearDown() {
4459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
4469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
4489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mLayers[i].tearDown();
4499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mGLHelper != NULL) {
4529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (mWindowSurface != EGL_NO_SURFACE) {
4539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                mGLHelper->destroySurface(&mWindowSurface);
4549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->destroySurface(&mSurface);
4569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer->abandon();
4579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer.clear();
4589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mSurfaceControl.clear();
4599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->tearDown();
4609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mGLHelper;
4619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper = NULL;
4629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
4649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    nsecs_t run(uint32_t warmUpFrames, uint32_t totalFrames) {
4669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
4679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
4699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
4709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        resetColorGenerator();
4729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Do the warm-up frames.
4749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (uint32_t i = 0; i < warmUpFrames; i++) {
4759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
4789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Grab the fence for the start timestamp.
4829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        sp<Fence> startFence = mGLConsumer->getCurrentFence();
4839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        //  the timed frames.
4859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (uint32_t i = warmUpFrames; i < totalFrames; i++) {
4869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
4899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Grab the fence for the end timestamp.
4939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        sp<Fence> endFence = mGLConsumer->getCurrentFence();
4949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Keep doing frames until the end fence has signaled.
4969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        while (endFence->wait(0) == -ETIME) {
4979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
5009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Compute the time delta.
5049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        nsecs_t startTime = startFence->getSignalTime();
5059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        nsecs_t endTime = endFence->getSignalTime();
5069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return endTime - startTime;
5089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisprivate:
5119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool doFrame(EGLSurface surface) {
5139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
5149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
5159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
5179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].render();
5189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
5199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
5209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
5249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].prepareComposition();
5259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
5269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
5279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->makeCurrent(surface);
5319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
5329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
5339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
5369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        glClear(GL_COLOR_BUFFER_BIT);
5379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
5399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].compose();
5409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
5419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
5429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->swapBuffers(surface);
5469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
5479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
5489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        err = mGLConsumer->updateTexImage();
5519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (err < 0) {
5529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            fprintf(stderr, "GLConsumer::updateTexImage error: %d\n", err);
5539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
5549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
5579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    static size_t countLayers(const BenchmarkDesc& desc) {
5609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t i;
5619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (i = 0; i < MAX_NUM_LAYERS; i++) {
5629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (desc.layers[i].rendererFactory == NULL) {
5639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                break;
5649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return i;
5679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const BenchmarkDesc& mDesc;
5709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const size_t mInstance;
5719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const size_t mNumLayers;
5729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLHelper* mGLHelper;
5749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The surface into which layers are composited
5769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<GLConsumer> mGLConsumer;
5779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mSurface;
5789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // Used for displaying the surface to a window.
5809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mWindowSurface;
5819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<SurfaceControl> mSurfaceControl;
5829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Layer mLayers[MAX_NUM_LAYERS];
5849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
5859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic int cmpDouble(const double* lhs, const double* rhs) {
5879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (*lhs < *rhs) {
5889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return -1;
5899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } else if (*rhs < *lhs) {
5909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return 1;
5919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return 0;
5939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
5949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Run a single benchmark and print the result.
5969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool runTest(const BenchmarkDesc b, size_t run) {
5979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool success = true;
5989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    double prevResult = 0.0, result = 0.0;
5999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Vector<double> samples;
6009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runHeight = b.runHeights[run];
6029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runWidth = b.width * runHeight / b.height;
60392dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn    printf(" %-*s | %4d x %4d | ", static_cast<int>(g_BenchmarkNameLen), b.name,
6049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            runWidth, runHeight);
6059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fflush(stdout);
6069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    BenchmarkRunner r(b, run);
6089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (!r.setUp()) {
6099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fprintf(stderr, "error initializing runner.\n");
6109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return false;
6119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The slowest 1/outlierFraction sample results are ignored as potential
6149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // outliers.
6159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const uint32_t outlierFraction = 16;
6169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const double threshold = .0025;
6179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t warmUpFrames = 1;
6199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t totalFrames = 5;
6209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // Find the number of frames needed to run for over 100ms.
6229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    double runTime = 0.0;
6239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    while (true) {
6249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        runTime = double(r.run(warmUpFrames, totalFrames));
6259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (runTime < 50e6) {
6269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            warmUpFrames *= 2;
6279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            totalFrames *= 2;
6289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        } else {
6299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
6309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (totalFrames - warmUpFrames > 16) {
6359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // The test runs too fast to get a stable result.  Skip it.
6369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf("  fast");
6379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        goto done;
6389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } else if (totalFrames == 5 && runTime > 200e6) {
6399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // The test runs too slow to be very useful.  Skip it.
6409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf("  slow");
6419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        goto done;
6429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    do {
6459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t newSamples = samples.size();
6469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (newSamples == 0) {
6479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            newSamples = 4*outlierFraction;
6489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (newSamples > 512) {
6519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            printf("varies");
6529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            goto done;
6539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < newSamples; i++) {
6569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            double sample = double(r.run(warmUpFrames, totalFrames));
6579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (g_SleepBetweenSamplesMs > 0) {
6599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                usleep(g_SleepBetweenSamplesMs  * 1000);
6609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
6619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (sample < 0.0) {
6639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                success = false;
6649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                goto done;
6659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
6669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            samples.add(sample);
6689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        samples.sort(cmpDouble);
6719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        prevResult = result;
6739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t elem = (samples.size() * (outlierFraction-1) / outlierFraction);
6749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = (samples[elem-1] + samples[elem]) * 0.5;
6759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } while (fabs(result - prevResult) > threshold * result);
6769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("%6.3f", result / double(totalFrames - warmUpFrames) / 1e6);
6789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisdone:
6809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("\n");
6829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fflush(stdout);
6839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    r.tearDown();
6849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return success;
6869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic void printResultsTableHeader() {
6899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const char* scenario = "Scenario";
6909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t len = strlen(scenario);
6919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t leftPad = (g_BenchmarkNameLen - len) / 2;
6929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t rightPad = g_BenchmarkNameLen - len - leftPad;
69392dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn    printf(" %*s%s%*s | Resolution  | Time (ms)\n",
69492dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn            static_cast<int>(leftPad), "",
69592dc3fc52cf097bd105460cf377779bdcf146d62Mark Salyzyn            "Scenario", static_cast<int>(rightPad), "");
6969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Run ALL the benchmarks!
6999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool runTests() {
7009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printResultsTableHeader();
7019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (size_t i = 0; i < NELEMS(benchmarks); i++) {
7039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        const BenchmarkDesc& b = benchmarks[i];
7049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t j = 0; j < MAX_TEST_RUNS && b.runHeights[j]; j++) {
7059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!runTest(b, j)) {
7069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
7079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
7089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
7099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return true;
7119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
7129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Return the length longest benchmark name.
7149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic size_t maxBenchmarkNameLen() {
7159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t maxLen = 0;
7169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (size_t i = 0; i < NELEMS(benchmarks); i++) {
7179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        const BenchmarkDesc& b = benchmarks[i];
7189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t len = strlen(b.name);
7199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (len > maxLen) {
7209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            maxLen = len;
7219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
7229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return maxLen;
7249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
7259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Print the command usage help to stderr.
7279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic void showHelp(const char *cmd) {
7289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fprintf(stderr, "usage: %s [options]\n", cmd);
7299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fprintf(stderr, "options include:\n"
7309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  -s N            sleep for N ms between samples\n"
7319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  -d              display the test frame to a window\n"
7329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  --help          print this helpful message and exit\n"
7339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            );
7349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
7359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisint main(int argc, char** argv) {
7379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
7389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        showHelp(argv[0]);
7399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        exit(0);
7409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (;;) {
7439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        int ret;
7449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        int option_index = 0;
7459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        static struct option long_options[] = {
7469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {"help",     no_argument, 0,  0 },
7479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {     0,               0, 0,  0 }
7489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        };
7499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ret = getopt_long(argc, argv, "ds:",
7519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                          long_options, &option_index);
7529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (ret < 0) {
7549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
7559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
7569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        switch(ret) {
7589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 'd':
7599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                g_PresentToWindow = true;
7609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
7619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 's':
7639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                g_SleepBetweenSamplesMs = atoi(optarg);
7649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
7659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 0:
7679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                if (strcmp(long_options[option_index].name, "help")) {
7689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    showHelp(argv[0]);
7699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    exit(0);
7709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                }
7719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
7729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            default:
7749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                showHelp(argv[0]);
7759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                exit(2);
7769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
7779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    g_BenchmarkNameLen = maxBenchmarkNameLen();
7809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf(" cmdline:");
7829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (int i = 0; i < argc; i++) {
7839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf(" %s", argv[i]);
7849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("\n");
7869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (!runTests()) {
7889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fprintf(stderr, "exiting due to error.\n");
7899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return 1;
7909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
792