1// Copyright 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 "cc/output/delegating_renderer.h"
6
7#include <set>
8#include <string>
9#include <vector>
10
11#include "base/debug/trace_event.h"
12#include "cc/output/compositor_frame_ack.h"
13#include "cc/output/context_provider.h"
14#include "cc/quads/draw_quad.h"
15#include "cc/quads/render_pass.h"
16#include "cc/resources/resource_provider.h"
17#include "gpu/command_buffer/client/context_support.h"
18#include "gpu/command_buffer/client/gles2_interface.h"
19
20
21namespace cc {
22
23scoped_ptr<DelegatingRenderer> DelegatingRenderer::Create(
24    RendererClient* client,
25    const LayerTreeSettings* settings,
26    OutputSurface* output_surface,
27    ResourceProvider* resource_provider) {
28  return make_scoped_ptr(new DelegatingRenderer(
29      client, settings, output_surface, resource_provider));
30}
31
32DelegatingRenderer::DelegatingRenderer(RendererClient* client,
33                                       const LayerTreeSettings* settings,
34                                       OutputSurface* output_surface,
35                                       ResourceProvider* resource_provider)
36    : Renderer(client, settings),
37      output_surface_(output_surface),
38      resource_provider_(resource_provider) {
39  DCHECK(resource_provider_);
40
41  capabilities_.using_partial_swap = false;
42  capabilities_.max_texture_size = resource_provider_->max_texture_size();
43  capabilities_.best_texture_format = resource_provider_->best_texture_format();
44  capabilities_.allow_partial_texture_updates = false;
45
46  if (!output_surface_->context_provider()) {
47    capabilities_.using_shared_memory_resources = true;
48    capabilities_.using_map_image = true;
49  } else {
50    const ContextProvider::Capabilities& caps =
51        output_surface_->context_provider()->ContextCapabilities();
52
53    DCHECK(!caps.gpu.iosurface || caps.gpu.texture_rectangle);
54
55    capabilities_.using_egl_image = caps.gpu.egl_image_external;
56    capabilities_.using_map_image = caps.gpu.map_image;
57
58    capabilities_.allow_rasterize_on_demand = false;
59  }
60}
61
62DelegatingRenderer::~DelegatingRenderer() {}
63
64const RendererCapabilitiesImpl& DelegatingRenderer::Capabilities() const {
65  return capabilities_;
66}
67
68static ResourceProvider::ResourceId AppendToArray(
69    ResourceProvider::ResourceIdArray* array,
70    ResourceProvider::ResourceId id) {
71  array->push_back(id);
72  return id;
73}
74
75void DelegatingRenderer::DrawFrame(RenderPassList* render_passes_in_draw_order,
76                                   float device_scale_factor,
77                                   const gfx::Rect& device_viewport_rect,
78                                   const gfx::Rect& device_clip_rect,
79                                   bool disable_picture_quad_image_filtering) {
80  TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame");
81
82  DCHECK(!delegated_frame_data_);
83
84  delegated_frame_data_ = make_scoped_ptr(new DelegatedFrameData);
85  DelegatedFrameData& out_data = *delegated_frame_data_;
86  out_data.device_scale_factor = device_scale_factor;
87  // Move the render passes and resources into the |out_frame|.
88  out_data.render_pass_list.swap(*render_passes_in_draw_order);
89
90  // Collect all resource ids in the render passes into a ResourceIdArray.
91  ResourceProvider::ResourceIdArray resources;
92  DrawQuad::ResourceIteratorCallback append_to_array =
93      base::Bind(&AppendToArray, &resources);
94  for (size_t i = 0; i < out_data.render_pass_list.size(); ++i) {
95    RenderPass* render_pass = out_data.render_pass_list.at(i);
96    for (QuadList::Iterator iter = render_pass->quad_list.begin();
97         iter != render_pass->quad_list.end();
98         ++iter) {
99      iter->IterateResources(append_to_array);
100    }
101  }
102  resource_provider_->PrepareSendToParent(resources, &out_data.resource_list);
103}
104
105void DelegatingRenderer::SwapBuffers(const CompositorFrameMetadata& metadata) {
106  TRACE_EVENT0("cc,benchmark", "DelegatingRenderer::SwapBuffers");
107  CompositorFrame compositor_frame;
108  compositor_frame.metadata = metadata;
109  compositor_frame.delegated_frame_data = delegated_frame_data_.Pass();
110  output_surface_->SwapBuffers(&compositor_frame);
111}
112
113void DelegatingRenderer::ReceiveSwapBuffersAck(
114    const CompositorFrameAck& ack) {
115  resource_provider_->ReceiveReturnsFromParent(ack.resources);
116}
117
118void DelegatingRenderer::DidChangeVisibility() {
119  ContextProvider* context_provider = output_surface_->context_provider();
120  if (!visible()) {
121    TRACE_EVENT0("cc", "DelegatingRenderer::SetVisible dropping resources");
122    resource_provider_->ReleaseCachedData();
123    if (context_provider) {
124      context_provider->DeleteCachedResources();
125      context_provider->ContextGL()->Flush();
126    }
127  }
128  // We loop visibility to the GPU process, since that's what manages memory.
129  // That will allow it to feed us with memory allocations that we can act
130  // upon.
131  if (context_provider)
132    context_provider->ContextSupport()->SetSurfaceVisible(visible());
133}
134
135}  // namespace cc
136