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/string_util.h"
13 #include "base/strings/string_split.h"
14 #include "cc/output/compositor_frame.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/khronos/GLES2/gl2ext.h"
27 using WebKit::WebGraphicsContext3D
;
31 scoped_ptr
<DelegatingRenderer
> DelegatingRenderer::Create(
32 RendererClient
* client
,
33 OutputSurface
* output_surface
,
34 ResourceProvider
* resource_provider
) {
35 scoped_ptr
<DelegatingRenderer
> renderer(
36 new DelegatingRenderer(client
, output_surface
, resource_provider
));
37 if (!renderer
->Initialize())
38 return scoped_ptr
<DelegatingRenderer
>();
39 return renderer
.Pass();
42 DelegatingRenderer::DelegatingRenderer(
43 RendererClient
* client
,
44 OutputSurface
* output_surface
,
45 ResourceProvider
* resource_provider
)
47 output_surface_(output_surface
),
48 resource_provider_(resource_provider
),
50 DCHECK(resource_provider_
);
53 bool DelegatingRenderer::Initialize() {
54 capabilities_
.using_partial_swap
= false;
55 // TODO(danakj): Throttling - we may want to only allow 1 outstanding frame,
56 // but the parent compositor may pipeline for us.
57 // TODO(danakj): Can we use this in single-thread mode?
58 capabilities_
.using_swap_complete_callback
= true;
59 capabilities_
.max_texture_size
= resource_provider_
->max_texture_size();
60 capabilities_
.best_texture_format
= resource_provider_
->best_texture_format();
61 capabilities_
.allow_partial_texture_updates
= false;
63 WebGraphicsContext3D
* context3d
= resource_provider_
->GraphicsContext3D();
66 // Software compositing.
70 if (!context3d
->makeContextCurrent())
73 context3d
->setContextLostCallback(this);
74 context3d
->pushGroupMarkerEXT("CompositorContext");
76 std::string extensions_string
=
77 UTF16ToASCII(context3d
->getString(GL_EXTENSIONS
));
79 std::vector
<std::string
> extensions
;
80 base::SplitString(extensions_string
, ' ', &extensions
);
82 // TODO(danakj): We need non-GPU-specific paths for these things. This
83 // renderer shouldn't need to use context3d extensions directly.
84 bool has_read_bgra
= true;
85 bool has_set_visibility
= true;
86 bool has_io_surface
= true;
87 bool has_arb_texture_rect
= true;
88 bool has_egl_image
= true;
89 for (size_t i
= 0; i
< extensions
.size(); ++i
) {
90 if (extensions
[i
] == "GL_EXT_read_format_bgra")
92 else if (extensions
[i
] == "GL_CHROMIUM_set_visibility")
93 has_set_visibility
= true;
94 else if (extensions
[i
] == "GL_CHROMIUM_iosurface")
95 has_io_surface
= true;
96 else if (extensions
[i
] == "GL_ARB_texture_rectangle")
97 has_arb_texture_rect
= true;
98 else if (extensions
[i
] == "GL_OES_EGL_image_external")
103 DCHECK(has_arb_texture_rect
);
105 capabilities_
.using_accelerated_painting
=
106 Settings().accelerate_painting
&&
107 capabilities_
.best_texture_format
== GL_BGRA_EXT
&&
110 // TODO(piman): loop visibility to GPU process?
111 capabilities_
.using_set_visibility
= has_set_visibility
;
113 // TODO(danakj): Support GpuMemoryManager.
114 capabilities_
.using_gpu_memory_manager
= false;
116 capabilities_
.using_egl_image
= has_egl_image
;
121 DelegatingRenderer::~DelegatingRenderer() {
122 WebGraphicsContext3D
* context3d
= resource_provider_
->GraphicsContext3D();
124 context3d
->setContextLostCallback(NULL
);
127 const RendererCapabilities
& DelegatingRenderer::Capabilities() const {
128 return capabilities_
;
131 static ResourceProvider::ResourceId
AppendToArray(
132 ResourceProvider::ResourceIdArray
* array
,
133 ResourceProvider::ResourceId id
) {
134 array
->push_back(id
);
138 void DelegatingRenderer::DrawFrame(
139 RenderPassList
* render_passes_in_draw_order
) {
140 TRACE_EVENT0("cc", "DelegatingRenderer::DrawFrame");
142 CompositorFrame out_frame
;
143 out_frame
.metadata
= client_
->MakeCompositorFrameMetadata();
145 out_frame
.delegated_frame_data
= make_scoped_ptr(new DelegatedFrameData
);
147 // Collect all resource ids in the render passes into a ResourceIdArray.
148 ResourceProvider::ResourceIdArray resources
;
149 DrawQuad::ResourceIteratorCallback append_to_array
=
150 base::Bind(&AppendToArray
, &resources
);
151 for (size_t i
= 0; i
< render_passes_in_draw_order
->size(); ++i
) {
152 RenderPass
* render_pass
= render_passes_in_draw_order
->at(i
);
153 for (size_t j
= 0; j
< render_pass
->quad_list
.size(); ++j
)
154 render_pass
->quad_list
[j
]->IterateResources(append_to_array
);
157 // Move the render passes and resources into the |out_frame|.
158 DelegatedFrameData
& out_data
= *out_frame
.delegated_frame_data
;
159 out_data
.render_pass_list
.swap(*render_passes_in_draw_order
);
160 resource_provider_
->PrepareSendToParent(resources
, &out_data
.resource_list
);
162 output_surface_
->SendFrameToParentCompositor(&out_frame
);
165 bool DelegatingRenderer::SwapBuffers() {
169 void DelegatingRenderer::GetFramebufferPixels(void* pixels
, gfx::Rect rect
) {
173 void DelegatingRenderer::ReceiveCompositorFrameAck(
174 const CompositorFrameAck
& ack
) {
175 resource_provider_
->ReceiveFromParent(ack
.resources
);
176 if (client_
->HasImplThread())
177 client_
->OnSwapBuffersComplete();
181 bool DelegatingRenderer::IsContextLost() {
182 WebGraphicsContext3D
* context3d
= resource_provider_
->GraphicsContext3D();
185 return context3d
->getGraphicsResetStatusARB() != GL_NO_ERROR
;
188 void DelegatingRenderer::SetVisible(bool visible
) {
192 void DelegatingRenderer::onContextLost() {
193 client_
->DidLoseOutputSurface();