15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "mojo/apps/js/bindings/gl/context.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <GLES2/gl2.h>
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/arguments.h"
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/array_buffer.h"
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/object_template_builder.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "gin/per_context_data.h"
134ad1aa43a48567659193a298fad74f55e00b3dd9Ben Murdoch#include "mojo/public/c/gles2/gles2.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "mojo/public/cpp/environment/environment.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gin {
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)template<>
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct Converter<GLboolean> {
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     GLboolean* out) {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool bool_val = false;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!Converter<bool>::FromV8(isolate, val, &bool_val))
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    *out = static_cast<GLboolean>(bool_val);
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return true;
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace mojo {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace js {
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace gl {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::WrapperInfo Context::kWrapperInfo = { gin::kEmbedderNativeGin };
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::Handle<Context> Context::Create(
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Isolate* isolate,
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    mojo::Handle handle,
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Handle<v8::Function> context_lost_callback) {
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return gin::CreateHandle(isolate,
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           new Context(isolate, handle, context_lost_callback));
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::BufferData(GLenum target, const gin::ArrayBufferView& buffer,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         GLenum usage) {
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glBufferData(target, static_cast<GLsizeiptr>(buffer.num_bytes()),
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               buffer.bytes(), usage);
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::CompileShader(const gin::Arguments& args, GLuint shader) {
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glCompileShader(shader);
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GLint compiled = 0;
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!compiled) {
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    args.ThrowTypeError(std::string("Could not compile shader: ") +
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        GetShaderInfoLog(shader));
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GLuint Context::CreateBuffer() {
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GLuint result = 0;
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGenBuffers(1, &result);
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return result;
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::DrawElements(GLenum mode, GLsizei count, GLenum type,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                           uint64_t indices) {
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This looks scary, but it's what WebGL does too:
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.1
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glDrawElements(mode, count, type, reinterpret_cast<void*>(indices));
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GLint Context::GetAttribLocation(GLuint program, const std::string& name) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return glGetAttribLocation(program, name.c_str());
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string Context::GetProgramInfoLog(GLuint program) {
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GLint info_log_length = 0;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length);
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string info_log(info_log_length, 0);
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGetProgramInfoLog(program, info_log_length, NULL, &info_log.at(0));
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return info_log;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string Context::GetShaderInfoLog(GLuint shader) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  GLint info_log_length = 0;
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string info_log(info_log_length, 0);
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glGetShaderInfoLog(shader, info_log_length, NULL, &info_log.at(0));
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return info_log;
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)GLint Context::GetUniformLocation(GLuint program, const std::string& name) {
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return glGetUniformLocation(program, name.c_str());
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::ShaderSource(GLuint shader, const std::string& source) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const char* source_chars = source.c_str();
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glShaderSource(shader, 1, &source_chars, NULL);
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::UniformMatrix4fv(GLint location, GLboolean transpose,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                               const gin::ArrayBufferView& buffer) {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glUniformMatrix4fv(location, 1, transpose,
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     static_cast<float*>(buffer.bytes()));
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::VertexAttribPointer(GLuint index, GLint size, GLenum type,
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  GLboolean normalized, GLsizei stride,
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                  uint64_t offset) {
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  glVertexAttribPointer(index, size, type, normalized, stride,
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        reinterpret_cast<void*>(offset));
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gin::ObjectTemplateBuilder Context::GetObjectTemplateBuilder(
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Isolate* isolate) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return gin::ObjectTemplateBuilder(isolate)
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("ARRAY_BUFFER", GL_ARRAY_BUFFER)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("COLOR_BUFFER_BIT", GL_COLOR_BUFFER_BIT)
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("ELEMENT_ARRAY_BUFFER", GL_ELEMENT_ARRAY_BUFFER)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("FLOAT", GL_FLOAT)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("FRAGMENT_SHADER", GL_FRAGMENT_SHADER)
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("STATIC_DRAW", GL_STATIC_DRAW)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("TRIANGLES", GL_TRIANGLES)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("UNSIGNED_SHORT", GL_UNSIGNED_SHORT)
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetValue("VERTEX_SHADER", GL_VERTEX_SHADER)
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("attachShader", glAttachShader)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("bindBuffer", glBindBuffer)
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("bufferData", BufferData)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("clear", glClear)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("clearColor", glClearColor)
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("compileShader", CompileShader)
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("createBuffer", CreateBuffer)
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("createProgram", glCreateProgram)
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("createShader", glCreateShader)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("deleteShader", glDeleteShader)
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("drawElements", DrawElements)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("enableVertexAttribArray", glEnableVertexAttribArray)
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("getAttribLocation", GetAttribLocation)
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("getProgramInfoLog", GetProgramInfoLog)
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("getShaderInfoLog", GetShaderInfoLog)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("getUniformLocation", GetUniformLocation)
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("linkProgram", glLinkProgram)
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("shaderSource", ShaderSource)
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("swapBuffers", MojoGLES2SwapBuffers)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("uniformMatrix4fv", UniformMatrix4fv)
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("useProgram", glUseProgram)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("vertexAttribPointer", VertexAttribPointer)
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      .SetMethod("viewport", glViewport);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Context::Context(v8::Isolate* isolate,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 mojo::Handle handle,
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 v8::Handle<v8::Function> context_lost_callback) {
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Context> context = isolate->GetCurrentContext();
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr();
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  context_lost_callback_.Reset(isolate, context_lost_callback);
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  context_ = MojoGLES2CreateContext(handle.value(),
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                    &ContextLostThunk,
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                    this,
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                    Environment::GetDefaultAsyncWaiter());
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoGLES2MakeCurrent(context_);
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Context::~Context() {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MojoGLES2DestroyContext(context_);
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::ContextLost() {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!runner_)
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  gin::Runner::Scope scope(runner_.get());
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  v8::Handle<v8::Function> callback = v8::Local<v8::Function>::New(
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      isolate, context_lost_callback_);
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  runner_->Call(callback, runner_->global(), 0, NULL);
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void Context::ContextLostThunk(void* closure) {
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  static_cast<Context*>(closure)->ContextLost();
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace gl
1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace js
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace mojo
188