Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ui / ozone / platform / dri / dri_surface.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/dri/dri_surface.h"
6
7 #include "base/logging.h"
8 #include "base/message_loop/message_loop.h"
9 #include "third_party/skia/include/core/SkCanvas.h"
10 #include "third_party/skia/include/core/SkSurface.h"
11 #include "ui/gfx/geometry/rect.h"
12 #include "ui/gfx/skia_util.h"
13 #include "ui/ozone/platform/dri/dri_buffer.h"
14 #include "ui/ozone/platform/dri/dri_vsync_provider.h"
15 #include "ui/ozone/platform/dri/dri_wrapper.h"
16 #include "ui/ozone/platform/dri/hardware_display_controller.h"
17
18 namespace ui {
19
20 namespace {
21
22 scoped_refptr<DriBuffer> AllocateBuffer(DriWrapper* dri,
23                                         const gfx::Size& size) {
24   scoped_refptr<DriBuffer> buffer(new DriBuffer(dri));
25   SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height());
26
27   bool initialized = buffer->Initialize(info);
28   DCHECK(initialized) << "Failed to create drm buffer.";
29
30   return buffer;
31 }
32
33 }  // namespace
34
35 DriSurface::DriSurface(
36     DriWrapper* dri,
37     const base::WeakPtr<HardwareDisplayController>& controller)
38     : dri_(dri),
39       buffers_(),
40       front_buffer_(0),
41       controller_(controller) {
42 }
43
44 DriSurface::~DriSurface() {
45 }
46
47 skia::RefPtr<SkCanvas> DriSurface::GetCanvas() {
48   return skia::SharePtr(surface_->getCanvas());
49 }
50
51 void DriSurface::ResizeCanvas(const gfx::Size& viewport_size) {
52   SkImageInfo info = SkImageInfo::MakeN32(
53       viewport_size.width(), viewport_size.height(), kOpaque_SkAlphaType);
54   surface_ = skia::AdoptRef(SkSurface::NewRaster(info));
55
56   if (!controller_)
57     return;
58
59   // For the display buffers use the mode size since a |viewport_size| smaller
60   // than the display size will not scanout.
61   gfx::Size mode_size(controller_->get_mode().hdisplay,
62                       controller_->get_mode().vdisplay);
63   for (size_t i = 0; i < arraysize(buffers_); ++i)
64     buffers_[i] = AllocateBuffer(dri_, mode_size);
65 }
66
67 void DriSurface::PresentCanvas(const gfx::Rect& damage) {
68   DCHECK(base::MessageLoopForUI::IsCurrent());
69   DCHECK(buffers_[front_buffer_ ^ 1]);
70
71   if (!controller_)
72     return;
73
74   controller_->QueueOverlayPlane(OverlayPlane(buffers_[front_buffer_ ^ 1]));
75
76   UpdateNativeSurface(damage);
77   controller_->SchedulePageFlip();
78   controller_->WaitForPageFlipEvent();
79
80   // Update our front buffer pointer.
81   front_buffer_ ^= 1;
82 }
83
84 scoped_ptr<gfx::VSyncProvider> DriSurface::CreateVSyncProvider() {
85   return scoped_ptr<gfx::VSyncProvider>(new DriVSyncProvider(controller_));
86 }
87
88 void DriSurface::UpdateNativeSurface(const gfx::Rect& damage) {
89   SkCanvas* canvas = buffers_[front_buffer_ ^ 1]->GetCanvas();
90
91   // The DriSurface is double buffered, so the current back buffer is
92   // missing the previous update. Expand damage region.
93   SkRect real_damage = RectToSkRect(UnionRects(damage, last_damage_));
94
95   // Copy damage region.
96   skia::RefPtr<SkImage> image = skia::AdoptRef(surface_->newImageSnapshot());
97   image->draw(canvas, &real_damage, real_damage, NULL);
98
99   last_damage_ = damage;
100 }
101
102 }  // namespace ui