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 |