OLD | NEW |
| (Empty) |
1 // Copyright 2016 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 "components/mus/surfaces/direct_output_surface_ozone.h" | |
6 | |
7 #include <utility> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/memory/ptr_util.h" | |
11 #include "cc/output/compositor_frame.h" | |
12 #include "cc/output/context_provider.h" | |
13 #include "cc/output/output_surface_client.h" | |
14 #include "cc/scheduler/begin_frame_source.h" | |
15 #include "components/display_compositor/buffer_queue.h" | |
16 #include "components/mus/common/gpu_service.h" | |
17 #include "components/mus/common/mojo_gpu_memory_buffer_manager.h" | |
18 #include "components/mus/gpu/mus_gpu_memory_buffer_manager.h" | |
19 #include "components/mus/surfaces/surfaces_context_provider.h" | |
20 #include "gpu/command_buffer/client/context_support.h" | |
21 #include "gpu/command_buffer/client/gles2_interface.h" | |
22 | |
23 using display_compositor::BufferQueue; | |
24 | |
25 namespace mus { | |
26 | |
27 DirectOutputSurfaceOzone::DirectOutputSurfaceOzone( | |
28 scoped_refptr<SurfacesContextProvider> context_provider, | |
29 gfx::AcceleratedWidget widget, | |
30 cc::SyntheticBeginFrameSource* synthetic_begin_frame_source, | |
31 uint32_t target, | |
32 uint32_t internalformat) | |
33 : cc::OutputSurface(context_provider, nullptr, nullptr), | |
34 gl_helper_(context_provider->ContextGL(), | |
35 context_provider->ContextSupport()), | |
36 synthetic_begin_frame_source_(synthetic_begin_frame_source), | |
37 weak_ptr_factory_(this) { | |
38 if (!GpuService::UseChromeGpuCommandBuffer()) { | |
39 ozone_gpu_memory_buffer_manager_.reset(new OzoneGpuMemoryBufferManager()); | |
40 buffer_queue_.reset(new BufferQueue( | |
41 context_provider->ContextGL(), target, internalformat, &gl_helper_, | |
42 ozone_gpu_memory_buffer_manager_.get(), widget)); | |
43 } else { | |
44 buffer_queue_.reset(new BufferQueue( | |
45 context_provider->ContextGL(), target, internalformat, &gl_helper_, | |
46 MusGpuMemoryBufferManager::current(), widget)); | |
47 } | |
48 | |
49 capabilities_.uses_default_gl_framebuffer = false; | |
50 capabilities_.flipped_output_surface = true; | |
51 // Set |max_frames_pending| to 2 for surfaceless, which aligns scheduling | |
52 // more closely with the previous surfaced behavior. | |
53 // With a surface, swap buffer ack used to return early, before actually | |
54 // presenting the back buffer, enabling the browser compositor to run ahead. | |
55 // Surfaceless implementation acks at the time of actual buffer swap, which | |
56 // shifts the start of the new frame forward relative to the old | |
57 // implementation. | |
58 capabilities_.max_frames_pending = 2; | |
59 | |
60 buffer_queue_->Initialize(); | |
61 | |
62 context_provider->SetSwapBuffersCompletionCallback( | |
63 base::Bind(&DirectOutputSurfaceOzone::OnGpuSwapBuffersCompleted, | |
64 base::Unretained(this))); | |
65 } | |
66 | |
67 DirectOutputSurfaceOzone::~DirectOutputSurfaceOzone() { | |
68 // TODO(rjkroege): Support cleanup. | |
69 } | |
70 | |
71 bool DirectOutputSurfaceOzone::IsDisplayedAsOverlayPlane() const { | |
72 // TODO(rjkroege): implement remaining overlay functionality. | |
73 return true; | |
74 } | |
75 | |
76 unsigned DirectOutputSurfaceOzone::GetOverlayTextureId() const { | |
77 DCHECK(buffer_queue_); | |
78 return buffer_queue_->current_texture_id(); | |
79 } | |
80 | |
81 void DirectOutputSurfaceOzone::SwapBuffers(cc::CompositorFrame frame) { | |
82 DCHECK(buffer_queue_); | |
83 DCHECK(frame.gl_frame_data); | |
84 | |
85 buffer_queue_->SwapBuffers(frame.gl_frame_data->sub_buffer_rect); | |
86 | |
87 // Code combining GpuBrowserCompositorOutputSurface + DirectOutputSurface | |
88 if (frame.gl_frame_data->sub_buffer_rect == | |
89 gfx::Rect(frame.gl_frame_data->size)) { | |
90 context_provider_->ContextSupport()->Swap(); | |
91 } else { | |
92 context_provider_->ContextSupport()->PartialSwapBuffers( | |
93 frame.gl_frame_data->sub_buffer_rect); | |
94 } | |
95 | |
96 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
97 const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM(); | |
98 gl->ShallowFlushCHROMIUM(); | |
99 | |
100 gpu::SyncToken sync_token; | |
101 gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); | |
102 | |
103 client_->DidSwapBuffers(); | |
104 } | |
105 | |
106 bool DirectOutputSurfaceOzone::BindToClient(cc::OutputSurfaceClient* client) { | |
107 if (!cc::OutputSurface::BindToClient(client)) | |
108 return false; | |
109 | |
110 if (capabilities_.uses_default_gl_framebuffer) { | |
111 capabilities_.flipped_output_surface = | |
112 context_provider()->ContextCapabilities().flips_vertically; | |
113 } | |
114 return true; | |
115 } | |
116 | |
117 void DirectOutputSurfaceOzone::OnUpdateVSyncParametersFromGpu( | |
118 base::TimeTicks timebase, | |
119 base::TimeDelta interval) { | |
120 DCHECK(HasClient()); | |
121 synthetic_begin_frame_source_->OnUpdateVSyncParameters(timebase, interval); | |
122 } | |
123 | |
124 void DirectOutputSurfaceOzone::OnGpuSwapBuffersCompleted( | |
125 gfx::SwapResult result) { | |
126 DCHECK(buffer_queue_); | |
127 bool force_swap = false; | |
128 if (result == gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS) { | |
129 // Even through the swap failed, this is a fixable error so we can pretend | |
130 // it succeeded to the rest of the system. | |
131 result = gfx::SwapResult::SWAP_ACK; | |
132 buffer_queue_->RecreateBuffers(); | |
133 force_swap = true; | |
134 } | |
135 | |
136 buffer_queue_->PageFlipComplete(); | |
137 OnSwapBuffersComplete(); | |
138 | |
139 if (force_swap) | |
140 client_->SetNeedsRedrawRect(gfx::Rect(SurfaceSize())); | |
141 } | |
142 | |
143 void DirectOutputSurfaceOzone::BindFramebuffer() { | |
144 DCHECK(buffer_queue_); | |
145 buffer_queue_->BindFramebuffer(); | |
146 } | |
147 | |
148 uint32_t DirectOutputSurfaceOzone::GetFramebufferCopyTextureFormat() { | |
149 return buffer_queue_->internal_format(); | |
150 } | |
151 | |
152 // We call this on every frame but changing the size once we've allocated | |
153 // backing NativePixmapOzone instances will cause a DCHECK because | |
154 // Chrome never Reshape(s) after the first one from (0,0). NB: this implies | |
155 // that screen size changes need to be plumbed differently. In particular, we | |
156 // must create the native window in the size that the hardware reports. | |
157 void DirectOutputSurfaceOzone::Reshape(const gfx::Size& size, | |
158 float scale_factor, | |
159 const gfx::ColorSpace& color_space, | |
160 bool alpha) { | |
161 OutputSurface::Reshape(size, scale_factor, color_space, alpha); | |
162 DCHECK(buffer_queue_); | |
163 buffer_queue_->Reshape(SurfaceSize(), scale_factor); | |
164 } | |
165 | |
166 } // namespace mus | |
OLD | NEW |