12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/output/output_surface.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <set>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector>
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/bind.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/debug/trace_event.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "cc/output/compositor_frame.h"
18eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "cc/output/managed_memory_policy.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "cc/output/output_surface_client.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "cc/scheduler/delay_based_time_source.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "third_party/WebKit/public/platform/WebGraphicsMemoryAllocation.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/khronos/GLES2/gl2ext.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/rect.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::set;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::string;
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using std::vector;
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc {
33eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
34eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen MurdochManagedMemoryPolicy::PriorityCutoff ConvertPriorityCutoff(
36eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    WebKit::WebGraphicsMemoryAllocation::PriorityCutoff priority_cutoff) {
37eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // This is simple a 1:1 map, the names differ only because the WebKit names
38eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // should be to match the cc names.
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  switch (priority_cutoff) {
40eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowNothing:
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING;
42eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowVisibleOnly:
43eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return ManagedMemoryPolicy::CUTOFF_ALLOW_REQUIRED_ONLY;
44eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case WebKit::WebGraphicsMemoryAllocation::
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        PriorityCutoffAllowVisibleAndNearby:
46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return ManagedMemoryPolicy::CUTOFF_ALLOW_NICE_TO_HAVE;
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    case WebKit::WebGraphicsMemoryAllocation::PriorityCutoffAllowEverything:
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return ManagedMemoryPolicy::CUTOFF_ALLOW_EVERYTHING;
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  NOTREACHED();
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return ManagedMemoryPolicy::CUTOFF_ALLOW_NOTHING;
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // anonymous namespace
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)class OutputSurfaceCallbacks
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : public WebKit::WebGraphicsContext3D::
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        WebGraphicsSwapBuffersCompleteCallbackCHROMIUM,
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      public WebKit::WebGraphicsContext3D::WebGraphicsContextLostCallback,
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    public WebKit::WebGraphicsContext3D::
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      WebGraphicsMemoryAllocationChangedCallbackCHROMIUM {
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  explicit OutputSurfaceCallbacks(OutputSurface* client)
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      : client_(client) {
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK(client_);
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // WK:WGC3D::WGSwapBuffersCompleteCallbackCHROMIUM implementation.
695e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  virtual void onSwapBuffersComplete() { client_->OnSwapBuffersComplete(NULL); }
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // WK:WGC3D::WGContextLostCallback implementation.
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void onContextLost() { client_->DidLoseOutputSurface(); }
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // WK:WGC3D::WGMemoryAllocationChangedCallbackCHROMIUM implementation.
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual void onMemoryAllocationChanged(
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      WebKit::WebGraphicsMemoryAllocation allocation) {
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ManagedMemoryPolicy policy(
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        allocation.bytesLimitWhenVisible,
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        ConvertPriorityCutoff(allocation.priorityCutoffWhenVisible),
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        allocation.bytesLimitWhenNotVisible,
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        ConvertPriorityCutoff(allocation.priorityCutoffWhenNotVisible),
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        ManagedMemoryPolicy::kDefaultNumResourcesLimit);
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    bool discard_backbuffer = !allocation.suggestHaveBackbuffer;
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    client_->SetMemoryPolicy(policy, discard_backbuffer);
85eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
86eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  OutputSurface* client_;
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OutputSurface::OutputSurface(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<WebKit::WebGraphicsContext3D> context3d)
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : context3d_(context3d.Pass()),
94868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      has_gl_discard_backbuffer_(false),
955e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      has_swap_buffers_complete_callback_(false),
965e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      device_scale_factor_(-1),
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      weak_ptr_factory_(this),
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      max_frames_pending_(0),
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pending_swap_buffers_(0),
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      needs_begin_frame_(false),
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      begin_frame_pending_(false),
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      client_(NULL),
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      check_for_retroactive_begin_frame_pending_(false) {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OutputSurface::OutputSurface(
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<cc::SoftwareOutputDevice> software_device)
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : software_device_(software_device.Pass()),
109868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      has_gl_discard_backbuffer_(false),
1105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      has_swap_buffers_complete_callback_(false),
1115e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      device_scale_factor_(-1),
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      weak_ptr_factory_(this),
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      max_frames_pending_(0),
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pending_swap_buffers_(0),
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      needs_begin_frame_(false),
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      begin_frame_pending_(false),
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      client_(NULL),
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      check_for_retroactive_begin_frame_pending_(false) {
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OutputSurface::OutputSurface(
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<cc::SoftwareOutputDevice> software_device)
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    : context3d_(context3d.Pass()),
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      software_device_(software_device.Pass()),
126868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      has_gl_discard_backbuffer_(false),
1275e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      has_swap_buffers_complete_callback_(false),
1285e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)      device_scale_factor_(-1),
1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      weak_ptr_factory_(this),
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      max_frames_pending_(0),
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      pending_swap_buffers_(0),
132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      needs_begin_frame_(false),
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      begin_frame_pending_(false),
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      client_(NULL),
135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      check_for_retroactive_begin_frame_pending_(false) {
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::InitializeBeginFrameEmulation(
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::SingleThreadTaskRunner* task_runner,
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    bool throttle_frame_production,
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    base::TimeDelta interval) {
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (throttle_frame_production) {
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_.reset(
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        new FrameRateController(
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            DelayBasedTimeSource::Create(interval, task_runner)));
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_.reset(new FrameRateController(task_runner));
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  frame_rate_controller_->SetClient(this);
1517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  frame_rate_controller_->SetMaxSwapsPending(max_frames_pending_);
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  frame_rate_controller_->SetDeadlineAdjustment(
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      capabilities_.adjust_deadline_for_parent ?
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          BeginFrameArgs::DefaultDeadlineAdjustment() : base::TimeDelta());
1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // The new frame rate controller will consume the swap acks of the old
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // frame rate controller, so we set that expectation up here.
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (int i = 0; i < pending_swap_buffers_; i++)
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->DidSwapBuffers();
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::SetMaxFramesPending(int max_frames_pending) {
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame_rate_controller_)
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->SetMaxSwapsPending(max_frames_pending);
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  max_frames_pending_ = max_frames_pending;
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::OnVSyncParametersChanged(base::TimeTicks timebase,
1697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                             base::TimeDelta interval) {
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT2("cc", "OutputSurface::OnVSyncParametersChanged",
1717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "timebase", (timebase - base::TimeTicks()).InSecondsF(),
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "interval", interval.InSecondsF());
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame_rate_controller_)
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->SetTimebaseAndInterval(timebase, interval);
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::FrameRateControllerTick(bool throttled,
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                            const BeginFrameArgs& args) {
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(frame_rate_controller_);
180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (throttled)
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    skipped_begin_frame_args_ = args;
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  else
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    BeginFrame(args);
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Forwarded to OutputSurfaceClient
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::SetNeedsRedrawRect(gfx::Rect damage_rect) {
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT0("cc", "OutputSurface::SetNeedsRedrawRect");
1897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  client_->SetNeedsRedrawRect(damage_rect);
1907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::SetNeedsBeginFrame(bool enable) {
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT1("cc", "OutputSurface::SetNeedsBeginFrame", "enable", enable);
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  needs_begin_frame_ = enable;
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  begin_frame_pending_ = false;
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (frame_rate_controller_) {
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    BeginFrameArgs skipped = frame_rate_controller_->SetActive(enable);
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (skipped.IsValid())
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      skipped_begin_frame_args_ = skipped;
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (needs_begin_frame_)
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    PostCheckForRetroactiveBeginFrame();
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::BeginFrame(const BeginFrameArgs& args) {
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT2("cc", "OutputSurface::BeginFrame",
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "begin_frame_pending_", begin_frame_pending_,
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "pending_swap_buffers_", pending_swap_buffers_);
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!needs_begin_frame_ || begin_frame_pending_ ||
210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      (pending_swap_buffers_ >= max_frames_pending_ &&
211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch       max_frames_pending_ > 0)) {
212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    skipped_begin_frame_args_ = args;
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  } else {
214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    begin_frame_pending_ = true;
215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    client_->BeginFrame(args);
216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // args might be an alias for skipped_begin_frame_args_.
217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    // Do not reset it before calling BeginFrame!
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    skipped_begin_frame_args_ = BeginFrameArgs();
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochbase::TimeDelta OutputSurface::RetroactiveBeginFramePeriod() {
223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return BeginFrameArgs::DefaultRetroactiveBeginFramePeriod();
224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OutputSurface::PostCheckForRetroactiveBeginFrame() {
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (!skipped_begin_frame_args_.IsValid() ||
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      check_for_retroactive_begin_frame_pending_)
2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return;
230eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::MessageLoop::current()->PostTask(
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     FROM_HERE,
233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch     base::Bind(&OutputSurface::CheckForRetroactiveBeginFrame,
234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                weak_ptr_factory_.GetWeakPtr()));
235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  check_for_retroactive_begin_frame_pending_ = true;
236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OutputSurface::CheckForRetroactiveBeginFrame() {
239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TRACE_EVENT0("cc", "OutputSurface::CheckForRetroactiveBeginFrame");
240eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  check_for_retroactive_begin_frame_pending_ = false;
241eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::TimeTicks now = base::TimeTicks::Now();
242eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::TimeTicks alternative_deadline =
243eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      skipped_begin_frame_args_.frame_time +
244eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      RetroactiveBeginFramePeriod();
245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (now < skipped_begin_frame_args_.deadline ||
246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      now < alternative_deadline) {
247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    BeginFrame(skipped_begin_frame_args_);
248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::DidSwapBuffers() {
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  begin_frame_pending_ = false;
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pending_swap_buffers_++;
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT1("cc", "OutputSurface::DidSwapBuffers",
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "pending_swap_buffers_", pending_swap_buffers_);
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame_rate_controller_)
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->DidSwapBuffers();
258eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PostCheckForRetroactiveBeginFrame();
2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::OnSwapBuffersComplete(const CompositorFrameAck* ack) {
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pending_swap_buffers_--;
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT1("cc", "OutputSurface::OnSwapBuffersComplete",
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               "pending_swap_buffers_", pending_swap_buffers_);
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  client_->OnSwapBuffersComplete(ack);
2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame_rate_controller_)
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->DidSwapBuffersComplete();
268eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PostCheckForRetroactiveBeginFrame();
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::DidLoseOutputSurface() {
2727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TRACE_EVENT0("cc", "OutputSurface::DidLoseOutputSurface");
2737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  begin_frame_pending_ = false;
2747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  pending_swap_buffers_ = 0;
2757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  client_->DidLoseOutputSurface();
2767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
278fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid OutputSurface::SetExternalStencilTest(bool enabled) {
279fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch  client_->SetExternalStencilTest(enabled);
280fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch}
281fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdoch
2827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void OutputSurface::SetExternalDrawConstraints(const gfx::Transform& transform,
283438599f994082010ffd07abcbecb7a97956451e2Bo Liu                                               gfx::Rect viewport,
284438599f994082010ffd07abcbecb7a97956451e2Bo Liu                                               gfx::Rect clip,
285438599f994082010ffd07abcbecb7a97956451e2Bo Liu                                               bool valid_for_tile_management) {
286438599f994082010ffd07abcbecb7a97956451e2Bo Liu  client_->SetExternalDrawConstraints(
287438599f994082010ffd07abcbecb7a97956451e2Bo Liu      transform, viewport, clip, valid_for_tile_management);
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)OutputSurface::~OutputSurface() {
2917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame_rate_controller_)
2927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    frame_rate_controller_->SetActive(false);
2937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (context3d_) {
2957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    context3d_->setSwapBuffersCompleteCallbackCHROMIUM(NULL);
2967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    context3d_->setContextLostCallback(NULL);
2977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    context3d_->setMemoryAllocationChangedCallbackCHROMIUM(NULL);
2987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
301b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool OutputSurface::ForcedDrawToSoftwareDevice() const {
302b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return false;
303b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
304b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool OutputSurface::BindToClient(cc::OutputSurfaceClient* client) {
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(client);
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_ = client;
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = true;
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context3d_) {
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    success = context3d_->makeContextCurrent();
312868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (success)
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SetContext3D(context3d_.Pass());
314868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
316868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!success)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    client_ = NULL;
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return success;
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)bool OutputSurface::InitializeAndSetContext3D(
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<WebKit::WebGraphicsContext3D> context3d,
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_refptr<ContextProvider> offscreen_context_provider) {
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!context3d_);
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(context3d);
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(client_);
328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
329868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool success = false;
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context3d->makeContextCurrent()) {
331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    SetContext3D(context3d.Pass());
332868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (client_->DeferredInitialize(offscreen_context_provider))
333868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      success = true;
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (!success)
3377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ResetContext3D();
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return success;
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OutputSurface::ReleaseGL() {
3437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(client_);
3447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  DCHECK(context3d_);
3457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  client_->ReleaseGL();
3467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ResetContext3D();
3477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
349868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void OutputSurface::SetContext3D(
350868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    scoped_ptr<WebKit::WebGraphicsContext3D> context3d) {
351868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!context3d_);
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(context3d);
353868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(client_);
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  string extensions_string = UTF16ToASCII(context3d->getString(GL_EXTENSIONS));
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  vector<string> extensions_list;
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::SplitString(extensions_string, ' ', &extensions_list);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set<string> extensions(extensions_list.begin(), extensions_list.end());
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  has_gl_discard_backbuffer_ =
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extensions.count("GL_CHROMIUM_discard_backbuffer") > 0;
3615e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  has_swap_buffers_complete_callback_ =
3625e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)       extensions.count("GL_CHROMIUM_swapbuffers_complete_callback") > 0;
3635e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  context3d_ = context3d.Pass();
3667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callbacks_.reset(new OutputSurfaceCallbacks(this));
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  context3d_->setSwapBuffersCompleteCallbackCHROMIUM(callbacks_.get());
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  context3d_->setContextLostCallback(callbacks_.get());
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  context3d_->setMemoryAllocationChangedCallbackCHROMIUM(callbacks_.get());
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid OutputSurface::ResetContext3D() {
3737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  context3d_.reset();
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  callbacks_.reset();
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OutputSurface::EnsureBackbuffer() {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context3d_);
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_gl_discard_backbuffer_)
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context3d_->ensureBackbufferCHROMIUM();
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OutputSurface::DiscardBackbuffer() {
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context3d_);
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_gl_discard_backbuffer_)
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context3d_->discardBackbufferCHROMIUM();
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void OutputSurface::Reshape(gfx::Size size, float scale_factor) {
390868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (size == surface_size_ && scale_factor == device_scale_factor_)
391868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  surface_size_ = size;
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  device_scale_factor_ = scale_factor;
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (context3d_) {
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    context3d_->reshapeWithScaleFactor(
397868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        size.width(), size.height(), scale_factor);
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
3995e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (software_device_)
4005e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    software_device_->Resize(size);
401868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
402868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
403868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)gfx::Size OutputSurface::SurfaceSize() const {
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return surface_size_;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OutputSurface::BindFramebuffer() {
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context3d_);
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  context3d_->bindFramebuffer(GL_FRAMEBUFFER, 0);
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4125e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
4135e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (frame->software_frame_data) {
4145e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    PostSwapBuffersComplete();
4157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DidSwapBuffers();
4165e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    return;
4175e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
4185e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(context3d_);
4205e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  DCHECK(frame->gl_frame_data);
4215e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
4227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (frame->gl_frame_data->sub_buffer_rect ==
4237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      gfx::Rect(frame->gl_frame_data->size)) {
4247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Note that currently this has the same effect as SwapBuffers; we should
4257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // consider exposing a different entry point on WebGraphicsContext3D.
4267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    context3d()->prepareTexture();
4277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
4285e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    gfx::Rect sub_buffer_rect = frame->gl_frame_data->sub_buffer_rect;
4295e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    context3d()->postSubBufferCHROMIUM(sub_buffer_rect.x(),
4305e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                                       sub_buffer_rect.y(),
4315e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                                       sub_buffer_rect.width(),
4325e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)                                       sub_buffer_rect.height());
4335e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  }
4345e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)
4355e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  if (!has_swap_buffers_complete_callback_)
4365e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)    PostSwapBuffersComplete();
4377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
4387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DidSwapBuffers();
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4415e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)void OutputSurface::PostSwapBuffersComplete() {
4425e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)  base::MessageLoop::current()->PostTask(
4435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)       FROM_HERE,
4447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)       base::Bind(&OutputSurface::OnSwapBuffersComplete,
4457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                  weak_ptr_factory_.GetWeakPtr(),
4467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                  static_cast<CompositorFrameAck*>(NULL)));
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid OutputSurface::SetMemoryPolicy(const ManagedMemoryPolicy& policy,
450a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                                    bool discard_backbuffer) {
451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TRACE_EVENT2("cc", "OutputSurface::SetMemoryPolicy",
452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch               "bytes_limit_when_visible", policy.bytes_limit_when_visible,
453a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)               "discard_backbuffer", discard_backbuffer);
454a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Just ignore the memory manager when it says to set the limit to zero
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // bytes. This will happen when the memory manager thinks that the renderer
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // is not visible (which the renderer knows better).
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (policy.bytes_limit_when_visible)
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    client_->SetMemoryPolicy(policy);
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  client_->SetDiscardBackBufferWhenNotVisible(discard_backbuffer);
460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cc
463