OSDN Git Service

Merge "Add missing calls to JavaInstance::end() in JavaNPObjectInvoke() and JavaNPObj...
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / MediaTexture.cpp
1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 #include "config.h"
17 #include "MediaTexture.h"
18 #include "TilesManager.h"
19 #include "GLUtils.h"
20 #include "MediaListener.h"
21
22 #if USE(ACCELERATED_COMPOSITING)
23
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"
30
31 #define LAYER_DEBUG
32 #undef LAYER_DEBUG
33
34 #ifdef DEBUG
35
36 #include <cutils/log.h>
37 #include <wtf/text/CString.h>
38
39 #undef XLOG
40 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "MediaTexture", __VA_ARGS__)
41
42 #else
43
44 #undef XLOG
45 #define XLOG(...)
46
47 #endif // DEBUG
48
49 namespace WebCore {
50
51 MediaTexture::MediaTexture(jobject weakWebViewRef) : android::LightRefBase<MediaTexture>()
52 {
53     m_weakWebViewRef = weakWebViewRef;
54     m_textureId = 0;
55     m_dimensions.setEmpty();
56     m_newWindowRequest = false;
57     m_newWindowReady = false;
58     m_mediaListener = new MediaListener(m_weakWebViewRef);
59 }
60
61 MediaTexture::~MediaTexture()
62 {
63     releaseNativeWindow();
64     if (m_textureId)
65         glDeleteTextures(1, &m_textureId);
66     if (m_weakWebViewRef) {
67         JNIEnv* env = JSC::Bindings::getJNIEnv();
68         env->DeleteWeakGlobalRef(m_weakWebViewRef);
69     }
70 }
71
72 void MediaTexture::initNativeWindowIfNeeded()
73 {
74     {
75         android::Mutex::Autolock lock(m_mediaLock);
76
77         if(!m_newWindowRequest)
78             return;
79
80         // reuse an existing texture if possible
81         if (!m_textureId)
82             glGenTextures(1, &m_textureId);
83
84         m_surfaceTexture = new android::SurfaceTexture(m_textureId);
85         m_surfaceTextureClient = new android::SurfaceTextureClient(m_surfaceTexture);
86
87         //setup callback
88         m_mediaListener->resetFrameAvailable();
89         m_surfaceTexture->setFrameAvailableListener(m_mediaListener);
90
91         m_newWindowRequest = false;
92         m_newWindowReady = true;
93     }
94     m_newMediaRequestCond.signal();
95 }
96
97 void MediaTexture::drawContent(const TransformationMatrix& matrix)
98 {
99     android::Mutex::Autolock lock(m_mediaLock);
100
101     if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
102             || !m_mediaListener->isFrameAvailable())
103         return;
104
105     m_surfaceTexture->updateTexImage();
106
107     bool forceBlending = ANativeWindow_getFormat(m_surfaceTextureClient.get()) == WINDOW_FORMAT_RGB_565;
108     TilesManager::instance()->shader()->drawLayerQuad(matrix, m_dimensions,
109                                                       m_textureId, 1.0f,
110                                                       forceBlending, GL_TEXTURE_EXTERNAL_OES);
111 }
112
113 void MediaTexture::drawVideo(const TransformationMatrix& matrix, const SkRect& parentBounds)
114 {
115     android::Mutex::Autolock lock(m_mediaLock);
116
117     if(!m_surfaceTexture.get() || m_dimensions.isEmpty()
118             || !m_mediaListener->isFrameAvailable())
119         return;
120
121     m_surfaceTexture->updateTexImage();
122
123     float surfaceMatrix[16];
124     m_surfaceTexture->getTransformMatrix(surfaceMatrix);
125
126     SkRect dimensions = m_dimensions;
127     dimensions.offset(parentBounds.fLeft, parentBounds.fTop);
128
129 #ifdef DEBUG
130     if (!parentBounds.contains(dimensions)) {
131         XLOG("The video exceeds is parent's bounds.");
132     }
133 #endif // DEBUG
134
135     TilesManager::instance()->shader()->drawVideoLayerQuad(matrix, surfaceMatrix,
136             dimensions, m_textureId);
137 }
138
139 ANativeWindow* MediaTexture::requestNewWindow()
140 {
141     android::Mutex::Autolock lock(m_mediaLock);
142
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();
147     }
148     // we only allow for one texture, so if one already exists return null
149     else if (m_surfaceTextureClient.get()) {
150         return 0;
151     }
152
153     m_newWindowRequest = true;
154
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);
165         }
166         checkException(env);
167     }
168
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;
174     }
175
176     if (m_surfaceTextureClient.get())
177         m_newWindowReady = false;
178
179     return m_surfaceTextureClient.get();
180 }
181
182 ANativeWindow* MediaTexture::getNativeWindow()
183 {
184     android::Mutex::Autolock lock(m_mediaLock);
185     return m_surfaceTextureClient.get();
186 }
187
188 void MediaTexture::releaseNativeWindow()
189 {
190     android::Mutex::Autolock lock(m_mediaLock);
191     m_dimensions.setEmpty();
192
193     if (m_surfaceTexture.get())
194         m_surfaceTexture->setFrameAvailableListener(0);
195
196     // clear the strong pointer references
197     m_surfaceTextureClient.clear();
198     m_surfaceTexture.clear();
199 }
200
201 void MediaTexture::setDimensions(const SkRect& dimensions)
202 {
203     android::Mutex::Autolock lock(m_mediaLock);
204     m_dimensions = dimensions;
205 }
206
207 } // namespace WebCore
208
209 #endif // USE(ACCELERATED_COMPOSITING)