12bde8e466a4451c7319e3a072d118917957d6554Steve Block/*
22bde8e466a4451c7319e3a072d118917957d6554Steve Block * Copyright (C) 2011 Google Inc. All rights reserved.
32bde8e466a4451c7319e3a072d118917957d6554Steve Block *
42bde8e466a4451c7319e3a072d118917957d6554Steve Block * Redistribution and use in source and binary forms, with or without
52bde8e466a4451c7319e3a072d118917957d6554Steve Block * modification, are permitted provided that the following conditions
62bde8e466a4451c7319e3a072d118917957d6554Steve Block * are met:
72bde8e466a4451c7319e3a072d118917957d6554Steve Block *
82bde8e466a4451c7319e3a072d118917957d6554Steve Block * 1.  Redistributions of source code must retain the above copyright
92bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer.
102bde8e466a4451c7319e3a072d118917957d6554Steve Block * 2.  Redistributions in binary form must reproduce the above copyright
112bde8e466a4451c7319e3a072d118917957d6554Steve Block *     notice, this list of conditions and the following disclaimer in the
122bde8e466a4451c7319e3a072d118917957d6554Steve Block *     documentation and/or other materials provided with the distribution.
132bde8e466a4451c7319e3a072d118917957d6554Steve Block *
142bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
152bde8e466a4451c7319e3a072d118917957d6554Steve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
162bde8e466a4451c7319e3a072d118917957d6554Steve Block * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
172bde8e466a4451c7319e3a072d118917957d6554Steve Block * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
182bde8e466a4451c7319e3a072d118917957d6554Steve Block * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
192bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
202bde8e466a4451c7319e3a072d118917957d6554Steve Block * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
212bde8e466a4451c7319e3a072d118917957d6554Steve Block * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
222bde8e466a4451c7319e3a072d118917957d6554Steve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
232bde8e466a4451c7319e3a072d118917957d6554Steve Block * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
242bde8e466a4451c7319e3a072d118917957d6554Steve Block */
252bde8e466a4451c7319e3a072d118917957d6554Steve Block
262bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "config.h"
272bde8e466a4451c7319e3a072d118917957d6554Steve Block
282bde8e466a4451c7319e3a072d118917957d6554Steve Block#if USE(ACCELERATED_COMPOSITING)
292bde8e466a4451c7319e3a072d118917957d6554Steve Block
302bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "cc/CCVideoLayerImpl.h"
312bde8e466a4451c7319e3a072d118917957d6554Steve Block
322bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "GraphicsContext3D.h"
332bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "LayerRendererChromium.h"
342bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "NotImplemented.h"
352bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "VideoLayerChromium.h"
362bde8e466a4451c7319e3a072d118917957d6554Steve Block#include <wtf/text/WTFString.h>
372bde8e466a4451c7319e3a072d118917957d6554Steve Block
382bde8e466a4451c7319e3a072d118917957d6554Steve Blocknamespace WebCore {
392bde8e466a4451c7319e3a072d118917957d6554Steve Block
402bde8e466a4451c7319e3a072d118917957d6554Steve Block// These values are magic numbers that are used in the transformation
412bde8e466a4451c7319e3a072d118917957d6554Steve Block// from YUV to RGB color values.
422bde8e466a4451c7319e3a072d118917957d6554Steve Block// They are taken from the following webpage:
432bde8e466a4451c7319e3a072d118917957d6554Steve Block// http://www.fourcc.org/fccyvrgb.php
442bde8e466a4451c7319e3a072d118917957d6554Steve Blockconst float CCVideoLayerImpl::yuv2RGB[9] = {
452bde8e466a4451c7319e3a072d118917957d6554Steve Block    1.164f, 1.164f, 1.164f,
462bde8e466a4451c7319e3a072d118917957d6554Steve Block    0.f, -.391f, 2.018f,
472bde8e466a4451c7319e3a072d118917957d6554Steve Block    1.596f, -.813f, 0.f,
482bde8e466a4451c7319e3a072d118917957d6554Steve Block};
492bde8e466a4451c7319e3a072d118917957d6554Steve Block
502bde8e466a4451c7319e3a072d118917957d6554Steve Block// These values map to 16, 128, and 128 respectively, and are computed
512bde8e466a4451c7319e3a072d118917957d6554Steve Block// as a fraction over 256 (e.g. 16 / 256 = 0.0625).
522bde8e466a4451c7319e3a072d118917957d6554Steve Block// They are used in the YUV to RGBA conversion formula:
532bde8e466a4451c7319e3a072d118917957d6554Steve Block//   Y - 16   : Gives 16 values of head and footroom for overshooting
542bde8e466a4451c7319e3a072d118917957d6554Steve Block//   U - 128  : Turns unsigned U into signed U [-128,127]
552bde8e466a4451c7319e3a072d118917957d6554Steve Block//   V - 128  : Turns unsigned V into signed V [-128,127]
562bde8e466a4451c7319e3a072d118917957d6554Steve Blockconst float CCVideoLayerImpl::yuvAdjust[3] = {
572bde8e466a4451c7319e3a072d118917957d6554Steve Block    -0.0625f,
582bde8e466a4451c7319e3a072d118917957d6554Steve Block    -0.5f,
592bde8e466a4451c7319e3a072d118917957d6554Steve Block    -0.5f,
602bde8e466a4451c7319e3a072d118917957d6554Steve Block};
612bde8e466a4451c7319e3a072d118917957d6554Steve Block
622bde8e466a4451c7319e3a072d118917957d6554Steve BlockCCVideoLayerImpl::CCVideoLayerImpl(LayerChromium* owner)
632bde8e466a4451c7319e3a072d118917957d6554Steve Block    : CCLayerImpl(owner)
642bde8e466a4451c7319e3a072d118917957d6554Steve Block{
652bde8e466a4451c7319e3a072d118917957d6554Steve Block}
662bde8e466a4451c7319e3a072d118917957d6554Steve Block
672bde8e466a4451c7319e3a072d118917957d6554Steve BlockCCVideoLayerImpl::~CCVideoLayerImpl()
682bde8e466a4451c7319e3a072d118917957d6554Steve Block{
692bde8e466a4451c7319e3a072d118917957d6554Steve Block    cleanupResources();
702bde8e466a4451c7319e3a072d118917957d6554Steve Block}
712bde8e466a4451c7319e3a072d118917957d6554Steve Block
722bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid CCVideoLayerImpl::setTexture(size_t i, VideoLayerChromium::Texture texture)
732bde8e466a4451c7319e3a072d118917957d6554Steve Block{
742bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(i < 3);
752bde8e466a4451c7319e3a072d118917957d6554Steve Block    m_textures[i] = texture;
762bde8e466a4451c7319e3a072d118917957d6554Steve Block}
772bde8e466a4451c7319e3a072d118917957d6554Steve Block
782daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid CCVideoLayerImpl::draw(const IntRect&)
792bde8e466a4451c7319e3a072d118917957d6554Steve Block{
802bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (m_skipsDraw)
812bde8e466a4451c7319e3a072d118917957d6554Steve Block        return;
822bde8e466a4451c7319e3a072d118917957d6554Steve Block
832bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(layerRenderer());
842bde8e466a4451c7319e3a072d118917957d6554Steve Block    const RGBAProgram* rgbaProgram = layerRenderer()->videoLayerRGBAProgram();
852bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(rgbaProgram && rgbaProgram->initialized());
862bde8e466a4451c7319e3a072d118917957d6554Steve Block    const YUVProgram* yuvProgram = layerRenderer()->videoLayerYUVProgram();
872bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(yuvProgram && yuvProgram->initialized());
882bde8e466a4451c7319e3a072d118917957d6554Steve Block
892bde8e466a4451c7319e3a072d118917957d6554Steve Block    switch (m_frameFormat) {
902bde8e466a4451c7319e3a072d118917957d6554Steve Block    case VideoFrameChromium::YV12:
912bde8e466a4451c7319e3a072d118917957d6554Steve Block    case VideoFrameChromium::YV16:
922bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawYUV(yuvProgram);
932bde8e466a4451c7319e3a072d118917957d6554Steve Block        break;
942bde8e466a4451c7319e3a072d118917957d6554Steve Block    case VideoFrameChromium::RGBA:
952bde8e466a4451c7319e3a072d118917957d6554Steve Block        drawRGBA(rgbaProgram);
962bde8e466a4451c7319e3a072d118917957d6554Steve Block        break;
972bde8e466a4451c7319e3a072d118917957d6554Steve Block    default:
982bde8e466a4451c7319e3a072d118917957d6554Steve Block        // FIXME: Implement other paths.
992bde8e466a4451c7319e3a072d118917957d6554Steve Block        notImplemented();
1002bde8e466a4451c7319e3a072d118917957d6554Steve Block        break;
1012bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
1022bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1032bde8e466a4451c7319e3a072d118917957d6554Steve Block
1042bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid CCVideoLayerImpl::drawYUV(const CCVideoLayerImpl::YUVProgram* program) const
1052bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1062bde8e466a4451c7319e3a072d118917957d6554Steve Block    GraphicsContext3D* context = layerRenderer()->context();
1072bde8e466a4451c7319e3a072d118917957d6554Steve Block    VideoLayerChromium::Texture yTexture = m_textures[VideoFrameChromium::yPlane];
1082bde8e466a4451c7319e3a072d118917957d6554Steve Block    VideoLayerChromium::Texture uTexture = m_textures[VideoFrameChromium::uPlane];
1092bde8e466a4451c7319e3a072d118917957d6554Steve Block    VideoLayerChromium::Texture vTexture = m_textures[VideoFrameChromium::vPlane];
1102bde8e466a4451c7319e3a072d118917957d6554Steve Block
1112bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE1));
1122bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.id));
1132bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE2));
1142bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.id));
1152bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE3));
1162bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.id));
1172bde8e466a4451c7319e3a072d118917957d6554Steve Block
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block    layerRenderer()->useShader(program->program());
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block    float yWidthScaleFactor = static_cast<float>(yTexture.visibleSize.width()) / yTexture.size.width();
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Arbitrarily take the u sizes because u and v dimensions are identical.
1222bde8e466a4451c7319e3a072d118917957d6554Steve Block    float uvWidthScaleFactor = static_cast<float>(uTexture.visibleSize.width()) / uTexture.size.width();
1232bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
1242bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
1252bde8e466a4451c7319e3a072d118917957d6554Steve Block
1262bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1i(program->fragmentShader().yTextureLocation(), 1));
1272bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1i(program->fragmentShader().uTextureLocation(), 2));
1282bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1i(program->fragmentShader().vTextureLocation(), 3));
1292bde8e466a4451c7319e3a072d118917957d6554Steve Block
1302bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 0, const_cast<float*>(yuv2RGB), 1));
1312bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform3fv(program->fragmentShader().yuvAdjLocation(), const_cast<float*>(yuvAdjust), 1));
1322bde8e466a4451c7319e3a072d118917957d6554Steve Block
1332bde8e466a4451c7319e3a072d118917957d6554Steve Block    LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
1342bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    bounds().width(), bounds().height(), drawOpacity(),
1352bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    program->vertexShader().matrixLocation(),
1362bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    program->fragmentShader().alphaLocation());
1372bde8e466a4451c7319e3a072d118917957d6554Steve Block
1382bde8e466a4451c7319e3a072d118917957d6554Steve Block    // Reset active texture back to texture 0.
1392bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
1402bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1412bde8e466a4451c7319e3a072d118917957d6554Steve Block
1422bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid CCVideoLayerImpl::drawRGBA(const CCVideoLayerImpl::RGBAProgram* program) const
1432bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1442bde8e466a4451c7319e3a072d118917957d6554Steve Block    GraphicsContext3D* context = layerRenderer()->context();
1452bde8e466a4451c7319e3a072d118917957d6554Steve Block    VideoLayerChromium::Texture texture = m_textures[VideoFrameChromium::rgbPlane];
1462bde8e466a4451c7319e3a072d118917957d6554Steve Block
1472bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->activeTexture(GraphicsContext3D::TEXTURE0));
1482bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, texture.id));
1492bde8e466a4451c7319e3a072d118917957d6554Steve Block
1502bde8e466a4451c7319e3a072d118917957d6554Steve Block    layerRenderer()->useShader(program->program());
1512bde8e466a4451c7319e3a072d118917957d6554Steve Block    float widthScaleFactor = static_cast<float>(texture.visibleSize.width()) / texture.size.width();
1522bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
1532bde8e466a4451c7319e3a072d118917957d6554Steve Block
1542bde8e466a4451c7319e3a072d118917957d6554Steve Block    GLC(context, context->uniform1i(program->fragmentShader().samplerLocation(), 0));
1552bde8e466a4451c7319e3a072d118917957d6554Steve Block
1562bde8e466a4451c7319e3a072d118917957d6554Steve Block    LayerChromium::drawTexturedQuad(context, layerRenderer()->projectionMatrix(), drawTransform(),
1572bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    bounds().width(), bounds().height(), drawOpacity(),
1582bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    program->vertexShader().matrixLocation(),
1592bde8e466a4451c7319e3a072d118917957d6554Steve Block                                    program->fragmentShader().alphaLocation());
1602bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1612bde8e466a4451c7319e3a072d118917957d6554Steve Block
1622bde8e466a4451c7319e3a072d118917957d6554Steve Block
1632bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid CCVideoLayerImpl::dumpLayerProperties(TextStream& ts, int indent) const
1642bde8e466a4451c7319e3a072d118917957d6554Steve Block{
1652bde8e466a4451c7319e3a072d118917957d6554Steve Block    writeIndent(ts, indent);
1662bde8e466a4451c7319e3a072d118917957d6554Steve Block    ts << "video layer\n";
1672bde8e466a4451c7319e3a072d118917957d6554Steve Block    CCLayerImpl::dumpLayerProperties(ts, indent);
1682bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1692bde8e466a4451c7319e3a072d118917957d6554Steve Block
1702bde8e466a4451c7319e3a072d118917957d6554Steve Block}
1712bde8e466a4451c7319e3a072d118917957d6554Steve Block
1722bde8e466a4451c7319e3a072d118917957d6554Steve Block#endif // USE(ACCELERATED_COMPOSITING)
173