Chromium Code Reviews| 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 |