summaryrefslogtreecommitdiff
path: root/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/common/gpu/image_transport_surface_fbo_mac.mm')
-rw-r--r--chromium/content/common/gpu/image_transport_surface_fbo_mac.mm114
1 files changed, 98 insertions, 16 deletions
diff --git a/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm b/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
index 6af794d552e..f1aa838a778 100644
--- a/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
+++ b/chromium/content/common/gpu/image_transport_surface_fbo_mac.mm
@@ -4,6 +4,7 @@
#include "content/common/gpu/image_transport_surface_fbo_mac.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"
@@ -15,6 +16,13 @@
namespace content {
+scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
+ GpuChannelManager* manager,
+ GpuCommandBufferStub* stub,
+ gfx::PluginWindowHandle handle) {
+ return new ImageTransportSurfaceFBO(manager, stub, handle);
+}
+
ImageTransportSurfaceFBO::ImageTransportSurfaceFBO(
GpuChannelManager* manager,
GpuCommandBufferStub* stub,
@@ -43,7 +51,9 @@ 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::kGLImplementationDesktopGL &&
+ if (gfx::GetGLImplementation() !=
+ gfx::kGLImplementationDesktopGLCoreProfile &&
+ gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL &&
gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL)
return false;
@@ -62,6 +72,10 @@ 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;
}
@@ -81,6 +95,47 @@ bool ImageTransportSurfaceFBO::OnMakeCurrent(gfx::GLContext* context) {
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_;
}
@@ -115,6 +170,11 @@ void ImageTransportSurfaceFBO::AdjustBufferAllocation() {
}
bool ImageTransportSurfaceFBO::SwapBuffers() {
+ TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::SwapBuffers");
+ return SwapBuffersInternal();
+}
+
+bool ImageTransportSurfaceFBO::SwapBuffersInternal() {
DCHECK(backbuffer_suggested_allocation_);
if (!frontbuffer_suggested_allocation_)
return true;
@@ -122,13 +182,18 @@ bool ImageTransportSurfaceFBO::SwapBuffers() {
// It is the responsibility of the storage provider to send the swap IPC.
is_swap_buffers_send_pending_ = true;
- storage_provider_->SwapBuffers(pixel_size_, scale_factor_);
+ storage_provider_->SwapBuffers();
+
+ // 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;
@@ -145,9 +210,8 @@ void ImageTransportSurfaceFBO::SetRendererID(int renderer_id) {
bool ImageTransportSurfaceFBO::PostSubBuffer(
int x, int y, int width, int height) {
- // Mac does not support sub-buffer swaps.
- NOTREACHED();
- return false;
+ TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::PostSubBuffer");
+ return SwapBuffersInternal();
}
bool ImageTransportSurfaceFBO::SupportsPostSubBuffer() {
@@ -168,6 +232,7 @@ void* ImageTransportSurfaceFBO::GetDisplay() {
void ImageTransportSurfaceFBO::OnBufferPresented(
const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
+ TRACE_EVENT0("gpu", "ImageTransportSurfaceFBO::OnBufferPresented");
SetRendererID(params.renderer_id);
storage_provider_->SwapBuffersAckedByBrowser(params.disable_throttling);
}
@@ -244,8 +309,10 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
rounded_pixel_size_ = new_rounded_pixel_size;
scale_factor_ = new_scale_factor;
- if (!needs_new_storage)
+ if (!needs_new_storage) {
+ storage_provider_->FrameSizeChanged(pixel_size_, scale_factor_);
return;
+ }
TRACE_EVENT2("gpu", "ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer",
"width", new_rounded_pixel_size.width(),
@@ -254,7 +321,19 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
// 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;
- glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id);
+
+ 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();
@@ -264,17 +343,17 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
glGenTextures(1, &texture_id_);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id_);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,
+ 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(GL_TEXTURE_RECTANGLE_ARB,
+ glTexParameteri(texture_target,
GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_RECTANGLE_ARB,
+ texture_target,
texture_id_,
0);
@@ -310,8 +389,10 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
}
bool allocated_color_buffer = storage_provider_->AllocateColorBufferStorage(
- static_cast<CGLContextObj>(context_->GetHandle()), texture_id_,
- rounded_pixel_size_, scale_factor_);
+ 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();
@@ -326,8 +407,9 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer(
}
has_complete_framebuffer_ = true;
+ storage_provider_->FrameSizeChanged(pixel_size_, scale_factor_);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, previous_texture_id);
+ glBindTexture(texture_target, previous_texture_id);
// The FBO remains bound for this GL context.
}