Example #1
0
EGLint EglDisplayImpl::MakeCurrent(EGLContext egl_ctx, EGLSurface egl_draw,
                                   EGLSurface egl_read) {
  if (egl_read != egl_draw) {
    LOG_ALWAYS_FATAL("Read and draw surfaces must be the same.");
    return EGL_BAD_MATCH;
  }

  ContextPtr ctx = contexts_.Get(egl_ctx);
  SurfacePtr sfc = surfaces_.Get(egl_draw);

  bool release = ctx == NULL && sfc == NULL;
  // If a context is being set, then a surface must be set.  Similarly, if a
  // context is being cleared, the surface must be cleared.  Any other
  // combination is an error.
  const bool invalid_surface = ctx != NULL ? sfc == NULL : sfc != NULL;
  if (!release && invalid_surface) {
    return EGL_BAD_MATCH;
  }

  EglThreadInfo& info = EglThreadInfo::GetInstance();
  ContextPtr prev_ctx = info.GetCurrentContext();
  SurfacePtr prev_sfc =
      prev_ctx != NULL ? prev_ctx->GetSurface() : SurfacePtr();

  if (release) {
    if (prev_ctx != NULL) {
      prev_ctx->Flush();
      info.SetCurrentContext(ContextPtr());
    }
  } else {
    if (ctx == NULL) {
      return EGL_BAD_CONTEXT;
    }
    if (ctx->config != sfc->config) {
      return EGL_BAD_MATCH;
    }
    if (ctx != NULL && prev_ctx != NULL) {
      if (ctx == prev_ctx) {
        if (sfc == prev_sfc) {
            // Reassigning the same context and surface.
            return EGL_SUCCESS;
        }
      } else {
        // Make sure to clear the previous context.
        release = true;
      }
    }

    if (prev_ctx != NULL) {
      prev_ctx->Flush();
    }

    if (!ctx->SetCurrent()) {
      return EGL_BAD_ACCESS;
    }

    info.SetCurrentContext(ctx);
    ctx->SetSurface(sfc);
  }

  if (prev_ctx != NULL && release) {
    prev_ctx->ClearCurrent();
    prev_ctx->ClearSurface();
  }
  return EGL_SUCCESS;
}