Compare commits

..

3 Commits

Author SHA1 Message Date
Vitaly Provodin
5438a83c83 fixup! JBR-9238 Introduce distinct test groups for Vulkan runs 2025-08-29 14:44:20 +04:00
Vitaly Provodin
230ef3a2b0 JBR-9274 add a test against streaming output for attach API 2025-08-29 14:22:38 +04:00
Vitaly Provodin
616b476674 JBR-9274 turn off streaming output for attach API by default 2025-08-29 14:22:38 +04:00
230 changed files with 3286 additions and 10258 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 libdbus-1-dev
wayland-protocols libxkbcommon-x11-0
```
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,7 +254,8 @@ configurations (for example, `release` and `fastdebug`), supply the `--conf <con
Then open the git root directory as a project in IDEA.
## Contributing
Please contribute your changes through [OpenJDK](https://dev.java/contribute/openjdk/).
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/).
## Resources
* [JetBrains Runtime on GitHub](https://github.com/JetBrains/JetBrainsRuntime).

View File

@@ -1,7 +1,7 @@
[general]
project=jdk-updates
project=jdk
jbs=JDK
version=25.0.1
version=25
[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="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 ",")
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)
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)/org/jetbrains/runtime/jbr-api/SNAPSHOT
M2_ARTIFACT := $(M2_REPO)/com/jetbrains/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>org.jetbrains.runtime</groupId> \
<groupId>com.jetbrains</groupId> \
<artifactId>jbr-api</artifactId> \
<version>SNAPSHOT</version> \
</project> \
@@ -65,8 +65,7 @@ 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 org.jetbrains.runtime:jbr-api:SNAPSHOT"; \
cd "$(M2_ARTIFACT)" && sha256sum --binary "$(ARTIFACT_NAME).jar"; \
$(ECHO) "Installed into local Maven repository as com.jetbrains:jbr-api:SNAPSHOT"; \
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"
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num -o"
fi
# Check glslangValidator
@@ -97,8 +97,7 @@ AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
test "x$SHADER_COMPILER" = x; then
UTIL_LOOKUP_PROGS(GLSLANG, glslangValidator)
SHADER_COMPILER="$GLSLANG"
# Newer glslangValidator could use -P\"\#extension GL_GOOGLE_include_directive: require\"
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x"
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x -o"
fi
if test "x$SHADER_COMPILER" = x; then

View File

@@ -40,23 +40,12 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
[specify the root directory for the wayland protocols xml files])])
AC_ARG_WITH(gtk-shell1-protocol, [AS_HELP_STRING([--with-gtk-shell1-protocol],
[specify the path to the gtk-shell1 Wayland protocol xml file])])
AC_ARG_WITH(xkbcommon, [AS_HELP_STRING([--with-xkbcommon],
[specify prefix directory for the xkbcommon package
(expecting the headers under PATH/include)])])
AC_ARG_WITH(xkbcommon-include, [AS_HELP_STRING([--with-xkbcommon-include],
[specify directory for the xkbcommon include files])])
AC_ARG_WITH(xkbcommon-lib, [AS_HELP_STRING([--with-xkbcommon-lib],
[specify directory for the xkbcommon library files])])
if test "x$NEEDS_LIB_WAYLAND" = xfalse; then
if (test "x${with_wayland}" != x && test "x${with_wayland}" != xno) || \
(test "x${with_wayland_include}" != x && test "x${with_wayland_include}" != xno); then
AC_MSG_WARN([[wayland not used, so --with-wayland[-*] is ignored]])
fi
if (test "x${with_xkbcommon}" != x && test "x${with_xkbcommon}" != xno) || \
(test "x${with_xkbcommon_include}" != x && test "x${with_xkbcommon_include}" != xno); then
AC_MSG_WARN([[wayland not used, so --with-xkbcommon[-*] is ignored]])
fi
WAYLAND_CFLAGS=
WAYLAND_LIBS=
else
@@ -66,9 +55,6 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
if test "x${with_wayland}" = xno || test "x${with_wayland_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of wayland. Remove the --without-wayland option.])
fi
if test "x${with_xkbcommon}" = xno || test "x${with_xkbcommon_include}" = xno; then
AC_MSG_ERROR([It is not possible to disable the use of xkbcommon. Remove the --without-xkbcommon option.])
fi
if test "x${with_wayland}" != x; then
AC_MSG_CHECKING([for wayland headers])
@@ -135,52 +121,7 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
HELP_MSG_MISSING_DEPENDENCY([wayland])
AC_MSG_ERROR([Could not find wayland! $HELP_MSG ])
fi
XKBCOMMON_FOUND=no
XKBCOMMON_INCLUDES=
XKBCOMMON_LIBS=-lxkbcommon
if test "x${with_xkbcommon}" != x; then
AC_MSG_CHECKING([for xkbcommon headers])
if test -s "${with_xkbcommon}/include/xkbcommon/xkbcommon.h" &&
test -s "${with_xkbcommon}/include/xkbcommon/xkbcommon-compose.h"; then
XKBCOMMON_INCLUDES="-I${with_xkbcommon}/include"
XKBCOMMON_LIBS="-L${with_xkbcommon}/lib ${XKBCOMMON_LIBS}"
XKBCOMMON_FOUND=yes
AC_MSG_RESULT([$XKBCOMMON_FOUND])
else
AC_MSG_ERROR([Can't find 'include/xkbcommon/xkbcommon.h' and 'include/xkbcommon/xkbcommon-compose.h' under ${with_xkbcommon} given with the --with-xkbcommon option.])
fi
fi
if test "x${with_xkbcommon_include}" != x; then
AC_MSG_CHECKING([for xkbcommon headers])
if test -s "${with_xkbcommon_include}/xkbcommon/xkbcommon.h" &&
test -s "${with_xkbcommon_include}/xkbcommon/xkbcommon-compose.h"; then
XKBCOMMON_INCLUDES="-I${with_xkbcommon_include}"
XKBCOMMON_FOUND=yes
AC_MSG_RESULT([$XKBCOMMON_FOUND])
else
AC_MSG_ERROR([Can't find 'include/xkbcommon/xkbcommon.h' and 'include/xkbcommon/xkbcommon-compose.h' under ${with_xkbcommon_include} given with the --with-xkbcommon-include option.])
fi
fi
if test "x${with_xkbcommon_lib}" != x; then
XKBCOMMON_LIBS="-L${with_xkbcommon_lib} ${XKBCOMMON_LIBS}"
fi
if test "x${XKBCOMMON_FOUND}" != xyes; then
AC_CHECK_HEADERS([xkbcommon/xkbcommon.h xkbcommon/xkbcommon-compose.h],
[ XKBCOMMON_FOUND=yes ],
[ XKBCOMMON_FOUND=no; break ]
)
fi
if test "x$XKBCOMMON_FOUND" != xyes; then
HELP_MSG_MISSING_DEPENDENCY([xkbcommon])
AC_MSG_ERROR([Could not find xkbcommon! $HELP_MSG ])
fi
WAYLAND_LIBS="${WAYLAND_LIBS} ${XKBCOMMON_LIBS}"
WAYLAND_CFLAGS="${WAYLAND_INCLUDES} ${XKBCOMMON_INCLUDES} ${WAYLAND_DEFINES}"
WAYLAND_CFLAGS="${WAYLAND_INCLUDES} ${WAYLAND_DEFINES}"
fi
AC_SUBST(WAYLAND_CFLAGS)
AC_SUBST(WAYLAND_LIBS)

View File

@@ -28,12 +28,12 @@
DEFAULT_VERSION_FEATURE=25
DEFAULT_VERSION_INTERIM=0
DEFAULT_VERSION_UPDATE=1
DEFAULT_VERSION_UPDATE=0
DEFAULT_VERSION_PATCH=0
DEFAULT_VERSION_EXTRA1=0
DEFAULT_VERSION_EXTRA2=0
DEFAULT_VERSION_EXTRA3=0
DEFAULT_VERSION_DATE=2025-10-21
DEFAULT_VERSION_DATE=2025-09-16
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, key, pattern, this::convertDateTimePatternLetter);
String transPattern = translateDateFormatLetters(calendarType, pattern, this::convertDateTimePatternLetter);
dateTimePatterns.add(i, transPattern);
// Additionally, perform SDF specific date-time format pattern conversion
sdfPatterns.add(i, translateDateFormatLetters(calendarType, key, transPattern, this::convertSDFLetter));
sdfPatterns.add(i, translateDateFormatLetters(calendarType, transPattern, this::convertSDFLetter));
} else {
dateTimePatterns.add(i, null);
sdfPatterns.add(i, null);
@@ -568,7 +568,7 @@ class Bundle {
}
}
private String translateDateFormatLetters(CalendarType calendarType, String patternKey, String cldrFormat, ConvertDateTimeLetters converter) {
private String translateDateFormatLetters(CalendarType calendarType, 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, patternKey, lastLetter, count, jrePattern);
converter.convert(calendarType, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -597,7 +597,7 @@ class Bundle {
}
if (!inQuote) {
if (count != 0) {
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
converter.convert(calendarType, 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, patternKey, lastLetter, count, jrePattern);
converter.convert(calendarType, lastLetter, count, jrePattern);
lastLetter = 0;
count = 0;
}
@@ -627,7 +627,7 @@ class Bundle {
count++;
continue;
}
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
converter.convert(calendarType, lastLetter, count, jrePattern);
lastLetter = c;
count = 1;
}
@@ -637,7 +637,7 @@ class Bundle {
}
if (count != 0) {
converter.convert(calendarType, patternKey, lastLetter, count, jrePattern);
converter.convert(calendarType, 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, String patternKey, char cldrLetter, int count, StringBuilder sb) {
private void convertDateTimePatternLetter(CalendarType calendarType, 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, String patternKey, char cldrLetter, int count, StringBuilder sb) {
private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) {
switch (cldrLetter) {
case 'G':
if (calendarType != CalendarType.GREGORIAN) {
@@ -722,17 +722,6 @@ 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");
@@ -778,7 +767,6 @@ class Bundle {
.collect(Collectors.toMap(
e -> calendarPrefix + e.getKey(),
e -> translateDateFormatLetters(calendarType,
e.getKey(),
(String)e.getValue(),
this::convertDateTimePatternLetter)
))
@@ -787,7 +775,7 @@ class Bundle {
@FunctionalInterface
private interface ConvertDateTimeLetters {
void convert(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb);
void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb);
}
/**

View File

@@ -65,7 +65,6 @@ 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

@@ -35,8 +35,6 @@ WAYLAND_BASIC_PROTOCOL_FILES := \
$(WAYLAND_PROTOCOLS_ROOT)/staging/xdg-activation/xdg-activation-v1.xml \
$(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,6 +58,7 @@ 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
@@ -101,7 +102,6 @@ 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
@@ -199,7 +199,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
-framework OpenGL, \
LIBS_windows := advapi32.lib comctl32.lib comdlg32.lib delayimp.lib \
gdi32.lib gdiplus.lib imm32.lib kernel32.lib ole32.lib shell32.lib shlwapi.lib \
user32.lib uuid.lib winmm.lib winspool.lib dwmapi.lib $(A11Y_NVDA_ANNOUNCING_LIBS) oleacc.lib, \
user32.lib uuid.lib winmm.lib winspool.lib dwmapi.lib $(A11Y_NVDA_ANNOUNCING_LIBS), \
VERSIONINFO_RESOURCE := $(LIBAWT_VERSIONINFO_RESOURCE), \
EXTRA_RCFLAGS := $(LIBAWT_RCFLAGS), \
STATIC_LIB_EXCLUDE_OBJS := $(LIBAWT_STATIC_EXCLUDE_OBJS), \
@@ -220,7 +220,7 @@ endif
# Compile Vulkan shaders
define compile-spirv
$(call MakeTargetDir)
$(VULKAN_SHADER_COMPILER) -D$(call uppercase,$(patsubst .%,STAGE_%,$(suffix $<))) -o '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
$(VULKAN_SHADER_COMPILER) '$(call DecodeSpace, $@)' '$(call DecodeSpace, $<)'
endef
spirv-name = $(strip $1).h

View File

@@ -5344,6 +5344,42 @@ 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.
*/
@@ -5560,16 +5596,77 @@ 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_done;
Label L_multiply_64_x_64_loop, 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,6 +1384,10 @@ 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,17 +8431,6 @@ 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 that could depend on RVV.
// Misc Intrinsics could depend on RVV
if (!AvoidUnalignedAccesses && (UseZba || UseRVV)) {
if (UseZba || UseRVV) {
if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
FLAG_SET_DEFAULT(UseCRC32Intrinsics, true);
}
} else {
if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
warning("CRC32 intrinsic are not available on this CPU.");
warning("CRC32 intrinsic requires Zba or RVV instructions (not available on this CPU)");
}
FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
}
@@ -325,40 +325,20 @@ void VM_Version::c2_initialize() {
FLAG_SET_DEFAULT(UseMulAddIntrinsic, 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(UseMultiplyToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, 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(UseSquareToLenIntrinsic)) {
FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, 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(UseMontgomeryMultiplyIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, 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);
if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true);
}
// Adler32

View File

@@ -352,6 +352,16 @@ 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;
@@ -363,27 +373,17 @@ 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 check_old) {
bool ClassLoaderDataGraph::dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass) {
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, check_old) || ok;
ok = cld->dictionary()->update_klass(current, name, k, old_klass) || 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, bool check_old);
static void dictionary_classes_do_classes_do_safepoint(void f(InstanceKlass* const));
static bool dictionary_classes_do_update_klass(Thread* current, Symbol* name, InstanceKlass* k, InstanceKlass* old_klass);
static void verify_dictionary();
static void print_dictionary(outputStream* st);

View File

@@ -211,23 +211,15 @@ class UpdateKlassDcevm : public StackObj {
InstanceKlass* _new_klass;
InstanceKlass* _old_klass;
bool _replaced;
bool _check_old;
public:
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass, bool check_old) :
UpdateKlassDcevm(InstanceKlass* new_klass, InstanceKlass* old_klass) :
_new_klass(new_klass),
_old_klass(old_klass),
_replaced(false),
_check_old(check_old) {
_replaced(false) {
}
void operator()(InstanceKlass** old_table_value) {
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());
}
assert(*old_table_value == _old_klass, "should be old class");
*old_table_value = _new_klass;
_replaced = true;
}
@@ -238,14 +230,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, bool check_old) {
UpdateKlassDcevm found(k, old_klass, check_old);
bool Dictionary::update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass) {
UpdateKlassDcevm found(k, old_klass);
DictionaryLookup lookup(class_name);
// (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();
InstanceKlass* result = nullptr;
bool needs_rehashing = false;
bool ret = _table->insert_get(current, lookup, old_klass, found);
return ret || 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 check_old);
bool update_klass(Thread* current, Symbol* class_name, InstanceKlass* k, InstanceKlass* old_klass);
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() != nullptr && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
|| (Universe::is_inside_redefinition() && vmClasses::Class_klass()->old_version() != NULL && mirror->is_a(vmClasses::Class_klass()->old_version()))), "must be a Class");
assert(is_primitive(mirror), "must be primitive");
return mirror;
}

View File

@@ -132,16 +132,8 @@ bool StackMapTable::match_stackmap(
}
void StackMapTable::check_jump_target(
StackMapFrame* frame, int bci, int offset, TRAPS) const {
StackMapFrame* frame, int32_t target, 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, int bci, int offset, TRAPS) const;
void check_jump_target(StackMapFrame* frame, int32_t target, 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 != nullptr);
bool is_redefining = (old_klass != NULL);
// Bootstrap and other parallel classloaders don't acquire a lock,
// they use placeholder token.
@@ -1386,9 +1386,10 @@ 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
MutexLocker lock(ClassLoaderDataGraph_lock);
ClassLoaderDataGraph_lock->lock();
Symbol* name_h = k->name();
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass, true);
bool ok = ClassLoaderDataGraph::dictionary_classes_do_update_klass(THREAD, name_h, k, old_klass);
ClassLoaderDataGraph_lock->unlock();
assert (ok, "must have found old class and updated!");
}
check_constraints(k, loader_data, !is_redefining, CHECK);
@@ -1486,7 +1487,7 @@ InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handl
}
}
define_instance_class(k, nullptr, class_loader, THREAD);
define_instance_class(k, NULL, class_loader, THREAD);
// definer must notify any waiting threads
{
@@ -1526,7 +1527,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 != nullptr, "just checking");
assert(k != NULL, "just checking");
// remove receiver from sibling list
k->remove_from_sibling_list();

