Compare commits

..

81 Commits

Author SHA1 Message Date
Vitaly Provodin
b66f6293e3 fixup! update exclude list on results of 25.0.1_212.14 test runs 2025-11-21 07:39:25 +04:00
Vitaly Provodin
360fa14c07 update exclude list on results of 25.0.1_212.14 test runs 2025-11-21 03:10:46 +04:00
Vitaly Provodin
531e1450af JBR-9422 revert "8296972: [macos13] java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java: getExtendedState() != 6 as expected." 2025-11-21 02:41:31 +04:00
Vitaly Provodin
7c48cc7040 update exclude list on results of 25.0.1_212 test runs 2025-11-15 01:01:49 +04:00
Nikita Provotorov
60bfa2b12e JBR-9616: JBR can't be built on Windows: "LAUNCHER_ARGS must be defined".
fixup! JRE-681 [windows] direct drawing into frame graphics may have wrong translate

Using LIBAWT_EXTRA_HEADER_DIRS instead of LIBAWT_EXTRA_SRC to get src/java.base/windows/native/launcher/java_rc.h discoverable by src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp.
2025-11-14 16:51:18 +01:00
Nikita Tsarev
ae6360371c JBR-9591 Wayland: Fix wrong DnD action on KWin
This patch implements a workaround for a bug that exists on KWin 6.5. For
some reason, KWin sends a wl_data_source.action(0) event immediately
after wl_data_source.dnd_drop_finished(). This makes the drag source
think that the DnD operation failed, even though it succeeded.
The workaround it to ignore the wl_data_source.action() events
after a successful wl_data_source.dnd_drop_finished()

In addition to this, this patch also fixes some inconsistency with
translating between AWT and Wayland DnD operation masks. This doesn't
have any visible effect though, since the mask values happen to be the
same.
2025-11-14 16:20:38 +01:00
Maxim Kartashev
f8aee55ea6 JBR-9598 Wayland: auto-detect Wayland session at startup
Adds -Dawt.toolkit.name=auto to prefer WLToolkit over XToolkit when
available. The default is still XToolkit.
2025-11-14 14:04:53 +04:00
Maxim Kartashev
ffc581146c JBR-9608 Correct README.md to suggest contributing through OpenJDK 2025-11-13 15:04:36 +04:00
Maxim Kartashev
75930f77d2 JBR-9577 Extra info on JVM crash to the terminal 2025-11-13 12:35:35 +04:00
Nikita Gubarkov
7b721d2610 JBR-9505 Vulkan: Remove sun.java2d.vulkan.accelsd from tests
(cherry picked from commit 3fb012e9dd)
2025-11-12 17:41:22 +01:00
Vitaly Provodin
fed9ce336e update exclude list on results of 25.0.1_197.11 test runs 2025-11-12 12:50:25 +04:00
Dmitry Drobotov
14be13239e JBR-9580 Fix crash in [MenuAccessibility accessibilityChildren]
* Add null checks for variables that can have null values to prevent hard crash
* Add missing CHECK_EXCEPTION after JNI call
* Add missing DeleteLocalRef for axComponent

(cherry picked from commit 96fcd9e591)
2025-11-11 20:28:55 +01:00
Vladimir Dvorak
c9aea14597 JBR-9548 DCEVM: Ensure updated class versions in dictionary in doit() 2025-11-11 20:03:40 +01:00
Maxim Kartashev
d619feefc6 JBR-5989 Wayland: added more tests to jdk_awt_wayland 2025-11-11 18:06:00 +04:00
bourgesl
b38204cb12 JBR-9609 JBR Metal compilation error on Intel MacBooks
Wrapped MTLDrawable.drawableID usages in getDrawableId to check macOS version
2025-11-11 11:23:07 +01:00
Sergey Shelomentsev
c7fe20689c JBR-9610 Set TimerQueue thread exclusion for BugJBR9563.java 2025-11-11 11:38:31 +02:00
Vitaly Provodin
bb52503876 update exclude list on results of 25.0.1_190.10 test runs 2025-11-06 16:44:43 +04:00
Nikita Gubarkov
a9554a0e4a JBR-5594 Pass display configuration from outside on full display update 2025-11-06 13:31:38 +01:00
Nikita Gubarkov
cbae1a769b JBR-5594 Pass display configuration info from AppKit to EDT 2025-11-06 13:31:37 +01:00
bourgesl
505522f2e2 JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke
Minimal changes for JBR-21: added @try/&@catch(nsexception) in ThreadUtilities.processQueuedCallbacks() to handle any native or java exception and avoid crashing the main run loop
2025-11-05 22:47:04 +01:00
bourgesl
9e729bf99d Revert "JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke"
This reverts commit 39743018bb.
2025-11-05 22:46:44 +01:00
bourgesl
14eaa570d1 Revert "JBR-8651 remove logging producing warnings in stderr"
This reverts commit e880107619.
2025-11-05 22:46:43 +01:00
Nikita Tsarev
54b65e514f JBR-9542 Wayland: Fix modifier mask on modifier key press/release
When pressing a modifier key such as Shift or Alt, other toolkits
include the corresponding bit in the modifier mask. Similiarly, when
releasing a modifier key, other toolkits will not include this bit if
the just released modifier key was the last key producing this bit.

When pressing such a key, Wayland compositors first send the
wl_keyboard.key event, and only then the wl_keyboard.modifiers event.
This causes the reported AWT modifier mask to be inconsistent with
XToolkit. This patch fixes this.
2025-11-05 17:15:19 +01:00
Vladimir Dvorak
86e6947981 JBR-9578 DCEVM: update class only in dictionary 2025-11-05 13:01:59 +01:00
Sergey Shelomentsev
0f7c371233 JBR-9563 Add test to verify that new threads aren't spawned infinitely 2025-11-05 13:15:50 +02:00
Vitaly Provodin
e880107619 JBR-8651 remove logging producing warnings in stderr 2025-11-01 16:11:48 +01:00
bourgesl
39743018bb JBR-8651 Pycharm Crashing after lock/sleep: SIGABRT at # C [libsystem_kernel.dylib+0x9388] __pthread_kill / __displaycb_handle_block_invoke
Rewritten exception handling to adopt the improved NSApplicationAWT exception handler (log all exceptions, avoid crash GUI)
Fixed JNI_COCOA_EXIT(env) usages to test also pending JNI exceptions
Added JNI_COCOA_EXIT_FATAL(message) used by NSApplicationAWT.sendEvent to report a crash with full details
Unified logException to report both crash and exceptions
Added isAWTCrashOnException() using the system property 'apple.awt.crashOnException' to crash on any exception occuring in NSApplication level
Added missing CHECK_EXCEPTION after (*env)->Call...Method()
Intercept all exception in NSApplicationAWT as NSExceptionHandlerDelegate + added tests in LWCToolkit (native) and Java code to test all exceptions are reported in logs and caught properly

(cherry picked from commit 8664158b6de5e71374212a4a7807a038d925c9a1)
2025-10-31 17:03:19 +01:00
Vitaly Provodin
ceb2dcb091 update exclude list on results of 25.0.1_186.7 test runs 2025-10-30 15:56:05 +04:00
Nikita Tsarev
fe29694915 JBR-9547: Fix macOS build failure with Xcode 26.0.1 2025-10-28 12:50:20 +01:00
Rob McKenna
a336a88057 8367031: [backout] Change java.time month/day field types to 'byte'
Backport-of: 00be643fa3eff6fd66d39f5f5ea70ff347296318
2025-10-26 03:05:42 +04:00
Nibedita Jena
6c753b5d49 8368308: ISO 4217 Amendment 180 Update
Backport-of: 3f9c665586705c833674ae998f49cabbc7e15615
2025-10-26 03:05:41 +04:00
Nibedita Jena
099394e43a 8366223: ZGC: ZPageAllocator::cleanup_failed_commit_multi_partition is broken
Backport-of: 009612805f79e37d9ce4e3f5c90627b635b095cf
2025-10-26 03:05:41 +04:00
Matias Saavedra Silva
71241ecc59 8352637: Enhance bytecode verification
Reviewed-by: dlong
Backport-of: d9bf0c2ca2d52d783a8122504cac9566d42b22df
2025-10-26 03:05:41 +04:00
Nibedita Jena
377b0902b1 8360647: [XWayland] [OL10] NumPad keys are not triggered
Backport-of: 4d5fb6eb8bb66556f06dada72df531d537cf32c2
2025-10-26 03:05:41 +04:00
Ravi Reddy
04fdd306ab 8356294: Enhance Path Factories
Backport-of: 5835cefe4946524af3be4933b20cd1b0005b0ad0
2025-10-26 03:05:40 +04:00
Nibedita Jena
06b190878a 8361212: Remove AffirmTrust root CAs
Backport-of: e58859e8acc19bfd8aaa80e98534651e83850a97
2025-10-26 03:05:40 +04:00
Nibedita Jena
b8cfdc28dc 8360937: Enhance certificate handling
Reviewed-by: mullan
Backport-of: f2fba5a55176ca82985ca42996cef36be7b7500a
2025-10-26 03:05:40 +04:00
Taizo Kurashige
1e7ae9c8d5 8358819: The first year is not displayed correctly in Japanese Calendar
Backport-of: 99829950f6
2025-10-26 03:05:39 +04:00
Dingli Zhang
0c7f8b1b00 8361829: [TESTBUG] RISC-V: compiler/vectorization/runner/BasicIntOpTest.java fails with RVV but not Zvbb
Backport-of: 2e7e272d7b
2025-10-26 03:05:39 +04:00
Dingli Zhang
3f53deeaf2 8361532: RISC-V: Several vector tests fail after JDK-8354383
Backport-of: e0245682c8
2025-10-26 03:05:39 +04:00
Matthias Baesken
a2f4b57bb2 8357826: Avoid running some jtreg tests when asan is configured
Backport-of: d7aa349820
2025-10-26 03:05:38 +04:00
Kieran Farrell
a471e942e4 8359454: Enhance String handling
Backport-of: 2f2665738a67aeed224b54870608a346eb627d2a
2025-10-26 03:05:38 +04:00
Ian Myers
d5ceea456c 8358577: Test serviceability/jvmti/thread/GetCurrentContendedMonitor/contmon01/contmon01.java failed: unexpexcted monitor object
Backport-of: 8f487d26c0
2025-10-26 03:05:38 +04:00
Matthias Baesken
e6cb0a1b56 8360533: ContainerRuntimeVersionTestUtils fromVersionString fails with some docker versions
Backport-of: 97ec9d3e0a
2025-10-26 03:05:38 +04:00
Renjith Kannath Pariyangad
ab7a9f8f87 8358452: JNI exception pending in Java_sun_awt_screencast_ScreencastHelper_remoteDesktopKeyImpl of screencast_pipewire.c:1214 (ID: 51119)
Backport-of: 2103dc15cb
2025-10-26 03:05:37 +04:00
Fei Yang
6b43d1a768 8359270: C2: alignment check should consider base offset when emitting arraycopy runtime call
Backport-of: 6b4393917a
2025-10-26 03:05:37 +04:00
Fei Yang
dfe78a31f5 8360179: RISC-V: Only enable BigInteger intrinsics when AvoidUnalignedAccess == false
Backport-of: 34412da52b
2025-10-26 03:05:37 +04:00
Fei Yang
e48181b9aa 8359218: RISC-V: Only enable CRC32 intrinsic when AvoidUnalignedAccess == false
Backport-of: 65e63b6ab4
2025-10-26 03:05:36 +04:00
Rob McKenna
f0d54ab6e5 8359059: Bump version numbers for 25.0.1
Reviewed-by: iris
2025-10-26 03:05:36 +04:00
Vitaly Provodin
20b513f189 JBR-4154 use -V to sort versions 2025-10-26 03:05:28 +04:00
Vitaly Provodin
58f04296e7 fixup! update exclude list on results of 25.176.2 test runs 2025-10-26 03:05:10 +04:00
Maxim Kartashev
7a2d71329d JBR-9503 Wayland: IDE frame disappears after click on 'Cancel' 2025-10-24 13:39:30 +04:00
Maxim Kartashev
54276e869b JBR-9521 sources/TestNoNULL.java: Test found 14 usages of 'NULL' in source files 2025-10-23 12:13:29 +04:00
Ilia K
75dcbe8f20 JBR-9515 Allow size of per-directory buffer used to retrieve events to be configurable to avoid OVERFLOW_EVENT 2025-10-22 14:19:59 +04:00
Nikita Tsarev
37b13e2f17 JBR-9527: Fix NPE with WLDataDevice.performDeletionsOnEDT() when headless [WLToolkit] 2025-10-22 11:57:25 +02:00
Vitaly Provodin
bde37c774a update exclude list on results of 25.176.2 test runs 2025-10-22 07:30:54 +04:00
Nikita Tsarev
8dfd14f671 JBR-8353: Use a deletion queue to destroy data transfer objects [WLToolkit] 2025-10-20 21:09:46 +02:00
Nikita Gubarkov
49bed44184 JBR-9486 Vulkan: Handle VK_ERROR_OUT_OF_DATE_KHR 2025-10-16 20:32:31 +02:00
Vitaly Provodin
a270d9e6a3 clean up fixed issues from exclude lists, start 2026.1 2025-10-16 14:48:45 +04:00
Vitaly Provodin
11e3c06ba0 update exclude list on results of 25.165.38 test runs 2025-10-16 06:50:07 +04:00
Nikita Gubarkov
95c6f7c37f JBR-9481 Vulkan: OOM-safe BLIT 2025-10-15 18:44:53 +02:00
Nikita Provotorov
c4f2b64d19 JBR-5672: Wayland: support input methods.
Providing support of the "text-input-unstable-v3" protocol, except its surrounding text API (zwp_text_input_v3::set_surrounding_text + zwp_text_input_v3::delete_surrounding_text).
A new system property "sun.awt.wl.im.enabled"[=true|false] is introduced to enable/disable all the integrations with Wayland's native input methods. Set to 'true' by default.

(cherry picked from commit 1c37490f00)
2025-10-15 03:43:41 +02:00
Nikita Provotorov
9a6415585d fixup! JBR-6376: implement detecting of OS theme on linux
Adding the D-Bus libs as a dependency: it's required for src/java.desktop/linux/native/libawt/awt/dbus_interface.h

(cherry picked from commit 3fb240f4aa)
2025-10-14 20:53:18 +02:00
Nikita Gubarkov
51d7cd2afb JBR-9477 JBR API: Update local artifact group 2025-10-14 12:40:21 +02:00
bourgesl
3c66bdc1e9 JBR-9375 macOS: Right-click context menu shows blurry animation when opening
Disable NSWindow animationBehavior (=NSWindowAnimationBehaviorNone) by default except if the system property 'apple.awt.window.animation' = true
+ Fixed J2dRlsTraceLn
2025-10-14 08:16:47 +02:00
Nikita Gubarkov
e65cb43ba1 JBR-9438 Vulkan: JBR API for accessing configuration info 2025-10-13 16:52:02 +02:00
Nikita Tsarev
7c84fbe810 JBR-8353: Fix wrong order of java/wayland object destruction in DataOffer/DataSource [WLToolkit] 2025-10-10 14:29:00 +02:00
Vitaly Provodin
6c47534225 update exclude list on results of 25.152.37 test runs 2025-10-10 03:17:36 +04:00
Maxim Kartashev
ffde0964ef JBR-9451 Wayland: Calling other JNI functions in the scope of Get/ReleasePrimitiveArrayCritical or Get/ReleaseStringCritical 2025-10-09 16:38:25 +04:00
Alexey Ushakov
d0299a4c6a JBR-9292 Vulkan: RenderPerfTest missing frames 2025-10-08 22:51:35 +02:00
Nikita Gubarkov
1186447190 JBR-9457 Vulkan: Enable accelerated surfaces by default 2025-10-08 22:10:35 +02:00
Nikita Gubarkov
4eab05ccd9 JBR-7646 Vulkan: Implement painting modes 2025-10-08 22:10:35 +02:00
Nikita Gubarkov
74b4df4496 JBR-9450 Vulkan: Unify pipelines 2025-10-08 22:09:48 +02:00
Nikita Gubarkov
8f660e630c JBR-9439 Vulkan: Fix blit composites 2025-10-08 22:09:40 +02:00
Nikita Gubarkov
4bd1551dc4 JBR-8344 Vulkan: Fix color XOR 2025-10-08 16:46:02 +02:00
Nikita Tsarev
4879508145 JBR-9449: Use wl_proxy_create_wrapper when creating data source objects for thread-safety [WLToolkit] 2025-10-07 10:25:16 +02:00
Maxim Kartashev
84473294fb JBR-9364 Wayland: Popups are shifted with multiple monitor setup after monitor reconnected (Ubuntu) 2025-10-07 10:17:17 +04:00
bourgesl
57e694c1ae JBR-9408 Fix Marlin renderer statistics
Revert JBR-9283 changes to StatLong (completely) to avoid future conflicts

(cherry picked from commit bc60599b45bddcb2d251035f945b5616e43554d2)
(cherry picked from commit 5be4830ecf30e2c74d1e828e3482edca03d166c6)
2025-10-05 23:17:06 +02:00
bourgesl
12e0466566 JDK-8341381 Random lines appear in graphic causing by the fix of JDK-8297230
- Fix cubic offsetting artefacts (sort cubic roots + fixed numerical accuracy problem in ROC^2-w^2 = 0 solver + fixed EliminateInf)
- Restored lower precision using ulp(float) in point, line or flat bezier curve checks

(cherry picked from commit e72b87e6538dda97e6f0f2840040c6864b3f146e)
2025-10-05 23:04:09 +02:00
Nikita Gubarkov
02ab184c01 JBR-9425 Vulkan: Fix surface disposal 2025-10-01 13:19:46 +02:00
Vitaly Provodin
bf7dea965a update exclude list on results of 25.144.34 test runs 2025-10-01 08:48:01 +04:00
201 changed files with 7979 additions and 2243 deletions

5
.github/README.md vendored
View File

