blob: 9868a555efd2c7586e24be93c3c51d0b3ae3f5e7 [file] [log] [blame]
// Copyright 2015 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 COMPONENTS_EXO_SURFACE_H_
#define COMPONENTS_EXO_SURFACE_H_
#include <list>
#include <utility>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/window.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/gfx/geometry/rect.h"
namespace base {
namespace trace_event {
class TracedValue;
}
}
namespace exo {
class Buffer;
class SurfaceDelegate;
class SurfaceObserver;
// This class represents a rectangular area that is displayed on the screen.
// It has a location, size and pixel contents.
class Surface : public aura::Window, public ui::CompositorObserver {
public:
Surface();
~Surface() override;
// Type-checking downcast routine.
static Surface* AsSurface(aura::Window* window);
// Set a buffer as the content of this surface. A buffer can only be attached
// to one surface at a time.
void Attach(Buffer* buffer);
// Describe the regions where the pending buffer is different from the
// current surface contents, and where the surface therefore needs to be
// repainted.
void Damage(const gfx::Rect& rect);
// Request notification when the next frame is displayed. Useful for
// throttling redrawing operations, and driving animations.
using FrameCallback = base::Callback<void(base::TimeTicks frame_time)>;
void RequestFrameCallback(const FrameCallback& callback);
// This sets the region of the surface that contains opaque content.
void SetOpaqueRegion(const SkRegion& region);
// This sets the scaling factor used to interpret the contents of the buffer
// attached to the surface. Note that if the scale is larger than 1, then you
// have to attach a buffer that is larger (by a factor of scale in each
// dimension) than the desired surface size.
void SetBufferScale(float scale);
// Functions that control sub-surface state. All sub-surface state is
// double-buffered and will be applied when Commit() is called.
void AddSubSurface(Surface* sub_surface);
void RemoveSubSurface(Surface* sub_surface);
void SetSubSurfacePosition(Surface* sub_surface, const gfx::Point& position);
void PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference);
void PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling);
// Surface state (damage regions, attached buffers, etc.) is double-buffered.
// A Commit() call atomically applies all pending state, replacing the
// current state. Commit() is not guaranteed to be synchronous. See
// CommitSurfaceHierarchy() below.
void Commit();
// This will synchronously commit all pending state of the surface and its
// descendants by recursively calling CommitSurfaceHierarchy() for each
// sub-surface with pending state.
void CommitSurfaceHierarchy();
// Returns true if surface is in synchronized mode.
bool IsSynchronized() const;
// Returns the preferred size of surface.
gfx::Size GetPreferredSize() const;
// Set the surface delegate.
void SetSurfaceDelegate(SurfaceDelegate* delegate);
// Returns true if surface has been assigned a surface delegate.
bool HasSurfaceDelegate() const;
// Surface does not own observers. It is the responsibility of the observer
// to remove itself when it is done observing.
void AddSurfaceObserver(SurfaceObserver* observer);
void RemoveSurfaceObserver(SurfaceObserver* observer);
bool HasSurfaceObserver(const SurfaceObserver* observer) const;
// Returns a trace value representing the state of the surface.
scoped_refptr<base::trace_event::TracedValue> AsTracedValue() const;
bool HasPendingDamageForTesting() const { return !pending_damage_.IsEmpty(); }
// Overridden from ui::CompositorObserver:
void OnCompositingDidCommit(ui::Compositor* compositor) override;
void OnCompositingStarted(ui::Compositor* compositor,
base::TimeTicks start_time) override;
void OnCompositingEnded(ui::Compositor* compositor) override;
void OnCompositingAborted(ui::Compositor* compositor) override;
void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
void OnCompositingShuttingDown(ui::Compositor* compositor) override;
private:
bool needs_commit_surface_hierarchy() const {
return needs_commit_surface_hierarchy_;
}
// This returns true when the surface has some contents assigned to it.
bool has_contents() const { return !!current_buffer_; }
// This is true when Attach() has been called and new contents should take
// effect next time Commit() is called.
bool has_pending_contents_;
// The buffer that will become the content of surface when Commit() is called.
base::WeakPtr<Buffer> pending_buffer_;
// The damage region to schedule paint for when Commit() is called.
// TODO(reveman): Use SkRegion here after adding a version of
// ui::Layer::SchedulePaint that takes a SkRegion.
gfx::Rect pending_damage_;
// These lists contains the callbacks to notify the client when it is a good
// time to start producing a new frame. These callbacks move to
// |frame_callbacks_| when Commit() is called. Later they are moved to
// |active_frame_callbacks_| when the effect of the Commit() is reflected in
// the compositor's active layer tree. The callbacks fire once we're notified
// that the compositor started drawing that active layer tree.
std::list<FrameCallback> pending_frame_callbacks_;
std::list<FrameCallback> frame_callbacks_;
std::list<FrameCallback> active_frame_callbacks_;
// The opaque region to take effect when Commit() is called.
SkRegion pending_opaque_region_;
// The buffer scaling factor to take effect when Commit() is called.
float pending_buffer_scale_;
// The stack of sub-surfaces to take effect when Commit() is called.
// Bottom-most sub-surface at the front of the list and top-most sub-surface
// at the back.
using SubSurfaceEntry = std::pair<Surface*, gfx::Point>;
using SubSurfaceEntryList = std::list<SubSurfaceEntry>;
SubSurfaceEntryList pending_sub_surfaces_;
// The buffer that is currently set as content of surface.
base::WeakPtr<Buffer> current_buffer_;
// This is true if a call to Commit() as been made but
// CommitSurfaceHierarchy() has not yet been called.
bool needs_commit_surface_hierarchy_;
// This is true when the contents of the surface should be updated next time
// the compositor successfully ends compositing.
bool update_contents_after_successful_compositing_;
// The compsitor being observer or null if not observing a compositor.
ui::Compositor* compositor_;
// This can be set to have some functions delegated. E.g. ShellSurface class
// can set this to handle Commit() and apply any double buffered state it
// maintains.
SurfaceDelegate* delegate_;
// Surface observer list. Surface does not own the observers.
base::ObserverList<SurfaceObserver, true> observers_;
DISALLOW_COPY_AND_ASSIGN(Surface);
};
} // namespace exo
#endif // COMPONENTS_EXO_SURFACE_H_