On Fri, 4 Sep 2026 22:17:44 GMT, John Hendrikx <[email protected]> wrote:

>> This PR adds a `getDrawingContext` method to `WritableImage`, which works 
>> similar to `Canvas::getGraphicsContext` and shares the same signatures. Key 
>> features include:
>> 
>> - **Shape rendering**: `strokeRect`, `fillRect`, `strokeOval`, `fillOval`, 
>> `strokeArc`, `fillArc`, `strokePolyline`, `fillPolygon`, etc.
>> - **Stroke and fill attributes**: `lineWidth`, `lineCap`, `lineJoin`, 
>> `miterLimit`, `fillRule`, `stroke` and `fill` paints.
>> - **Global graphics settings**: `globalAlpha` and `globalBlendMode`.
>> - **Image drawing**: draw other `Image` instances with scaling and 
>> source/destination rectangles.
>> - **Text rendering**: render text
>> - **Save/Restore**: store current stroke, font, dashes, etc and restore them 
>> later
>> - **Paths**: begin a path, with lines, curves, etc, then stroke or fill it
>> - **Clips**: support rectangular clips in the SW renderer
>> 
>> This feature enables direct software rendering to `WritableImage` without 
>> requiring a `Canvas` + snapshot.
>> 
>> **Additional notes**:
>> 
>> - The implementation leverages the software stack consisting of the Marlin 
>> rasterizer and Pisces compositor/painter.
>> 
>> **Example usage**:
>> 
>> 
>> WritableImage img = new WritableImage(400, 400);
>> DrawingContext ctx = img.getDrawingContext();
>> ctx.setFill(Color.RED);
>> ctx.fillRect(50, 50, 100, 100);
>> 
>> 
>> See the sample program `RandomShapesDemo` to see a `WritableImage` and 
>> `Canvas` side by side performing the same operations:
>> 
>> <img width="1249" height="741" alt="image" 
>> src="https://github.com/user-attachments/assets/4a0b9dcc-8f96-4faa-99cf-83c66d2c851e";
>>  />
>> 
>> Newer version:
>> 
>> <img width="1249" height="741" alt="image" 
>> src="https://github.com/user-attachments/assets/c0502620-3d02-4fbd-8c33-43bd5138b42c";
>>  />
>> 
>> ---------
>> - [x] I confirm that I make this contribution in accordance with the 
>> [OpenJDK Interim AI Policy](https://openjdk.org/legal/ai).
>
> John Hendrikx has updated the pull request incrementally with one additional 
> commit since the last revision:
> 
>   Remove whitespace

modules/javafx.graphics/src/main/java/javafx/scene/image/WritableImage.java 
line 177:

> 175:         if (drawingContext == null) {
> 176:             // note: there is only one implementation of PlatformImage 
> (by QuantumToolkit) so the hard cast here is safe
> 177:             drawingContext = new SWDrawingContext((com.sun.prism.Image) 
> getWritablePlatformImage(), rect -> bufferDirty(rect));

Multiple `WritableImage` instance can be backed by the same `PixelBuffer`, and 
`PixelBuffer.updateBuffer()` accounts for that fact by notifying all associated 
writable images.

However, in this method, you're only invalidating the `WritableImage` from 
which the `DrawingContext` was obtained. This leaves all other writable images 
in a stale state.

Maybe this could be solved by using the existing `PixelBuffer.updateBuffer()` 
logic if the image is backed by a `PixelBuffer`.

modules/javafx.graphics/src/main/native-prism-sw/JJavaSurface.c line 163:

> 161: 
> 162:     surface->super.data = (void *)((jint *)surface->super.data +
> 163:         (*env)->GetIntField(env, surfaceHandle, 
> fieldIds[SURFACE_DATA_OFFSET]));

This might violate the contract of 
[GetPrimitiveArrayCritical](https://docs.oracle.com/en/java/javase/26/docs/specs/jni/functions.html#getprimitivearraycritical-releaseprimitivearraycritical)
 in two ways:
1. "Inside a critical region, native code must not call other JNI functions", 
but you're calling `GetIntField`.
2. The pointer passed to `ReleasePrimitiveArrayCritical` must be the exact 
pointer as returned by `GetPrimitiveArrayCritical`, you can't do pointer 
arithmetic with it.

A solution could be to read the data offset before entering the critical 
region, retain the original base pointer separately, use base + offset only as 
the renderer pointer, and then pass the base pointer to 
`ReleasePrimitiveArrayCritical`.

-------------

PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r3939347932
PR Review Comment: https://git.openjdk.org/jfx/pull/1969#discussion_r3939333162

Reply via email to