View File

@@ -781,6 +781,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
// Merge with the next instruction
{
int target;
VerificationType type, type2;
VerificationType atype;
@@ -1605,8 +1606,9 @@ 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, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
&current_frame, target, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_if_acmpeq :
case Bytecodes::_if_acmpne :
@@ -1617,16 +1619,19 @@ 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, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
(&current_frame, target, CHECK_VERIFY(this));
no_control_flow = false; break;
case Bytecodes::_goto :
target = bcs.dest();
stackmap_table.check_jump_target(
&current_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this));
&current_frame, target, CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_goto_w :
target = bcs.dest_w();
stackmap_table.check_jump_target(
&current_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this));
&current_frame, target, CHECK_VERIFY(this));
no_control_flow = true; break;
case Bytecodes::_tableswitch :
case Bytecodes::_lookupswitch :
@@ -2275,14 +2280,15 @@ void ClassVerifier::verify_switch(
}
}
}
stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this));
int target = bci + default_offset;
stackmap_table->check_jump_target(current_frame, target, 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);
int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
stackmap_table->check_jump_target(
current_frame, bci, offset, CHECK_VERIFY(this));
current_frame, target, CHECK_VERIFY(this));
}
NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point
}
@@ -2543,12 +2549,7 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
case Bytecodes::_goto:
case Bytecodes::_goto_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;
int target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w());
if (visited_branches->contains(bci)) {
if (bci_stack->is_empty()) {
if (handler_stack->is_empty()) {
@@ -2606,10 +2607,7 @@ bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
// Push the switch alternatives onto the stack.
for (int i = 0; i < keys; i++) {
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;
int target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
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() != nullptr) {
if (task->method()->is_old() || task->method()->method_holder()->new_version() != NULL) {
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 != nullptr, "Must have been initialized");
assert(_current_region != NULL, "Must have been initialized");
// Ensure the object fit in the current region.
while (!object_will_fit(size)) {
if (!_compaction_region_iterator.has_next()) {
return nullptr;
return NULL;
}
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 != nullptr, "Must have been initialized");
assert(_current_region != NULL, "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 = partial_vmem.last_part(allocation->harvested());
const ZVirtualMemory non_harvested_vmem = 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,20 +214,9 @@ 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 = ZFailLargerCommits > 0
? inject_commit_limit(vmem)
: vmem.size();
const size_t size = vmem.size();
size_t total_committed = 0;

View File

@@ -118,11 +118,6 @@
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,23 +100,8 @@ 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 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;
}
int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); }
int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); }
// 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() == nullptr || super() == vmClasses::Object_klass() || (k->is_redefining() && super() == vmClasses::Object_klass()->newest_version()),
assert(super() == NULL || 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 != nullptr) {
if (_super != NULL) {
_super = _super->newest_version();
}
int sup_depth = super_depth();
for (int idx = 0; idx < sup_depth; idx++) {
Klass* primary = _primary_supers[idx];
if (primary == nullptr) {
if (primary == NULL) {
break;
}
_primary_supers[idx] = primary->newest_version();
}
if (secondary_super_cache() != nullptr) {
if (secondary_super_cache() != NULL) {
set_secondary_super_cache(secondary_super_cache()->newest_version());
}

View File

@@ -432,9 +432,6 @@ 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,14 +1575,9 @@ 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 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);
}
// 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);
// Figure out which arraycopy runtime method to call (disjoint, uninitialized).
const char* copyfunc_name = "arraycopy";
@@ -1663,8 +1658,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() && ((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);
bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
tdst->is_con() && ((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,14 +1473,9 @@ 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 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);
}
// 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);
// 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,7 +218,9 @@ intptr_t jfieldIDWorkaround::encode_klass_hash(Klass* k, int offset) {
DEBUG_ONLY(NoSafepointVerifier nosafepoint;)
if (AllowEnhancedClassRedefinition) {
field_klass = field_klass->oldest_version();
while (field_klass->old_version() != NULL) {
field_klass = field_klass->old_version();
}
}
uintptr_t klass_hash = field_klass->identity_hash();
return ((klass_hash & klass_mask) << klass_shift) | checked_mask_in_place;
@@ -240,9 +242,9 @@ bool jfieldIDWorkaround::klass_hash_ok(Klass* k, jfieldID id) {
intptr_t klass_hash = (as_uint >> klass_shift) & klass_mask;
if (AllowEnhancedClassRedefinition) {
// 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();
while (k->old_version() != NULL) {
k = k->old_version();
}
}
do {
@@ -251,11 +253,6 @@ 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,6 +62,7 @@
#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
@@ -694,16 +695,6 @@ 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));
@@ -926,7 +917,7 @@ void VM_EnhancedRedefineClasses::doit() {
}
}
log_trace(redefine, class, redefine, metadata)("calling check_class");
ClassLoaderDataGraph::dictionary_classes_do_classes_do_safepoint(check_class);
ClassLoaderData::the_null_class_loader_data()->dictionary()->classes_do_safepoint(check_class);
#ifdef PRODUCT
}
#endif

