15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/tools/player_x11/gl_video_renderer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <X11/Xutil.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/buffers.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/video_frame.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/base/yuv_convert.h" 145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gl/gl_surface.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum { kNumYUVPlanes = 3 }; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GLXContext InitGLContext(Display* display, Window window) { 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Some versions of NVIDIA's GL libGL.so include a broken version of 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // load it, and use glew to dynamically resolve symbols. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See http://code.google.com/p/chromium/issues/detail?id=16800 235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!gfx::GLSurface::InitializeOneOff()) { 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "GLSurface::InitializeOneOff failed"; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XWindowAttributes attributes; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XGetWindowAttributes(display, window, &attributes); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XVisualInfo visual_info_template; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int visual_info_count = 0; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XVisualInfo* visual_info_list = XGetVisualInfo(display, VisualIDMask, 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &visual_info_template, 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &visual_info_count); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLXContext context = NULL; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < visual_info_count && !context; ++i) { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = glXCreateContext(display, visual_info_list + i, 0, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) True /* Direct rendering */); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XFree(visual_info_list); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!context) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!glXMakeCurrent(display, window, context)) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXDestroyContext(display, context); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return context; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Matrix used for the YUV to RGB conversion. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const float kYUV2RGB[9] = { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.f, 0.f, 1.403f, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.f, -.344f, -.714f, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.f, 1.772f, 0.f, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Vertices for a full screen quad. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const float kVertices[8] = { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) -1.f, 1.f, 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) -1.f, -1.f, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.f, 1.f, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1.f, -1.f, 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pass-through vertex shader. 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kVertexShader[] = 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "varying vec2 interp_tc;\n" 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n" 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "attribute vec4 in_pos;\n" 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "attribute vec2 in_tc;\n" 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n" 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "void main() {\n" 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " interp_tc = in_tc;\n" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " gl_Position = in_pos;\n" 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "}\n"; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// YUV to RGB pixel shader. Loads a pixel from each plane and pass through the 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// matrix. 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kFragmentShader[] = 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "varying vec2 interp_tc;\n" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n" 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uniform sampler2D y_tex;\n" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uniform sampler2D u_tex;\n" 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uniform sampler2D v_tex;\n" 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "uniform mat3 yuv2rgb;\n" 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n" 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "void main() {\n" 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " float y = texture2D(y_tex, interp_tc).x;\n" 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " float u = texture2D(u_tex, interp_tc).r - .5;\n" 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " float v = texture2D(v_tex, interp_tc).r - .5;\n" 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " gl_FragColor = vec4(rgb, 1);\n" 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "}\n"; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Buffer size for compile errors. 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const unsigned int kErrorSize = 4096; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlVideoRenderer::GlVideoRenderer(Display* display, Window window) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : display_(display), 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) window_(window), 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gl_context_(NULL) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GlVideoRenderer::~GlVideoRenderer() { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXMakeCurrent(display_, 0, NULL); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXDestroyContext(display_, gl_context_); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid GlVideoRenderer::Paint( 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const scoped_refptr<media::VideoFrame>& video_frame) { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!gl_context_) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Initialize(video_frame->coded_size(), video_frame->visible_rect()); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert YUV frame to RGB. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(video_frame->format() == media::VideoFrame::YV12 || 121c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch video_frame->format() == media::VideoFrame::I420 || 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_frame->format() == media::VideoFrame::YV16); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_frame->stride(media::VideoFrame::kVPlane)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (glXGetCurrentContext() != gl_context_ || 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXGetCurrentDrawable() != window_) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXMakeCurrent(display_, window_, gl_context_); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < kNumYUVPlanes; ++i) { 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int width = video_frame->stride(i); 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int height = video_frame->rows(i); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glActiveTexture(GL_TEXTURE0 + i); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glPixelStorei(GL_UNPACK_ROW_LENGTH, video_frame->stride(i)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GL_LUMINANCE, GL_UNSIGNED_BYTE, video_frame->data(i)); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXSwapBuffers(display_, window_); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GlVideoRenderer::Initialize(gfx::Size coded_size, gfx::Rect visible_rect) { 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!gl_context_); 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) VLOG(0) << "Initializing GL Renderer..."; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Resize the window to fit that of the video. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XResizeWindow(display_, window_, visible_rect.width(), visible_rect.height()); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gl_context_ = InitGLContext(display_, window_); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(gl_context_) << "Failed to initialize GL context"; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create 3 textures, one for each plane, and bind them to different 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // texture units. 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGenTextures(3, textures_); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glActiveTexture(GL_TEXTURE0); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glBindTexture(GL_TEXTURE_2D, textures_[0]); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glEnable(GL_TEXTURE_2D); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glActiveTexture(GL_TEXTURE1); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glBindTexture(GL_TEXTURE_2D, textures_[1]); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glEnable(GL_TEXTURE_2D); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glActiveTexture(GL_TEXTURE2); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glBindTexture(GL_TEXTURE_2D, textures_[2]); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glEnable(GL_TEXTURE_2D); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint program = glCreateProgram(); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Create our YUV->RGB shader. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* vs_source = kVertexShader; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int vs_size = sizeof(kVertexShader); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glShaderSource(vertex_shader, 1, &vs_source, &vs_size); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glCompileShader(vertex_shader); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = GL_FALSE; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &result); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char log[kErrorSize]; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = 0; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetShaderInfoLog(vertex_shader, kErrorSize - 1, &len, log); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log[kErrorSize - 1] = 0; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << log; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glAttachShader(program, vertex_shader); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteShader(vertex_shader); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* ps_source = kFragmentShader; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ps_size = sizeof(kFragmentShader); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glShaderSource(fragment_shader, 1, &ps_source, &ps_size); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glCompileShader(fragment_shader); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = GL_FALSE; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &result); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char log[kErrorSize]; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = 0; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetShaderInfoLog(fragment_shader, kErrorSize - 1, &len, log); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log[kErrorSize - 1] = 0; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << log; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glAttachShader(program, fragment_shader); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteShader(fragment_shader); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glLinkProgram(program); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = GL_FALSE; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetProgramiv(program, GL_LINK_STATUS, &result); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char log[kErrorSize]; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int len = 0; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glGetProgramInfoLog(program, kErrorSize - 1, &len, log); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) log[kErrorSize - 1] = 0; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(FATAL) << log; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glUseProgram(program); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glDeleteProgram(program); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Bind parameters. 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glUniform1i(glGetUniformLocation(program, "y_tex"), 0); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glUniform1i(glGetUniformLocation(program, "u_tex"), 1); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glUniform1i(glGetUniformLocation(program, "v_tex"), 2); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int yuv2rgb_location = glGetUniformLocation(program, "yuv2rgb"); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pos_location = glGetAttribLocation(program, "in_pos"); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glEnableVertexAttribArray(pos_location); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tc_location = glGetAttribLocation(program, "in_tc"); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glEnableVertexAttribArray(tc_location); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float verts[8]; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float x0 = static_cast<float>(visible_rect.x()) / coded_size.width(); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float y0 = static_cast<float>(visible_rect.y()) / coded_size.height(); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float x1 = static_cast<float>(visible_rect.right()) / coded_size.width(); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) float y1 = static_cast<float>(visible_rect.bottom()) / coded_size.height(); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verts[0] = x0; verts[1] = y0; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verts[2] = x0; verts[3] = y1; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verts[4] = x1; verts[5] = y0; 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verts[6] = x1; verts[7] = y1; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, verts); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We are getting called on a thread. Release the context so that it can be 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // made current on the main thread. 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) glXMakeCurrent(display_, 0, NULL); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 252