1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 28 #if USE(ACCELERATED_COMPOSITING) 29 30 #include "cc/CCVideoLayerImpl.h" 31 32 #include "GraphicsContext3D.h" 33 #include "LayerRendererChromium.h" 34 #include "NotImplemented.h" 35 #include "VideoLayerChromium.h" 36 #include <wtf/text/WTFString.h> 37 38 namespace WebCore { 39 40 // These values are magic numbers that are used in the transformation 41 // from YUV to RGB color values. 42 // They are taken from the following webpage: 43 // http://www.fourcc.org/fccyvrgb.php 44 const float CCVideoLayerImpl::yuv2RGB[9] = { 45 1.164f, 1.164f, 1.164f, 46 0.f, -.391f, 2.018f, 47 1.596f, -.813f, 0.f, 48 }; 49 50 // These values map to 16, 128, and 128 respectively, and are computed 51 // as a fraction over 256 (e.g. 16 / 256 = 0.0625). 52 // They are used in the YUV to RGBA conversion formula: 53 // Y - 16 : Gives 16 values of head and footroom for overshooting 54 // U - 128 : Turns unsigned U into signed U [-128,127] 55 // V - 128 : Turns unsigned V into signed V [-128,127] 56 const float CCVideoLayerImpl::yuvAdjust[3] = { 57 -0.0625f, 58 -0.5f, 59 -0.5f, 60 }; 61 62 CCVideoLayerImpl::CCVideoLayerImpl(LayerChromium* owner) 63 : CCLayerImpl(owner) 64 { 65 } 66 67 CCVideoLayerImpl::~CCVideoLayerImpl() 68 { 69 cleanupResources(); 70 } 71 72 void CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture) 73 { 74 ASSERT(i < 3); 75 m_textures[i] = texture; 76 } 77 78 void CCVideoLayerImpl::draw(const IntRect&) 79 { 80 if (m_skipsDraw) 81 return; 82 83 ASSERT(layerRenderer()); 84 const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram(); 85 ASSERT(rgbaProgram && rgbaProgram->initialized()); 86 const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram(); 87 ASSERT(yuvProgram && yuvProgram->initialized()); 88 89 switch (m_frameFormat) { 90 case VideoFrameChromium::YV12: 91 case VideoFrameChromium::YV16: 92 drawYUV(yuvProgram); 93 break; 94 case VideoFrameChromium::RGBA: 95 drawRGBA(rgbaProgram); 96 break; 97 default: 98 // FIXME: Implement other paths. 99 notImplemented(); 100 break; 101 } 102 } 103 104 void CCVideoLayerImpl::drawYUV(const CCVideoLayerImpl::YUVProgram* program) const 105 { 106 GraphicsContext3D* context = layerRenderer()->context(); 107 VideoLayerChromium::Texture yTexture = m_textures[VideoFrameChromium::yPlane]; 108 VideoLayerChromium::Texture uTexture = m_textures[VideoFrameChromium::uPlane]; 109 VideoLayerChromium::Texture vTexture = m_textures[VideoFrameChromium::vPlane]; 110 111 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1)); 112 GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id)); 113 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2)); 114 GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id)); 115 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3)); 116 GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id)); 117 118 layerRenderer()->useShader(program->program()); 119 120 float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width(); 121 // Arbitrarily take the u sizes because u and v dimensions are identical. 122 float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width(); 123 GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor)); 124 GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor)); 125 126 GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1)); 127 GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2)); 128 GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3)); 129 130 GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1)); 131 GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1)); 132 133 LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), 134 bounds().width(), bounds().height(), drawOpacity(), 135 program->vertexShader().matrixLocation(), 136 program->fragmentShader().alphaLocation()); 137 138 // Reset active texture back to texture 0. 139 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); 140 } 141 142 void CCVideoLayerImpl::drawRGBA(const CCVideoLayerImpl::RGBAProgram* program) const 143 { 144 GraphicsContext3D* context = layerRenderer()->context(); 145 VideoLayerChromium::Texture texture = m_textures[VideoFrameChromium::rgbPlane]; 146 147 GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0)); 148 GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture.id)); 149 150 layerRenderer()->useShader(program->program()); 151 float widthScaleFactor = static_cast<float>(texture.visibleSize.width()) / texture.size.width(); 152 GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1)); 153 154 GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0)); 155 156 LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(), 157 bounds().width(), bounds().height(), drawOpacity(), 158 program->vertexShader().matrixLocation(), 159 program->fragmentShader().alphaLocation()); 160 } 161 162 163 void CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const 164 { 165 writeIndent(ts, indent); 166 ts << "video layer\n"; 167 CCLayerImpl::dumpLayerProperties(ts, indent); 168 } 169 170 } 171 172 #endif // USE(ACCELERATED_COMPOSITING) 173