Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Reenable HardwareBuffer backed Android Platform Views on SDK >= 29 #44790

Merged
merged 2 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion shell/platform/android/hardware_buffer_external_texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ void HardwareBufferExternalTexture::Paint(PaintContext& context,
flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges
);
} else {
FML_LOG(WARNING) << "No DlImage available.";
FML_LOG(WARNING)
<< "No DlImage available for HardwareBufferExternalTexture to paint.";
Comment on lines +42 to +43
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the developer action to take here?

If there is none, maybe this should be a DLOG/DCHECK?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is useful information for debugging the engine and I'd like to keep it in place for now until this code is more solid.

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ public void run() {

@Keep
final class ImageTextureRegistryEntry implements TextureRegistry.ImageTextureEntry {
private static final String TAG = "ImageTextureRegistryEntry";
private final long id;
private boolean released;
private Image image;
Expand Down Expand Up @@ -356,8 +357,10 @@ public void pushImage(Image image) {
if (toClose != null) {
toClose.close();
}
// Mark that we have a new frame available.
markTextureFrameAvailable(id);
if (image != null) {
// Mark that we have a new frame available.
markTextureFrameAvailable(id);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,24 @@
import android.view.Surface;
import io.flutter.view.TextureRegistry.ImageTextureEntry;

@TargetApi(26)
@TargetApi(29)
public class ImageReaderPlatformViewRenderTarget implements PlatformViewRenderTarget {
private ImageTextureEntry textureEntry;
private boolean mustRecreateImageReader = false;
private ImageReader reader;
private int bufferWidth = 0;
private int bufferHeight = 0;
private static final String TAG = "ImageReaderPlatformViewRenderTarget";

private void closeReader() {
if (this.reader != null) {
// Push a null image, forcing the texture entry to close any cached images.
textureEntry.pushImage(null);
// Close the reader, which also closes any produced images.
this.reader.close();
this.reader = null;
}
}

private void recreateImageReaderIfNeeded() {
if (!mustRecreateImageReader) {
return;
}
mustRecreateImageReader = false;
closeReader();
this.reader = createImageReader();
}

private final Handler onImageAvailableHandler = new Handler();
private final ImageReader.OnImageAvailableListener onImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
Expand All @@ -55,9 +48,12 @@ protected ImageReader createImageReader33() {
// Allow for double buffering.
builder.setMaxImages(3);
// Use PRIVATE image format so that we can support video decoding.
// TODO(johnmccutchan): Should we always use PRIVATE here? It may impact our ability
// to read back texture data. If we don't always want to use it, how do we decide when
// to use it or not? Perhaps PlatformViews can indicate if they may contain DRM'd content.
// TODO(johnmccutchan): Should we always use PRIVATE here? It may impact our
// ability to read back texture data. If we don't always want to use it, how do we
// decide when to use it or not? Perhaps PlatformViews can indicate if they may contain
// DRM'd content.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: formatting
nit: please link an issue here explaining what has to be done (even if just what investigation is left to do or what resources someone interested in this should read about)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed added more context to the TODO.

// I need to investigate how PRIVATE impacts our ability to take screenshots or capture
// the output of Flutter application.
builder.setImageFormat(ImageFormat.PRIVATE);
// Hint that consumed images will only be read by GPU.
builder.setUsage(HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
Expand All @@ -68,29 +64,31 @@ protected ImageReader createImageReader33() {

@TargetApi(29)
protected ImageReader createImageReader29() {
return ImageReader.newInstance(
bufferWidth, bufferHeight, ImageFormat.PRIVATE, 2, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
}

@TargetApi(26)
protected ImageReader createImageReader26() {
return ImageReader.newInstance(bufferWidth, bufferHeight, ImageFormat.PRIVATE, 2);
final ImageReader reader =
ImageReader.newInstance(
bufferWidth,
bufferHeight,
ImageFormat.PRIVATE,
2,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE);
reader.setOnImageAvailableListener(this.onImageAvailableListener, onImageAvailableHandler);
return reader;
}

protected ImageReader createImageReader() {
if (Build.VERSION.SDK_INT >= 33) {
return createImageReader33();
} else if (Build.VERSION.SDK_INT >= 29) {
return createImageReader29();
} else {
return createImageReader26();
}
throw new UnsupportedOperationException(
"ImageReaderPlatformViewRenderTarget requires API version 29+");
}

public ImageReaderPlatformViewRenderTarget(ImageTextureEntry textureEntry) {
if (Build.VERSION.SDK_INT < 26) {
if (Build.VERSION.SDK_INT < 29) {
throw new UnsupportedOperationException(
"ImageReaderPlatformViewRenderTarget requires API version 26+");
"ImageReaderPlatformViewRenderTarget requires API version 29+");
}
this.textureEntry = textureEntry;
}
Expand Down Expand Up @@ -127,17 +125,16 @@ public long getId() {
}

public void release() {
closeReader();
// textureEntry has a finalizer attached.
textureEntry = null;
closeReader();
}

public boolean isReleased() {
return this.textureEntry == null;
}

public Surface getSurface() {
recreateImageReaderIfNeeded();
return this.reader.getSurface();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -968,8 +968,7 @@ private void unlockInputConnection(@NonNull VirtualDisplayController controller)

private static PlatformViewRenderTarget makePlatformViewRenderTarget(
TextureRegistry textureRegistry) {
// TODO(johnmccutchan): Enable ImageReaderPlatformViewRenderTarget for public use.
if (false) {
if (Build.VERSION.SDK_INT >= 29) {
final TextureRegistry.ImageTextureEntry textureEntry = textureRegistry.createImageTexture();
return new ImageReaderPlatformViewRenderTarget(textureEntry);
}
Expand Down
3 changes: 2 additions & 1 deletion shell/platform/android/surface_texture_external_texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ void SurfaceTextureExternalTexture::Paint(PaintContext& context,
flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges
);
} else {
FML_LOG(WARNING) << "No DlImage available.";
FML_LOG(WARNING)
<< "No DlImage available for SurfaceTextureExternalTexture to paint.";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto on log message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

}
}

Expand Down