Home | History | Annotate | Download | only in layers
      1 /*
      2  * Copyright 2011 The Android Open Source Project
      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  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #define LOG_TAG "VideoLayerAndroid"
     27 #define LOG_NDEBUG 1
     28 
     29 #include "config.h"
     30 #include "VideoLayerAndroid.h"
     31 
     32 #include "AndroidLog.h"
     33 #include "DrawQuadData.h"
     34 #include "ShaderProgram.h"
     35 #include "TilesManager.h"
     36 #include <GLES2/gl2.h>
     37 #include <gui/SurfaceTexture.h>
     38 
     39 #if USE(ACCELERATED_COMPOSITING)
     40 
     41 namespace WebCore {
     42 
     43 double VideoLayerAndroid::m_rotateDegree = 0;
     44 
     45 VideoLayerAndroid::VideoLayerAndroid()
     46     : LayerAndroid((RenderLayer*)0)
     47 {
     48     init();
     49 }
     50 
     51 VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer)
     52     : LayerAndroid(layer)
     53 {
     54     init();
     55 }
     56 
     57 void VideoLayerAndroid::init()
     58 {
     59     // m_surfaceTexture is only useful on UI thread, no need to copy.
     60     // And it will be set at setBaseLayer timeframe
     61     m_playerState = INITIALIZED;
     62 }
     63 
     64 // We can use this function to set the Layer to point to surface texture.
     65 void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture,
     66                                           int textureName, PlayerState playerState)
     67 {
     68     m_surfaceTexture = texture;
     69     m_playerState = playerState;
     70     TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName);
     71 }
     72 
     73 void VideoLayerAndroid::showPreparingAnimation(const SkRect& rect,
     74                                                const SkRect innerRect)
     75 {
     76     ShaderProgram* shader = TilesManager::instance()->shader();
     77     VideoLayerManager* manager = TilesManager::instance()->videoLayerManager();
     78     // Paint the video content's background.
     79     PureColorQuadData backGroundQuadData(Color(128, 128, 128, 255), LayerQuad,
     80                                          &m_drawTransform, &rect);
     81     shader->drawQuad(&backGroundQuadData);
     82 
     83     TransformationMatrix addReverseRotation;
     84     TransformationMatrix addRotation = m_drawTransform;
     85     addRotation.translate(innerRect.fLeft, innerRect.fTop);
     86     double halfButtonSize = manager->getButtonSize() / 2;
     87     addRotation.translate(halfButtonSize, halfButtonSize);
     88     addReverseRotation = addRotation;
     89     addRotation.rotate(m_rotateDegree);
     90     addRotation.translate(-halfButtonSize, -halfButtonSize);
     91 
     92     SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height());
     93 
     94     TextureQuadData spinnerQuadData(manager->getSpinnerOuterTextureId(),
     95                                     GL_TEXTURE_2D, GL_LINEAR,
     96                                     LayerQuad, &addRotation, &size);
     97     shader->drawQuad(&spinnerQuadData);
     98 
     99     addReverseRotation.rotate(-m_rotateDegree);
    100     addReverseRotation.translate(-halfButtonSize, -halfButtonSize);
    101 
    102     spinnerQuadData.updateTextureId(manager->getSpinnerInnerTextureId());
    103     spinnerQuadData.updateDrawMatrix(&addReverseRotation);
    104     shader->drawQuad(&spinnerQuadData);
    105 
    106     m_rotateDegree += ROTATESTEP;
    107 }
    108 
    109 SkRect VideoLayerAndroid::calVideoRect(const SkRect& rect)
    110 {
    111     SkRect videoRect = rect;
    112     VideoLayerManager* manager = TilesManager::instance()->videoLayerManager();
    113     float aspectRatio = manager->getAspectRatio(uniqueId());
    114     float deltaY = rect.height() - rect.width() / aspectRatio;
    115     if (deltaY >= 0)
    116         videoRect.inset(0, deltaY / 2);
    117     else {
    118         float deltaX = rect.width() - rect.height() * aspectRatio;
    119         if (deltaX >= 0)
    120             videoRect.inset(deltaX / 2, 0);
    121     }
    122     return videoRect;
    123 }
    124 
    125 bool VideoLayerAndroid::drawGL(bool layerTilesDisabled)
    126 {
    127     // Lazily allocated the textures.
    128     TilesManager* tilesManager = TilesManager::instance();
    129     VideoLayerManager* manager = tilesManager->videoLayerManager();
    130     manager->initGLResourcesIfNeeded();
    131 
    132     ShaderProgram* shader = tilesManager->shader();
    133 
    134     SkRect rect = SkRect::MakeSize(getSize());
    135     GLfloat surfaceMatrix[16];
    136 
    137     // Calculate the video rect based on the aspect ratio and the element rect.
    138     SkRect videoRect = calVideoRect(rect);
    139     PureColorQuadData pureColorQuadData(Color(0, 0, 0, 255), LayerQuad,
    140                                         &m_drawTransform, &rect);
    141 
    142     if (videoRect != rect) {
    143         // Paint the whole video element with black color when video content
    144         // can't cover the whole area.
    145         shader->drawQuad(&pureColorQuadData);
    146     }
    147 
    148     // Inner rect is for the progressing / play / pause animation.
    149     SkRect innerRect = SkRect::MakeWH(manager->getButtonSize(),
    150                                       manager->getButtonSize());
    151     if (innerRect.contains(videoRect))
    152         innerRect = videoRect;
    153     double buttonSize = manager->getButtonSize();
    154     innerRect.offset(videoRect.fLeft + (videoRect.width() - buttonSize) / 2,
    155                      videoRect.fTop + (videoRect.height() - buttonSize) / 2);
    156 
    157     // When we are drawing the animation of the play/pause button in the
    158     // middle of the video, we need to ask for redraw.
    159     bool needRedraw = false;
    160     TextureQuadData iconQuadData(0, GL_TEXTURE_2D, GL_LINEAR, LayerQuad,
    161                                  &m_drawTransform, &innerRect);
    162     // Draw the poster image, the progressing image or the Video depending
    163     // on the player's state.
    164     if (m_playerState == PREPARING) {
    165         // Show the progressing animation, with two rotating circles
    166         showPreparingAnimation(videoRect, innerRect);
    167         needRedraw = true;
    168     } else if (m_playerState == PLAYING && m_surfaceTexture.get()) {
    169         // Show the real video.
    170         m_surfaceTexture->updateTexImage();
    171         m_surfaceTexture->getTransformMatrix(surfaceMatrix);
    172         GLuint textureId = manager->getTextureId(uniqueId());
    173         shader->drawVideoLayerQuad(m_drawTransform, surfaceMatrix,
    174                                    videoRect, textureId);
    175         manager->updateMatrix(uniqueId(), surfaceMatrix);
    176 
    177         // Use the scale to control the fading the sizing during animation
    178         double scale = manager->drawIcon(uniqueId(), PlayIcon);
    179         if (scale) {
    180             innerRect.inset(manager->getButtonSize() / 4 * scale,
    181                             manager->getButtonSize() / 4 * scale);
    182             iconQuadData.updateTextureId(manager->getPlayTextureId());
    183             iconQuadData.updateOpacity(scale);
    184             shader->drawQuad(&iconQuadData);
    185             needRedraw = true;
    186         }
    187     } else {
    188         GLuint textureId = manager->getTextureId(uniqueId());
    189         GLfloat* matrix = manager->getMatrix(uniqueId());
    190         if (textureId && matrix) {
    191             // Show the screen shot for each video.
    192             shader->drawVideoLayerQuad(m_drawTransform, matrix,
    193                                        videoRect, textureId);
    194         } else {
    195             // Show the static poster b/c there is no screen shot available.
    196             pureColorQuadData.updateColor(Color(128, 128, 128, 255));
    197             shader->drawQuad(&pureColorQuadData);
    198 
    199             iconQuadData.updateTextureId(manager->getPosterTextureId());
    200             iconQuadData.updateOpacity(1.0);
    201             shader->drawQuad(&iconQuadData);
    202         }
    203 
    204         // Use the scale to control the fading and the sizing during animation.
    205         double scale = manager->drawIcon(uniqueId(), PauseIcon);
    206         if (scale) {
    207             innerRect.inset(manager->getButtonSize() / 4 * scale,
    208                             manager->getButtonSize() / 4 * scale);
    209             iconQuadData.updateTextureId(manager->getPauseTextureId());
    210             iconQuadData.updateOpacity(scale);
    211             shader->drawQuad(&iconQuadData);
    212             needRedraw = true;
    213         }
    214 
    215     }
    216     return needRedraw;
    217 }
    218 
    219 }
    220 #endif // USE(ACCELERATED_COMPOSITING)
    221