View File

@@ -1097,22 +1097,6 @@ 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);
@@ -1924,14 +1908,6 @@ 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
@@ -2932,8 +2908,6 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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,9 +72,6 @@ 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_IF("JNI global references", _verbose)
st->print_cr("JNI global refs:");
JNIHandles::print_on_unsafe(st);
JNIHandles::print_memory_usage_on(st);
STEP("JNI global references")
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_IF("OOME stack traces", _verbose)
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
STEP("OOME stack traces")
st->print_cr("OOME stack traces (most recent first):");
print_oome_stacks(st);
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("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("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 && str.length() == len)
? putStringAt(currValue, coder, count, dstOffset, str)
byte[] newValue = (s instanceof String str)
? putStringAt(currValue, coder, count, dstOffset, str, start, end)
: 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) {
private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) {
byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder());
coder = (newValue == value) ? coder : UTF16;
str.getBytes(newValue, 0, index, coder, str.length());
str.getBytes(newValue, off, index, coder, end - off);
return newValue;
}

View File

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

View File

@@ -146,11 +146,11 @@ public final class MonthDay
/**
* @serial The month-of-year, not null.
*/
private final int month;
private final byte month;
/**
* @serial The day-of-month.
*/
private final int day;
private final byte 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 = month;
this.day = dayOfMonth;
this.month = (byte) month;
this.day = (byte) dayOfMonth;
}
//-----------------------------------------------------------------------

View File

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

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2019, 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
@@ -137,11 +137,11 @@ public final class HijrahDate
/**
* The month-of-year.
*/
private final transient int monthOfYear;
private final transient byte monthOfYear;
/**
* The day-of-month.
*/
private final transient int dayOfMonth;
private final transient byte dayOfMonth;
//-------------------------------------------------------------------------
/**
@@ -273,8 +273,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = prolepticYear;
this.monthOfYear = monthOfYear;
this.dayOfMonth = dayOfMonth;
this.monthOfYear = (byte) monthOfYear;
this.dayOfMonth = (byte) dayOfMonth;
}
/**
@@ -287,8 +287,8 @@ public final class HijrahDate
this.chrono = chrono;
this.prolepticYear = dateInfo[0];
this.monthOfYear = dateInfo[1];
this.dayOfMonth = dateInfo[2];
this.monthOfYear = (byte) dateInfo[1];
this.dayOfMonth = (byte) dateInfo[2];
}
//-----------------------------------------------------------------------

View File

@@ -859,22 +859,6 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 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,7 +71,19 @@ final class EntrustTLSPolicy {
// OU=(c) 1999 Entrust.net Limited,
// OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),
// O=Entrust.net
"6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177"
"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"
);
// Any TLS Server certificate that is anchored by one of the Entrust

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, 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,13 +28,10 @@ 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;
@@ -592,10 +589,6 @@ 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 {
@@ -720,8 +713,7 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr =
new String(value.getDataBytes(), getCharset(value, false));
String valStr = new String(value.getDataBytes(), UTF_8);
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -840,8 +832,7 @@ public class AVA implements DerEncoder {
* NOTE: this implementation only emits DirectoryStrings of the
* types returned by isDerString().
*/
String valStr =
new String(value.getDataBytes(), getCharset(value, true));
String valStr = new String(value.getDataBytes(), UTF_8);
/*
* 2.4 (cont): If the UTF-8 string does not have any of the
@@ -936,39 +927,6 @@ 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

@@ -0,0 +1,27 @@
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

@@ -0,0 +1,27 @@
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

@@ -0,0 +1,38 @@
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

@@ -0,0 +1,20 @@
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=180
dataVersion=179
# 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;2025-12-31-22-00-00;EUR
BG=BGN
# BURKINA FASO
BF=XOF
# BURUNDI
@@ -193,7 +193,7 @@ HR=EUR
# CUBA
CU=CUP
# Curaçao
CW=XCG
CW=ANG;2025-04-01-04-00-00;XCG
# CYPRUS
CY=EUR
# CZECHIA
@@ -510,7 +510,7 @@ SR=SRD
# SVALBARD AND JAN MAYEN
SJ=NOK
# Sint Maarten (Dutch part)
SX=XCG
SX=ANG;2025-04-01-04-00-00;XCG
# ESWATINI
SZ=SZL
# SWEDEN

View File

@@ -395,8 +395,7 @@ 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 isLegalOffset(context_type *, int bci, int offset);
static jboolean isLegalTarget(context_type *, int target);
static jboolean isLegalTarget(context_type *, int offset);
static void verify_constant_pool_type(context_type *, int, unsigned);
static void initialize_dataflow(context_type *);
@@ -1155,9 +1154,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];
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
if (!isLegalTarget(context, target))
CCerror(context, "Illegal target of jump or branch");
this_idata->operand.i = code_data[target];
break;
}
@@ -1171,9 +1170,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]);
if (!isLegalOffset(context, offset, jump))
CCerror(context, "Illegal target of jump or branch");
int target = offset + jump;
if (!isLegalTarget(context, target))
CCerror(context, "Illegal target of jump or branch");
this_idata->operand.i = code_data[target];
break;
}
@@ -1212,16 +1211,13 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset)
}
}
saved_operand = NEW(int, keys + 2);
int jump = _ck_ntohl(lpc[0]);
if (!isLegalOffset(context, offset, jump))
if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0])))
CCerror(context, "Illegal default target in switch");
int target = offset + jump;
saved_operand[keys + 1] = code_data[target];
saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])];
for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) {
jump = _ck_ntohl(lptr[0]);
if (!isLegalOffset(context, offset, jump))
int target = offset + _ck_ntohl(lptr[0]);
if (!isLegalTarget(context, target))
CCerror(context, "Illegal branch in tableswitch");
target = offset + jump;
saved_operand[k + 1] = code_data[target];
}
saved_operand[0] = keys + 1; /* number of successors */
@@ -1750,24 +1746,11 @@ 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 target)
isLegalTarget(context_type *context, int offset)
{
int code_length = context->code_length;
int *code_data = context->code_data;
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);
return (offset >= 0 && offset < code_length && code_data[offset] >= 0);
}

View File

