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.
5 #include "cc/output/delegating_renderer.h"
11 #include "base/debug/trace_event.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "cc/output/compositor_frame_ack.h"
16 #include "cc/quads/checkerboard_draw_quad.h"
17 #include "cc/quads/debug_border_draw_quad.h"
18 #include "cc/quads/render_pass.h"
19 #include "cc/quads/render_pass_draw_quad.h"
20 #include "cc/quads/solid_color_draw_quad.h"
21 #include "cc/quads/texture_draw_quad.h"
22 #include "cc/quads/tile_draw_quad.h"
23 #include "cc/quads/yuv_video_draw_quad.h"
24 #include "cc/resources/resource_provider.h"
25 #include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
26 #include "third_party/khronos/GLES2/gl2ext.h"
28 using WebKit::WebGraphicsContext3D
;
32 scoped_ptr
<DelegatingRenderer
> DelegatingRenderer::Create(
33 RendererClient
* client
,
34 const LayerTreeSettings
* settings
,
35 OutputSurface
* output_surface
,
36 ResourceProvider
* resource_provider
) {
37 scoped_ptr
<DelegatingRenderer
> renderer(new DelegatingRenderer(
38 client
, settings
, output_surface
, resource_provider
));
39 if (!renderer
->Initialize())
40 return scoped_ptr
<DelegatingRenderer
>();
41 return renderer
.Pass();
44 DelegatingRenderer::DelegatingRenderer(RendererClient
* client
,
45 const LayerTreeSettings
* settings
,
46 OutputSurface
* output_surface
,
47 ResourceProvider
* resource_provider
)
48 : Renderer(client
, settings
),
49 output_surface_(output_surface
),
50 resource_provider_(resource_provider
),
52 DCHECK(resource_provider_
);
55 bool DelegatingRenderer::Initialize() {
56 capabilities_
.using_partial_swap
= false;
57 capabilities_
.max_texture_size
= resource_provider_
->max_texture_size();
58 capabilities_
.best_texture_format
= resource_provider_
->best_texture_format();
59 capabilities_
.allow_partial_texture_updates
= false;
60 capabilities_
.using_offscreen_context3d
= false;
62 if (!output_surface_
->context_provider()) {
63 // TODO(danakj): Make software compositing work.
67 WebGraphicsContext3D
* context3d
=
68 output_surface_
->context_provider()->Context3d();
70 if (!context3d
->makeContextCurrent())
73 const ContextProvider::Capabilities
& caps
=
74 output_surface_
->context_provider()->ContextCapabilities();
76 DCHECK(!caps
.iosurface
|| caps
.texture_rectangle
);
78 capabilities_
.using_set_visibility
= caps
.set_visibility
;
79 capabilities_
.using_egl_image
= caps
.egl_image_external
;
80 capabilities_
.using_map_image
= settings_
->use_map_image
&& caps
.map_image
;
85 DelegatingRenderer::~DelegatingRenderer() {}
87 const RendererCapabilities
& DelegatingRenderer::Capabilities() const {
91 bool DelegatingRenderer::CanReadPixels() const { return false; }
93 static ResourceProvider::ResourceId
AppendToArray(
94 ResourceProvider::ResourceIdArray
* array
,
95 ResourceProvider::ResourceId id
) {
100 void DelegatingRenderer::DrawFrame(RenderPassList
* render_passes_in_draw_order
,
101 ContextProvider
* offscreen_context_provider
,
102 float device_scale_factor
,
103 bool allow_partial_swap
,
104 bool disable_picture_quad_image_filtering
) {
105 TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame");
107 DCHECK(!frame_for_swap_buffers_
.delegated_frame_data
);
109 frame_for_swap_buffers_
.metadata
= client_
->MakeCompositorFrameMetadata();
111 frame_for_swap_buffers_
.delegated_frame_data
=
112 make_scoped_ptr(new DelegatedFrameData
);
113 DelegatedFrameData
& out_data
= *frame_for_swap_buffers_
.delegated_frame_data
;
114 // Move the render passes and resources into the |out_frame|.
115 out_data
.render_pass_list
.swap(*render_passes_in_draw_order
);
117 // Collect all resource ids in the render passes into a ResourceIdArray.
118 ResourceProvider::ResourceIdArray resources
;
119 DrawQuad::ResourceIteratorCallback append_to_array
=
120 base::Bind(&AppendToArray
, &resources
);
121 for (size_t i
= 0; i
< out_data
.render_pass_list
.size(); ++i
) {
122 RenderPass
* render_pass
= out_data
.render_pass_list
.at(i
);
123 for (size_t j
= 0; j
< render_pass
->quad_list
.size(); ++j
)
124 render_pass
->quad_list
[j
]->IterateResources(append_to_array
);
126 resource_provider_
->PrepareSendToParent(resources
, &out_data
.resource_list
);
129 void DelegatingRenderer::SwapBuffers() {
130 TRACE_EVENT0("cc", "DelegatingRenderer::SwapBuffers");
132 output_surface_
->SwapBuffers(&frame_for_swap_buffers_
);
133 frame_for_swap_buffers_
.delegated_frame_data
.reset();
136 void DelegatingRenderer::GetFramebufferPixels(void* pixels
, gfx::Rect rect
) {
140 void DelegatingRenderer::ReceiveSwapBuffersAck(
141 const CompositorFrameAck
& ack
) {
142 resource_provider_
->ReceiveReturnsFromParent(ack
.resources
);
145 bool DelegatingRenderer::IsContextLost() {
146 ContextProvider
* context_provider
= output_surface_
->context_provider();
147 if (!context_provider
)
149 return context_provider
->Context3d()->getGraphicsResetStatusARB() !=
153 void DelegatingRenderer::SetVisible(bool visible
) {
154 if (visible
== visible_
)
158 ContextProvider
* context_provider
= output_surface_
->context_provider();
160 TRACE_EVENT0("cc", "DelegatingRenderer::SetVisible dropping resources");
161 resource_provider_
->ReleaseCachedData();
162 if (context_provider
)
163 context_provider
->Context3d()->flush();
165 if (capabilities_
.using_set_visibility
) {
166 // We loop visibility to the GPU process, since that's what manages memory.
167 // That will allow it to feed us with memory allocations that we can act
169 DCHECK(context_provider
);
170 context_provider
->Context3d()->setVisibilityCHROMIUM(visible
);
174 void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible
,
175 size_t bytes_visible_and_nearby
,
176 size_t bytes_allocated
) {
177 ContextProvider
* context_provider
= output_surface_
->context_provider();
178 if (!context_provider
) {
179 // TODO(piman): software path.
183 WebKit::WebGraphicsManagedMemoryStats stats
;
184 stats
.bytesVisible
= bytes_visible
;
185 stats
.bytesVisibleAndNearby
= bytes_visible_and_nearby
;
186 stats
.bytesAllocated
= bytes_allocated
;
187 stats
.backbufferRequested
= false;
188 context_provider
->Context3d()->sendManagedMemoryStatsCHROMIUM(&stats
);
191 void DelegatingRenderer::SetDiscardBackBufferWhenNotVisible(bool discard
) {
192 // Nothing to do, we don't have a back buffer.