| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/ipc/service/image_transport_surface.h" |
| |
| #include <android/native_window_jni.h> |
| |
| #include <utility> |
| #include <variant> |
| |
| #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/logging.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "gpu/config/gpu_finch_features.h" |
| #include "gpu/ipc/common/gpu_surface_lookup.h" |
| #include "third_party/abseil-cpp/absl/functional/overload.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 { |
| |
| // static |
| scoped_refptr<gl::Presenter> ImageTransportSurface::CreatePresenter( |
| scoped_refptr<SharedContextState> context_state, |
| const GpuDriverBugWorkarounds& workarounds, |
| const GpuFeatureInfo& gpu_feature_info, |
| SurfaceHandle surface_handle) { |
| if (gl::GetGLImplementation() == gl::kGLImplementationMockGL || |
| gl::GetGLImplementation() == gl::kGLImplementationStubGL) |
| return nullptr; |
| |
| if (!features::IsAndroidSurfaceControlEnabled()) { |
| return nullptr; |
| } |
| |
| DCHECK(GpuSurfaceLookup::GetInstance()); |
| DCHECK_NE(surface_handle, kNullSurfaceHandle); |
| // On Android, the surface_handle is the id of the surface in the |
| // GpuSurfaceTracker/GpuSurfaceLookup |
| auto surface_record = |
| GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_handle); |
| |
| if (!surface_record.can_be_used_with_surface_control) { |
| return nullptr; |
| } |
| |
| scoped_refptr<gl::Presenter> presenter; |
| std::visit( |
| absl::Overload{[&](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_record.surface_variant)); |
| |
| return presenter; |
| } |
| |
| // static |
| scoped_refptr<gl::GLSurface> ImageTransportSurface::CreateNativeGLSurface( |
| gl::GLDisplay* display, |
| SurfaceHandle surface_handle, |
| gl::GLSurfaceFormat format) { |
| if (gl::GetGLImplementation() == gl::kGLImplementationMockGL || |
| gl::GetGLImplementation() == gl::kGLImplementationStubGL) { |
| return base::MakeRefCounted<gl::GLSurfaceStub>(); |
| } |
| |
| // For some unittests, we will using ANGLE with Null ANGLE backend, in this |
| // case, we need to use SurfacelessEGL. |
| if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE && |
| gl::GetANGLEImplementation() == gl::ANGLEImplementation::kNull) { |
| auto surface = base::MakeRefCounted<gl::SurfacelessEGL>( |
| display->GetAs<gl::GLDisplayEGL>(), gfx::Size()); |
| if (!surface->Initialize(format)) { |
| return nullptr; |
| } |
| return surface; |
| } |
| |
| DCHECK(GpuSurfaceLookup::GetInstance()); |
| DCHECK_NE(surface_handle, kNullSurfaceHandle); |
| |
| // On Android, the surface_handle is the id of the surface in the |
| // GpuSurfaceTracker/GpuSurfaceLookup |
| auto surface_record = |
| GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(surface_handle); |
| if (!std::holds_alternative<gl::ScopedJavaSurface>( |
| surface_record.surface_variant)) { |
| LOG(WARNING) << "Expected Java Surface"; |
| return nullptr; |
| } |
| gl::ScopedJavaSurface& scoped_java_surface = |
| std::get<gl::ScopedJavaSurface>(surface_record.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 surface; |
| } |
| |
| } // namespace gpu |