Commit message: None
CVE: CVE-2014-3176

Project: Chrome

void GLSurfaceOzoneSurfacelessSurfaceImpl::BindFramebuffer() {
  ScopedFrameBufferBinder fb(fbo_);
  glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                            textures_[current_surface_], 0);
}

Project: Chrome

scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
    const gfx::Size& size) {
  switch (GetGLImplementation()) {
    case kGLImplementationOSMesaGL: {
      scoped_refptr<GLSurface> surface(
          new GLSurfaceOSMesa(SURFACE_OSMESA_BGRA, size));
      if (!surface->Initialize())
        return nullptr;

      return surface;
    }
    case kGLImplementationEGLGLES2: {
      scoped_refptr<GLSurface> surface;
      if (GLSurfaceEGL::IsEGLSurfacelessContextSupported() &&
          (size.width() == 0 && size.height() == 0)) {
        surface = new SurfacelessEGL(size);
      } else {
        surface = new PbufferGLSurfaceEGL(size);
      }

      if (!surface->Initialize())
        return nullptr;
      return surface;
    }
    case kGLImplementationMockGL:
      return new GLSurfaceStub;
    default:
      NOTREACHED();
      return nullptr;
  }
}

Project: Chrome

bool GLSurfaceOzoneSurfacelessSurfaceImpl::CreatePixmaps() {
  if (!fbo_)
    return true;
  for (size_t i = 0; i < arraysize(textures_); i++) {
    scoped_refptr<ui::NativePixmap> pixmap =
        ui::OzonePlatform::GetInstance()
            ->GetSurfaceFactoryOzone()
            ->CreateNativePixmap(widget_, GetSize(),
                                 gfx::BufferFormat::BGRA_8888,
                                 gfx::BufferUsage::SCANOUT);
    if (!pixmap)
      return false;
    scoped_refptr<GLImageOzoneNativePixmap> image =
        new GLImageOzoneNativePixmap(GetSize(), GL_BGRA_EXT);
    if (!image->Initialize(pixmap.get(), gfx::BufferFormat::BGRA_8888))
      return false;
    if (images_[i])
      images_[i]->Destroy(true);
    images_[i] = image;
    ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
    if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
      return false;
  }
  return true;
}

Project: Chrome

scoped_refptr<GLSurface> GLSurface::CreateSurfacelessViewGLSurface(
    gfx::AcceleratedWidget window) {
  if (GetGLImplementation() == kGLImplementationEGLGLES2 &&
      window != kNullAcceleratedWidget &&
      GLSurfaceEGL::IsEGLSurfacelessContextSupported()) {
    std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone =
        ui::OzonePlatform::GetInstance()
            ->GetSurfaceFactoryOzone()
            ->CreateSurfacelessEGLSurfaceForWidget(window);
    if (!surface_ozone)
      return nullptr;
    scoped_refptr<GLSurface> surface;
    surface = new GLSurfaceOzoneSurfaceless(std::move(surface_ozone), window);
    if (surface->Initialize())
      return surface;
  }

  return nullptr;
}

Project: Chrome

scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
    gfx::AcceleratedWidget window) {
  if (GetGLImplementation() == kGLImplementationOSMesaGL) {
    scoped_refptr<GLSurface> surface(new GLSurfaceOSMesaHeadless());
    if (!surface->Initialize())
      return nullptr;
    return surface;
  }
  DCHECK(GetGLImplementation() == kGLImplementationEGLGLES2);
  if (window != kNullAcceleratedWidget) {
    scoped_refptr<GLSurface> surface;
    if (GLSurfaceEGL::IsEGLSurfacelessContextSupported())
      surface = CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(window);
    if (!surface)
      surface = CreateViewGLSurfaceOzone(window);
    return surface;
  } else {
    scoped_refptr<GLSurface> surface = new GLSurfaceStub();
    if (surface->Initialize())
      return surface;
  }
  return nullptr;
}

Project: Chrome

scoped_refptr<GLSurface> CreateViewGLSurfaceOzone(
    gfx::AcceleratedWidget window) {
  std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone =
      ui::OzonePlatform::GetInstance()
          ->GetSurfaceFactoryOzone()
          ->CreateEGLSurfaceForWidget(window);
  if (!surface_ozone)
    return nullptr;
  scoped_refptr<GLSurface> surface =
      new GLSurfaceOzoneEGL(std::move(surface_ozone), window);
  if (!surface->Initialize())
    return nullptr;
  return surface;
}

Project: Chrome

