1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/apps/js/bindings/gl/context.h" 6 7 #include <GLES2/gl2.h> 8 9 #include "gin/arguments.h" 10 #include "gin/array_buffer.h" 11 #include "gin/object_template_builder.h" 12 #include "gin/per_context_data.h" 13 #include "mojo/public/c/gles2/gles2.h" 14 15 namespace gin { 16 template<> 17 struct Converter<GLboolean> { 18 static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, 19 GLboolean* out) { 20 bool bool_val = false; 21 if (!Converter<bool>::FromV8(isolate, val, &bool_val)) 22 return false; 23 *out = static_cast<GLboolean>(bool_val); 24 return true; 25 } 26 }; 27 } 28 29 namespace mojo { 30 namespace js { 31 namespace gl { 32 33 gin::WrapperInfo Context::kWrapperInfo = { gin::kEmbedderNativeGin }; 34 35 gin::Handle<Context> Context::Create( 36 v8::Isolate* isolate, 37 mojo::Handle handle, 38 v8::Handle<v8::Function> context_lost_callback) { 39 return gin::CreateHandle(isolate, 40 new Context(isolate, handle, context_lost_callback)); 41 } 42 43 void Context::BufferData(GLenum target, const gin::ArrayBufferView& buffer, 44 GLenum usage) { 45 glBufferData(target, static_cast<GLsizeiptr>(buffer.num_bytes()), 46 buffer.bytes(), usage); 47 } 48 49 void Context::CompileShader(const gin::Arguments& args, GLuint shader) { 50 glCompileShader(shader); 51 GLint compiled = 0; 52 glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); 53 if (!compiled) { 54 args.ThrowTypeError(std::string("Could not compile shader: ") + 55 GetShaderInfoLog(shader)); 56 } 57 } 58 59 GLuint Context::CreateBuffer() { 60 GLuint result = 0; 61 glGenBuffers(1, &result); 62 return result; 63 } 64 65 void Context::DrawElements(GLenum mode, GLsizei count, GLenum type, 66 uint64_t indices) { 67 // This looks scary, but it's what WebGL does too: 68 // http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.1 69 glDrawElements(mode, count, type, reinterpret_cast<void*>(indices)); 70 } 71 72 GLint Context::GetAttribLocation(GLuint program, const std::string& name) { 73 return glGetAttribLocation(program, name.c_str()); 74 } 75 76 std::string Context::GetProgramInfoLog(GLuint program) { 77 GLint info_log_length = 0; 78 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_log_length); 79 std::string info_log(info_log_length, 0); 80 glGetProgramInfoLog(program, info_log_length, NULL, &info_log.at(0)); 81 return info_log; 82 } 83 84 std::string Context::GetShaderInfoLog(GLuint shader) { 85 GLint info_log_length = 0; 86 glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &info_log_length); 87 std::string info_log(info_log_length, 0); 88 glGetShaderInfoLog(shader, info_log_length, NULL, &info_log.at(0)); 89 return info_log; 90 } 91 92 GLint Context::GetUniformLocation(GLuint program, const std::string& name) { 93 return glGetUniformLocation(program, name.c_str()); 94 } 95 96 void Context::ShaderSource(GLuint shader, const std::string& source) { 97 const char* source_chars = source.c_str(); 98 glShaderSource(shader, 1, &source_chars, NULL); 99 } 100 101 void Context::UniformMatrix4fv(GLint location, GLboolean transpose, 102 const gin::ArrayBufferView& buffer) { 103 glUniformMatrix4fv(location, 1, transpose, 104 static_cast<float*>(buffer.bytes())); 105 } 106 107 void Context::VertexAttribPointer(GLuint index, GLint size, GLenum type, 108 GLboolean normalized, GLsizei stride, 109 uint64_t offset) { 110 glVertexAttribPointer(index, size, type, normalized, stride, 111 reinterpret_cast<void*>(offset)); 112 } 113 114 gin::ObjectTemplateBuilder Context::GetObjectTemplateBuilder( 115 v8::Isolate* isolate) { 116 return gin::ObjectTemplateBuilder(isolate) 117 .SetValue("ARRAY_BUFFER", GL_ARRAY_BUFFER) 118 .SetValue("COLOR_BUFFER_BIT", GL_COLOR_BUFFER_BIT) 119 .SetValue("ELEMENT_ARRAY_BUFFER", GL_ELEMENT_ARRAY_BUFFER) 120 .SetValue("FLOAT", GL_FLOAT) 121 .SetValue("FRAGMENT_SHADER", GL_FRAGMENT_SHADER) 122 .SetValue("STATIC_DRAW", GL_STATIC_DRAW) 123 .SetValue("TRIANGLES", GL_TRIANGLES) 124 .SetValue("UNSIGNED_SHORT", GL_UNSIGNED_SHORT) 125 .SetValue("VERTEX_SHADER", GL_VERTEX_SHADER) 126 .SetMethod("attachShader", glAttachShader) 127 .SetMethod("bindBuffer", glBindBuffer) 128 .SetMethod("bufferData", BufferData) 129 .SetMethod("clear", glClear) 130 .SetMethod("clearColor", glClearColor) 131 .SetMethod("compileShader", CompileShader) 132 .SetMethod("createBuffer", CreateBuffer) 133 .SetMethod("createProgram", glCreateProgram) 134 .SetMethod("createShader", glCreateShader) 135 .SetMethod("deleteShader", glDeleteShader) 136 .SetMethod("drawElements", DrawElements) 137 .SetMethod("enableVertexAttribArray", glEnableVertexAttribArray) 138 .SetMethod("getAttribLocation", GetAttribLocation) 139 .SetMethod("getProgramInfoLog", GetProgramInfoLog) 140 .SetMethod("getShaderInfoLog", GetShaderInfoLog) 141 .SetMethod("getUniformLocation", GetUniformLocation) 142 .SetMethod("linkProgram", glLinkProgram) 143 .SetMethod("shaderSource", ShaderSource) 144 .SetMethod("swapBuffers", MojoGLES2SwapBuffers) 145 .SetMethod("uniformMatrix4fv", UniformMatrix4fv) 146 .SetMethod("useProgram", glUseProgram) 147 .SetMethod("vertexAttribPointer", VertexAttribPointer) 148 .SetMethod("viewport", glViewport); 149 } 150 151 Context::Context(v8::Isolate* isolate, 152 mojo::Handle handle, 153 v8::Handle<v8::Function> context_lost_callback) { 154 v8::Handle<v8::Context> context = isolate->GetCurrentContext(); 155 runner_ = gin::PerContextData::From(context)->runner()->GetWeakPtr(); 156 context_lost_callback_.Reset(isolate, context_lost_callback); 157 context_ = MojoGLES2CreateContext( 158 handle.value(), 159 &ContextLostThunk, 160 NULL, 161 this); 162 MojoGLES2MakeCurrent(context_); 163 } 164 165 Context::~Context() { 166 MojoGLES2DestroyContext(context_); 167 } 168 169 void Context::ContextLost() { 170 if (!runner_) 171 return; 172 gin::Runner::Scope scope(runner_.get()); 173 v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); 174 175 v8::Handle<v8::Function> callback = v8::Local<v8::Function>::New( 176 isolate, context_lost_callback_); 177 178 runner_->Call(callback, runner_->global(), 0, NULL); 179 } 180 181 void Context::ContextLostThunk(void* closure) { 182 static_cast<Context*>(closure)->ContextLost(); 183 } 184 185 } // namespace gl 186 } // namespace js 187 } // namespace mojo 188