diff options
author | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-18 00:25:04 +0000 |
---|---|---|
committer | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-18 00:25:04 +0000 |
commit | cafa295eb0c24cd3d8b5518bfe3d83544552888a (patch) | |
tree | a38ce1c2f6e6ea04335d37211571b200723bae9d /ui/gl | |
parent | 1270ea67ad7abc29d7ac452b41e14cb1656b7f5d (diff) | |
download | chromium_src-cafa295eb0c24cd3d8b5518bfe3d83544552888a.zip chromium_src-cafa295eb0c24cd3d8b5518bfe3d83544552888a.tar.gz chromium_src-cafa295eb0c24cd3d8b5518bfe3d83544552888a.tar.bz2 |
gpu: Fix Vivante's "hisilicon" GPUs
This fixes "Hisilicon" GPUs, which is an instance of a
Vivante's GPU design. This involves enabling virtual
contexts, since they don't support share-groups, and further
adds a work-around for switching surfaces. Without the work-
around the view surface "inherits" the size of the last
bound surface (which for Chrome tends to be a 1x1 pbuffer)
resulting in a black screen. The following steps "repair"
the view surface every time it is made current:
- Make it current.
- Bind the default frame-buffer.
- Make it not current.
- Destroy/recreate it from the native handle.
- Make it current again.
NOTE: The "Recreate" function is added to surface because
the Destroy/Initialize may be intercepted or modified by
wrapper surface classes. Recreate is similar to resize,
which after being forwarded by a wrapper can call
Destroy/Initialize on the 'real' surface.
BUG=179250, 229643
NOTRY=true
No try, since it's Android only and already tested.
Review URL: https://chromiumcodereview.appspot.com/13140006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194737 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gl')
-rw-r--r-- | ui/gl/gl_context_egl.cc | 36 | ||||
-rw-r--r-- | ui/gl/gl_context_egl.h | 2 | ||||
-rw-r--r-- | ui/gl/gl_surface.cc | 24 | ||||
-rw-r--r-- | ui/gl/gl_surface.h | 11 | ||||
-rw-r--r-- | ui/gl/gl_surface_egl.cc | 22 | ||||
-rw-r--r-- | ui/gl/gl_surface_egl.h | 4 |
6 files changed, 94 insertions, 5 deletions
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc index 52c60e2..c29eb2a 100644 --- a/ui/gl/gl_context_egl.cc +++ b/ui/gl/gl_context_egl.cc @@ -112,6 +112,9 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) { return false; } + if (!RecreateSurfaceIfNeeded(surface)) + return false; + if (!surface->OnMakeCurrent(this)) { LOG(ERROR) << "Could not make current."; return false; @@ -121,6 +124,39 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) { return true; } +bool GLContextEGL::RecreateSurfaceIfNeeded(GLSurface* surface) { + if (!surface || !surface->RecreateOnMakeCurrent()) + return true; + + // This is specifically needed for Vivante GPU's on Android. + // A native view surface will not be configured correctly + // unless we do all of the following steps after making the + // surface current. + GLint fbo = 0; + glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo); + glBindFramebufferEXT(GL_FRAMEBUFFER, 0); + + eglMakeCurrent(display_, + EGL_NO_SURFACE, + EGL_NO_SURFACE, + EGL_NO_CONTEXT); + if (!surface->Recreate()) { + LOG(ERROR) << "Failed to recreate surface"; + return false; + } + if (!eglMakeCurrent(display_, + surface->GetHandle(), + surface->GetHandle(), + context_)) { + LOG(ERROR) << "eglMakeCurrent failed with error " + << GetLastEGLErrorString(); + return false; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + return true; +} + void GLContextEGL::ReleaseCurrent(GLSurface* surface) { if (!IsCurrent(surface)) return; diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h index e45cc25..ea61976 100644 --- a/ui/gl/gl_context_egl.h +++ b/ui/gl/gl_context_egl.h @@ -36,6 +36,8 @@ class GLContextEGL : public GLContext { virtual bool WasAllocatedUsingRobustnessExtension() OVERRIDE; virtual bool GetTotalGpuMemory(size_t* bytes) OVERRIDE; + bool RecreateSurfaceIfNeeded(GLSurface* surface); + protected: virtual ~GLContextEGL(); diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc index 0feeb34..fc271a2 100644 --- a/ui/gl/gl_surface.cc +++ b/ui/gl/gl_surface.cc @@ -84,6 +84,11 @@ bool GLSurface::Resize(const gfx::Size& size) { return false; } +bool GLSurface::Recreate() { + NOTIMPLEMENTED(); + return false; +} + bool GLSurface::DeferDraws() { return false; } @@ -145,6 +150,13 @@ VSyncProvider* GLSurface::GetVSyncProvider() { return NULL; } +bool GLSurface::RecreateOnMakeCurrent() { + return false; +} + +void GLSurface::SetRecreateOnMakeCurrent(bool recreate) { +} + GLSurface* GLSurface::GetCurrent() { return current_surface_.Pointer()->Get(); } @@ -185,6 +197,10 @@ bool GLSurfaceAdapter::Resize(const gfx::Size& size) { return surface_->Resize(size); } +bool GLSurfaceAdapter::Recreate() { + return surface_->Recreate(); +} + bool GLSurfaceAdapter::DeferDraws() { return surface_->DeferDraws(); } @@ -249,6 +265,14 @@ VSyncProvider* GLSurfaceAdapter::GetVSyncProvider() { return surface_->GetVSyncProvider(); } +bool GLSurfaceAdapter::RecreateOnMakeCurrent() { + return surface_->RecreateOnMakeCurrent(); +} + +void GLSurfaceAdapter::SetRecreateOnMakeCurrent(bool recreate) { + surface_->SetRecreateOnMakeCurrent(recreate); +} + GLSurfaceAdapter::~GLSurfaceAdapter() {} } // namespace gfx diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h index 6924685..ac2be89 100644 --- a/ui/gl/gl_surface.h +++ b/ui/gl/gl_surface.h @@ -39,6 +39,9 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { virtual bool Resize(const gfx::Size& size); + // Recreate the surface without changing the size. + virtual bool Recreate(); + // Unschedule the GpuScheduler and return true to abort the processing of // a GL draw call to this surface and defer it until the GpuScheduler is // rescheduled. @@ -102,6 +105,11 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> { // of screen refresh. If unavailable, returns NULL. virtual VSyncProvider* GetVSyncProvider(); + // Certain surfaces need to be destroyed and recreated + // every time they are made the current surface. + virtual bool RecreateOnMakeCurrent(); + virtual void SetRecreateOnMakeCurrent(bool recreate); + // Create a GL surface that renders directly to a view. static scoped_refptr<GLSurface> CreateViewGLSurface( bool software, @@ -137,6 +145,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface { virtual bool Initialize() OVERRIDE; virtual void Destroy() OVERRIDE; virtual bool Resize(const gfx::Size& size) OVERRIDE; + virtual bool Recreate() OVERRIDE; virtual bool DeferDraws() OVERRIDE; virtual bool IsOffscreen() OVERRIDE; virtual bool SwapBuffers() OVERRIDE; @@ -153,6 +162,8 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface { virtual void* GetConfig() OVERRIDE; virtual unsigned GetFormat() OVERRIDE; virtual VSyncProvider* GetVSyncProvider() OVERRIDE; + virtual bool RecreateOnMakeCurrent() OVERRIDE; + virtual void SetRecreateOnMakeCurrent(bool recreate) OVERRIDE; GLSurface* surface() const { return surface_.get(); } diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 3b81daf..b57655651 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc @@ -399,18 +399,30 @@ bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size) { if (was_current) current_context->ReleaseCurrent(this); - Destroy(); + Recreate(); + + if (was_current) + return current_context->MakeCurrent(this); + return true; +} +bool NativeViewGLSurfaceEGL::Recreate() { + Destroy(); if (!Initialize()) { - LOG(ERROR) << "Failed to resize pbuffer."; + LOG(ERROR) << "Failed to create surface."; return false; } - - if (was_current) - return current_context->MakeCurrent(this); return true; } +bool NativeViewGLSurfaceEGL::RecreateOnMakeCurrent() { + return recreate_on_make_current_; +} + +void NativeViewGLSurfaceEGL::SetRecreateOnMakeCurrent(bool recreate) { + recreate_on_make_current_ = recreate; +} + EGLSurface NativeViewGLSurfaceEGL::GetHandle() { return surface_; } diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h index 17e6e94..c54fbc0 100644 --- a/ui/gl/gl_surface_egl.h +++ b/ui/gl/gl_surface_egl.h @@ -60,6 +60,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL { virtual bool Initialize() OVERRIDE; virtual void Destroy() OVERRIDE; virtual bool Resize(const gfx::Size& size) OVERRIDE; + virtual bool Recreate() OVERRIDE; virtual bool IsOffscreen() OVERRIDE; virtual bool SwapBuffers() OVERRIDE; virtual gfx::Size GetSize() OVERRIDE; @@ -67,6 +68,8 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL { virtual std::string GetExtensions() OVERRIDE; virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE; virtual VSyncProvider* GetVSyncProvider() OVERRIDE; + virtual bool RecreateOnMakeCurrent() OVERRIDE; + virtual void SetRecreateOnMakeCurrent(bool recreate) OVERRIDE; protected: virtual ~NativeViewGLSurfaceEGL(); @@ -77,6 +80,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL { EGLSurface surface_; bool supports_post_sub_buffer_; EGLConfig config_; + bool recreate_on_make_current_; scoped_ptr<VSyncProvider> vsync_provider_; |