@@ -161,7 +161,7 @@ Install the necessary tools, libraries, and headers with:
```
$ sudo apt-get install autoconf make build-essential libx11-dev libxext-dev libxrender-dev libxtst-dev \
libxt-dev libxrandr-dev libcups2-dev libfontconfig1-dev libasound2-dev libspeechd-dev libwayland-dev \
wayland-protocols libxkbcommon-x11-0
wayland-protocols libxkbcommon-x11-0 libdbus-1-dev
```
Get Java 23 (for instance, [Azul Zulu Builds of OpenJDK 23](https://www.azul.com/downloads/?version=java-23&os=linux&package=jdk#zulu)).
@@ -254,8 +254,7 @@ configurations (for example, `release` and `fastdebug`), supply the `--conf <con
Then open the git root directory as a project in IDEA.
## Contributing
We are happy to receive your pull requests!
Before you submit one, please sign our [Contributor License Agreement (CLA)](https://www.jetbrains.com/agreements/cla/).
Please contribute your changes through [OpenJDK](https://dev.java/contribute/openjdk/).
## Resources
* [JetBrains Runtime on GitHub](https://github.com/JetBrains/JetBrainsRuntime).

View File

@@ -1,7 +1,7 @@
[general]
project=jdk
project=jdk-updates
jbs=JDK
version=25
version=25.0.1
[checks]
error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists,copyright

View File

@@ -47,8 +47,8 @@ VERSION_PATCH=$(getVersionProp "DEFAULT_VERSION_PATCH")
[[ $VERSION_UPDATE = 0 ]] && JBSDK_VERSION="$VERSION_FEATURE" || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}"
[[ $VERSION_PATCH = 0 ]] || JBSDK_VERSION="${VERSION_FEATURE}.${VERSION_INTERIM}.${VERSION_UPDATE}.${VERSION_PATCH}"
echo "##teamcity[setParameter name='env.JBSDK_VERSION' value='${JBSDK_VERSION}']"
tag_prefix="jdk-"
OPENJDK_TAG=$(git tag -l | grep "$tag_prefix$JBSDK_VERSION" | grep -v ga | sort -t "-" -k 2 -V -f | tail -n 1)
tag_prefix="jbr-"
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "${tag_prefix}${JBSDK_VERSION}" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -V -f | tail -n 1 | tr -d ",")
JDK_BUILD_NUMBER=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
re='^[0-9]+$'

View File

@@ -40,13 +40,13 @@ else ifeq ($(call isBuildOsEnv, windows.wsl1 windows.wsl2), true)
else
M2_REPO := $(HOME)/.m2/repository
endif
M2_ARTIFACT := $(M2_REPO)/com/jetbrains/jbr-api/SNAPSHOT
M2_ARTIFACT := $(M2_REPO)/org/jetbrains/runtime/jbr-api/SNAPSHOT
M2_POM_CONTENT := \
<?xml version="1.0" encoding="UTF-8"?> \
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" \
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> \
<modelVersion>4.0.0</modelVersion> \
<groupId>com.jetbrains</groupId> \
<groupId>org.jetbrains.runtime</groupId> \
<artifactId>jbr-api</artifactId> \
<version>SNAPSHOT</version> \
</project> \
@@ -65,7 +65,8 @@ jbr-api:
$(MKDIR) -p $(M2_ARTIFACT); \
$(ECHO) '$(M2_POM_CONTENT)' > $(M2_ARTIFACT)/$(ARTIFACT_NAME).pom; \
$(CP) "$(JBR_API_DIR)/out/$(ARTIFACT_NAME).jar" "$(M2_ARTIFACT)"; \
$(ECHO) "Installed into local Maven repository as com.jetbrains:jbr-api:SNAPSHOT"; \
$(ECHO) "Installed into local Maven repository as org.jetbrains.runtime:jbr-api:SNAPSHOT"; \
cd "$(M2_ARTIFACT)" && sha256sum --binary "$(ARTIFACT_NAME).jar"; \
else \
$(ECHO) "No Maven repository found at $(M2_REPO) - skipping local installation"; \
fi

View File

@@ -89,7 +89,7 @@ AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslc); then
UTIL_LOOKUP_PROGS(GLSLC, glslc)
SHADER_COMPILER="$GLSLC"
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num -o"
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num"
fi
# Check glslangValidator
@@ -97,7 +97,8 @@ AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
test "x$SHADER_COMPILER" = x; then
UTIL_LOOKUP_PROGS(GLSLANG, glslangValidator)
SHADER_COMPILER="$GLSLANG"
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x -o"
# Newer glslangValidator could use -P\"\#extension GL_GOOGLE_include_directive: require\"
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x"
fi
if test "x$SHADER_COMPILER" = x; then

View File

@@ -28,12 +28,12 @@
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_UPDATE=1
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2025-09-16
DEFAULT_VERSION_DATE=2025-10-21
DEFAULT_VERSION_CLASSFILE_MAJOR=69 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`"
DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11

View File

@@ -542,10 +542,10 @@ class Bundle {
if (pattern != null) {
// Perform date-time format pattern conversion which is
// applicable to both SimpleDateFormat and j.t.f.DateTimeFormatter.
String transPattern = translateDateFormatLetters(calendarType, pattern, this::convertDateTimePatternLetter);
String transPattern = translateDateFormatLetters(calendarType, key, pattern, this::convertDateTimePatternLetter);
dateTimePatterns.add(i, transPattern);
// Additionally, perform SDF specific date-time format pattern conversion
sdfPatterns.add(i, translateDateFormatLetters(calendarType, transPattern, this::convertSDFLetter));
sdfPatterns.add(i, translateDateFormatLetters(calendarType, key, transPattern, this::convertSDFLetter));
} else {
dateTimePatterns.add(i, null);
sdfPatterns.add(i, null);
@@ -568,7 +568,7 @@ class Bundle {
}
}
private String translateDateFormatLetters(CalendarType calendarType, String cldrFormat, ConvertDateTimeLetters converter) {
private String translateDateFormatLetters(CalendarType calendarType, String patternKey, String cldrFormat, ConvertDateTimeLetters converter) {
String pattern = cldrFormat;
int length = pattern.length();
boolean inQuote = false;
@@ -587,7 +587,7 @@ class Bundle {
if (nextc == '\'') {
i++;
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -597,7 +597,7 @@ class Bundle {
}
if (!inQuote) {
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -614,7 +614,7 @@ class Bundle {
}
if (!(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) {
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -627,7 +627,7 @@ class Bundle {
count++;
continue;
}
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
lastLetter = c;
count = 1;
}
@@ -637,7 +637,7 @@ class Bundle {
}
if (count != 0) {
converter.convert(calendarType, lastLetter, count, jrePattern);
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
}
if (cldrFormat.contentEquals(jrePattern)) {
return cldrFormat;
@@ -661,7 +661,7 @@ class Bundle {
* on the support given by the SimpleDateFormat and the j.t.f.DateTimeFormatter
* for date-time formatting.
*/
private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
private void convertDateTimePatternLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) {
switch (cldrLetter) {
case 'u':
case 'U':
@@ -683,7 +683,7 @@ class Bundle {
* Perform a conversion of CLDR date-time format pattern letter which is
* specific to the SimpleDateFormat.
*/
private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
private void convertSDFLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) {
switch (cldrLetter) {
case 'G':
if (calendarType != CalendarType.GREGORIAN) {
@@ -722,6 +722,17 @@ class Bundle {
appendN('z', count, sb);
break;
case 'y':
// If the style is FULL/LONG for a Japanese Calendar, make the
// count == 4 for Gan-nen
if (calendarType == CalendarType.JAPANESE &&
(patternKey.contains("full-") ||
patternKey.contains("long-"))) {
count = 4;
}
appendN(cldrLetter, count, sb);
break;
case 'Z':
if (count == 4 || count == 5) {
sb.append("XXX");
@@ -767,6 +778,7 @@ class Bundle {
.collect(Collectors.toMap(
e -> calendarPrefix + e.getKey(),
e -> translateDateFormatLetters(calendarType,
e.getKey(),
(String)e.getValue(),
this::convertDateTimePatternLetter)
))
@@ -775,7 +787,7 @@ class Bundle {
@FunctionalInterface
private interface ConvertDateTimeLetters {
void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb);
void convert(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb);
}
/**

View File

@@ -65,6 +65,7 @@ ifeq ($(call isTargetOs, aix), false)
CXXFLAGS := $(LIBJSOUND_CFLAGS), \
DISABLED_WARNINGS_gcc := undef unused-variable, \
DISABLED_WARNINGS_clang := undef unused-variable, \
DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_Ports.cpp := vla-cxx-extension, \
DISABLED_WARNINGS_clang_PLATFORM_API_MacOSX_MidiUtils.c := \
unused-but-set-variable, \
DISABLED_WARNINGS_clang_DirectAudioDevice.c := unused-function, \

View File

@@ -36,6 +36,7 @@ WAYLAND_BASIC_PROTOCOL_FILES := \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/primary-selection/primary-selection-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/xdg-output/xdg-output-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/relative-pointer/relative-pointer-unstable-v1.xml \
$(WAYLAND_PROTOCOLS_ROOT)/unstable/text-input/text-input-unstable-v3.xml \
$(GTK_SHELL1_PROTOCOL_PATH) \
#

View File

@@ -58,7 +58,6 @@ ifeq ($(call isTargetOs, windows), true)
$(TOPDIR)/src/$(MODULE)/share/native/common/font \
$(TOPDIR)/src/$(MODULE)/share/native/common/java2d/opengl \
$(TOPDIR)/src/$(MODULE)/$(OPENJDK_TARGET_OS_TYPE)/native/common/awt/systemscale \
$(TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/launcher \
#
endif
@@ -102,6 +101,7 @@ ifeq ($(call isTargetOs, windows), true)
LIBAWT_RCFLAGS ?= -I$(TOPDIR)/src/java.base/windows/native/launcher/icons
LIBAWT_VERSIONINFO_RESOURCE := \
$(TOPDIR)/src/$(MODULE)/windows/native/libawt/windows/awt.rc
LIBAWT_EXTRA_HEADER_DIRS += $(TOPDIR)/src/java.base/windows/native/launcher
endif
# This is the object file to provide the dladdr API, which is not
@@ -220,7 +220,7 @@ endif
# Compile Vulkan shaders
define compile-spirv
$(call MakeTargetDir)
$(VULKAN_SHADER_COMPILER) '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
$(VULKAN_SHADER_COMPILER) -D$(call uppercase,$(patsubst .%,STAGE_%,$(suffix $<))) -o '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
endef
spirv-name = $(strip $1).h

View File

@@ -5344,42 +5344,6 @@ void MacroAssembler::add2_with_carry(Register final_dest_hi, Register dest_hi, R
add(final_dest_hi, dest_hi, carry);
}
/**
* Multiply 32 bit by 32 bit first loop.
*/
void MacroAssembler::multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,
Register idx, Register kdx) {
// jlong carry, x[], y[], z[];
// for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) {
// long product = y[idx] * x[xstart] + carry;
// z[kdx] = (int)product;
// carry = product >>> 32;
// }
// z[xstart] = (int)carry;
Label L_first_loop, L_first_loop_exit;
blez(idx, L_first_loop_exit);
shadd(t0, xstart, x, t0, LogBytesPerInt);
lwu(x_xstart, Address(t0, 0));
bind(L_first_loop);
subiw(idx, idx, 1);
shadd(t0, idx, y, t0, LogBytesPerInt);
lwu(y_idx, Address(t0, 0));
mul(product, x_xstart, y_idx);
add(product, product, carry);
srli(carry, product, 32);
subiw(kdx, kdx, 1);
shadd(t0, kdx, z, t0, LogBytesPerInt);
sw(product, Address(t0, 0));
bgtz(idx, L_first_loop);
bind(L_first_loop_exit);
}
/**
* Multiply 64 bit by 64 bit first loop.
*/
@@ -5596,77 +5560,16 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi
const Register carry = tmp5;
const Register product = xlen;
const Register x_xstart = tmp0;
const Register jdx = tmp1;
mv(idx, ylen); // idx = ylen;
addw(kdx, xlen, ylen); // kdx = xlen+ylen;
mv(carry, zr); // carry = 0;
Label L_multiply_64_x_64_loop, L_done;
Label L_done;
subiw(xstart, xlen, 1);
bltz(xstart, L_done);
const Register jdx = tmp1;
if (AvoidUnalignedAccesses) {
int base_offset = arrayOopDesc::base_offset_in_bytes(T_INT);
assert((base_offset % (UseCompactObjectHeaders ? 4 :
(UseCompressedClassPointers ? 8 : 4))) == 0, "Must be");
if ((base_offset % 8) == 0) {
// multiply_64_x_64_loop emits 8-byte load/store to access two elements
// at a time from int arrays x and y. When base_offset is 8 bytes, these
// accesses are naturally aligned if both xlen and ylen are even numbers.
orr(t0, xlen, ylen);
test_bit(t0, t0, 0);
beqz(t0, L_multiply_64_x_64_loop);
}
Label L_second_loop_unaligned, L_third_loop, L_third_loop_exit;
multiply_32_x_32_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
shadd(t0, xstart, z, t0, LogBytesPerInt);
sw(carry, Address(t0, 0));
bind(L_second_loop_unaligned);
mv(carry, zr);
mv(jdx, ylen);
subiw(xstart, xstart, 1);
bltz(xstart, L_done);
subi(sp, sp, 2 * wordSize);
sd(z, Address(sp, 0));
sd(zr, Address(sp, wordSize));
shadd(t0, xstart, z, t0, LogBytesPerInt);
addi(z, t0, 4);
shadd(t0, xstart, x, t0, LogBytesPerInt);
lwu(product, Address(t0, 0));
blez(jdx, L_third_loop_exit);
bind(L_third_loop);
subiw(jdx, jdx, 1);
shadd(t0, jdx, y, t0, LogBytesPerInt);
lwu(t0, Address(t0, 0));
mul(t1, t0, product);
add(t0, t1, carry);
shadd(tmp6, jdx, z, t1, LogBytesPerInt);
lwu(t1, Address(tmp6, 0));
add(t0, t0, t1);
sw(t0, Address(tmp6, 0));
srli(carry, t0, 32);
bgtz(jdx, L_third_loop);
bind(L_third_loop_exit);
ld(z, Address(sp, 0));
addi(sp, sp, 2 * wordSize);
shadd(t0, xstart, z, t0, LogBytesPerInt);
sw(carry, Address(t0, 0));
j(L_second_loop_unaligned);
}
bind(L_multiply_64_x_64_loop);
multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx);
Label L_second_loop_aligned;

View File

@@ -1384,10 +1384,6 @@ public:
void adc(Register dst, Register src1, Register src2, Register carry);
void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo,
Register src1, Register src2, Register carry);
void multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,
Register idx, Register kdx);
void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart,
Register y, Register y_idx, Register z,
Register carry, Register product,

View File

@@ -8431,6 +8431,17 @@ instruct castVV(vReg dst)
ins_pipe(pipe_class_empty);
%}
instruct castVVMask(vRegMask dst)
%{
match(Set dst (CastVV dst));
size(0);
format %{ "# castVV of $dst" %}
ins_encode(/* empty encoding */);
ins_cost(0);
ins_pipe(pipe_class_empty);
%}
// ============================================================================
// Convert Instructions

View File

@@ -203,15 +203,15 @@ void VM_Version::common_initialize() {
}
}
// Misc Intrinsics could depend on RVV
// Misc Intrinsics that could depend on RVV.
if (UseZba || UseRVV) {
if (!AvoidUnalignedAccesses && (UseZba || UseRVV)) {
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, true);
}
} else {
if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
warning("CRC32 intrinsic requires Zba or RVV instructions (not available on this CPU)");
warning("CRC32 intrinsic are not available on this CPU.");
}
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
@@ -325,20 +325,40 @@ void VM_Version::c2_initialize() {
FLAG_SET_DEFAULT(UseMulAddIntrinsic, true);
}
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true);
}
} else if (UseMultiplyToLenIntrinsic) {
warning("Intrinsics for BigInteger.multiplyToLen() not available on this CPU.");
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true);
}
} else if (UseSquareToLenIntrinsic) {
warning("Intrinsics for BigInteger.squareToLen() not available on this CPU.");
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true);
}
} else if (UseMontgomeryMultiplyIntrinsic) {
warning("Intrinsics for BigInteger.montgomeryMultiply() not available on this CPU.");
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
}
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
if (!AvoidUnalignedAccesses) {
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
}
} else if (UseMontgomerySquareIntrinsic) {
warning("Intrinsics for BigInteger.montgomerySquare() not available on this CPU.");
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
}
// Adler32

View File

@@ -352,16 +352,6 @@ void ClassLoaderDataGraph::verify_dictionary() {
}
}
// (DCEVM) - iterate over dict classes
void ClassLoaderDataGraph::dictionary_classes_do(KlassClosure* klass_closure) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
cld->dictionary()->classes_do(klass_closure);
}
}
}
// (DCEVM) rollback redefined classes
void ClassLoaderDataGraph::rollback_redefinition() {
ClassLoaderDataGraphIterator iter;
@@ -373,17 +363,27 @@ void ClassLoaderDataGraph::rollback_redefinition() {
}
// (DCEVM) - iterate over all classes in all dictionaries
bool ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass) {
bool ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old) {
bool ok = false;
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
ok = cld->dictionary()->update_klass(current, name, k, old_klass) || ok;
ok = cld->dictionary()->update_klass(current, name, k, old_klass, check_old) || ok;
}
}
return ok;
}
// (DCEVM) - iterate over all classes in all dictionaries
void ClassLoaderDataGraph::dictionary_classes_do_classes_do_safepoint(void f(InstanceKlass* const)) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData* cld = iter.get_next()) {
if (cld->dictionary() != nullptr) {
cld->dictionary()->classes_do_safepoint(f);
}
}
}
void ClassLoaderDataGraph::print_dictionary(outputStream* st) {
ClassLoaderDataGraphIterator iter;
while (ClassLoaderData *cld = iter.get_next()) {

View File

@@ -102,9 +102,9 @@ class ClassLoaderDataGraph : public AllStatic {
static void walk_metadata_and_clean_metaspaces();
// (DCEVM) Enhanced class redefinition
static void dictionary_classes_do(KlassClosure* klass_closure);
static void rollback_redefinition();
static bool dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass);
static bool dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old);
static void dictionary_classes_do_classes_do_safepoint(void f(InstanceKlass* const));
static void verify_dictionary();
static void print_dictionary(outputStream* st);

View File

@@ -211,15 +211,23 @@ class UpdateKlassDcevm : public StackObj {
InstanceKlass* _new_klass;
InstanceKlass* _old_klass;
bool _replaced;
bool _check_old;
public:
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass) :
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass, bool check_old) :
_new_klass(new_klass),
_old_klass(old_klass),
_replaced(false) {
_replaced(false),
_check_old(check_old) {
}
void operator()(InstanceKlass** old_table_value) {
assert(*old_table_value == _old_klass, "should be old class");
InstanceKlass* table_class = *old_table_value;
assert(!_check_old || table_class == _old_klass, "should be old class");
assert(table_class->class_loader_data() == _new_klass->class_loader_data(), "Must be same class loader");
if (!_check_old && table_class->new_version() != nullptr) {
ResourceMark rm;
log_debug(redefine, class, redefine, metadata)("Updating old class from doit() %s", table_class->name()->as_C_string());
}
*old_table_value = _new_klass;
_replaced = true;
}
@@ -230,14 +238,14 @@ public:
};
// (DCEVM) replace old_class by new class in dictionary
bool Dictionary::update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass) {
UpdateKlassDcevm found(k, old_klass);
bool Dictionary::update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old) {
UpdateKlassDcevm found(k, old_klass, check_old);
DictionaryLookup lookup(class_name);
InstanceKlass* result = nullptr;
bool needs_rehashing = false;
bool ret = _table->insert_get(current, lookup, old_klass, found);
return ret || found.get_replaced();
// (DCEVM): old_klass is replaced with the new one in UpdateKlassDcevm::operator(),
// which is invoked when class_name is found in the dictionary.
bool exists = _table->get(current, lookup, found);
return exists && found.get_replaced();
}
class RollBackDcevm : public StackObj {

View File

@@ -77,7 +77,7 @@ public:
void verify();
// (DCEVM) Enhanced class redefinition
bool update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass);
bool update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass, bool check_old);
void rollback_redefinition();
private:

View File

@@ -1507,7 +1507,7 @@ BasicType java_lang_Class::as_BasicType(oop java_class, Klass** reference_klass)
oop java_lang_Class::primitive_mirror(BasicType t) {
oop mirror = Universe::java_mirror(t);
assert(mirror != nullptr && (mirror->is_a(vmClasses::Class_klass())
|| (Universe::is_inside_redefinition() && vmClasses::Class_klass()->old_version() != NULL && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
|| (Universe::is_inside_redefinition() && vmClasses::Class_klass()->old_version() != nullptr && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
assert(is_primitive(mirror), "must be primitive");
return mirror;
}

View File

@@ -132,8 +132,16 @@ bool StackMapTable::match_stackmap(
}
void StackMapTable::check_jump_target(
StackMapFrame* frame, int32_t target, TRAPS) const {
StackMapFrame* frame, int bci, int offset, TRAPS) const {
ErrorContext ctx;
// Jump targets must be within the method and the method size is limited. See JVMS 4.11
int min_offset = -1 * max_method_code_size;
if (offset < min_offset || offset > max_method_code_size) {
frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame),
"Illegal target of jump or branch (bci %d + offset %d)", bci, offset);
return;
}
int target = bci + offset;
bool match = match_stackmap(
frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
if (!match || (target < 0 || target >= _code_length)) {

View File

@@ -67,7 +67,7 @@ class StackMapTable : public StackObj {
// Check jump instructions. Make sure there are no uninitialized
// instances on backward branch.
void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const;
void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const;
// The following methods are only used inside this class.

View File

@@ -1360,7 +1360,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* ol
ClassLoaderData* loader_data = k->class_loader_data();
assert(loader_data->class_loader() == class_loader(), "they must be the same");
bool is_redefining = (old_klass != NULL);
bool is_redefining = (old_klass != nullptr);
// Bootstrap and other parallel classloaders don't acquire a lock,
// they use placeholder token.
@@ -1386,10 +1386,9 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, InstanceKlass* ol
if (is_redefining) {
// Update all dictionaries containing old_class to new_class
// outcome must be same as result of standard redefinition, that does not create a new Klass
ClassLoaderDataGraph_lock->lock();
MutexLocker lock(ClassLoaderDataGraph_lock);
Symbol* name_h = k->name();
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass);
ClassLoaderDataGraph_lock->unlock();
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass, true);
assert (ok, "must have found old class and updated!");
}
check_constraints(k, loader_data, !is_redefining, CHECK);
@@ -1487,7 +1486,7 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl
}
}
define_instance_class(k, NULL, class_loader, THREAD);
define_instance_class(k, nullptr, class_loader, THREAD);
// definer must notify any waiting threads
{
@@ -1527,7 +1526,7 @@ InstanceKlass* SystemDictionary::find_or_define_instance_class(Symbol* class_nam
// (DCEVM) - remove from klass hierarchy
void SystemDictionary::remove_from_hierarchy(InstanceKlass* k) {
assert(k != NULL, "just checking");
assert(k != nullptr, "just checking");
// remove receiver from sibling list
k->remove_from_sibling_list();

View File

@@ -781,7 +781,6 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
// Merge with the next instruction
{
int target;
VerificationType type, type2;
VerificationType atype;
@@ -1606,9 +1605,8 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifle:
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_if_acmpeq :
case Bytecodes::_if_acmpne :
@@ -1619,19 +1617,16 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
case Bytecodes::_ifnonnull :
current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this));
target = bcs.dest();
stackmap_table.check_jump_target
(&current_frame, target, CHECK_VERIFY(this));
(&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_goto_w :
target = bcs.dest_w();
stackmap_table.check_jump_target(
&current_frame, target, CHECK_VERIFY(this));
&current_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_tableswitch :
case Bytecodes::_lookupswitch :
@@ -2280,15 +2275,14 @@ void ClassVerifier::verify_switch(
}
}
}
int target = bci + default_offset;
stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this));
stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this));
for (int i = 0; i < keys; i++) {
// Because check_jump_target() may safepoint, the bytecode could have
// moved, which means 'aligned_bcp' is no good and needs to be recalculated.
aligned_bcp = align_up(bcs->bcp() + 1, jintSize);
target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
stackmap_table->check_jump_target(
current_frame, target, CHECK_VERIFY(this));
current_frame, bci, offset, CHECK_VERIFY(this));
}
NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point
}
@@ -2549,7 +2543,12 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
case Bytecodes::_goto:
case Bytecodes::_goto_w: {
int target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w());
int offset = (opcode == Bytecodes::_goto ? bcs.get_offset_s2() : bcs.get_offset_s4());
int min_offset = -1 * max_method_code_size;
// Check offset for overflow
if (offset < min_offset || offset > max_method_code_size) return false;
int target = bci + offset;
if (visited_branches->contains(bci)) {
if (bci_stack->is_empty()) {
if (handler_stack->is_empty()) {
@@ -2607,7 +2606,10 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
// Push the switch alternatives onto the stack.
for (int i = 0; i < keys; i++) {
int target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
int min_offset = -1 * max_method_code_size;
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
if (offset < min_offset || offset > max_method_code_size) return false;
int target = bci + offset;
if (target > code_length) return false;
bci_stack->push(target);
}

View File

@@ -2353,7 +2353,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
}
if (AllowEnhancedClassRedefinition) {
// Skip redefined methods
if (task->method()->is_old() || task->method()->method_holder()->new_version() != NULL) {
if (task->method()->is_old() || task->method()->method_holder()->new_version() != nullptr) {
ci_env.record_method_not_compilable("redefined method", true);
} else {
comp->compile_method(&ci_env, target, osr_bci, true, directive);

View File

@@ -231,11 +231,11 @@ uint G1FullGCCompactionPoint::find_contiguous_before(G1HeapRegion* hr, uint num_
}
HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) {
assert(_current_region != NULL, "Must have been initialized");
assert(_current_region != nullptr, "Must have been initialized");
// Ensure the object fit in the current region.
while (!object_will_fit(size)) {
if (!_compaction_region_iterator.has_next()) {
return NULL;
return nullptr;
}
switch_region();
}
@@ -243,7 +243,7 @@ HeapWord* G1FullGCCompactionPoint::forward_compact_top(size_t size) {
}
void G1FullGCCompactionPoint::forward_dcevm(oop object, size_t size, bool force_forward) {
assert(_current_region != NULL, "Must have been initialized");
assert(_current_region != nullptr, "Must have been initialized");
// Ensure the object fit in the current region.
while (!object_will_fit(size)) {

View File

@@ -1936,7 +1936,7 @@ void ZPageAllocator::cleanup_failed_commit_multi_partition(ZMultiPartitionAlloca
}
const size_t committed = allocation->committed_capacity();
const ZVirtualMemory non_harvested_vmem = vmem.last_part(allocation->harvested());
const ZVirtualMemory non_harvested_vmem = partial_vmem.last_part(allocation->harvested());
const ZVirtualMemory committed_vmem = non_harvested_vmem.first_part(committed);
const ZVirtualMemory non_committed_vmem = non_harvested_vmem.last_part(committed);

View File

@@ -214,9 +214,20 @@ void ZPhysicalMemoryManager::free(const ZVirtualMemory& vmem, uint32_t numa_id)
});
}
static size_t inject_commit_limit(const ZVirtualMemory& vmem) {
// To facilitate easier interoperability with multi partition allocations we
// divide by ZNUMA::count(). Users of ZFailLargerCommits need to be aware of
// this when writing tests. In the future we could probe the VirtualMemoryManager
// and condition this division on whether the vmem is in the multi partition
// address space.
return align_up(MIN2(ZFailLargerCommits / ZNUMA::count(), vmem.size()), ZGranuleSize);
}
size_t ZPhysicalMemoryManager::commit(const ZVirtualMemory& vmem, uint32_t numa_id) {
zbacking_index* const pmem = _physical_mappings.addr(vmem.start());
const size_t size = vmem.size();
const size_t size = ZFailLargerCommits > 0
? inject_commit_limit(vmem)
: vmem.size();
size_t total_committed = 0;

View File

@@ -118,6 +118,11 @@
develop(bool, ZVerifyOops, false, \
"Verify accessed oops") \
\
develop(size_t, ZFailLargerCommits, 0, \
"Commits larger than ZFailLargerCommits will be truncated, " \
"used to stress page allocation commit failure paths " \
"(0: Disabled)") \
\
develop(uint, ZFakeNUMA, 1, \
"ZFakeNUMA is used to test the internal NUMA memory support " \
"without the need for UseNUMA") \

View File

@@ -100,8 +100,23 @@ class BaseBytecodeStream: StackObj {
void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; }
// Bytecode-specific attributes
int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }
int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }
int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); }
int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); }
// These methods are not safe to use before or during verification as they may
// have large offsets and cause overflows
int dest() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s2(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
int dest_w() const {
int min_offset = -1 * max_method_code_size;
int offset = bytecode().get_offset_s4(raw_code());
guarantee(offset >= min_offset && offset <= max_method_code_size, "must be");
return bci() + offset;
}
// One-byte indices.
u1 get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); }

