From 5462cc0fcf8c6e8fdda8eada0c5cfaac455ff21e Mon Sep 17 00:00:00 2001
From: Mathias Agopian Typically After calling this method, the callback associated with
+ * The following format are always supported:
+ *
+ *
+ * Framebuffer as seen on User buffer (PixelBufferDescriptor)
+ * screen
+ * +--------------------+
+ * | | .stride .alignment
+ * | | ----------------------->-->
+ * | | O----------------------+--+ low addresses
+ * | | | | | |
+ * | w | | | .top | |
+ * | <---------> | | V | |
+ * | +---------+ | | +---------+ | |
+ * | | ^ | | ======> | | | | |
+ * | x | h| | | |.left| | | |
+ * +------>| v | | +---->| | | |
+ * | +.........+ | | +.........+ | |
+ * | ^ | | | |
+ * | y | | +----------------------+--+ high addresses
+ * O------------+-------+
+ *
+ *
+ *
+ *
+ * readPixels will be called after {@link #render} and before
+ * {@link #endFrame}.
+ * buffer
+ * will be invoked on the main thread, indicating that the read-back has completed.
+ * Typically, this will happen after multiple calls to {@link #beginFrame},
+ * {@link #render}, {@link #endFrame}.
+ * readPixels is intended for debugging and testing.
+ * It will impact performance significantly.
+ * The following types are always supported: + *
Other combination of format/type may be supported. If a combination is + * not supported, this operation may fail silently. Use a DEBUG build + * to get some logs about the failure.
+ * + * @exception BufferOverflowException if the specified parameters would result in reading + * outside ofbuffer.
+ */
+ public void readPixels(
+ @NonNull RenderTarget renderTarget,
+ @IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
+ @IntRange(from = 0) int width, @IntRange(from = 0) int height,
+ @NonNull Texture.PixelBufferDescriptor buffer) {
+
+ if (buffer.storage.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ }
+
+ int result = nReadPixelsEx(getNativeObject(), mEngine.getNativeObject(),
+ renderTarget.getNativeObject(),
+ xoffset, yoffset, width, height,
+ buffer.storage, buffer.storage.remaining(),
+ buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
+ buffer.stride, buffer.format.ordinal(),
+ buffer.handler, buffer.callback);
+
+ if (result < 0) {
+ throw new BufferOverflowException();
+ }
+ }
+
/**
* Returns a timestamp (in seconds) for the last call to {@link #beginFrame}. This value is
* constant for all {@link View views} rendered during a frame. The epoch is set with
@@ -386,6 +474,12 @@ public class Renderer {
Buffer storage, int remaining,
int left, int top, int type, int alignment, int stride, int format,
Object handler, Runnable callback);
+ private static native int nReadPixelsEx(long nativeRenderer, long nativeEngine,
+ long nativeRenderTarget,
+ int xoffset, int yoffset, int width, int height,
+ Buffer storage, int remaining,
+ int left, int top, int type, int alignment, int stride, int format,
+ Object handler, Runnable callback);
private static native double nGetUserTime(long nativeRenderer);
private static native void nResetUserTime(long nativeRenderer);
}
diff --git a/filament/include/filament/Renderer.h b/filament/include/filament/Renderer.h
index cc3ea38dad..f9c9811fcc 100644
--- a/filament/include/filament/Renderer.h
+++ b/filament/include/filament/Renderer.h
@@ -31,6 +31,7 @@
namespace filament {
class Engine;
+class RenderTarget;
class SwapChain;
class View;
@@ -190,7 +191,7 @@ public:
Viewport const& srcViewport, uint32_t flags = 0);
/**
- * Read-back the content of the SwapChain associated with this Renderer.
+ * Reads back the content of the SwapChain associated with this Renderer.
*
* @param xoffset Left offset of the sub-region to read back.
* @param yoffset Bottom offset of the sub-region to read back.
@@ -247,6 +248,67 @@ public:
void readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
backend::PixelBufferDescriptor&& buffer);
+
+ /**
+ * Reads back the content of the provided RenderTarget.
+ *
+ * @param renderTarget RenderTarget to read back from.
+ * @param xoffset Left offset of the sub-region to read back.
+ * @param yoffset Bottom offset of the sub-region to read back.
+ * @param width Width of the sub-region to read back.
+ * @param height Height of the sub-region to read back.
+ * @param buffer Client-side buffer where the read-back will be written.
+ *
+ * The following format are always supported:
+ * - PixelBufferDescriptor::PixelDataFormat::RGBA
+ * - PixelBufferDescriptor::PixelDataFormat::RGBA_INTEGER
+ *
+ * The following types are always supported:
+ * - PixelBufferDescriptor::PixelDataType::UBYTE
+ * - PixelBufferDescriptor::PixelDataType::UINT
+ * - PixelBufferDescriptor::PixelDataType::INT
+ * - PixelBufferDescriptor::PixelDataType::FLOAT
+ *
+ * Other combination of format/type may be supported. If a combination is
+ * not supported, this operation may fail silently. Use a DEBUG build
+ * to get some logs about the failure.
+ *
+ *
+ * Framebuffer as seen on User buffer (PixelBufferDescriptor&)
+ * screen
+ * +--------------------+
+ * | | .stride .alignment
+ * | | ----------------------->-->
+ * | | O----------------------+--+ low addresses
+ * | | | | | |
+ * | w | | | .top | |
+ * | <---------> | | V | |
+ * | +---------+ | | +---------+ | |
+ * | | ^ | | ======> | | | | |
+ * | x | h| | | |.left| | | |
+ * +------>| v | | +---->| | | |
+ * | +.........+ | | +.........+ | |
+ * | ^ | | | |
+ * | y | | +----------------------+--+ high addresses
+ * O------------+-------+
+ *
+ *
+ * Typically readPixels() will be called after render() and before endFrame().
+ *
+ * After issuing this method, the callback associated with `buffer` will be invoked on the
+ * main thread, indicating that the read-back has completed. Typically, this will happen
+ * after multiple calls to beginFrame(), render(), endFrame().
+ *
+ * It is also possible to use a Fence to wait for the read-back.
+ *
+ * @remark
+ * readPixels() is intended for debugging and testing. It will impact performance significantly.
+ *
+ */
+ void readPixels(RenderTarget* renderTarget,
+ uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
+ backend::PixelBufferDescriptor&& buffer);
+
/**
* Set-up a frame for this Renderer.
*
diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp
index 9f0216fd27..98b49b95e3 100644
--- a/filament/src/Renderer.cpp
+++ b/filament/src/Renderer.cpp
@@ -581,7 +581,18 @@ void FRenderer::endFrame() {
void FRenderer::readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
PixelBufferDescriptor&& buffer) {
+ readPixels(mRenderTarget, xoffset, yoffset, width, height, std::move(buffer));
+}
+void FRenderer::readPixels(FRenderTarget* renderTarget,
+ uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
+ backend::PixelBufferDescriptor&& buffer) {
+ readPixels(renderTarget->getHwHandle(), xoffset, yoffset, width, height, std::move(buffer));
+}
+
+void FRenderer::readPixels(Handle