@@ -144,6 +144,9 @@ 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;
/*
@@ -756,48 +759,33 @@ 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*
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);
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;
}
}
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)
{
#ifdef __linux
char *toolkit_name = GetToolkitName();
char *toolkit_name = getToolkitNameByEnv();
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);
@@ -818,10 +806,7 @@ RegisterThread()
jboolean
ProcessPlatformOption(const char *arg)
{
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) {
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,7 +36,6 @@ 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.*;
@@ -285,26 +284,9 @@ class WindowsWatchService
private static final short OFFSETOF_FILENAMELENGTH = 8;
private static final short OFFSETOF_FILENAME = 12;
// 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;
}
// 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;
private final WindowsFileSystem fs;
private final WindowsWatchService watcher;

View File

@@ -27,7 +27,6 @@ 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;
@@ -66,8 +65,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 {
@@ -275,14 +274,9 @@ class _AppEventHandler {
logger.fine("NOTIFY_SCREEN_CHANGE_PARAMETERS");
}
if (AppContext.getAppContext() != null) {
CGraphicsDevice.DisplayConfiguration displayConfiguration = CGraphicsDevice.DisplayConfiguration.get();
EventQueue.invokeLater(() -> {
for (GraphicsDevice gd : GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices()) {
if (gd instanceof CGraphicsDevice) {
((CGraphicsDevice) gd).updateDisplayParameters(displayConfiguration);
}
}
});
EventQueue.invokeLater(
() -> ((SunGraphicsEnvironment) GraphicsEnvironment.
getLocalGraphicsEnvironment()).displayParametersChanged());
}
break;
default:

View File

@@ -34,21 +34,18 @@ 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 {
implements DisplayChangedListener, DisplayParametersChangedListener {
private static final PlatformLogger logger = PlatformLogger.getLogger(CGraphicsDevice.class.getName());
/**
@@ -70,7 +67,7 @@ public final class CGraphicsDevice extends GraphicsDevice
private DisplayMode originalMode;
private DisplayMode initialMode;
public CGraphicsDevice(final int displayID, DisplayConfiguration config) {
public CGraphicsDevice(final int displayID) {
this.displayID = displayID;
this.initialMode = getDisplayMode();
StringBuilder errorMessage = new StringBuilder();
@@ -94,7 +91,7 @@ public final class CGraphicsDevice extends GraphicsDevice
}
// [JBR] we don't call displayChanged after creating a device, so call it here.
updateDevice(config);
displayChanged();
}
int getDisplayID() {
@@ -177,6 +174,8 @@ 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?
}
@@ -184,43 +183,29 @@ public final class CGraphicsDevice extends GraphicsDevice
/**
* @return false if display parameters were changed, so we need to recreate the device.
*/
boolean updateDevice(DisplayConfiguration config) {
boolean updateDevice() {
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 updateDisplayParameters(DisplayConfiguration config) {
Descriptor desc = config.getDescriptor(displayID);
if (desc == null) return;
if (!desc.screenInsets.equals(screenInsets)) {
public void displayParametersChanged() {
Insets newScreenInsets = nativeGetScreenInsets(displayID);
if (!newScreenInsets.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=" + desc.screenInsets.top + ",left=" + desc.screenInsets.left +
",bottom=" + desc.screenInsets.bottom + ",right=" + desc.screenInsets.right +
"]->[top=" + newScreenInsets.top + ",left=" + newScreenInsets.left +
",bottom=" + newScreenInsets.bottom + ",right=" + newScreenInsets.right +
"]");
}
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;
screenInsets = newScreenInsets;
}
}
@Override
public void paletteChanged() {
// devices do not need to react to this event.
@@ -367,6 +352,23 @@ 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);
@@ -381,37 +383,7 @@ 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,7 +245,6 @@ 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.
@@ -253,7 +252,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, config));
old.put(mainDisplayID, new CGraphicsDevice(mainDisplayID));
} catch (IllegalStateException e) {
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
logger.fine("Unable to initialize graphics device for displayID=" +
@@ -269,13 +268,13 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
}
for (int id : displayIDs) {
old.compute(id, (i, d) -> {
if (d != null && d.updateDevice(config)) {
if (d != null && d.updateDevice()) {
// Device didn't change -> reuse
devices.put(i, d);
return null;
} else {
// Device changed -> create new
devices.put(i, new CGraphicsDevice(i, config));
devices.put(i, new CGraphicsDevice(i));
return d;
}
});

View File

@@ -33,6 +33,7 @@ import sun.lwawt.macosx.CFLayer;
import sun.util.logging.PlatformLogger;
import java.awt.Component;
import java.awt.GraphicsConfiguration;
import java.awt.Insets;
import java.awt.Window;
@@ -50,13 +51,12 @@ public class MTLLayer extends CFLayer {
private static native void nativeSetOpaque(long layerPtr, boolean opaque);
private int scale = 1;
private final boolean perfCountersEnabled;
public MTLLayer(LWWindowPeer peer) {
super(0, true);
Window target = (peer != null) ? peer.getTarget() : null;
this.perfCountersEnabled = (target != null) && AWTAccessor.getWindowAccessor().countersEnabled(target);
boolean perfCountersEnabled = (target != null) && AWTAccessor.getWindowAccessor().countersEnabled(target);
setPtr(nativeCreateLayer(perfCountersEnabled));
this.peer = peer;
@@ -150,29 +150,11 @@ public class MTLLayer extends CFLayer {
}
}
private final static String[] STAT_NAMES = new String[]{
"java2d.native.mtlLayer.drawInMTLContext", // type = 0
"java2d.native.mtlLayer.nextDrawable" // type = 1
};
private void addStat(int type, double value) {
// Called from the native code when this layer has been presented on screen
if (perfCountersEnabled && (peer != null)) {
final Component target = peer.getTarget();
if (target instanceof Window window) {
AWTAccessor.getWindowAccessor().addStat(window,
((type >= 0) && (type < STAT_NAMES.length)) ? STAT_NAMES[type] : "undefined", value);
}
}
}
private void countNewFrame() {
// Called from the native code when this layer has been presented on screen
if (perfCountersEnabled && (peer != null)) {
final Component target = peer.getTarget();
if (target instanceof Window window) {
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.frames");
}
Component target = peer.getTarget();
if (target instanceof Window window) {
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.frames");
}
}
@@ -180,11 +162,9 @@ public class MTLLayer extends CFLayer {
// Called from the native code when an attempt was made to present this layer
// on screen, but that attempt was not successful. This can happen, for example,
// when those attempts are too frequent.
if (perfCountersEnabled && (peer != null)) {
final Component target = peer.getTarget();
if (target instanceof Window window) {
AWTAccessor.getWindowAccessor().incrementCounter(window, "java2d.native.framesDropped");
}
Component target = peer.getTarget();
if (target instanceof Window window) {
AWTAccessor.getWindowAccessor().bumpCounter(window, "java2d.native.framesDropped");
}
}
}

View File

@@ -75,19 +75,6 @@ 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
@@ -618,10 +605,6 @@ 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
@@ -3025,6 +3008,8 @@ 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;
@@ -3039,11 +3024,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;
w.hasShadow = YES;
// remove corner radius animation
[w.contentView.layer removeAllAnimations];
[w invalidateShadow];
}];

View File

@@ -363,6 +363,47 @@ 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
@@ -516,40 +557,31 @@ Java_sun_awt_CGraphicsDevice_nativeGetDisplayModes
/*
* Class: sun_awt_CGraphicsDevice
* Method: nativeGetDisplayConfiguration
* Signature: (Lsun/awt/CGraphicsDevice$DisplayConfiguration;)V
* Method: nativeGetScaleFactor
* Signature: (I)D
*/
JNIEXPORT void JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetDisplayConfiguration
(JNIEnv *env, jclass class, jobject config) {
AWT_ASSERT_APPKIT_THREAD;
JNIEXPORT jdouble JNICALL
Java_sun_awt_CGraphicsDevice_nativeGetScaleFactor
(JNIEnv *env, jclass class, jint displayID)
{
__block jdouble ret = 1.0f;
JNI_COCOA_ENTER(env);
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];
[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;
}
}
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);
CHECK_EXCEPTION();
}
}];
JNI_COCOA_EXIT(env);
return ret;
}

View File

@@ -116,7 +116,6 @@ 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) {
@@ -153,6 +152,7 @@ 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,6 +173,7 @@ 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 },
};
#define NUM_SYMBOLIC_HOTKEYS (sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]))
static const int numSymbolicHotkeys = sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]);
static struct SystemHotkeyState {
bool symbolicHotkeysFilled;
struct SymbolicHotKey currentSymbolicHotkeys[NUM_SYMBOLIC_HOTKEYS];
struct SymbolicHotKey currentSymbolicHotkeys[numSymbolicHotkeys];
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[NUM_SYMBOLIC_HOTKEYS]) {
static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
// Called from the main thread
@try {
@@ -425,7 +425,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_
return;
}
memcpy(hotkeys, defaultSymbolicHotKeys, NUM_SYMBOLIC_HOTKEYS * sizeof(struct SymbolicHotKey));
memcpy(hotkeys, defaultSymbolicHotKeys, numSymbolicHotkeys * sizeof(struct SymbolicHotKey));
for (id keyObj in hkObj) {
if (![keyObj isKindOfClass:[NSString class]]) {
@@ -438,7 +438,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_
int uid = [hkNumber intValue];
// Ignore hotkeys out of range, as well as 0, which is the "invalid value" for intValue
if (uid <= 0 || uid >= NUM_SYMBOLIC_HOTKEYS) {
if (uid <= 0 || uid >= numSymbolicHotkeys) {
continue;
}
@@ -512,7 +512,7 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_
}
static void updateAppleSymbolicHotkeysCache() {
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
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[NUM_SYMBOLIC_HOTKEYS], Visitor visitorBlock) {
static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHotkeys], Visitor visitorBlock) {
const NSOperatingSystemVersion macOSVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
for (int uid = 0; uid < NUM_SYMBOLIC_HOTKEYS; ++uid) {
for (int uid = 0; uid < numSymbolicHotkeys; ++uid) {
struct SymbolicHotKey* hotkey = &hotkeys[uid];
if (!hotkey->enabled) {
@@ -646,12 +646,12 @@ static bool ensureInitializedAndEnabled() {
return true;
}
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
static void readAppleSymbolicHotkeysCached(struct SymbolicHotKey hotkeys[numSymbolicHotkeys]) {
memset(hotkeys, 0, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
pthread_mutex_lock(&state.mutex);
if (state.symbolicHotkeysFilled) {
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * NUM_SYMBOLIC_HOTKEYS);
memcpy(hotkeys, state.currentSymbolicHotkeys, sizeof(struct SymbolicHotKey) * numSymbolicHotkeys);
}
pthread_mutex_unlock(&state.mutex);
}
@@ -661,7 +661,7 @@ static void readSystemHotkeysImpl(Visitor visitorBlock) {
return;
}
struct SymbolicHotKey hotkeys[NUM_SYMBOLIC_HOTKEYS];
struct SymbolicHotKey hotkeys[numSymbolicHotkeys];
readAppleSymbolicHotkeysCached(hotkeys);
iterateAppleSymbolicHotkeys(hotkeys, visitorBlock);

View File

@@ -67,17 +67,9 @@ 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

@@ -71,8 +71,6 @@
- (void) stopRedraw:(MTLContext*)mtlc displayID:(jint)displayID force:(BOOL)force;
- (void) flushBuffer;
- (void) commitCommandBuffer:(MTLContext*)mtlc wait:(BOOL)waitUntilCompleted display:(BOOL)updateDisplay;
- (void) addStatCallback:(int)type value:(double)value;
- (void) countFramePresentedCallback;
- (void) countFrameDroppedCallback;
@end

View File

@@ -112,13 +112,6 @@ 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;
@@ -136,7 +129,6 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
[NSNull null], @"anchorPoint",
[NSNull null], @"bounds",
[NSNull null], @"contents",
[NSNull null], @"cornerRadius",
[NSNull null], @"contentsScale",
[NSNull null], @"onOrderIn",
[NSNull null], @"onOrderOut",
@@ -234,33 +226,29 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
}
// Acquire CAMetalDrawable without blocking:
const CFTimeInterval beforeDrawableTime = CACurrentMediaTime();
const CFTimeInterval beforeDrawableTime = (TRACE_DISPLAY) ? CACurrentMediaTime() : 0.0;
const id<CAMetalDrawable> mtlDrawable = [self nextDrawable];
if (mtlDrawable == nil) {
J2dTraceLn(J2D_TRACE_VERBOSE, "MTLLayer.blitTexture: nextDrawable is null");
return;
}
const CFTimeInterval nextDrawableTime = CACurrentMediaTime();
const CFTimeInterval nextDrawableLatency = (nextDrawableTime - beforeDrawableTime);
const CFTimeInterval nextDrawableTime = (TRACE_DISPLAY) ? CACurrentMediaTime() : 0.0;
// rolling mean weight (lerp):
static const NSTimeInterval a = 0.25;
if (nextDrawableLatency > 0.0) {
if (self.perfCountersEnabled) {
[self addStatCallback:1 value:1000.0 * nextDrawableLatency]; // See MTLLayer.STAT_NAMES[1]
}
#if TRACE_DISPLAY_ON
const CFTimeInterval nextDrawableLatency = (nextDrawableTime - beforeDrawableTime);
if (nextDrawableLatency > 0.0) {
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(), [MTLLayer getDrawableId:mtlDrawable],
CACurrentMediaTime(), mtlDrawable.drawableID,
1000.0 * nextDrawableLatency, 1000.0 * self.avgNextDrawableTime
);
#endif
}
// Keep Fence from now:
releaseFence = NO;
@@ -291,7 +279,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) presented"
" - presentedHandlerLatency = %.3lf ms frameInterval = %.3lf ms",
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
CACurrentMediaTime(), drawable.drawableID,
1000.0 * presentedHandlerLatency, 1000.0 * frameInterval
);
self.lastPresentedTime = presentedTime;
@@ -306,8 +294,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
"[%.6lf] MTLLayer_blitTexture_PresentedHandler: drawable(%d) skipped"
" - presentedHandlerLatency = %.3lf ms",
CACurrentMediaTime(), [MTLLayer getDrawableId:drawable],
1000.0 * presentedHandlerLatency
CACurrentMediaTime(), drawable.drawableID, 1000.0 * presentedHandlerLatency
);
}
}
@@ -317,7 +304,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
// Present drawable:
NSUInteger drawableId = -1;
if (TRACE_DISPLAY) {
drawableId = [MTLLayer getDrawableId:mtlDrawable];
drawableId = mtlDrawable.drawableID;
J2dRlsTraceLn(J2D_TRACE_INFO,
"[%.6lf] MTLLayer.blitTexture: layer[%p] present drawable(%d)",
CACurrentMediaTime(), self, drawableId);
@@ -402,17 +389,8 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
return;
}
const CFTimeInterval beforeMethod = CACurrentMediaTime();
(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_drawInMTLContext);
CHECK_EXCEPTION();
const CFTimeInterval drawInMTLContextLatency = (CACurrentMediaTime() - beforeMethod);
if (drawInMTLContextLatency > 0.0) {
if (self.perfCountersEnabled) {
[self addStatCallback:0 value:1000.0 * drawInMTLContextLatency]; // See MTLLayer.STAT_NAMES[0]
}
}
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
}
@@ -538,20 +516,6 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
}
}
- (void) addStatCallback:(int)type value:(double)value {
// attach the current thread to the JVM if necessary, and get an env
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];
GET_MTL_LAYER_CLASS();
DECLARE_METHOD(jm_addStatFrame, jc_JavaLayer, "addStat", "(ID)V");
jobject javaLayerLocalRef = (*env)->NewLocalRef(env, self.javaLayer);
if (javaLayerLocalRef != NULL) {
(*env)->CallVoidMethod(env, javaLayerLocalRef, jm_addStatFrame, (jint)type, (jdouble)value);
CHECK_EXCEPTION();
(*env)->DeleteLocalRef(env, javaLayerLocalRef);
}
}
- (void) countFrameDroppedCallback {
// attach the current thread to the JVM if necessary, and get an env
JNIEnv* env = [ThreadUtilities getJNIEnvUncached];

View File

@@ -63,7 +63,6 @@ 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,11 +254,8 @@ AWT_ASSERT_APPKIT_THREAD;
* Note : if waiting cross-thread, possibly the stack allocated copy is accessible ?
*/
+ (void)invokeBlockCopy:(void (^)(void))blockCopy {
@try {
blockCopy();
} @finally {
Block_release(blockCopy);
}
blockCopy();
Block_release(blockCopy);
}
+ (NSString*)getCaller:(NSString*)prefixSymbol {
@@ -783,18 +780,9 @@ 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++) {
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];
}
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
// invoke callback:
[ThreadUtilities invokeBlockCopy:blockCopy];
}
// reset queue anyway:
[self reset];