View File

@@ -521,7 +521,7 @@ void Klass::initialize_supers(Klass* k, Array<InstanceKlass*>* transitive_interf
_primary_supers[0] = this;
assert(super_depth() == 0, "Object must already be initialized properly");
} else if (k != super() || k == vmClasses::Object_klass() || (k->is_redefining() && k == vmClasses::Object_klass()->newest_version())) {
assert(super() == NULL || super() == vmClasses::Object_klass() || (k->is_redefining() && super() == vmClasses::Object_klass()->newest_version()),
assert(super() == nullptr || super() == vmClasses::Object_klass() || (k->is_redefining() && super() == vmClasses::Object_klass()->newest_version()),
"initialize this only once to a non-trivial value");
set_super(k);
Klass* sup = k;
@@ -1388,18 +1388,18 @@ void Klass::on_secondary_supers_verification_failure(Klass* super, Klass* sub, b
}
void Klass::update_supers_dcevm() {
if (_super != NULL) {
if (_super != nullptr) {
_super = _super->newest_version();
}
int sup_depth = super_depth();
for (int idx = 0; idx < sup_depth; idx++) {
Klass* primary = _primary_supers[idx];
if (primary == NULL) {
if (primary == nullptr) {
break;
}
_primary_supers[idx] = primary->newest_version();
}
if (secondary_super_cache() != NULL) {
if (secondary_super_cache() != nullptr) {
set_secondary_super_cache(secondary_super_cache()->newest_version());
}

View File

@@ -432,6 +432,9 @@ protected:
const Klass* newest_version() const { return _new_version == nullptr ? this : _new_version->newest_version(); }
Klass* newest_version() { return _new_version == nullptr ? this : _new_version->newest_version(); }
const Klass* oldest_version() const { return _old_version == nullptr ? this : _old_version->oldest_version(); }
Klass* oldest_version() { return _old_version == nullptr ? this : _old_version->oldest_version(); }
const Klass* active_version() const { return _new_version == nullptr || _new_version->is_redefining() ? this : _new_version->active_version(); }
Klass* active_version() { return _new_version == nullptr || _new_version->is_redefining() ? this : _new_version->active_version(); }

View File

@@ -1575,9 +1575,14 @@ bool LibraryCallKit::inline_string_toBytesU() {
Node* src_start = array_element_address(value, offset, T_CHAR);
Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE));
// Check if src array address is aligned to HeapWordSize (dst is always aligned)
const TypeInt* toffset = gvn().type(offset)->is_int();
bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
// Check if dst array address is aligned to HeapWordSize
bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0);
// If true, then check if src array address is aligned to HeapWordSize
if (aligned) {
const TypeInt* toffset = gvn().type(offset)->is_int();
aligned = toffset->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) +
toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
}
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";
@@ -1658,8 +1663,8 @@ bool LibraryCallKit::inline_string_getCharsU() {
// Check if array addresses are aligned to HeapWordSize
const TypeInt* tsrc = gvn().type(src_begin)->is_int();
const TypeInt* tdst = gvn().type(dst_begin)->is_int();
bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";

View File

@@ -1473,9 +1473,14 @@ void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array,
Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE);
Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE);
// Check if destination address is aligned to HeapWordSize
const TypeInt* tdst = __ gvn().type(start)->is_int();
bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0);
// Check if src array address is aligned to HeapWordSize
bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0);
// If true, then check if dst array address is aligned to HeapWordSize
if (aligned) {
const TypeInt* tdst = __ gvn().type(start)->is_int();
aligned = tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) +
tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0);
}
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";
address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true);

View File

@@ -218,9 +218,7 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, int offset) {
DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
if (AllowEnhancedClassRedefinition) {
while (field_klass->old_version() != NULL) {
field_klass = field_klass->old_version();
}
field_klass = field_klass->oldest_version();
}
uintptr_t klass_hash = field_klass->identity_hash();
return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
@@ -242,9 +240,9 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
if (AllowEnhancedClassRedefinition) {
while (k->old_version() != NULL) {
k = k->old_version();
}
// DCEVM: use the oldest class version so all pre-existing IDs
// from old classes match IDs of the new (current) class.
k = k->oldest_version();
}
do {
@@ -253,6 +251,11 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
if ((k->identity_hash() & klass_mask) == klass_hash)
return true;
k = k->super();
if (AllowEnhancedClassRedefinition) {
// DCEVM: Same for each superclass: normalize to the oldest version
// so old IDs match the new class IDs.
k = k->oldest_version();
}
} while (k != nullptr);
return false;
}

View File

@@ -62,7 +62,6 @@
#include "utilities/bitMap.inline.hpp"
#include "prims/jvmtiThreadState.inline.hpp"
#include "utilities/events.hpp"
#include "oops/constantPool.inline.hpp"
#if INCLUDE_G1GC
#include "gc/g1/g1CollectedHeap.hpp"
#endif
@@ -695,6 +694,16 @@ void VM_EnhancedRedefineClasses::doit() {
new_class->old_version()->set_new_version(new_class);
}
// Update Dictionaries to ensure all references contain the new class versions.
// During load_new_class_versions(), another thread may have loaded an old version, so this pass replaces
// any remaining old ones.
for (int i = 0; i < _new_classes->length(); i++) {
InstanceKlass* new_class = _new_classes->at(i);
InstanceKlass* old_class = InstanceKlass::cast(new_class->old_version());
Symbol *name_h = new_class->name();
ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread::current(), name_h, new_class, old_class, false);
}
for (int i = 0; i < _new_classes->length(); i++) {
Klass* new_class = _new_classes->at(i);
redefine_single_class(current, _new_classes->at(i));
@@ -917,7 +926,7 @@ void VM_EnhancedRedefineClasses::doit() {
}
}
log_trace(redefine, class, redefine, metadata)("calling check_class");
ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do_safepoint(check_class);
ClassLoaderDataGraph::dictionary_classes_do_classes_do_safepoint(check_class);
#ifdef PRODUCT
}
#endif

View File

