1 // Copyright (c) 2012 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 "media/tools/shader_bench/gpu_color_painter.h" 6 #include "ui/gl/gl_context.h" 7 8 enum { kNumYUVPlanes = 3 }; 9 10 // Matrix used for the YUV to RGB conversion. 11 static const float kYUV2RGB[9] = { 12 1.f, 0.f, 1.403f, 13 1.f, -.344f, -.714f, 14 1.f, 1.772f, 0.f, 15 }; 16 17 static const float kYUV2RGB_TRANS[9] = { 18 1.f, 1.f, 1.f, 19 0.f, -.344f, 1.772f, 20 1.403f, -.714f, 0.f, 21 }; 22 23 // Pass-through vertex shader. 24 static const char kVertexShader[] = 25 "precision highp float;\n" 26 "precision highp int;\n" 27 "varying vec2 interp_tc;\n" 28 "\n" 29 "attribute vec4 in_pos;\n" 30 "attribute vec2 in_tc;\n" 31 "\n" 32 "void main() {\n" 33 " interp_tc = in_tc;\n" 34 " gl_Position = in_pos;\n" 35 "}\n"; 36 37 // YUV to RGB pixel shader. Loads a pixel from each plane and pass through the 38 // matrix. 39 static const char kFragmentShader[] = 40 "precision mediump float;\n" 41 "precision mediump int;\n" 42 "varying vec2 interp_tc;\n" 43 "\n" 44 "uniform sampler2D y_tex;\n" 45 "uniform sampler2D u_tex;\n" 46 "uniform sampler2D v_tex;\n" 47 "uniform mat3 yuv2rgb;\n" 48 "\n" 49 "void main() {\n" 50 " float y = texture2D(y_tex, interp_tc).x;\n" 51 " float u = texture2D(u_tex, interp_tc).r - .5;\n" 52 " float v = texture2D(v_tex, interp_tc).r - .5;\n" 53 " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" 54 " gl_FragColor = vec4(rgb, 1);\n" 55 "}\n"; 56 57 GPUColorWithLuminancePainter::GPUColorWithLuminancePainter() 58 : program_id_(-1) { 59 } 60 61 GPUColorWithLuminancePainter::~GPUColorWithLuminancePainter() { 62 if (program_id_) { 63 glDeleteProgram(program_id_); 64 glDeleteTextures(kNumYUVPlanes, textures_); 65 } 66 } 67 68 void GPUColorWithLuminancePainter::Initialize(int width, int height) { 69 // Create 3 textures, one for each plane, and bind them to different 70 // texture units. 71 glGenTextures(kNumYUVPlanes, textures_); 72 73 for (unsigned int i = 0; i < kNumYUVPlanes; ++i) { 74 unsigned int texture_width = (i == media::VideoFrame::kYPlane) ? 75 width : width / 2; 76 unsigned int texture_height = (i == media::VideoFrame::kYPlane) ? 77 height : height / 2; 78 glActiveTexture(GL_TEXTURE0 + i); 79 glBindTexture(GL_TEXTURE_2D, textures_[i]); 80 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 81 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 82 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 83 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 84 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, texture_width, texture_height, 85 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0); 86 } 87 88 GLuint program = CreateShaderProgram(kVertexShader, kFragmentShader); 89 90 // Bind parameters. 91 glUniform1i(glGetUniformLocation(program, "y_tex"), 0); 92 glUniform1i(glGetUniformLocation(program, "u_tex"), 1); 93 glUniform1i(glGetUniformLocation(program, "v_tex"), 2); 94 int yuv2rgb_location = glGetUniformLocation(program, "yuv2rgb"); 95 96 // DesktopGL supports transpose matrices. 97 if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) 98 glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); 99 else 100 glUniformMatrix3fv(yuv2rgb_location, 1, GL_FALSE, kYUV2RGB_TRANS); 101 102 program_id_ = program; 103 } 104 105 void GPUColorWithLuminancePainter::Paint( 106 scoped_refptr<media::VideoFrame> video_frame) { 107 // Not accounting for x/y offset presently. 108 int width = video_frame->visible_rect().width(); 109 int height = video_frame->visible_rect().height(); 110 for (unsigned int i = 0; i < kNumYUVPlanes; ++i) { 111 unsigned int plane_width = 112 (i == media::VideoFrame::kYPlane) ? width : width / 2; 113 unsigned int plane_height = 114 (i == media::VideoFrame::kYPlane) ? height : height / 2; 115 glBindTexture(GL_TEXTURE_2D, textures_[i]); 116 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, plane_width, plane_height, 117 GL_LUMINANCE, GL_UNSIGNED_BYTE, video_frame->data(i)); 118 } 119 120 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 121 surface()->SwapBuffers(); 122 } 123