View File

@@ -1,68 +0,0 @@
/*
* 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

@@ -53,14 +53,10 @@ import java.awt.event.TextEvent;
import java.awt.im.InputContext;
import java.awt.im.InputMethodRequests;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.Raster;
import java.awt.image.SampleModel;
import java.awt.image.VolatileImage;
import java.awt.image.WritableRaster;
import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;
import java.awt.peer.LightweightPeer;
@@ -93,7 +89,6 @@ import javax.accessibility.AccessibleStateSet;
import javax.swing.JComponent;
import javax.swing.JRootPane;
import com.jetbrains.exported.JBRApi;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.ComponentFactory;
@@ -104,7 +99,6 @@ import sun.awt.EmbeddedFrame;
import sun.awt.RequestFocusController;
import sun.awt.SubRegionShowable;
import sun.awt.SunToolkit;
import sun.awt.SurfacePixelGrabber;
import sun.awt.dnd.SunDropTargetEvent;
import sun.awt.im.CompositionArea;
import sun.awt.image.VSyncedBSManager;
@@ -10565,79 +10559,4 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
return p.updateCustomTitleBarHitTest(allowNativeActions);
}
@JBRApi.Provides("Screenshoter#getWindowBackbufferArea")
private static BufferedImage getWindowBackbufferArea(Window window, int x, int y, int width, int height) {
Objects.requireNonNull(window);
if (x < 0 || y < 0) {
throw new IllegalArgumentException("Negative coordinates are not allowed");
}
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("The size must be positive");
}
Image fullBackbuffer = window.getBackBuffer();
if (fullBackbuffer == null) {
return null;
}
var bufferWidth = fullBackbuffer.getWidth(null);
var bufferHeight = fullBackbuffer.getHeight(null);
if (x >= width) {
throw new IllegalArgumentException(String.format("x coordinate (%d) is out of bounds (%d)", x, bufferWidth));
}
if (y >= height) {
throw new IllegalArgumentException(String.format("y coordinate (%d) is out of bounds (%d)", y, bufferHeight));
}
if ((long) x + width > bufferWidth) {
width = bufferWidth - x;
}
if ((long) y + height > bufferHeight) {
height = bufferHeight - y;
}
if (fullBackbuffer instanceof BufferedImage bufferedImage) {
return bufferedImage.getSubimage(x, y, width, height);
} else {
ColorModel colorModel = window.getGraphicsConfiguration().getColorModel();
SampleModel sampleModel = colorModel.createCompatibleSampleModel(width, height);
WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
image.getGraphics().drawImage(fullBackbuffer,
0, 0, width, height,
x, y, x + width, y + height,
null);
return image;
}
}
@JBRApi.Provides("Screenshoter#getWindowSurfaceArea")
private static BufferedImage getWindowSurfaceArea(Window window, int x, int y, int width, int height) {
Objects.requireNonNull(window);
if (x < 0 || y < 0) {
throw new IllegalArgumentException("Negative coordinates are not allowed");
}
if (width <= 0 || height <= 0) {
throw new IllegalArgumentException("The size must be positive");
}
ComponentPeer peer = window.peer;
if (peer == null || !window.isVisible()) {
return null;
}
if (peer instanceof SurfacePixelGrabber spg) {
// TODO: translate coordinates, maybe?
return spg.getClientAreaSnapshot(x, y, width, height);
}
return null;
}
}

View File

@@ -34,6 +34,7 @@ import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.im.InputContext;
import java.awt.image.BufferStrategy;
import java.awt.peer.ComponentPeer;
@@ -43,7 +44,6 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.PrintStream;
import java.io.Serial;
import java.io.Serializable;
import java.lang.annotation.Native;
@@ -53,15 +53,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EventListener;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.HashMap;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -72,14 +69,11 @@ import javax.accessibility.AccessibleState;
import javax.accessibility.AccessibleStateSet;
import com.jetbrains.exported.JBRApi;
import jdk.internal.misc.InnocuousThread;
import sun.awt.AWTAccessor;
import sun.awt.AppContext;
import sun.awt.DebugSettings;
import sun.awt.SunToolkit;
import sun.awt.util.IdentityArrayList;
import sun.awt.util.ThreadGroupUtils;
import sun.java2d.marlin.stats.StatDouble;
import sun.java2d.pipe.Region;
import sun.util.logging.PlatformLogger;
@@ -1159,51 +1153,45 @@ public class Window extends Container implements Accessible {
}
void doDispose() {
final class DisposeAction implements Runnable {
public void run() {
final Window window = Window.this;
// dump stats if needed:
AWTAccessor.getWindowAccessor().dumpStats(window, true, null);
disposing = true;
try {
// Check if this window is the fullscreen window for the
// device. Exit the fullscreen mode prior to disposing
// of the window if that's the case.
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
if (gd.getFullScreenWindow() == window) {
gd.setFullScreenWindow(null);
}
Object[] ownedWindowArray;
synchronized(ownedWindowList) {
ownedWindowArray = new Object[ownedWindowList.size()];
ownedWindowList.copyInto(ownedWindowArray);
}
for (int i = 0; i < ownedWindowArray.length; i++) {
Window child = (Window) (((WeakReference)
(ownedWindowArray[i])).get());
if (child != null) {
child.disposeImpl();
}
}
hide();
beforeFirstShow = true;
removeNotify();
synchronized (inputContextLock) {
if (inputContext != null) {
inputContext.dispose();
inputContext = null;
}
}
clearCurrentFocusCycleRootOnHide();
} finally {
disposing = false;
class DisposeAction implements Runnable {
public void run() {
disposing = true;
try {
// Check if this window is the fullscreen window for the
// device. Exit the fullscreen mode prior to disposing
// of the window if that's the case.
GraphicsDevice gd = getGraphicsConfiguration().getDevice();
if (gd.getFullScreenWindow() == Window.this) {
gd.setFullScreenWindow(null);
}
Object[] ownedWindowArray;
synchronized(ownedWindowList) {
ownedWindowArray = new Object[ownedWindowList.size()];
ownedWindowList.copyInto(ownedWindowArray);
}
for (int i = 0; i < ownedWindowArray.length; i++) {
Window child = (Window) (((WeakReference)
(ownedWindowArray[i])).get());
if (child != null) {
child.disposeImpl();
}
}
hide();
beforeFirstShow = true;
removeNotify();
synchronized (inputContextLock) {
if (inputContext != null) {
inputContext.dispose();
inputContext = null;
}
}
clearCurrentFocusCycleRootOnHide();
} finally {
disposing = false;
}
}
}
boolean fireWindowClosedEvent = isDisplayable();
DisposeAction action = new DisposeAction();
if (EventQueue.isDispatchThread()) {
@@ -3962,7 +3950,6 @@ public class Window extends Container implements Accessible {
private float getHeight() { return height; }
private void setHeight(float height) {
if (height <= 0.0f) throw new IllegalArgumentException("TitleBar height must be positive");
if (this.height == height) return;
this.height = height;
notifyUpdate();
}
@@ -3971,17 +3958,13 @@ public class Window extends Container implements Accessible {
}
private void putProperties(Map<String, ?> m) {
if (properties == null) properties = new HashMap<>();
boolean needsUpdate = false;
for (Map.Entry<String, ?> e : m.entrySet()) {
Object old = properties.put(e.getKey(), e.getValue());
if (!needsUpdate && !Objects.equals(old, e.getValue())) needsUpdate = true;
}
if (needsUpdate) notifyUpdate();
properties.putAll(m);
notifyUpdate();
}
private void putProperty(String key, Object value) {
if (properties == null) properties = new HashMap<>();
Object old = properties.put(key, value);
if (!Objects.equals(old, value)) notifyUpdate();
properties.put(key, value);
notifyUpdate();
}
private float getLeftInset() { return insets[0]; }
private float getRightInset() { return insets[1]; }
@@ -4176,36 +4159,8 @@ public class Window extends Container implements Accessible {
return value;
}
private final static String STATS_ALL_SUFFIX = ".all";
private final static String SYSTEM_PROPERTY_COUNTERS;
private final static boolean USE_COUNTERS;
private final static boolean TRACE_ALL_COUNTERS;
private final static boolean TRACE_STD_ERR;
private final static int TRACE_CAPACITY;
private final static boolean TRACE_COUNTERS = true;
private final static boolean DUMP_STATS = true;
// thread dump interval (ms)
static final long DUMP_INTERVAL = 10 * 1000L;
private static PrintStream getTraceStdStream() {
// get live std stream:
return TRACE_STD_ERR ? System.err : System.out;
}
static {
SYSTEM_PROPERTY_COUNTERS = System.getProperty("awt.window.counters");
USE_COUNTERS = (SYSTEM_PROPERTY_COUNTERS != null);
TRACE_ALL_COUNTERS = USE_COUNTERS && (Objects.equals(SYSTEM_PROPERTY_COUNTERS, "")
|| Objects.equals(SYSTEM_PROPERTY_COUNTERS, "stderr")
|| Objects.equals(SYSTEM_PROPERTY_COUNTERS, "stdout"));
TRACE_STD_ERR = USE_COUNTERS && SYSTEM_PROPERTY_COUNTERS.contains("stderr");
TRACE_CAPACITY = USE_COUNTERS ? 8 : 0;
String counters = System.getProperty("awt.window.counters");
AWTAccessor.setWindowAccessor(new AWTAccessor.WindowAccessor() {
public void updateWindow(Window window) {
@@ -4242,201 +4197,100 @@ public class Window extends Container implements Accessible {
public boolean countersEnabled(Window w) {
// May want to selectively enable or disable counters per window
return USE_COUNTERS;
return counters != null;
}
private final static long NANO_IN_SEC = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
public void bumpCounter(Window w, String counterName) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
public void incrementCounter(final Window w, final String counterName) {
if (USE_COUNTERS) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
final long curTimeNanos = System.nanoTime();
// use try-catch to avoid throwing runtime exception to native JNI callers!
try {
PerfCounter newCounter, prevCounter;
synchronized (w.perfCounters) {
newCounter = w.perfCounters.compute(counterName, (_, v) ->
v == null
? new PerfCounter(curTimeNanos, 1L)
: new PerfCounter(curTimeNanos, v.value + 1));
PerfCounter newCounter;
long curTimeNanos = System.nanoTime();
synchronized (w.perfCounters) {
newCounter = w.perfCounters.compute(counterName, (k, v) ->
v == null
? new PerfCounter(curTimeNanos, 1L)
: new PerfCounter(curTimeNanos, v.value + 1));
}
PerfCounter prevCounter;
synchronized (w.perfCountersPrev) {
prevCounter = w.perfCountersPrev.putIfAbsent(counterName, newCounter);
}
if (prevCounter != null) {
long nanosInSecond = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
long timeDeltaNanos = curTimeNanos - prevCounter.updateTimeNanos;
if (timeDeltaNanos > nanosInSecond) {
long valPerSecond = (long) ((double) (newCounter.value - prevCounter.value)
* nanosInSecond / timeDeltaNanos);
boolean traceAllCounters = Objects.equals(counters, "")
|| Objects.equals(counters, "stdout")
|| Objects.equals(counters, "stderr");
boolean traceEnabled = traceAllCounters || (counters != null && counters.contains(counterName));
if (traceEnabled) {
if (counters.contains("stderr")) {
System.err.println(counterName + " per second: " + valPerSecond);
} else {
System.out.println(counterName + " per second: " + valPerSecond);
}
}
if (perfLog.isLoggable(PlatformLogger.Level.FINE)) {
perfLog.fine(counterName + " per second: " + valPerSecond);
}
synchronized (w.perfCountersPrev) {
prevCounter = w.perfCountersPrev.putIfAbsent(counterName, newCounter);
}
if (prevCounter != null) {
final long timeDeltaNanos = curTimeNanos - prevCounter.updateTimeNanos;
if (timeDeltaNanos > NANO_IN_SEC) {
final double valPerSecond = (double) (newCounter.value - prevCounter.value)
* NANO_IN_SEC / timeDeltaNanos;
synchronized (w.perfCountersPrev) {
w.perfCountersPrev.put(counterName, newCounter);
}
addStat(w, counterName, valPerSecond);
if (TRACE_COUNTERS) {
dumpCounter(counterName, valPerSecond);
}
}
}
} catch (RuntimeException re) {
perfLog.severe("incrementCounter: failed", re);
}
}
}
public void addStat(final Window w, final String statName, final double value) {
if (USE_COUNTERS && Double.isFinite(value)) {
Objects.requireNonNull(w);
Objects.requireNonNull(statName);
// use try-catch to avoid throwing runtime exception to native JNI callers!
try {
synchronized (w.perfStats) {
StatDouble stat = w.perfStats.computeIfAbsent(statName, StatDouble::new);
stat.add(value);
stat = w.perfStats.computeIfAbsent(statName + STATS_ALL_SUFFIX, StatDouble::new);
stat.add(value);
}
} catch (RuntimeException re) {
perfLog.severe("addStat: failed", re);
}
}
}
public long getCounter(final Window w, final String counterName) {
if (USE_COUNTERS) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
synchronized (w.perfCounters) {
PerfCounter counter = w.perfCounters.get(counterName);
return counter != null ? counter.value : -1L;
}
}
return -1L;
}
public double getCounterPerSecond(final Window w, final String counterName) {
if (USE_COUNTERS) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
PerfCounter newCounter, prevCounter;
synchronized (w.perfCounters) {
newCounter = w.perfCounters.get(counterName);
}
synchronized (w.perfCountersPrev) {
prevCounter = w.perfCountersPrev.get(counterName);
}
if (newCounter != null && prevCounter != null) {
final long timeDeltaNanos = newCounter.updateTimeNanos - prevCounter.updateTimeNanos;
// Note that this time delta will usually be above one second.
if (timeDeltaNanos > 0L) {
return (double) (newCounter.value - prevCounter.value) * NANO_IN_SEC / timeDeltaNanos;
}
}
}
return Double.NaN;
}
public void dumpStats(final Window w, final boolean reset, StringBuilder sb) {
if (USE_COUNTERS) {
synchronized (w.perfStats) {
boolean header = false;
for (final StatDouble stat : w.perfStats.values()) {
if (stat.shouldLog()) {
final boolean traceEnabled = TRACE_ALL_COUNTERS || SYSTEM_PROPERTY_COUNTERS.contains(stat.name);
if (!header) {
header = true;
doLog(String.format("* Window['%s'@%s]:",
(w instanceof Frame ? ((Frame) w).getTitle() : ""),
Integer.toHexString(System.identityHashCode(w))),
traceEnabled);
}
// format:
if (sb == null) {
sb = new StringBuilder(128);
}
sb.setLength(0);
sb.append(" - ");
stat.toString(sb);
doLog(sb.toString(), traceEnabled);
if (reset && !stat.name.endsWith(STATS_ALL_SUFFIX)) {
stat.reset();
} else {
stat.updateLastLogCount();
}
}
w.perfCountersPrev.put(counterName, newCounter);
}
}
}
}
private static void dumpCounter(final String counterName, final double valPerSecond) {
if (USE_COUNTERS) {
doLog(String.format("%s per second: %.2f", counterName, valPerSecond),
TRACE_ALL_COUNTERS || SYSTEM_PROPERTY_COUNTERS.contains(counterName));
public long getCounter(Window w, String counterName) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
synchronized (w.perfCounters) {
PerfCounter counter = w.perfCounters.get(counterName);
return counter != null ? counter.value : -1L;
}
}
private static void doLog(final String msg, final boolean traceEnabled) {
if (traceEnabled) {
getTraceStdStream().println(msg);
public long getCounterPerSecond(Window w, String counterName) {
Objects.requireNonNull(w);
Objects.requireNonNull(counterName);
PerfCounter newCounter;
PerfCounter prevCounter;
synchronized (w.perfCounters) {
newCounter = w.perfCounters.get(counterName);
}
if (perfLog.isLoggable(PlatformLogger.Level.FINE)) {
perfLog.fine(msg);
synchronized (w.perfCountersPrev) {
prevCounter = w.perfCountersPrev.get(counterName);
}
if (newCounter != null && prevCounter != null) {
long timeDeltaNanos = newCounter.updateTimeNanos - prevCounter.updateTimeNanos;
// Note that this time delta will usually be above one second.
if (timeDeltaNanos > 0) {
long nanosInSecond = java.util.concurrent.TimeUnit.SECONDS.toNanos(1);
long valPerSecond = (long) ((double) (newCounter.value - prevCounter.value)
* nanosInSecond / timeDeltaNanos);
return valPerSecond;
}
}
return -1;
}
}); // WindowAccessor
if (USE_COUNTERS) {
final Runnable dumper = new Runnable() {
private final static StringBuilder sb = new StringBuilder(128);
@Override
public void run() {
getTraceStdStream().printf("--- WindowStats dump at: %s ---\n", new java.util.Date());
final AWTAccessor.WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor();
for (Window window : Window.getWindows()) {
// dump stats if needed:
windowAccessor.dumpStats(window, true, sb);
}
getTraceStdStream().println("-----");
}
};
final Thread hook = InnocuousThread.newSystemThread("WindowStatsHook", dumper);
hook.setDaemon(true);
hook.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(hook);
if (DUMP_STATS) {
final Timer statTimer = new Timer("WindowStats", true);
statTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
dumper.run();
}
}, DUMP_INTERVAL, DUMP_INTERVAL);
}
}
} // static
// a window doesn't need to be updated in the Z-order.
@Override
void updateZOrder() {}
private record PerfCounter(long updateTimeNanos, long value) {}
private record PerfCounter(Long updateTimeNanos, Long value) {}
private transient final HashMap<String, PerfCounter> perfCounters = (USE_COUNTERS) ? new HashMap<>(TRACE_CAPACITY) : null;
private transient final HashMap<String, PerfCounter> perfCountersPrev = (USE_COUNTERS) ? new HashMap<>(TRACE_CAPACITY) : null;
private transient final LinkedHashMap<String, StatDouble> perfStats = (USE_COUNTERS) ? new LinkedHashMap<>(TRACE_CAPACITY) : null;
private transient final Map<String, PerfCounter> perfCounters = new HashMap<>(4);
private transient final Map<String, PerfCounter> perfCountersPrev = new HashMap<>(4);
} // class Window

View File

@@ -27,7 +27,10 @@ package javax.swing;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.VolatileImage;
import java.awt.peer.WindowPeer;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.applet.*;
@@ -40,12 +43,14 @@ import sun.java2d.SunGraphicsEnvironment;
import com.sun.java.swing.SwingUtilities3;
import java.awt.geom.AffineTransform;
import java.util.stream.Collectors;
import sun.java2d.SunGraphics2D;
import sun.java2d.pipe.Region;
import sun.swing.SwingAccessor;
import sun.swing.SwingUtilities2;
import sun.swing.SwingUtilities2.RepaintListener;
import java.util.stream.Collectors;
/**
* This class manages repaint requests, allowing the number
@@ -750,7 +755,7 @@ public class RepaintManager
.filter(Objects::nonNull)
.distinct()
.forEach(w -> AWTAccessor.getWindowAccessor()
.incrementCounter(w, "swing.RepaintManager.updateWindows"));
.bumpCounter(w, "swing.RepaintManager.updateWindows"));
if (Toolkit.getDefaultToolkit() instanceof SunToolkit sunToolkit &&
sunToolkit.needUpdateWindow()) {
@@ -769,14 +774,14 @@ public class RepaintManager
for (Window window : windows) {
AWTAccessor.getWindowAccessor().updateWindow(window);
AWTAccessor.getWindowAccessor().incrementCounter(window, "swing.RepaintManager.updateWindows");
AWTAccessor.getWindowAccessor().bumpCounter(window, "swing.RepaintManager.updateWindows");
}
} else {
dirtyComponents.keySet().stream()
.map(c -> c instanceof Window w ? w : SwingUtilities.getWindowAncestor(c))
.filter(Objects::nonNull)
.forEach(w -> AWTAccessor.getWindowAccessor()
.incrementCounter(w, "swing.RepaintManager.updateWindows"));
.bumpCounter(w, "swing.RepaintManager.updateWindows"));
}
}

View File

@@ -748,27 +748,6 @@ public class BasicTreeUI extends TreeUI
return bounds;
}
/**
* A potentially faster version of {@link #getPathBounds(JTree, TreePath)}
* which calculates only {@code y} and {@code height}
* of the bounding {@code Rectangle}
*/
private Rectangle getVerticalPathBounds(TreePath path) {
if (tree == null || treeState == null) {
return null;
}
int rowHeight = treeState.getRowHeight();
if (rowHeight <= 0) {
return getPathBounds(tree, path);
}
int row = treeState.getRowForPath(path);
if (row < 0) {
return null;
}
return new Rectangle(0, tree.getInsets().top + row * rowHeight,
0, rowHeight);
}
/**
* Returns the path for passed in row. If row is not visible
* null is returned.
@@ -4402,21 +4381,17 @@ public class BasicTreeUI extends TreeUI
updateSize();
}
else if (treeState.isExpanded(parentPath)) {
TreePath minPath = null;
Rectangle minBounds = null;
if (tree.isShowing()) {
// Changed nodes are visible
// Find the minimum index, we only need paint from there
// down.
int minIndex = indices[0];
for (int i = indices.length - 1; i > 0; i--) {
minIndex = Math.min(indices[i], minIndex);
}
Object minChild = treeModel.getChild(
parentPath.getLastPathComponent(), minIndex);
minPath = parentPath.pathByAddingChild(minChild);
minBounds = getVerticalPathBounds(minPath);
// Changed nodes are visible
// Find the minimum index, we only need paint from there
// down.
int minIndex = indices[0];
for (int i = indices.length - 1; i > 0; i--) {
minIndex = Math.min(indices[i], minIndex);
}
Object minChild = treeModel.getChild(
parentPath.getLastPathComponent(), minIndex);
TreePath minPath = parentPath.pathByAddingChild(minChild);
Rectangle minBounds = getPathBounds(tree, minPath);
// Forward to the treestate
treeState.treeNodesChanged(e);
@@ -4424,19 +4399,20 @@ public class BasicTreeUI extends TreeUI
// Mark preferred size as bogus.
updateSize0();
if (minBounds != null) {
// And repaint
Rectangle newMinBounds = getVerticalPathBounds(minPath);
if (newMinBounds != null) {
if (indices.length == 1 &&
newMinBounds.height == minBounds.height) {
tree.repaint(0, minBounds.y, tree.getWidth(),
minBounds.height);
} else {
tree.repaint(0, minBounds.y, tree.getWidth(),
tree.getHeight() - minBounds.y);
}
}
// And repaint
Rectangle newMinBounds = getPathBounds(tree, minPath);
if (minBounds == null || newMinBounds == null) {
return;
}
if (indices.length == 1 &&
newMinBounds.height == minBounds.height) {
tree.repaint(0, minBounds.y, tree.getWidth(),
minBounds.height);
}
else {
tree.repaint(0, minBounds.y, tree.getWidth(),
tree.getHeight() - minBounds.y);
}
}
else {

View File

@@ -37,6 +37,7 @@ import java.awt.event.InputEvent;
import java.awt.event.InvocationEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.image.BufferStrategy;
import java.awt.peer.ComponentPeer;
@@ -328,15 +329,10 @@ public final class AWTAccessor {
*/
Window[] getOwnedWindows(Window w);
/* JBR Window counters API */
boolean countersEnabled(Window w);
void incrementCounter(Window w, String counterName);
void addStat(Window w, String statName, double value);
void bumpCounter(Window w, String counterName);
long getCounter(Window w, String counterName);
double getCounterPerSecond(Window w, String counterName);
void dumpStats(Window w, boolean reset, StringBuilder sb);
long getCounterPerSecond(Window w, String counterName);
}
/**

View File

@@ -1,5 +1,6 @@
/*
* Copyright 2025 JetBrains s.r.o.
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, JetBrains s.r.o.. 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
@@ -23,11 +24,13 @@
* questions.
*/
package sun.awt;
import java.awt.image.BufferedImage;
import java.util.EventListener;
public interface SurfacePixelGrabber {
BufferedImage getClientAreaSnapshot(int x, int y, int width, int height);
public interface DisplayParametersChangedListener extends EventListener {
/**
* Invoked when the display parameters changed.
*/
public void displayParametersChanged();
}

View File

@@ -50,7 +50,6 @@ import java.awt.KeyboardFocusManager;
import java.awt.Label;
import java.awt.MenuComponent;
import java.awt.Panel;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.ScrollPane;
import java.awt.Scrollbar;
@@ -91,7 +90,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import com.jetbrains.exported.JBRApi;
import sun.awt.im.InputContext;
import sun.awt.image.ByteArrayImageSource;
import sun.awt.image.FileImageSource;
@@ -2086,23 +2084,6 @@ public abstract class SunToolkit extends Toolkit
return AWTAccessor.getAWTEventAccessor().isSystemGenerated(e);
}
@JBRApi.Service
@JBRApi.Provides("RelativePointerMovement")
public interface RelativePointerMovementInfoProvider {
private static RelativePointerMovementInfoProvider create() {
var tk = Toolkit.getDefaultToolkit();
if (tk instanceof ComponentFactory cf) {
var mouseInfoPeer = cf.getMouseInfoPeer();
if (mouseInfoPeer instanceof RelativePointerMovementInfoProvider p){
return p;
}
}
throw new JBRApi.ServiceNotAvailableException("Service not supported for toolkit " + tk.getClass().getName());
}
Point getAccumulatedMouseDeltaAndReset();
}
} // class SunToolkit