@@ -1097,6 +1097,22 @@ bool WhiteBox::validate_cgroup(bool cgroups_v2_enabled,
}
#endif
bool WhiteBox::is_asan_enabled() {
#ifdef ADDRESS_SANITIZER
return true;
#else
return false;
#endif
}
bool WhiteBox::is_ubsan_enabled() {
#ifdef UNDEFINED_BEHAVIOR_SANITIZER
return true;
#else
return false;
#endif
}
bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) {
// Screen for unavailable/bad comp level or null method
AbstractCompiler* comp = CompileBroker::compiler(comp_level);
@@ -1908,6 +1924,14 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
return (jboolean) obj_oop->mark().has_monitor();
WB_END
WB_ENTRY(jboolean, WB_IsAsanEnabled(JNIEnv* env))
return (jboolean) WhiteBox::is_asan_enabled();
WB_END
WB_ENTRY(jboolean, WB_IsUbsanEnabled(JNIEnv* env))
return (jboolean) WhiteBox::is_ubsan_enabled();
WB_END
WB_ENTRY(jlong, WB_getInUseMonitorCount(JNIEnv* env, jobject wb))
return (jlong) WhiteBox::get_in_use_monitor_count();
WB_END
@@ -2908,6 +2932,8 @@ static JNINativeMethod methods[] = {
(void*)&WB_AddModuleExportsToAll },
{CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors },
{CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated },
{CC"isAsanEnabled", CC"()Z", (void*)&WB_IsAsanEnabled },
{CC"isUbsanEnabled", CC"()Z", (void*)&WB_IsUbsanEnabled },
{CC"getInUseMonitorCount", CC"()J", (void*)&WB_getInUseMonitorCount },
{CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity },
{CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking },

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -72,6 +72,9 @@ class WhiteBox : public AllStatic {
#ifdef LINUX
static bool validate_cgroup(bool cgroups_v2_enabled, const char* controllers_file, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags);
#endif
// provide info about enabling of Address Sanitizer / Undefined Behavior Sanitizer
static bool is_asan_enabled();
static bool is_ubsan_enabled();
};
#endif // SHARE_PRIMS_WHITEBOX_HPP

View File

@@ -1312,24 +1312,24 @@ void VMError::report(outputStream* st, bool _verbose) {
NativeHeapTrimmer::print_state(st);
st->cr();
STEP("JNI global references")
st->print_cr("JNI global refs:");
JNIHandles::print_on_unsafe(st);
JNIHandles::print_memory_usage_on(st);
STEP_IF("JNI global references", _verbose)
st->print_cr("JNI global refs:");
JNIHandles::print_on_unsafe(st);
JNIHandles::print_memory_usage_on(st);
STEP_IF("Process memory usage", _verbose)
print_process_memory_usage(st);
STEP("OOME stack traces")
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
STEP_IF("OOME stack traces", _verbose)
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
STEP("Classloader stats")
st->print_cr("Classloader memory used:");
FREE_C_HEAP_ARRAY(void*, _ballast_memory);
_ballast_memory = nullptr;
print_classloaders_stats(st);
print_dup_classes(st); // do it separately in case we're low on memory
STEP_IF("Classloader stats", _verbose)
st->print_cr("Classloader memory used:");
FREE_C_HEAP_ARRAY(void*, _ballast_memory);
_ballast_memory = nullptr;
print_classloaders_stats(st);
print_dup_classes(st); // do it separately in case we're low on memory
STEP_IF("printing system", _verbose)
st->print_cr("--------------- S Y S T E M ---------------");

View File

@@ -1448,8 +1448,8 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
shift(currValue, coder, count, dstOffset, len);
count += len;
// Coder of CharSequence may be a mismatch, requiring the value array to be inflated
byte[] newValue = (s instanceof String str)
? putStringAt(currValue, coder, count, dstOffset, str, start, end)
byte[] newValue = (s instanceof String str && str.length() == len)
? putStringAt(currValue, coder, count, dstOffset, str)
: putCharsAt(currValue, coder, count, dstOffset, s, start, end);
if (currValue != newValue) {
this.coder = UTF16;
@@ -1928,10 +1928,10 @@ abstract sealed class AbstractStringBuilder implements Appendable, CharSequence
* @param index the index to insert the string
* @param str the string
*/
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) {
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str) {
byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder());
coder = (newValue == value) ? coder : UTF16;
str.getBytes(newValue, off, index, coder, end - off);
str.getBytes(newValue, 0, index, coder, str.length());
return newValue;
}

View File

@@ -182,11 +182,11 @@ public final class LocalDate
/**
* @serial The month-of-year.
*/
private final byte month;
private final short month;
/**
* @serial The day-of-month.
*/
private final byte day;
private final short day;
//-----------------------------------------------------------------------
/**
@@ -490,8 +490,8 @@ public final class LocalDate
*/
private LocalDate(int year, int month, int dayOfMonth) {
this.year = year;
this.month = (byte) month;
this.day = (byte) dayOfMonth;
this.month = (short) month;
this.day = (short) dayOfMonth;
}
//-----------------------------------------------------------------------

View File

@@ -146,11 +146,11 @@ public final class MonthDay
/**
* @serial The month-of-year, not null.
*/
private final byte month;
private final int month;
/**
* @serial The day-of-month.
*/
private final byte day;
private final int day;
//-----------------------------------------------------------------------
/**
@@ -319,8 +319,8 @@ public final class MonthDay
* @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31
*/
private MonthDay(int month, int dayOfMonth) {
this.month = (byte) month;
this.day = (byte) dayOfMonth;
this.month = month;
this.day = dayOfMonth;
}
//-----------------------------------------------------------------------

View File

@@ -153,7 +153,7 @@ public final class YearMonth
/**
* @serial The month-of-year, not null.
*/
private final byte month;
private final int month;
//-----------------------------------------------------------------------
/**
@@ -306,7 +306,7 @@ public final class YearMonth
*/
private YearMonth(int year, int month) {
this.year = year;
this.month = (byte) month;
this.month = month;
}
/**

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -137,11 +137,11 @@ public final class HijrahDate
/**
* The month-of-year.
*/
private final transient byte monthOfYear;
private final transient int monthOfYear;
/**
* The day-of-month.
*/
private final transient byte dayOfMonth;
private final transient int dayOfMonth;
//-------------------------------------------------------------------------
/**
@@ -273,8 +273,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = prolepticYear;
this.monthOfYear = (byte) monthOfYear;
this.dayOfMonth = (byte) dayOfMonth;
this.monthOfYear = monthOfYear;
this.dayOfMonth = dayOfMonth;
}
/**
@@ -287,8 +287,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = dateInfo[0];
this.monthOfYear = (byte) dateInfo[1];
this.dayOfMonth = (byte) dateInfo[2];
this.monthOfYear = dateInfo[1];
this.dayOfMonth = dateInfo[2];
}
//-----------------------------------------------------------------------

View File

@@ -859,6 +859,22 @@ public class DerValue {
return readStringInternal(tag_UniversalString, new UTF_32BE());
}
/**
* Checks that the BMPString does not contain any surrogate characters,
* which are outside the Basic Multilingual Plane.
*
* @throws IOException if illegal characters are detected
*/
public void validateBMPString() throws IOException {
String bmpString = getBMPString();
for (int i = 0; i < bmpString.length(); i++) {
if (Character.isSurrogate(bmpString.charAt(i))) {
throw new IOException(
"Illegal character in BMPString, index: " + i);
}
}
}
/**
* Reads the ASN.1 NULL value
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -71,19 +71,7 @@ final class EntrustTLSPolicy {
// OU=(c) 1999 Entrust.net Limited,
// OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),
// O=Entrust.net
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177",
// cacerts alias: affirmtrustcommercialca
// DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
"0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7",
// cacerts alias: affirmtrustnetworkingca
// DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US
"0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B",
// cacerts alias: affirmtrustpremiumca
// DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US
"70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A",
// cacerts alias: affirmtrustpremiumeccca
// DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
"BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423"
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177"
);
// Any TLS Server certificate that is anchored by one of the Entrust

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -28,10 +28,13 @@ package sun.security.x509;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.Charset;
import java.text.Normalizer;
import java.util.*;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.nio.charset.StandardCharsets.UTF_16BE;
import sun.security.util.*;
import sun.security.pkcs.PKCS9Attribute;
@@ -589,6 +592,10 @@ public class AVA implements DerEncoder {
throw new IOException("AVA, extra bytes = "
+ derval.data.available());
}
if (value.tag == DerValue.tag_BMPString) {
value.validateBMPString();
}
}
AVA(DerInputStream in) throws IOException {
@@ -713,7 +720,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, false));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -832,7 +840,8 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr = new String(value.getDataBytes(), UTF_8);
String valStr =
new String(value.getDataBytes(), getCharset(value, true));
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -927,6 +936,39 @@ public class AVA implements DerEncoder {
}
}
/*
* Returns the charset that should be used to decode each DN string type.
*
* This method ensures that multi-byte (UTF8String and BMPString) types
* are decoded using the correct charset and the String forms represent
* the correct characters. For 8-bit ASCII-based types (PrintableString
* and IA5String), we return ISO_8859_1 rather than ASCII, so that the
* complete range of characters can be represented, as many certificates
* do not comply with the Internationalized Domain Name ACE format.
*
* NOTE: this method only supports DirectoryStrings of the types returned
* by isDerString().
*/
private static Charset getCharset(DerValue value, boolean canonical) {
if (canonical) {
return switch (value.tag) {
case DerValue.tag_PrintableString -> ISO_8859_1;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
return switch (value.tag) {
case DerValue.tag_PrintableString,
DerValue.tag_T61String,
DerValue.tag_IA5String,
DerValue.tag_GeneralString -> ISO_8859_1;
case DerValue.tag_BMPString -> UTF_16BE;
case DerValue.tag_UTF8String -> UTF_8;
default -> throw new Error("unexpected tag: " + value.tag);
};
}
boolean hasRFC2253Keyword() {
return AVAKeyword.hasKeyword(oid, RFC2253);
}

View File

@@ -1,27 +0,0 @@
Owner: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Commercial, O=AffirmTrust, C=US
Serial number: 7777062726a9b17c
Valid from: Fri Jan 29 14:06:06 GMT 2010 until: Tue Dec 31 14:06:06 GMT 2030
Signature algorithm name: SHA256withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
-----END CERTIFICATE-----

View File

@@ -1,27 +0,0 @@
Owner: CN=AffirmTrust Networking, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Networking, O=AffirmTrust, C=US
Serial number: 7c4f04391cd4992d
Valid from: Fri Jan 29 14:08:24 GMT 2010 until: Tue Dec 31 14:08:24 GMT 2030
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
-----END CERTIFICATE-----

View File

@@ -1,38 +0,0 @@
Owner: CN=AffirmTrust Premium, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Premium, O=AffirmTrust, C=US
Serial number: 6d8c1446b1a60aee
Valid from: Fri Jan 29 14:10:36 GMT 2010 until: Mon Dec 31 14:10:36 GMT 2040
Signature algorithm name: SHA384withRSA
Subject Public Key Algorithm: 4096-bit RSA key
Version: 3
-----BEGIN CERTIFICATE-----
MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
+jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
KeC2uAloGRwYQw==
-----END CERTIFICATE-----

View File

@@ -1,20 +0,0 @@
Owner: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
Issuer: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US
Serial number: 7497258ac73f7a54
Valid from: Fri Jan 29 14:20:24 GMT 2010 until: Mon Dec 31 14:20:24 GMT 2040
Signature algorithm name: SHA384withECDSA
Subject Public Key Algorithm: 384-bit EC (secp384r1) key
Version: 3
-----BEGIN CERTIFICATE-----
MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
-----END CERTIFICATE-----

View File

@@ -32,7 +32,7 @@ formatVersion=3
# Version of the currency code information in this class.
# It is a serial number that accompanies with each amendment.
dataVersion=179
dataVersion=180
# List of all valid ISO 4217 currency codes.
# To ensure compatibility, do not remove codes.
@@ -147,7 +147,7 @@ IO=USD
# BRUNEI DARUSSALAM
BN=BND
# BULGARIA
BG=BGN
BG=BGN;2025-12-31-22-00-00;EUR
# BURKINA FASO
BF=XOF
# BURUNDI
@@ -193,7 +193,7 @@ HR=EUR
# CUBA
CU=CUP
# Curaçao
CW=ANG;2025-04-01-04-00-00;XCG
CW=XCG
# CYPRUS
CY=EUR
# CZECHIA
@@ -510,7 +510,7 @@ SR=SRD
# SVALBARD AND JAN MAYEN
SJ=NOK
# Sint Maarten (Dutch part)
SX=ANG;2025-04-01-04-00-00;XCG
SX=XCG
# ESWATINI
SZ=SZL
# SWEDEN

View File

@@ -395,7 +395,8 @@ static jboolean is_superclass(context_type *, fullinfo_type);
static void initialize_exception_table(context_type *);
static int instruction_length(unsigned char *iptr, unsigned char *end);
static jboolean isLegalTarget(context_type *, int offset);
static jboolean isLegalOffset(context_type *, int bci, int offset);
static jboolean isLegalTarget(context_type *, int target);
static void verify_constant_pool_type(context_type *, int, unsigned);
static void initialize_dataflow(context_type *);
@@ -1154,9 +1155,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
case JVM_OPC_goto: {
/* Set the ->operand to be the instruction number of the target. */
int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@@ -1170,9 +1171,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
int jump = (((signed char)(code[offset+1])) << 24) +
(code[offset+2] << 16) + (code[offset+3] << 8) +
(code[offset + 4]);
int target = offset + jump;
if (!isLegalTarget(context, target))
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
this_idata->operand.i = code_data[target];
break;
}
@@ -1211,13 +1212,16 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
}
}
saved_operand = NEW(int, keys + 2);
if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0])))
int jump = _ck_ntohl(lpc[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal default target in switch");
saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])];
int target = offset + jump;
saved_operand[keys + 1] = code_data[target];
for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) {
int target = offset + _ck_ntohl(lptr[0]);
if (!isLegalTarget(context, target))
jump = _ck_ntohl(lptr[0]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal branch in tableswitch");
target = offset + jump;
saved_operand[k + 1] = code_data[target];
}
saved_operand[0] = keys + 1; /* number of successors */
@@ -1746,11 +1750,24 @@ static int instruction_length(unsigned char *iptr, unsigned char *end)
/* Given the target of a branch, make sure that it's a legal target. */
static jboolean
isLegalTarget(context_type *context, int offset)
isLegalTarget(context_type *context, int target)
{
int code_length = context->code_length;
int *code_data = context->code_data;
return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
return (target >= 0 && target < code_length && code_data[target] >= 0);
}
/* Given a bci and offset, make sure the offset is valid and the target is legal */
static jboolean
isLegalOffset(context_type *context, int bci, int offset)
{
int code_length = context->code_length;
int *code_data = context->code_data;
int max_offset = 65535; // JVMS 4.11
int min_offset = -65535;
if (offset < min_offset || offset > max_offset) return JNI_FALSE;
int target = bci + offset;
return (target >= 0 && target < code_length && code_data[target] >= 0);
}

View File

@@ -144,9 +144,6 @@ typedef enum awt_toolkit {
TK_WAYLAND = 2
} awt_toolkit;
// TODO when wayland support will be fully implemented change to TK_UNKNOWN
// currently wayland support is not Production-Ready ready so default awt toolkit is X11
// wayland could be chosen manually via passing -Dawt.toolkit.name=WLToolkit argument
static awt_toolkit _awt_toolkit = TK_X11;
/*
@@ -759,33 +756,48 @@ CallJavaMainInNewThread(jlong stack_size, void* args) {
/* Coarse estimation of number of digits assuming the worst case is a 64-bit pid. */
#define MAX_PID_STR_SZ 20
#ifdef __linux
static char*
getToolkitNameByEnv() {
if (_awt_toolkit == TK_UNKNOWN) {
char *xdg_session_type = getenv("XDG_SESSION_TYPE");
if (xdg_session_type != NULL && strcmp(xdg_session_type, "wayland") == 0) {
_awt_toolkit = TK_WAYLAND;
} else if (xdg_session_type != NULL && strcmp(xdg_session_type, "x11") == 0) {
_awt_toolkit = TK_X11;
} else if (getenv("DISPLAY") != NULL) {
_awt_toolkit = TK_X11;
} else if (getenv("WAYLAND_DISPLAY") != NULL) {
_awt_toolkit = TK_WAYLAND;
GetToolkitName(void) {
if (_awt_toolkit == TK_UNKNOWN) { // Prefer WLToolkit, then XToolkit
void* libwayland = dlopen(VERSIONED_JNI_LIB_NAME("wayland-client", "0"), RTLD_LAZY | RTLD_LOCAL);
if (!libwayland) {
// Fallback to any development version available on the system
libwayland = dlopen(JNI_LIB_NAME("wayland-client"), RTLD_LAZY | RTLD_LOCAL);
}
if (libwayland) {
typedef void* (*wl_display_connect_t)(const char*);
typedef void (*wl_display_disconnect_t)(void*);
wl_display_connect_t fp_wl_display_connect = dlsym(libwayland, "wl_display_connect");
wl_display_disconnect_t fp_wl_display_disconnect = dlsym(libwayland, "wl_display_disconnect");
if (fp_wl_display_connect && fp_wl_display_disconnect) {
void* display = fp_wl_display_connect(NULL);
if (display) {
_awt_toolkit = TK_WAYLAND;
fp_wl_display_disconnect(display);
}
}
dlclose(libwayland);
}
}
return _awt_toolkit == TK_WAYLAND ? "WLToolkit" : "XToolkit";
}
#endif // __linux
int
JVMInit(InvocationFunctions* ifn, jlong threadStackSize,
int argc, char **argv,
int mode, char *what, int ret)
{
char *toolkit_name = getToolkitNameByEnv();
#ifdef __linux
char *toolkit_name = GetToolkitName();
size_t toolkit_name_size = JLI_StrLen("-Dawt.toolkit.name=") + JLI_StrLen(toolkit_name) + 1;
char *toolkit_option = (char *)JLI_MemAlloc(toolkit_name_size);
snprintf(toolkit_option, toolkit_name_size, "-Dawt.toolkit.name=%s", toolkit_name);
AddOption(toolkit_option, NULL);
#endif // __linux
ShowSplashScreen();
return ContinueInNewThread(ifn, threadStackSize, argc, argv, mode, what, ret);
@@ -806,7 +818,10 @@ RegisterThread()
jboolean
ProcessPlatformOption(const char *arg)
{
if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=WLToolkit") == 0) {
if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=auto") == 0) {
_awt_toolkit = TK_UNKNOWN;
return JNI_TRUE;
} else if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=WLToolkit") == 0) {
_awt_toolkit = TK_WAYLAND;
return JNI_TRUE;
} else if (JLI_StrCCmp(arg, "-Dawt.toolkit.name=XToolkit") == 0) {

View File

@@ -36,6 +36,7 @@ import java.util.Map;
import java.util.Set;
import jdk.internal.misc.Unsafe;
import jdk.internal.util.ArraysSupport;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;
@@ -284,9 +285,26 @@ class WindowsWatchService
private static final short OFFSETOF_FILENAMELENGTH = 8;
private static final short OFFSETOF_FILENAME = 12;
// size of per-directory buffer for events (FIXME - make this configurable)
// Need to be less than 4*16384 = 65536. DWORD align.
private static final int CHANGES_BUFFER_SIZE = 16 * 1024;
// size of per-directory buffer for events
// Need to be less than 4*16384 = 65536 when monitoring a directory over the network. DWORD align.
private static final int DEFAULT_CHANGES_BUFFER_SIZE = 16 * 1024;
static final int CHANGES_BUFFER_SIZE;
static {
String rawValue = System.getProperty(
"jdk.nio.file.WatchService.bufferSizeToRetrieveEventsPerDirectory",
String.valueOf(DEFAULT_CHANGES_BUFFER_SIZE));
int intValue;
try {
// Clamp to size of per-directory buffer used to retrieve events.
intValue = Math.clamp(
Long.decode(rawValue),
1,
ArraysSupport.SOFT_MAX_ARRAY_LENGTH);
} catch (NumberFormatException e) {
intValue = DEFAULT_CHANGES_BUFFER_SIZE;
}
CHANGES_BUFFER_SIZE = intValue;
}
private final WindowsFileSystem fs;
private final WindowsWatchService watcher;

View File

@@ -27,6 +27,7 @@ package com.apple.eawt;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.desktop.AboutEvent;
import java.awt.desktop.AboutHandler;
@@ -65,8 +66,8 @@ import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import sun.awt.AppContext;
import sun.awt.CGraphicsDevice;
import sun.awt.SunToolkit;
import sun.java2d.SunGraphicsEnvironment;
import sun.util.logging.PlatformLogger;
class _AppEventHandler {
@@ -274,9 +275,14 @@ class _AppEventHandler {
logger.fine("NOTIFY_SCREEN_CHANGE_PARAMETERS");
}
if (AppContext.getAppContext() != null) {
EventQueue.invokeLater(
() -> ((SunGraphicsEnvironment) GraphicsEnvironment.
getLocalGraphicsEnvironment()).displayParametersChanged());
CGraphicsDevice.DisplayConfiguration displayConfiguration = CGraphicsDevice.DisplayConfiguration.get();
EventQueue.invokeLater(() -> {
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
if (gd instanceof CGraphicsDevice) {
((CGraphicsDevice) gd).updateDisplayParameters(displayConfiguration);
}
}
});
}
break;
default:

View File

@@ -34,18 +34,21 @@ import java.awt.Window;
import java.awt.geom.Rectangle2D;
import java.awt.peer.WindowPeer;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import sun.java2d.SunGraphicsEnvironment;
import sun.java2d.MacOSFlags;
import sun.java2d.metal.MTLGraphicsConfig;
import sun.java2d.opengl.CGLGraphicsConfig;
import sun.lwawt.macosx.CThreading;
import sun.util.logging.PlatformLogger;
import static java.awt.peer.ComponentPeer.SET_BOUNDS;
public final class CGraphicsDevice extends GraphicsDevice
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
@@ -67,7 +70,7 @@ public final class CGraphicsDevice extends GraphicsDevice
private DisplayMode originalMode;
private DisplayMode initialMode;
public CGraphicsDevice(final int displayID) {
public CGraphicsDevice(final int displayID, DisplayConfiguration config) {
this.displayID = displayID;
this.initialMode = getDisplayMode();
StringBuilder errorMessage = new StringBuilder();
@@ -91,7 +94,7 @@ public final class CGraphicsDevice extends GraphicsDevice
}
// [JBR] we don't call displayChanged after creating a device, so call it here.
displayChanged();
updateDevice(config);
}
int getDisplayID() {
@@ -174,8 +177,6 @@ public final class CGraphicsDevice extends GraphicsDevice
yResolution = nativeGetYResolution(displayID);
isMirroring = nativeIsMirroring(displayID);
bounds = nativeGetBounds(displayID).getBounds(); //does integer rounding
screenInsets = nativeGetScreenInsets(displayID);
initScaleFactor();
resizeFSWindow(getFullScreenWindow(), bounds);
//TODO configs?
}
@@ -183,29 +184,43 @@ public final class CGraphicsDevice extends GraphicsDevice
/**
* @return false if display parameters were changed, so we need to recreate the device.
*/
boolean updateDevice() {
boolean updateDevice(DisplayConfiguration config) {
int s = scale;
double xr = xResolution, yr = yResolution;
boolean m = isMirroring;
var b = bounds;
updateDisplayParameters(config);
displayChanged();
return s == scale && xr == xResolution && yr == yResolution && m == isMirroring && b.equals(bounds);
}
public void displayParametersChanged() {
Insets newScreenInsets = nativeGetScreenInsets(displayID);
if (!newScreenInsets.equals(screenInsets)) {
public void updateDisplayParameters(DisplayConfiguration config) {
Descriptor desc = config.getDescriptor(displayID);
if (desc == null) return;
if (!desc.screenInsets.equals(screenInsets)) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Screen insets for display(" + displayID + ") changed " +
"[top=" + screenInsets.top + ",left=" + screenInsets.left +
",bottom=" + screenInsets.bottom + ",right=" + screenInsets.right +
"]->[top=" + newScreenInsets.top + ",left=" + newScreenInsets.left +
",bottom=" + newScreenInsets.bottom + ",right=" + newScreenInsets.right +
"]->[top=" + desc.screenInsets.top + ",left=" + desc.screenInsets.left +
",bottom=" + desc.screenInsets.bottom + ",right=" + desc.screenInsets.right +
"]");
}
screenInsets = newScreenInsets;
screenInsets = desc.screenInsets;
}
int newScale = 1;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
newScale = (int) (debugScale >= 1 ? Math.round(debugScale) : (int) desc.scale);
}
if (newScale != scale) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Scale for display(" + displayID + ") changed " + scale + "->" + newScale);
}
scale = newScale;
}
}
@Override
public void paletteChanged() {
// devices do not need to react to this event.
@@ -352,23 +367,6 @@ public final class CGraphicsDevice extends GraphicsDevice
}
}
private void initScaleFactor() {
int _scale = scale;
if (SunGraphicsEnvironment.isUIScaleEnabled()) {
double debugScale = SunGraphicsEnvironment.getDebugScale();
scale = (int) (debugScale >= 1
? Math.round(debugScale)
: nativeGetScaleFactor(displayID));
} else {
scale = 1;
}
if (_scale != scale && logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("current scale = " + _scale + ", new scale = " + scale + " (" + this + ")");
}
}
private static native double nativeGetScaleFactor(int displayID);
private static native void nativeResetDisplayMode();
private static native void nativeSetDisplayMode(int displayID, int w, int h, int bpp, int refrate);
@@ -383,7 +381,37 @@ public final class CGraphicsDevice extends GraphicsDevice
private static native boolean nativeIsMirroring(int displayID);
private static native Insets nativeGetScreenInsets(int displayID);
private static native Rectangle2D nativeGetBounds(int displayID);
private static native void nativeGetDisplayConfiguration(DisplayConfiguration config);
public static final class DisplayConfiguration {
private final Map<Integer, Descriptor> map = new HashMap<>();
private void addDescriptor(int displayID, int top, int left, int bottom, int right, double scale) {
map.put(displayID, new Descriptor(new Insets(top, left, bottom, right), scale));
}
public Descriptor getDescriptor(int displayID) {
return map.get(displayID);
}
public static DisplayConfiguration get() {
try {
return CThreading.executeOnAppKit(() -> {
DisplayConfiguration config = new DisplayConfiguration();
nativeGetDisplayConfiguration(config);
return config;
});
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
}
private static final class Descriptor {
private final Insets screenInsets;
private final double scale;
private Descriptor(Insets screenInsets, double scale) {
this.screenInsets = screenInsets;
this.scale = scale;
}
}
}

View File

@@ -245,6 +245,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
Map<Integer, CGraphicsDevice> old = new HashMap<>(devices);
devices.clear();
mainDisplayID = getMainDisplayID();
CGraphicsDevice.DisplayConfiguration config = CGraphicsDevice.DisplayConfiguration.get();
// initialization of the graphics device may change list of displays on
// hybrid systems via an activation of discrete video.
@@ -252,7 +253,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
// of displays, and then recheck the main display again.
if (!old.containsKey(mainDisplayID)) {
try {
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID));
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID, config));
} catch (IllegalStateException e) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Unable to initialize graphics device for displayID=" +
@@ -268,13 +269,13 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
}
for (int id : displayIDs) {
old.compute(id, (i, d) -> {
if (d != null && d.updateDevice()) {
if (d != null && d.updateDevice(config)) {
// Device didn't change -> reuse
devices.put(i, d);
return null;
} else {
// Device changed -> create new
devices.put(i, new CGraphicsDevice(i));
devices.put(i, new CGraphicsDevice(i, config));
return d;
}
});

View File

@@ -45,7 +45,6 @@ import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.FocusEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowStateListener;
import java.awt.peer.ComponentPeer;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
@@ -1066,33 +1065,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
return isFullScreenMode;
}
private void waitForWindowState(int state) {
if (peer.getState() == state) {
return;
}
Object lock = new Object();
WindowStateListener wsl = new WindowStateListener() {
public void windowStateChanged(WindowEvent e) {
synchronized (lock) {
if (e.getNewState() == state) {
lock.notifyAll();
}
}
}
};
target.addWindowStateListener(wsl);
if (peer.getState() != state) {
synchronized (lock) {
try {
lock.wait();
} catch (InterruptedException ie) {}
}
}
target.removeWindowStateListener(wsl);
}
@Override
public void setWindowState(int windowState) {
if (peer == null || !peer.isVisible()) {
@@ -1114,7 +1086,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
// let's return into the normal states first
// the zoom call toggles between the normal and the max states
unmaximize();
waitForWindowState(Frame.NORMAL);
}
execute(CWrapper.NSWindow::miniaturize);
break;
@@ -1122,7 +1093,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
if (prevWindowState == Frame.ICONIFIED) {
// let's return into the normal states first
execute(CWrapper.NSWindow::deminiaturize);
waitForWindowState(Frame.NORMAL);
}
maximize();
break;

View File

@@ -75,6 +75,19 @@ BOOL isColorMatchingEnabled() {
return (BOOL)colorMatchingEnabled;
}
BOOL isWindowAnimationEnabled() {
static int windowAnimationEnabled = -1;
if (windowAnimationEnabled == -1) {
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
if (env == NULL) return NO;
NSString* windowAnimationEnabledProp = [PropertiesUtilities javaSystemPropertyForKey:@"apple.awt.window.animation"
withEnv:env];
windowAnimationEnabled = [@"true" isCaseInsensitiveLike:windowAnimationEnabledProp] ? YES : NO;
J2dRlsTraceLn(J2D_TRACE_INFO, "AWTWindow_windowAnimationEnabled: %d", windowAnimationEnabled);
}
return (BOOL)windowAnimationEnabled;
}
@interface NSTitlebarAccessoryViewController (Private)
- (void)_setHidden:(BOOL)h animated:(BOOL)a;
@end
@@ -605,6 +618,10 @@ AWT_ASSERT_APPKIT_THREAD;
if (self.nsWindow == nil) return nil; // no hope either
[self.nsWindow release]; // the property retains the object already
if (!isWindowAnimationEnabled()
&& (self.nsWindow.animationBehavior != NSWindowAnimationBehaviorNone)) {
self.nsWindow.animationBehavior = NSWindowAnimationBehaviorNone;
}
if (isColorMatchingEnabled()) {
// Supported by both OpenGL & Metal pipelines
// Tell the system we have an sRGB backing store
@@ -3008,8 +3025,6 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetRoundedCor
NSWindow *w = (NSWindow *)jlong_to_ptr(windowPtr);
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
w.hasShadow = YES;
w.contentView.wantsLayer = YES;
w.contentView.layer.cornerRadius = radius;
w.contentView.layer.masksToBounds = YES;
w.contentView.layer.opaque = NO;
@@ -3024,11 +3039,11 @@ JNIEXPORT void JNICALL Java_sun_lwawt_macosx_CPlatformWindow_nativeSetRoundedCor
w.contentView.layer.borderWidth = borderWidth;
w.contentView.layer.borderColor = color.CGColor;
}
w.contentView.wantsLayer = YES;
w.backgroundColor = NSColor.clearColor;
w.opaque = NO;
// remove corner radius animation
[w.contentView.layer removeAllAnimations];
w.hasShadow = YES;
[w invalidateShadow];
}];

View File

