summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeng-Hui Zhu <ztenghui@google.com>2012-04-19 14:54:31 -0700
committerTeng-Hui Zhu <ztenghui@google.com>2012-04-20 09:33:49 -0700
commit2ac76fe4e18c3325c8b3bb8f9435fdc7b96c0aca (patch)
treee9a2ec93fffb786b8eccf3f4bdba490c769337e6
parent7ad2efca85a989d9ab57e311af605a6fed9c9925 (diff)
downloadexternal_webkit-2ac76fe4e18c3325c8b3bb8f9435fdc7b96c0aca.zip
external_webkit-2ac76fe4e18c3325c8b3bb8f9435fdc7b96c0aca.tar.gz
external_webkit-2ac76fe4e18c3325c8b3bb8f9435fdc7b96c0aca.tar.bz2
Better handle the EGL context lost situation.
Unless framework provide a better message, we can't avoid this EGL context issue totally if mis-match happen again. Clean up some obsolete code. Change-Id: Ica03daecd58f9757c8cad41e0f40d5d51b041748
-rw-r--r--Source/WebCore/platform/graphics/android/GLWebViewState.cpp8
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp19
-rw-r--r--Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h1
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp43
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/GLUtils.h1
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h2
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp58
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TilesManager.h7
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp35
-rw-r--r--Source/WebCore/platform/graphics/android/rendering/TransferQueue.h7
-rw-r--r--Source/WebKit/android/nav/WebView.cpp4
11 files changed, 107 insertions, 78 deletions
diff --git a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
index 8581a8e..a52a3fe 100644
--- a/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
+++ b/Source/WebCore/platform/graphics/android/GLWebViewState.cpp
@@ -323,10 +323,7 @@ int GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
if (scale < MIN_SCALE_WARNING || scale > MAX_SCALE_WARNING)
ALOGW("WARNING, scale seems corrupted before update: %e", scale);
- // Here before we draw, update the Tile which has updated content.
- // Inside this function, just do GPU blits from the transfer queue into
- // the Tiles' texture.
- tilesManager->transferQueue()->updateDirtyTiles();
+ tilesManager->updateTilesIfContextVerified();
// Upload any pending ImageTexture
// Return true if we still have some images to upload.
@@ -366,9 +363,6 @@ int GLWebViewState::drawGL(IntRect& rect, SkRect& viewport, IntRect* invalRect,
glBindBuffer(GL_ARRAY_BUFFER, 0);
- // Clean up GL textures for video layer.
- tilesManager->videoLayerManager()->deleteUnusedTextures();
-
if (returnFlags & uirenderer::DrawGlInfo::kStatusDraw) {
// returnFlags & kStatusDraw && empty inval region means we've inval'd everything,
// but don't have new content. Keep redrawing full view (0,0,0,0)
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
index 6501f98..a7b3184 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.cpp
@@ -107,16 +107,15 @@ void VideoLayerManager::initGLResourcesIfNeeded()
void VideoLayerManager::initGLResources()
{
GLUtils::checkGlError("before initGLResources()");
- if (!m_createdTexture) {
- m_spinnerOuterTextureId =
- createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER);
- m_spinnerInnerTextureId =
- createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER);
- m_posterTextureId =
- createTextureFromImage(RenderSkinMediaButton::VIDEO);
- m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY);
- m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE);
- }
+ m_spinnerOuterTextureId =
+ createTextureFromImage(RenderSkinMediaButton::SPINNER_OUTER);
+ m_spinnerInnerTextureId =
+ createTextureFromImage(RenderSkinMediaButton::SPINNER_INNER);
+ m_posterTextureId =
+ createTextureFromImage(RenderSkinMediaButton::VIDEO);
+ m_playTextureId = createTextureFromImage(RenderSkinMediaButton::PLAY);
+ m_pauseTextureId = createTextureFromImage(RenderSkinMediaButton::PAUSE);
+
m_createdTexture = !GLUtils::checkGlError("initGLResources()");
return;
}
diff --git a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
index 6c02534..adce0f4 100644
--- a/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
+++ b/Source/WebCore/platform/graphics/android/layers/VideoLayerManager.h
@@ -97,6 +97,7 @@ public:
void initGLResourcesIfNeeded();
void cleanupGLResources();
+ void forceNeedsInit() { m_createdTexture = false; }
static int getButtonSize();
private:
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
index 9435065..7206c98 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.cpp
@@ -298,49 +298,6 @@ static EGLSurface createPbufferSurface(EGLDisplay display, const EGLConfig& conf
return surface;
}
-EGLContext GLUtils::createBackgroundContext(EGLContext sharedContext)
-{
- checkEglError("<init>");
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- checkEglError("eglGetDisplay");
- if (display == EGL_NO_DISPLAY) {
- ALOGE("eglGetDisplay returned EGL_NO_DISPLAY");
- return EGL_NO_CONTEXT;
- }
-
- EGLint majorVersion;
- EGLint minorVersion;
- EGLBoolean returnValue = eglInitialize(display, &majorVersion, &minorVersion);
- checkEglError("eglInitialize", returnValue);
- if (returnValue != EGL_TRUE) {
- ALOGE("eglInitialize failed\n");
- return EGL_NO_CONTEXT;
- }
-
- EGLConfig config = defaultPbufferConfig(display);
- EGLSurface surface = createPbufferSurface(display, config, 0);
-
- EGLint surfaceConfigId;
- EGLBoolean success = eglGetConfigAttrib(display, config, EGL_CONFIG_ID, &surfaceConfigId);
-
- EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- EGLContext context = eglCreateContext(display, config, sharedContext, contextAttribs);
- checkEglError("eglCreateContext");
- if (context == EGL_NO_CONTEXT) {
- ALOGE("eglCreateContext failed\n");
- return EGL_NO_CONTEXT;
- }
-
- returnValue = eglMakeCurrent(display, surface, surface, context);
- checkEglError("eglMakeCurrent", returnValue);
- if (returnValue != EGL_TRUE) {
- ALOGE("eglMakeCurrent failed\n");
- return EGL_NO_CONTEXT;
- }
-
- return context;
-}
-
void GLUtils::deleteTexture(GLuint* texture)
{
glDeleteTextures(1, texture);
diff --git a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
index d4a2e84..a235458 100644
--- a/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
+++ b/Source/WebCore/platform/graphics/android/rendering/GLUtils.h
@@ -67,7 +67,6 @@ public:
static bool isEGLFenceSyncSupported();
// Texture utilities
- static EGLContext createBackgroundContext(EGLContext sharedContext);
static void deleteTexture(GLuint* texture);
static GLuint createSampleColorTexture(int r, int g, int b);
static GLuint createSampleTexture();
diff --git a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
index cfdccda..d93fd89 100644
--- a/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
+++ b/Source/WebCore/platform/graphics/android/rendering/ShaderProgram.h
@@ -153,7 +153,7 @@ public:
m_contrast = contrast;
}
void setGLDrawInfo(const android::uirenderer::DrawGlInfo* info);
-
+ void forceNeedsInit() { m_needsInit = true; }
bool needsInit() { return m_needsInit; }
bool usePointSampling(float tileScale, const TransformationMatrix* layerTransform);
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
index f46562a..731db23 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.cpp
@@ -96,6 +96,7 @@ TilesManager::TilesManager()
, m_drawGLCount(1)
, m_lastTimeLayersUsed(0)
, m_hasLayerTextures(false)
+ , m_eglContext(EGL_NO_CONTEXT)
{
ALOGV("TilesManager ctor");
m_textures.reserveCapacity(MAX_TEXTURE_ALLOCATION);
@@ -163,6 +164,14 @@ void TilesManager::discardTextures(bool allTextures, bool glTextures)
discardTexturesVector(sparedDrawCount, m_tilesTextures, glTextures);
}
+void TilesManager::markAllGLTexturesZero()
+{
+ for (unsigned int i = 0; i < m_textures.size(); i++)
+ m_textures[i]->m_ownTextureId = 0;
+ for (unsigned int i = 0; i < m_tilesTextures.size(); i++)
+ m_tilesTextures[i]->m_ownTextureId = 0;
+}
+
void TilesManager::discardTexturesVector(unsigned long long sparedDrawCount,
WTF::Vector<TileTexture*>& textures,
bool deallocateGLTextures)
@@ -417,6 +426,55 @@ TransferQueue* TilesManager::transferQueue()
return m_queue;
}
+// When GL context changed or we get a low memory signal, we want to cleanup all
+// the GPU memory webview is using.
+// The recreation will be on the next incoming draw call at the drawGL of
+// GLWebViewState or the VideoLayerAndroid
+void TilesManager::cleanupGLResources()
+{
+ transferQueue()->cleanupGLResourcesAndQueue();
+ shader()->cleanupGLResources();
+ videoLayerManager()->cleanupGLResources();
+ m_eglContext = EGL_NO_CONTEXT;
+ GLUtils::checkGlError("TilesManager::cleanupGLResources");
+}
+
+void TilesManager::updateTilesIfContextVerified()
+{
+ if (updateContextIfChanged()) {
+ // A change in EGL context is an unexpected error, but we don't want to
+ // crash or ANR. Therefore, abandon the Surface Texture and GL resources;
+ // they'll be recreated later in setupDrawing. (We can't delete them
+ // since the context is gone)
+ transferQueue()->resetQueue();
+ shader()->forceNeedsInit();
+ videoLayerManager()->forceNeedsInit();
+ markAllGLTexturesZero();
+ } else {
+ // Here before we draw, update the Tile which has updated content.
+ // Inside this function, just do GPU blits from the transfer queue into
+ // the Tiles' texture.
+ transferQueue()->updateDirtyTiles();
+ // Clean up GL textures for video layer.
+ videoLayerManager()->deleteUnusedTextures();
+ }
+}
+
+// Return true if context has changed, which indicate an error we should look
+// into.
+bool TilesManager::updateContextIfChanged()
+{
+ bool changed = false;
+ EGLContext ctx = eglGetCurrentContext();
+ GLUtils::checkEglError("contextChanged");
+ if (ctx != m_eglContext && m_eglContext != EGL_NO_CONTEXT) {
+ ALOGE("Unexpected : EGLContext changed! current %x , expected %x", ctx, m_eglContext);
+ changed = true;
+ }
+ m_eglContext = ctx;
+ return changed;
+}
+
float TilesManager::tileWidth()
{
return TILE_WIDTH;
diff --git a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
index 92c56d3..17d44b5 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
+++ b/Source/WebCore/platform/graphics/android/rendering/TilesManager.h
@@ -69,6 +69,9 @@ public:
TransferQueue* transferQueue();
VideoLayerManager* videoLayerManager() { return &m_videoLayerManager; }
+ void updateTilesIfContextVerified();
+ void cleanupGLResources();
+
void gatherTextures();
bool layerTexturesRemain() { return m_layerTexturesRemain; }
void gatherTexturesNumbers(int* nbTextures, int* nbAllocatedTextures,
@@ -163,6 +166,8 @@ private:
void discardTexturesVector(unsigned long long sparedDrawCount,
WTF::Vector<TileTexture*>& textures,
bool deallocateGLTextures);
+ void markAllGLTexturesZero();
+ bool updateContextIfChanged();
WTF::Vector<TileTexture*> m_textures;
WTF::Vector<TileTexture*> m_availableTextures;
@@ -201,6 +206,8 @@ private:
unsigned long long m_drawGLCount;
double m_lastTimeLayersUsed;
bool m_hasLayerTextures;
+
+ EGLContext m_eglContext;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
index 5ede167..559bd4f 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
+++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.cpp
@@ -75,14 +75,19 @@ TransferQueue::~TransferQueue()
delete[] m_transferQueue;
}
+// Set the queue to be totally empty, abandon the Surface Texture. This should
+// be called only when we hit a wrong EGL Context in an error situation.
+void TransferQueue::resetQueue()
+{
+ android::Mutex::Autolock lock(m_transferQueueItemLocks);
+ emptyAndAbandonQueue();
+ m_sharedSurfaceTextureId = 0;
+}
+
// This should be called within the m_transferQueueItemLocks.
// Now only called by emptyQueue() and destructor.
void TransferQueue::cleanupGLResources()
{
- if (m_sharedSurfaceTexture.get()) {
- m_sharedSurfaceTexture->abandon();
- m_sharedSurfaceTexture.clear();
- }
if (m_fboID) {
glDeleteFramebuffers(1, &m_fboID);
m_fboID = 0;
@@ -290,17 +295,27 @@ void TransferQueue::setHasGLContext(bool hasContext)
m_hasGLContext = hasContext;
}
-void TransferQueue::setPendingDiscardWithLock()
+// Call within a m_transferQueueItemLocks, now called by resetQueue() and
+// cleanupGLResoucesAndQueue()
+void TransferQueue::emptyAndAbandonQueue()
{
- android::Mutex::Autolock lock(m_transferQueueItemLocks);
- setPendingDiscard();
+ for (int i = 0 ; i < m_transferQueueSize; i++)
+ m_transferQueue[i].status = emptyItem;
+ m_emptyItemCount = m_transferQueueSize;
+ m_pureColorTileQueue.clear();
+
+ if (m_sharedSurfaceTexture.get()) {
+ m_sharedSurfaceTexture->abandon();
+ m_sharedSurfaceTexture.clear();
+ }
+ // This can prevent the tex gen thread to produce, until next incoming draw.
+ setHasGLContext(false);
}
-void TransferQueue::emptyQueue()
+void TransferQueue::cleanupGLResourcesAndQueue()
{
android::Mutex::Autolock lock(m_transferQueueItemLocks);
- setPendingDiscard();
- cleanupPendingDiscard();
+ emptyAndAbandonQueue();
cleanupGLResources();
}
diff --git a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
index d1024a4..fe58336 100644
--- a/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
+++ b/Source/WebCore/platform/graphics/android/rendering/TransferQueue.h
@@ -117,7 +117,6 @@ public:
// This will be called by the browser through nativeSetProperty
void setTextureUploadType(TextureUploadType type);
- void cleanupGLResources();
void updateDirtyTiles();
void initGLResources(int width, int height);
@@ -140,10 +139,10 @@ public:
void addItemInPureColorQueue(const TileRenderInfo* renderInfo);
- void setPendingDiscardWithLock();
- void emptyQueue();
+ void cleanupGLResourcesAndQueue();
bool needsInit() { return !m_sharedSurfaceTextureId; }
+ void resetQueue();
// This queue can be accessed from UI and TexGen thread, therefore, we need
// a lock to protect its access
TileTransferData* m_transferQueue;
@@ -159,6 +158,7 @@ private:
const SkBitmap& bitmap);
bool getHasGLContext();
void setHasGLContext(bool hasContext);
+ void emptyAndAbandonQueue();
int getNextTransferQueueIndex();
@@ -174,6 +174,7 @@ private:
// Before each draw call and the blit operation, clean up all the
// pendingDiscard items.
void cleanupPendingDiscard();
+ void cleanupGLResources();
void blitTileFromQueue(GLuint fboID, TileTexture* destTex,
TileTexture* frontTex,
diff --git a/Source/WebKit/android/nav/WebView.cpp b/Source/WebKit/android/nav/WebView.cpp
index d3bc62d..fbd0d94 100644
--- a/Source/WebKit/android/nav/WebView.cpp
+++ b/Source/WebKit/android/nav/WebView.cpp
@@ -1063,9 +1063,7 @@ static void nativeOnTrimMemory(JNIEnv *env, jobject obj, jint level)
&& !tilesManager->highEndGfx())
|| level >= TRIM_MEMORY_COMPLETE) {
ALOGD("OnTrimMemory with EGL Context %p", eglGetCurrentContext());
- tilesManager->transferQueue()->emptyQueue();
- tilesManager->shader()->cleanupGLResources();
- tilesManager->videoLayerManager()->cleanupGLResources();
+ tilesManager->cleanupGLResources();
}
bool freeAllTextures = (level > TRIM_MEMORY_UI_HIDDEN), glTextures = true;