Main.cpp revision e3c697fb929c856b59fa56a8e05a2a7eba187c3d
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>
219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <gui/GLConsumer.h>
22e3c697fb929c856b59fa56a8e05a2a7eba187c3dMathias Agopian#include <gui/Surface.h>
239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <ui/Fence.h>
249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <utils/Trace.h>
259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <EGL/egl.h>
279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <GLES2/gl2.h>
289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <math.h>
309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include <getopt.h>
319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include "Flatland.h"
339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis#include "GLHelper.h"
349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisusing namespace ::android;
369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic uint32_t g_SleepBetweenSamplesMs = 0;
389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool     g_PresentToWindow       = false;
399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic size_t   g_BenchmarkNameLen      = 0;
409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstruct BenchmarkDesc {
429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The name of the test.
439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const char* name;
449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The dimensions of the space in which window layers are specified.
469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t width;
479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t height;
489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The screen heights at which to run the test.
509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runHeights[MAX_TEST_RUNS];
519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The list of window layers.
539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    LayerDesc layers[MAX_NUM_LAYERS];
549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic const BenchmarkDesc benchmarks[] = {
579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 Single Static Window",
589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        2560, 1600, { 800, 1600, 2400 },
599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Window
619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 App -> Home Transition",
769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        2560, 1600, { 800, 1600, 2400 },
779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Wallpaper
799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Launcher
839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blend,
849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing activity
879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
1009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
1019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    { "16:10 SurfaceView -> Home Transition",
1029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        2560, 1600, { 800, 1600, 2400 },
1039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        {
1049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Wallpaper
1059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Launcher
1099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blend,
1109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    50,     2560,   1454,
1119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing SurfaceView
1139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
1149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
1159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Outgoing activity
1179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, blendShrink,
1189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                20,    70,     2520,   1414,
1199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Status bar
1219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    0,      2560,   50,
1239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {   // Navigation bar
1259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0, staticGradient, opaque,
1269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                0,    1504,   2560,   96,
1279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            },
1289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
1309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
1319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
1329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic const ShaderDesc shaders[] = {
1339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    {
1349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        name: "Blit",
1359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        vertexShader: {
1369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
1379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 position;",
1399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 uv;",
1409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying vec4 texCoords;",
1429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 objToNdc;",
1449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 uvToTex;",
1459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
1479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_Position = objToNdc * position;",
1489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    texCoords = uvToTex * uv;",
1499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
1509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fragmentShader: {
1529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "#extension GL_OES_EGL_image_external : require",
1539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
1549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying vec4 texCoords;",
1569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform samplerExternalOES blitSrc;",
1589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 modColor;",
1599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
1619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor = texture2D(blitSrc, texCoords.xy);",
1629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor *= modColor;",
1639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
1649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
1669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
1679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    {
1689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        name: "Gradient",
1699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        vertexShader: {
1709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
1719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 position;",
1739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "attribute vec4 uv;",
1749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying float interp;",
1769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 objToNdc;",
1789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform mat4 uvToInterp;",
1799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
1819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_Position = objToNdc * position;",
1829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    interp = (uvToInterp * uv).x;",
1839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
1849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
1859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fragmentShader: {
1869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "precision mediump float;",
1879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "varying float interp;",
1899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 color0;",
1919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform vec4 color1;",
1929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform sampler2D ditherKernel;",
1949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform float invDitherKernelSize;",
1959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "uniform float invDitherKernelSizeSq;",
1969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "",
1979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "void main() {",
1989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    float dither = texture2D(ditherKernel,",
1999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "            gl_FragCoord.xy * invDitherKernelSize).a;",
2009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    dither *= invDitherKernelSizeSq;",
2019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    vec4 color = mix(color0, color1, clamp(interp, 0.0, 1.0));",
2029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "    gl_FragColor = color + vec4(dither, dither, dither, 0.0);",
2039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "}",
2049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        },
2059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    },
2069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
2079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisclass Layer {
2099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennispublic:
2119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Layer() :
2139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mFirstFrame(true),
2149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper(NULL),
2159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mSurface(EGL_NO_SURFACE) {
2169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool setUp(const LayerDesc& desc, GLHelper* helper) {
2199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
2209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mDesc = desc;
2229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = helper;
2239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->createSurfaceTexture(mDesc.width, mDesc.height,
2259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                &mGLConsumer, &mSurface, &mTexName);
2269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
2279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
2289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mRenderer = desc.rendererFactory();
2319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mRenderer->setUp(helper);
2329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
2339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
2349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mComposer = desc.composerFactory();
2379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mComposer->setUp(desc, helper);
2389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
2399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
2409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
2439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    void tearDown() {
2469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mComposer != NULL) {
2479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mComposer->tearDown();
2489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mComposer;
2499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mComposer = NULL;
2509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mRenderer != NULL) {
2539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mRenderer->tearDown();
2549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mRenderer;
2559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mRenderer = NULL;
2569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mSurface != EGL_NO_SURFACE) {
2599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->destroySurface(&mSurface);
2609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer->abandon();
2619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = NULL;
2639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLConsumer.clear();
2649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool render() {
2679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return mRenderer->render(mSurface);
2689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool prepareComposition() {
2719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
2729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        err = mGLConsumer->updateTexImage();
2749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (err < 0) {
2759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            fprintf(stderr, "GLConsumer::updateTexImage error: %d\n", err);
2769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
2779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
2789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
2809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool compose() {
2839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return mComposer->compose(mTexName, mGLConsumer);
2849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
2859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisprivate:
2879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool mFirstFrame;
2889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    LayerDesc mDesc;
2909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLHelper* mGLHelper;
2929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLuint mTexName;
2949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<GLConsumer> mGLConsumer;
2959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mSurface;
2969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
2979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Renderer* mRenderer;
2989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Composer* mComposer;
2999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
3009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisclass BenchmarkRunner {
3029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennispublic:
3049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    BenchmarkRunner(const BenchmarkDesc& desc, size_t instance) :
3069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mDesc(desc),
3079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mInstance(instance),
3089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mNumLayers(countLayers(desc)),
3099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper(NULL),
3109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mSurface(EGL_NO_SURFACE),
3119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mWindowSurface(EGL_NO_SURFACE) {
3129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool setUp() {
3159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
3169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
3189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        EGLint resulte;
3199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        float scaleFactor = float(mDesc.runHeights[mInstance]) /
3219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            float(mDesc.height);
3229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        uint32_t w = uint32_t(scaleFactor * float(mDesc.width));
3239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        uint32_t h = mDesc.runHeights[mInstance];
3249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        mGLHelper = new GLHelper();
3269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->setUp(shaders, NELEMS(shaders));
3279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
3289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        GLuint texName;
3329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->createSurfaceTexture(w, h, &mGLConsumer, &mSurface,
3339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                &texName);
3349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
3359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
3369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
3399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            // Scale the layer to match the current screen size.
3409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            LayerDesc ld = mDesc.layers[i];
3419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.x = int32_t(scaleFactor * float(ld.x));
3429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.y = int32_t(scaleFactor * float(ld.y));
3439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.width = uint32_t(scaleFactor * float(ld.width));
3449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            ld.height = uint32_t(scaleFactor * float(ld.height));
3459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            // Set up the layer.
3479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].setUp(ld, mGLHelper);
3489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
3499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
3509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
3519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (g_PresentToWindow) {
3549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mGLHelper->createWindowSurface(w, h, &mSurfaceControl,
3559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    &mWindowSurface);
3569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
3579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
3589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
3599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mWindowSurface);
3619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
3629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
3639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
3649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
3679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    void tearDown() {
3709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
3719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
3739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mLayers[i].tearDown();
3749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (mGLHelper != NULL) {
3779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (mWindowSurface != EGL_NO_SURFACE) {
3789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                mGLHelper->destroySurface(&mWindowSurface);
3799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
3809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->destroySurface(&mSurface);
3819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer->abandon();
3829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLConsumer.clear();
3839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mSurfaceControl.clear();
3849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper->tearDown();
3859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            delete mGLHelper;
3869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            mGLHelper = NULL;
3879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
3889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
3899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    nsecs_t run(uint32_t warmUpFrames, uint32_t totalFrames) {
3919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ATRACE_CALL();
3929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
3949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
3959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        resetColorGenerator();
3979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
3989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Do the warm-up frames.
3999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (uint32_t i = 0; i < warmUpFrames; i++) {
4009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
4039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Grab the fence for the start timestamp.
4079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        sp<Fence> startFence = mGLConsumer->getCurrentFence();
4089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        //  the timed frames.
4109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (uint32_t i = warmUpFrames; i < totalFrames; i++) {
4119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
4149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Grab the fence for the end timestamp.
4189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        sp<Fence> endFence = mGLConsumer->getCurrentFence();
4199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Keep doing frames until the end fence has signaled.
4219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        while (endFence->wait(0) == -ETIME) {
4229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = doFrame(mSurface);
4239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return -1;
4259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // Compute the time delta.
4299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        nsecs_t startTime = startFence->getSignalTime();
4309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        nsecs_t endTime = endFence->getSignalTime();
4319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return endTime - startTime;
4339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
4349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisprivate:
4369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool doFrame(EGLSurface surface) {
4389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        bool result;
4399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        status_t err;
4409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
4429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].render();
4439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
4499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].prepareComposition();
4509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->makeCurrent(surface);
4569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
4579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
4589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
4619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        glClear(GL_COLOR_BUFFER_BIT);
4629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < mNumLayers; i++) {
4649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            result = mLayers[i].compose();
4659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!result) {
4669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
4679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = mGLHelper->swapBuffers(surface);
4719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (!result) {
4729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
4739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        err = mGLConsumer->updateTexImage();
4769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (err < 0) {
4779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            fprintf(stderr, "GLConsumer::updateTexImage error: %d\n", err);
4789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            return false;
4799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return true;
4829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
4839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    static size_t countLayers(const BenchmarkDesc& desc) {
4859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t i;
4869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (i = 0; i < MAX_NUM_LAYERS; i++) {
4879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (desc.layers[i].rendererFactory == NULL) {
4889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                break;
4899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
4909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
4919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return i;
4929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
4939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const BenchmarkDesc& mDesc;
4959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const size_t mInstance;
4969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const size_t mNumLayers;
4979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
4989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    GLHelper* mGLHelper;
4999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The surface into which layers are composited
5019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<GLConsumer> mGLConsumer;
5029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mSurface;
5039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // Used for displaying the surface to a window.
5059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    EGLSurface mWindowSurface;
5069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    sp<SurfaceControl> mSurfaceControl;
5079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Layer mLayers[MAX_NUM_LAYERS];
5099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis};
5109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic int cmpDouble(const double* lhs, const double* rhs) {
5129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (*lhs < *rhs) {
5139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return -1;
5149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } else if (*rhs < *lhs) {
5159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return 1;
5169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return 0;
5189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
5199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Run a single benchmark and print the result.
5219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool runTest(const BenchmarkDesc b, size_t run) {
5229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    bool success = true;
5239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    double prevResult = 0.0, result = 0.0;
5249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    Vector<double> samples;
5259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runHeight = b.runHeights[run];
5279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t runWidth = b.width * runHeight / b.height;
5289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf(" %-*s | %4d x %4d | ", g_BenchmarkNameLen, b.name,
5299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            runWidth, runHeight);
5309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fflush(stdout);
5319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    BenchmarkRunner r(b, run);
5339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (!r.setUp()) {
5349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fprintf(stderr, "error initializing runner.\n");
5359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return false;
5369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // The slowest 1/outlierFraction sample results are ignored as potential
5399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // outliers.
5409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const uint32_t outlierFraction = 16;
5419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const double threshold = .0025;
5429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t warmUpFrames = 1;
5449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    uint32_t totalFrames = 5;
5459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    // Find the number of frames needed to run for over 100ms.
5479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    double runTime = 0.0;
5489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    while (true) {
5499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        runTime = double(r.run(warmUpFrames, totalFrames));
5509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (runTime < 50e6) {
5519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            warmUpFrames *= 2;
5529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            totalFrames *= 2;
5539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        } else {
5549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
5559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (totalFrames - warmUpFrames > 16) {
5609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // The test runs too fast to get a stable result.  Skip it.
5619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf("  fast");
5629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        goto done;
5639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } else if (totalFrames == 5 && runTime > 200e6) {
5649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        // The test runs too slow to be very useful.  Skip it.
5659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf("  slow");
5669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        goto done;
5679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
5689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    do {
5709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t newSamples = samples.size();
5719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (newSamples == 0) {
5729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            newSamples = 4*outlierFraction;
5739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (newSamples > 512) {
5769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            printf("varies");
5779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            goto done;
5789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t i = 0; i < newSamples; i++) {
5819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            double sample = double(r.run(warmUpFrames, totalFrames));
5829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (g_SleepBetweenSamplesMs > 0) {
5849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                usleep(g_SleepBetweenSamplesMs  * 1000);
5859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (sample < 0.0) {
5889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                success = false;
5899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                goto done;
5909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
5919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            samples.add(sample);
5939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
5949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        samples.sort(cmpDouble);
5969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
5979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        prevResult = result;
5989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t elem = (samples.size() * (outlierFraction-1) / outlierFraction);
5999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        result = (samples[elem-1] + samples[elem]) * 0.5;
6009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    } while (fabs(result - prevResult) > threshold * result);
6019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("%6.3f", result / double(totalFrames - warmUpFrames) / 1e6);
6039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisdone:
6059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("\n");
6079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fflush(stdout);
6089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    r.tearDown();
6099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return success;
6119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic void printResultsTableHeader() {
6149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    const char* scenario = "Scenario";
6159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t len = strlen(scenario);
6169c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t leftPad = (g_BenchmarkNameLen - len) / 2;
6179c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t rightPad = g_BenchmarkNameLen - len - leftPad;
6189c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf(" %*s%s%*s | Resolution  | Time (ms)\n", leftPad, "",
6199c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            "Scenario", rightPad, "");
6209c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6219c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6229c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Run ALL the benchmarks!
6239c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic bool runTests() {
6249c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printResultsTableHeader();
6259c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6269c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (size_t i = 0; i < NELEMS(benchmarks); i++) {
6279c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        const BenchmarkDesc& b = benchmarks[i];
6289c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        for (size_t j = 0; j < MAX_TEST_RUNS && b.runHeights[j]; j++) {
6299c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            if (!runTest(b, j)) {
6309c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                return false;
6319c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            }
6329c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6339c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6349c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return true;
6359c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6369c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6379c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Return the length longest benchmark name.
6389c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic size_t maxBenchmarkNameLen() {
6399c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    size_t maxLen = 0;
6409c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (size_t i = 0; i < NELEMS(benchmarks); i++) {
6419c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        const BenchmarkDesc& b = benchmarks[i];
6429c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        size_t len = strlen(b.name);
6439c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (len > maxLen) {
6449c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            maxLen = len;
6459c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6469c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6479c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    return maxLen;
6489c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6499c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6509c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis// Print the command usage help to stderr.
6519c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisstatic void showHelp(const char *cmd) {
6529c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fprintf(stderr, "usage: %s [options]\n", cmd);
6539c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    fprintf(stderr, "options include:\n"
6549c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  -s N            sleep for N ms between samples\n"
6559c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  -d              display the test frame to a window\n"
6569c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    "  --help          print this helpful message and exit\n"
6579c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            );
6589c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
6599c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6609c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennisint main(int argc, char** argv) {
6619c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
6629c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        showHelp(argv[0]);
6639c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        exit(0);
6649c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
6659c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6669c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (;;) {
6679c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        int ret;
6689c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        int option_index = 0;
6699c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        static struct option long_options[] = {
6709c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {"help",     no_argument, 0,  0 },
6719c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            {     0,               0, 0,  0 }
6729c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        };
6739c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6749c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        ret = getopt_long(argc, argv, "ds:",
6759c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                          long_options, &option_index);
6769c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6779c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        if (ret < 0) {
6789c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
6799c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
6809c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6819c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        switch(ret) {
6829c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 'd':
6839c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                g_PresentToWindow = true;
6849c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
6859c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6869c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 's':
6879c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                g_SleepBetweenSamplesMs = atoi(optarg);
6889c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
6899c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6909c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            case 0:
6919c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                if (strcmp(long_options[option_index].name, "help")) {
6929c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    showHelp(argv[0]);
6939c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                    exit(0);
6949c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                }
6959c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            break;
6969c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
6979c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis            default:
6989c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                showHelp(argv[0]);
6999c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis                exit(2);
7009c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        }
7019c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7029c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7039c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    g_BenchmarkNameLen = maxBenchmarkNameLen();
7049c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7059c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf(" cmdline:");
7069c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    for (int i = 0; i < argc; i++) {
7079c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        printf(" %s", argv[i]);
7089c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7099c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    printf("\n");
7109c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis
7119c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    if (!runTests()) {
7129c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        fprintf(stderr, "exiting due to error.\n");
7139c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis        return 1;
7149c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis    }
7159c183f2493222000fa512d927cfde3f4c748eda0Jamie Gennis}
716