| Index: content/common/gpu/image_transport_surface_fbo_mac.mm
|
| diff --git a/content/common/gpu/image_transport_surface_fbo_mac.mm b/content/common/gpu/image_transport_surface_fbo_mac.mm
|
| deleted file mode 100644
|
| index 3b6aa0fb8332b08d6838c83d64df0a5c6b6a8738..0000000000000000000000000000000000000000
|
| --- a/content/common/gpu/image_transport_surface_fbo_mac.mm
|
| +++ /dev/null
|
| @@ -1,441 +0,0 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/common/gpu/image_transport_surface_fbo_mac.h"
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/trace_event/trace_event.h"
|
| -#include "content/common/gpu/gpu_messages.h"
|
| -#include "content/common/gpu/image_transport_surface_calayer_mac.h"
|
| -#include "content/common/gpu/image_transport_surface_iosurface_mac.h"
|
| -#include "content/common/gpu/image_transport_surface_overlay_mac.h"
|
| -#include "ui/base/cocoa/remote_layer_api.h"
|
| -#include "ui/base/ui_base_switches.h"
|
| -#include "ui/gfx/native_widget_types.h"
|
| -#include "ui/gl/gl_context.h"
|
| -#include "ui/gl/gl_implementation.h"
|
| -#include "ui/gl/gl_surface_osmesa.h"
|
| -
|
| -namespace content {
|
| -
|
| -scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
|
| - GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub,
|
| - gfx::PluginWindowHandle handle) {
|
| - // Overlays should be used unless the remote layer API isn't present (they
|
| - // depend on it) or it is disabled at the command line.
|
| - static bool overlays_disabled_at_command_line =
|
| - base::CommandLine::ForCurrentProcess()->HasSwitch(
|
| - switches::kDisableMacOverlays);
|
| - if (ui::RemoteLayerAPISupported() && !overlays_disabled_at_command_line)
|
| - return new ImageTransportSurfaceOverlayMac(manager, stub, handle);
|
| - else
|
| - return new ImageTransportSurfaceFBO(manager, stub, handle);
|
| -}
|
| -
|
| -ImageTransportSurfaceFBO::ImageTransportSurfaceFBO(
|
| - GpuChannelManager* manager,
|
| - GpuCommandBufferStub* stub,
|
| - gfx::PluginWindowHandle handle)
|
| - : backbuffer_suggested_allocation_(true),
|
| - frontbuffer_suggested_allocation_(true),
|
| - fbo_id_(0),
|
| - texture_id_(0),
|
| - depth_stencil_renderbuffer_id_(0),
|
| - has_complete_framebuffer_(false),
|
| - context_(NULL),
|
| - scale_factor_(1.f),
|
| - made_current_(false),
|
| - is_swap_buffers_send_pending_(false) {
|
| - if (ui::RemoteLayerAPISupported())
|
| - storage_provider_.reset(new CALayerStorageProvider(this));
|
| - else
|
| - storage_provider_.reset(new IOSurfaceStorageProvider(this));
|
| - helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
|
| -}
|
| -
|
| -ImageTransportSurfaceFBO::~ImageTransportSurfaceFBO() {
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::Initialize() {
|
| - // Only support IOSurfaces if the GL implementation is the native desktop GL.
|
| - // IO surfaces will not work with, for example, OSMesa software renderer
|
| - // GL contexts.
|
| - if (gfx::GetGLImplementation() !=
|
| - gfx::kGLImplementationDesktopGLCoreProfile &&
|
| - gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
|
| - gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
|
| - return false;
|
| -
|
| - if (!helper_->Initialize())
|
| - return false;
|
| -
|
| - helper_->stub()->AddDestructionObserver(this);
|
| - return true;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::Destroy() {
|
| - DestroyFramebuffer();
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::DeferDraws() {
|
| - storage_provider_->WillWriteToBackbuffer();
|
| - // We should not have a pending send when we are drawing the next frame.
|
| - DCHECK(!is_swap_buffers_send_pending_);
|
| -
|
| - // The call to WillWriteToBackbuffer could potentially force a draw. Ensure
|
| - // that any changes made to the context's state are restored.
|
| - context_->RestoreStateIfDirtiedExternally();
|
| - return false;
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::IsOffscreen() {
|
| - return false;
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::OnMakeCurrent(gfx::GLContext* context) {
|
| - context_ = context;
|
| -
|
| - if (made_current_)
|
| - return true;
|
| -
|
| - AllocateOrResizeFramebuffer(gfx::Size(1, 1), 1.f);
|
| -
|
| - made_current_ = true;
|
| - return true;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::NotifyWasBound() {
|
| - // Sometimes calling glBindFramebuffer doesn't seem to be enough to get
|
| - // rendered contents to show up in the color attachment. It appears that doing
|
| - // a glBegin/End pair with program 0 is enough to tickle the driver into
|
| - // actually effecting the binding.
|
| - // http://crbug.com/435786
|
| - DCHECK(has_complete_framebuffer_);
|
| -
|
| - // We will restore the current program after the dummy glBegin/End pair.
|
| - // Ensure that we will be able to restore this state before attempting to
|
| - // change it.
|
| - GLint old_program_signed = 0;
|
| - glGetIntegerv(GL_CURRENT_PROGRAM, &old_program_signed);
|
| - GLuint old_program = static_cast<GLuint>(old_program_signed);
|
| - if (old_program && glIsProgram(old_program)) {
|
| - // A deleted program cannot be re-bound.
|
| - GLint delete_status = GL_FALSE;
|
| - glGetProgramiv(old_program, GL_DELETE_STATUS, &delete_status);
|
| - if (delete_status == GL_TRUE)
|
| - return;
|
| - // A program which has had the most recent link fail cannot be re-bound.
|
| - GLint link_status = GL_FALSE;
|
| - glGetProgramiv(old_program, GL_LINK_STATUS, &link_status);
|
| - if (link_status != GL_TRUE)
|
| - return;
|
| - }
|
| -
|
| - // Issue the dummy call and then restore the state.
|
| - glUseProgram(0);
|
| - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
| - DCHECK(status == GL_FRAMEBUFFER_COMPLETE);
|
| - if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
|
| - // These aren't present in the core profile.
|
| - // TODO(ccameron): verify this workaround isn't still needed with
|
| - // the core profile.
|
| - glBegin(GL_TRIANGLES);
|
| - glEnd();
|
| - }
|
| - glUseProgram(old_program);
|
| -}
|
| -
|
| -unsigned int ImageTransportSurfaceFBO::GetBackingFrameBufferObject() {
|
| - return fbo_id_;
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::SetBackbufferAllocation(bool allocation) {
|
| - if (backbuffer_suggested_allocation_ == allocation)
|
| - return true;
|
| - backbuffer_suggested_allocation_ = allocation;
|
| - AdjustBufferAllocation();
|
| - if (!allocation)
|
| - storage_provider_->DiscardBackbuffer();
|
| - return true;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::SetFrontbufferAllocation(bool allocation) {
|
| - if (frontbuffer_suggested_allocation_ == allocation)
|
| - return;
|
| - frontbuffer_suggested_allocation_ = allocation;
|
| - AdjustBufferAllocation();
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::AdjustBufferAllocation() {
|
| - // On mac, the frontbuffer and backbuffer are the same buffer. The buffer is
|
| - // free'd when both the browser and gpu processes have Unref'd the IOSurface.
|
| - if (!backbuffer_suggested_allocation_ &&
|
| - !frontbuffer_suggested_allocation_ &&
|
| - has_complete_framebuffer_) {
|
| - DestroyFramebuffer();
|
| - } else if (backbuffer_suggested_allocation_ && !has_complete_framebuffer_) {
|
| - AllocateOrResizeFramebuffer(pixel_size_, scale_factor_);
|
| - }
|
| -}
|
| -
|
| -gfx::SwapResult ImageTransportSurfaceFBO::SwapBuffers() {
|
| - TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::SwapBuffers");
|
| - pending_swap_pixel_damage_rect_ = gfx::Rect(pixel_size_);
|
| - return SwapBuffersInternal(gfx::Rect(pixel_size_)) ?
|
| - gfx::SwapResult::SWAP_ACK : gfx::SwapResult::SWAP_FAILED;
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::SwapBuffersInternal(
|
| - const gfx::Rect& dirty_rect) {
|
| - DCHECK(backbuffer_suggested_allocation_);
|
| - if (!frontbuffer_suggested_allocation_)
|
| - return true;
|
| -
|
| - {
|
| - TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::glFlush");
|
| - glFlush();
|
| - }
|
| -
|
| - // It is the responsibility of the storage provider to send the swap IPC.
|
| - is_swap_buffers_send_pending_ = true;
|
| - storage_provider_->SwapBuffers(dirty_rect);
|
| -
|
| - // The call to swapBuffers could potentially result in an immediate draw.
|
| - // Ensure that any changes made to the context's state are restored.
|
| - context_->RestoreStateIfDirtiedExternally();
|
| - return true;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::SendSwapBuffers(uint64 surface_handle,
|
| - const gfx::Size pixel_size,
|
| - float scale_factor) {
|
| - TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::SendSwapBuffers");
|
| - GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
|
| - params.surface_handle = surface_handle;
|
| - params.size = pixel_size;
|
| - params.damage_rect = pending_swap_pixel_damage_rect_;
|
| - params.scale_factor = scale_factor;
|
| - params.latency_info.swap(latency_info_);
|
| - helper_->SendAcceleratedSurfaceBuffersSwapped(params);
|
| - is_swap_buffers_send_pending_ = false;
|
| - pending_swap_pixel_damage_rect_ = gfx::Rect();
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::SetRendererID(int renderer_id) {
|
| - if (renderer_id)
|
| - context_->share_group()->SetRendererID(renderer_id);
|
| -}
|
| -
|
| -const gpu::gles2::FeatureInfo* ImageTransportSurfaceFBO::GetFeatureInfo()
|
| - const {
|
| - return helper_->stub()->GetFeatureInfo();
|
| -}
|
| -
|
| -gfx::SwapResult ImageTransportSurfaceFBO::PostSubBuffer(int x,
|
| - int y,
|
| - int width,
|
| - int height) {
|
| - TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::PostSubBuffer");
|
| - pending_swap_pixel_damage_rect_.Union(gfx::Rect(x, y, width, height));
|
| - return SwapBuffersInternal(gfx::Rect(x, y, width, height)) ?
|
| - gfx::SwapResult::SWAP_ACK : gfx::SwapResult::SWAP_FAILED;
|
| -}
|
| -
|
| -bool ImageTransportSurfaceFBO::SupportsPostSubBuffer() {
|
| - return true;
|
| -}
|
| -
|
| -gfx::Size ImageTransportSurfaceFBO::GetSize() {
|
| - return pixel_size_;
|
| -}
|
| -
|
| -void* ImageTransportSurfaceFBO::GetHandle() {
|
| - return NULL;
|
| -}
|
| -
|
| -void* ImageTransportSurfaceFBO::GetDisplay() {
|
| - return NULL;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::OnBufferPresented(
|
| - const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
|
| - TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::OnBufferPresented");
|
| - SetRendererID(params.renderer_id);
|
| - storage_provider_->SwapBuffersAckedByBrowser(params.disable_throttling);
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::OnResize(gfx::Size pixel_size,
|
| - float scale_factor) {
|
| - TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::OnResize",
|
| - "old_size", pixel_size_.ToString(),
|
| - "new_size", pixel_size.ToString());
|
| - // Caching |context_| from OnMakeCurrent. It should still be current.
|
| - DCHECK(context_->IsCurrent(this));
|
| -
|
| - AllocateOrResizeFramebuffer(pixel_size, scale_factor);
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::SetLatencyInfo(
|
| - const std::vector<ui::LatencyInfo>& latency_info) {
|
| - for (size_t i = 0; i < latency_info.size(); i++)
|
| - latency_info_.push_back(latency_info[i]);
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::OnWillDestroyStub() {
|
| - helper_->stub()->RemoveDestructionObserver(this);
|
| - Destroy();
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::DestroyFramebuffer() {
|
| - // If we have resources to destroy, then make sure that we have a current
|
| - // context which we can use to delete the resources.
|
| - if (context_ || fbo_id_ || texture_id_ || depth_stencil_renderbuffer_id_) {
|
| - DCHECK(gfx::GLContext::GetCurrent() == context_);
|
| - DCHECK(context_->IsCurrent(this));
|
| - DCHECK(CGLGetCurrentContext());
|
| - }
|
| -
|
| - if (fbo_id_) {
|
| - glDeleteFramebuffersEXT(1, &fbo_id_);
|
| - fbo_id_ = 0;
|
| - }
|
| -
|
| - if (texture_id_) {
|
| - glDeleteTextures(1, &texture_id_);
|
| - texture_id_ = 0;
|
| - }
|
| -
|
| - if (depth_stencil_renderbuffer_id_) {
|
| - glDeleteRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
|
| - depth_stencil_renderbuffer_id_ = 0;
|
| - }
|
| -
|
| - storage_provider_->FreeColorBufferStorage();
|
| -
|
| - has_complete_framebuffer_ = false;
|
| -}
|
| -
|
| -void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
|
| - const gfx::Size& new_pixel_size, float new_scale_factor) {
|
| - gfx::Size new_rounded_pixel_size =
|
| - storage_provider_->GetRoundedSize(new_pixel_size);
|
| -
|
| - // Only recreate the surface's storage when the rounded up size has changed,
|
| - // or the scale factor has changed.
|
| - bool needs_new_storage =
|
| - !has_complete_framebuffer_ ||
|
| - new_rounded_pixel_size != rounded_pixel_size_ ||
|
| - new_scale_factor != scale_factor_;
|
| -
|
| - // Save the new storage parameters.
|
| - pixel_size_ = new_pixel_size;
|
| - rounded_pixel_size_ = new_rounded_pixel_size;
|
| - scale_factor_ = new_scale_factor;
|
| -
|
| - if (!needs_new_storage) {
|
| - storage_provider_->FrameSizeChanged(pixel_size_, scale_factor_);
|
| - return;
|
| - }
|
| -
|
| - TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer",
|
| - "width", new_rounded_pixel_size.width(),
|
| - "height", new_rounded_pixel_size.height());
|
| -
|
| - // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on
|
| - // Mac OS X and is required for IOSurface interoperability.
|
| - GLint previous_texture_id = 0;
|
| -
|
| - GLenum texture_target = GL_TEXTURE_RECTANGLE_ARB;
|
| - GLenum texture_binding_target = GL_TEXTURE_BINDING_RECTANGLE_ARB;
|
| - // However, the remote core animation path on the core profile will
|
| - // be the preferred combination going forward.
|
| - if (gfx::GetGLImplementation() ==
|
| - gfx::kGLImplementationDesktopGLCoreProfile &&
|
| - ui::RemoteLayerAPISupported()) {
|
| - texture_target = GL_TEXTURE_2D;
|
| - texture_binding_target = GL_TEXTURE_BINDING_2D;
|
| - }
|
| -
|
| - glGetIntegerv(texture_binding_target, &previous_texture_id);
|
| -
|
| - // Free the old IO Surface first to reduce memory fragmentation.
|
| - DestroyFramebuffer();
|
| -
|
| - glGenFramebuffersEXT(1, &fbo_id_);
|
| - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id_);
|
| -
|
| - glGenTextures(1, &texture_id_);
|
| -
|
| - glBindTexture(texture_target, texture_id_);
|
| - glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
| - glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
| - glTexParameteri(texture_target,
|
| - GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
| - glTexParameteri(texture_target,
|
| - GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
| -
|
| - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
|
| - GL_COLOR_ATTACHMENT0_EXT,
|
| - texture_target,
|
| - texture_id_,
|
| - 0);
|
| -
|
| - // Search through the provided attributes; if the caller has
|
| - // requested a stencil buffer, try to get one.
|
| -
|
| - int32 stencil_bits =
|
| - helper_->stub()->GetRequestedAttribute(EGL_STENCIL_SIZE);
|
| - if (stencil_bits > 0) {
|
| - // Create and bind the stencil buffer
|
| - bool has_packed_depth_stencil =
|
| - GLSurface::ExtensionsContain(
|
| - reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)),
|
| - "GL_EXT_packed_depth_stencil");
|
| -
|
| - if (has_packed_depth_stencil) {
|
| - glGenRenderbuffersEXT(1, &depth_stencil_renderbuffer_id_);
|
| - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT,
|
| - depth_stencil_renderbuffer_id_);
|
| - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
|
| - rounded_pixel_size_.width(),
|
| - rounded_pixel_size_.height());
|
| - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT,
|
| - GL_STENCIL_ATTACHMENT_EXT,
|
| - GL_RENDERBUFFER_EXT,
|
| - depth_stencil_renderbuffer_id_);
|
| - }
|
| -
|
| - // If we asked for stencil but the extension isn't present,
|
| - // it's OK to silently fail; subsequent code will/must check
|
| - // for the presence of a stencil buffer before attempting to
|
| - // do stencil-based operations.
|
| - }
|
| -
|
| - bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
|
| - static_cast<CGLContextObj>(
|
| - context_->GetHandle()),
|
| - context_->GetStateWasDirtiedExternallyCallback(),
|
| - texture_id_, rounded_pixel_size_, scale_factor_);
|
| - if (!allocated_color_buffer) {
|
| - DLOG(ERROR) << "Failed to allocate color buffer storage.";
|
| - DestroyFramebuffer();
|
| - return;
|
| - }
|
| -
|
| - GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
| - if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
|
| - DLOG(ERROR) << "Framebuffer was incomplete: " << status;
|
| - DestroyFramebuffer();
|
| - return;
|
| - }
|
| -
|
| - has_complete_framebuffer_ = true;
|
| - storage_provider_->FrameSizeChanged(pixel_size_, scale_factor_);
|
| -
|
| - glBindTexture(texture_target, previous_texture_id);
|
| - // The FBO remains bound for this GL context.
|
| -}
|
| -
|
| -} // namespace content
|
|
|