| Index: chromecast/ui/gfx/gfx_plane.cc
|
| diff --git a/chromecast/ui/gfx/gfx_plane.cc b/chromecast/ui/gfx/gfx_plane.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a28f2dba587bdf029f3f0ce82ae05a129aa36386
|
| --- /dev/null
|
| +++ b/chromecast/ui/gfx/gfx_plane.cc
|
| @@ -0,0 +1,140 @@
|
| +// Copyright (c) 2014 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 "chromecast/ui/gfx/gfx_plane.h"
|
| +
|
| +#include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +
|
| +namespace gfx {
|
| +namespace chromecast {
|
| +
|
| +Osd::Osd(Surface* arg_surface)
|
| + : surface_(arg_surface) {
|
| + DCHECK(surface_.get());
|
| +}
|
| +
|
| +Osd::~Osd() {
|
| +}
|
| +
|
| +// static
|
| +GfxPlane* GfxPlane::primary_ = NULL;
|
| +
|
| +GfxPlane::GfxPlane()
|
| + : num_surfaces_(0),
|
| + current_surface_(NULL) {
|
| +}
|
| +
|
| +GfxPlane::~GfxPlane() {
|
| + // Make sure we haven't leaked any surfaces
|
| + LOG_IF(DFATAL, num_surfaces_ != 0)
|
| + << num_surfaces_ << " of surfaces are not released.";
|
| + if (this == primary_) {
|
| + primary_ = NULL;
|
| + }
|
| +}
|
| +
|
| +void GfxPlane::Display(Surface* surface, const Rect& rect,
|
| + const Point& frame_buffer_point) {
|
| + DCHECK(frame_buffer_.get());
|
| + DCHECK(surface);
|
| +
|
| + // Keeps track of current surface to restore original bitmap when OSD
|
| + // surfaces are gone. Since all backing store surfaces are full screen,
|
| + // it's enough to remember only one (last) surface which displays something.
|
| + current_surface_ = surface;
|
| +
|
| + if (osd_and_rects_.empty()) { // Fast display for most cases.
|
| + frame_buffer_->Blit(surface, rect, frame_buffer_point);
|
| + return;
|
| + }
|
| +
|
| + Rect frame_buffer_rect(frame_buffer_point, rect.size());
|
| + scoped_ptr<Surface> composite;
|
| + // Draws lowest priority OSD surfaces first.
|
| + for (std::list<OsdAndRect>::const_reverse_iterator
|
| + it = osd_and_rects_.rbegin(); it != osd_and_rects_.rend(); ++it) {
|
| + if (frame_buffer_rect.Intersects(it->rect)) {
|
| + // Creates a temporary composite surface and copies the original bitmap.
|
| + if (composite.get() == NULL) {
|
| + composite.reset(CreateSurface(rect.size()));
|
| + composite->Blit(surface, rect, Point(0, 0));
|
| + }
|
| +
|
| + Rect overlapped_in_frame_buffer = gfx::IntersectRects(frame_buffer_rect,
|
| + it->rect);
|
| + Point overlapped_origin_in_composite(
|
| + overlapped_in_frame_buffer.origin() -
|
| + frame_buffer_point.OffsetFromOrigin());
|
| + Rect overlapped_in_osd(
|
| + overlapped_in_frame_buffer.origin() -
|
| + it->rect.origin().OffsetFromOrigin(),
|
| + overlapped_in_frame_buffer.size());
|
| + composite->Composite(it->osd->surface(), overlapped_in_osd,
|
| + overlapped_origin_in_composite);
|
| + }
|
| + }
|
| +
|
| + // Blits composite surface if created.
|
| + if (composite.get() == NULL) {
|
| + frame_buffer_->Blit(surface, rect, frame_buffer_point);
|
| + } else {
|
| + frame_buffer_->Blit(composite.get(), Rect(composite->size()),
|
| + frame_buffer_point);
|
| + }
|
| +}
|
| +
|
| +void GfxPlane::OnRemoved(Surface* surface) {
|
| + if (surface == current_surface_) {
|
| + current_surface_ = NULL;
|
| + }
|
| +}
|
| +
|
| +bool GfxPlane::IsOsdPlane() const {
|
| + return false;
|
| +}
|
| +
|
| +Osd* GfxPlane::CreateOsd(const Size& size) {
|
| + return new Osd(CreateSurface(size));
|
| +}
|
| +
|
| +void GfxPlane::AddOsd(Osd* osd, const Point& frame_buffer_point) {
|
| + OsdAndRect osd_rect;
|
| + osd_rect.rect = Rect(frame_buffer_point, osd->size());
|
| + osd_rect.osd = osd;
|
| + osd_and_rects_.push_front(osd_rect);
|
| + Refresh(osd_rect.rect);
|
| +}
|
| +
|
| +void GfxPlane::RemoveOsd(Osd* osd, const Point& frame_buffer_point) {
|
| + for (std::list<OsdAndRect>::iterator it = osd_and_rects_.begin();
|
| + it != osd_and_rects_.end(); ++it) {
|
| + if (it->osd == osd
|
| + && it->rect.origin() == frame_buffer_point) {
|
| + Rect overlaid_rect(it->rect);
|
| + osd_and_rects_.erase(it);
|
| + Refresh(overlaid_rect);
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void GfxPlane::Refresh(const Rect& frame_buffer_rect) {
|
| + if (current_surface_) {
|
| + DCHECK(frame_buffer_.get());
|
| + DCHECK(current_surface_->size() == frame_buffer_->size());
|
| + current_surface_->Display(frame_buffer_rect, frame_buffer_rect.origin());
|
| + }
|
| +}
|
| +
|
| +const Size GfxPlane::size() const {
|
| + if (frame_buffer_.get()) {
|
| + return frame_buffer_->size();
|
| + } else {
|
| + return Size(0, 0);
|
| + }
|
| +}
|
| +
|
| +} // namespace chromecast
|
| +} // namespace gfx
|
|
|