| Index: content/browser/compositor/io_surface_texture_mac.mm
|
| diff --git a/content/browser/compositor/io_surface_texture_mac.mm b/content/browser/compositor/io_surface_texture_mac.mm
|
| index 6670d08e358d5f40948b1ccf0ece8ddf63933387..3424cbdfd35f56f3702d2757328111d2f3e6ee49 100644
|
| --- a/content/browser/compositor/io_surface_texture_mac.mm
|
| +++ b/content/browser/compositor/io_surface_texture_mac.mm
|
| @@ -29,20 +29,6 @@
|
| #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
|
| @@ -61,8 +47,6 @@ scoped_refptr<IOSurfaceTexture> IOSurfaceTexture::Create() {
|
| IOSurfaceTexture::IOSurfaceTexture(
|
| const scoped_refptr<IOSurfaceContext>& 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()),
|
| @@ -80,17 +64,6 @@ IOSurfaceTexture::~IOSurfaceTexture() {
|
| DCHECK(eviction_queue_iterator_ == eviction_queue_.Get().end());
|
| }
|
|
|
| -bool IOSurfaceTexture::SetIOSurfaceWithContextCurrent(
|
| - scoped_refptr<IOSurfaceContext> 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 IOSurfaceTexture::GetRendererID() {
|
| GLint current_renderer_id = -1;
|
| if (CGLGetParameter(offscreen_context_->cgl_context(),
|
| @@ -100,77 +73,46 @@ int IOSurfaceTexture::GetRendererID() {
|
| return -1;
|
| }
|
|
|
| -bool IOSurfaceTexture::DrawIOSurface(
|
| - scoped_refptr<IOSurfaceContext> drawing_context,
|
| - const gfx::Rect& window_rect,
|
| - float window_scale_factor) {
|
| - DCHECK_EQ(CGLGetCurrentContext(), drawing_context->cgl_context());
|
| +bool IOSurfaceTexture::DrawIOSurface() {
|
| + TRACE_EVENT0("browser", "IOSurfaceTexture::DrawIOSurface");
|
| + DCHECK(HasIOSurface());
|
|
|
| - bool has_io_surface = HasIOSurface();
|
| - TRACE_EVENT1("browser", "IOSurfaceTexture::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_);
|
| + // The viewport is the size of the CALayer, which should always match the
|
| + // IOSurface pixel size.
|
| + GLint viewport[4];
|
| + glGetIntegerv(GL_VIEWPORT, viewport);
|
| + gfx::Rect viewport_rect(viewport[0], viewport[1], viewport[2], viewport[3]);
|
| + DCHECK_EQ(pixel_size_.ToString(), viewport_rect.size().ToString());
|
|
|
| + // Set the projection matrix to match 1 unit to 1 pixel.
|
| 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);
|
| + glOrtho(0, viewport_rect.width(), 0, viewport_rect.height(), -1, 1);
|
| glMatrixMode(GL_MODELVIEW);
|
| glLoadIdentity();
|
|
|
| - glDisable(GL_DEPTH_TEST);
|
| - glDisable(GL_BLEND);
|
| -
|
| + // Draw a quad the size of the IOSurface. This should cover the full viewport.
|
| 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 IOSurfaceTexture.
|
| - 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);
|
| - }
|
| + glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
| + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_);
|
| + glBegin(GL_QUADS);
|
| + glTexCoord2f(0, 0);
|
| + glVertex2f(0, 0);
|
| + glTexCoord2f(pixel_size_.width(), 0);
|
| + glVertex2f(pixel_size_.width(), 0);
|
| + glTexCoord2f(pixel_size_.width(), pixel_size_.height());
|
| + glVertex2f(pixel_size_.width(), pixel_size_.height());
|
| + glTexCoord2f(0, pixel_size_.height());
|
| + glVertex2f(0, pixel_size_.height());
|
| + glEnd();
|
| + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
| + glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
| +
|
| + // 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();
|
|
|
| bool workaround_needed =
|
| GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
|
| @@ -187,61 +129,59 @@ bool IOSurfaceTexture::DrawIOSurface(
|
| 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.
|
| + // rendering artifacts.
|
| 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 IOSurfaceTexture::MapIOSurfaceToTextureWithContextCurrent(
|
| - const scoped_refptr<IOSurfaceContext>& current_context,
|
| - const gfx::Size pixel_size,
|
| - float scale_factor,
|
| - IOSurfaceID io_surface_handle) {
|
| +bool IOSurfaceTexture::SetIOSurface(
|
| + scoped_refptr<IOSurfaceContext> context,
|
| + IOSurfaceID io_surface_id,
|
| + const gfx::Size& pixel_size) {
|
| TRACE_EVENT0("browser", "IOSurfaceTexture::MapIOSurfaceToTexture");
|
|
|
| - if (!io_surface_ || io_surface_handle != io_surface_handle_)
|
| + gfx::ScopedCGLSetCurrentContext scoped_set_current_context(
|
| + context->cgl_context());
|
| +
|
| + // Destroy the old IOSurface and texture if it is no longer needed.
|
| + bool needs_new_iosurface =
|
| + !io_surface_ || io_surface_id != IOSurfaceGetID(io_surface_);
|
| + if (needs_new_iosurface)
|
| 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_));
|
| + // Note that because IOSurface sizes are rounded, the same IOSurface may have
|
| + // two different sizes associated with it, so update the sizes before the
|
| + // early-out.
|
| + pixel_size_ = pixel_size;
|
|
|
| - // 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_)
|
| + // Early-out if the IOSurface has not changed.
|
| + if (!needs_new_iosurface)
|
| return true;
|
|
|
| - io_surface_.reset(IOSurfaceLookup(io_surface_handle));
|
| - // Can fail if IOSurface with that ID was already released by the gpu
|
| - // process.
|
| + // Open the IOSurface handle.
|
| + io_surface_.reset(IOSurfaceLookup(io_surface_id));
|
| 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_));
|
|
|
| + // Create the GL texture and set it to be backed by the IOSurface.
|
| 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(),
|
| + context->cgl_context(),
|
| GL_TEXTURE_RECTANGLE_ARB,
|
| GL_RGBA,
|
| rounded_size.width(),
|
| @@ -251,17 +191,20 @@ bool IOSurfaceTexture::MapIOSurfaceToTextureWithContextCurrent(
|
| io_surface_.get(),
|
| plane);
|
| glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
|
| + GetAndSaveGLError();
|
| +
|
| + // Return failure if an error was encountered by CGL or GL.
|
| if (cgl_error != kCGLNoError) {
|
| - LOG(ERROR) << "CGLTexImageIOSurface2D: " << cgl_error;
|
| + LOG(ERROR) << "CGLTexImageIOSurface2D failed with CGL error: " << cgl_error;
|
| UnrefIOSurfaceWithContextCurrent();
|
| return false;
|
| }
|
| - GetAndSaveGLError();
|
| if (gl_error_ != GL_NO_ERROR) {
|
| - LOG(ERROR) << "GL error in MapIOSurfaceToTexture: " << gl_error_;
|
| + LOG(ERROR) << "Hit GL error in SetIOSurface: " << gl_error_;
|
| UnrefIOSurfaceWithContextCurrent();
|
| return false;
|
| }
|
| +
|
| return true;
|
| }
|
|
|
| @@ -271,35 +214,14 @@ void IOSurfaceTexture::UnrefIOSurface() {
|
| UnrefIOSurfaceWithContextCurrent();
|
| }
|
|
|
| -void IOSurfaceTexture::DrawQuad(const SurfaceQuad& quad) {
|
| - TRACE_EVENT0("gpu", "IOSurfaceTexture::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 IOSurfaceTexture::UnrefIOSurfaceWithContextCurrent() {
|
| if (texture_) {
|
| glDeleteTextures(1, &texture_);
|
| texture_ = 0;
|
| }
|
| - pixel_io_surface_size_ = gfx::Size();
|
| - scale_factor_ = 1;
|
| - dip_io_surface_size_ = gfx::Size();
|
| + pixel_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();
|
| }
|
|
|
|
|