View File

@@ -44,6 +44,7 @@ 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;
@@ -59,7 +60,7 @@ import sun.java2d.pipe.Region;
* @see GraphicsConfiguration
*/
public abstract class SunGraphicsEnvironment extends GraphicsEnvironment
implements DisplayChangedListener {
implements DisplayChangedListener, DisplayParametersChangedListener {
/** Establish the default font to be used by SG2D. */
private final Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
@@ -275,6 +276,15 @@ 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, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2021, 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,9 +144,7 @@ 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,
final double A, final double B)
{
private int perpendiculardfddf(final double[] pts, final int off) {
assert pts.length >= off + 4;
// these are the coefficients of some multiple of g(t) (not g(t),
@@ -157,7 +155,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, A, B);
return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d);
}
// Tries to find the roots of the function ROC(t)-w in [0, 1). It uses
@@ -173,43 +171,35 @@ 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 A, final double B)
{
int rootsOfROCMinusW(final double[] roots, final int off, final double w2, final double err) {
// 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, A, B);
Helpers.isort(roots, off, end);
final int end = off + perpendiculardfddf(roots, off);
roots[end] = 1.0d; // always check interval end points
double t0 = 0.0d;
double ft0 = eliminateInf(ROCsq(t0) - w2);
double t1, ft1;
double t0 = 0.0d, ft0 = ROCsq(t0) - w2;
for (int i = off; i <= end; i++) {
t1 = roots[i];
ft1 = eliminateInf(ROCsq(t1) - w2);
double t1 = roots[i], ft1 = 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, ft0, ft1, w2, A); // A = err
roots[ret++] = falsePositionROCsqMinusX(t0, t1, w2, err);
}
t0 = t1;
ft0 = ft1;
}
return ret - off;
}
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;
private static double eliminateInf(final double x) {
return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE :
(x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x));
}
// A slight modification of the false position algorithm on wikipedia.
@@ -220,18 +210,17 @@ 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 s = t0, fs = eliminateInf(ft0);
double t = t1, ft = eliminateInf(ft1);
double t = t1, ft = eliminateInf(ROCsq(t) - w2);
double s = t0, fs = eliminateInf(ROCsq(s) - w2);
double r = s, fr;
for (int i = 0; i < iterLimit && Math.abs(t - s) > err; i++) {
for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) {
r = (fs * t - ft * s) / (fs - ft);
fr = eliminateInf(ROCsq(r) - w2);
fr = ROCsq(r) - w2;
if (sameSign(fr, ft)) {
ft = fr; t = r;
if (side < 0) {
@@ -252,7 +241,7 @@ final class Curve {
break;
}
}
return (Math.abs(ft) <= Math.abs(fs)) ? t : s;
return r;
}
private static boolean sameSign(final double x, final double y) {
@@ -267,9 +256,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; // 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
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));
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2024, 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 * Helpers.ulp(num);
return Math.abs(num) < 2.0d * Math.ulp(num);
}
abstract static class NormalizingPathIterator implements PathIterator {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2022, 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,19 +31,12 @@ 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);
}
@@ -329,10 +322,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, T_A, T_B);
ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d);
ret = filterOutNotInAB(ts, 0, ret, T_A, T_B);
isort(ts, 0, ret);
ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d);
isort(ts, ret);
return ret;
}
@@ -361,7 +354,7 @@ final class Helpers implements MarlinConst {
if ((outCodeOR & OUTCODE_BOTTOM) != 0) {
ret += curve.yPoints(ts, ret, clipRect[1]);
}
isort(ts, 0, ret);
isort(ts, ret);
return ret;
}
@@ -381,11 +374,11 @@ final class Helpers implements MarlinConst {
}
}
static void isort(final double[] a, final int off, final int len) {
for (int i = off + 1, j; i < len; i++) {
static void isort(final double[] a, final int len) {
for (int i = 1, j; i < len; i++) {
final double ai = a[i];
j = i - 1;
for (; j >= off && a[j] > ai; j--) {
for (; j >= 0 && a[j] > ai; j--) {
a[j + 1] = a[j];
}
a[j + 1] = ai;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2024, 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,8 +28,6 @@ package sun.java2d.marlin;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentLinkedQueue;
import jdk.internal.misc.InnocuousThread;
import jdk.internal.ref.CleanerFactory;
import sun.java2d.marlin.ArrayCacheConst.CacheStats;
import static sun.java2d.marlin.MarlinUtils.logInfo;
@@ -385,13 +383,21 @@ public final class RendererStats implements MarlinConst {
= new ConcurrentLinkedQueue<>();
private RendererStatsHolder() {
final Thread hook = InnocuousThread.newSystemThread("MarlinStatsHook", () -> dump());
hook.setDaemon(true);
final Thread hook = new Thread(
MarlinUtils.getRootThreadGroup(),
new Runnable() {
@Override
public void run() {
dump();
}
},
"MarlinStatsHook"
);
hook.setContextClassLoader(null);
Runtime.getRuntime().addShutdownHook(hook);
if (USE_DUMP_THREAD) {
final Timer statTimer = new Timer("RendererStats", true);
final Timer statTimer = new Timer("RendererStats");
statTimer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2023, 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 * Helpers.ulp(y2));
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Helpers.ulp(y4));
final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Math.ulp(y2));
final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Math.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 * Helpers.ulp(dotsq))) {
if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Math.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 * Helpers.ulp(y2));
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Helpers.ulp(y3));
final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Math.ulp(y2));
final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Math.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 * Helpers.ulp(dotsq))) {
if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) {
return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2023, 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.9-Unsafe-OpenJDK";
private static final String VERSION = "marlin-0.9.4.7-Unsafe-OpenJDK";
public static String getVersion() {
return VERSION;

View File

@@ -1,128 +0,0 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* 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 sun.java2d.marlin.stats;
import static sun.java2d.marlin.stats.StatLong.trimTo3Digits;
/**
* Statistics on double values
*/
public final class StatDouble {
// rolling mean weight (lerp):
private final static double EMA_ALPHA = 0.25;
private final static double EMA_ONE_MINUS_ALPHA = 1.0 - EMA_ALPHA;
public final String name;
private long count, lastLogCount;
private double min, max, mean, ema_mean = 0.0, squaredError;
public StatDouble(final String name) {
this.name = name;
reset();
}
public void reset() {
count = 0L;
lastLogCount = 0L;
min = Double.POSITIVE_INFINITY;
max = Double.NEGATIVE_INFINITY;
mean = 0.0;
// skip ema_mean = 0.0;
squaredError = 0.0;
}
public void add(final double val) {
count++;
if (val < min) {
min = val;
}
if (val > max) {
max = val;
}
// Exponential smoothing (EMA):
ema_mean = EMA_ALPHA * val + EMA_ONE_MINUS_ALPHA * ema_mean;
// Welford's algorithm:
final double oldMean = mean;
mean += (val - mean) / count;
squaredError += (val - mean) * (val - oldMean);
}
public boolean shouldLog() {
return (count > lastLogCount);
}
public void updateLastLogCount() {
this.lastLogCount = this.count;
}
public long count() {
return count;
}
public double min() {
return (count != 0L) ? min : Double.NaN;
}
public double max() {
return (count != 0L) ? max : Double.NaN;
}
public double mean() {
return (count != 0L) ? mean : Double.NaN;
}
public double ema() {
return (count != 0L) ? ema_mean : Double.NaN;
}
public double variance() {
return (count != 0L) ? (squaredError / (count - 1L)) : Double.NaN;
}
public double stddev() {
return (count != 0L) ? Math.sqrt(variance()) : Double.NaN;
}
public double total() {
return (count != 0L) ? (mean() * count) : Double.NaN;
}
@Override
public String toString() {
return toString(new StringBuilder(128)).toString();
}
public StringBuilder toString(final StringBuilder sb) {
sb.append(name).append('[').append(count);
sb.append("] sum: ").append(trimTo3Digits(total()));
sb.append(" avg: ").append(trimTo3Digits(mean()));
sb.append(" stddev: ").append(trimTo3Digits(stddev()));
sb.append(" ema: ").append(trimTo3Digits(ema()));
sb.append(" [").append(trimTo3Digits(min())).append(" - ").append(trimTo3Digits(max())).append("]");
return sb;
}
}

View File

@@ -31,6 +31,7 @@ import sun.util.logging.PlatformLogger;
import java.awt.Toolkit;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public final class VKEnv {
@@ -48,7 +49,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", "true")));
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "")));
@SuppressWarnings("removal")
private static final int deviceNumber = !vulkan ? 0 : AccessController.doPrivileged(
@@ -108,20 +109,16 @@ public final class VKEnv {
state = newState;
if (Options.verbose || log.isLoggable(PlatformLogger.Level.FINE)) {
StringBuilder msg = new StringBuilder("Vulkan rendering enabled: ");
String message;
if (isVulkanEnabled()) {
msg.append("YES")
.append("\n Presentation enabled: ").append(isPresentationEnabled() ? "YES" : "NO")
.append("\n Accelerated surface data enabled: ").append(isSurfaceDataAccelerated() ? "YES" : "NO")
.append("\n Devices:");
for (int i = 0; i < devices.length; i++) {
VKGPU d = devices[i];
msg.append(d == defaultDevice ? "\n *" : "\n ").append(i).append(": ").append(d.getName());
}
message = "Vulkan rendering enabled: YES" +
"\n presentation enabled: " + (isPresentationEnabled() ? "YES" : "NO") +
"\n accelerated surface data enabled: " + (isSurfaceDataAccelerated() ? "YES" : "NO") +
"\n devices:" + Stream.of(devices).map(d -> (d == defaultDevice ?
"\n *" : "\n ") + d.getName()).collect(Collectors.joining());
} else {
msg.append("NO");
message = "Vulkan rendering enabled: NO";
}
String message = msg.toString();
if (Options.verbose) {
System.err.println(message);
}

View File

@@ -36,7 +36,6 @@ 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;
@@ -44,6 +43,7 @@ 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,29 +137,7 @@ 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) {
protected BufferedImage getSnapshot(int x, int y, int width, int height) {
BufferedImage image = getFormat().createCompatibleImage(width, height, getTransparency());
SurfaceData sd = SurfaceData.getPrimarySurfaceData(image);
Blit blit = Blit.getFromCache(getSurfaceType(), CompositeType.SrcNoEa, sd.getSurfaceType());

View File

@@ -0,0 +1,20 @@
#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
#include "common.glsl"
DEFAULT_PUSH_CONSTANTS();
#define ALPHA_TYPE_SPEC_INDEX 0
#include "alpha_type.glsl"
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 = APPLY_COMPOSITE(convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord)));
out_Color = convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord));
}

