diff options
Diffstat (limited to 'chrome/gpu/gpu_video_layer_glx.cc')
-rw-r--r-- | chrome/gpu/gpu_video_layer_glx.cc | 332 |
1 files changed, 0 insertions, 332 deletions
diff --git a/chrome/gpu/gpu_video_layer_glx.cc b/chrome/gpu/gpu_video_layer_glx.cc deleted file mode 100644 index d0578ad..0000000 --- a/chrome/gpu/gpu_video_layer_glx.cc +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/gpu/gpu_video_layer_glx.h" - -#include "app/gfx/gl/gl_bindings.h" -#include "chrome/common/gpu_messages.h" -#include "chrome/gpu/gpu_thread.h" -#include "chrome/gpu/gpu_view_x.h" - -// Handy constants for addressing YV12 data. -static const int kYUVPlanes = 3; -static const int kYPlane = 0; -static const int kUPlane = 1; -static const int kVPlane = 2; - -// Buffer size for shader compile errors. -static const unsigned int kErrorSize = 4096; - -// Matrix used for the YUV to RGB conversion. -static const float kYUV2RGB[9] = { - 1.f, 0.f, 1.403f, - 1.f, -.344f, -.714f, - 1.f, 1.772f, 0.f, -}; - -// Texture coordinates mapping the entire texture. -static const float kTextureCoords[8] = { - 0, 0, - 0, 1, - 1, 0, - 1, 1, -}; - -#define I915_WORKAROUND - -// Pass-through vertex shader. -static const char kVertexShader[] = - "varying vec2 interp_tc;\n" - "\n" - "attribute vec4 in_pos;\n" - "attribute vec2 in_tc;\n" - "\n" - "void main() {\n" -#if defined(I915_WORKAROUND) - " gl_TexCoord[0].st = in_tc;\n" -#else - " interp_tc = in_tc;\n" -#endif - " gl_Position = in_pos;\n" - "}\n"; - -// YUV to RGB pixel shader. Loads a pixel from each plane and pass through the -// matrix. -static const char kFragmentShader[] = - "varying vec2 interp_tc;\n" - "\n" - "uniform sampler2D y_tex;\n" - "uniform sampler2D u_tex;\n" - "uniform sampler2D v_tex;\n" - "uniform mat3 yuv2rgb;\n" - "\n" - "void main() {\n" -#if defined(I915_WORKAROUND) - " float y = texture2D(y_tex, gl_TexCoord[0].st).x;\n" - " float u = texture2D(u_tex, gl_TexCoord[0].st).r - .5;\n" - " float v = texture2D(v_tex, gl_TexCoord[0].st).r - .5;\n" - " float r = y + v * 1.403;\n" - " float g = y - u * 0.344 - v * 0.714;\n" - " float b = y + u * 1.772;\n" - " gl_FragColor = vec4(r, g, b, 1);\n" -#else - " float y = texture2D(y_tex, interp_tc).x;\n" - " float u = texture2D(u_tex, interp_tc).r - .5;\n" - " float v = texture2D(v_tex, interp_tc).r - .5;\n" - " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" - " gl_FragColor = vec4(rgb, 1);\n" -#endif - "}\n"; - - -// Assume that somewhere along the line, someone will do width * height * 4 -// with signed numbers. If the maximum value is 2**31, then 2**31 / 4 = -// 2**29 and floor(sqrt(2**29)) = 23170. - -// Max height and width for layers -static const int kMaxVideoLayerSize = 23170; - -GpuVideoLayerGLX::GpuVideoLayerGLX(GpuViewX* view, - GpuThread* gpu_thread, - int32 routing_id, - const gfx::Size& size) - : view_(view), - gpu_thread_(gpu_thread), - routing_id_(routing_id), - native_size_(size), - program_(0) { - memset(textures_, 0, sizeof(textures_)); - - // Load identity vertices. - gfx::Rect identity(0, 0, 1, 1); - CalculateVertices(identity.size(), identity, target_vertices_); - - gpu_thread_->AddRoute(routing_id_, this); - - view_->BindContext(); // Must do this before issuing OpenGl. - - // TODO(apatrick): These functions are not available in GLES2. - // glMatrixMode(GL_MODELVIEW); - - // Create 3 textures, one for each plane, and bind them to different - // texture units. - glGenTextures(kYUVPlanes, textures_); - - glBindTexture(GL_TEXTURE_2D, textures_[kYPlane]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glBindTexture(GL_TEXTURE_2D, textures_[kUPlane]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - glBindTexture(GL_TEXTURE_2D, textures_[kVPlane]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - - // Create our YUV->RGB shader. - program_ = glCreateProgram(); - GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); - const char* vs_source = kVertexShader; - int vs_size = sizeof(kVertexShader); - glShaderSource(vertex_shader, 1, &vs_source, &vs_size); - glCompileShader(vertex_shader); - int result = GL_FALSE; - glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetShaderInfoLog(vertex_shader, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glAttachShader(program_, vertex_shader); - glDeleteShader(vertex_shader); - - GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - const char* ps_source = kFragmentShader; - int ps_size = sizeof(kFragmentShader); - glShaderSource(fragment_shader, 1, &ps_source, &ps_size); - glCompileShader(fragment_shader); - result = GL_FALSE; - glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetShaderInfoLog(fragment_shader, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glAttachShader(program_, fragment_shader); - glDeleteShader(fragment_shader); - - glLinkProgram(program_); - result = GL_FALSE; - glGetProgramiv(program_, GL_LINK_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetProgramInfoLog(program_, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } -} - -GpuVideoLayerGLX::~GpuVideoLayerGLX() { - // TODO(scherkus): this seems like a bad idea.. we might be better off with - // separate Initialize()/Teardown() calls instead. - view_->BindContext(); - if (program_) { - glDeleteProgram(program_); - } - - gpu_thread_->RemoveRoute(routing_id_); -} - -void GpuVideoLayerGLX::Render(const gfx::Size& viewport_size) { - // Nothing to do if we're not visible or have no YUV data. - if (target_rect_.IsEmpty()) { - return; - } - - // Calculate the position of our quad. - CalculateVertices(viewport_size, target_rect_, target_vertices_); - - // Bind Y, U and V textures to texture units. - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textures_[kYPlane]); - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, textures_[kUPlane]); - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, textures_[kVPlane]); - - // Bind vertex/fragment shader program. - glUseProgram(program_); - - // Bind parameters. - glUniform1i(glGetUniformLocation(program_, "y_tex"), 0); - glUniform1i(glGetUniformLocation(program_, "u_tex"), 1); - glUniform1i(glGetUniformLocation(program_, "v_tex"), 2); - -#if !defined(I915_WORKAROUND) - int yuv2rgb_location = glGetUniformLocation(program_, "yuv2rgb"); - glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); -#endif - - // TODO(scherkus): instead of calculating and loading a geometry each time, - // we should store a constant geometry in a VBO and use a vertex shader. - int pos_location = glGetAttribLocation(program_, "in_pos"); - glEnableVertexAttribArray(pos_location); - glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, - target_vertices_); - - int tc_location = glGetAttribLocation(program_, "in_tc"); - glEnableVertexAttribArray(tc_location); - glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, - kTextureCoords); - - // Render! - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - - // Reset back to original state. - glDisableVertexAttribArray(pos_location); - glDisableVertexAttribArray(tc_location); - glActiveTexture(GL_TEXTURE0); - glUseProgram(0); -} - -void GpuVideoLayerGLX::OnMessageReceived(const IPC::Message& msg) { - IPC_BEGIN_MESSAGE_MAP(GpuVideoLayerGLX, msg) - IPC_MESSAGE_HANDLER(GpuMsg_PaintToVideoLayer, OnPaintToVideoLayer) - IPC_END_MESSAGE_MAP_EX() -} - -void GpuVideoLayerGLX::OnChannelConnected(int32 peer_pid) { -} - -void GpuVideoLayerGLX::OnChannelError() { - // FIXME(brettw) does this mean we aren't getting any more messages and we - // should delete outselves? - NOTIMPLEMENTED(); -} - -void GpuVideoLayerGLX::OnPaintToVideoLayer(base::ProcessId source_process_id, - TransportDIB::Id id, - const gfx::Rect& bitmap_rect) { - // TODO(scherkus): |native_size_| is set in constructor, so perhaps this check - // should be a DCHECK(). - const int width = native_size_.width(); - const int height = native_size_.height(); - const int stride = width; - - if (width <= 0 || width > kMaxVideoLayerSize || - height <= 0 || height > kMaxVideoLayerSize) - return; - - TransportDIB* dib = TransportDIB::Map(id); - if (!dib) - return; - - // Everything looks good, update our target position and size. - target_rect_ = bitmap_rect; - - // Perform colour space conversion. - uint8* planes[kYUVPlanes]; - planes[kYPlane] = reinterpret_cast<uint8*>(dib->memory()); - planes[kUPlane] = planes[kYPlane] + width * height; - planes[kVPlane] = planes[kUPlane] + ((width * height) >> 2); - - view_->BindContext(); // Must do this before issuing OpenGl. - - // Assume YV12 format. - for (int i = 0; i < kYUVPlanes; ++i) { - int plane_width = (i == kYPlane ? width : width / 2); - int plane_height = (i == kYPlane ? height : height / 2); - int plane_stride = (i == kYPlane ? stride : stride / 2); - - // Ensure that we will not read outside the shared mem region. - if (planes[i] >= planes[kYPlane] && - (dib->size() - (planes[kYPlane] - planes[i])) >= - static_cast<unsigned int>(plane_width * plane_height)) { - glActiveTexture(GL_TEXTURE0 + i); - glBindTexture(GL_TEXTURE_2D, textures_[i]); - glPixelStorei(GL_UNPACK_ROW_LENGTH, plane_stride); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, plane_width, plane_height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, planes[i]); - } - } - - // Reset back to original state. - glActiveTexture(GL_TEXTURE0); - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - glFlush(); - - // TODO(scherkus): we may not need to ACK video layer updates at all. - gpu_thread_->Send(new GpuHostMsg_PaintToVideoLayer_ACK(routing_id_)); -} - -// static -void GpuVideoLayerGLX::CalculateVertices(const gfx::Size& world, - const gfx::Rect& object, - float* vertices) { - // Don't forget GL has a flipped Y-axis! - float width = world.width(); - float height = world.height(); - - // Top left. - vertices[0] = 2.0f * (object.x() / width) - 1.0f; - vertices[1] = -2.0f * (object.y() / height) + 1.0f; - - // Bottom left. - vertices[2] = 2.0f * (object.x() / width) - 1.0f; - vertices[3] = -2.0f * (object.bottom() / height) + 1.0f; - - // Top right. - vertices[4] = 2.0f * (object.right() / width) - 1.0f; - vertices[5] = -2.0f * (object.y() / height) + 1.0f; - - // Bottom right. - vertices[6] = 2.0f * (object.right() / width) - 1.0f; - vertices[7] = -2.0f * (object.bottom() / height) + 1.0f; -} |