OLD | NEW |
| (Empty) |
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/delegating_renderer.h" | |
6 | |
7 #include <set> | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "base/debug/trace_event.h" | |
12 #include "base/string_util.h" | |
13 #include "base/strings/string_split.h" | |
14 #include "cc/checkerboard_draw_quad.h" | |
15 #include "cc/compositor_frame.h" | |
16 #include "cc/compositor_frame_ack.h" | |
17 #include "cc/debug_border_draw_quad.h" | |
18 #include "cc/render_pass.h" | |
19 #include "cc/render_pass_draw_quad.h" | |
20 #include "cc/resource_provider.h" | |
21 #include "cc/solid_color_draw_quad.h" | |
22 #include "cc/texture_draw_quad.h" | |
23 #include "cc/tile_draw_quad.h" | |
24 #include "cc/yuv_video_draw_quad.h" | |
25 #include "third_party/khronos/GLES2/gl2ext.h" | |
26 | |
27 using WebKit::WebGraphicsContext3D; | |
28 | |
29 namespace cc { | |
30 | |
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(); | |
40 } | |
41 | |
42 DelegatingRenderer::DelegatingRenderer( | |
43 RendererClient* client, | |
44 OutputSurface* output_surface, | |
45 ResourceProvider* resource_provider) | |
46 : Renderer(client), | |
47 output_surface_(output_surface), | |
48 resource_provider_(resource_provider), | |
49 visible_(true) { | |
50 DCHECK(resource_provider_); | |
51 } | |
52 | |
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; | |
62 | |
63 WebGraphicsContext3D* context3d = resource_provider_->GraphicsContext3D(); | |
64 | |
65 if (!context3d) { | |
66 // Software compositing. | |
67 return true; | |
68 } | |
69 | |
70 if (!context3d->makeContextCurrent()) | |
71 return false; | |
72 | |
73 context3d->setContextLostCallback(this); | |
74 context3d->pushGroupMarkerEXT("CompositorContext"); | |
75 | |
76 std::string extensionsString = | |
77 UTF16ToASCII(context3d->getString(GL_EXTENSIONS)); | |
78 | |
79 std::vector<std::string> extensions; | |
80 base::SplitString(extensionsString, ' ', &extensions); | |
81 | |
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 hasReadBGRA = true; | |
85 bool hasSetVisibility = true; | |
86 bool hasIOSurface = true; | |
87 bool hasARBTextureRect = true; | |
88 bool hasGpuMemoryManager = true; | |
89 bool hasEGLImage = true; | |
90 for (size_t i = 0; i < extensions.size(); ++i) { | |
91 if (extensions[i] == "GL_EXT_read_format_bgra") | |
92 hasReadBGRA = true; | |
93 else if (extensions[i] == "GL_CHROMIUM_set_visibility") | |
94 hasSetVisibility = true; | |
95 else if (extensions[i] == "GL_CHROMIUM_iosurface") | |
96 hasIOSurface = true; | |
97 else if (extensions[i] == "GL_ARB_texture_rectangle") | |
98 hasARBTextureRect = true; | |
99 else if (extensions[i] == "GL_CHROMIUM_gpu_memory_manager") | |
100 hasGpuMemoryManager = true; | |
101 else if (extensions[i] == "GL_OES_EGL_image_external") | |
102 hasEGLImage = true; | |
103 } | |
104 | |
105 if (hasIOSurface) | |
106 DCHECK(hasARBTextureRect); | |
107 | |
108 capabilities_.using_accelerated_painting = | |
109 Settings().acceleratePainting && | |
110 capabilities_.best_texture_format == GL_BGRA_EXT && | |
111 hasReadBGRA; | |
112 | |
113 // TODO(piman): loop visibility to GPU process? | |
114 capabilities_.using_set_visibility = hasSetVisibility; | |
115 | |
116 // TODO(danakj): Support GpuMemoryManager. | |
117 capabilities_.using_gpu_memory_manager = false; | |
118 | |
119 capabilities_.using_egl_image = hasEGLImage; | |
120 | |
121 return true; | |
122 } | |
123 | |
124 DelegatingRenderer::~DelegatingRenderer() { | |
125 WebGraphicsContext3D* context3d = resource_provider_->GraphicsContext3D(); | |
126 if (context3d) | |
127 context3d->setContextLostCallback(NULL); | |
128 } | |
129 | |
130 const RendererCapabilities& DelegatingRenderer::Capabilities() const { | |
131 return capabilities_; | |
132 } | |
133 | |
134 static ResourceProvider::ResourceId AppendToArray( | |
135 ResourceProvider::ResourceIdArray* array, | |
136 ResourceProvider::ResourceId id) { | |
137 array->push_back(id); | |
138 return id; | |
139 } | |
140 | |
141 void DelegatingRenderer::DrawFrame( | |
142 RenderPassList& render_passes_in_draw_order) { | |
143 TRACE_EVENT0("cc", "DelegatingRenderer::drawFrame"); | |
144 | |
145 CompositorFrame out_frame; | |
146 out_frame.metadata = client_->MakeCompositorFrameMetadata(); | |
147 | |
148 out_frame.delegated_frame_data = make_scoped_ptr(new DelegatedFrameData); | |
149 | |
150 // Collect all resource ids in the render passes into a ResourceIdArray. | |
151 ResourceProvider::ResourceIdArray resources; | |
152 DrawQuad::ResourceIteratorCallback append_to_array = | |
153 base::Bind(&AppendToArray, &resources); | |
154 for (size_t i = 0; i < render_passes_in_draw_order.size(); ++i) { | |
155 RenderPass* render_pass = render_passes_in_draw_order[i]; | |
156 for (size_t j = 0; j < render_pass->quad_list.size(); ++j) | |
157 render_pass->quad_list[j]->IterateResources(append_to_array); | |
158 } | |
159 | |
160 // Move the render passes and resources into the |out_frame|. | |
161 DelegatedFrameData& out_data = *out_frame.delegated_frame_data; | |
162 out_data.render_pass_list.swap(render_passes_in_draw_order); | |
163 resource_provider_->PrepareSendToParent(resources, &out_data.resource_list); | |
164 | |
165 output_surface_->SendFrameToParentCompositor(&out_frame); | |
166 } | |
167 | |
168 bool DelegatingRenderer::SwapBuffers() { | |
169 return true; | |
170 } | |
171 | |
172 void DelegatingRenderer::GetFramebufferPixels(void* pixels, gfx::Rect rect) { | |
173 NOTIMPLEMENTED(); | |
174 } | |
175 | |
176 void DelegatingRenderer::ReceiveCompositorFrameAck( | |
177 const CompositorFrameAck& ack) { | |
178 resource_provider_->ReceiveFromParent(ack.resources); | |
179 if (client_->HasImplThread()) | |
180 client_->OnSwapBuffersComplete(); | |
181 } | |
182 | |
183 | |
184 bool DelegatingRenderer::IsContextLost() { | |
185 WebGraphicsContext3D* context3d = resource_provider_->GraphicsContext3D(); | |
186 if (!context3d) | |
187 return false; | |
188 return context3d->getGraphicsResetStatusARB() != GL_NO_ERROR; | |
189 } | |
190 | |
191 void DelegatingRenderer::SetVisible(bool visible) { | |
192 visible_ = visible; | |
193 } | |
194 | |
195 void DelegatingRenderer::onContextLost() { | |
196 client_->DidLoseOutputSurface(); | |
197 } | |
198 | |
199 } // namespace cc | |
OLD | NEW |