Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8226947

Add native rendering support by supporting WritableImages backed by NIO ByteBuffers

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P3 P3
    • jfx13
    • javafx
    • None
    • minimal
    • This adds new Class and a new Constructor to existing class, which will not affect any existing behavior.
    • Java API
    • JDK

      Summary

      Add support to share pixel data buffer between WritableImages.

      Problem

      • WritableImage creates its own buffer to store pixel data. This buffer is not accessible to programmer and can not be shared between WritableImages.
      • Rendering an externally created buffer to WritableImage requires copying of entire buffer or the modified part of the buffer into the WritableImage's internal pixel data buffer.
      • This is a very costly operation for a frequently updating buffer.

      Solution

      • Create WritableImages which can share pixel data buffer.
      • Use java.nio.Buffer to store the pixel data.
      • Only java.nio.IntBuffer and java.nio.ByteBuffer are sufficient to handle different PixelFormats.

      Specification

      Added a new javafx.scene.image.PixelBuffer class:

      /**
       * The {@code PixelBuffer} class represents pixel data that is constructed from
       * a {@link Buffer java.nio.Buffer} supplied by the application.
       * A {@link WritableImage} can use this {@code PixelBuffer} directly without copying the pixel data.
       * This {@code PixelBuffer} can be shared among multiple {@code WritableImage}s.
       * Pixel data should be stored either in an {@link IntBuffer} using a {@link PixelFormat} of type
       * {@code INT_ARGB_PRE} or in a {@link ByteBuffer} using a {@link PixelFormat} of type {@code BYTE_BGRA_PRE}.
       * When the {@code Buffer} is updated using the {@link #updateBuffer PixelBuffer.updateBuffer} method,
       * all {@code WritableImage}s that were created using this {@code PixelBuffer} are redrawn.
       * <p>
       * Example code that shows how to create a {@code PixelBuffer}:
       * <pre>{@code  // Creating a PixelBuffer using BYTE_BGRA_PRE pixel format.
       * ByteBuffer byteBuffer = ByteBuffer.allocateDirect(width * height * 4);
       * PixelFormat<ByteBuffer> pixelFormat = PixelFormat.getByteBgraPreInstance();
       * PixelBuffer<ByteBuffer> pixelBuffer = new PixelBuffer<>(width, height, byteBuffer, pixelFormat);
       * Image img = new WritableImage(pixelBuffer);
       *
       * // Creating a PixelBuffer using INT_ARGB_PRE pixel format.
       * IntBuffer intBuffer = IntBuffer.allocate(width * height);
       * PixelFormat<IntBuffer> pixelFormat = PixelFormat.getIntArgbPreInstance();
       * PixelBuffer<IntBuffer> pixelBuffer = new PixelBuffer<>(width, height, intBuffer, pixelFormat);
       * Image img = new WritableImage(pixelBuffer);}</pre>
       *
       * @param <T> the type of {@code Buffer} that stores the pixel data.
       *           Only {@code ByteBuffer} and {@code IntBuffer} are supported.
       * @see WritableImage#WritableImage(PixelBuffer)
       * @since 13
       */
      public class PixelBuffer<T extends Buffer> {...}
      
      /**
       * Constructs a {@code PixelBuffer} using the specified {@code Buffer} and {@code PixelFormat}.
       * The type of the specified {@code PixelFormat} must be either {@code PixelFormat.Type.INT_ARGB_PRE}
       * or {@code PixelFormat.Type.BYTE_BGRA_PRE}.
       * <p>The constructor does not allocate memory to store the pixel data. The application must provide
       * a buffer with sufficient memory for the combination of dimensions {@code (width, height)} and the type
       * of {@code PixelFormat}. The {@code PixelFormat.Type.INT_ARGB_PRE} requires an {@code IntBuffer} with
       * minimum capacity of {@code width * height}, and the {@code PixelFormat.Type.BYTE_BGRA_PRE} requires
       * a {@code ByteBuffer} with minimum capacity of {@code width * height * 4}.
       *
       * @param width       width in pixels of this {@code PixelBuffer}
       * @param height      height in pixels of this {@code PixelBuffer}
       * @param buffer      the buffer that stores the pixel data
       * @param pixelFormat the format of pixels in the {@code buffer}
       * @throws IllegalArgumentException if either {@code width} or {@code height}
       *                                  is negative or zero, or if the type of {@code pixelFormat}
       *                                  is unsupported, or if {@code buffer} does
       *                                  not have sufficient memory, or if the type of {@code buffer}
       *                                  and {@code pixelFormat} do not match
       * @throws NullPointerException     if {@code buffer} or {@code pixelFormat} is {@code null}
       */
      public PixelBuffer(int width, int height, T buffer, PixelFormat<T> pixelFormat) {...}
      
      
      /**
       * Returns the {@code buffer} of this {@code PixelBuffer}.
       *
       * @return the {@code buffer} of this {@code PixelBuffer}
       */
      public T getBuffer() {...}
      
      /**
       * Returns the {@code width} of this {@code PixelBuffer}.
       *
       * @return the {@code width} of this {@code PixelBuffer}
       */
      public int getWidth() {...}
      
      /**
       * Returns the {@code height} of this {@code PixelBuffer}.
       *
       * @return the {@code height} of this {@code PixelBuffer}
       */
      public int getHeight() {...}
      
      /**
       * Returns the {@code PixelFormat} of this {@code PixelBuffer}.
       *
       * @return the {@code PixelFormat} of this {@code PixelBuffer}
       */
      public PixelFormat<T> getPixelFormat() {...}
      
      /**
       * Invokes the specified {@code Callback} method and updates the dirty region of
       * all {@code WritableImage}s that were created using this {@code PixelBuffer}.
       * The {@code Callback} method is expected to update the buffer and
       * return a {@code Rectangle2D} that encloses the dirty region, or
       * return {@code null} to indicate that the entire buffer is dirty.
       * <p>This method must be called on the JavaFX Application Thread.
       * <p>Example code that shows how to use this method:
       * <pre>{@code  Callback<PixelBuffer<ByteBuffer>, Rectangle2D> callback = pixelBuffer -> {
       *     ByteBuffer buffer = pixelBuffer.getBuffer();
       *     // Update the buffer.
       *     return new Rectangle2D(x, y, dirtyWidth, dirtyHeight);
       * };
       * pixelBuffer.updateBuffer(callback);}</pre>
       *
       * @param callback the {@code Callback} method that updates the buffer
       * @throws IllegalStateException if this method is called on a thread
       *                               other than the JavaFX Application Thread.
       * @throws NullPointerException  if {@code callback} is {@code null}
       **/
      public void updateBuffer(Callback<PixelBuffer<T>, Rectangle2D> callback) {...}

      Added a new Constructor to WritableImage class,

      /**
       * Constructs a {@code WritableImage} using the specified {@code PixelBuffer}.
       * The {@code Buffer} provided by the {@code PixelBuffer} will be used
       * directly as the pixel data for this image.
       * The {@code PixelBuffer} can be shared by multiple {@code WritableImage}s.
       * Images constructed this way are readable using {@code Image.getPixelReader()},
       * but are not writable using {@code WritableImage.getPixelWriter()}.
       *
       * @param pixelBuffer the {@code PixelBuffer} used to construct this image
       * @throws NullPointerException if {@code pixelBuffer} is {@code null}
       * @since 13
       */
      public WritableImage(@NamedArg("PixelBuffer") PixelBuffer<? extends Buffer> pixelBuffer) {...}

      Modified the javadoc of WritableImage.getPixelWriter() from:

      /**
       * This method returns a {@code PixelWriter} that provides access to
       * write the pixels of the image.
       *
       * @return the {@code PixelWriter} for writing pixels to the image
       */
      public final PixelWriter getPixelWriter() {...}

      to:

      /**
       * This method returns a {@code PixelWriter} that provides access to
       * write the pixels of the image. This method is not supported for
       * images constructed using a {@code PixelBuffer}.
       *
       * @return the {@code PixelWriter} for writing pixels to the image
       * @throws UnsupportedOperationException if this image was created using a {@code PixelBuffer}
       */
      public final PixelWriter getPixelWriter() {...}

            arapte Ambarish Rapte
            webbuggrp Webbug Group
            Kevin Rushforth
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: