| |
| #include "flutter/shell/platform/android/hardware_buffer_external_texture.h" |
| |
| #include <android/hardware_buffer_jni.h> |
| #include <android/sensor.h> |
| #include "shell/platform/android/ndk_helpers.h" |
| |
| namespace flutter { |
| |
| HardwareBufferExternalTexture::HardwareBufferExternalTexture( |
| int64_t id, |
| const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry, |
| const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade) |
| : Texture(id), |
| image_texture_entry_(image_texture_entry), |
| jni_facade_(jni_facade) {} |
| |
| // Implementing flutter::Texture. |
| void HardwareBufferExternalTexture::Paint(PaintContext& context, |
| const SkRect& bounds, |
| bool freeze, |
| const DlImageSampling sampling) { |
| if (state_ == AttachmentState::kDetached) { |
| return; |
| } |
| const bool should_process_frame = |
| (!freeze && new_frame_ready_) || dl_image_ == nullptr; |
| if (should_process_frame) { |
| ProcessFrame(context, bounds); |
| new_frame_ready_ = false; |
| } |
| if (dl_image_) { |
| context.canvas->DrawImageRect( |
| dl_image_, // image |
| SkRect::Make(dl_image_->bounds()), // source rect |
| bounds, // destination rect |
| sampling, // sampling |
| context.paint, // paint |
| flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges |
| ); |
| } else { |
| FML_LOG(ERROR) << "No DlImage available."; |
| } |
| } |
| |
| // Implementing flutter::Texture. |
| void HardwareBufferExternalTexture::MarkNewFrameAvailable() { |
| new_frame_ready_ = true; |
| } |
| |
| // Implementing flutter::Texture. |
| void HardwareBufferExternalTexture::OnTextureUnregistered() {} |
| |
| // Implementing flutter::ContextListener. |
| void HardwareBufferExternalTexture::OnGrContextCreated() { |
| state_ = AttachmentState::kUninitialized; |
| } |
| |
| AHardwareBuffer* HardwareBufferExternalTexture::GetLatestHardwareBuffer() { |
| JNIEnv* env = fml::jni::AttachCurrentThread(); |
| FML_CHECK(env != nullptr); |
| |
| // ImageTextureEntry.acquireLatestImage. |
| JavaLocalRef image_java = jni_facade_->ImageTextureEntryAcquireLatestImage( |
| JavaLocalRef(image_texture_entry_)); |
| if (image_java.obj() == nullptr) { |
| return nullptr; |
| } |
| |
| // Image.getHardwareBuffer. |
| JavaLocalRef hardware_buffer_java = |
| jni_facade_->ImageGetHardwareBuffer(image_java); |
| if (hardware_buffer_java.obj() == nullptr) { |
| jni_facade_->ImageClose(image_java); |
| return nullptr; |
| } |
| |
| // Convert into NDK HardwareBuffer. |
| AHardwareBuffer* latest_hardware_buffer = |
| NDKHelpers::AHardwareBuffer_fromHardwareBuffer( |
| env, hardware_buffer_java.obj()); |
| if (latest_hardware_buffer == nullptr) { |
| return nullptr; |
| } |
| |
| // Keep hardware buffer alive. |
| NDKHelpers::AHardwareBuffer_acquire(latest_hardware_buffer); |
| |
| // Now that we have referenced the native hardware buffer, close the Java |
| // Image and HardwareBuffer objects. |
| jni_facade_->HardwareBufferClose(hardware_buffer_java); |
| jni_facade_->ImageClose(image_java); |
| |
| return latest_hardware_buffer; |
| } |
| |
| // Implementing flutter::ContextListener. |
| void HardwareBufferExternalTexture::OnGrContextDestroyed() { |
| if (state_ == AttachmentState::kAttached) { |
| dl_image_.reset(); |
| Detach(); |
| } |
| state_ = AttachmentState::kDetached; |
| } |
| |
| } // namespace flutter |