View File

@@ -1,12 +1,14 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
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 = transformToDeviceSpace(in_Position);
gl_Position = vec4(vec3(in_Position, 1.0)*push.transform, 0.0, 1.0);
out_TexCoord = in_TexCoord;
}

View File

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

View File

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

View File

@@ -1,103 +0,0 @@
// 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

@@ -1,21 +0,0 @@
#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

@@ -1,21 +0,0 @@
#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,6 +1,4 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(set = 0, binding = 0, r8) uniform readonly restrict imageBuffer u_Mask;
@@ -12,5 +10,9 @@ layout(location = 1) in flat vec4 in_Color;
layout(location = 0) out vec4 out_Color;
void main() {
out_Color = APPLY_MASK(in_Color);
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;
}

View File

@@ -1,9 +1,11 @@
#version 450
#extension GL_GOOGLE_include_directive: require
#include "common.glsl"
layout(push_constant) uniform PushConstants {
mat2x3 transform;
} push;
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
layout(location = 1) in uint in_Color;
layout(location = 1) in vec4 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.
@@ -12,7 +14,7 @@ layout(location = 0) out flat ivec4 out_OriginOffsetAndScanline;
layout(location = 1) out flat vec4 out_Color;
void main() {
gl_Position = transformToDeviceSpace(in_PositionOffsetAndScanline.xy);
gl_Position = vec4(vec3(in_PositionOffsetAndScanline.xy, 1)*push.transform, 0.0, 1.0);
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
out_Color = convertAlpha(decodeColor(in_Color));
out_Color = in_Color;
}

View File

@@ -1,15 +0,0 @@
#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 0
#define INIT_TEST 1
#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, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
if (!VKRenderer_Validate(SHADER_BLIT, 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);
while (srcInfo.rasBase) {
if (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,17 +165,12 @@ 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, NO_SHADER_VARIANT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) break;
if (!VKRenderer_Validate(SHADER_BLIT, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, alphaType)) return;
VKDevice* device = context->surface->device;
BlitSrcType type = decodeSrcType(device, srctype);
VKTexturePoolHandle* imageHandle =
VKTexturePool_GetTexture(VKRenderer_GetTexturePool(device->renderer), sw, sh, type.format);
VKTexturePoolHandle* imageHandle = VKTexturePool_GetTexture(device->texturePool, 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;
@@ -236,9 +231,7 @@ 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);
break;
}
if (!srcInfo.rasBase) {
} else {
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_STRAIGHT });
.logicOp = VK_LOGIC_OP_XOR }, ALPHA_TYPE_PRE_MULTIPLIED });
// NAME | SRC_COLOR | DST_COLOR | SRC_ALPHA | DST_ALPHA ||
ALPHA_BLEND( CLEAR , ZERO , ZERO , ZERO , ZERO );
@@ -138,6 +138,7 @@ 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,

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