- add sources.
[platform/framework/web/crosswalk.git] / src / content / common / gpu / image_transport_surface_win.cc
1 // Copyright (c) 2012 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 "content/common/gpu/image_transport_surface.h"
6
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/compiler_specific.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/win/windows_version.h"
13 #include "content/common/gpu/gpu_messages.h"
14 #include "content/public/common/content_switches.h"
15 #include "ui/gfx/native_widget_types.h"
16 #include "ui/gl/gl_bindings.h"
17 #include "ui/gl/gl_context.h"
18 #include "ui/gl/gl_implementation.h"
19 #include "ui/gl/gl_surface_egl.h"
20
21 namespace content {
22 namespace {
23
24 // We are backed by an Pbuffer offscreen surface through which ANGLE provides
25 // a handle to the corresponding render target texture through an extension.
26 class PbufferImageTransportSurface
27     : public gfx::GLSurfaceAdapter,
28       public ImageTransportSurface,
29       public base::SupportsWeakPtr<PbufferImageTransportSurface> {
30  public:
31   PbufferImageTransportSurface(GpuChannelManager* manager,
32                                GpuCommandBufferStub* stub);
33
34   // gfx::GLSurface implementation
35   virtual bool Initialize() OVERRIDE;
36   virtual void Destroy() OVERRIDE;
37   virtual bool DeferDraws() OVERRIDE;
38   virtual bool IsOffscreen() OVERRIDE;
39   virtual bool SwapBuffers() OVERRIDE;
40   virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
41   virtual std::string GetExtensions() OVERRIDE;
42   virtual bool SetBackbufferAllocation(bool allocated) OVERRIDE;
43   virtual void SetFrontbufferAllocation(bool allocated) OVERRIDE;
44
45  protected:
46   // ImageTransportSurface implementation
47   virtual void OnBufferPresented(
48       const AcceleratedSurfaceMsg_BufferPresented_Params& params) OVERRIDE;
49   virtual void OnResizeViewACK() OVERRIDE;
50   virtual void OnResize(gfx::Size size, float scale_factor) OVERRIDE;
51   virtual void SetLatencyInfo(const ui::LatencyInfo&) OVERRIDE;
52   virtual gfx::Size GetSize() OVERRIDE;
53
54  private:
55   virtual ~PbufferImageTransportSurface();
56   void SendBuffersSwapped();
57   void DestroySurface();
58
59   // Tracks the current buffer allocation state.
60   bool backbuffer_suggested_allocation_;
61   bool frontbuffer_suggested_allocation_;
62
63   // Whether a SwapBuffers is pending.
64   bool is_swap_buffers_pending_;
65
66   // Whether we unscheduled command buffer because of pending SwapBuffers.
67   bool did_unschedule_;
68
69   // Size to resize to when the surface becomes visible.
70   gfx::Size visible_size_;
71
72   ui::LatencyInfo latency_info_;
73
74   scoped_ptr<ImageTransportHelper> helper_;
75
76   DISALLOW_COPY_AND_ASSIGN(PbufferImageTransportSurface);
77 };
78
79 PbufferImageTransportSurface::PbufferImageTransportSurface(
80     GpuChannelManager* manager,
81     GpuCommandBufferStub* stub)
82     : GLSurfaceAdapter(new gfx::PbufferGLSurfaceEGL(gfx::Size(1, 1))),
83       backbuffer_suggested_allocation_(true),
84       frontbuffer_suggested_allocation_(true),
85       is_swap_buffers_pending_(false),
86       did_unschedule_(false) {
87   helper_.reset(new ImageTransportHelper(this,
88                                          manager,
89                                          stub,
90                                          gfx::kNullPluginWindow));
91 }
92
93 PbufferImageTransportSurface::~PbufferImageTransportSurface() {
94   Destroy();
95 }
96
97 bool PbufferImageTransportSurface::Initialize() {
98   // Only support this path if the GL implementation is ANGLE.
99   // IO surfaces will not work with, for example, OSMesa software renderer
100   // GL contexts.
101   if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2)
102     return false;
103
104   if (!helper_->Initialize())
105     return false;
106
107   return GLSurfaceAdapter::Initialize();
108 }
109
110 void PbufferImageTransportSurface::Destroy() {
111   helper_->Destroy();
112   GLSurfaceAdapter::Destroy();
113 }
114
115 bool PbufferImageTransportSurface::DeferDraws() {
116   // The command buffer hit a draw/clear command that could clobber the
117   // IOSurface in use by an earlier SwapBuffers. If a Swap is pending, abort
118   // processing of the command by returning true and unschedule until the Swap
119   // Ack arrives.
120   if (did_unschedule_)
121     return true;
122   if (is_swap_buffers_pending_) {
123     did_unschedule_ = true;
124     helper_->SetScheduled(false);
125     return true;
126   }
127   return false;
128 }
129
130 bool PbufferImageTransportSurface::IsOffscreen() {
131   return false;
132 }
133
134 bool PbufferImageTransportSurface::SwapBuffers() {
135   DCHECK(backbuffer_suggested_allocation_);
136   if (!frontbuffer_suggested_allocation_)
137     return true;
138
139   HANDLE surface_handle = GetShareHandle();
140   if (!surface_handle)
141     return false;
142
143   // Don't send the surface to the browser until we hit the fence that
144   // indicates the drawing to the surface has been completed.
145   // TODO(jbates) unscheduling should be deferred until draw commands from the
146   // next frame -- otherwise the GPU is potentially sitting idle.
147   helper_->DeferToFence(base::Bind(
148       &PbufferImageTransportSurface::SendBuffersSwapped,
149       AsWeakPtr()));
150
151   return true;
152 }
153
154 bool PbufferImageTransportSurface::PostSubBuffer(
155     int x, int y, int width, int height) {
156   NOTREACHED();
157   return false;
158 }
159
160 bool PbufferImageTransportSurface::SetBackbufferAllocation(bool allocation) {
161   if (backbuffer_suggested_allocation_ == allocation)
162     return true;
163   backbuffer_suggested_allocation_ = allocation;
164
165   DestroySurface();
166
167   if (backbuffer_suggested_allocation_ && visible_size_.GetArea() != 0)
168     return Resize(visible_size_);
169   else
170     return Resize(gfx::Size(1, 1));
171 }
172
173 void PbufferImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
174   if (frontbuffer_suggested_allocation_ == allocation)
175     return;
176   frontbuffer_suggested_allocation_ = allocation;
177
178   // We recreate frontbuffer by recreating backbuffer and swapping.
179   // But we release frontbuffer by telling UI to release its handle on it.
180   if (!frontbuffer_suggested_allocation_)
181     helper_->Suspend();
182 }
183
184 void PbufferImageTransportSurface::DestroySurface() {
185   helper_->SendAcceleratedSurfaceRelease();
186 }
187
188 std::string PbufferImageTransportSurface::GetExtensions() {
189   std::string extensions = gfx::GLSurface::GetExtensions();
190   extensions += extensions.empty() ? "" : " ";
191   extensions += "GL_CHROMIUM_front_buffer_cached";
192   return extensions;
193 }
194
195 void PbufferImageTransportSurface::SendBuffersSwapped() {
196   GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
197   params.surface_handle = reinterpret_cast<int64>(GetShareHandle());
198   CHECK(params.surface_handle);
199   params.size = GetSize();
200   params.latency_info = latency_info_;
201
202   helper_->SendAcceleratedSurfaceBuffersSwapped(params);
203
204   DCHECK(!is_swap_buffers_pending_);
205   is_swap_buffers_pending_ = true;
206 }
207
208 void PbufferImageTransportSurface::OnBufferPresented(
209     const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
210   if (!params.vsync_timebase.is_null() &&
211       params.vsync_interval != base::TimeDelta()) {
212     helper_->SendUpdateVSyncParameters(params.vsync_timebase,
213                                        params.vsync_interval);
214   }
215   is_swap_buffers_pending_ = false;
216   if (did_unschedule_) {
217     did_unschedule_ = false;
218     helper_->SetScheduled(true);
219   }
220 }
221
222 void PbufferImageTransportSurface::OnResizeViewACK() {
223   NOTREACHED();
224 }
225
226 void PbufferImageTransportSurface::OnResize(gfx::Size size,
227                                             float scale_factor) {
228   DCHECK(backbuffer_suggested_allocation_);
229   DCHECK(frontbuffer_suggested_allocation_);
230   Resize(size);
231
232   DestroySurface();
233
234   visible_size_ = size;
235 }
236
237 void PbufferImageTransportSurface::SetLatencyInfo(
238     const ui::LatencyInfo& latency_info) {
239   latency_info_ = latency_info;
240 }
241
242 gfx::Size PbufferImageTransportSurface::GetSize() {
243   return GLSurfaceAdapter::GetSize();
244 }
245
246 }  // namespace anonymous
247
248 // static
249 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
250     GpuChannelManager* manager,
251     GpuCommandBufferStub* stub,
252     const gfx::GLSurfaceHandle& handle) {
253   DCHECK(handle.handle);
254   DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
255          handle.transport_type == gfx::NATIVE_TRANSPORT);
256   if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
257       !CommandLine::ForCurrentProcess()->HasSwitch(
258           switches::kDisableImageTransportSurface)) {
259     // This path handles two different cases.
260     //
261     // For post-Vista regular Windows, this surface will be used for
262     // renderer compositors.
263     //
264     // For Aura Windows, this will be the surface for the browser compositor
265     // (and the renderer compositors surface's will be
266     // TextureImageTransportSurface above).
267     const char* extensions = eglQueryString(
268         gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_EXTENSIONS);
269     if (extensions &&
270         strstr(extensions, "EGL_ANGLE_query_surface_pointer") &&
271         strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) {
272       return scoped_refptr<gfx::GLSurface>(
273           new PbufferImageTransportSurface(manager, stub));
274     }
275   }
276
277   scoped_refptr<gfx::GLSurface> surface =
278       gfx::GLSurface::CreateViewGLSurface(handle.handle);
279   if (!surface)
280     return surface;
281   return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
282       manager, stub, surface.get(), handle.is_transport()));
283 }
284
285 }  // namespace content