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 #include "config.h" 27 #include "VideoLayerAndroid.h" 28 29 #include "RenderSkinMediaButton.h" 30 #include "TilesManager.h" 31 #include <GLES2/gl2.h> 32 #include <gui/SurfaceTexture.h> 33 34 #if USE(ACCELERATED_COMPOSITING) 35 36 #ifdef DEBUG 37 #include <cutils/log.h> 38 #include <wtf/text/CString.h> 39 40 #undef XLOG 41 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "VideoLayerAndroid", __VA_ARGS__) 42 43 #else 44 45 #undef XLOG 46 #define XLOG(...) 47 48 #endif // DEBUG 49 50 namespace WebCore { 51 52 GLuint VideoLayerAndroid::m_spinnerOuterTextureId = 0; 53 GLuint VideoLayerAndroid::m_spinnerInnerTextureId = 0; 54 GLuint VideoLayerAndroid::m_posterTextureId = 0; 55 GLuint VideoLayerAndroid::m_backgroundTextureId = 0; 56 bool VideoLayerAndroid::m_createdTexture = false; 57 58 double VideoLayerAndroid::m_rotateDegree = 0; 59 60 const IntRect VideoLayerAndroid::buttonRect(0, 0, IMAGESIZE, IMAGESIZE); 61 62 VideoLayerAndroid::VideoLayerAndroid() 63 : LayerAndroid((RenderLayer*)0) 64 { 65 init(); 66 } 67 68 VideoLayerAndroid::VideoLayerAndroid(const VideoLayerAndroid& layer) 69 : LayerAndroid(layer) 70 { 71 init(); 72 } 73 74 void VideoLayerAndroid::init() 75 { 76 // m_surfaceTexture is only useful on UI thread, no need to copy. 77 // And it will be set at setBaseLayer timeframe 78 m_playerState = INITIALIZED; 79 } 80 81 // We can use this function to set the Layer to point to surface texture. 82 void VideoLayerAndroid::setSurfaceTexture(sp<SurfaceTexture> texture, 83 int textureName, PlayerState playerState) 84 { 85 m_surfaceTexture = texture; 86 m_playerState = playerState; 87 TilesManager::instance()->videoLayerManager()->registerTexture(uniqueId(), textureName); 88 } 89 90 GLuint VideoLayerAndroid::createSpinnerInnerTexture() 91 { 92 return createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER); 93 } 94 95 GLuint VideoLayerAndroid::createSpinnerOuterTexture() 96 { 97 return createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER); 98 } 99 100 GLuint VideoLayerAndroid::createPosterTexture() 101 { 102 return createTextureFromImage(RenderSkinMediaButton::VIDEO); 103 } 104 105 GLuint VideoLayerAndroid::createTextureFromImage(int buttonType) 106 { 107 SkRect rect = SkRect(buttonRect); 108 SkBitmap bitmap; 109 bitmap.setConfig(SkBitmap::kARGB_8888_Config, rect.width(), rect.height()); 110 bitmap.allocPixels(); 111 bitmap.eraseColor(0); 112 113 SkCanvas canvas(bitmap); 114 canvas.drawARGB(0, 0, 0, 0, SkXfermode::kClear_Mode); 115 RenderSkinMediaButton::Draw(&canvas, buttonRect, buttonType, true); 116 117 GLuint texture; 118 glGenTextures(1, &texture); 119 120 GLUtils::createTextureWithBitmap(texture, bitmap); 121 bitmap.reset(); 122 return texture; 123 } 124 125 GLuint VideoLayerAndroid::createBackgroundTexture() 126 { 127 GLuint texture; 128 glGenTextures(1, &texture); 129 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 130 GLubyte pixels[4 *3] = { 131 128, 128, 128, 132 128, 128, 128, 133 128, 128, 128, 134 128, 128, 128 135 }; 136 glBindTexture(GL_TEXTURE_2D, texture); 137 GLUtils::checkGlError("glBindTexture"); 138 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels); 139 GLUtils::checkGlError("glTexImage2D"); 140 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 141 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 142 return texture; 143 } 144 145 bool VideoLayerAndroid::drawGL() 146 { 147 // Lazily allocated the textures. 148 if (!m_createdTexture) { 149 m_backgroundTextureId = createBackgroundTexture(); 150 m_spinnerOuterTextureId = createSpinnerOuterTexture(); 151 m_spinnerInnerTextureId = createSpinnerInnerTexture(); 152 m_posterTextureId = createPosterTexture(); 153 m_createdTexture = true; 154 } 155 156 SkRect rect = SkRect::MakeSize(getSize()); 157 GLfloat surfaceMatrix[16]; 158 159 SkRect innerRect = SkRect(buttonRect); 160 if (innerRect.contains(rect)) 161 innerRect = rect; 162 163 innerRect.offset((rect.width() - IMAGESIZE) / 2 , (rect.height() - IMAGESIZE) / 2); 164 165 // Draw the poster image, the progressing image or the Video depending 166 // on the player's state. 167 if (m_playerState == PREPARING) { 168 // Show the progressing animation, with two rotating circles 169 TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, 170 m_backgroundTextureId, 171 1, true); 172 173 TransformationMatrix addReverseRotation; 174 TransformationMatrix addRotation = m_drawTransform; 175 addRotation.translate(innerRect.fLeft, innerRect.fTop); 176 addRotation.translate(IMAGESIZE / 2, IMAGESIZE / 2); 177 addReverseRotation = addRotation; 178 addRotation.rotate(m_rotateDegree); 179 addRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); 180 181 SkRect size = SkRect::MakeWH(innerRect.width(), innerRect.height()); 182 TilesManager::instance()->shader()->drawLayerQuad(addRotation, size, 183 m_spinnerOuterTextureId, 184 1, true); 185 186 addReverseRotation.rotate(-m_rotateDegree); 187 addReverseRotation.translate(-IMAGESIZE / 2, -IMAGESIZE / 2); 188 189 TilesManager::instance()->shader()->drawLayerQuad(addReverseRotation, size, 190 m_spinnerInnerTextureId, 191 1, true); 192 193 m_rotateDegree += ROTATESTEP; 194 195 } else if (m_playerState == PLAYING && m_surfaceTexture.get()) { 196 // Show the real video. 197 m_surfaceTexture->updateTexImage(); 198 m_surfaceTexture->getTransformMatrix(surfaceMatrix); 199 GLuint textureId = 200 TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); 201 TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, 202 surfaceMatrix, 203 rect, textureId); 204 TilesManager::instance()->videoLayerManager()->updateMatrix(uniqueId(), 205 surfaceMatrix); 206 } else { 207 GLuint textureId = 208 TilesManager::instance()->videoLayerManager()->getTextureId(uniqueId()); 209 GLfloat* matrix = 210 TilesManager::instance()->videoLayerManager()->getMatrix(uniqueId()); 211 if (textureId && matrix) { 212 // Show the screen shot for each video. 213 TilesManager::instance()->shader()->drawVideoLayerQuad(m_drawTransform, 214 matrix, 215 rect, textureId); 216 } else { 217 // Show the static poster b/c there is no screen shot available. 218 TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, rect, 219 m_backgroundTextureId, 220 1, true); 221 TilesManager::instance()->shader()->drawLayerQuad(m_drawTransform, innerRect, 222 m_posterTextureId, 223 1, true); 224 } 225 } 226 227 return drawChildrenGL(); 228 } 229 230 } 231 #endif // USE(ACCELERATED_COMPOSITING) 232