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 OutputSurface
* output_surface
,
35 ResourceProvider
* resource_provider
) {
36 scoped_ptr
<DelegatingRenderer
> renderer(
37 new DelegatingRenderer(client
, output_surface
, resource_provider
));
38 if (!renderer
->Initialize())
39 return scoped_ptr
<DelegatingRenderer
>();
40 return renderer
.Pass();
43 DelegatingRenderer::DelegatingRenderer(
44 RendererClient
* client
,
45 OutputSurface
* output_surface
,
46 ResourceProvider
* resource_provider
)
48 output_surface_(output_surface
),
49 resource_provider_(resource_provider
),
51 DCHECK(resource_provider_
);
54 bool DelegatingRenderer::Initialize() {
55 capabilities_
.using_partial_swap
= false;
56 capabilities_
.max_texture_size
= resource_provider_
->max_texture_size();
57 capabilities_
.best_texture_format
= resource_provider_
->best_texture_format();
58 capabilities_
.allow_partial_texture_updates
= false;
59 capabilities_
.using_offscreen_context3d
= false;
61 WebGraphicsContext3D
* context3d
= resource_provider_
->GraphicsContext3D();
64 // Software compositing.
68 if (!context3d
->makeContextCurrent())
71 std::string unique_context_name
= base::StringPrintf(
73 Settings().compositor_name
.c_str(),
75 context3d
->pushGroupMarkerEXT(unique_context_name
.c_str());
77 std::string extensions_string
=
78 UTF16ToASCII(context3d
->getString(GL_EXTENSIONS
));
80 std::vector
<std::string
> extensions
;
81 base::SplitString(extensions_string
, ' ', &extensions
);
83 // TODO(danakj): We need non-GPU-specific paths for these things. This
84 // renderer shouldn't need to use context3d extensions directly.
85 bool has_set_visibility
= false;
86 bool has_io_surface
= false;
87 bool has_arb_texture_rect
= false;
88 bool has_egl_image
= false;
89 bool has_map_image
= false;
90 for (size_t i
= 0; i
< extensions
.size(); ++i
) {
91 if (extensions
[i
] == "GL_CHROMIUM_set_visibility") {
92 has_set_visibility
= true;
93 } else if (extensions
[i
] == "GL_CHROMIUM_iosurface") {
94 has_io_surface
= true;
95 } else if (extensions
[i
] == "GL_ARB_texture_rectangle") {
96 has_arb_texture_rect
= true;
97 } else if (extensions
[i
] == "GL_OES_EGL_image_external") {
99 } else if (extensions
[i
] == "GL_CHROMIUM_map_image") {
100 has_map_image
= true;
105 DCHECK(has_arb_texture_rect
);
107 capabilities_
.using_set_visibility
= has_set_visibility
;
109 capabilities_
.using_egl_image
= has_egl_image
;
111 capabilities_
.using_map_image
= has_map_image
;
116 DelegatingRenderer::~DelegatingRenderer() {}
118 const RendererCapabilities
& DelegatingRenderer::Capabilities() const {
119 return capabilities_
;
122 bool DelegatingRenderer::CanReadPixels() const { return false; }
124 static ResourceProvider::ResourceId
AppendToArray(
125 ResourceProvider::ResourceIdArray
* array
,
126 ResourceProvider::ResourceId id
) {
127 array
->push_back(id
);
131 void DelegatingRenderer::DrawFrame(
132 RenderPassList
* render_passes_in_draw_order
) {
133 TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame");
135 DCHECK(!frame_for_swap_buffers_
.delegated_frame_data
);
137 frame_for_swap_buffers_
.metadata
= client_
->MakeCompositorFrameMetadata();
139 frame_for_swap_buffers_
.delegated_frame_data
=
140 make_scoped_ptr(new DelegatedFrameData
);
141 DelegatedFrameData
& out_data
= *frame_for_swap_buffers_
.delegated_frame_data
;
142 // Move the render passes and resources into the |out_frame|.
143 out_data
.render_pass_list
.swap(*render_passes_in_draw_order
);
145 // Collect all resource ids in the render passes into a ResourceIdArray.
146 ResourceProvider::ResourceIdArray resources
;
147 DrawQuad::ResourceIteratorCallback append_to_array
=
148 base::Bind(&AppendToArray
, &resources
);
149 for (size_t i
= 0; i
< out_data
.render_pass_list
.size(); ++i
) {
150 RenderPass
* render_pass
= out_data
.render_pass_list
.at(i
);
151 for (size_t j
= 0; j
< render_pass
->quad_list
.size(); ++j
)
152 render_pass
->quad_list
[j
]->IterateResources(append_to_array
);
154 resource_provider_
->PrepareSendToParent(resources
, &out_data
.resource_list
);
157 void DelegatingRenderer::SwapBuffers() {
158 TRACE_EVENT0("cc", "DelegatingRenderer::SwapBuffers");
160 output_surface_
->SwapBuffers(&frame_for_swap_buffers_
);
161 frame_for_swap_buffers_
.delegated_frame_data
.reset();
164 void DelegatingRenderer::GetFramebufferPixels(void* pixels
, gfx::Rect rect
) {
168 void DelegatingRenderer::ReceiveSwapBuffersAck(
169 const CompositorFrameAck
& ack
) {
170 resource_provider_
->ReceiveFromParent(ack
.resources
);
173 bool DelegatingRenderer::IsContextLost() {
174 WebGraphicsContext3D
* context3d
= resource_provider_
->GraphicsContext3D();
177 return context3d
->getGraphicsResetStatusARB() != GL_NO_ERROR
;
180 void DelegatingRenderer::SetVisible(bool visible
) {
181 if (visible
== visible_
)
185 WebGraphicsContext3D
* context
= resource_provider_
->GraphicsContext3D();
187 TRACE_EVENT0("cc", "DelegatingRenderer::SetVisible dropping resources");
188 resource_provider_
->ReleaseCachedData();
192 if (capabilities_
.using_set_visibility
) {
193 // We loop visibility to the GPU process, since that's what manages memory.
194 // That will allow it to feed us with memory allocations that we can act
197 context
->setVisibilityCHROMIUM(visible
);
201 void DelegatingRenderer::SendManagedMemoryStats(size_t bytes_visible
,
202 size_t bytes_visible_and_nearby
,
203 size_t bytes_allocated
) {
204 WebGraphicsContext3D
* context
= resource_provider_
->GraphicsContext3D();
206 // TODO(piman): software path.
210 WebKit::WebGraphicsManagedMemoryStats stats
;
211 stats
.bytesVisible
= bytes_visible
;
212 stats
.bytesVisibleAndNearby
= bytes_visible_and_nearby
;
213 stats
.bytesAllocated
= bytes_allocated
;
214 stats
.backbufferRequested
= false;
215 context
->sendManagedMemoryStatsCHROMIUM(&stats
);
218 void DelegatingRenderer::SetDiscardBackBufferWhenNotVisible(bool discard
) {
219 // Nothing to do, we don't have a back buffer.