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/GLConsumer.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<GLConsumer> 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