@@ -363,47 +363,6 @@ Java_sun_awt_CGraphicsDevice_nativeGetBounds
return CGToJavaRect(env, rect);
}
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetScreenInsets
* Signature: (I)D
*/
JNIEXPORT jobject JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScreenInsets
(JNIEnv *env, jclass class, jint displayID)
{
jobject ret = NULL;
__block NSRect frame = NSZeroRect;
__block NSRect visibleFrame = NSZeroRect;
JNI_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
if ([screenID unsignedIntValue] == displayID){
frame = [screen frame];
visibleFrame = [screen visibleFrame];
break;
}
}
}];
// Convert between Cocoa's coordinate system and Java.
jint bottom = visibleFrame.origin.y - frame.origin.y;
jint top = frame.size.height - visibleFrame.size.height - bottom;
jint left = visibleFrame.origin.x - frame.origin.x;
jint right = frame.size.width - visibleFrame.size.width - left;
DECLARE_CLASS_RETURN(jc_Insets, "java/awt/Insets", ret);
DECLARE_METHOD_RETURN(jc_Insets_ctor, jc_Insets, "<init>", "(IIII)V", ret);
ret = (*env)->NewObject(env, jc_Insets, jc_Insets_ctor, top, left, bottom, right);
JNI_COCOA_EXIT(env);
return ret;
}
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeResetDisplayMode
@@ -557,31 +516,39 @@ Java_sun_awt_CGraphicsDevice_nativeGetDisplayModes
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetScaleFactor
* Signature: (I)D
* Method: nativeGetDisplayConfiguration
* Signature: (Lsun/awt/CGraphicsDevice$DisplayConfiguration;)V
*/
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScaleFactor
(JNIEnv *env, jclass class, jint displayID)
{
__block jdouble ret = 1.0f;
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayConfiguration
(JNIEnv *env, jclass class, jobject config) {
AWT_ASSERT_APPKIT_THREAD;
JNI_COCOA_ENTER(env);
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
if ([screenID unsignedIntValue] == displayID){
if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
ret = [screen backingScaleFactor];
}
break;
}
DECLARE_CLASS(jc_DisplayConfiguration, "sun/awt/CGraphicsDevice$DisplayConfiguration");
DECLARE_METHOD(jc_DisplayConfiguration_addDescriptor, jc_DisplayConfiguration, "addDescriptor", "(IIIIID)V");
NSArray *screens = [NSScreen screens];
for (NSScreen *screen in screens) {
NSDictionary *screenInfo = [screen deviceDescription];
NSNumber *screenID = [screenInfo objectForKey:@"NSScreenNumber"];
jint displayID = [screenID unsignedIntValue];
jdouble scale = 1.0;
if ([screen respondsToSelector:@selector(backingScaleFactor)]) {
scale = [screen backingScaleFactor];
}
}];
NSRect frame = [screen frame];
NSRect visibleFrame = [screen visibleFrame];
// Convert between Cocoa's coordinate system and Java.
jint bottom = visibleFrame.origin.y - frame.origin.y;
jint top = frame.size.height - visibleFrame.size.height - bottom;
jint left = visibleFrame.origin.x - frame.origin.x;
jint right = frame.size.width - visibleFrame.size.width - left;
(*env)->CallVoidMethod(env, config, jc_DisplayConfiguration_addDescriptor,
displayID, top, left, bottom, right, scale);
}
JNI_COCOA_EXIT(env);
return ret;
}

View File

@@ -116,6 +116,7 @@ static void displaycb_handle
(CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo)
{
AWT_ASSERT_APPKIT_THREAD;
JNIEnv *env = [ThreadUtilities getJNIEnv];
JNI_COCOA_ENTER(env);
if (TRACE_DISPLAY_CALLBACKS) {
@@ -152,7 +153,6 @@ JNI_COCOA_ENTER(env);
block:^()
{
@try {
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef);
if (graphicsEnv == NULL) return; // ref already GC'd
DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");
@@ -173,7 +173,6 @@ JNI_COCOA_ENTER(env);
// braces to reduce variable scope
{
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject graphicsEnv = (*env)->NewLocalRef(env, cgeRef);
if (graphicsEnv == NULL) return; // ref already GC'd
DECLARE_CLASS(jc_CGraphicsEnvironment, "sun/awt/CGraphicsEnvironment");

View File

@@ -311,11 +311,11 @@ static const struct SymbolicHotKey defaultSymbolicHotKeys[] = {
[Shortcut_FullScreenTileRight] = { "FullScreenTileRight", "Windows: Full-Screen Tile Right", YES, 65535, 65535, 0, 15, 4 },
};
static const int numSymbolicHotkeys = sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]);
#define NUM_SYMBOLIC_HOTKEYS (sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]))
static struct SystemHotkeyState {
bool symbolicHotkeysFilled;
struct SymbolicHotKey currentSymbolicHotkeys[numSymbolicHotkeys];
struct SymbolicHotKey currentSymbolicHotkeys[NUM_SYMBOLIC_HOTKEYS];
bool initialized;
bool enabled;
@@ -398,7 +398,7 @@ static void visitServicesShortcut(Visitor visitorBlock, NSString * key_equivalen
visitorBlock(-1, keyChar.UTF8String, modifiers, desc.UTF8String, -1, NULL);
}
static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS]) {
// Called from the main thread
@try {
@@ -425,7 +425,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
return;
}
memcpy(hotkeys, defaultSymbolicHotKeys, numSymbolicHotkeys * sizeof(struct SymbolicHotKey));
memcpy(hotkeys, defaultSymbolicHotKeys, NUM_SYMBOLIC_HOTKEYS * sizeof(struct SymbolicHotKey));
for (id keyObj in hkObj) {
if (![keyObj isKindOfClass:[NSString class]]) {
@@ -438,7 +438,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
int uid = [hkNumber intValue];
// Ignore hotkeys out of range, as well as 0, which is the "invalid value" for intValue
if (uid <= 0 || uid >= numSymbolicHotkeys) {
if (uid <= 0 || uid >= NUM_SYMBOLIC_HOTKEYS) {
continue;
}
@@ -512,7 +512,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
}
static void updateAppleSymbolicHotkeysCache() {
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
readAppleSymbolicHotkeys(hotkeys);
pthread_mutex_lock(&state.mutex);
@@ -521,10 +521,10 @@ static void updateAppleSymbolicHotkeysCache() {
pthread_mutex_unlock(&state.mutex);
}
static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys], Visitor visitorBlock) {
static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS], Visitor visitorBlock) {
const NSOperatingSystemVersion macOSVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
for (int uid = 0; uid < numSymbolicHotkeys; ++uid) {
for (int uid = 0; uid < NUM_SYMBOLIC_HOTKEYS; ++uid) {
struct SymbolicHotKey* hotkey = &hotkeys[uid];
if (!hotkey->enabled) {
@@ -646,12 +646,12 @@ static bool ensureInitializedAndEnabled() {
return true;
}
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
pthread_mutex_lock(&state.mutex);
if (state.symbolicHotkeysFilled) {
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
}
pthread_mutex_unlock(&state.mutex);
}
@@ -661,7 +661,7 @@ static void readSystemHotkeysImpl(Visitor visitorBlock) {
return;
}
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
readAppleSymbolicHotkeysCached(hotkeys);
iterateAppleSymbolicHotkeys(hotkeys, visitorBlock);

View File

@@ -67,9 +67,17 @@ static jclass sjc_CAccessibility = NULL;
jobject axComponent = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility,
sjm_getCurrentAccessiblePopupMenu,
fAccessible, fComponent);
CHECK_EXCEPTION();
if (axComponent == NULL) {
return nil;
}
CommonComponentAccessibility *currentElement = [CommonComponentAccessibility createWithAccessible:axComponent
withEnv:env withView:self->fView isCurrent:YES];
(*env)->DeleteLocalRef(env, axComponent);
if (currentElement == nil) {
return nil;
}
NSArray *children = [CommonComponentAccessibility childrenOfParent:currentElement
withEnv:env

View File

@@ -112,6 +112,13 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
NSLock* _lock;
}
+ (NSUInteger) getDrawableId:(id<MTLDrawable>)mtlDrawable {
if (@available(macOS 10.15.4, *)) {
return [mtlDrawable drawableID];
}
return -1;
}
- (id) initWithJavaLayer:(jobject)layer usePerfCounters:(jboolean)perfCountersEnabled
{
AWT_ASSERT_APPKIT_THREAD;
@@ -129,6 +136,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
[NSNull null], @"anchorPoint",
[NSNull null], @"bounds",
[NSNull null], @"contents",
[NSNull null], @"cornerRadius",
[NSNull null], @"contentsScale",
[NSNull null], @"onOrderIn",
[NSNull null], @"onOrderOut",
@@ -245,12 +253,12 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
#if TRACE_DISPLAY_ON
self.avgNextDrawableTime = nextDrawableLatency * a + self.avgNextDrawableTime * (1.0 - a);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
CACurrentMediaTime(), mtlDrawable.drawableID,
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture: drawable(%d) presented"
" - nextDrawableLatency = %.3lf ms - average = %.3lf ms",
CACurrentMediaTime(), [MTLLayer getDrawableId:mtlDrawable],
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
);
#endif
}
// Keep Fence from now:
@@ -283,7 +291,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) presented"
" - presentedHandlerLatency = %.3lf ms frameInterval = %.3lf ms",
CACurrentMediaTime(), drawable.drawableID,
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
1000.0 * presentedHandlerLatency, 1000.0 * frameInterval
);
self.lastPresentedTime = presentedTime;
@@ -298,7 +306,8 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) skipped"
" - presentedHandlerLatency = %.3lf ms",
CACurrentMediaTime(), drawable.drawableID, 1000.0 * presentedHandlerLatency
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
1000.0 * presentedHandlerLatency
);
}
}
@@ -308,7 +317,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
// Present drawable:
NSUInteger drawableId = -1;
if (TRACE_DISPLAY) {
drawableId = mtlDrawable.drawableID;
drawableId = [MTLLayer getDrawableId:mtlDrawable];
J2dRlsTraceLn(J2D_TRACE_INFO,
"[%.6lf] MTLLayer.blitTexture: layer[%p] present drawable(%d)",
CACurrentMediaTime(), self, drawableId);

View File

@@ -63,6 +63,7 @@ AWT_ASSERT_APPKIT_THREAD;
[NSNull null], @"anchorPoint",
[NSNull null], @"bounds",
[NSNull null], @"contents",
[NSNull null], @"cornerRadius",
[NSNull null], @"contentsScale",
[NSNull null], @"onOrderIn",
[NSNull null], @"onOrderOut",

View File

@@ -254,8 +254,11 @@ AWT_ASSERT_APPKIT_THREAD;
* Note : if waiting cross-thread, possibly the stack allocated copy is accessible ?
*/
+ (void)invokeBlockCopy:(void (^)(void))blockCopy {
blockCopy();
Block_release(blockCopy);
@try {
blockCopy();
} @finally {
Block_release(blockCopy);
}
}
+ (NSString*)getCaller:(NSString*)prefixSymbol {
@@ -780,9 +783,18 @@ JNIEXPORT void lwc_plog(JNIEnv* env, const char *formatMsg, ...) {
const NSUInteger count = [self.queue count];
if (count != 0) {
for (NSUInteger i = 0; i < count; i++) {
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
// invoke callback:
[ThreadUtilities invokeBlockCopy:blockCopy];
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
@try {
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
// invoke callback:
[ThreadUtilities invokeBlockCopy:blockCopy];
} @catch (NSException *exception) {
// handle any exception to avoid crashing the main run loop:
NSLog(@"Apple AWT Cocoa Exception: %@", [exception description]);
NSLog(@"Apple AWT Cocoa Exception callstack: %@", [exception callStackSymbols]);
} @finally {
[pool drain];
}
}
// reset queue anyway:
[self reset];

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2025 JetBrains s.r.o.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.jetbrains.desktop;
import com.jetbrains.exported.JBRApi;
import sun.java2d.vulkan.VKEnv;
import sun.java2d.vulkan.VKGPU;
@JBRApi.Service
@JBRApi.Provides("Vulkan")
public class Vulkan {
Vulkan() {
if (!VKEnv.isVulkanEnabled()) throw new JBRApi.ServiceNotAvailableException("Vulkan is not enabled");
}
boolean isPresentationEnabled() {
return VKEnv.isPresentationEnabled();
}
Device[] getDevices() {
return VKEnv.getDevices().map(Device::new).toArray(Device[]::new);
}
@JBRApi.Provides("Vulkan.Device")
static class Device {
private final VKGPU device;
Device(VKGPU device) {
this.device = device;
}
String getName() {
return device.getName();
}
String getTypeString() {
return device.getType().toString();
}
int getCapabilities() {
return device.getCaps();
}
}
}

View File

@@ -4377,11 +4377,6 @@ public class Window extends Container implements Accessible {
}
}
@Override
public void addWindowListener(Window w, WindowListener listener) {
w.addWindowListener(listener);
}
private static void dumpCounter(final String counterName, final double valPerSecond) {
if (USE_COUNTERS) {
doLog(String.format("%s per second: %.2f", counterName, valPerSecond),

View File

@@ -37,7 +37,6 @@ import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowListener;
import java.awt.image.BufferStrategy;
import java.awt.peer.ComponentPeer;
@@ -338,8 +337,6 @@ public final class AWTAccessor {
double getCounterPerSecond(Window w, String counterName);
void dumpStats(Window w, boolean reset, StringBuilder sb);
void addWindowListener(Window w, WindowListener listener);
}
/**

View File

@@ -44,7 +44,6 @@ import java.util.Locale;
import java.util.TreeMap;
import sun.awt.DisplayChangedListener;
import sun.awt.DisplayParametersChangedListener;
import sun.awt.SunDisplayChanger;
import sun.font.FontManager;
import sun.font.FontManagerFactory;
@@ -60,7 +59,7 @@ import sun.java2d.pipe.Region;
* @see GraphicsConfiguration
*/
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
implements DisplayChangedListener, DisplayParametersChangedListener {
implements DisplayChangedListener {
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
@@ -276,15 +275,6 @@ public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
displayChanger.notifyListeners();
}
@Override
public void displayParametersChanged() {
for (GraphicsDevice gd : getScreenDevices()) {
if (gd instanceof DisplayParametersChangedListener) {
((DisplayParametersChangedListener) gd).displayParametersChanged();
}
}
}
/**
* Part of the DisplayChangedListener interface:
* propagate this event to listeners

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -144,7 +144,9 @@ final class Curve {
// finds points where the first and second derivative are
// perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where
// * is a dot product). Unfortunately, we have to solve a cubic.
private int perpendiculardfddf(final double[] pts, final int off) {
private int perpendiculardfddf(final double[] pts, final int off,
final double A, final double B)
{
assert pts.length >= off + 4;
// these are the coefficients of some multiple of g(t) (not g(t),
@@ -155,7 +157,7 @@ final class Curve {
final double c = 2.0d * (dax * cx + day * cy) + dbx * dbx + dby * dby;
final double d = dbx * cx + dby * cy;
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d);
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, A, B);
}
// Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
@@ -171,35 +173,43 @@ final class Curve {
// at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection
// points, so roc-w can have at least 6 roots. This shouldn't be a
// problem for what we're trying to do (draw a nice looking curve).
int rootsOfROCMinusW(final double[] roots, final int off, final double w2, final double err) {
int rootsOfROCMinusW(final double[] roots, final int off, final double w2,
final double A, final double B)
{
// no OOB exception, because by now off<=6, and roots.length >= 10
assert off <= 6 && roots.length >= 10;
int ret = off;
final int end = off + perpendiculardfddf(roots, off);
final int end = off + perpendiculardfddf(roots, off, A, B);
Helpers.isort(roots, off, end);
roots[end] = 1.0d; // always check interval end points
double t0 = 0.0d, ft0 = ROCsq(t0) - w2;
double t0 = 0.0d;
double ft0 = eliminateInf(ROCsq(t0) - w2);
double t1, ft1;
for (int i = off; i <= end; i++) {
double t1 = roots[i], ft1 = ROCsq(t1) - w2;
t1 = roots[i];
ft1 = eliminateInf(ROCsq(t1) - w2);
if (ft0 == 0.0d) {
roots[ret++] = t0;
} else if (ft1 * ft0 < 0.0d) { // have opposite signs
// (ROC(t)^2 == w^2) == (ROC(t) == w) is true because
// ROC(t) >= 0 for all t.
roots[ret++] = falsePositionROCsqMinusX(t0, t1, w2, err);
roots[ret++] = falsePositionROCsqMinusX(t0, t1, ft0, ft1, w2, A); // A = err
}
t0 = t1;
ft0 = ft1;
}
return ret - off;
}
private static double eliminateInf(final double x) {
return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE :
(x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x));
private final static double MAX_ROC_SQ = 1e20;
private static double eliminateInf(final double x2) {
// limit the value of x to avoid numerical problems (smaller step):
// must handle NaN and +Infinity:
return (x2 <= MAX_ROC_SQ) ? x2 : MAX_ROC_SQ;
}
// A slight modification of the false position algorithm on wikipedia.
@@ -210,17 +220,18 @@ final class Curve {
// and turn out. Same goes for the newton's method
// algorithm in Helpers.java
private double falsePositionROCsqMinusX(final double t0, final double t1,
final double ft0, final double ft1,
final double w2, final double err)
{
final int iterLimit = 100;
int side = 0;
double t = t1, ft = eliminateInf(ROCsq(t) - w2);
double s = t0, fs = eliminateInf(ROCsq(s) - w2);
double s = t0, fs = eliminateInf(ft0);
double t = t1, ft = eliminateInf(ft1);
double r = s, fr;
for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
for (int i = 0; i < iterLimit && Math.abs(t - s) > err; i++) {
r = (fs * t - ft * s) / (fs - ft);
fr = ROCsq(r) - w2;
fr = eliminateInf(ROCsq(r) - w2);
if (sameSign(fr, ft)) {
ft = fr; t = r;
if (side < 0) {
@@ -241,7 +252,7 @@ final class Curve {
break;
}
}
return r;
return (Math.abs(ft) <= Math.abs(fs)) ? t : s;
}
private static boolean sameSign(final double x, final double y) {
@@ -256,9 +267,9 @@ final class Curve {
final double dy = t * (t * day + dby) + cy;
final double ddx = 2.0d * dax * t + dbx;
final double ddy = 2.0d * day * t + dby;
final double dx2dy2 = dx * dx + dy * dy;
final double ddx2ddy2 = ddx * ddx + ddy * ddy;
final double ddxdxddydy = ddx * dx + ddy * dy;
return dx2dy2 * ((dx2dy2 * dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy * ddxdxddydy));
final double dx2dy2 = dx * dx + dy * dy; // positive
final double dxddyddxdy = dx * ddy - dy * ddx;
// may return +Infinity if dxddyddxdy = 0 or NaN if 0/0:
return (dx2dy2 * dx2dy2 * dx2dy2) / (dxddyddxdy * dxddyddxdy); // both positive
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -564,7 +564,7 @@ public final class DMarlinRenderingEngine extends RenderingEngine
}
private static boolean nearZero(final double num) {
return Math.abs(num) < 2.0d * Math.ulp(num);
return Math.abs(num) < 2.0d * Helpers.ulp(num);
}
abstract static class NormalizingPathIterator implements PathIterator {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,12 +31,19 @@ import sun.java2d.marlin.stats.StatLong;
final class Helpers implements MarlinConst {
private final static double T_ERR = 1e-4;
private final static double T_A = T_ERR;
private final static double T_B = 1.0 - T_ERR;
private static final double EPS = 1e-9d;
private Helpers() {
throw new Error("This is a non instantiable class");
}
/** use lower precision like former Pisces and Marlin (float-precision) */
static double ulp(final double value) { return Math.ulp((float)value); }
static boolean within(final double x, final double y) {
return within(x, y, EPS);
}
@@ -322,10 +329,10 @@ final class Helpers implements MarlinConst {
// now we must subdivide at points where one of the offset curves will have
// a cusp. This happens at ts where the radius of curvature is equal to w.
ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d);
ret += c.rootsOfROCMinusW(ts, ret, w2, T_A, T_B);
ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d);
isort(ts, ret);
ret = filterOutNotInAB(ts, 0, ret, T_A, T_B);
isort(ts, 0, ret);
return ret;
}
@@ -354,7 +361,7 @@ final class Helpers implements MarlinConst {
if ((outCodeOR & OUTCODE_BOTTOM) != 0) {
ret += curve.yPoints(ts, ret, clipRect[1]);
}
isort(ts, ret);
isort(ts, 0, ret);
return ret;
}
@@ -374,11 +381,11 @@ final class Helpers implements MarlinConst {
}
}
static void isort(final double[] a, final int len) {
for (int i = 1, j; i < len; i++) {
static void isort(final double[] a, final int off, final int len) {
for (int i = off + 1, j; i < len; i++) {
final double ai = a[i];
j = i - 1;
for (; j >= 0 && a[j] > ai; j--) {
for (; j >= off && a[j] > ai; j--) {
a[j + 1] = a[j];
}
a[j + 1] = ai;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -886,8 +886,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
// if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4,
// in which case ignore if p1 == p2
final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Math.ulp(y2));
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Math.ulp(y4));
final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Helpers.ulp(y2));
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Helpers.ulp(y4));
if (p1eqp2 && p3eqp4) {
return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
@@ -905,7 +905,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
final double l1sq = dx1 * dx1 + dy1 * dy1;
final double l4sq = dx4 * dx4 + dy4 * dy4;
if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Math.ulp(dotsq))) {
if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Helpers.ulp(dotsq))) {
return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff);
}
@@ -1078,8 +1078,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
// equal if they're very close to each other.
// if p1 == p2 or p2 == p3: draw line from p1->p3
final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Math.ulp(y2));
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Math.ulp(y3));
final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Helpers.ulp(y2));
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Helpers.ulp(y3));
if (p1eqp2 || p2eqp3) {
return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
@@ -1091,7 +1091,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst {
final double l1sq = dx12 * dx12 + dy12 * dy12;
final double l3sq = dx23 * dx23 + dy23 * dy23;
if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) {
if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Helpers.ulp(dotsq))) {
return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@ package sun.java2d.marlin;
public final class Version {
private static final String VERSION = "marlin-0.9.4.7-Unsafe-OpenJDK";
private static final String VERSION = "marlin-0.9.4.9-Unsafe-OpenJDK";
public static String getVersion() {
return VERSION;

View File

@@ -31,18 +31,20 @@ package sun.java2d.marlin.stats;
public class StatLong {
public final String name;
public long count, sum, min, max;
public long count = 0L;
public long sum = 0L;
public long min = Integer.MAX_VALUE;
public long max = Integer.MIN_VALUE;
public StatLong(final String name) {
this.name = name;
reset();
}
public void reset() {
count = 0L;
sum = 0L;
min = Long.MAX_VALUE;
max = Long.MIN_VALUE;
min = Integer.MAX_VALUE;
max = Integer.MIN_VALUE;
}
public void add(final int val) {
@@ -76,7 +78,7 @@ public class StatLong {
sb.append(name).append('[').append(count);
sb.append("] sum: ").append(sum).append(" avg: ");
sb.append(trimTo3Digits(((double) sum) / count));
sb.append(" [").append(min).append(" - ").append(max).append("]");
sb.append(" [").append(min).append(" | ").append(max).append("]");
return sb;
}
@@ -87,7 +89,7 @@ public class StatLong {
* @return double value with only 3 decimal digits
*/
public static double trimTo3Digits(final double value) {
return Double.isFinite(value) ? ((long) (1e3d * value)) / 1e3d : Double.NaN;
return ((long) (1e3d * value)) / 1e3d;
}
}

View File

@@ -48,7 +48,7 @@ public final class VKEnv {
@SuppressWarnings("removal")
private static final boolean accelsd = vulkan && "true".equalsIgnoreCase(AccessController.doPrivileged(
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "")));
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "true")));
@SuppressWarnings("removal")
private static final int deviceNumber = !vulkan ? 0 : AccessController.doPrivileged(

View File

@@ -36,6 +36,7 @@ import sun.java2d.loops.CompositeType;
import sun.java2d.loops.GraphicsPrimitive;
import sun.java2d.loops.SurfaceType;
import static sun.java2d.pipe.BufferedOpCodes.CONFIGURE_SURFACE;
import static sun.java2d.pipe.BufferedOpCodes.DISPOSE_SURFACE;
import sun.java2d.pipe.BufferedContext;
import sun.java2d.pipe.ParallelogramPipe;
import sun.java2d.pipe.PixelToParallelogramConverter;
@@ -43,7 +44,6 @@ import sun.java2d.pipe.RenderBuffer;
import sun.java2d.pipe.TextPipe;
import sun.java2d.pipe.hw.AccelSurface;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
@@ -137,6 +137,28 @@ public abstract class VKSurfaceData extends SurfaceData
}
}
/**
* Disposes the native resources associated with the given VKSurfaceData
* (referenced by the pData parameter). This method is invoked from
* the native Dispose() method from the Disposer thread when the
* Java-level VKSurfaceData object is about to go away.
*/
static void dispose(long pData) {
VKRenderQueue rq = VKRenderQueue.getInstance();
rq.lock();
try {
RenderBuffer buf = rq.getBuffer();
rq.ensureCapacityAndAlignment(12, 4);
buf.putInt(DISPOSE_SURFACE);
buf.putLong(pData);
// this call is expected to complete synchronously, so flush now
rq.flushNow();
} finally {
rq.unlock();
}
}
public BufferedImage getSnapshot(int x, int y, int width, int height) {
BufferedImage image = getFormat().createCompatibleImage(width, height, getTransparency());
SurfaceData sd = SurfaceData.getPrimarySurfaceData(image);

View File

@@ -1,20 +0,0 @@
#define ALPHA_TYPE_PRE_MULTIPLIED 0U
#define ALPHA_TYPE_STRAIGHT 1U
vec4 convertAlpha(vec4 color, uint inType, uint outType) {
if (inType == ALPHA_TYPE_STRAIGHT && outType == ALPHA_TYPE_PRE_MULTIPLIED) {
return vec4(color.rgb * color.a, color.a);
} else if (inType == ALPHA_TYPE_PRE_MULTIPLIED && outType == ALPHA_TYPE_STRAIGHT && color.a > 0.0) {
return vec4(color.rgb / color.a, color.a);
} else return color;
}
#ifdef ALPHA_TYPE_SPEC_INDEX
layout (constant_id = ALPHA_TYPE_SPEC_INDEX ) const uint const_InAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
layout (constant_id = ALPHA_TYPE_SPEC_INDEX+1) const uint const_OutAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
vec4 convertAlpha(vec4 color) {
return convertAlpha(color, const_InAlphaType, const_OutAlphaType);
}
#endif

View File

@@ -1,7 +1,7 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#define ALPHA_TYPE_SPEC_INDEX 0
#include "alpha_type.glsl"
#include "common.glsl"
DEFAULT_PUSH_CONSTANTS();
layout(set = 0, binding = 0) uniform texture2D u_Texture;
layout(set = 1, binding = 0) uniform sampler u_Sampler;
@@ -9,5 +9,5 @@ layout(location = 0) in vec2 in_TexCoord;
layout(location = 0) out vec4 out_Color;
void main() {
out_Color = convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord));
out_Color = APPLY_COMPOSITE(convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord)));
}

