Skip to content

Commit

Permalink
Add AwGLSurface and use it in WGC3D
Browse files Browse the repository at this point in the history
Android can put the webview into an FBO, and compositor should draw into 
the FBO instead of directly on screen.  Use AwGLSurface and explicitly
set the FBO at the beginning of each hardware draw.

Add new APIs in GLInProcessContext and WGC3DIPCBI to allow the 
underlying GLSurface to be created separately.

BUG=251501

Review URL: https://chromiumcodereview.appspot.com/22277004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216136 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
boliu@chromium.org committed Aug 7, 2013
1 parent ddafdb6 commit 6172484
Show file tree
Hide file tree
Showing 18 changed files with 447 additions and 143 deletions.
2 changes: 2 additions & 0 deletions android_webview/android_webview.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@
'browser/aw_download_manager_delegate.h',
'browser/aw_form_database_service.cc',
'browser/aw_form_database_service.h',
'browser/aw_gl_surface.cc',
'browser/aw_gl_surface.h',
'browser/aw_http_auth_handler_base.cc',
'browser/aw_http_auth_handler_base.h',
'browser/aw_javascript_dialog_manager.cc',
Expand Down
48 changes: 48 additions & 0 deletions android_webview/browser/aw_gl_surface.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "android_webview/browser/aw_gl_surface.h"

namespace android_webview {

AwGLSurface::AwGLSurface() : fbo_(0) {}

AwGLSurface::~AwGLSurface() {}

void AwGLSurface::Destroy() {
}

bool AwGLSurface::IsOffscreen() {
return false;
}

unsigned int AwGLSurface::GetBackingFrameBufferObject() {
return fbo_;
}

bool AwGLSurface::SwapBuffers() {
return true;
}

gfx::Size AwGLSurface::GetSize() {
return gfx::Size(1, 1);
}

void* AwGLSurface::GetHandle() {
return NULL;
}

void* AwGLSurface::GetDisplay() {
return NULL;
}

void AwGLSurface::SetBackingFrameBufferObject(unsigned int fbo) {
fbo_ = fbo;
}

void AwGLSurface::ResetBackingFrameBufferObject() {
fbo_ = 0;
}

} // namespace android_webview
42 changes: 42 additions & 0 deletions android_webview/browser/aw_gl_surface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ANDROID_WEBVIEW_BROWSER_AW_GL_SURFACE_H_
#define ANDROID_WEBVIEW_BROWSER_AW_GL_SURFACE_H_

#include "ui/gl/gl_surface.h"

namespace android_webview {

// This surface is used to represent the underlying surface provided by the App
// inside a hardware draw. Note that offscreen contexts will not be using this
// GLSurface.
class GL_EXPORT AwGLSurface : public gfx::GLSurface {
public:
AwGLSurface();

// Implement GLSurface.
virtual void Destroy() OVERRIDE;
virtual bool IsOffscreen() OVERRIDE;
virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
virtual bool SwapBuffers() OVERRIDE;
virtual gfx::Size GetSize() OVERRIDE;
virtual void* GetHandle() OVERRIDE;
virtual void* GetDisplay() OVERRIDE;

void SetBackingFrameBufferObject(unsigned int fbo);
void ResetBackingFrameBufferObject();

protected:
virtual ~AwGLSurface();

private:
unsigned int fbo_;

DISALLOW_COPY_AND_ASSIGN(AwGLSurface);
};

} // namespace android_webview

#endif // ANDROID_WEBVIEW_BROWSER_AW_GL_SURFACE_H_
35 changes: 26 additions & 9 deletions android_webview/browser/in_process_view_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <android/bitmap.h>

#include "android_webview/browser/aw_gl_surface.h"
#include "android_webview/browser/scoped_app_gl_state_restore.h"
#include "android_webview/common/aw_switches.h"
#include "android_webview/public/browser/draw_gl.h"
Expand Down Expand Up @@ -289,6 +290,19 @@ bool InProcessViewRenderer::OnDraw(jobject java_canvas,
return result;
}

bool InProcessViewRenderer::InitializeHwDraw() {
TRACE_EVENT0("android_webview", "InitializeHwDraw");
DCHECK(!gl_surface_);
gl_surface_ = new AwGLSurface;
hardware_failed_ = !compositor_->InitializeHwDraw(gl_surface_);
hardware_initialized_ = true;

if (hardware_failed_)
gl_surface_ = NULL;

return !hardware_failed_;
}

void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
TRACE_EVENT0("android_webview", "InProcessViewRenderer::DrawGL");
DCHECK(visible_);
Expand All @@ -309,13 +323,11 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
ScopedAllowGL allow_gl;