scoped_refptr<GLSurface> CreateViewGLSurfaceOzoneSurfacelessSurfaceImpl(
    gfx::AcceleratedWidget window) {
  std::unique_ptr<ui::SurfaceOzoneEGL> surface_ozone =
      ui::OzonePlatform::GetInstance()
          ->GetSurfaceFactoryOzone()
          ->CreateSurfacelessEGLSurfaceForWidget(window);
  if (!surface_ozone)
    return nullptr;
  scoped_refptr<GLSurface> surface = new GLSurfaceOzoneSurfacelessSurfaceImpl(
      std::move(surface_ozone), window);
  if (!surface->Initialize())
    return nullptr;
  return surface;
}

Project: Chrome

bool EglChooseConfig(EGLDisplay display,
                     const int32_t* attribs,
                     EGLConfig* configs,
                     int32_t config_size,
                     int32_t* num_configs) {
  return eglChooseConfig(display, attribs, configs, config_size, num_configs);
}

Project: Chrome

bool EglGetConfigAttribute(EGLDisplay display,
                           EGLConfig config,
                           int32_t attribute,
                           int32_t* value) {
  return eglGetConfigAttrib(display, config, attribute, value);
}

Project: Chrome

void GLSurfaceOzoneSurfaceless::FenceRetired(EGLSyncKHR fence,
                                             PendingFrame* frame) {
  eglDestroySyncKHR(GetDisplay(), fence);
  frame->ready = true;
  SubmitFrame();
}

Project: Chrome

GLSurfaceOzoneEGL::GLSurfaceOzoneEGL(
    std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface,
    AcceleratedWidget widget)
    : NativeViewGLSurfaceEGL(ozone_surface->GetNativeWindow()),
      ozone_surface_(std::move(ozone_surface)),
      widget_(widget) {}

Project: Chrome

GLSurfaceOzoneSurfaceless::GLSurfaceOzoneSurfaceless(
    std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface,
    AcceleratedWidget widget)
    : SurfacelessEGL(gfx::Size()),
      ozone_surface_(std::move(ozone_surface)),
      widget_(widget),
      has_implicit_external_sync_(
          HasEGLExtension("EGL_ARM_implicit_external_sync")),
      last_swap_buffers_result_(true),
      swap_buffers_pending_(false),
      weak_factory_(this) {
  unsubmitted_frames_.push_back(new PendingFrame());
}

Project: Chrome

GLSurfaceOzoneSurfacelessSurfaceImpl::GLSurfaceOzoneSurfacelessSurfaceImpl(
    std::unique_ptr<ui::SurfaceOzoneEGL> ozone_surface,
    AcceleratedWidget widget)
    : GLSurfaceOzoneSurfaceless(std::move(ozone_surface), widget),
      context_(nullptr),
      fbo_(0),
      current_surface_(0) {
  for (auto& texture : textures_)
    texture = 0;
}

Project: Chrome

GLSurfaceOzoneSurfacelessSurfaceImpl::GetBackingFrameBufferObject() {
  return fbo_;
}

Project: Chrome

EGLConfig GLSurfaceOzoneEGL::GetConfig() {
  if (!config_) {
    ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
    config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
  }
  if (config_)
    return config_;
  return NativeViewGLSurfaceEGL::GetConfig();
}

Project: Chrome

EGLConfig GLSurfaceOzoneSurfaceless::GetConfig() {
  if (!config_) {
    ui::EglConfigCallbacks callbacks = GetEglConfigCallbacks(GetDisplay());
    config_ = ozone_surface_->GetEGLSurfaceConfig(callbacks);
  }
  if (config_)
    return config_;
  return SurfacelessEGL::GetConfig();
}

Project: Chrome

ui::EglConfigCallbacks GetEglConfigCallbacks(EGLDisplay display) {
  ui::EglConfigCallbacks callbacks;
  callbacks.choose_config = base::Bind(EglChooseConfig, display);
  callbacks.get_config_attribute = base::Bind(EglGetConfigAttribute, display);
  callbacks.get_last_error_string = base::Bind(&ui::GetLastEGLErrorString);
  return callbacks;
}

Project: Chrome

EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() {
  return ui::OzonePlatform::GetInstance()
      ->GetSurfaceFactoryOzone()
      ->GetNativeDisplay();
}

Project: Chrome

VSyncProvider* GLSurfaceOzoneSurfaceless::GetVSyncProvider() {
  return vsync_provider_.get();
}

Project: Chrome

