| Index: content/browser/renderer_host/compositing_iosurface_mac.mm
|
| diff --git a/content/browser/renderer_host/compositing_iosurface_mac.mm b/content/browser/renderer_host/compositing_iosurface_mac.mm
|
| deleted file mode 100644
|
| index 701239999da34873d3a9a7a95584a29f8d9dfd95..0000000000000000000000000000000000000000
|
| --- a/content/browser/renderer_host/compositing_iosurface_mac.mm
|
| +++ /dev/null
|
| @@ -1,376 +0,0 @@
|
| -// Copyright (c) 2012 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/browser/renderer_host/compositing_iosurface_mac.h"
|
| -
|
| -#include <OpenGL/CGLIOSurface.h>
|
| -#include <OpenGL/CGLRenderers.h>
|
| -#include <OpenGL/OpenGL.h>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/logging.h"
|
| -#include "base/mac/mac_util.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/threading/platform_thread.h"
|
| -#include "content/browser/gpu/gpu_data_manager_impl.h"
|
| -#include "content/browser/renderer_host/compositing_iosurface_context_mac.h"
|
| -#include "content/browser/renderer_host/render_widget_host_impl.h"
|
| -#include "content/browser/renderer_host/render_widget_host_view_mac.h"
|
| -#include "content/common/content_constants_internal.h"
|
| -#include "gpu/config/gpu_driver_bug_workaround_type.h"
|
| -#include "media/base/video_util.h"
|
| -#include "third_party/skia/include/core/SkBitmap.h"
|
| -#include "ui/gfx/rect.h"
|
| -#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
|
| -#include "ui/gfx/size_conversions.h"
|
| -#include "ui/gl/gl_context.h"
|
| -
|
| -#ifdef NDEBUG
|
| -#define CHECK_GL_ERROR()
|
| -#define CHECK_AND_SAVE_GL_ERROR()
|
| -#else
|
| -#define CHECK_GL_ERROR() do { \
|
| - GLenum gl_error = glGetError(); \
|
| - LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
|
| - } while (0)
|
| -#define CHECK_AND_SAVE_GL_ERROR() do { \
|
| - GLenum gl_error = GetAndSaveGLError(); \
|
| - LOG_IF(ERROR, gl_error != GL_NO_ERROR) << "GL Error: " << gl_error; \
|
| - } while (0)
|
| -#endif
|
| -
|
| -namespace content {
|
| -
|
| -// static
|
| -scoped_refptr<CompositingIOSurfaceMac> CompositingIOSurfaceMac::Create() {
|
| - scoped_refptr<CompositingIOSurfaceContext> offscreen_context =
|
| - CompositingIOSurfaceContext::Get(
|
| - CompositingIOSurfaceContext::kOffscreenContextWindowNumber);
|
| - if (!offscreen_context) {
|
| - LOG(ERROR) << "Failed to create context for offscreen operations";
|
| - return NULL;
|
| - }
|
| -
|
| - return new CompositingIOSurfaceMac(offscreen_context);
|
| -}
|
| -
|
| -CompositingIOSurfaceMac::CompositingIOSurfaceMac(
|
| - const scoped_refptr<CompositingIOSurfaceContext>& offscreen_context)
|
| - : offscreen_context_(offscreen_context),
|
| - io_surface_handle_(0),
|
| - scale_factor_(1.f),
|
| - texture_(0),
|
| - gl_error_(GL_NO_ERROR),
|
| - eviction_queue_iterator_(eviction_queue_.Get().end()),
|
| - eviction_has_been_drawn_since_updated_(false) {
|
| - CHECK(offscreen_context_);
|
| -}
|
| -
|
| -CompositingIOSurfaceMac::~CompositingIOSurfaceMac() {
|
| - {
|
| - gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
|
| - offscreen_context_->cgl_context());
|
| - UnrefIOSurfaceWithContextCurrent();
|
| - }
|
| - offscreen_context_ = NULL;
|
| - DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
|
| -}
|
| -
|
| -bool CompositingIOSurfaceMac::SetIOSurfaceWithContextCurrent(
|
| - scoped_refptr<CompositingIOSurfaceContext> current_context,
|
| - IOSurfaceID io_surface_handle,
|
| - const gfx::Size& size,
|
| - float scale_factor) {
|
| - bool result = MapIOSurfaceToTextureWithContextCurrent(
|
| - current_context, size, scale_factor, io_surface_handle);
|
| - EvictionMarkUpdated();
|
| - return result;
|
| -}
|
| -
|
| -int CompositingIOSurfaceMac::GetRendererID() {
|
| - GLint current_renderer_id = -1;
|
| - if (CGLGetParameter(offscreen_context_->cgl_context(),
|
| - kCGLCPCurrentRendererID,
|
| - ¤t_renderer_id) == kCGLNoError)
|
| - return current_renderer_id & kCGLRendererIDMatchingMask;
|
| - return -1;
|
| -}
|
| -
|
| -bool CompositingIOSurfaceMac::DrawIOSurface(
|
| - scoped_refptr<CompositingIOSurfaceContext> drawing_context,
|
| - const gfx::Rect& window_rect,
|
| - float window_scale_factor) {
|
| - DCHECK_EQ(CGLGetCurrentContext(), drawing_context->cgl_context());
|
| -
|
| - bool has_io_surface = HasIOSurface();
|
| - TRACE_EVENT1("browser", "CompositingIOSurfaceMac::DrawIOSurface",
|
| - "has_io_surface", has_io_surface);
|
| -
|
| - gfx::Rect pixel_window_rect =
|
| - ToNearestRect(gfx::ScaleRect(window_rect, window_scale_factor));
|
| - glViewport(
|
| - pixel_window_rect.x(), pixel_window_rect.y(),
|
| - pixel_window_rect.width(), pixel_window_rect.height());
|
| -
|
| - SurfaceQuad quad;
|
| - quad.set_size(dip_io_surface_size_, pixel_io_surface_size_);
|
| -
|
| - glMatrixMode(GL_PROJECTION);
|
| - glLoadIdentity();
|
| -
|
| - // Note that the projection keeps things in view units, so the use of
|
| - // window_rect / dip_io_surface_size_ (as opposed to the pixel_ variants)
|
| - // below is correct.
|
| - glOrtho(0, window_rect.width(), window_rect.height(), 0, -1, 1);
|
| - glMatrixMode(GL_MODELVIEW);
|
| - glLoadIdentity();
|
| -
|
| - glDisable(GL_DEPTH_TEST);
|
| - glDisable(GL_BLEND);
|
| -
|
| - glColor4f(1, 1, 1, 1);
|
| - if (has_io_surface) {
|
| - glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
| - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
|
| - DrawQuad(quad);
|
| - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
| - glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
| - CHECK_AND_SAVE_GL_ERROR();
|
| -
|
| - // Fill the resize gutters with white.
|
| - if (window_rect.width() > dip_io_surface_size_.width() ||
|
| - window_rect.height() > dip_io_surface_size_.height()) {
|
| - SurfaceQuad filler_quad;
|
| - if (window_rect.width() > dip_io_surface_size_.width()) {
|
| - // Draw right-side gutter down to the bottom of the window.
|
| - filler_quad.set_rect(dip_io_surface_size_.width(), 0.0f,
|
| - window_rect.width(), window_rect.height());
|
| - DrawQuad(filler_quad);
|
| - }
|
| - if (window_rect.height() > dip_io_surface_size_.height()) {
|
| - // Draw bottom gutter to the width of the IOSurface.
|
| - filler_quad.set_rect(
|
| - 0.0f, dip_io_surface_size_.height(),
|
| - dip_io_surface_size_.width(), window_rect.height());
|
| - DrawQuad(filler_quad);
|
| - }
|
| - }
|
| -
|
| - // Workaround for issue 158469. Issue a dummy draw call with texture_ not
|
| - // bound to a texture, in order to shake all references to the IOSurface out
|
| - // of the driver.
|
| - glBegin(GL_TRIANGLES);
|
| - glEnd();
|
| - CHECK_AND_SAVE_GL_ERROR();
|
| - } else {
|
| - // Should match the clear color of RenderWidgetHostViewMac.
|
| - glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
| - glClear(GL_COLOR_BUFFER_BIT);
|
| - }
|
| -
|
| - bool workaround_needed =
|
| - GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
|
| - gpu::FORCE_GL_FINISH_AFTER_COMPOSITING);
|
| - if (workaround_needed) {
|
| - TRACE_EVENT0("gpu", "glFinish");
|
| - glFinish();
|
| - }
|
| -
|
| - // Check if any of the drawing calls result in an error.
|
| - GetAndSaveGLError();
|
| - bool result = true;
|
| - if (gl_error_ != GL_NO_ERROR) {
|
| - LOG(ERROR) << "GL error in DrawIOSurface: " << gl_error_;
|
| - result = false;
|
| - // If there was an error, clear the screen to a light grey to avoid
|
| - // rendering artifacts. If we're in a really bad way, this too may
|
| - // generate an error. Clear the GL error afterwards just in case.
|
| - glClearColor(0.8, 0.8, 0.8, 1.0);
|
| - glClear(GL_COLOR_BUFFER_BIT);
|
| - glGetError();
|
| - }
|
| -
|
| - eviction_has_been_drawn_since_updated_ = true;
|
| - return result;
|
| -}
|
| -
|
| -bool CompositingIOSurfaceMac::MapIOSurfaceToTextureWithContextCurrent(
|
| - const scoped_refptr<CompositingIOSurfaceContext>& current_context,
|
| - const gfx::Size pixel_size,
|
| - float scale_factor,
|
| - IOSurfaceID io_surface_handle) {
|
| - TRACE_EVENT0("browser", "CompositingIOSurfaceMac::MapIOSurfaceToTexture");
|
| -
|
| - if (!io_surface_ || io_surface_handle != io_surface_handle_)
|
| - UnrefIOSurfaceWithContextCurrent();
|
| -
|
| - pixel_io_surface_size_ = pixel_size;
|
| - scale_factor_ = scale_factor;
|
| - dip_io_surface_size_ = gfx::ToFlooredSize(
|
| - gfx::ScaleSize(pixel_io_surface_size_, 1.0 / scale_factor_));
|
| -
|
| - // Early-out if the IOSurface has not changed. Note that because IOSurface
|
| - // sizes are rounded, the same IOSurface may have two different sizes
|
| - // associated with it.
|
| - if (io_surface_ && io_surface_handle == io_surface_handle_)
|
| - return true;
|
| -
|
| - io_surface_.reset(IOSurfaceLookup(io_surface_handle));
|
| - // Can fail if IOSurface with that ID was already released by the gpu
|
| - // process.
|
| - if (!io_surface_) {
|
| - UnrefIOSurfaceWithContextCurrent();
|
| - return false;
|
| - }
|
| -
|
| - io_surface_handle_ = io_surface_handle;
|
| -
|
| - // Actual IOSurface size is rounded up to reduce reallocations during window
|
| - // resize. Get the actual size to properly map the texture.
|
| - gfx::Size rounded_size(IOSurfaceGetWidth(io_surface_),
|
| - IOSurfaceGetHeight(io_surface_));
|
| -
|
| - glGenTextures(1, &texture_);
|
| - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
|
| - glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
| - glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
| - CHECK_AND_SAVE_GL_ERROR();
|
| - GLuint plane = 0;
|
| - CGLError cgl_error = CGLTexImageIOSurface2D(
|
| - current_context->cgl_context(),
|
| - GL_TEXTURE_RECTANGLE_ARB,
|
| - GL_RGBA,
|
| - rounded_size.width(),
|
| - rounded_size.height(),
|
| - GL_BGRA,
|
| - GL_UNSIGNED_INT_8_8_8_8_REV,
|
| - io_surface_.get(),
|
| - plane);
|
| - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
| - if (cgl_error != kCGLNoError) {
|
| - LOG(ERROR) << "CGLTexImageIOSurface2D: " << cgl_error;
|
| - UnrefIOSurfaceWithContextCurrent();
|
| - return false;
|
| - }
|
| - GetAndSaveGLError();
|
| - if (gl_error_ != GL_NO_ERROR) {
|
| - LOG(ERROR) << "GL error in MapIOSurfaceToTexture: " << gl_error_;
|
| - UnrefIOSurfaceWithContextCurrent();
|
| - return false;
|
| - }
|
| - return true;
|
| -}
|
| -
|
| -void CompositingIOSurfaceMac::UnrefIOSurface() {
|
| - gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
|
| - offscreen_context_->cgl_context());
|
| - UnrefIOSurfaceWithContextCurrent();
|
| -}
|
| -
|
| -void CompositingIOSurfaceMac::DrawQuad(const SurfaceQuad& quad) {
|
| - TRACE_EVENT0("gpu", "CompositingIOSurfaceMac::DrawQuad");
|
| -
|
| - glEnableClientState(GL_VERTEX_ARRAY); CHECK_AND_SAVE_GL_ERROR();
|
| - glEnableClientState(GL_TEXTURE_COORD_ARRAY); CHECK_AND_SAVE_GL_ERROR();
|
| -
|
| - glVertexPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].x_);
|
| - glTexCoordPointer(2, GL_FLOAT, sizeof(SurfaceVertex), &quad.verts_[0].tx_);
|
| - glDrawArrays(GL_QUADS, 0, 4); CHECK_AND_SAVE_GL_ERROR();
|
| -
|
| - glDisableClientState(GL_VERTEX_ARRAY);
|
| - glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
| -}
|
| -
|
| -void CompositingIOSurfaceMac::UnrefIOSurfaceWithContextCurrent() {
|
| - if (texture_) {
|
| - glDeleteTextures(1, &texture_);
|
| - texture_ = 0;
|
| - }
|
| - pixel_io_surface_size_ = gfx::Size();
|
| - scale_factor_ = 1;
|
| - dip_io_surface_size_ = gfx::Size();
|
| - io_surface_.reset();
|
| -
|
| - // Forget the ID, because even if it is still around when we want to use it
|
| - // again, OSX may have reused the same ID for a new tab and we don't want to
|
| - // blit random tab contents.
|
| - io_surface_handle_ = 0;
|
| -
|
| - EvictionMarkEvicted();
|
| -}
|
| -
|
| -bool CompositingIOSurfaceMac::HasBeenPoisoned() const {
|
| - return offscreen_context_->HasBeenPoisoned();
|
| -}
|
| -
|
| -GLenum CompositingIOSurfaceMac::GetAndSaveGLError() {
|
| - GLenum gl_error = glGetError();
|
| - if (gl_error_ == GL_NO_ERROR)
|
| - gl_error_ = gl_error;
|
| - return gl_error;
|
| -}
|
| -
|
| -void CompositingIOSurfaceMac::EvictionMarkUpdated() {
|
| - EvictionMarkEvicted();
|
| - eviction_queue_.Get().push_back(this);
|
| - eviction_queue_iterator_ = --eviction_queue_.Get().end();
|
| - eviction_has_been_drawn_since_updated_ = false;
|
| - EvictionScheduleDoEvict();
|
| -}
|
| -
|
| -void CompositingIOSurfaceMac::EvictionMarkEvicted() {
|
| - if (eviction_queue_iterator_ == eviction_queue_.Get().end())
|
| - return;
|
| - eviction_queue_.Get().erase(eviction_queue_iterator_);
|
| - eviction_queue_iterator_ = eviction_queue_.Get().end();
|
| - eviction_has_been_drawn_since_updated_ = false;
|
| -}
|
| -
|
| -// static
|
| -void CompositingIOSurfaceMac::EvictionScheduleDoEvict() {
|
| - if (eviction_scheduled_)
|
| - return;
|
| - if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
|
| - return;
|
| -
|
| - eviction_scheduled_ = true;
|
| - base::MessageLoop::current()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&CompositingIOSurfaceMac::EvictionDoEvict));
|
| -}
|
| -
|
| -// static
|
| -void CompositingIOSurfaceMac::EvictionDoEvict() {
|
| - eviction_scheduled_ = false;
|
| - // Walk the list of allocated surfaces from least recently used to most
|
| - // recently used.
|
| - for (EvictionQueue::iterator it = eviction_queue_.Get().begin();
|
| - it != eviction_queue_.Get().end();) {
|
| - CompositingIOSurfaceMac* surface = *it;
|
| - ++it;
|
| -
|
| - // If the number of IOSurfaces allocated is less than the threshold,
|
| - // stop walking the list of surfaces.
|
| - if (eviction_queue_.Get().size() <= kMaximumUnevictedSurfaces)
|
| - break;
|
| -
|
| - // Don't evict anything that has not yet been drawn.
|
| - if (!surface->eviction_has_been_drawn_since_updated_)
|
| - continue;
|
| -
|
| - // Evict the surface.
|
| - surface->UnrefIOSurface();
|
| - }
|
| -}
|
| -
|
| -// static
|
| -base::LazyInstance<CompositingIOSurfaceMac::EvictionQueue>
|
| - CompositingIOSurfaceMac::eviction_queue_;
|
| -
|
| -// static
|
| -bool CompositingIOSurfaceMac::eviction_scheduled_ = false;
|
| -
|
| -} // namespace content
|
|
|