add graphics_WebGLClear client test

The graphics_WebGLClear client test is a simple test to gauge
the glClear performance on any particular client.

v2: set preserve_srcdir=True; don't bother installing again if
    version hasn't changed.

v3: minor style fixes; improved/added comment sections; change
    width/height of context; fix copyrights; fix control file
    constants; added graphics state checker to test; add test
    to perf dashboard config.

BUG=chromium:397666
TEST=Manually created/updated ebuilds, then execute:
TEST= cros_workon-{B} start autotest-deps-webgl-clear autotest-chrome
TEST= emerge-{B} autotest-deps-webgl-clear
TEST= TESTS="graphics_WebGLClear" emerge-{B} autotest-chrome
TEST= ./run_remote_tests.sh --use_emerged --remote <ip> graphics_WebGLClear

Change-Id: I67d3358eee36a52f18a88c7bf944336d913b2a7d
Signed-off-by: U. Artie Eoff <ullysses.a.eoff@intel.com>
Reviewed-on: https://chromium-review.googlesource.com/209675
Reviewed-by: Ilja Friedel <ihf@chromium.org>
Commit-Queue: Joe Konno <joe.konno@intel.com>
diff --git a/client/deps/webgl_clear/common.py b/client/deps/webgl_clear/common.py
new file mode 100644
index 0000000..be9fa80
--- /dev/null
+++ b/client/deps/webgl_clear/common.py
@@ -0,0 +1,15 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import sys
+
+dirname = os.path.dirname(sys.modules[__name__].__file__)
+# Load setup_modules from client_dir (two level up from current dir).
+client_dir = os.path.abspath(os.path.join(dirname, "..", ".."))
+sys.path.insert(0, client_dir)
+import setup_modules
+sys.path.pop(0)
+setup_modules.setup(base_path=client_dir,
+                    root_module_name="autotest_lib.client")
diff --git a/client/deps/webgl_clear/control b/client/deps/webgl_clear/control
new file mode 100644
index 0000000..a2dc94d
--- /dev/null
+++ b/client/deps/webgl_clear/control
@@ -0,0 +1,5 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+job.setup_dep(['webgl_clear'])
diff --git a/client/deps/webgl_clear/files/WebGLClear.html b/client/deps/webgl_clear/files/WebGLClear.html
new file mode 100644
index 0000000..fe88737
--- /dev/null
+++ b/client/deps/webgl_clear/files/WebGLClear.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<!--
+ * Copyright 2014 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+-->
+
+<html>
+    <head>
+    <title>WebGL Clear Test</title>
+    <script type="text/javascript" src="tdl/base.js"></script>
+    <script type="text/javascript">
+        tdl.require('tdl.fps');
+        tdl.require('tdl.webgl');
+
+        window.onload = initialize;
+
+        var g_fpsTimer; // object to measure frames per second
+
+        function initialize() {
+            var then = 0.0;
+            var last = 0.0;
+            var fpsElem = document.getElementById('fps');
+            var canvas = document.getElementById('canvas');
+            var w = 1024;
+            var h = 1024;
+
+            canvas.width = w;
+            canvas.height = h;
+
+            tdl.fps.NUM_FRAMES_TO_AVERAGE = 120;
+            g_fpsTimer = new tdl.fps.FPSTimer();
+
+            gl = tdl.webgl.setupWebGL(canvas, {alpha:false,antialias:false});
+            if (!gl) {
+                return false;
+            }
+
+            gl.clearColor(
+                Math.random(), Math.random(), Math.random(), 1.0);
+            gl.viewport(0, 0, w, h);
+
+            function render() {
+                tdl.webgl.requestAnimationFrame(render, canvas);
+
+                var now = (new Date()).getTime();
+                var elapsedTime = 0.0;
+                if (then != 0.0) {
+                    elapsedTime = now - then;
+                }
+                then = now;
+
+                g_fpsTimer.update(elapsedTime * 0.001);
+                fpsElem.innerHTML = g_fpsTimer.averageFPS;
+
+                // Regulate how often we change the clear color over time. If we
+                // were to change the color every frame then, depending on the
+                // FPS rate, this would potentially happen very very fast and is
+                // really irritating to watch.  I'm not sure how much impact
+                // changing the color really has on performance, if any.
+                // Nonetheless, changing the color periodically gives us a
+                // visual cue that somethings actually happening.
+                if (now - last > 500) {
+                    gl.clearColor(
+                        Math.random(), Math.random(), Math.random(), 1.0);
+                    last = now;
+                }
+
+                // Clear color and depth buffers
+                gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+            }
+
+            render();
+
+            return true;
+        }
+    </script>
+  </head>
+  <body>
+    <div>fps: <span id="fps"></span></div>
+    <canvas id="canvas" width="1024" height="1024" style="width: 100%; height: 100%;"></canvas>
+  </body>
+</html>
diff --git a/client/deps/webgl_clear/webgl_clear.py b/client/deps/webgl_clear/webgl_clear.py
new file mode 100755
index 0000000..03c8d27
--- /dev/null
+++ b/client/deps/webgl_clear/webgl_clear.py
@@ -0,0 +1,34 @@
+#!/usr/bin/python
+
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os, shutil
+from autotest_lib.client.bin import utils
+
+version = 1
+
+def setup(topdir):
+    """Download TDL library tarball and unpack to src/, then
+    install remaining files/ into src/.
+    @param topdir: The directory of this deps.
+    """
+    tarball = 'tdl-0.0.2.tar.gz'
+    srcdir = os.path.join(topdir, 'src')
+    filesdir = os.path.join(topdir, 'files')
+    tarball_path = os.path.join(filesdir, tarball)
+
+    shutil.rmtree(srcdir, ignore_errors=True)
+
+    if not os.path.exists(tarball_path):
+        utils.get_file(
+            'http://github.com/greggman/tdl/archive/0.0.2.tar.gz', tarball_path)
+
+    os.mkdir(srcdir)
+    utils.extract_tarball_to_dir(tarball_path, srcdir)
+    os.chdir(srcdir)
+    shutil.copy(os.path.join(filesdir, 'WebGLClear.html'), srcdir)
+
+pwd = os.getcwd()
+utils.update_version(pwd + '/src', True, version, setup, pwd)
diff --git a/client/site_tests/graphics_WebGLClear/control b/client/site_tests/graphics_WebGLClear/control
new file mode 100644
index 0000000..13c1360
--- /dev/null
+++ b/client/site_tests/graphics_WebGLClear/control
@@ -0,0 +1,19 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+AUTHOR = "chromeos-gfx"
+NAME = "graphics_WebGLClear"
+PURPOSE = "Execute the WebGL clear test suite."
+CRITERIA = "All suite tests must not crash/hang."
+SUITE = "graphics"
+TIME = "SHORT"
+TEST_CATEGORY = "Performance"
+TEST_CLASS = "graphics"
+TEST_TYPE = "client"
+
+DOC = """
+This runs the WebGL clear test.
+"""
+
+job.run_test('graphics_WebGLClear')
diff --git a/client/site_tests/graphics_WebGLClear/graphics_WebGLClear.py b/client/site_tests/graphics_WebGLClear/graphics_WebGLClear.py
new file mode 100644
index 0000000..48c3eed
--- /dev/null
+++ b/client/site_tests/graphics_WebGLClear/graphics_WebGLClear.py
@@ -0,0 +1,101 @@
+# Copyright 2014 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+This is a client side WebGL clear test that measures how many frames-per-second
+(FPS) can be achieved (possibly limited by vsync) with glClear only.  It can be
+useful to gauge that most WebGL applications won't likely achieve anything
+higher than the FPS output of this test, assuming all else equal.  It may also
+be useful to various types of graphics developers as a sanity check.  However,
+your mileage may vary and we make no claims with respect to any particular
+platform or application.
+
+This test is expected to run 30 seconds by default.  Any run that reports a FPS
+value and finishes is a PASS.  An acceptable FPS value is subjective and
+platform, driver and/or project dependent... interpretation of the FPS results
+are left up to the interested parties.
+"""
+
+import logging
+import os
+import time
+from autotest_lib.client.bin import test
+from autotest_lib.client.bin import utils
+from autotest_lib.client.common_lib import error
+from autotest_lib.client.common_lib.cros import chrome
+from autotest_lib.client.cros.graphics import graphics_utils
+
+
+class graphics_WebGLClear(test.test):
+    """WebGL clear graphics test."""
+    version = 1
+    GSC = None
+
+
+    def setup(self):
+        self.job.setup_dep(['webgl_clear'])
+
+
+    def initialize(self):
+        self.perf_keyval = {}
+        self.GSC = graphics_utils.GraphicsStateChecker()
+
+
+    def cleanup(self):
+        if self.GSC:
+            self.GSC.finalize()
+
+
+    def run_clear_test(self, browser, test_url):
+        """Runs the clear test from the given url.
+
+        @param browser: The Browser object to run the test with.
+        @param test_url: The URL to the clear test suite.
+        """
+        tab = browser.tabs.New()
+        tab.Navigate(test_url)
+        tab.Activate()
+
+        utils.wait_for_value(
+            lambda: tab.EvaluateJavaScript(
+                'if (document.readyState === "complete") {'
+                '  true;'
+                '} else {'
+                '  false;'
+                '}'),
+            expected_value=True, timeout_sec=30)
+
+        time.sleep(self.test_duration_secs)
+        avg_fps = tab.EvaluateJavaScript('g_fpsTimer.averageFPS;')
+        self.perf_keyval['avg_fps'] = avg_fps
+        self.output_perf_value(
+            description='avg_fps',
+            value=avg_fps, units='fps',
+            higher_is_better=True)
+        logging.info('Average FPS = %f', avg_fps)
+
+        tab.Close()
+
+
+    def run_once(self, test_duration_secs=30):
+        """Finds a brower with telemetry, and run the test.
+
+        @param test_duration_secs: The test duration in seconds to run the test
+                for.
+        """
+        self.test_duration_secs = test_duration_secs
+
+        # For this to have any noticable effect, SwapbuffersWait needs to be false
+        # in xorg.conf.
+        browser_args = '--disable-gpu-vsync'
+
+        with chrome.Chrome(logged_in=False, extra_browser_args=browser_args) as cr:
+            clearsrc = os.path.join(self.autodir, 'deps', 'webgl_clear', 'src')
+            if not cr.browser.SetHTTPServerDirectories(clearsrc):
+                raise error.TestError('Unable to start HTTP server')
+            test_url = cr.browser.http_server.UrlOf(
+                os.path.join(clearsrc, 'WebGLClear.html'))
+            self.run_clear_test(cr.browser, test_url)
+
+        self.write_perf_keyval(self.perf_keyval)