Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / common / gpu / image_transport_surface_win.cc
blobc69e3cc5264e0eb150d5513784ea591bc8a05a62
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.
5 #include "content/common/gpu/image_transport_surface.h"
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"
21 namespace content {
22 namespace {
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);
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;
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;
54 private:
55 virtual ~PbufferImageTransportSurface();
56 void SendBuffersSwapped();
57 void DestroySurface();
59 // Tracks the current buffer allocation state.
60 bool backbuffer_suggested_allocation_;
61 bool frontbuffer_suggested_allocation_;
63 // Whether a SwapBuffers is pending.
64 bool is_swap_buffers_pending_;
66 // Whether we unscheduled command buffer because of pending SwapBuffers.
67 bool did_unschedule_;
69 // Size to resize to when the surface becomes visible.
70 gfx::Size visible_size_;
72 ui::LatencyInfo latency_info_;
74 scoped_ptr<ImageTransportHelper> helper_;
76 DISALLOW_COPY_AND_ASSIGN(PbufferImageTransportSurface);
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));
93 PbufferImageTransportSurface::~PbufferImageTransportSurface() {
94 Destroy();
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;
104 if (!helper_->Initialize())
105 return false;
107 return GLSurfaceAdapter::Initialize();
110 void PbufferImageTransportSurface::Destroy() {
111 helper_->Destroy();
112 GLSurfaceAdapter::Destroy();
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;
127 return false;
130 bool PbufferImageTransportSurface::IsOffscreen() {
131 return false;
134 bool PbufferImageTransportSurface::SwapBuffers() {
135 DCHECK(backbuffer_suggested_allocation_);
136 if (!frontbuffer_suggested_allocation_)
137 return true;
139 HANDLE surface_handle = GetShareHandle();
140 if (!surface_handle)
141 return false;
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()));
151 return true;
154 bool PbufferImageTransportSurface::PostSubBuffer(
155 int x, int y, int width, int height) {
156 NOTREACHED();
157 return false;
160 bool PbufferImageTransportSurface::SetBackbufferAllocation(bool allocation) {
161 if (backbuffer_suggested_allocation_ == allocation)
162 return true;
163 backbuffer_suggested_allocation_ = allocation;
165 DestroySurface();
167 if (backbuffer_suggested_allocation_ && visible_size_.GetArea() != 0)
168 return Resize(visible_size_);
169 else
170 return Resize(gfx::Size(1, 1));
173 void PbufferImageTransportSurface::SetFrontbufferAllocation(bool allocation) {
174 if (frontbuffer_suggested_allocation_ == allocation)
175 return;
176 frontbuffer_suggested_allocation_ = allocation;
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();
184 void PbufferImageTransportSurface::DestroySurface() {
185 GpuHostMsg_AcceleratedSurfaceRelease_Params params;
186 helper_->SendAcceleratedSurfaceRelease(params);
189 std::string PbufferImageTransportSurface::GetExtensions() {
190 std::string extensions = gfx::GLSurface::GetExtensions();
191 extensions += extensions.empty() ? "" : " ";
192 extensions += "GL_CHROMIUM_front_buffer_cached";
193 return extensions;
196 void PbufferImageTransportSurface::SendBuffersSwapped() {
197 GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
198 params.surface_handle = reinterpret_cast<int64>(GetShareHandle());
199 CHECK(params.surface_handle);
200 params.size = GetSize();
201 params.latency_info = latency_info_;
203 helper_->SendAcceleratedSurfaceBuffersSwapped(params);
205 DCHECK(!is_swap_buffers_pending_);
206 is_swap_buffers_pending_ = true;
209 void PbufferImageTransportSurface::OnBufferPresented(
210 const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
211 if (!params.vsync_timebase.is_null() &&
212 params.vsync_interval != base::TimeDelta()) {
213 helper_->SendUpdateVSyncParameters(params.vsync_timebase,
214 params.vsync_interval);
216 is_swap_buffers_pending_ = false;
217 if (did_unschedule_) {
218 did_unschedule_ = false;
219 helper_->SetScheduled(true);
223 void PbufferImageTransportSurface::OnResizeViewACK() {
224 NOTREACHED();
227 void PbufferImageTransportSurface::OnResize(gfx::Size size,
228 float scale_factor) {
229 DCHECK(backbuffer_suggested_allocation_);
230 DCHECK(frontbuffer_suggested_allocation_);
231 Resize(size);
233 DestroySurface();
235 visible_size_ = size;
238 void PbufferImageTransportSurface::SetLatencyInfo(
239 const ui::LatencyInfo& latency_info) {
240 latency_info_ = latency_info;
243 gfx::Size PbufferImageTransportSurface::GetSize() {
244 return GLSurfaceAdapter::GetSize();
247 } // namespace anonymous
249 // static
250 scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
251 GpuChannelManager* manager,
252 GpuCommandBufferStub* stub,
253 const gfx::GLSurfaceHandle& handle) {
254 DCHECK(handle.handle);
255 DCHECK(handle.transport_type == gfx::NATIVE_DIRECT ||
256 handle.transport_type == gfx::NATIVE_TRANSPORT);
257 if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
258 !CommandLine::ForCurrentProcess()->HasSwitch(
259 switches::kDisableImageTransportSurface)) {
260 // This path handles two different cases.
262 // For post-Vista regular Windows, this surface will be used for
263 // renderer compositors.
265 // For Aura Windows, this will be the surface for the browser compositor
266 // (and the renderer compositors surface's will be
267 // TextureImageTransportSurface above).
268 const char* extensions = eglQueryString(
269 gfx::GLSurfaceEGL::GetHardwareDisplay(), EGL_EXTENSIONS);
270 if (extensions &&
271 strstr(extensions, "EGL_ANGLE_query_surface_pointer") &&
272 strstr(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle")) {
273 return scoped_refptr<gfx::GLSurface>(
274 new PbufferImageTransportSurface(manager, stub));
278 scoped_refptr<gfx::GLSurface> surface =
279 gfx::GLSurface::CreateViewGLSurface(handle.handle);
280 if (!surface)
281 return surface;
282 return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
283 manager, stub, surface.get(), handle.is_transport()));
286 } // namespace content