2 * Copyright (C) 2011 The Android Open Source Project
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "MediaTexture.h"
18 #include "TilesManager.h"
20 #include "MediaListener.h"
22 #if USE(ACCELERATED_COMPOSITING)
24 #include <android/native_window.h>
25 #include <gui/SurfaceTexture.h>
26 #include <gui/SurfaceTextureClient.h>
27 #include <wtf/CurrentTime.h>
28 #include <JNIUtility.h>
29 #include "WebCoreJni.h"
36 #include <cutils/log.h>
37 #include <wtf/text/CString.h>
40 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaTexture", __VA_ARGS__)
51 MediaTexture::MediaTexture(jobject weakWebViewRef) : android::LightRefBase<MediaTexture>()
53 m_weakWebViewRef = weakWebViewRef;
55 m_dimensions.setEmpty();
56 m_newWindowRequest = false;
57 m_newWindowReady = false;
58 m_mediaListener = new MediaListener(m_weakWebViewRef);
61 MediaTexture::~MediaTexture()
63 releaseNativeWindow();
65 glDeleteTextures(1, &m_textureId);
66 if (m_weakWebViewRef) {
67 JNIEnv* env = JSC::Bindings::getJNIEnv();
68 env->DeleteWeakGlobalRef(m_weakWebViewRef);
72 void MediaTexture::initNativeWindowIfNeeded()
75 android::Mutex::Autolock lock(m_mediaLock);
77 if(!m_newWindowRequest)
80 // reuse an existing texture if possible
82 glGenTextures(1, &m_textureId);
84 m_surfaceTexture = new android::SurfaceTexture(m_textureId);
85 m_surfaceTextureClient = new android::SurfaceTextureClient(m_surfaceTexture);
88 m_mediaListener->resetFrameAvailable();
89 m_surfaceTexture->setFrameAvailableListener(m_mediaListener);
91 m_newWindowRequest = false;
92 m_newWindowReady = true;
94 m_newMediaRequestCond.signal();
97 void MediaTexture::drawContent(const TransformationMatrix& matrix)
99 android::Mutex::Autolock lock(m_mediaLock);
101 if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
102 || !m_mediaListener->isFrameAvailable())
105 m_surfaceTexture->updateTexImage();
107 bool forceBlending = ANativeWindow_getFormat(m_surfaceTextureClient.get()) == WINDOW_FORMAT_RGB_565;
108 TilesManager::instance()->shader()->drawLayerQuad(matrix, m_dimensions,
110 forceBlending, GL_TEXTURE_EXTERNAL_OES);
113 void MediaTexture::drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds)
115 android::Mutex::Autolock lock(m_mediaLock);
117 if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
118 || !m_mediaListener->isFrameAvailable())
121 m_surfaceTexture->updateTexImage();
123 float surfaceMatrix[16];
124 m_surfaceTexture->getTransformMatrix(surfaceMatrix);
126 SkRect dimensions = m_dimensions;
127 dimensions.offset(parentBounds.fLeft, parentBounds.fTop);
130 if (!parentBounds.contains(dimensions)) {
131 XLOG("The video exceeds is parent's bounds.");
135 TilesManager::instance()->shader()->drawVideoLayerQuad(matrix, surfaceMatrix,
136 dimensions, m_textureId);
139 ANativeWindow* MediaTexture::requestNewWindow()
141 android::Mutex::Autolock lock(m_mediaLock);
143 // the window was not ready before the timeout so return it this time
144 if (m_newWindowReady) {
145 m_newWindowReady = false;
146 return m_surfaceTextureClient.get();
148 // we only allow for one texture, so if one already exists return null
149 else if (m_surfaceTextureClient.get()) {
153 m_newWindowRequest = true;
155 // post an inval message to the UI thread to fulfill the request
156 if (m_weakWebViewRef) {
157 JNIEnv* env = JSC::Bindings::getJNIEnv();
158 jobject localWebViewRef = env->NewLocalRef(m_weakWebViewRef);
159 if (localWebViewRef) {
160 jclass wvClass = env->GetObjectClass(localWebViewRef);
161 jmethodID postInvalMethod = env->GetMethodID(wvClass, "postInvalidate", "()V");
162 env->CallVoidMethod(localWebViewRef, postInvalMethod);
163 env->DeleteLocalRef(wvClass);
164 env->DeleteLocalRef(localWebViewRef);
169 //block until the request can be fulfilled or we time out
170 bool timedOut = false;
171 while (m_newWindowRequest && !timedOut) {
172 int ret = m_newMediaRequestCond.waitRelative(m_mediaLock, 500000000); // .5 sec
173 timedOut = ret == TIMED_OUT;
176 if (m_surfaceTextureClient.get())
177 m_newWindowReady = false;
179 return m_surfaceTextureClient.get();
182 ANativeWindow* MediaTexture::getNativeWindow()
184 android::Mutex::Autolock lock(m_mediaLock);
185 return m_surfaceTextureClient.get();
188 void MediaTexture::releaseNativeWindow()
190 android::Mutex::Autolock lock(m_mediaLock);
191 m_dimensions.setEmpty();
193 if (m_surfaceTexture.get())
194 m_surfaceTexture->setFrameAvailableListener(0);
196 // clear the strong pointer references
197 m_surfaceTextureClient.clear();
198 m_surfaceTexture.clear();
201 void MediaTexture::setDimensions(const SkRect& dimensions)
203 android::Mutex::Autolock lock(m_mediaLock);
204 m_dimensions = dimensions;
207 } // namespace WebCore
209 #endif // USE(ACCELERATED_COMPOSITING)