OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/compositor/gpu_browser_compositor_output_surface.h" | 5 #include "content/browser/compositor/gpu_browser_compositor_output_surface.h" |
6 | 6 |
7 #include "cc/output/compositor_frame.h" | 7 #include "cc/output/compositor_frame.h" |
8 #include "content/browser/compositor/reflector_impl.h" | 8 #include "content/browser/compositor/reflector_impl.h" |
9 #include "content/browser/gpu/gpu_surface_tracker.h" | |
9 #include "content/common/gpu/client/context_provider_command_buffer.h" | 10 #include "content/common/gpu/client/context_provider_command_buffer.h" |
11 #include "gpu/GLES2/gl2extchromium.h" | |
10 #include "gpu/command_buffer/client/gles2_interface.h" | 12 #include "gpu/command_buffer/client/gles2_interface.h" |
11 | 13 |
12 namespace content { | 14 namespace content { |
13 | 15 |
14 GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface( | 16 GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface( |
15 const scoped_refptr<ContextProviderCommandBuffer>& context, | 17 const scoped_refptr<ContextProviderCommandBuffer>& context, |
16 int surface_id, | 18 int surface_id, |
17 IDMap<BrowserCompositorOutputSurface>* output_surface_map, | 19 IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
18 const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager, | 20 const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager, |
19 scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator) | 21 scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator) |
(...skipping 22 matching lines...) Expand all Loading... | |
42 if (frame->gl_frame_data->sub_buffer_rect == | 44 if (frame->gl_frame_data->sub_buffer_rect == |
43 gfx::Rect(frame->gl_frame_data->size)) | 45 gfx::Rect(frame->gl_frame_data->size)) |
44 reflector_->OnSwapBuffers(); | 46 reflector_->OnSwapBuffers(); |
45 else | 47 else |
46 reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect); | 48 reflector_->OnPostSubBuffer(frame->gl_frame_data->sub_buffer_rect); |
47 } | 49 } |
48 | 50 |
49 OutputSurface::SwapBuffers(frame); | 51 OutputSurface::SwapBuffers(frame); |
50 } | 52 } |
51 | 53 |
54 GpuSurfacelessBrowserCompositorOutputSurface:: | |
55 GpuSurfacelessBrowserCompositorOutputSurface( | |
56 const scoped_refptr<ContextProviderCommandBuffer>& context, | |
57 int surface_id, | |
58 IDMap<BrowserCompositorOutputSurface>* output_surface_map, | |
59 const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager, | |
60 scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator, | |
61 unsigned internalformat, | |
62 int z_order) | |
alexst (slow to review)
2014/09/02 13:15:59
I see primary surface as always being 0, others ca
achaulk
2014/09/02 17:48:44
I just made this configurable so that if someone d
| |
63 : GpuBrowserCompositorOutputSurface(context, | |
64 surface_id, | |
65 output_surface_map, | |
66 vsync_manager, | |
67 overlay_candidate_validator.Pass()), | |
68 z_order_(z_order), | |
69 expects_pageflip_messages_(false), | |
alexst (slow to review)
2014/09/02 13:15:59
Please provide a way to change this.
achaulk
2014/09/02 17:48:44
That will be when the IPC gets integrated
| |
70 internalformat_(internalformat) { | |
71 } | |
72 | |
73 GpuSurfacelessBrowserCompositorOutputSurface:: | |
74 ~GpuSurfacelessBrowserCompositorOutputSurface() { | |
75 } | |
76 | |
77 void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers( | |
78 cc::CompositorFrame* frame) { | |
79 DCHECK(output_surface_); | |
80 output_surface_->SwapBuffers(); | |
81 | |
82 const gfx::Rect& rect = frame->gl_frame_data->sub_buffer_rect; | |
alexst (slow to review)
2014/09/02 13:15:59
sub_buffer_rect provides a dirty region, if I am n
achaulk
2014/09/02 17:48:44
Sure. I'm not sure how we can really do partial up
| |
83 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
84 gl->Finish(); | |
85 gl->ScheduleOverlayPlaneCHROMIUM(z_order_, | |
86 GL_OVERLAY_TRANSFORM_NONE_CHROMIUM, | |
87 output_surface_->tex_id(), | |
88 rect.x(), | |
89 rect.y(), | |
90 rect.width(), | |
91 rect.height(), | |
92 0, | |
93 0, | |
94 1.0f, | |
95 1.0f); | |
96 GpuBrowserCompositorOutputSurface::SwapBuffers(frame); | |
97 } | |
98 | |
99 void GpuSurfacelessBrowserCompositorOutputSurface::OnSwapBuffersComplete() { | |
100 DCHECK(output_surface_); | |
101 // PageFlipComplete must be called to properly drive the buffering. If we | |
102 // don't expect to receive these calls from IPCs, we should call it here. | |
103 if (!expects_pageflip_messages_) | |
104 output_surface_->PageFlipComplete(); | |
105 GpuBrowserCompositorOutputSurface::OnSwapBuffersComplete(); | |
106 } | |
107 | |
108 void GpuSurfacelessBrowserCompositorOutputSurface::BindFramebuffer() { | |
109 DCHECK(output_surface_); | |
110 output_surface_->BindFramebuffer(); | |
111 } | |
112 | |
113 void GpuSurfacelessBrowserCompositorOutputSurface::Reshape( | |
114 const gfx::Size& size, | |
115 float scale_factor) { | |
116 gfx::Size current = SurfaceSize(); | |
117 GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor); | |
118 DCHECK(output_surface_); | |
119 output_surface_->Reshape(SurfaceSize(), scale_factor); | |
120 } | |
121 | |
122 bool GpuSurfacelessBrowserCompositorOutputSurface::BindToClient( | |
123 cc::OutputSurfaceClient* client) { | |
124 DCHECK(output_surface_); | |
125 if (!GpuBrowserCompositorOutputSurface::BindToClient(client)) | |
126 return false; | |
127 if (!output_surface_) { | |
128 output_surface_.reset( | |
129 new BufferedOutputSurface(context_provider_, internalformat_)); | |
130 } | |
131 return true; | |
132 } | |
133 | |
134 BufferedOutputSurface::BufferedOutputSurface( | |
135 scoped_refptr<cc::ContextProvider> context_provider, | |
136 unsigned int internalformat) | |
137 : context_provider_(context_provider), | |
138 fbo_(0), | |
139 depth_rb_(0), | |
140 tex_id_(0), | |
141 internalformat_(internalformat), | |
142 current_surface_(0), | |
143 last_surface_(0), | |
144 available_surface_(0), | |
145 in_flight_surface_(0) { | |
146 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
alexst (slow to review)
2014/09/02 13:15:59
Please split all the GL code from the constructor
achaulk
2014/09/02 17:48:44
Done.
| |
147 gl->GenFramebuffers(1, &fbo_); | |
148 gl->GenRenderbuffers(1, &depth_rb_); | |
149 gl->GenTextures(1, &tex_id_); | |
150 DCHECK(fbo_); | |
151 DCHECK(depth_rb_); | |
152 DCHECK(tex_id_); | |
153 } | |
154 | |
155 BufferedOutputSurface::~BufferedOutputSurface() { | |
156 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
157 if (fbo_) | |
158 gl->DeleteFramebuffers(1, &fbo_); | |
159 if (depth_rb_) | |
160 gl->DeleteRenderbuffers(1, &depth_rb_); | |
161 if (tex_id_) | |
162 gl->DeleteTextures(1, &tex_id_); | |
163 FreeAllSurfaces(); | |
164 } | |
165 | |
166 void BufferedOutputSurface::BindFramebuffer() { | |
167 if (!current_surface_) | |
168 current_surface_ = GetNextSurface(); | |
169 | |
170 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
171 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | |
172 gl->BindTexture(GL_TEXTURE_2D, tex_id_); | |
173 gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, current_surface_); | |
174 gl->FramebufferTexture2D( | |
175 GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id_, 0); | |
176 } | |
177 | |
178 void BufferedOutputSurface::SwapBuffers() { | |
179 if (last_surface_) { | |
180 if (in_flight_surface_) | |
181 context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); | |
182 else | |
183 in_flight_surface_ = last_surface_; | |
184 } | |
185 last_surface_ = current_surface_; | |
186 current_surface_ = 0; | |
187 } | |
188 | |
189 void BufferedOutputSurface::Reshape(const gfx::Size& size, float scale_factor) { | |
190 if (size == size_) | |
191 return; | |
192 size_ = size; | |
193 FreeAllSurfaces(); | |
194 | |
195 if (size_.width() == 0 || size_.height() == 0) | |
196 return; // Nothing to do. | |
197 gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); | |
198 gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); | |
199 gl->BindRenderbuffer(GL_RENDERBUFFER, depth_rb_); | |
200 gl->RenderbufferStorage( | |
201 GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, size_.width(), size_.height()); | |
202 gl->FramebufferRenderbuffer( | |
203 GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb_); | |
204 } | |
205 | |
206 void BufferedOutputSurface::PageFlipComplete() { | |
207 if (!available_surface_) | |
208 available_surface_ = in_flight_surface_; | |
209 else | |
210 context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); | |
211 in_flight_surface_ = 0; | |
212 } | |
213 | |
214 void BufferedOutputSurface::FreeAllSurfaces() { | |
215 FreeSurface(&in_flight_surface_); | |
216 FreeSurface(&available_surface_); | |
217 FreeSurface(&last_surface_); | |
218 FreeSurface(¤t_surface_); | |
219 } | |
220 | |
221 void BufferedOutputSurface::FreeSurface(unsigned int* surface) { | |
222 if (*surface) { | |
223 context_provider_->ContextGL()->DestroyImageCHROMIUM(*surface); | |
224 *surface = 0; | |
225 } | |
226 } | |
227 | |
228 unsigned int BufferedOutputSurface::GetNextSurface() { | |
229 if (available_surface_) { | |
230 unsigned int id = available_surface_; | |
231 available_surface_ = 0; | |
232 return id; | |
233 } | |
234 | |
235 unsigned int id = context_provider_->ContextGL()->CreateImageCHROMIUM( | |
alexst (slow to review)
2014/09/02 13:15:59
Allocating these involves a sync IPC, and I would
achaulk
2014/09/02 17:48:44
I can make it keep the third buffer around instead
| |
236 size_.width(), | |
237 size_.height(), | |
238 internalformat_, | |
239 GL_IMAGE_SCANOUT_CHROMIUM); | |
240 DCHECK(id); | |
241 return id; | |
242 } | |
243 | |
52 } // namespace content | 244 } // namespace content |
OLD | NEW |