Skip to content

Commit

Permalink
aw: Add and use DrawGL kModeSync
Browse files Browse the repository at this point in the history
We need to support this new hidden api to avoid onDraw getting ahead of
DrawGL. Without this, onDraw can finish producing frame n+1 before DrawGL
consumes frame n, in which case DrawGL skips a frame.

Also make AwDrawGLInfo future proof.

BUG=397358

Review URL: https://codereview.chromium.org/414163002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@285712 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
boliu@chromium.org committed Jul 25, 2014
1 parent 4cafbe2 commit 33e9e43
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 52 deletions.
107 changes: 56 additions & 51 deletions android_webview/browser/hardware_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@ HardwareRenderer::HardwareRenderer(SharedRendererState* state)
last_egl_context_(eglGetCurrentContext()),
stencil_enabled_(false),
viewport_clip_valid_for_dcheck_(false),
gl_surface_(new AwGLSurface),
root_layer_(cc::Layer::Create()),
resource_collection_(new cc::DelegatedFrameResourceCollection),
output_surface_(NULL) {
DCHECK(last_egl_context_);

gl_surface_ = new AwGLSurface;
resource_collection_->SetClient(this);

cc::LayerTreeSettings settings;

Expand All @@ -105,17 +107,15 @@ HardwareRenderer::~HardwareRenderer() {
root_layer_ = NULL;
delegated_layer_ = NULL;
frame_provider_ = NULL;
if (resource_collection_.get()) {
#if DCHECK_IS_ON
// Check collection is empty.
cc::ReturnedResourceArray returned_resources;
resource_collection_->TakeUnusedResourcesForChildCompositor(
&returned_resources);
DCHECK_EQ(0u, returned_resources.size());
// Check collection is empty.
cc::ReturnedResourceArray returned_resources;
resource_collection_->TakeUnusedResourcesForChildCompositor(
&returned_resources);
DCHECK_EQ(0u, returned_resources.size());
#endif // DCHECK_IS_ON

resource_collection_->SetClient(NULL);
}
resource_collection_->SetClient(NULL);
}

void HardwareRenderer::DidBeginMainFrame() {
Expand All @@ -127,6 +127,48 @@ void HardwareRenderer::DidBeginMainFrame() {
output_surface_->SetDrawConstraints(viewport_, clip_);
}

void HardwareRenderer::CommitFrame() {
scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput();
if (!input.get()) {
DLOG(WARNING) << "No frame to commit";
return;
}

DCHECK(!input->frame.gl_frame_data);
DCHECK(!input->frame.software_frame_data);

// DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
// renderer frame, assuming that the browser compositor will scale
// it back up to device scale. But on Android we put our browser layers in
// physical pixels and set our browser CC device_scale_factor to 1, so this
// suppresses the transform.
input->frame.delegated_frame_data->device_scale_factor = 1.0f;

gfx::Size frame_size =
input->frame.delegated_frame_data->render_pass_list.back()
->output_rect.size();
bool size_changed = frame_size != frame_size_;
frame_size_ = frame_size;
scroll_offset_ = input->scroll_offset;

if (!frame_provider_ || size_changed) {
if (delegated_layer_) {
delegated_layer_->RemoveFromParent();
}

frame_provider_ = new cc::DelegatedFrameProvider(
resource_collection_.get(), input->frame.delegated_frame_data.Pass());

delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
delegated_layer_->SetBounds(gfx::Size(input->width, input->height));
delegated_layer_->SetIsDrawable(true);

root_layer_->AddChild(delegated_layer_);
} else {
frame_provider_->SetFrameData(input->frame.delegated_frame_data.Pass());
}
}

void HardwareRenderer::DrawGL(bool stencil_enabled,
int framebuffer_binding_ext,
AwDrawGLInfo* draw_info) {
Expand All @@ -140,52 +182,15 @@ void HardwareRenderer::DrawGL(bool stencil_enabled,
return;
}

if (!delegated_layer_.get()) {
DLOG(ERROR) << "No frame committed";
return;
}

// TODO(boliu): Handle context loss.
if (last_egl_context_ != current_context)
DLOG(WARNING) << "EGLContextChanged";

scoped_ptr<DrawGLInput> input = shared_renderer_state_->PassDrawGLInput();
if (!resource_collection_.get()) {
resource_collection_ = new cc::DelegatedFrameResourceCollection;
resource_collection_->SetClient(this);
}

if (input.get()) {
DCHECK(!input->frame.gl_frame_data);
DCHECK(!input->frame.software_frame_data);

// DelegatedRendererLayerImpl applies the inverse device_scale_factor of the
// renderer frame, assuming that the browser compositor will scale
// it back up to device scale. But on Android we put our browser layers in
// physical pixels and set our browser CC device_scale_factor to 1, so this
// suppresses the transform.
input->frame.delegated_frame_data->device_scale_factor = 1.0f;

gfx::Size frame_size =
input->frame.delegated_frame_data->render_pass_list.back()
->output_rect.size();
bool size_changed = frame_size != frame_size_;
frame_size_ = frame_size;
scroll_offset_ = input->scroll_offset;

if (!frame_provider_ || size_changed) {
if (delegated_layer_) {
delegated_layer_->RemoveFromParent();
}

frame_provider_ = new cc::DelegatedFrameProvider(
resource_collection_.get(), input->frame.delegated_frame_data.Pass());

delegated_layer_ = cc::DelegatedRendererLayer::Create(frame_provider_);
delegated_layer_->SetBounds(gfx::Size(input->width, input->height));
delegated_layer_->SetIsDrawable(true);

root_layer_->AddChild(delegated_layer_);
} else {
frame_provider_->SetFrameData(input->frame.delegated_frame_data.Pass());
}
}

viewport_.SetSize(draw_info->width, draw_info->height);
layer_tree_host_->SetViewportSize(viewport_);
clip_.SetRect(draw_info->clip_left,
Expand Down
1 change: 1 addition & 0 deletions android_webview/browser/hardware_renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class HardwareRenderer : public cc::LayerTreeHostClient,
void DrawGL(bool stencil_enabled,
int framebuffer_binding_ext,
AwDrawGLInfo* draw_info);
void CommitFrame();

// cc::LayerTreeHostClient overrides.
virtual void WillBeginMainFrame(int frame_id) OVERRIDE {}
Expand Down
7 changes: 7 additions & 0 deletions android_webview/native/aw_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,12 @@ jlong AwContents::GetAwDrawGLViewContext(JNIEnv* env, jobject obj) {
}

void AwContents::DrawGL(AwDrawGLInfo* draw_info) {
if (draw_info->mode == AwDrawGLInfo::kModeSync) {
if (hardware_renderer_)
hardware_renderer_->CommitFrame();
return;
}

{
GLViewRendererManager* manager = GLViewRendererManager::GetInstance();
base::AutoLock lock(render_thread_lock_);
Expand All @@ -366,6 +372,7 @@ void AwContents::DrawGL(AwDrawGLInfo* draw_info) {

if (!hardware_renderer_) {
hardware_renderer_.reset(new HardwareRenderer(&shared_renderer_state_));
hardware_renderer_->CommitFrame();
}

hardware_renderer_->DrawGL(state_restore.stencil_enabled(),
Expand Down
6 changes: 5 additions & 1 deletion android_webview/public/browser/draw_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
extern "C" {
#endif

static const int kAwDrawGLInfoVersion = 1;

// Holds the information required to trigger an OpenGL drawing operation.
struct AwDrawGLInfo {
int version; // The AwDrawGLInfo this struct was built with.

// Input: tells the draw function what action to perform.
enum Mode {
kModeDraw,
kModeDraw = 0,
kModeProcess,
kModeProcessNoContext,
kModeSync,
Expand Down

0 comments on commit 33e9e43

Please sign in to comment.