chromium/content/test/data/gpu/pixel_webgl_fullscreen_quad.js

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

const vertexShader = [
  "attribute vec3 pos;",
  "void main(void)",
  "{",
  "  gl_Position = vec4(pos, 1.0);",
  "}"
].join("\n");

const fragmentShader = [
  "precision mediump float;",
  "void main(void)",
  "{",
  "  gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);",
  "}"
].join("\n");

let gl;

function logOutput(s) {
  if (window.domAutomationController)
    window.domAutomationController.log(s);
  else
    console.log(s);
}

function sendResult(status, detail) {
  logOutput(status + ' ' + detail);
  if (window.domAutomationController) {
    window.domAutomationController.send(status);
  }
}

function initGL(canvas, opt_attribs)
{
  try {
    let attribs = Object.assign({ powerPreference: "low-power" },
                                opt_attribs || {});
    gl = canvas.getContext("webgl", attribs);
  } catch (e) {}
  return gl;
}

function setupShader(source, type) {
  var shader = gl.createShader(type);
  gl.shaderSource(shader, source);
  gl.compileShader(shader);
  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS))
    return null;
  return shader;
}

function setupProgram(vs_id, fs_id) {
  var vs = setupShader(vertexShader, gl.VERTEX_SHADER);
  var fs = setupShader(fragmentShader, gl.FRAGMENT_SHADER);
  if (!vs || !fs)
    return null;
  var program = gl.createProgram();
  gl.attachShader(program, vs);
  gl.attachShader(program, fs);
  gl.linkProgram(program);
  if (!gl.getProgramParameter(program, gl.LINK_STATUS))
    return null;
  gl.useProgram(program);
  return program;
}

function setupBuffer(gl) {
  var buffer = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
  var vertexData = [
    // Triangle 1
    -1.0, -1.0, 0.0,
    1.0, 1.0, 0.0,
    -1.0, 1.0, 0.0,

    // Triangle 2
    -1.0, -1.0, 0.0,
    1.0, -1.0, 0.0,
    1.0, 1.0, 0.0
  ];
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW);
}

function setupGL() {
  var program = setupProgram("shader-vs", "shader-fs");
  if (!program)
    return false;
  var posAttr = gl.getAttribLocation(program, "pos");
  gl.enableVertexAttribArray(posAttr);
  setupBuffer(gl);
  var stride = 3 * Float32Array.BYTES_PER_ELEMENT;
  gl.vertexAttribPointer(posAttr, 3, gl.FLOAT, false, stride, 0);
  gl.clearColor(0.0, 0.0, 0.0, 0.0);
  gl.viewport(0, 0, 300, 300);
  gl.disable(gl.DEPTH_TEST);
  if (gl.getError() != gl.NO_ERROR)
    return false;
  return true;
}

function drawQuad() {
  gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  gl.drawArrays(gl.TRIANGLES, 0, 6);
}

function setup(opt_attribs)
{
  let canvas = document.getElementById("c");
  initGL(canvas, opt_attribs);
  if (gl && setupGL(gl))
    return true;
  if (window.domAutomationController)
    window.domAutomationController.send('FAILURE');
  return false;
}

function drawSomeFrames(callback)
{
  let swapsBeforeCallback = 60;

  function drawSomeFramesHelper() {
    if (--swapsBeforeCallback == 0) {
      callback();
    } else {
      drawQuad();
      window.requestAnimationFrame(drawSomeFramesHelper);
    }
  }

  window.requestAnimationFrame(drawSomeFramesHelper);
}

let _runningOnDualGPUSystem = false;

function setRunningOnDualGpuSystem() {
  _runningOnDualGPUSystem = true;
}

function isRunningOnDualGpuSystem() {
  return _runningOnDualGPUSystem;
}

function getUnmaskedVendor() {
  let ext = gl.getExtension('WEBGL_debug_renderer_info');
  let renderer = gl.getParameter(ext.UNMASKED_RENDERER_WEBGL);
  if (renderer.startsWith('ANGLE'))
    return renderer;
  return gl.getParameter(ext.UNMASKED_VENDOR_WEBGL);
}

function getSplitUnmaskedVendor() {
  let vendor = getUnmaskedVendor().toLowerCase();
  // Like:
  //  Intel Inc.
  //  ATI Technologies Inc.
  // Renderer would be like:
  //  Intel(R) HD Graphics 630
  //  AMD Radeon Pro 560 OpenGL Engine
  // Handle parentheses just in case.
  return vendor.split(/[ ()]/);
}

function assertRunningOnLowPowerGpu() {
  if (!isRunningOnDualGpuSystem())
    return false;
  let tokens = getSplitUnmaskedVendor();
  if (tokens.includes('intel')) {
    logOutput('System was correctly running on Intel integrated GPU');
    return true;
  }
  sendResult(
      'FAIL',
      'System wasn\'t running on Intel integrated GPU: vendor = ' +
          getUnmaskedVendor());
  return false;
}

function assertRunningOnHighPerformanceGpu() {
  if (!isRunningOnDualGpuSystem())
    return false;
  let tokens = getSplitUnmaskedVendor();
  if (tokens.includes('ati') || tokens.includes('amd') ||
      tokens.includes('nvidia')) {
    logOutput(
        'System was correctly running on discrete GPU: ' + getUnmaskedVendor());
    return true;
  }
  sendResult(
      'FAIL',
      'System wasn\'t running on discrete GPU: vendor = ' +
          getUnmaskedVendor());
  return false;
}