| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/renderer/android/synchronous_compositor_output_surface.h" | 5 #include "content/renderer/android/synchronous_compositor_output_surface.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
| 15 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 16 #include "cc/output/compositor_frame.h" | 16 #include "cc/output/compositor_frame.h" |
| 17 #include "cc/output/context_provider.h" | 17 #include "cc/output/context_provider.h" |
| 18 #include "cc/output/output_surface_client.h" | 18 #include "cc/output/output_surface_client.h" |
| 19 #include "cc/output/renderer_settings.h" |
| 19 #include "cc/output/software_output_device.h" | 20 #include "cc/output/software_output_device.h" |
| 21 #include "cc/output/texture_mailbox_deleter.h" |
| 22 #include "cc/surfaces/display.h" |
| 23 #include "cc/surfaces/surface_factory.h" |
| 24 #include "cc/surfaces/surface_id_allocator.h" |
| 25 #include "cc/surfaces/surface_manager.h" |
| 20 #include "content/common/android/sync_compositor_messages.h" | 26 #include "content/common/android/sync_compositor_messages.h" |
| 21 #include "content/renderer/android/synchronous_compositor_filter.h" | 27 #include "content/renderer/android/synchronous_compositor_filter.h" |
| 22 #include "content/renderer/android/synchronous_compositor_registry.h" | 28 #include "content/renderer/android/synchronous_compositor_registry.h" |
| 23 #include "content/renderer/gpu/frame_swap_message_queue.h" | 29 #include "content/renderer/gpu/frame_swap_message_queue.h" |
| 24 #include "content/renderer/render_thread_impl.h" | 30 #include "content/renderer/render_thread_impl.h" |
| 25 #include "gpu/command_buffer/client/context_support.h" | 31 #include "gpu/command_buffer/client/context_support.h" |
| 26 #include "gpu/command_buffer/client/gles2_interface.h" | 32 #include "gpu/command_buffer/client/gles2_interface.h" |
| 27 #include "gpu/command_buffer/common/gpu_memory_allocation.h" | 33 #include "gpu/command_buffer/common/gpu_memory_allocation.h" |
| 28 #include "ipc/ipc_message.h" | 34 #include "ipc/ipc_message.h" |
| 29 #include "ipc/ipc_message_macros.h" | 35 #include "ipc/ipc_message_macros.h" |
| 30 #include "ipc/ipc_sender.h" | 36 #include "ipc/ipc_sender.h" |
| 31 #include "third_party/skia/include/core/SkCanvas.h" | 37 #include "third_party/skia/include/core/SkCanvas.h" |
| 32 #include "ui/gfx/geometry/rect_conversions.h" | 38 #include "ui/gfx/geometry/rect_conversions.h" |
| 33 #include "ui/gfx/skia_util.h" | 39 #include "ui/gfx/skia_util.h" |
| 34 #include "ui/gfx/transform.h" | 40 #include "ui/gfx/transform.h" |
| 35 | 41 |
| 36 namespace content { | 42 namespace content { |
| 37 | 43 |
| 38 namespace { | 44 namespace { |
| 39 | 45 |
| 40 const int64_t kFallbackTickTimeoutInMilliseconds = 100; | 46 const int64_t kFallbackTickTimeoutInMilliseconds = 100; |
| 47 const uint32_t kCompositorSurfaceNamespace = 1; |
| 41 | 48 |
| 42 // Do not limit number of resources, so use an unrealistically high value. | 49 // Do not limit number of resources, so use an unrealistically high value. |
| 43 const size_t kNumResourcesLimit = 10 * 1000 * 1000; | 50 const size_t kNumResourcesLimit = 10 * 1000 * 1000; |
| 44 | 51 |
| 45 } // namespace | 52 } // namespace |
| 46 | 53 |
| 47 class SynchronousCompositorOutputSurface::SoftwareDevice | 54 class SoftwareDevice : public cc::SoftwareOutputDevice { |
| 48 : public cc::SoftwareOutputDevice { | |
| 49 public: | 55 public: |
| 50 SoftwareDevice(SynchronousCompositorOutputSurface* surface) | 56 SoftwareDevice(SkCanvas** canvas) : canvas_(canvas) {} |
| 51 : surface_(surface) { | 57 |
| 52 } | |
| 53 void Resize(const gfx::Size& pixel_size, float scale_factor) override { | 58 void Resize(const gfx::Size& pixel_size, float scale_factor) override { |
| 54 // Intentional no-op: canvas size is controlled by the embedder. | 59 // Intentional no-op: canvas size is controlled by the embedder. |
| 55 } | 60 } |
| 56 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override { | 61 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override { |
| 57 if (!surface_->current_sw_canvas_) { | 62 DCHECK(*canvas_) << "BeginPaint with no canvas set"; |
| 58 NOTREACHED() << "BeginPaint with no canvas set"; | 63 return *canvas_; |
| 59 return &null_canvas_; | |
| 60 } | |
| 61 LOG_IF(WARNING, surface_->did_swap_) | |
| 62 << "Mutliple calls to BeginPaint per frame"; | |
| 63 return surface_->current_sw_canvas_; | |
| 64 } | 64 } |
| 65 void EndPaint() override {} | 65 void EndPaint() override {} |
| 66 | 66 |
| 67 private: | 67 private: |
| 68 SynchronousCompositorOutputSurface* surface_; | 68 SkCanvas** canvas_; |
| 69 SkCanvas null_canvas_; | |
| 70 | 69 |
| 71 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice); | 70 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice); |
| 72 }; | 71 }; |
| 73 | 72 |
| 73 class SoftwareOutputSurface : public cc::OutputSurface { |
| 74 public: |
| 75 SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device) |
| 76 : cc::OutputSurface(nullptr, nullptr, std::move(software_device)) {} |
| 77 |
| 78 // cc::OutputSurface implementation. |
| 79 uint32_t GetFramebufferCopyTextureFormat() override { return 0; } |
| 80 void SwapBuffers(cc::CompositorFrame frame) override {} |
| 81 }; |
| 82 |
| 74 SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( | 83 SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface( |
| 75 scoped_refptr<cc::ContextProvider> context_provider, | 84 scoped_refptr<cc::ContextProvider> context_provider, |
| 76 scoped_refptr<cc::ContextProvider> worker_context_provider, | 85 scoped_refptr<cc::ContextProvider> worker_context_provider, |
| 77 int routing_id, | 86 int routing_id, |
| 78 uint32_t output_surface_id, | 87 uint32_t output_surface_id, |
| 79 SynchronousCompositorRegistry* registry, | 88 SynchronousCompositorRegistry* registry, |
| 80 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue) | 89 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue) |
| 81 : cc::OutputSurface(std::move(context_provider), | 90 : cc::OutputSurface(std::move(context_provider), |
| 82 std::move(worker_context_provider), | 91 std::move(worker_context_provider), |
| 83 base::MakeUnique<SoftwareDevice>(this)), | 92 nullptr), |
| 84 routing_id_(routing_id), | 93 routing_id_(routing_id), |
| 85 output_surface_id_(output_surface_id), | 94 output_surface_id_(output_surface_id), |
| 86 registry_(registry), | 95 registry_(registry), |
| 87 sender_(RenderThreadImpl::current()->sync_compositor_message_filter()), | 96 sender_(RenderThreadImpl::current()->sync_compositor_message_filter()), |
| 88 registered_(false), | |
| 89 sync_client_(nullptr), | |
| 90 current_sw_canvas_(nullptr), | |
| 91 memory_policy_(0u), | 97 memory_policy_(0u), |
| 92 did_swap_(false), | |
| 93 frame_swap_message_queue_(frame_swap_message_queue), | 98 frame_swap_message_queue_(frame_swap_message_queue), |
| 94 fallback_tick_pending_(false), | 99 surface_manager_(new cc::SurfaceManager), |
| 95 fallback_tick_running_(false) { | 100 surface_id_allocator_( |
| 101 new cc::SurfaceIdAllocator(kCompositorSurfaceNamespace)), |
| 102 surface_factory_(new cc::SurfaceFactory(surface_manager_.get(), this)) { |
| 96 DCHECK(registry_); | 103 DCHECK(registry_); |
| 97 DCHECK(sender_); | 104 DCHECK(sender_); |
| 98 thread_checker_.DetachFromThread(); | 105 thread_checker_.DetachFromThread(); |
| 99 capabilities_.adjust_deadline_for_parent = false; | 106 capabilities_.adjust_deadline_for_parent = false; |
| 100 capabilities_.delegated_rendering = true; | 107 capabilities_.delegated_rendering = true; |
| 101 memory_policy_.priority_cutoff_when_visible = | 108 memory_policy_.priority_cutoff_when_visible = |
| 102 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; | 109 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE; |
| 110 surface_id_allocator_->RegisterSurfaceIdNamespace(surface_manager_.get()); |
| 103 } | 111 } |
| 104 | 112 |
| 105 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {} | 113 SynchronousCompositorOutputSurface::~SynchronousCompositorOutputSurface() {} |
| 106 | 114 |
| 107 void SynchronousCompositorOutputSurface::SetSyncClient( | 115 void SynchronousCompositorOutputSurface::SetSyncClient( |
| 108 SynchronousCompositorOutputSurfaceClient* compositor) { | 116 SynchronousCompositorOutputSurfaceClient* compositor) { |
| 109 DCHECK(CalledOnValidThread()); | 117 DCHECK(CalledOnValidThread()); |
| 110 sync_client_ = compositor; | 118 sync_client_ = compositor; |
| 111 if (sync_client_) | 119 if (sync_client_) |
| 112 Send(new SyncCompositorHostMsg_OutputSurfaceCreated(routing_id_)); | 120 Send(new SyncCompositorHostMsg_OutputSurfaceCreated(routing_id_)); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 128 DCHECK(CalledOnValidThread()); | 136 DCHECK(CalledOnValidThread()); |
| 129 if (!cc::OutputSurface::BindToClient(surface_client)) | 137 if (!cc::OutputSurface::BindToClient(surface_client)) |
| 130 return false; | 138 return false; |
| 131 | 139 |
| 132 client_->SetMemoryPolicy(memory_policy_); | 140 client_->SetMemoryPolicy(memory_policy_); |
| 133 client_->SetTreeActivationCallback( | 141 client_->SetTreeActivationCallback( |
| 134 base::Bind(&SynchronousCompositorOutputSurface::DidActivatePendingTree, | 142 base::Bind(&SynchronousCompositorOutputSurface::DidActivatePendingTree, |
| 135 base::Unretained(this))); | 143 base::Unretained(this))); |
| 136 registry_->RegisterOutputSurface(routing_id_, this); | 144 registry_->RegisterOutputSurface(routing_id_, this); |
| 137 registered_ = true; | 145 registered_ = true; |
| 146 |
| 147 surface_manager_->RegisterSurfaceFactoryClient( |
| 148 surface_id_allocator_->id_namespace(), this); |
| 149 |
| 150 cc::RendererSettings software_renderer_settings; |
| 151 |
| 152 // The shared_bitmap_manager and gpu_memory_buffer_manager here are null as |
| 153 // this Display is only used for resourcesless software draws, where no |
| 154 // resources are included in the frame swapped from the compositor. So there |
| 155 // is no need for these. |
| 156 display_.reset(new cc::Display( |
| 157 surface_manager_.get(), nullptr /* shared_bitmap_manager */, |
| 158 nullptr /* gpu_memory_buffer_manager */, software_renderer_settings, |
| 159 surface_id_allocator_->id_namespace(), nullptr /* begin_frame_source */, |
| 160 base::MakeUnique<SoftwareOutputSurface>( |
| 161 base::MakeUnique<SoftwareDevice>(¤t_sw_canvas_)), |
| 162 nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */)); |
| 163 display_->Initialize(&display_client_); |
| 138 return true; | 164 return true; |
| 139 } | 165 } |
| 140 | 166 |
| 141 void SynchronousCompositorOutputSurface::DetachFromClient() { | 167 void SynchronousCompositorOutputSurface::DetachFromClient() { |
| 142 DCHECK(CalledOnValidThread()); | 168 DCHECK(CalledOnValidThread()); |
| 143 if (registered_) { | 169 if (registered_) { |
| 144 registry_->UnregisterOutputSurface(routing_id_, this); | 170 registry_->UnregisterOutputSurface(routing_id_, this); |
| 145 } | 171 } |
| 146 client_->SetTreeActivationCallback(base::Closure()); | 172 client_->SetTreeActivationCallback(base::Closure()); |
| 173 if (!delegated_surface_id_.is_null()) |
| 174 surface_factory_->Destroy(delegated_surface_id_); |
| 175 surface_manager_->UnregisterSurfaceFactoryClient( |
| 176 surface_id_allocator_->id_namespace()); |
| 177 display_ = nullptr; |
| 178 surface_factory_ = nullptr; |
| 179 surface_id_allocator_ = nullptr; |
| 180 surface_manager_ = nullptr; |
| 147 cc::OutputSurface::DetachFromClient(); | 181 cc::OutputSurface::DetachFromClient(); |
| 148 CancelFallbackTick(); | 182 CancelFallbackTick(); |
| 149 } | 183 } |
| 150 | 184 |
| 151 void SynchronousCompositorOutputSurface::Reshape( | 185 void SynchronousCompositorOutputSurface::Reshape( |
| 152 const gfx::Size& size, | 186 const gfx::Size& size, |
| 153 float scale_factor, | 187 float scale_factor, |
| 154 const gfx::ColorSpace& color_space, | 188 const gfx::ColorSpace& color_space, |
| 155 bool has_alpha) { | 189 bool has_alpha) { |
| 156 // Intentional no-op: surface size is controlled by the embedder. | 190 // Intentional no-op: surface size is controlled by the embedder. |
| 157 } | 191 } |
| 158 | 192 |
| 193 static void NoOpDrawCallback(cc::SurfaceDrawStatus s) {} |
| 194 |
| 159 void SynchronousCompositorOutputSurface::SwapBuffers( | 195 void SynchronousCompositorOutputSurface::SwapBuffers( |
| 160 cc::CompositorFrame frame) { | 196 cc::CompositorFrame frame) { |
| 161 DCHECK(CalledOnValidThread()); | 197 DCHECK(CalledOnValidThread()); |
| 162 DCHECK(sync_client_); | 198 DCHECK(sync_client_); |
| 199 |
| 200 cc::CompositorFrame swap_frame; |
| 201 |
| 202 if (in_software_draw_) { |
| 203 // The frame we send to the client is actually just the metadata. Preserve |
| 204 // the |frame| for the software path below. |
| 205 swap_frame.metadata = frame.metadata.Clone(); |
| 206 |
| 207 if (delegated_surface_id_.is_null()) { |
| 208 delegated_surface_id_ = surface_id_allocator_->GenerateId(); |
| 209 surface_factory_->Create(delegated_surface_id_); |
| 210 } |
| 211 |
| 212 display_->SetSurfaceId(delegated_surface_id_, |
| 213 frame.metadata.device_scale_factor); |
| 214 |
| 215 gfx::Size frame_size = |
| 216 frame.delegated_frame_data->render_pass_list.back()->output_rect.size(); |
| 217 display_->Resize(frame_size); |
| 218 |
| 219 surface_factory_->SubmitCompositorFrame( |
| 220 delegated_surface_id_, std::move(frame), base::Bind(&NoOpDrawCallback)); |
| 221 display_->DrawAndSwap(); |
| 222 } else { |
| 223 swap_frame = std::move(frame); |
| 224 } |
| 225 |
| 163 if (!fallback_tick_running_) { | 226 if (!fallback_tick_running_) { |
| 164 sync_client_->SwapBuffers(output_surface_id_, std::move(frame)); | 227 sync_client_->SwapBuffers(output_surface_id_, std::move(swap_frame)); |
| 165 DeliverMessages(); | 228 DeliverMessages(); |
| 166 } | 229 } |
| 167 client_->DidSwapBuffers(); | 230 client_->DidSwapBuffers(); |
| 168 did_swap_ = true; | 231 did_swap_ = true; |
| 169 } | 232 } |
| 170 | 233 |
| 171 void SynchronousCompositorOutputSurface::CancelFallbackTick() { | 234 void SynchronousCompositorOutputSurface::CancelFallbackTick() { |
| 172 fallback_tick_.Cancel(); | 235 fallback_tick_.Cancel(); |
| 173 fallback_tick_pending_ = false; | 236 fallback_tick_pending_ = false; |
| 174 } | 237 } |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 const gfx::Rect& viewport_rect_for_tile_priority, | 284 const gfx::Rect& viewport_rect_for_tile_priority, |
| 222 const gfx::Transform& transform_for_tile_priority) { | 285 const gfx::Transform& transform_for_tile_priority) { |
| 223 DCHECK(CalledOnValidThread()); | 286 DCHECK(CalledOnValidThread()); |
| 224 DCHECK(HasClient()); | 287 DCHECK(HasClient()); |
| 225 DCHECK(context_provider_.get()); | 288 DCHECK(context_provider_.get()); |
| 226 CancelFallbackTick(); | 289 CancelFallbackTick(); |
| 227 | 290 |
| 228 surface_size_ = surface_size; | 291 surface_size_ = surface_size; |
| 229 client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority, | 292 client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority, |
| 230 transform_for_tile_priority); | 293 transform_for_tile_priority); |
| 231 const bool software_draw = false; | 294 InvokeComposite(transform, viewport, clip); |
| 232 InvokeComposite(transform, viewport, clip, software_draw); | |
| 233 } | 295 } |
| 234 | 296 |
| 235 void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { | 297 void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) { |
| 236 DCHECK(CalledOnValidThread()); | 298 DCHECK(CalledOnValidThread()); |
| 237 DCHECK(canvas); | 299 DCHECK(canvas); |
| 238 DCHECK(!current_sw_canvas_); | 300 DCHECK(!current_sw_canvas_); |
| 239 CancelFallbackTick(); | 301 CancelFallbackTick(); |
| 240 | 302 |
| 241 base::AutoReset<SkCanvas*> canvas_resetter(¤t_sw_canvas_, canvas); | 303 base::AutoReset<SkCanvas*> canvas_resetter(¤t_sw_canvas_, canvas); |
| 242 | 304 |
| 243 SkIRect canvas_clip; | 305 SkIRect canvas_clip; |
| 244 canvas->getClipDeviceBounds(&canvas_clip); | 306 canvas->getClipDeviceBounds(&canvas_clip); |
| 245 gfx::Rect clip = gfx::SkIRectToRect(canvas_clip); | 307 gfx::Rect clip = gfx::SkIRectToRect(canvas_clip); |
| 246 | 308 |
| 247 gfx::Transform transform(gfx::Transform::kSkipInitialization); | 309 gfx::Transform transform(gfx::Transform::kSkipInitialization); |
| 248 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4. | 310 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4. |
| 249 | 311 |
| 250 surface_size_ = gfx::Size(canvas->getBaseLayerSize().width(), | 312 surface_size_ = gfx::Size(canvas->getBaseLayerSize().width(), |
| 251 canvas->getBaseLayerSize().height()); | 313 canvas->getBaseLayerSize().height()); |
| 252 const bool software_draw = true; | 314 base::AutoReset<bool> set_in_software_draw(&in_software_draw_, true); |
| 253 InvokeComposite(transform, clip, clip, software_draw); | 315 InvokeComposite(transform, clip, clip); |
| 254 } | 316 } |
| 255 | 317 |
| 256 void SynchronousCompositorOutputSurface::InvokeComposite( | 318 void SynchronousCompositorOutputSurface::InvokeComposite( |
| 257 const gfx::Transform& transform, | 319 const gfx::Transform& transform, |
| 258 const gfx::Rect& viewport, | 320 const gfx::Rect& viewport, |
| 259 const gfx::Rect& clip, | 321 const gfx::Rect& clip) { |
| 260 bool software_draw) { | |
| 261 gfx::Transform adjusted_transform = transform; | 322 gfx::Transform adjusted_transform = transform; |
| 262 adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0); | 323 adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0); |
| 263 did_swap_ = false; | 324 did_swap_ = false; |
| 264 client_->OnDraw(adjusted_transform, viewport, clip, software_draw); | 325 client_->OnDraw(adjusted_transform, viewport, clip, in_software_draw_); |
| 265 | 326 |
| 266 if (did_swap_) | 327 if (did_swap_) |
| 267 client_->DidSwapBuffersComplete(); | 328 client_->DidSwapBuffersComplete(); |
| 268 } | 329 } |
| 269 | 330 |
| 270 void SynchronousCompositorOutputSurface::OnReclaimResources( | 331 void SynchronousCompositorOutputSurface::OnReclaimResources( |
| 271 uint32_t output_surface_id, | 332 uint32_t output_surface_id, |
| 272 const cc::CompositorFrameAck& ack) { | 333 const cc::CompositorFrameAck& ack) { |
| 273 // Ignore message if it's a stale one coming from a different output surface | 334 // Ignore message if it's a stale one coming from a different output surface |
| 274 // (e.g. after a lost context). | 335 // (e.g. after a lost context). |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 318 | 379 |
| 319 bool SynchronousCompositorOutputSurface::Send(IPC::Message* message) { | 380 bool SynchronousCompositorOutputSurface::Send(IPC::Message* message) { |
| 320 DCHECK(CalledOnValidThread()); | 381 DCHECK(CalledOnValidThread()); |
| 321 return sender_->Send(message); | 382 return sender_->Send(message); |
| 322 } | 383 } |
| 323 | 384 |
| 324 bool SynchronousCompositorOutputSurface::CalledOnValidThread() const { | 385 bool SynchronousCompositorOutputSurface::CalledOnValidThread() const { |
| 325 return thread_checker_.CalledOnValidThread(); | 386 return thread_checker_.CalledOnValidThread(); |
| 326 } | 387 } |
| 327 | 388 |
| 389 void SynchronousCompositorOutputSurface::ReturnResources( |
| 390 const cc::ReturnedResourceArray& resources) { |
| 391 DCHECK(resources.empty()); |
| 392 cc::CompositorFrameAck ack; |
| 393 client_->ReclaimResources(&ack); |
| 394 } |
| 395 |
| 396 void SynchronousCompositorOutputSurface::SetBeginFrameSource( |
| 397 cc::BeginFrameSource* begin_frame_source) { |
| 398 // Software output is synchronous and doesn't use a BeginFrameSource. |
| 399 NOTREACHED(); |
| 400 } |
| 401 |
| 328 } // namespace content | 402 } // namespace content |
| OLD | NEW |