View File

@@ -1,14 +1,12 @@
#version 450
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in vec2 in_Position;
layout(location = 1) in vec2 in_TexCoord;
layout(location = 0) out vec2 out_TexCoord;
void main() {
gl_Position = vec4(vec3(in_Position, 1.0)*push.transform, 0.0, 1.0);
gl_Position = transformToDeviceSpace(in_Position);
out_TexCoord = in_TexCoord;
}

View File

@@ -1,11 +1,9 @@
#version 450
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in ivec2 in_Position;
void main() {
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
gl_Position = transformToDeviceSpace(in_Position);
}

View File

@@ -1,14 +1,12 @@
#version 450
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in vec2 in_Position;
layout(location = 1) in vec4 in_Color;
layout(location = 1) in uint in_Color;
layout(location = 0) out flat vec4 out_Color;
void main() {
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
out_Color = in_Color;
gl_Position = transformToDeviceSpace(in_Position);
out_Color = convertAlpha(decodeColor(in_Color)); // No need to APPLY_COMPOSITE - it was already done on the host.
}

View File

@@ -0,0 +1,103 @@
// Shader specialization.
#define SHADER_MOD_XOR 1U // Xor composite mode
#define SHADER_MOD_MASK 2U // MASK_FILL / MASK_BLIT
layout (constant_id = 0) const uint const_InAlphaType = 0;
layout (constant_id = 1) const uint const_OutAlphaType = 0;
layout (constant_id = 2) const uint const_ShaderVariant = 0;
layout (constant_id = 3) const uint const_ShaderModifier = 0;
// Host structs.
struct VKTransform {
float m00, m01, m02;
float m10, m11, m12;
};
struct VKCompositeConstants {
uint xorColor;
float extraAlpha;
};
// Vertex shader transformation support.
#ifdef STAGE_VERT
layout(push_constant) uniform PushConstants { VKTransform transform; } push;
vec4 transformToDeviceSpace(vec2 v) {
return vec4(vec3(v, 1.0) * mat2x3(push.transform.m00, push.transform.m01, push.transform.m02, push.transform.m10, push.transform.m11, push.transform.m12), 0.0, 1.0);
}
#endif
// Fragment shader push constant support.
#ifdef STAGE_FRAG
#define PUSH_CONSTANTS_IMPL(STATEMENT) \
layout(push_constant) uniform PushConstants { VKTransform _; VKCompositeConstants push_composite; STATEMENT }
#define DEFAULT_PUSH_CONSTANTS() PUSH_CONSTANTS_IMPL(STAGE_FRAG)
#define PUSH_CONSTANTS(TYPE) PUSH_CONSTANTS_IMPL(TYPE push;)
#endif
// Color conversion support.
#define ALPHA_TYPE_PRE_MULTIPLIED 0U
#define ALPHA_TYPE_STRAIGHT 1U
vec4 convertAlpha(vec4 color, uint inType, uint outType) {
if (inType == ALPHA_TYPE_STRAIGHT && outType == ALPHA_TYPE_PRE_MULTIPLIED) {
return vec4(color.rgb * color.a, color.a);
} else if (inType == ALPHA_TYPE_PRE_MULTIPLIED && outType == ALPHA_TYPE_STRAIGHT && color.a > 0.0) {
return vec4(color.rgb / color.a, color.a);
} else return color;
}
vec4 convertAlpha(vec4 color) {
return convertAlpha(color, const_InAlphaType, const_OutAlphaType);
}
// When applying alpha to a color, straight alpha only multiplies alpha,
// and pre-multiplied multiplies the whole color. Use this for convenience.
vec4 alphaMask(float alpha, uint alphaType) {
return alphaType == ALPHA_TYPE_PRE_MULTIPLIED ? vec4(alpha) : vec4(1.0, 1.0, 1.0, alpha);
}
// Decode color from uint-packed ARGB components.
vec4 decodeColor(uint srgb) {
return vec4((uvec4(srgb) >> uvec4(16, 8, 0, 24)) & 0xFFU) / 255.0;
}
#ifdef STAGE_FRAG
// Before outputting the color, some post-processing is needed:
// - For alpha composite, apply extra alpha.
// - For XOR composite, apply xor.
vec4 applyComposite(vec4 color, VKCompositeConstants composite) {
if ((const_ShaderModifier & SHADER_MOD_XOR) != 0) {
uvec4 xor = uvec4(composite.xorColor) >> uvec4(16, 8, 0, 24);
xor = (uvec4(color * 255.0) ^ xor) & 0xFFU;
return vec4(xor) / 255.0;
} else return color * alphaMask(composite.extraAlpha, const_OutAlphaType);
}
#define APPLY_COMPOSITE(COLOR) applyComposite(COLOR, push_composite)
// MASK_FILL / MASK_BLIT support.
int calculateMaskIndex(vec2 localCoord, ivec4 originOffsetAndScanline) {
ivec2 maskPos = ivec2(localCoord - vec2(originOffsetAndScanline.xy));
int offset = originOffsetAndScanline.z;
int scanline = originOffsetAndScanline.w;
return offset + scanline * maskPos.y + min(scanline, maskPos.x);
}
vec4 applyMaskOp(vec4 color, float mask) {
if ((const_ShaderModifier & SHADER_MOD_XOR) != 0) return color * float(mask > 0.0);
else return color * alphaMask(mask, const_OutAlphaType);
}
#define APPLY_MASK(COLOR) applyMaskOp(COLOR, imageLoad(u_Mask, calculateMaskIndex(gl_FragCoord.xy, in_OriginOffsetAndScanline)).r)
// Generic shader support.
#define GENERIC_INOUT() \
layout(location = 0) out vec4 out_Color; \
layout(location = 0) in vec2 in_Position; \
layout(location = 1) in flat uint in_Data; \
layout(location = 2) in flat ivec4 in_OriginOffsetAndScanline; \
layout(origin_upper_left) in vec4 gl_FragCoord; \
layout(set = 0, binding = 0, r8) uniform readonly restrict imageBuffer u_Mask
// Generic color output - handles composite and mask automatically.
#define OUTPUT(COLOR) out_Color = COLOR; out_Color = APPLY_COMPOSITE(out_Color); \
if ((const_ShaderModifier & SHADER_MOD_MASK) != 0) out_Color = APPLY_MASK(out_Color)
#endif

View File

@@ -0,0 +1,21 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
#define SHADER_VARIANT_GRADIENT_CLAMP 0
#define SHADER_VARIANT_GRADIENT_CYCLE 1
struct VKGradientPaintConstants {
vec4 c0, c1;
vec3 p;
};
PUSH_CONSTANTS(VKGradientPaintConstants);
GENERIC_INOUT();
void main() {
float t = dot(vec3(in_Position, 1.0), push.p);
t = const_ShaderVariant == SHADER_VARIANT_GRADIENT_CYCLE ?
abs(mod(t + 1.0, 2.0) - 1.0) : // Cycle
clamp(t, 0.0, 1.0); // Clamp
OUTPUT(convertAlpha(mix(push.c0, push.c1, t)));
}

View File

@@ -0,0 +1,21 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
layout(location = 1) in uint in_Data;
layout(location = 0) out vec2 out_Position;
layout(location = 1) out uint out_Data;
// This starts with "Origin" and not "Position" intentionally.
// When drawing, vertices are ordered in a such way, that provoking vertex is always the top-left one.
// This gives us an easy way to calculate offset within the rectangle without additional inputs.
layout(location = 2) out flat ivec4 out_OriginOffsetAndScanline;
void main() {
out_Position = in_PositionOffsetAndScanline.xy;
out_Data = in_Data;
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
gl_Position = transformToDeviceSpace(in_PositionOffsetAndScanline.xy);
}

View File

@@ -1,4 +1,6 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(set = 0, binding = 0, r8) uniform readonly restrict imageBuffer u_Mask;
@@ -10,9 +12,5 @@ layout(location = 1) in flat vec4 in_Color;
layout(location = 0) out vec4 out_Color;
void main() {
ivec2 maskPos = ivec2(gl_FragCoord.xy - vec2(in_OriginOffsetAndScanline.xy));
int offset = in_OriginOffsetAndScanline.z;
int scanline = in_OriginOffsetAndScanline.w;
int maskIndex = offset + scanline * maskPos.y + min(scanline, maskPos.x);
out_Color = in_Color * imageLoad(u_Mask, maskIndex).r;
out_Color = APPLY_MASK(in_Color);
}

View File

@@ -1,11 +1,9 @@
#version 450
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
layout(location = 1) in vec4 in_Color;
layout(location = 1) in uint in_Color;
// This starts with "Origin" and not "Position" intentionally.
// When drawing, vertices are ordered in a such way, that provoking vertex is always the top-left one.
@@ -14,7 +12,7 @@ layout(location = 0) out flat ivec4 out_OriginOffsetAndScanline;
layout(location = 1) out flat vec4 out_Color;
void main() {
gl_Position = vec4(vec3(in_PositionOffsetAndScanline.xy, 1)*push.transform, 0.0, 1.0);
gl_Position = transformToDeviceSpace(in_PositionOffsetAndScanline.xy);
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
out_Color = in_Color;
out_Color = convertAlpha(decodeColor(in_Color));
}

View File

@@ -0,0 +1,15 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(location = 0) in vec2 in_Position;
layout(location = 1) in uint in_Data;
layout(location = 0) out vec2 out_Position;
layout(location = 1) out uint out_Data;
layout(location = 2) out flat ivec4 _; // Unused output
void main() {
out_Position = in_Position;
out_Data = in_Data;
gl_Position = transformToDeviceSpace(in_Position);
}

View File

@@ -63,7 +63,7 @@
#define TRACE_USE_API 0
#define TRACE_REUSE 0
#define INIT_TEST 1
#define INIT_TEST 0
#define INIT_TEST_STEP 1
#define INIT_TEST_MAX 1024

View File