if (attached_to_window_ && compositor_ && !hardware_initialized_) {
TRACE_EVENT0("android_webview", "InitializeHwDraw");
hardware_failed_ = !compositor_->InitializeHwDraw();
hardware_initialized_ = true;
last_egl_context_ = current_context;

if (hardware_failed_)
if (InitializeHwDraw()) {
last_egl_context_ = current_context;
} else {
return;
}
}

if (draw_info->mode == AwDrawGLInfo::kModeProcess)
Expand All @@ -330,29 +342,33 @@ void InProcessViewRenderer::DrawGL(AwDrawGLInfo* draw_info) {
TRACE_EVENT_INSTANT0(
"android_webview", "EGLContextChanged", TRACE_EVENT_SCOPE_THREAD);
}
last_egl_context_ = current_context;

if (!compositor_) {
TRACE_EVENT_INSTANT0(
"android_webview", "EarlyOut_NoCompositor", TRACE_EVENT_SCOPE_THREAD);
return;
}

DCHECK(gl_surface_);
gl_surface_->SetBackingFrameBufferObject(
state_restore.framebuffer_binding_ext());

gfx::Transform transform;
transform.matrix().setColMajorf(draw_info->transform);
transform.Translate(scroll_at_start_of_frame_.x(),
scroll_at_start_of_frame_.y());
// TODO(joth): Check return value.
block_invalidates_ = true;
gfx::Rect clip_rect(draw_info->clip_left,
draw_info->clip_top,
draw_info->clip_right - draw_info->clip_left,
draw_info->clip_bottom - draw_info->clip_top);
block_invalidates_ = true;
// TODO(joth): Check return value.
compositor_->DemandDrawHw(gfx::Size(draw_info->width, draw_info->height),
transform,
clip_rect,
state_restore.stencil_enabled());
block_invalidates_ = false;
gl_surface_->ResetBackingFrameBufferObject();

UpdateCachedGlobalVisibleRect();
bool drew_full_visible_rect = clip_rect.Contains(cached_global_visible_rect_);
Expand Down Expand Up @@ -554,6 +570,7 @@ void InProcessViewRenderer::OnDetachedFromWindow() {
hardware_initialized_ = false;
}

gl_surface_ = NULL;
attached_to_window_ = false;
}

Expand Down
5 changes: 5 additions & 0 deletions android_webview/browser/in_process_view_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class SkCanvas;

namespace android_webview {

class AwGLSurface;

// Provides RenderViewHost wrapper functionality for sending WebView-specific
// IPC messages to the renderer and from there to WebKit.
class InProcessViewRenderer : public BrowserViewRenderer,
Expand Down Expand Up @@ -93,6 +95,8 @@ class InProcessViewRenderer : public BrowserViewRenderer,

void NoLongerExpectsDrawGL();

bool InitializeHwDraw();

// For debug tracing or logging. Return the string representation of this
// view renderer's state and the |draw_info| if provided.
std::string ToString(AwDrawGLInfo* draw_info) const;
Expand Down Expand Up @@ -127,6 +131,7 @@ class InProcessViewRenderer : public BrowserViewRenderer,
bool attached_to_window_;
bool hardware_initialized_;
bool hardware_failed_;
scoped_refptr<AwGLSurface> gl_surface_;

// Used only for detecting Android View System context changes.
// Not to be used between draw calls.
Expand Down
2 changes: 2 additions & 0 deletions android_webview/browser/scoped_app_gl_state_restore.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ ScopedAppGLStateRestore::ScopedAppGLStateRestore(CallMode mode) : mode_(mode) {
glGetIntegerv(GL_STENCIL_VALUE_MASK, &stencil_mask_);
glGetIntegerv(GL_STENCIL_REF, &stencil_ref_);

glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &framebuffer_binding_ext_);

if (!g_gl_max_texture_units) {
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &g_gl_max_texture_units);
Expand All @@ -155,6 +156,7 @@ ScopedAppGLStateRestore::~ScopedAppGLStateRestore() {
TRACE_EVENT0("android_webview", "AppGLStateRestore");
MakeAppContextCurrent();

glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_binding_ext_);
glBindBuffer(GL_ARRAY_BUFFER, vertex_array_buffer_binding_);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_array_buffer_binding_);

