Chromium Code Reviews| Index: content/browser/compositor/gpu_browser_compositor_output_surface.cc |
| diff --git a/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/content/browser/compositor/gpu_browser_compositor_output_surface.cc |
| index 3b79d546d4272f4c8608f441e81879faf3d86ed8..054d1a63e00bd12099fcce0622042e1f4a54fe89 100644 |
| --- a/content/browser/compositor/gpu_browser_compositor_output_surface.cc |
| +++ b/content/browser/compositor/gpu_browser_compositor_output_surface.cc |
| @@ -6,7 +6,9 @@ |
| #include "cc/output/compositor_frame.h" |
| #include "content/browser/compositor/reflector_impl.h" |
| +#include "content/browser/gpu/gpu_surface_tracker.h" |
| #include "content/common/gpu/client/context_provider_command_buffer.h" |
| +#include "gpu/GLES2/gl2extchromium.h" |
| #include "gpu/command_buffer/client/gles2_interface.h" |
| namespace content { |
| @@ -49,4 +51,194 @@ void GpuBrowserCompositorOutputSurface::SwapBuffers( |
| OutputSurface::SwapBuffers(frame); |
| } |
| +GpuSurfacelessBrowserCompositorOutputSurface:: |
| + GpuSurfacelessBrowserCompositorOutputSurface( |
| + const scoped_refptr<ContextProviderCommandBuffer>& context, |
| + int surface_id, |
| + IDMap<BrowserCompositorOutputSurface>* output_surface_map, |
| + const scoped_refptr<ui::CompositorVSyncManager>& vsync_manager, |
| + scoped_ptr<cc::OverlayCandidateValidator> overlay_candidate_validator, |
| + unsigned internalformat, |
| + 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
|
| + : GpuBrowserCompositorOutputSurface(context, |
| + surface_id, |
| + output_surface_map, |
| + vsync_manager, |
| + overlay_candidate_validator.Pass()), |
| + z_order_(z_order), |
| + 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
|
| + internalformat_(internalformat) { |
| +} |
| + |
| +GpuSurfacelessBrowserCompositorOutputSurface:: |
| + ~GpuSurfacelessBrowserCompositorOutputSurface() { |
| +} |
| + |
| +void GpuSurfacelessBrowserCompositorOutputSurface::SwapBuffers( |
| + cc::CompositorFrame* frame) { |
| + DCHECK(output_surface_); |
| + output_surface_->SwapBuffers(); |
| + |
| + 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
|
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->Finish(); |
| + gl->ScheduleOverlayPlaneCHROMIUM(z_order_, |
| + GL_OVERLAY_TRANSFORM_NONE_CHROMIUM, |
| + output_surface_->tex_id(), |
| + rect.x(), |
| + rect.y(), |
| + rect.width(), |
| + rect.height(), |
| + 0, |
| + 0, |
| + 1.0f, |
| + 1.0f); |
| + GpuBrowserCompositorOutputSurface::SwapBuffers(frame); |
| +} |
| + |
| +void GpuSurfacelessBrowserCompositorOutputSurface::OnSwapBuffersComplete() { |
| + DCHECK(output_surface_); |
| + // PageFlipComplete must be called to properly drive the buffering. If we |
| + // don't expect to receive these calls from IPCs, we should call it here. |
| + if (!expects_pageflip_messages_) |
| + output_surface_->PageFlipComplete(); |
| + GpuBrowserCompositorOutputSurface::OnSwapBuffersComplete(); |
| +} |
| + |
| +void GpuSurfacelessBrowserCompositorOutputSurface::BindFramebuffer() { |
| + DCHECK(output_surface_); |
| + output_surface_->BindFramebuffer(); |
| +} |
| + |
| +void GpuSurfacelessBrowserCompositorOutputSurface::Reshape( |
| + const gfx::Size& size, |
| + float scale_factor) { |
| + gfx::Size current = SurfaceSize(); |
| + GpuBrowserCompositorOutputSurface::Reshape(size, scale_factor); |
| + DCHECK(output_surface_); |
| + output_surface_->Reshape(SurfaceSize(), scale_factor); |
| +} |
| + |
| +bool GpuSurfacelessBrowserCompositorOutputSurface::BindToClient( |
| + cc::OutputSurfaceClient* client) { |
| + DCHECK(output_surface_); |
| + if (!GpuBrowserCompositorOutputSurface::BindToClient(client)) |
| + return false; |
| + if (!output_surface_) { |
| + output_surface_.reset( |
| + new BufferedOutputSurface(context_provider_, internalformat_)); |
| + } |
| + return true; |
| +} |
| + |
| +BufferedOutputSurface::BufferedOutputSurface( |
| + scoped_refptr<cc::ContextProvider> context_provider, |
| + unsigned int internalformat) |
| + : context_provider_(context_provider), |
| + fbo_(0), |
| + depth_rb_(0), |
| + tex_id_(0), |
| + internalformat_(internalformat), |
| + current_surface_(0), |
| + last_surface_(0), |
| + available_surface_(0), |
| + in_flight_surface_(0) { |
| + 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.
|
| + gl->GenFramebuffers(1, &fbo_); |
| + gl->GenRenderbuffers(1, &depth_rb_); |
| + gl->GenTextures(1, &tex_id_); |
| + DCHECK(fbo_); |
| + DCHECK(depth_rb_); |
| + DCHECK(tex_id_); |
| +} |
| + |
| +BufferedOutputSurface::~BufferedOutputSurface() { |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + if (fbo_) |
| + gl->DeleteFramebuffers(1, &fbo_); |
| + if (depth_rb_) |
| + gl->DeleteRenderbuffers(1, &depth_rb_); |
| + if (tex_id_) |
| + gl->DeleteTextures(1, &tex_id_); |
| + FreeAllSurfaces(); |
| +} |
| + |
| +void BufferedOutputSurface::BindFramebuffer() { |
| + if (!current_surface_) |
| + current_surface_ = GetNextSurface(); |
| + |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + gl->BindTexture(GL_TEXTURE_2D, tex_id_); |
| + gl->BindTexImage2DCHROMIUM(GL_TEXTURE_2D, current_surface_); |
| + gl->FramebufferTexture2D( |
| + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex_id_, 0); |
| +} |
| + |
| +void BufferedOutputSurface::SwapBuffers() { |
| + if (last_surface_) { |
| + if (in_flight_surface_) |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); |
| + else |
| + in_flight_surface_ = last_surface_; |
| + } |
| + last_surface_ = current_surface_; |
| + current_surface_ = 0; |
| +} |
| + |
| +void BufferedOutputSurface::Reshape(const gfx::Size& size, float scale_factor) { |
| + if (size == size_) |
| + return; |
| + size_ = size; |
| + FreeAllSurfaces(); |
| + |
| + if (size_.width() == 0 || size_.height() == 0) |
| + return; // Nothing to do. |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + gl->BindFramebuffer(GL_FRAMEBUFFER, fbo_); |
| + gl->BindRenderbuffer(GL_RENDERBUFFER, depth_rb_); |
| + gl->RenderbufferStorage( |
| + GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, size_.width(), size_.height()); |
| + gl->FramebufferRenderbuffer( |
| + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_rb_); |
| +} |
| + |
| +void BufferedOutputSurface::PageFlipComplete() { |
| + if (!available_surface_) |
| + available_surface_ = in_flight_surface_; |
| + else |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(in_flight_surface_); |
| + in_flight_surface_ = 0; |
| +} |
| + |
| +void BufferedOutputSurface::FreeAllSurfaces() { |
| + FreeSurface(&in_flight_surface_); |
| + FreeSurface(&available_surface_); |
| + FreeSurface(&last_surface_); |
| + FreeSurface(¤t_surface_); |
| +} |
| + |
| +void BufferedOutputSurface::FreeSurface(unsigned int* surface) { |
| + if (*surface) { |
| + context_provider_->ContextGL()->DestroyImageCHROMIUM(*surface); |
| + *surface = 0; |
| + } |
| +} |
| + |
| +unsigned int BufferedOutputSurface::GetNextSurface() { |
| + if (available_surface_) { |
| + unsigned int id = available_surface_; |
| + available_surface_ = 0; |
| + return id; |
| + } |
| + |
| + 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
|
| + size_.width(), |
| + size_.height(), |
| + internalformat_, |
| + GL_IMAGE_SCANOUT_CHROMIUM); |
| + DCHECK(id); |
| + return id; |
| +} |
| + |
| } // namespace content |