@@ -113,7 +113,7 @@ void VKBlitLoops_IsoBlit(VKSDOps* srcOps, jint filter,
VK_COMPONENT_SWIZZLE_ONE);
VKPackedSwizzle swizzle = srcOpaque ? OPAQUE_SWIZZLE : 0;
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
VKRenderer_DrawImage(srcOps->image, srcOps->image->format, swizzle, filter, SAMPLER_WRAP_BORDER,
(float)sx1, (float)sy1, (float)sx2, (float)sy2, (float)dx1, (float)dy1, (float)dx2, (float)dy2);
VKRenderer_AddSurfaceDependency(srcOps, context->surface);
@@ -154,7 +154,7 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
}
if (srcInfo.bounds.x2 > srcInfo.bounds.x1 && srcInfo.bounds.y2 > srcInfo.bounds.y1) {
src->GetRasInfo(env, src, &srcInfo);
if (srcInfo.rasBase) {
while (srcInfo.rasBase) {
if (srcInfo.bounds.x1 != sx1) dx1 += (srcInfo.bounds.x1 - sx1) * (dx2 - dx1) / (sx2 - sx1);
if (srcInfo.bounds.y1 != sy1) dy1 += (srcInfo.bounds.y1 - sy1) * (dy2 - dy1) / (sy2 - sy1);
if (srcInfo.bounds.x2 != sx2) dx2 += (srcInfo.bounds.x2 - sx2) * (dx2 - dx1) / (sx2 - sx1);
@@ -165,13 +165,17 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
// Need to validate render pass early, as image may not yet be configured.
AlphaType alphaType = getSrcAlphaType(srctype);
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
if (!VKRenderer_Validate(SHADER_BLIT, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) break;
VKDevice* device = context->surface->device;
BlitSrcType type = decodeSrcType(device, srctype);
VKTexturePoolHandle* imageHandle =
VKTexturePool_GetTexture(VKRenderer_GetTexturePool(device->renderer), sw, sh, type.format);
VKImage* image = VKTexturePoolHandle_GetTexture(imageHandle);
if (!image) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKBlitLoops_Blit: could not get texture from the pool");
break;
}
VkDeviceSize dataSize = sh * sw * srcInfo.pixelStride;
VKBuffer buffer;
@@ -232,7 +236,9 @@ void VKBlitLoops_Blit(JNIEnv *env, SurfaceDataOps* src, jshort srctype, jint fil
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeTexture, imageHandle);
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeBuffer, buffer.handle);
VKRenderer_ExecOnCleanup(context->surface, VKBlitLoops_DisposeMemory, page);
} else {
break;
}
if (!srcInfo.rasBase) {
J2dRlsTraceLn(J2D_TRACE_ERROR, "VKBlitLoops_Blit: could not get raster info");
}
SurfaceData_InvokeRelease(env, src, &srcInfo);

View File

@@ -56,7 +56,7 @@ VKComposites VKComposites_Create() {
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT },
{ .logicOpEnable = VK_TRUE,
.logicOp = VK_LOGIC_OP_XOR }, ALPHA_TYPE_PRE_MULTIPLIED });
.logicOp = VK_LOGIC_OP_XOR }, ALPHA_TYPE_STRAIGHT });
// NAME | SRC_COLOR | DST_COLOR | SRC_ALPHA | DST_ALPHA ||
ALPHA_BLEND( CLEAR , ZERO , ZERO , ZERO , ZERO );
@@ -138,7 +138,6 @@ void VKComposites_AddState(VKComposites* composites, VKCompositeMode mode, VKCom
state.blendState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
state.blendState.pNext = NULL;
state.blendState.attachmentCount = 1;
state.outAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
MAP_AT(composites->map, (VKCompositeDescriptor) { mode, VK_FALSE }) = state;
// Using pre-multiplied alpha is necessary for correct blending,

View File

@@ -49,6 +49,7 @@ static size_t pipelineDescriptorHash(const void* ptr) {
hash(&h, d->inAlphaType);
hash(&h, d->composite);
hash(&h, d->shader);
hash(&h, d->shaderVariant);
hash(&h, d->topology);
return (size_t) h;
}
@@ -59,6 +60,7 @@ static bool pipelineDescriptorEquals(const void* ap, const void* bp) {
a->inAlphaType == b->inAlphaType &&
a->composite == b->composite &&
a->shader == b->shader &&
a->shaderVariant == b->shaderVariant &&
a->topology == b->topology;
}
@@ -144,12 +146,20 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
VkPipelineShaderStageCreateInfo createInfos[2]; // vert + frag
} ShaderStages;
ShaderStages stages[count];
typedef struct {
uint32_t inAlphaType, outAlphaType, shaderVariant, shaderModifier;
} SpecializationData;
const VkSpecializationMapEntry SPECIALIZATION_ENTRIES[] = {
{ 0, 0, 4 },
{ 1, 4, 4 },
{ 2, 8, 4 },
{ 3, 12, 4 }
};
typedef struct {
VkSpecializationInfo info;
VkSpecializationMapEntry entries[2];
uint64_t data[1];
SpecializationData data;
} Specialization;
Specialization specializations[count][2];
Specialization specializations[count];
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStates[count];
VkPipelineDepthStencilStateCreateInfo depthStencilStates[count];
VkPipelineDynamicStateCreateInfo dynamicStates[count];
@@ -163,14 +173,19 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
// - pStages (but stageCount is set to 2)
// - pVertexInputState
// - createInfo.layout
for (uint32_t j = 0; j < SARRAY_COUNT_OF(specializations[i]); j++) {
specializations[i][j].info = (VkSpecializationInfo) {
.mapEntryCount = 0,
.pMapEntries = specializations[i][j].entries,
.dataSize = 0,
.pData = specializations[i][j].data
};
}
specializations[i] = (Specialization) {
.info = {
.mapEntryCount = SARRAY_COUNT_OF(SPECIALIZATION_ENTRIES),
.pMapEntries = SPECIALIZATION_ENTRIES,
.dataSize = sizeof(SpecializationData),
.pData = &specializations[i].data
},
.data = {
descriptors[i].inAlphaType, pipelineInfos[i].outAlphaType, (uint32_t) descriptors[i].shaderVariant,
(descriptors[i].composite == LOGIC_COMPOSITE_XOR ? 1 : 0) |
(descriptors[i].shader & SHADER_MASK ? 2 : 0)
}
};
inputAssemblyStates[i] = (VkPipelineInputAssemblyStateCreateInfo) {
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
.topology = descriptors[i].topology
@@ -234,37 +249,38 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
}
// Setup input states.
MAKE_INPUT_STATE(COLOR, VKColorVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32B32A32_SFLOAT);
MAKE_INPUT_STATE(MASK_FILL_COLOR, VKMaskFillColorVertex, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32G32B32A32_SFLOAT);
MAKE_INPUT_STATE(PRIMITIVE, VKVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32_UINT);
MAKE_INPUT_STATE(MASK_FILL, VKMaskFillVertex, VK_FORMAT_R32G32B32A32_SINT, VK_FORMAT_R32_UINT);
MAKE_INPUT_STATE(BLIT, VKTxVertex, VK_FORMAT_R32G32_SFLOAT, VK_FORMAT_R32G32_SFLOAT);
MAKE_INPUT_STATE(CLIP, VKIntVertex, VK_FORMAT_R32G32_SINT);
for (uint32_t i = 0; i < count; i++) {
// Setup shader-specific pipeline parameters.
switch (descriptors[i].shader) {
switch ((int) descriptors[i].shader) {
case SHADER_COLOR:
createInfos[i].pVertexInputState = &INPUT_STATE_COLOR;
createInfos[i].layout = pipelineContext->colorPipelineLayout;
createInfos[i].pVertexInputState = &INPUT_STATE_PRIMITIVE;
createInfos[i].layout = pipelineContext->commonPipelineLayout;
stages[i] = (ShaderStages) {{ shaders->color_vert, shaders->color_frag }};
break;
case SHADER_MASK_FILL_COLOR:
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL_COLOR;
case SHADER_COLOR | SHADER_MASK:
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL;
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
stages[i] = (ShaderStages) {{ shaders->mask_fill_color_vert, shaders->mask_fill_color_frag }};
break;
case SHADER_GRADIENT:
createInfos[i].pVertexInputState = &INPUT_STATE_PRIMITIVE;
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
stages[i] = (ShaderStages) {{ shaders->primitive_vert, shaders->gradient_frag }};
break;
case SHADER_GRADIENT | SHADER_MASK:
createInfos[i].pVertexInputState = &INPUT_STATE_MASK_FILL;
createInfos[i].layout = pipelineContext->maskFillPipelineLayout;
stages[i] = (ShaderStages) {{ shaders->mask_fill_vert, shaders->gradient_frag }};
break;
case SHADER_BLIT:
createInfos[i].pVertexInputState = &INPUT_STATE_BLIT;
createInfos[i].layout = pipelineContext->texturePipelineLayout;
stages[i] = (ShaderStages) {{ shaders->blit_vert, shaders->blit_frag }};
// Alpha conversion specialization.
uint32_t* spec = (uint32_t*) specializations[i][1].data;
spec[0] = descriptors[i].inAlphaType;
spec[1] = pipelineInfos[i].outAlphaType;
specializations[i][1].info.dataSize = 8;
specializations[i][1].entries[0] = (VkSpecializationMapEntry) { 0, 0, 4 };
specializations[i][1].entries[1] = (VkSpecializationMapEntry) { 1, 4, 4 };
specializations[i][1].info.mapEntryCount = 2;
stages[i].createInfos[1].pSpecializationInfo = &specializations[i][1].info;
break;
case SHADER_CLIP:
createInfos[i].pVertexInputState = &INPUT_STATE_CLIP;
@@ -290,6 +306,9 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
default:
VK_FATAL_ERROR("Cannot create pipeline, unknown shader requested!");
}
for (uint32_t j = 0; j < createInfos[i].stageCount; j++) {
stages[i].createInfos[j].pSpecializationInfo = &specializations[i].info;
}
assert(createInfos[i].pDynamicState->dynamicStateCount <= MAX_DYNAMIC_STATES);
J2dRlsTraceLn(J2D_TRACE_INFO, "VKPipelines_CreatePipelines: stencilMode=%d, dstOpaque=%d, composite=%d, shader=%d, topology=%d",
descriptors[i].stencilMode, descriptors[i].dstOpaque, descriptors[i].composite, descriptors[i].shader, descriptors[i].topology);
@@ -303,6 +322,7 @@ static VKPipelineInfo VKPipelines_CreatePipelines(VKRenderPassContext* renderPas
J2dRlsTraceLn(J2D_TRACE_INFO, "VKPipelines_CreatePipelines: created %d pipelines", count);
for (uint32_t i = 0; i < count; i++) {
pipelineInfos[i].pipeline = pipelines[i];
pipelineInfos[i].layout = createInfos[i].layout;
MAP_AT(renderPassContext->pipelines, descriptors[i]) = pipelineInfos[i];
}
return pipelineInfos[0];
@@ -403,21 +423,49 @@ static VkResult VKPipelines_InitPipelineLayouts(VKDevice* device, VKPipelineCont
assert(device != NULL && pipelines != NULL);
VkResult result;
// We want all our pipelines to have same push constant range to ensure common state is compatible between pipelines.
VkPushConstantRange pushConstantRange = {
// We want all our pipelines to have the same push constant ranges to ensure a common state is compatible between pipelines.
VkPushConstantRange pushConstantRanges[] = {{
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(VKTransform)
};
}, {
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.offset = PUSH_CONSTANTS_OFFSET,
.size = PUSH_CONSTANTS_SIZE
}};
// Common pipeline.
VkPipelineLayoutCreateInfo createInfo = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 0,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pushConstantRange
.pushConstantRangeCount = SARRAY_COUNT_OF(pushConstantRanges),
.pPushConstantRanges = pushConstantRanges
};
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->colorPipelineLayout);
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->commonPipelineLayout);
VK_IF_ERROR(result) return result;
// Mask fill pipeline.
VkDescriptorSetLayoutBinding maskBufferLayoutBinding = {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &maskBufferLayoutBinding
};
result = device->vkCreateDescriptorSetLayout(device->handle, &descriptorSetLayoutCreateInfo, NULL, &pipelines->maskFillDescriptorSetLayout);
VK_IF_ERROR(result) return result;
createInfo.setLayoutCount = 1;
createInfo.pSetLayouts = &pipelines->maskFillDescriptorSetLayout;
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->maskFillPipelineLayout);
VK_IF_ERROR(result) return result;
// Texture pipeline.
VkDescriptorSetLayoutBinding textureLayoutBinding = {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
@@ -437,31 +485,11 @@ static VkResult VKPipelines_InitPipelineLayouts(VKDevice* device, VKPipelineCont
pipelines->textureDescriptorSetLayout,
pipelines->samplers.descriptorSetLayout
};
createInfo.setLayoutCount = 2;
createInfo.setLayoutCount = SARRAY_COUNT_OF(textureDescriptorSetLayouts);
createInfo.pSetLayouts = textureDescriptorSetLayouts;
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->texturePipelineLayout);
VK_IF_ERROR(result) return result;
VkDescriptorSetLayoutBinding maskBufferLayoutBinding = {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
.pImmutableSamplers = NULL
};
VkDescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &maskBufferLayoutBinding
};
result = device->vkCreateDescriptorSetLayout(device->handle, &descriptorSetLayoutCreateInfo, NULL, &pipelines->maskFillDescriptorSetLayout);
VK_IF_ERROR(result) return result;
createInfo.setLayoutCount = 1;
createInfo.pSetLayouts = &pipelines->maskFillDescriptorSetLayout;
result = device->vkCreatePipelineLayout(device->handle, &createInfo, NULL, &pipelines->maskFillPipelineLayout);
VK_IF_ERROR(result) return result;
return VK_SUCCESS;
}
@@ -504,7 +532,7 @@ void VKPipelines_DestroyContext(VKPipelineContext* pipelineContext) {
VKPipelines_DestroyShaders(device, pipelineContext->shaders);
device->vkDestroyPipelineLayout(device->handle, pipelineContext->colorPipelineLayout, NULL);
device->vkDestroyPipelineLayout(device->handle, pipelineContext->commonPipelineLayout, NULL);
device->vkDestroyPipelineLayout(device->handle, pipelineContext->texturePipelineLayout, NULL);
device->vkDestroyDescriptorSetLayout(device->handle, pipelineContext->textureDescriptorSetLayout, NULL);
device->vkDestroyPipelineLayout(device->handle, pipelineContext->maskFillPipelineLayout, NULL);

View File

@@ -36,13 +36,26 @@
* Shader programs.
*/
typedef enum {
// Base shaders.
SHADER_COLOR,
SHADER_MASK_FILL_COLOR,
SHADER_GRADIENT,
SHADER_BLIT,
SHADER_CLIP,
NO_SHADER = 0x7FFFFFFF
NO_SHADER = 0x7FFFFFFF,
// Mask modifier bit (MASK_FILL & MASK_BLIT).
SHADER_MASK = ~NO_SHADER
} VKShader;
/**
* Shader variant.
* It is used to specialize shader behavior, and its meaning varies with each particular shader.
*/
typedef enum {
SHADER_VARIANT_GRADIENT_CLAMP = 0,
SHADER_VARIANT_GRADIENT_CYCLE = 1,
NO_SHADER_VARIANT = 0x7FFFFFFF
} VKShaderVariant;
typedef enum {
STENCIL_MODE_NONE = 0, // No stencil attachment.
STENCIL_MODE_OFF = 1, // Has stencil attachment, stencil test disabled.
@@ -59,12 +72,14 @@ typedef struct {
AlphaType inAlphaType : 1;
VKCompositeMode composite;
VKShader shader;
VKShaderVariant shaderVariant;
VkPrimitiveTopology topology;
} VKPipelineDescriptor;
typedef struct {
VkPipeline pipeline;
AlphaType outAlphaType;
VkPipeline pipeline;
VkPipelineLayout layout;
AlphaType outAlphaType;
} VKPipelineInfo;
/**
@@ -72,7 +87,7 @@ typedef struct {
*/
struct VKPipelineContext {
VKDevice* device;
VkPipelineLayout colorPipelineLayout;
VkPipelineLayout commonPipelineLayout;
VkDescriptorSetLayout textureDescriptorSetLayout;
VkPipelineLayout texturePipelineLayout;
VkDescriptorSetLayout maskFillDescriptorSetLayout;
@@ -93,14 +108,42 @@ struct VKRenderPassContext {
MAP(VKPipelineDescriptor, VKPipelineInfo) pipelines;
};
typedef struct {
unsigned int xorColor;
float extraAlpha;
} VKCompositeConstants;
typedef struct {
RGBA c0, c1;
float p0, p1, p3;
} VKGradientPaintConstants;
typedef union {
// The minimum guaranteed size of push constants is 128 bytes.
alignas(32) // The maximum alignment for built-in glsl types is 32 bytes (dvec4).
char data[(128 - sizeof(VKTransform) - sizeof(VKCompositeConstants)) / 32 * 32];
VKGradientPaintConstants gradientPaint;
} VKShaderConstants;
#define MAX_SHADER_CONSTANTS_SIZE 96 // We expect 96 bytes
typedef char VKShaderConstantsCheckOffset[sizeof(VKShaderConstants) == MAX_SHADER_CONSTANTS_SIZE ? 1 : -1]; // Verify.
typedef struct {
VKTransform transform;
VKCompositeConstants composite;
VKShaderConstants shader;
} VKPushConstants;
typedef char VKPushConstantsCheckSize[sizeof(VKPushConstants) <= 128 ? 1 : -1]; // We should not exceed 128 bytes.
static const uint32_t PUSH_CONSTANTS_OFFSET = (uintptr_t) &((VKPushConstants*) NULL)->composite;
static const uint32_t PUSH_CONSTANTS_SIZE = sizeof(VKPushConstants) - PUSH_CONSTANTS_OFFSET;
typedef struct {
int x, y;
} VKIntVertex;
typedef struct {
float x, y;
RGBA color;
} VKColorVertex;
unsigned int data;
} VKVertex;
typedef struct {
float px, py;
@@ -109,8 +152,8 @@ typedef struct {
typedef struct {
int x, y, maskOffset, maskScanline;
RGBA color;
} VKMaskFillColorVertex;
unsigned int data;
} VKMaskFillVertex;
VKPipelineContext* VKPipelines_CreateContext(VKDevice* device);
void VKPipelines_DestroyContext(VKPipelineContext* pipelines);

View File

@@ -93,6 +93,21 @@
#define OFFSET_XFORM sun_java2d_vulkan_VKBlitLoops_OFFSET_XFORM
#define OFFSET_ISOBLIT sun_java2d_vulkan_VKBlitLoops_OFFSET_ISOBLIT
static void applyXor() {
if (VKRenderer_GetContext()->shader == SHADER_COLOR) {
VKRenderer_GetContext()->vertexData ^= VKRenderer_GetContext()->constants.composite.xorColor;
}
}
static void setComposite(VKCompositeMode comp, unsigned int xorColor, float extraAlpha) {
VKRenderer_GetContext()->composite = comp;
if (VKRenderer_GetContext()->constants.composite.xorColor != xorColor ||
VKRenderer_GetContext()->constants.composite.extraAlpha != extraAlpha) {
VKRenderer_GetContext()->constants.composite = (VKCompositeConstants) { xorColor, extraAlpha };
VKRenderer_GetContext()->constantsModCount++;
}
}
JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
(JNIEnv *env, jobject oglrq, jlong buf, jint limit)
{
@@ -476,30 +491,26 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
jint flags = NEXT_INT(b);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: SET_ALPHA_COMPOSITE(%d, %f, %d)", rule, extraAlpha, flags);
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
VKRenderer_GetContext()->composite = (VKCompositeMode) rule;
VKRenderer_GetContext()->extraAlpha = extraAlpha;
applyXor();
setComposite((VKCompositeMode) rule, 0, extraAlpha);
}
break;
case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
{
jint xorPixel = NEXT_INT(b);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: SET_XOR_COMPOSITE");
VKRenderer_GetContext()->renderColor = VKUtil_DecodeJavaColor(xorPixel, ALPHA_TYPE_STRAIGHT);
// TODO Fix XOR mode!
// VKRenderer_GetContext()->renderColor.a = 0.0f; // Alpha is left unchanged in XOR mode.
VKRenderer_GetContext()->composite = LOGIC_COMPOSITE_XOR;
VKRenderer_GetContext()->extraAlpha = 1.0f;
"VKRenderQueue_flushBuffer: SET_XOR_COMPOSITE(0x%08x)", xorPixel);
applyXor();
setComposite(LOGIC_COMPOSITE_XOR, xorPixel, -1.0f);
applyXor();
}
break;
case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
{
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: RESET_COMPOSITE");
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
VKRenderer_GetContext()->composite = ALPHA_COMPOSITE_SRC;
VKRenderer_GetContext()->extraAlpha = 1.0f;
applyXor();
setComposite(ALPHA_COMPOSITE_SRC, 0, 1.0f);
}
break;
case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
@@ -522,8 +533,8 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
};
VKRenderingContext* context = VKRenderer_GetContext();
if (VK_IS_NEQ_TRANSFORM(&context->transform, &transform)) {
context->transform = transform;
if (VK_IS_NEQ_TRANSFORM(&context->constants.transform, &transform)) {
context->constants.transform = transform;
context->transformModCount++;
}
}
@@ -533,8 +544,8 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: RESET_TRANSFORM");
VKRenderingContext* context = VKRenderer_GetContext();
if (VK_IS_NEQ_TRANSFORM(&context->transform, &VK_ID_TRANSFORM)) {
context->transform = VK_ID_TRANSFORM;
if (VK_IS_NEQ_TRANSFORM(&context->constants.transform, &VK_ID_TRANSFORM)) {
context->constants.transform = VK_ID_TRANSFORM;
context->transformModCount++;
}
}
@@ -568,9 +579,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
break;
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_SURFACE:
{
jlong pData = NEXT_LONG(b);
VKSDOps* surface = NEXT_VK_SURFACE(b);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: DISPOSE_SURFACE");
VKSD_ResetSurface(surface);
}
break;
case sun_java2d_pipe_BufferedOpCodes_DISPOSE_CONFIG:
@@ -643,31 +655,34 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
break;
case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
{
jint javaColor = NEXT_INT(b);
VKRenderer_GetContext()->color = VKUtil_DecodeJavaColor(javaColor, ALPHA_TYPE_STRAIGHT);
if (COMPOSITE_GROUP(VKRenderer_GetContext()->composite) == ALPHA_COMPOSITE_GROUP) {
VKRenderer_GetContext()->renderColor = VKRenderer_GetContext()->color;
}
J2dRlsTraceLn(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: SET_COLOR(0x%08x)", javaColor);
J2dTraceLn(J2D_TRACE_VERBOSE, // Print color values with straight alpha for convenience.
" srgb={%.3f, %.3f, %.3f, %.3f}",
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).r,
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).g,
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).b,
VKUtil_GetRGBA(VKRenderer_GetContext()->color, ALPHA_TYPE_STRAIGHT).a);
VKRenderer_GetContext()->inAlphaType = ALPHA_TYPE_STRAIGHT;
VKRenderer_GetContext()->shader = SHADER_COLOR;
VKRenderer_GetContext()->shaderVariant = NO_SHADER_VARIANT;
VKRenderer_GetContext()->vertexData = NEXT_INT(b);
applyXor();
J2dRlsTraceLn(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: SET_COLOR(0x%08x)", VKRenderer_GetContext()->vertexData);
}
break;
case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
{
jboolean useMask= NEXT_BOOLEAN(b);
jboolean cyclic = NEXT_BOOLEAN(b);
jdouble p0 = NEXT_DOUBLE(b);
jdouble p1 = NEXT_DOUBLE(b);
jdouble p3 = NEXT_DOUBLE(b);
jint pixel1 = NEXT_INT(b);
jint pixel2 = NEXT_INT(b);
jboolean useMask = NEXT_BOOLEAN(b); // Unused.
jboolean cyclic = NEXT_BOOLEAN(b);
jdouble p0 = NEXT_DOUBLE(b);
jdouble p1 = NEXT_DOUBLE(b);
jdouble p3 = NEXT_DOUBLE(b);
jint pixel1 = NEXT_INT(b);
jint pixel2 = NEXT_INT(b);
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"VKRenderQueue_flushBuffer: SET_GRADIENT_PAINT");
VKRenderer_GetContext()->inAlphaType = ALPHA_TYPE_PRE_MULTIPLIED;
VKRenderer_GetContext()->shader = SHADER_GRADIENT;
VKRenderer_GetContext()->shaderVariant = cyclic ? SHADER_VARIANT_GRADIENT_CYCLE : SHADER_VARIANT_GRADIENT_CLAMP;
VKRenderer_GetContext()->constants.shader.gradientPaint = (VKGradientPaintConstants) {
VKUtil_GetRGBA(VKUtil_DecodeJavaColor(pixel1, ALPHA_TYPE_PRE_MULTIPLIED), ALPHA_TYPE_PRE_MULTIPLIED),
VKUtil_GetRGBA(VKUtil_DecodeJavaColor(pixel2, ALPHA_TYPE_PRE_MULTIPLIED), ALPHA_TYPE_PRE_MULTIPLIED),
p0*2.0, p1*2.0, p3*2.0-0.5
};
VKRenderer_GetContext()->constantsModCount++;
}
break;
case sun_java2d_pipe_BufferedOpCodes_SET_LINEAR_GRADIENT_PAINT:

View File