Expand Down
3 changes: 3 additions & 0 deletions android_webview/browser/scoped_app_gl_state_restore.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class ScopedAppGLStateRestore {
~ScopedAppGLStateRestore();

bool stencil_enabled() const { return stencil_test_; }
GLint framebuffer_binding_ext() const { return framebuffer_binding_ext_; }

private:
const CallMode mode_;
Expand Down Expand Up @@ -83,6 +84,8 @@ class ScopedAppGLStateRestore {
GLint stencil_mask_;
GLint stencil_ref_;

GLint framebuffer_binding_ext_;

struct TextureBindings {
GLint texture_2d;
GLint texture_cube_map;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/renderer/android/synchronous_compositor_factory.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/context_provider_in_process.h"

namespace content {
Expand Down Expand Up @@ -143,10 +144,12 @@ void SynchronousCompositorImpl::SetClient(
compositor_client_ = compositor_client;
}

bool SynchronousCompositorImpl::InitializeHwDraw() {
bool SynchronousCompositorImpl::InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
return output_surface_->InitializeHwDraw(
surface,
g_factory.Get().GetOffscreenContextProviderForCompositorThread());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ class SynchronousCompositorImpl
// SynchronousCompositor
virtual void SetClient(SynchronousCompositorClient* compositor_client)
OVERRIDE;
virtual bool InitializeHwDraw() OVERRIDE;
virtual bool InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface) OVERRIDE;
virtual void ReleaseHwDraw() OVERRIDE;
virtual bool DemandDrawHw(
gfx::Size view_size,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,50 @@
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/public/browser/browser_thread.h"
#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/skia_util.h"
#include "ui/gfx/transform.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"

using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;

namespace content {

namespace {

// TODO(boliu): RenderThreadImpl should create in process contexts as well.
scoped_ptr<WebKit::WebGraphicsContext3D> CreateWebGraphicsContext3D() {
scoped_ptr<WebKit::WebGraphicsContext3D> CreateWebGraphicsContext3D(
scoped_refptr<gfx::GLSurface> surface) {
using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
if (!gfx::GLSurface::InitializeOneOff())
return scoped_ptr<WebKit::WebGraphicsContext3D>();

const char* allowed_extensions = "*";
const gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;

WebKit::WebGraphicsContext3D::Attributes attributes;
attributes.antialias = false;
attributes.shareResources = true;
attributes.noAutomaticFlushes = true;

gpu::GLInProcessContextAttribs in_process_attribs;
WebGraphicsContext3DInProcessCommandBufferImpl::ConvertAttributes(
attributes, &in_process_attribs);
scoped_ptr<gpu::GLInProcessContext> context(
gpu::GLInProcessContext::CreateWithSurface(surface,
attributes.shareResources,
allowed_extensions,
in_process_attribs,
gpu_preference));

if (!context.get())
return scoped_ptr<WebKit::WebGraphicsContext3D>();

return scoped_ptr<WebKit::WebGraphicsContext3D>(
WebGraphicsContext3DInProcessCommandBufferImpl
::CreateViewContext(attributes, NULL));
WebGraphicsContext3DInProcessCommandBufferImpl::WrapContext(
context.Pass(), attributes));
}

void DidActivatePendingTree(int routing_id) {
Expand Down Expand Up @@ -176,13 +196,15 @@ void AdjustTransformForClip(gfx::Transform* transform, gfx::Rect clip) {
} // namespace

bool SynchronousCompositorOutputSurface::InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface,
scoped_refptr<cc::ContextProvider> offscreen_context) {
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
DCHECK(!context3d_);
DCHECK(surface);

return InitializeAndSetContext3D(CreateWebGraphicsContext3D().Pass(),
offscreen_context);
return InitializeAndSetContext3D(
CreateWebGraphicsContext3D(surface).Pass(), offscreen_context);
}

void SynchronousCompositorOutputSurface::ReleaseHwDraw() {
Expand All @@ -205,8 +227,6 @@ bool SynchronousCompositorOutputSurface::DemandDrawHw(
SetExternalStencilTest(stencil_enabled);
InvokeComposite(clip.size());

// TODO(boliu): Check if context is lost here.

return did_swap_buffer_;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ class SynchronousCompositorOutputSurface
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;

// Partial SynchronousCompositor API implementation.
bool InitializeHwDraw(scoped_refptr<cc::ContextProvider> offscreen_context);
bool InitializeHwDraw(
scoped_refptr<gfx::GLSurface> surface,
scoped_refptr<cc::ContextProvider> offscreen_context);
void ReleaseHwDraw();
bool DemandDrawHw(gfx::Size surface_size,
const gfx::Transform& transform,
Expand Down
Loading

0 comments on commit 6172484

Please sign in to comment.