bool GLSurfaceOzoneEGL::Initialize(gfx::GLSurface::Format format) {
  format_ = format;
  return Initialize(ozone_surface_->CreateVSyncProvider());
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::Initialize(gfx::GLSurface::Format format) {
  if (!SurfacelessEGL::Initialize(format))
    return false;
  vsync_provider_ = ozone_surface_->CreateVSyncProvider();
  if (!vsync_provider_)
    return false;
  return true;
}

Project: Chrome

bool GLSurface::InitializeOneOffInternal() {
  switch (GetGLImplementation()) {
    case kGLImplementationEGLGLES2:
      if (!GLSurfaceEGL::InitializeOneOff()) {
        LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
        return false;
      }

      return true;
    case kGLImplementationOSMesaGL:
    case kGLImplementationMockGL:
      return true;
    default:
      return false;
  }
}

Project: Chrome

EGLSyncKHR GLSurfaceOzoneSurfaceless::InsertFence() {
  const EGLint attrib_list[] = {EGL_SYNC_CONDITION_KHR,
                                EGL_SYNC_PRIOR_COMMANDS_IMPLICIT_EXTERNAL_ARM,
                                EGL_NONE};
  return eglCreateSyncKHR(GetDisplay(), EGL_SYNC_FENCE_KHR, attrib_list);
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::IsOffscreen() {
  return false;
}

Project: Chrome

bool GLSurfaceOzoneSurfacelessSurfaceImpl::IsSurfaceless() const {
  return false;
}

Project: Chrome

GLSurfaceOzoneSurfaceless::PendingFrame::PendingFrame() : ready(false) {}

Project: Chrome

void GLSurfaceOzoneSurfaceless::PostSubBufferAsync(
    int x,
    int y,
    int width,
    int height,
    const SwapCompletionCallback& callback) {
  SwapBuffersAsync(callback);
}

Project: Chrome

bool GLSurfaceOzoneEGL::ReinitializeNativeSurface() {
  std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current;
  GLContext* current_context = GLContext::GetCurrent();
  bool was_current = current_context && current_context->IsCurrent(this);
  if (was_current) {
    scoped_make_current.reset(new ui::ScopedMakeCurrent(current_context, this));
  }

  Destroy();
  ozone_surface_ = ui::OzonePlatform::GetInstance()
                       ->GetSurfaceFactoryOzone()
                       ->CreateEGLSurfaceForWidget(widget_);
  if (!ozone_surface_) {
    LOG(ERROR) << "Failed to create native surface.";
    return false;
  }

  window_ = ozone_surface_->GetNativeWindow();
  if (!Initialize(format_)) {
    LOG(ERROR) << "Failed to initialize.";
    return false;
  }

  return true;
}

Project: Chrome

bool GLSurfaceOzoneEGL::Resize(const gfx::Size& size,
                               float scale_factor,
                               bool has_alpha) {
  if (!ozone_surface_->ResizeNativeWindow(size)) {
    if (!ReinitializeNativeSurface() ||
        !ozone_surface_->ResizeNativeWindow(size))
      return false;
  }

  return NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::Resize(const gfx::Size& size,
                                       float scale_factor,
                                       bool has_alpha) {
  if (!ozone_surface_->ResizeNativeWindow(size))
    return false;

  return SurfacelessEGL::Resize(size, scale_factor, has_alpha);
}

Project: Chrome

bool GLSurfaceOzoneEGL::ScheduleOverlayPlane(int z_order,
                                             OverlayTransform transform,
                                             GLImage* image,
                                             const Rect& bounds_rect,
                                             const RectF& crop_rect) {
  return image->ScheduleOverlayPlane(widget_, z_order, transform, bounds_rect,
                                     crop_rect);
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::ScheduleOverlayPlane(int z_order,
                                                     OverlayTransform transform,
                                                     GLImage* image,
                                                     const Rect& bounds_rect,
                                                     const RectF& crop_rect) {
  unsubmitted_frames_.back()->overlays.push_back(
      GLSurfaceOverlay(z_order, transform, image, bounds_rect, crop_rect));
  return true;
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::PendingFrame::ScheduleOverlayPlanes(
    gfx::AcceleratedWidget widget) {
  for (const auto& overlay : overlays)
    if (!overlay.ScheduleOverlayPlane(widget))
      return false;
  return true;
}

Project: Chrome

void GLSurfaceOzoneSurfaceless::SubmitFrame() {
  DCHECK(!unsubmitted_frames_.empty());

  if (unsubmitted_frames_.front()->ready && !swap_buffers_pending_) {
    std::unique_ptr<PendingFrame> frame(unsubmitted_frames_.front());
    unsubmitted_frames_.weak_erase(unsubmitted_frames_.begin());
    swap_buffers_pending_ = true;

    if (!frame->ScheduleOverlayPlanes(widget_)) {
      frame->callback.Run(gfx::SwapResult::SWAP_FAILED);
      return;
    }

    if (ozone_surface_->IsUniversalDisplayLinkDevice())
      glFinish();

    ozone_surface_->OnSwapBuffersAsync(frame->callback);
  }
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::SupportsAsyncSwap() {
  return true;
}

Project: Chrome

bool GLSurfaceOzoneSurfaceless::SupportsPostSubBuffer() {
  return true;
}

Project: Chrome

bool GLSurfaceOzoneSurfacelessSurfaceImpl::SupportsPostSubBuffer() {
  return false;
}

Project: Chrome

gfx::SwapResult GLSurfaceOzoneEGL::SwapBuffers() {
  gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
  if (result != gfx::SwapResult::SWAP_ACK)
    return result;

  return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
                                         : gfx::SwapResult::SWAP_FAILED;
}

Project: Chrome

gfx::SwapResult GLSurfaceOzoneSurfaceless::SwapBuffers() {
  glFlush();
  if (has_implicit_external_sync_) {
    EGLSyncKHR fence = InsertFence();
    if (!fence)
      return SwapResult::SWAP_FAILED;

    EGLDisplay display = GetDisplay();
    WaitForFence(display, fence);
    eglDestroySyncKHR(display, fence);
  }

  unsubmitted_frames_.back()->ScheduleOverlayPlanes(widget_);
  unsubmitted_frames_.back()->overlays.clear();

  if (ozone_surface_->IsUniversalDisplayLinkDevice())
    glFinish();

  return ozone_surface_->OnSwapBuffers() ? gfx::SwapResult::SWAP_ACK
                                         : gfx::SwapResult::SWAP_FAILED;
}

Project: Chrome

gfx::SwapResult GLSurfaceOzoneSurfacelessSurfaceImpl::SwapBuffers() {
  if (!images_[current_surface_]->ScheduleOverlayPlane(
          widget_, 0, OverlayTransform::OVERLAY_TRANSFORM_NONE,
          gfx::Rect(GetSize()), gfx::RectF(1, 1)))
    return gfx::SwapResult::SWAP_FAILED;
  gfx::SwapResult result = GLSurfaceOzoneSurfaceless::SwapBuffers();
  if (result != gfx::SwapResult::SWAP_ACK)
    return result;
  current_surface_ ^= 1;
  BindFramebuffer();
  return gfx::SwapResult::SWAP_ACK;
}

Project: Chrome

void GLSurfaceOzoneSurfaceless::SwapBuffersAsync(
    const SwapCompletionCallback& callback) {
  if (!last_swap_buffers_result_) {
    callback.Run(gfx::SwapResult::SWAP_FAILED);
    return;
  }

  glFlush();

  SwapCompletionCallback surface_swap_callback =
      base::Bind(&GLSurfaceOzoneSurfaceless::SwapCompleted,
                 weak_factory_.GetWeakPtr(), callback);

  PendingFrame* frame = unsubmitted_frames_.back();
  frame->callback = surface_swap_callback;
  unsubmitted_frames_.push_back(new PendingFrame());

  if (has_implicit_external_sync_) {
    EGLSyncKHR fence = InsertFence();
    if (!fence) {
      callback.Run(gfx::SwapResult::SWAP_FAILED);
      return;
    }

    base::Closure fence_wait_task =
        base::Bind(&WaitForFence, GetDisplay(), fence);

    base::Closure fence_retired_callback =
        base::Bind(&GLSurfaceOzoneSurfaceless::FenceRetired,
                   weak_factory_.GetWeakPtr(), fence, frame);

    base::WorkerPool::PostTaskAndReply(FROM_HERE, fence_wait_task,
                                       fence_retired_callback, false);
    return;  // Defer frame submission until fence signals.
  }

  frame->ready = true;
  SubmitFrame();
}

Project: Chrome

void GLSurfaceOzoneSurfaceless::SwapCompleted(
    const SwapCompletionCallback& callback,
    gfx::SwapResult result) {
  callback.Run(result);
  swap_buffers_pending_ = false;
  if (result == gfx::SwapResult::SWAP_FAILED) {
    last_swap_buffers_result_ = false;
    return;
  }

  SubmitFrame();
}

Project: Chrome

void WaitForFence(EGLDisplay display, EGLSyncKHR fence) {
  eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
                       EGL_FOREVER_KHR);
}

Project: Chrome

GLSurfaceOzoneSurfaceless::~GLSurfaceOzoneSurfaceless() {
  Destroy();  // The EGL surface must be destroyed before SurfaceOzone.
}

Project: Chrome

GLSurfaceOzoneSurfacelessSurfaceImpl::~GLSurfaceOzoneSurfacelessSurfaceImpl() {
  Destroy();
}