#include "gpu/ipc/service/image_transport_surface.h"
#include <android/native_window_jni.h>
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/scoped_java_ref.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/functional/overloaded.h"
#include "base/logging.h"
#include "base/task/single_thread_task_runner.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/config/gpu_finch_features.h"
#include "gpu/ipc/common/gpu_surface_lookup.h"
#include "gpu/ipc/service/pass_through_image_transport_surface.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "ui/gl/android/scoped_a_native_window.h"
#include "ui/gl/gl_surface_egl.h"
#include "ui/gl/gl_surface_egl_surface_control.h"
#include "ui/gl/gl_surface_stub.h"
namespace gpu {
scoped_refptr<gl::Presenter> ImageTransportSurface::CreatePresenter(
gl::GLDisplay* display,
base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
SurfaceHandle surface_handle,
gl::GLSurfaceFormat format) {
if (gl::GetGLImplementation() == gl::kGLImplementationMockGL ||
gl::GetGLImplementation() == gl::kGLImplementationStubGL)
return nullptr;
if (!delegate ||
!delegate->GetFeatureInfo()->feature_flags().android_surface_control) {
return nullptr;
}
DCHECK(GpuSurfaceLookup::GetInstance());
DCHECK_NE(surface_handle, kNullSurfaceHandle);
bool can_be_used_with_surface_control = false;
auto surface_variant = GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(
surface_handle, &can_be_used_with_surface_control);
if (!can_be_used_with_surface_control) {
return nullptr;
}
scoped_refptr<gl::Presenter> presenter;
absl::visit(
base::Overloaded{[&](gl::ScopedJavaSurface&& scoped_java_surface) {
gl::ScopedANativeWindow window(scoped_java_surface);
if (!window) {
LOG(WARNING) << "Failed to acquire ANativeWindow";
return;
}
presenter = new gl::GLSurfaceEGLSurfaceControl(
std::move(window),
base::SingleThreadTaskRunner::GetCurrentDefault());
},
[&](gl::ScopedJavaSurfaceControl&& surface_control) {
presenter = new gl::GLSurfaceEGLSurfaceControl(
std::move(surface_control),
base::SingleThreadTaskRunner::GetCurrentDefault());
}},
std::move(surface_variant));
return presenter;
}
scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeGLSurface(
gl::GLDisplay* display,
base::WeakPtr<ImageTransportSurfaceDelegate> delegate,
SurfaceHandle surface_handle,
gl::GLSurfaceFormat format) {
if (gl::GetGLImplementation() == gl::kGLImplementationMockGL ||
gl::GetGLImplementation() == gl::kGLImplementationStubGL)
return new gl::GLSurfaceStub;
DCHECK(GpuSurfaceLookup::GetInstance());
DCHECK_NE(surface_handle, kNullSurfaceHandle);
bool can_be_used_with_surface_control = false;
auto surface_variant = GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(
surface_handle, &can_be_used_with_surface_control);
if (!absl::holds_alternative<gl::ScopedJavaSurface>(surface_variant)) {
LOG(WARNING) << "Expected Java Surface";
return nullptr;
}
gl::ScopedJavaSurface& scoped_java_surface =
absl::get<gl::ScopedJavaSurface>(surface_variant);
gl::ScopedANativeWindow window(scoped_java_surface);
if (!window) {
LOG(WARNING) << "Failed to acquire ANativeWindow";
return nullptr;
}
scoped_refptr<gl::GLSurface> surface = new gl::NativeViewGLSurfaceEGL(
display->GetAs<gl::GLDisplayEGL>(), std::move(window), nullptr);
bool initialize_success = surface->Initialize(format);
if (!initialize_success)
return scoped_refptr<gl::GLSurface>();
return scoped_refptr<gl::GLSurface>(
new PassThroughImageTransportSurface(delegate, surface.get(), false));
}
}