@@ -164,6 +164,7 @@ struct VKRenderPass {
BufferWritingState maskFillBufferWriting;
VKPipelineDescriptor state;
uint64_t constantsModCount; // Just a tag to detect when constants were changed.
uint64_t transformModCount; // Just a tag to detect when transform was changed.
uint64_t clipModCount; // Just a tag to detect when clip was changed.
VkBool32 pendingFlush : 1;
@@ -176,12 +177,17 @@ struct VKRenderPass {
// which is only called from queue flusher thread, no need for synchronization.
static VKRenderingContext context = {
.surface = NULL,
.transform = VK_ID_TRANSFORM,
.transformModCount = 1,
.color = {},
.renderColor = {},
.composite = ALPHA_COMPOSITE_SRC_OVER,
.extraAlpha = 1.0f,
.inAlphaType = ALPHA_TYPE_UNKNOWN,
.shader = NO_SHADER,
.shaderVariant = NO_SHADER_VARIANT,
.vertexData = 0,
.constantsModCount = 1,
.transformModCount = 1,
.constants = {
.transform = VK_ID_TRANSFORM,
.composite = { 0, 1.0f }
},
.clipModCount = 1,
.clipRect = NO_CLIP,
.clipSpanVertices = NULL
@@ -221,7 +227,7 @@ static VkBool32 VKRenderer_CheckPoolDrain(void* pool, void* entry) {
return VK_FALSE;
}
#define VERTEX_BUFFER_SIZE (128 * 1024) // 128KiB - enough to draw 910 quads (6 verts) with VKColorVertex.
#define VERTEX_BUFFER_SIZE (128 * 1024) // 128KiB - enough to draw 1820 quads (6 verts) with VKVertex.
#define VERTEX_BUFFER_PAGE_SIZE (1 * 1024 * 1024) // 1MiB - fits 8 buffers.
static void VKRenderer_FindVertexBufferMemoryType(VKMemoryRequirements* requirements) {
VKAllocator_FindMemoryType(requirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
@@ -597,33 +603,47 @@ inline void VKRenderer_FlushDraw(VKSDOps* surface) {
static void VKRenderer_ResetDrawing(VKSDOps* surface) {
assert(surface != NULL && surface->renderPass != NULL);
VKRenderer* renderer = surface->device->renderer;
surface->renderPass->state.composite = NO_COMPOSITE;
surface->renderPass->state.shader = NO_SHADER;
surface->renderPass->transformModCount = 0;
surface->renderPass->firstVertex = 0;
surface->renderPass->vertexCount = 0;
surface->renderPass->vertexBufferWriting = (BufferWritingState) {NULL, 0, VK_FALSE};
surface->renderPass->maskFillBufferWriting = (BufferWritingState) {NULL, 0, VK_FALSE};
if (ARRAY_SIZE(surface->renderPass->flushRanges) > 0) {
VKRenderPass* renderPass = surface->renderPass;
renderPass->state.composite = NO_COMPOSITE;
renderPass->state.shader = NO_SHADER;
renderPass->constantsModCount = 0;
renderPass->transformModCount = 0;
renderPass->firstVertex = 0;
renderPass->vertexCount = 0;
renderPass->vertexBufferWriting = (BufferWritingState) { NULL, 0, VK_FALSE };
renderPass->maskFillBufferWriting = (BufferWritingState) { NULL, 0, VK_FALSE };
if (ARRAY_SIZE(renderPass->flushRanges) > 0) {
VK_IF_ERROR(surface->device->vkFlushMappedMemoryRanges(surface->device->handle,
ARRAY_SIZE(surface->renderPass->flushRanges), surface->renderPass->flushRanges)) {}
ARRAY_RESIZE(surface->renderPass->flushRanges, 0);
ARRAY_SIZE(renderPass->flushRanges), renderPass->flushRanges)) {}
ARRAY_RESIZE(renderPass->flushRanges, 0);
}
size_t vertexBufferCount = ARRAY_SIZE(surface->renderPass->vertexBuffers);
size_t maskFillBufferCount = ARRAY_SIZE(surface->renderPass->maskFillBuffers);
size_t cleanupQueueCount = ARRAY_SIZE(surface->renderPass->cleanupQueue);
size_t vertexBufferCount = ARRAY_SIZE(renderPass->vertexBuffers);
size_t maskFillBufferCount = ARRAY_SIZE(renderPass->maskFillBuffers);
size_t cleanupQueueCount = ARRAY_SIZE(renderPass->cleanupQueue);
for (uint32_t i = 0; i < vertexBufferCount; i++) {
POOL_RETURN(surface->device->renderer, vertexBufferPool, surface->renderPass->vertexBuffers[i]);
POOL_RETURN(renderer, vertexBufferPool, renderPass->vertexBuffers[i]);
}
for (uint32_t i = 0; i < maskFillBufferCount; i++) {
POOL_RETURN(surface->device->renderer, maskFillBufferPool, surface->renderPass->maskFillBuffers[i]);
POOL_RETURN(renderer, maskFillBufferPool, renderPass->maskFillBuffers[i]);
}
for (uint32_t i = 0; i < cleanupQueueCount; i++) {
POOL_RETURN(surface->device->renderer, cleanupQueue, surface->renderPass->cleanupQueue[i]);
POOL_RETURN(renderer, cleanupQueue, renderPass->cleanupQueue[i]);
}
ARRAY_RESIZE(surface->renderPass->vertexBuffers, 0);
ARRAY_RESIZE(surface->renderPass->maskFillBuffers, 0);
ARRAY_RESIZE(surface->renderPass->cleanupQueue, 0);
ARRAY_RESIZE(renderPass->vertexBuffers, 0);
ARRAY_RESIZE(renderPass->maskFillBuffers, 0);
ARRAY_RESIZE(renderPass->cleanupQueue, 0);
// Update dependencies on used surfaces.
for (uint32_t i = 0, surfaces = (uint32_t) ARRAY_SIZE(renderPass->usedSurfaces); i < surfaces; i++) {
VKSDOps* usedSurface = renderPass->usedSurfaces[i];
uint32_t newSize = 0, oldSize = (uint32_t) ARRAY_SIZE(usedSurface->dependentSurfaces);
for (uint32_t j = 0; j < oldSize; j++) {
VKSDOps* s = usedSurface->dependentSurfaces[j];
if (s != surface) usedSurface->dependentSurfaces[newSize++] = s;
}
if (newSize != oldSize) ARRAY_RESIZE(usedSurface->dependentSurfaces, newSize);
}
ARRAY_RESIZE(renderPass->usedSurfaces, 0);
}
/**
@@ -711,6 +731,7 @@ static VkBool32 VKRenderer_InitRenderPass(VKSDOps* surface) {
.composite = NO_COMPOSITE,
.shader = NO_SHADER
},
.constantsModCount = 0,
.transformModCount = 0,
.clipModCount = 0,
.pendingFlush = VK_FALSE,
@@ -877,19 +898,11 @@ VkBool32 VKRenderer_FlushRenderPass(VKSDOps* surface) {
VKRenderer* renderer = device->renderer;
VkCommandBuffer cb = VKRenderer_Record(renderer);
// Update dependencies on used surfaces.
// Update timestamps on used surfaces.
surface->lastTimestamp = renderer->writeTimestamp;
for (uint32_t i = 0, surfaces = (uint32_t) ARRAY_SIZE(surface->renderPass->usedSurfaces); i < surfaces; i++) {
VKSDOps* usedSurface = surface->renderPass->usedSurfaces[i];
usedSurface->lastTimestamp = renderer->writeTimestamp;
uint32_t newSize = 0, oldSize = (uint32_t) ARRAY_SIZE(usedSurface->dependentSurfaces);
for (uint32_t j = 0; j < oldSize; j++) {
VKSDOps* s = usedSurface->dependentSurfaces[j];
if (s != surface) usedSurface->dependentSurfaces[newSize++] = s;
}
if (newSize != oldSize) ARRAY_RESIZE(usedSurface->dependentSurfaces, newSize);
surface->renderPass->usedSurfaces[i]->lastTimestamp = renderer->writeTimestamp;
}
ARRAY_RESIZE(surface->renderPass->usedSurfaces, 0);
// Insert barriers to prepare surface for rendering.
VkImageMemoryBarrier barriers[2];
@@ -963,9 +976,12 @@ void VKRenderer_FlushSurface(VKSDOps* surface) {
uint32_t imageIndex;
VkResult acquireImageResult = device->vkAcquireNextImageKHR(device->handle, win->swapchain, UINT64_MAX,
acquireSemaphore, VK_NULL_HANDLE, &imageIndex);
if (acquireImageResult != VK_SUCCESS) {
// TODO possible suboptimal conditions
VK_IF_ERROR(acquireImageResult) {}
if (acquireImageResult != VK_SUCCESS && acquireImageResult != VK_SUBOPTIMAL_KHR) {
VK_IF_ERROR(acquireImageResult) {
// Failed, try again later.
surface->renderPass->pendingFlush = VK_TRUE;
return;
}
}
// Insert barriers to prepare both main (src) and swapchain (dst) images for blit.
@@ -1122,7 +1138,7 @@ static uint32_t VKRenderer_AllocateVertices(uint32_t primitives, uint32_t vertic
* This function can invalidate drawing state, always call it before VK_DRAW.
*/
static BufferWritingState VKRenderer_AllocateMaskFillBytes(uint32_t size) {
assert(size > 0);
// assert(size > 0); // size can be 0 when binding the buffer without allocating any data.
assert(size <= MASK_FILL_BUFFER_SIZE);
VKSDOps* surface = VKRenderer_GetContext()->surface;
BufferWritingState state = VKRenderer_AllocateBufferData(
@@ -1158,16 +1174,35 @@ static void VKRenderer_ValidateTransform() {
0.0f, 2.0f / (float) surface->image->extent.height, -1.0f
};
// Combine it with user transform.
VKUtil_ConcatenateTransform(&transform, &context->transform);
VKUtil_ConcatenateTransform(&transform, &context->constants.transform);
// Push the transform into shader.
surface->device->vkCmdPushConstants(
renderPass->commandBuffer,
surface->device->renderer->pipelineContext->colorPipelineLayout, // TODO what if our pipeline layout differs?
surface->device->renderer->pipelineContext->commonPipelineLayout,
VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(VKTransform), &transform
);
}
}
static void VKRenderer_ValidateConstants() {
VKRenderingContext* context = VKRenderer_GetContext();
assert(context->surface != NULL);
VKSDOps* surface = context->surface;
VKRenderPass* renderPass = surface->renderPass;
// Update constants, ignoring clip and color shaders.
if (renderPass->constantsModCount != context->constantsModCount &&
renderPass->state.shader != SHADER_CLIP && renderPass->state.shader != SHADER_COLOR) {
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_ValidateConstants: updating constants");
VKRenderer_FlushDraw(surface);
renderPass->constantsModCount = context->constantsModCount;
surface->device->vkCmdPushConstants(
renderPass->commandBuffer,
surface->device->renderer->pipelineContext->commonPipelineLayout,
VK_SHADER_STAGE_FRAGMENT_BIT, PUSH_CONSTANTS_OFFSET, PUSH_CONSTANTS_SIZE, &context->constants.composite
);
}
}
/**
* Setup stencil attachment according to the context clip state.
* If there is a clip shape, attachment is cleared with "fail" value and then
@@ -1204,6 +1239,7 @@ static void VKRenderer_SetupStencil() {
.inAlphaType = ALPHA_TYPE_UNKNOWN,
.composite = NO_COMPOSITE,
.shader = SHADER_CLIP,
.shaderVariant = NO_SHADER_VARIANT,
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
}).pipeline);
// Reset vertex buffer binding.
@@ -1248,7 +1284,7 @@ void VKRenderer_RecordBarriers(VKRenderer* renderer,
/**
* Setup pipeline for drawing. Returns FALSE if surface is not yet ready for drawing.
*/
VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, AlphaType inAlphaType) {
VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkPrimitiveTopology topology, AlphaType inAlphaType) {
assert(context.surface != NULL);
VKSDOps* surface = context.surface;
@@ -1290,10 +1326,18 @@ VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, Alph
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating clip");
surface->device->vkCmdSetScissor(renderPass->commandBuffer, 0, 1, &context.clipRect);
if (clipChanged) {
VKStencilMode stencilMode = STENCIL_MODE_NONE;
if (ARRAY_SIZE(context.clipSpanVertices) > 0) {
VKRenderer_SetupStencil();
renderPass->state.stencilMode = STENCIL_MODE_ON;
} else renderPass->state.stencilMode = surface->stencil != NULL ? STENCIL_MODE_OFF : STENCIL_MODE_NONE;
stencilMode = STENCIL_MODE_ON;
} else if (surface->stencil != NULL) {
stencilMode = STENCIL_MODE_OFF;
}
// Reset the pipeline when changing stencil mode.
if (renderPass->state.stencilMode != stencilMode) {
renderPass->state.shader = NO_SHADER;
}
renderPass->state.stencilMode = stencilMode;
}
}
// Validate current composite.
@@ -1309,6 +1353,7 @@ VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, Alph
// Validate current pipeline.
if (renderPass->state.shader != shader ||
renderPass->state.shaderVariant != shaderVariant ||
renderPass->state.topology != topology ||
renderPass->state.inAlphaType != inAlphaType) {
J2dTraceLn(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating pipeline, old=%d, new=%d",
@@ -1316,6 +1361,7 @@ VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, Alph
VKRenderer_FlushDraw(surface);
VkCommandBuffer cb = renderPass->commandBuffer;
renderPass->state.shader = shader;
renderPass->state.shaderVariant = shaderVariant;
renderPass->state.topology = topology;
renderPass->state.inAlphaType = inAlphaType;
VKPipelineInfo pipelineInfo = VKPipelines_GetPipelineInfo(renderPass->context, renderPass->state);
@@ -1323,10 +1369,26 @@ VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, Alph
surface->device->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineInfo.pipeline);
renderPass->vertexBufferWriting.bound = VK_FALSE;
renderPass->maskFillBufferWriting.bound = VK_FALSE;
// If pipeline uses mask fill layout, but the shader is not actually a MASK one, that must be a generic-layout pipeline.
// In that case, we need to bind a mask buffer, even if we won't ever use it.
// We could use VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT or nullDescriptor, but those require
// optional features or extensions, so don't bother for now...
// TODO this is ugly, do something with it.
if (pipelineInfo.layout == surface->device->renderer->pipelineContext->maskFillPipelineLayout && !(shader & SHADER_MASK)) {
VKRenderer_AllocateMaskFillBytes(0);
}
}
VKRenderer_ValidateConstants();
return VK_TRUE;
}
static VkBool32 VKRenderer_ValidatePaint(VKShader shaderModifier, VkBool32 fill) {
return VKRenderer_Validate(context.shader | shaderModifier, context.shaderVariant,
fill ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST : VK_PRIMITIVE_TOPOLOGY_LINE_LIST, context.inAlphaType);
}
// Drawing operations.
void VKRenderer_RenderRect(VkBool32 fill, jint x, jint y, jint w, jint h) {
@@ -1337,12 +1399,9 @@ void VKRenderer_RenderRect(VkBool32 fill, jint x, jint y, jint w, jint h) {
void VKRenderer_RenderParallelogram(VkBool32 fill,
jfloat x11, jfloat y11,
jfloat dx21, jfloat dy21,
jfloat dx12, jfloat dy12)
{
if (!VKRenderer_Validate(SHADER_COLOR,
fill ? VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
: VK_PRIMITIVE_TOPOLOGY_LINE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
jfloat dx12, jfloat dy12) {
if (!VKRenderer_ValidatePaint(0, fill)) return; // Not ready.
/* dx21
* (p1)---------(p2) | (p1)------
* |\ \ | | \ dy21
@@ -1353,12 +1412,12 @@ void VKRenderer_RenderParallelogram(VkBool32 fill,
* dy21 \ |
* -----(p3)
*/
VKColorVertex p1 = {x11, y11, c};
VKColorVertex p2 = {x11 + dx21, y11 + dy21, c};
VKColorVertex p3 = {x11 + dx21 + dx12, y11 + dy21 + dy12, c};
VKColorVertex p4 = {x11 + dx12, y11 + dy12, c};
VKVertex p1 = {x11, y11, context.vertexData};
VKVertex p2 = {x11 + dx21, y11 + dy21, context.vertexData};
VKVertex p3 = {x11 + dx21 + dx12, y11 + dy21 + dy12, context.vertexData};
VKVertex p4 = {x11 + dx12, y11 + dy12, context.vertexData};
VKColorVertex* vs;
VKVertex* vs;
VK_DRAW(vs, 1, fill ? 6 : 8);
uint32_t i = 0;
vs[i++] = p1;
@@ -1375,19 +1434,18 @@ void VKRenderer_RenderParallelogram(VkBool32 fill,
void VKRenderer_FillSpans(jint spanCount, jint *spans) {
if (spanCount == 0) return;
if (!VKRenderer_Validate(SHADER_COLOR, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
if (!VKRenderer_ValidatePaint(0, VK_TRUE)) return; // Not ready.
jfloat x1 = (float)*(spans++);
jfloat y1 = (float)*(spans++);
jfloat x2 = (float)*(spans++);
jfloat y2 = (float)*(spans++);
VKColorVertex p1 = {x1, y1, c};
VKColorVertex p2 = {x2, y1, c};
VKColorVertex p3 = {x2, y2, c};
VKColorVertex p4 = {x1, y2, c};
VKVertex p1 = {x1, y1, context.vertexData};
VKVertex p2 = {x2, y1, context.vertexData};
VKVertex p3 = {x2, y2, context.vertexData};
VKVertex p4 = {x1, y2, context.vertexData};
VKColorVertex* vs;
VKVertex* vs;
VK_DRAW(vs, 1, 6);
vs[0] = p1; vs[1] = p2; vs[2] = p3; vs[3] = p3; vs[4] = p4; vs[5] = p1;
@@ -1404,8 +1462,8 @@ void VKRenderer_FillSpans(jint spanCount, jint *spans) {
void VKRenderer_MaskFill(jint x, jint y, jint w, jint h,
jint maskoff, jint maskscan, jint masklen, uint8_t *mask) {
if (!VKRenderer_Validate(SHADER_MASK_FILL_COLOR,
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, ALPHA_TYPE_UNKNOWN)) return; // Not ready.
if (!VKRenderer_ValidatePaint(SHADER_MASK, VK_TRUE)) return; // Not ready.
// maskoff is the offset from the beginning of mask,
// it's the same as x and y offset within a tile (maskoff % maskscan, maskoff / maskscan).
// maskscan is the number of bytes in a row/
@@ -1423,14 +1481,13 @@ void VKRenderer_MaskFill(jint x, jint y, jint w, jint h,
*((char *)maskState.data) = (char)0xFF;
}
VKMaskFillColorVertex* vs;
VKMaskFillVertex* vs;
VK_DRAW(vs, 1, 6);
RGBA c = VKRenderer_GetRGBA(context.surface, context.renderColor);
int offset = (int) maskState.offset;
VKMaskFillColorVertex p1 = {x, y, offset, maskscan, c};
VKMaskFillColorVertex p2 = {x + w, y, offset, maskscan, c};
VKMaskFillColorVertex p3 = {x + w, y + h, offset, maskscan, c};
VKMaskFillColorVertex p4 = {x, y + h, offset, maskscan, c};
VKMaskFillVertex p1 = {x, y, offset, maskscan, context.vertexData};
VKMaskFillVertex p2 = {x + w, y, offset, maskscan, context.vertexData};
VKMaskFillVertex p3 = {x + w, y + h, offset, maskscan, context.vertexData};
VKMaskFillVertex p4 = {x, y + h, offset, maskscan, context.vertexData};
// Always keep p1 as provoking vertex for correct origin calculation in vertex shader.
vs[0] = p1; vs[1] = p3; vs[2] = p2;
vs[3] = p1; vs[4] = p3; vs[5] = p4;

View File

@@ -36,21 +36,15 @@
struct VKRenderingContext {
VKSDOps* surface;
VKTransform transform;
VKCompositeMode composite;
AlphaType inAlphaType;
VKShader shader;
VKShaderVariant shaderVariant;
unsigned int vertexData;
VKPushConstants constants;
uint64_t constantsModCount;
uint64_t transformModCount;
// We keep this color separately from renderColor,
// because we need consistent state when switching between XOR and alpha
// composite modes. This variable holds last value set by SET_COLOR, while
// renderColor holds color, currently used for drawing, which may have
// also been provided by SET_XOR_COMPOSITE.
Color color;
Color renderColor;
VKCompositeMode composite;
// Extra alpha is not used when painting with plain color,
// in this case color.a already includes it.
float extraAlpha;
uint64_t clipModCount; // Used to track changes to the clip.
VkRect2D clipRect;
ARRAY(VKIntVertex) clipSpanVertices;
@@ -63,7 +57,7 @@ VKRenderer* VKRenderer_Create(VKDevice* device);
/**
* Setup pipeline for drawing. Returns FALSE if the surface is not yet ready for drawing.
*/
VkBool32 VKRenderer_Validate(VKShader shader, VkPrimitiveTopology topology, AlphaType inAlphaType);
VkBool32 VKRenderer_Validate(VKShader shader, VKShaderVariant shaderVariant, VkPrimitiveTopology topology, AlphaType inAlphaType);
/**
* Record commands into the primary command buffer (outside of a render pass).

View File

@@ -292,15 +292,7 @@ VkBool32 VKSD_ConfigureWindowSurface(VKWinSDOps* vkwinsdo) {
}
static void VKSD_OnDispose(JNIEnv* env, SurfaceDataOps* ops) {
// We are being called from the disposer thread, RQ might be working in parallel.
// VKRenderQueue.lock/unlock is equivalent to AWT_LOCK/AWT_UNLOCK,
// but those are only available in the toolkit-specific part of AWT, so we call RQ there.
jobject rq = JNU_CallStaticMethodByName(env, NULL,
"sun/java2d/vulkan/VKRenderQueue", "getInstance", "()Lsun/java2d/vulkan/VKRenderQueue;").l;
JNU_CallMethodByName(env, NULL, rq, "lock", "()V");
VKSD_ResetSurface((VKSDOps*) ops);
JNU_CallMethodByName(env, NULL, rq, "unlock", "()V");
(*env)->DeleteLocalRef(env, rq);
JNU_CallStaticMethodByName(env, NULL, "sun/java2d/vulkan/VKSurfaceData", "dispose", "(J)V", ptr_to_jlong(ops));
}
JNIEXPORT VKSDOps* VKSD_CreateSurface(JNIEnv* env, jobject vksd, jint type, jint format, jint backgroundRGB,

View File

@@ -62,7 +62,7 @@ typedef uint16_t VKPackedSwizzle;
*/
typedef struct {
float m00, m01, m02;
float m10 __attribute__((aligned(16))), m11, m12;
float m10, m11, m12;
} VKTransform;
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VKMemory);

View File

@@ -268,7 +268,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
return false;
}
private static Window getToplevelFor(Component component) {
public static Window getToplevelFor(Component component) {
Container container = component instanceof Container c ? c : component.getParent();
for (Container p = container; p != null; p = p.getParent()) {
if (p instanceof Window window && !isWlPopup(window)) {
@@ -285,7 +285,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
: c.getParent();
}
static Point getRelativeLocation(Component c, Window toplevel) {
public static Point getRelativeLocation(Component c, Window toplevel) {
Objects.requireNonNull(c);
if (toplevel == null) {
@@ -1590,7 +1590,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
* Converts a value in the Java coordinate system into the Wayland
* surface-local coordinate system.
*/
int javaUnitsToSurfaceUnits(int value) {
public final int javaUnitsToSurfaceUnits(int value) {
if (!WLGraphicsEnvironment.isDebugScaleEnabled()) {
return value;
} else {
@@ -1600,7 +1600,7 @@ public class WLComponentPeer implements ComponentPeer, WLSurfaceSizeListener {
}
}
int javaUnitsToSurfaceSize(int value) {
public final int javaUnitsToSurfaceSize(int value) {
if (!WLGraphicsEnvironment.isDebugScaleEnabled()) {
return value;
} else {

Some files were not shown because too many files have changed in this diff Show More