mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-02-04 06:36:32 +01:00
Compare commits
109 Commits
jbr21.968
...
avu/ISO_BL
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da19b1c201 | ||
|
|
06cc75d80b | ||
|
|
203aad0e7d | ||
|
|
fa662e668a | ||
|
|
f4eed0aabf | ||
|
|
c43a8e77a9 | ||
|
|
44c769baf2 | ||
|
|
d65e4f3a69 | ||
|
|
01a88fa82d | ||
|
|
224651121f | ||
|
|
333dbcb00f | ||
|
|
c874bfb819 | ||
|
|
f14bfe0de9 | ||
|
|
e948e68a1c | ||
|
|
a40497a1a1 | ||
|
|
221844284c | ||
|
|
8ce1865667 | ||
|
|
dfa2f93ded | ||
|
|
a70d004636 | ||
|
|
bcaea044f6 | ||
|
|
62e4696d1a | ||
|
|
3dd9b5b323 | ||
|
|
9d1557ed3c | ||
|
|
b6f8f9f1b7 | ||
|
|
548521e162 | ||
|
|
633895e1d8 | ||
|
|
fdc9dd44b6 | ||
|
|
677d8edb87 | ||
|
|
52b213d96c | ||
|
|
df366c74c1 | ||
|
|
fc40612222 | ||
|
|
8b7153234f | ||
|
|
26f247ffb3 | ||
|
|
aa20c8b9f4 | ||
|
|
120dd88dd0 | ||
|
|
bb371ce7b0 | ||
|
|
abbf53d08e | ||
|
|
921053cda6 | ||
|
|
1b0348f1b9 | ||
|
|
8120022a66 | ||
|
|
ac68b628c7 | ||
|
|
99d3227951 | ||
|
|
9116f5b953 | ||
|
|
13ddb27c38 | ||
|
|
6e0ea66116 | ||
|
|
f6b0380fd9 | ||
|
|
70a658f57a | ||
|
|
8fd5f9c426 | ||
|
|
03cf016f2d | ||
|
|
1e1e4b38c6 | ||
|
|
3b4da58e2c | ||
|
|
1b439f8a98 | ||
|
|
4516560f65 | ||
|
|
4a94eadd90 | ||
|
|
42db39fb4e | ||
|
|
cb751d0b52 | ||
|
|
f711061895 | ||
|
|
6d0eb24888 | ||
|
|
3c90ecd46c | ||
|
|
54817b2e8d | ||
|
|
c70e17b88b | ||
|
|
bcd6f0c9c0 | ||
|
|
646d2e478f | ||
|
|
4214897d5e | ||
|
|
189907d2ae | ||
|
|
4b17fcc46e | ||
|
|
03804770b6 | ||
|
|
1d0cbadf05 | ||
|
|
8cfd55e764 | ||
|
|
b06068de9c | ||
|
|
eb027e2bc9 | ||
|
|
5fbd7f38e0 | ||
|
|
44754c75f9 | ||
|
|
0bf04b04b0 | ||
|
|
ca69af5c29 | ||
|
|
1527cb78dd | ||
|
|
bd8b5fa16f | ||
|
|
c53afaf1c6 | ||
|
|
81b393aa37 | ||
|
|
8b4249aa00 | ||
|
|
a8b4f08808 | ||
|
|
88532ca2e1 | ||
|
|
4b01cab791 | ||
|
|
971aaf09d7 | ||
|
|
219ad23c66 | ||
|
|
20015bc3b7 | ||
|
|
20bfe049b3 | ||
|
|
e32b9d4ebc | ||
|
|
8ec3e80317 | ||
|
|
c1325a3735 | ||
|
|
cc2280fd08 | ||
|
|
af4d8df355 | ||
|
|
8fe8fb8108 | ||
|
|
997c61fdc5 | ||
|
|
1651aa4318 | ||
|
|
a6cdff5987 | ||
|
|
5fc78ed3da | ||
|
|
e09479f433 | ||
|
|
d54ab6c19b | ||
|
|
8c3a5c3252 | ||
|
|
d08c6eb496 | ||
|
|
baf55e9e53 | ||
|
|
4482618c0b | ||
|
|
2c7e868474 | ||
|
|
510b4fa816 | ||
|
|
8ee1a7eece | ||
|
|
99bb681fc4 | ||
|
|
d474af791d | ||
|
|
146591e096 |
@@ -40,8 +40,6 @@ architecture=${3:-x64} # aarch64 or x64
|
||||
|
||||
check_bundle_type_maketest
|
||||
|
||||
tag_prefix="jbr-"
|
||||
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "$tag_prefix" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -g | tail -n 1 | tr -d ",")
|
||||
VERSION_FEATURE=$(getVersionProp "DEFAULT_VERSION_FEATURE")
|
||||
VERSION_INTERIM=$(getVersionProp "DEFAULT_VERSION_INTERIM")
|
||||
VERSION_UPDATE=$(getVersionProp "DEFAULT_VERSION_UPDATE")
|
||||
@@ -49,8 +47,15 @@ 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}']"
|
||||
JDK_BUILD_NUMBER=${JDK_BUILD_NUMBER:=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')}
|
||||
tag_prefix="jbr-"
|
||||
OPENJDK_TAG=$(git log --simplify-by-decoration --decorate=short --pretty=short | grep "${tag_prefix}${JBSDK_VERSION}" | cut -d "(" -f2 | cut -d ")" -f1 | awk '{print $2}' | sort -t "-" -k 2 -V -f | tail -n 1 | tr -d ",")
|
||||
JDK_BUILD_NUMBER=$(echo $OPENJDK_TAG | awk -F "-|[+]" '{print $3}')
|
||||
[ -z $JDK_BUILD_NUMBER ] && JDK_BUILD_NUMBER=1
|
||||
re='^[0-9]+$'
|
||||
if ! [[ $JDK_BUILD_NUMBER =~ $re ]] ; then
|
||||
echo "error: JDK_BUILD_NUMBER Not a number: $JDK_BUILD_NUMBER"
|
||||
JDK_BUILD_NUMBER=1
|
||||
fi
|
||||
echo "##teamcity[setParameter name='env.JDK_UPDATE_NUMBER' value='${JDK_BUILD_NUMBER}']"
|
||||
|
||||
VENDOR_NAME="JetBrains s.r.o."
|
||||
|
||||
@@ -32,6 +32,13 @@ function do_configure {
|
||||
--build=x86_64-unknown-linux-gnu \
|
||||
--openjdk-target=x86_64-unknown-linux-gnu"
|
||||
fi
|
||||
|
||||
if [ -n "${JCEF_BUILD_LEGACY:-}" ]; then
|
||||
WITH_VULKAN=""
|
||||
else
|
||||
WITH_VULKAN="--with-vulkan"
|
||||
fi
|
||||
|
||||
sh configure \
|
||||
$WITH_DEBUG_LEVEL \
|
||||
--with-vendor-name="$VENDOR_NAME" \
|
||||
@@ -42,7 +49,7 @@ function do_configure {
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
--enable-cds=yes \
|
||||
--with-vulkan \
|
||||
$WITH_VULKAN \
|
||||
$LINUX_TARGET \
|
||||
$DISABLE_WARNINGS_AS_ERRORS \
|
||||
$STATIC_CONF_ARGS \
|
||||
@@ -95,7 +102,9 @@ function create_image_bundle {
|
||||
|
||||
# jmod does not preserve file permissions (JDK-8173610)
|
||||
[ -f "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/jcef_helper
|
||||
[ -f "$IMAGES_DIR"/"$__root_dir"/lib/cef_server ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/cef_server
|
||||
if [ ! -n "${JCEF_BUILD_LEGACY:-}" ]; then
|
||||
[ -f "$IMAGES_DIR"/"$__root_dir"/lib/cef_server ] && chmod a+x "$IMAGES_DIR"/"$__root_dir"/lib/cef_server
|
||||
fi
|
||||
|
||||
echo Creating "$JBR".tar.gz ...
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ set -x
|
||||
#
|
||||
|
||||
source jb/project/tools/common/scripts/common.sh
|
||||
ENABLE_CDS="no"
|
||||
|
||||
function do_configure {
|
||||
linux32 bash configure \
|
||||
@@ -24,7 +25,7 @@ function do_configure {
|
||||
--with-version-opt=b"$build_number" \
|
||||
--with-boot-jdk="$BOOT_JDK" \
|
||||
$STATIC_CONF_ARGS \
|
||||
--enable-cds=yes \
|
||||
--enable-cds=$ENABLE_CDS \
|
||||
$DISABLE_WARNINGS_AS_ERRORS \
|
||||
$REPRODUCIBLE_BUILD_OPTS \
|
||||
$WITH_ZIPPED_NATIVE_DEBUG_SYMBOLS \
|
||||
@@ -51,7 +52,7 @@ function create_image_bundle {
|
||||
__cds_opt=''
|
||||
|
||||
if is_musl; then libc_type_suffix='musl-' ; fi
|
||||
__cds_opt="--generate-cds-archive"
|
||||
[ "${ENABLE_CDS}" == "yes" ] && __cds_opt="--generate-cds-archive"
|
||||
|
||||
[ "$bundle_type" == "fd" ] && [ "$__arch_name" == "$JBRSDK_BUNDLE" ] && __bundle_name=$__arch_name && fastdebug_infix="fastdebug-"
|
||||
JBR=${__bundle_name}-${JBSDK_VERSION}-linux-${libc_type_suffix}x86-${fastdebug_infix}b${build_number}
|
||||
|
||||
267
jb/project/tools/perf/j2dbopts_poly250-AA-rand_col.txt
Normal file
267
jb/project/tools/perf/j2dbopts_poly250-AA-rand_col.txt
Normal file
@@ -0,0 +1,267 @@
|
||||
prog.verbose=disabled
|
||||
prog.printresults=enabled
|
||||
global.env.outputwidth=640
|
||||
global.env.outputheight=480
|
||||
global.env.runcount=5
|
||||
global.env.repcount=0
|
||||
global.env.testtime=2500
|
||||
global.results.workunits=units
|
||||
global.results.timeunits=sec
|
||||
global.results.ratio=unitspersec
|
||||
global.dest.offscreen=disabled
|
||||
global.dest.frame.defaultframe=enabled
|
||||
global.dest.frame.transframe=disabled
|
||||
global.dest.frame.shapedframe=disabled
|
||||
global.dest.frame.shapedtransframe=disabled
|
||||
global.dest.compatimg.compatimg=disabled
|
||||
global.dest.compatimg.opqcompatimg=disabled
|
||||
global.dest.compatimg.bmcompatimg=disabled
|
||||
global.dest.compatimg.transcompatimg=disabled
|
||||
global.dest.volimg.volimg=disabled
|
||||
global.dest.volimg.opqvolimg=disabled
|
||||
global.dest.volimg.bmvolimg=disabled
|
||||
global.dest.volimg.transvolimg=disabled
|
||||
global.dest.bufimg.IntXrgb=disabled
|
||||
global.dest.bufimg.IntArgb=disabled
|
||||
global.dest.bufimg.IntArgbPre=disabled
|
||||
global.dest.bufimg.3ByteBgr=disabled
|
||||
global.dest.bufimg.ByteIndexed=disabled
|
||||
global.dest.bufimg.ByteGray=disabled
|
||||
global.dest.bufimg.4ByteAbgr=disabled
|
||||
global.dest.bufimg.4ByteAbgrPre=disabled
|
||||
global.dest.bufimg.custom=disabled
|
||||
graphics.opts.anim=2
|
||||
graphics.opts.sizes=250
|
||||
graphics.opts.alpharule=SrcOver
|
||||
graphics.opts.transform=ident
|
||||
graphics.opts.extraalpha=Off
|
||||
graphics.opts.xormode=Off
|
||||
graphics.opts.clip=Off
|
||||
graphics.opts.renderhint=Default
|
||||
graphics.render.opts.paint=random
|
||||
graphics.render.opts.alphacolor=Off
|
||||
graphics.render.opts.antialias=On
|
||||
graphics.render.opts.stroke=width1
|
||||
graphics.render.tests.drawLine=disabled
|
||||
graphics.render.tests.drawLineHoriz=disabled
|
||||
graphics.render.tests.drawLineVert=disabled
|
||||
graphics.render.tests.fillRect=disabled
|
||||
graphics.render.tests.drawRect=disabled
|
||||
graphics.render.tests.fillOval=disabled
|
||||
graphics.render.tests.drawOval=disabled
|
||||
graphics.render.tests.fillPoly=disabled
|
||||
graphics.render.tests.drawPoly=enabled
|
||||
graphics.render.tests.shape.fillCubic=disabled
|
||||
graphics.render.tests.shape.drawCubic=disabled
|
||||
graphics.render.tests.shape.fillEllipse2D=disabled
|
||||
graphics.render.tests.shape.drawEllipse2D=disabled
|
||||
graphics.imaging.src.offscr.opaque=disabled
|
||||
graphics.imaging.src.offscr.bitmask=disabled
|
||||
graphics.imaging.src.offscr.translucent=disabled
|
||||
graphics.imaging.src.opqcompatimg.opaque=disabled
|
||||
graphics.imaging.src.opqcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.opqcompatimg.translucent=disabled
|
||||
graphics.imaging.src.bmcompatimg.opaque=disabled
|
||||
graphics.imaging.src.bmcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.bmcompatimg.translucent=disabled
|
||||
graphics.imaging.src.transcompatimg.opaque=disabled
|
||||
graphics.imaging.src.transcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.transcompatimg.translucent=disabled
|
||||
graphics.imaging.src.opqvolimg.opaque=disabled
|
||||
graphics.imaging.src.opqvolimg.bitmask=disabled
|
||||
graphics.imaging.src.opqvolimg.translucent=disabled
|
||||
graphics.imaging.src.bmvolimg.opaque=disabled
|
||||
graphics.imaging.src.bmvolimg.bitmask=disabled
|
||||
graphics.imaging.src.bmvolimg.translucent=disabled
|
||||
graphics.imaging.src.transvolimg.opaque=disabled
|
||||
graphics.imaging.src.transvolimg.bitmask=disabled
|
||||
graphics.imaging.src.transvolimg.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.translucent=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.translucent=disabled
|
||||
graphics.imaging.benchmarks.opts.interpolation=Nearest neighbor
|
||||
graphics.imaging.benchmarks.opts.touchsrc=Off
|
||||
graphics.imaging.benchmarks.tests.drawimage=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagebg=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaleup=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaledown=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescalesplit=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagetxform=disabled
|
||||
graphics.imaging.imageops.opts.op=convolve3x3zero
|
||||
graphics.imaging.imageops.tests.graphics2d.drawimageop=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filtercached=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filtercached=disabled
|
||||
graphics.misc.copytests.copyAreaVert=disabled
|
||||
graphics.misc.copytests.copyAreaHoriz=disabled
|
||||
graphics.misc.copytests.copyAreaDiag=disabled
|
||||
pixel.opts.renderto=Off
|
||||
pixel.opts.renderfrom=Off
|
||||
pixel.src.1BitBinary=disabled
|
||||
pixel.src.2BitBinary=disabled
|
||||
pixel.src.4BitBinary=disabled
|
||||
pixel.src.ByteIndexed=disabled
|
||||
pixel.src.ByteGray=disabled
|
||||
pixel.src.Short555=disabled
|
||||
pixel.src.Short565=disabled
|
||||
pixel.src.ShortGray=disabled
|
||||
pixel.src.3ByteBgr=disabled
|
||||
pixel.src.4ByteAbgr=disabled
|
||||
pixel.src.IntXrgb=disabled
|
||||
pixel.src.IntXbgr=disabled
|
||||
pixel.src.IntArgb=disabled
|
||||
pixel.bimgtests.getrgb=disabled
|
||||
pixel.bimgtests.setrgb=disabled
|
||||
pixel.rastests.getdataelem=disabled
|
||||
pixel.rastests.setdataelem=disabled
|
||||
pixel.rastests.getpixel=disabled
|
||||
pixel.rastests.setpixel=disabled
|
||||
pixel.dbtests.getelem=disabled
|
||||
pixel.dbtests.setelem=disabled
|
||||
text.opts.data.tlength=16
|
||||
text.opts.data.tscript=english
|
||||
text.opts.font.fname=serif,physical
|
||||
text.opts.font.fstyle=0
|
||||
text.opts.font.fsize=13.0
|
||||
text.opts.font.ftx=Identity
|
||||
text.opts.graphics.textaa=Off
|
||||
text.opts.graphics.tfm=Off
|
||||
text.opts.graphics.gaa=Off
|
||||
text.opts.graphics.gtx=Identity
|
||||
text.opts.advopts.gvstyle=0
|
||||
text.opts.advopts.tlruns=1
|
||||
text.opts.advopts.maptype=FONT
|
||||
text.Rendering.tests.drawString=disabled
|
||||
text.Rendering.tests.drawChars=disabled
|
||||
text.Rendering.tests.drawBytes=disabled
|
||||
text.Rendering.tests.drawGlyphVectors=disabled
|
||||
text.Rendering.tests.drawTextLayout=disabled
|
||||
text.Measuring.tests.stringWidth=disabled
|
||||
text.Measuring.tests.stringBounds=disabled
|
||||
text.Measuring.tests.charsWidth=disabled
|
||||
text.Measuring.tests.charsBounds=disabled
|
||||
text.Measuring.tests.fontcandisplay=disabled
|
||||
text.Measuring.tests.gvWidth=disabled
|
||||
text.Measuring.tests.gvLogicalBounds=disabled
|
||||
text.Measuring.tests.gvVisualBounds=disabled
|
||||
text.Measuring.tests.gvPixelBounds=disabled
|
||||
text.Measuring.tests.gvOutline=disabled
|
||||
text.Measuring.tests.gvGlyphLogicalBounds=disabled
|
||||
text.Measuring.tests.gvGlyphVisualBounds=disabled
|
||||
text.Measuring.tests.gvGlyphPixelBounds=disabled
|
||||
text.Measuring.tests.gvGlyphOutline=disabled
|
||||
text.Measuring.tests.gvGlyphTransform=disabled
|
||||
text.Measuring.tests.gvGlyphMetrics=disabled
|
||||
text.Measuring.tests.tlAdvance=disabled
|
||||
text.Measuring.tests.tlAscent=disabled
|
||||
text.Measuring.tests.tlBounds=disabled
|
||||
text.Measuring.tests.tlGetCaretInfo=disabled
|
||||
text.Measuring.tests.tlGetNextHit=disabled
|
||||
text.Measuring.tests.tlGetCaretShape=disabled
|
||||
text.Measuring.tests.tlGetLogicalHighlightShape=disabled
|
||||
text.Measuring.tests.tlHitTest=disabled
|
||||
text.Measuring.tests.tlOutline=disabled
|
||||
text.construction.tests.gvfromfontstring=disabled
|
||||
text.construction.tests.gvfromfontchars=disabled
|
||||
text.construction.tests.gvfromfontci=disabled
|
||||
text.construction.tests.gvfromfontglyphs=disabled
|
||||
text.construction.tests.gvfromfontlayout=disabled
|
||||
text.construction.tests.tlfromfont=disabled
|
||||
text.construction.tests.tlfrommap=disabled
|
||||
imageio.opts.size=250
|
||||
imageio.opts.content=photo
|
||||
imageio.input.opts.general.source.file=disabled
|
||||
imageio.input.opts.general.source.url=disabled
|
||||
imageio.input.opts.general.source.byteArray=disabled
|
||||
imageio.input.opts.imageio.useCache=Off
|
||||
imageio.input.image.toolkit.opts.format=
|
||||
imageio.input.image.toolkit.tests.createImage=disabled
|
||||
imageio.input.image.imageio.opts.format=
|
||||
imageio.input.image.imageio.tests.imageioRead=disabled
|
||||
imageio.input.image.imageio.reader.opts.seekForwardOnly=On
|
||||
imageio.input.image.imageio.reader.opts.ignoreMetadata=On
|
||||
imageio.input.image.imageio.reader.opts.installListener=Off
|
||||
imageio.input.image.imageio.reader.tests.read=disabled
|
||||
imageio.input.image.imageio.reader.tests.getImageMetadata=disabled
|
||||
imageio.input.stream.tests.construct=disabled
|
||||
imageio.input.stream.tests.read=disabled
|
||||
imageio.input.stream.tests.readByteArray=disabled
|
||||
imageio.input.stream.tests.readFullyByteArray=disabled
|
||||
imageio.input.stream.tests.readBit=disabled
|
||||
imageio.input.stream.tests.readByte=disabled
|
||||
imageio.input.stream.tests.readUnsignedByte=disabled
|
||||
imageio.input.stream.tests.readShort=disabled
|
||||
imageio.input.stream.tests.readUnsignedShort=disabled
|
||||
imageio.input.stream.tests.readInt=disabled
|
||||
imageio.input.stream.tests.readUnsignedInt=disabled
|
||||
imageio.input.stream.tests.readFloat=disabled
|
||||
imageio.input.stream.tests.readLong=disabled
|
||||
imageio.input.stream.tests.readDouble=disabled
|
||||
imageio.input.stream.tests.skipBytes=disabled
|
||||
imageio.output.opts.general.dest.file=disabled
|
||||
imageio.output.opts.general.dest.byteArray=disabled
|
||||
imageio.output.opts.imageio.useCache=Off
|
||||
imageio.output.image.imageio.opts.format=
|
||||
imageio.output.image.imageio.tests.imageioWrite=disabled
|
||||
imageio.output.image.imageio.writer.opts.installListener=Off
|
||||
imageio.output.image.imageio.writer.tests.write=disabled
|
||||
imageio.output.stream.tests.construct=disabled
|
||||
imageio.output.stream.tests.write=disabled
|
||||
imageio.output.stream.tests.writeByteArray=disabled
|
||||
imageio.output.stream.tests.writeBit=disabled
|
||||
imageio.output.stream.tests.writeByte=disabled
|
||||
imageio.output.stream.tests.writeShort=disabled
|
||||
imageio.output.stream.tests.writeInt=disabled
|
||||
imageio.output.stream.tests.writeFloat=disabled
|
||||
imageio.output.stream.tests.writeLong=disabled
|
||||
imageio.output.stream.tests.writeDouble=disabled
|
||||
cmm.opts.profiles=1001
|
||||
cmm.colorconv.data.fromRGB=disabled
|
||||
cmm.colorconv.data.toRGB=disabled
|
||||
cmm.colorconv.data.fromCIEXYZ=disabled
|
||||
cmm.colorconv.data.toCIEXYZ=disabled
|
||||
cmm.colorconv.ccop.ccopOptions.size=250
|
||||
cmm.colorconv.ccop.ccopOptions.content=photo
|
||||
cmm.colorconv.ccop.ccopOptions.srcType=INT_RGB
|
||||
cmm.colorconv.ccop.ccopOptions.dstType=INT_RGB
|
||||
cmm.colorconv.ccop.op_img=disabled
|
||||
cmm.colorconv.ccop.op_rst=disabled
|
||||
cmm.colorconv.ccop.op_draw=disabled
|
||||
cmm.colorconv.embed.embedOptions.Images=512x512
|
||||
cmm.colorconv.embed.embd_img_read=disabled
|
||||
cmm.profiles.getHeader=disabled
|
||||
cmm.profiles.getNumComponents=disabled
|
||||
267
jb/project/tools/perf/j2dbopts_poly250-rand_col.txt
Normal file
267
jb/project/tools/perf/j2dbopts_poly250-rand_col.txt
Normal file
@@ -0,0 +1,267 @@
|
||||
prog.verbose=disabled
|
||||
prog.printresults=enabled
|
||||
global.env.outputwidth=640
|
||||
global.env.outputheight=480
|
||||
global.env.runcount=5
|
||||
global.env.repcount=0
|
||||
global.env.testtime=2500
|
||||
global.results.workunits=units
|
||||
global.results.timeunits=sec
|
||||
global.results.ratio=unitspersec
|
||||
global.dest.offscreen=disabled
|
||||
global.dest.frame.defaultframe=enabled
|
||||
global.dest.frame.transframe=disabled
|
||||
global.dest.frame.shapedframe=disabled
|
||||
global.dest.frame.shapedtransframe=disabled
|
||||
global.dest.compatimg.compatimg=disabled
|
||||
global.dest.compatimg.opqcompatimg=disabled
|
||||
global.dest.compatimg.bmcompatimg=disabled
|
||||
global.dest.compatimg.transcompatimg=disabled
|
||||
global.dest.volimg.volimg=disabled
|
||||
global.dest.volimg.opqvolimg=disabled
|
||||
global.dest.volimg.bmvolimg=disabled
|
||||
global.dest.volimg.transvolimg=disabled
|
||||
global.dest.bufimg.IntXrgb=disabled
|
||||
global.dest.bufimg.IntArgb=disabled
|
||||
global.dest.bufimg.IntArgbPre=disabled
|
||||
global.dest.bufimg.3ByteBgr=disabled
|
||||
global.dest.bufimg.ByteIndexed=disabled
|
||||
global.dest.bufimg.ByteGray=disabled
|
||||
global.dest.bufimg.4ByteAbgr=disabled
|
||||
global.dest.bufimg.4ByteAbgrPre=disabled
|
||||
global.dest.bufimg.custom=disabled
|
||||
graphics.opts.anim=2
|
||||
graphics.opts.sizes=250
|
||||
graphics.opts.alpharule=SrcOver
|
||||
graphics.opts.transform=ident
|
||||
graphics.opts.extraalpha=Off
|
||||
graphics.opts.xormode=Off
|
||||
graphics.opts.clip=Off
|
||||
graphics.opts.renderhint=Default
|
||||
graphics.render.opts.paint=random
|
||||
graphics.render.opts.alphacolor=Off
|
||||
graphics.render.opts.antialias=Off
|
||||
graphics.render.opts.stroke=width1
|
||||
graphics.render.tests.drawLine=disabled
|
||||
graphics.render.tests.drawLineHoriz=disabled
|
||||
graphics.render.tests.drawLineVert=disabled
|
||||
graphics.render.tests.fillRect=disabled
|
||||
graphics.render.tests.drawRect=disabled
|
||||
graphics.render.tests.fillOval=disabled
|
||||
graphics.render.tests.drawOval=disabled
|
||||
graphics.render.tests.fillPoly=disabled
|
||||
graphics.render.tests.drawPoly=enabled
|
||||
graphics.render.tests.shape.fillCubic=disabled
|
||||
graphics.render.tests.shape.drawCubic=disabled
|
||||
graphics.render.tests.shape.fillEllipse2D=disabled
|
||||
graphics.render.tests.shape.drawEllipse2D=disabled
|
||||
graphics.imaging.src.offscr.opaque=disabled
|
||||
graphics.imaging.src.offscr.bitmask=disabled
|
||||
graphics.imaging.src.offscr.translucent=disabled
|
||||
graphics.imaging.src.opqcompatimg.opaque=disabled
|
||||
graphics.imaging.src.opqcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.opqcompatimg.translucent=disabled
|
||||
graphics.imaging.src.bmcompatimg.opaque=disabled
|
||||
graphics.imaging.src.bmcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.bmcompatimg.translucent=disabled
|
||||
graphics.imaging.src.transcompatimg.opaque=disabled
|
||||
graphics.imaging.src.transcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.transcompatimg.translucent=disabled
|
||||
graphics.imaging.src.opqvolimg.opaque=disabled
|
||||
graphics.imaging.src.opqvolimg.bitmask=disabled
|
||||
graphics.imaging.src.opqvolimg.translucent=disabled
|
||||
graphics.imaging.src.bmvolimg.opaque=disabled
|
||||
graphics.imaging.src.bmvolimg.bitmask=disabled
|
||||
graphics.imaging.src.bmvolimg.translucent=disabled
|
||||
graphics.imaging.src.transvolimg.opaque=disabled
|
||||
graphics.imaging.src.transvolimg.bitmask=disabled
|
||||
graphics.imaging.src.transvolimg.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.translucent=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.translucent=disabled
|
||||
graphics.imaging.benchmarks.opts.interpolation=Nearest neighbor
|
||||
graphics.imaging.benchmarks.opts.touchsrc=Off
|
||||
graphics.imaging.benchmarks.tests.drawimage=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagebg=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaleup=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaledown=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescalesplit=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagetxform=disabled
|
||||
graphics.imaging.imageops.opts.op=convolve3x3zero
|
||||
graphics.imaging.imageops.tests.graphics2d.drawimageop=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filtercached=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filtercached=disabled
|
||||
graphics.misc.copytests.copyAreaVert=disabled
|
||||
graphics.misc.copytests.copyAreaHoriz=disabled
|
||||
graphics.misc.copytests.copyAreaDiag=disabled
|
||||
pixel.opts.renderto=Off
|
||||
pixel.opts.renderfrom=Off
|
||||
pixel.src.1BitBinary=disabled
|
||||
pixel.src.2BitBinary=disabled
|
||||
pixel.src.4BitBinary=disabled
|
||||
pixel.src.ByteIndexed=disabled
|
||||
pixel.src.ByteGray=disabled
|
||||
pixel.src.Short555=disabled
|
||||
pixel.src.Short565=disabled
|
||||
pixel.src.ShortGray=disabled
|
||||
pixel.src.3ByteBgr=disabled
|
||||
pixel.src.4ByteAbgr=disabled
|
||||
pixel.src.IntXrgb=disabled
|
||||
pixel.src.IntXbgr=disabled
|
||||
pixel.src.IntArgb=disabled
|
||||
pixel.bimgtests.getrgb=disabled
|
||||
pixel.bimgtests.setrgb=disabled
|
||||
pixel.rastests.getdataelem=disabled
|
||||
pixel.rastests.setdataelem=disabled
|
||||
pixel.rastests.getpixel=disabled
|
||||
pixel.rastests.setpixel=disabled
|
||||
pixel.dbtests.getelem=disabled
|
||||
pixel.dbtests.setelem=disabled
|
||||
text.opts.data.tlength=16
|
||||
text.opts.data.tscript=english
|
||||
text.opts.font.fname=serif,physical
|
||||
text.opts.font.fstyle=0
|
||||
text.opts.font.fsize=13.0
|
||||
text.opts.font.ftx=Identity
|
||||
text.opts.graphics.textaa=Off
|
||||
text.opts.graphics.tfm=Off
|
||||
text.opts.graphics.gaa=Off
|
||||
text.opts.graphics.gtx=Identity
|
||||
text.opts.advopts.gvstyle=0
|
||||
text.opts.advopts.tlruns=1
|
||||
text.opts.advopts.maptype=FONT
|
||||
text.Rendering.tests.drawString=disabled
|
||||
text.Rendering.tests.drawChars=disabled
|
||||
text.Rendering.tests.drawBytes=disabled
|
||||
text.Rendering.tests.drawGlyphVectors=disabled
|
||||
text.Rendering.tests.drawTextLayout=disabled
|
||||
text.Measuring.tests.stringWidth=disabled
|
||||
text.Measuring.tests.stringBounds=disabled
|
||||
text.Measuring.tests.charsWidth=disabled
|
||||
text.Measuring.tests.charsBounds=disabled
|
||||
text.Measuring.tests.fontcandisplay=disabled
|
||||
text.Measuring.tests.gvWidth=disabled
|
||||
text.Measuring.tests.gvLogicalBounds=disabled
|
||||
text.Measuring.tests.gvVisualBounds=disabled
|
||||
text.Measuring.tests.gvPixelBounds=disabled
|
||||
text.Measuring.tests.gvOutline=disabled
|
||||
text.Measuring.tests.gvGlyphLogicalBounds=disabled
|
||||
text.Measuring.tests.gvGlyphVisualBounds=disabled
|
||||
text.Measuring.tests.gvGlyphPixelBounds=disabled
|
||||
text.Measuring.tests.gvGlyphOutline=disabled
|
||||
text.Measuring.tests.gvGlyphTransform=disabled
|
||||
text.Measuring.tests.gvGlyphMetrics=disabled
|
||||
text.Measuring.tests.tlAdvance=disabled
|
||||
text.Measuring.tests.tlAscent=disabled
|
||||
text.Measuring.tests.tlBounds=disabled
|
||||
text.Measuring.tests.tlGetCaretInfo=disabled
|
||||
text.Measuring.tests.tlGetNextHit=disabled
|
||||
text.Measuring.tests.tlGetCaretShape=disabled
|
||||
text.Measuring.tests.tlGetLogicalHighlightShape=disabled
|
||||
text.Measuring.tests.tlHitTest=disabled
|
||||
text.Measuring.tests.tlOutline=disabled
|
||||
text.construction.tests.gvfromfontstring=disabled
|
||||
text.construction.tests.gvfromfontchars=disabled
|
||||
text.construction.tests.gvfromfontci=disabled
|
||||
text.construction.tests.gvfromfontglyphs=disabled
|
||||
text.construction.tests.gvfromfontlayout=disabled
|
||||
text.construction.tests.tlfromfont=disabled
|
||||
text.construction.tests.tlfrommap=disabled
|
||||
imageio.opts.size=250
|
||||
imageio.opts.content=photo
|
||||
imageio.input.opts.general.source.file=disabled
|
||||
imageio.input.opts.general.source.url=disabled
|
||||
imageio.input.opts.general.source.byteArray=disabled
|
||||
imageio.input.opts.imageio.useCache=Off
|
||||
imageio.input.image.toolkit.opts.format=
|
||||
imageio.input.image.toolkit.tests.createImage=disabled
|
||||
imageio.input.image.imageio.opts.format=
|
||||
imageio.input.image.imageio.tests.imageioRead=disabled
|
||||
imageio.input.image.imageio.reader.opts.seekForwardOnly=On
|
||||
imageio.input.image.imageio.reader.opts.ignoreMetadata=On
|
||||
imageio.input.image.imageio.reader.opts.installListener=Off
|
||||
imageio.input.image.imageio.reader.tests.read=disabled
|
||||
imageio.input.image.imageio.reader.tests.getImageMetadata=disabled
|
||||
imageio.input.stream.tests.construct=disabled
|
||||
imageio.input.stream.tests.read=disabled
|
||||
imageio.input.stream.tests.readByteArray=disabled
|
||||
imageio.input.stream.tests.readFullyByteArray=disabled
|
||||
imageio.input.stream.tests.readBit=disabled
|
||||
imageio.input.stream.tests.readByte=disabled
|
||||
imageio.input.stream.tests.readUnsignedByte=disabled
|
||||
imageio.input.stream.tests.readShort=disabled
|
||||
imageio.input.stream.tests.readUnsignedShort=disabled
|
||||
imageio.input.stream.tests.readInt=disabled
|
||||
imageio.input.stream.tests.readUnsignedInt=disabled
|
||||
imageio.input.stream.tests.readFloat=disabled
|
||||
imageio.input.stream.tests.readLong=disabled
|
||||
imageio.input.stream.tests.readDouble=disabled
|
||||
imageio.input.stream.tests.skipBytes=disabled
|
||||
imageio.output.opts.general.dest.file=disabled
|
||||
imageio.output.opts.general.dest.byteArray=disabled
|
||||
imageio.output.opts.imageio.useCache=Off
|
||||
imageio.output.image.imageio.opts.format=
|
||||
imageio.output.image.imageio.tests.imageioWrite=disabled
|
||||
imageio.output.image.imageio.writer.opts.installListener=Off
|
||||
imageio.output.image.imageio.writer.tests.write=disabled
|
||||
imageio.output.stream.tests.construct=disabled
|
||||
imageio.output.stream.tests.write=disabled
|
||||
imageio.output.stream.tests.writeByteArray=disabled
|
||||
imageio.output.stream.tests.writeBit=disabled
|
||||
imageio.output.stream.tests.writeByte=disabled
|
||||
imageio.output.stream.tests.writeShort=disabled
|
||||
imageio.output.stream.tests.writeInt=disabled
|
||||
imageio.output.stream.tests.writeFloat=disabled
|
||||
imageio.output.stream.tests.writeLong=disabled
|
||||
imageio.output.stream.tests.writeDouble=disabled
|
||||
cmm.opts.profiles=1001
|
||||
cmm.colorconv.data.fromRGB=disabled
|
||||
cmm.colorconv.data.toRGB=disabled
|
||||
cmm.colorconv.data.fromCIEXYZ=disabled
|
||||
cmm.colorconv.data.toCIEXYZ=disabled
|
||||
cmm.colorconv.ccop.ccopOptions.size=250
|
||||
cmm.colorconv.ccop.ccopOptions.content=photo
|
||||
cmm.colorconv.ccop.ccopOptions.srcType=INT_RGB
|
||||
cmm.colorconv.ccop.ccopOptions.dstType=INT_RGB
|
||||
cmm.colorconv.ccop.op_img=disabled
|
||||
cmm.colorconv.ccop.op_rst=disabled
|
||||
cmm.colorconv.ccop.op_draw=disabled
|
||||
cmm.colorconv.embed.embedOptions.Images=512x512
|
||||
cmm.colorconv.embed.embd_img_read=disabled
|
||||
cmm.profiles.getHeader=disabled
|
||||
cmm.profiles.getNumComponents=disabled
|
||||
267
jb/project/tools/perf/j2dbopts_poly250.txt
Normal file
267
jb/project/tools/perf/j2dbopts_poly250.txt
Normal file
@@ -0,0 +1,267 @@
|
||||
prog.verbose=disabled
|
||||
prog.printresults=enabled
|
||||
global.env.outputwidth=640
|
||||
global.env.outputheight=480
|
||||
global.env.runcount=5
|
||||
global.env.repcount=0
|
||||
global.env.testtime=2500
|
||||
global.results.workunits=units
|
||||
global.results.timeunits=sec
|
||||
global.results.ratio=unitspersec
|
||||
global.dest.offscreen=disabled
|
||||
global.dest.frame.defaultframe=enabled
|
||||
global.dest.frame.transframe=disabled
|
||||
global.dest.frame.shapedframe=disabled
|
||||
global.dest.frame.shapedtransframe=disabled
|
||||
global.dest.compatimg.compatimg=disabled
|
||||
global.dest.compatimg.opqcompatimg=disabled
|
||||
global.dest.compatimg.bmcompatimg=disabled
|
||||
global.dest.compatimg.transcompatimg=disabled
|
||||
global.dest.volimg.volimg=disabled
|
||||
global.dest.volimg.opqvolimg=disabled
|
||||
global.dest.volimg.bmvolimg=disabled
|
||||
global.dest.volimg.transvolimg=disabled
|
||||
global.dest.bufimg.IntXrgb=disabled
|
||||
global.dest.bufimg.IntArgb=disabled
|
||||
global.dest.bufimg.IntArgbPre=disabled
|
||||
global.dest.bufimg.3ByteBgr=disabled
|
||||
global.dest.bufimg.ByteIndexed=disabled
|
||||
global.dest.bufimg.ByteGray=disabled
|
||||
global.dest.bufimg.4ByteAbgr=disabled
|
||||
global.dest.bufimg.4ByteAbgrPre=disabled
|
||||
global.dest.bufimg.custom=disabled
|
||||
graphics.opts.anim=2
|
||||
graphics.opts.sizes=250
|
||||
graphics.opts.alpharule=SrcOver
|
||||
graphics.opts.transform=ident
|
||||
graphics.opts.extraalpha=Off
|
||||
graphics.opts.xormode=Off
|
||||
graphics.opts.clip=Off
|
||||
graphics.opts.renderhint=Default
|
||||
graphics.render.opts.paint=single
|
||||
graphics.render.opts.alphacolor=Off
|
||||
graphics.render.opts.antialias=Off
|
||||
graphics.render.opts.stroke=width1
|
||||
graphics.render.tests.drawLine=disabled
|
||||
graphics.render.tests.drawLineHoriz=disabled
|
||||
graphics.render.tests.drawLineVert=disabled
|
||||
graphics.render.tests.fillRect=disabled
|
||||
graphics.render.tests.drawRect=disabled
|
||||
graphics.render.tests.fillOval=disabled
|
||||
graphics.render.tests.drawOval=disabled
|
||||
graphics.render.tests.fillPoly=disabled
|
||||
graphics.render.tests.drawPoly=enabled
|
||||
graphics.render.tests.shape.fillCubic=disabled
|
||||
graphics.render.tests.shape.drawCubic=disabled
|
||||
graphics.render.tests.shape.fillEllipse2D=disabled
|
||||
graphics.render.tests.shape.drawEllipse2D=disabled
|
||||
graphics.imaging.src.offscr.opaque=disabled
|
||||
graphics.imaging.src.offscr.bitmask=disabled
|
||||
graphics.imaging.src.offscr.translucent=disabled
|
||||
graphics.imaging.src.opqcompatimg.opaque=disabled
|
||||
graphics.imaging.src.opqcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.opqcompatimg.translucent=disabled
|
||||
graphics.imaging.src.bmcompatimg.opaque=disabled
|
||||
graphics.imaging.src.bmcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.bmcompatimg.translucent=disabled
|
||||
graphics.imaging.src.transcompatimg.opaque=disabled
|
||||
graphics.imaging.src.transcompatimg.bitmask=disabled
|
||||
graphics.imaging.src.transcompatimg.translucent=disabled
|
||||
graphics.imaging.src.opqvolimg.opaque=disabled
|
||||
graphics.imaging.src.opqvolimg.bitmask=disabled
|
||||
graphics.imaging.src.opqvolimg.translucent=disabled
|
||||
graphics.imaging.src.bmvolimg.opaque=disabled
|
||||
graphics.imaging.src.bmvolimg.bitmask=disabled
|
||||
graphics.imaging.src.bmvolimg.translucent=disabled
|
||||
graphics.imaging.src.transvolimg.opaque=disabled
|
||||
graphics.imaging.src.transvolimg.bitmask=disabled
|
||||
graphics.imaging.src.transvolimg.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.IntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteGray.translucent=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.3ByteBgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgr.translucent=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.4ByteAbgrPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.opaque=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.ByteIndexedBm.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntXrgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgb.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanagedIntArgbPre.translucent=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.opaque=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.bitmask=disabled
|
||||
graphics.imaging.src.bufimg.unmanaged3ByteBgr.translucent=disabled
|
||||
graphics.imaging.benchmarks.opts.interpolation=Nearest neighbor
|
||||
graphics.imaging.benchmarks.opts.touchsrc=Off
|
||||
graphics.imaging.benchmarks.tests.drawimage=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagebg=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaleup=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescaledown=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagescalesplit=disabled
|
||||
graphics.imaging.benchmarks.tests.drawimagetxform=disabled
|
||||
graphics.imaging.imageops.opts.op=convolve3x3zero
|
||||
graphics.imaging.imageops.tests.graphics2d.drawimageop=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.bufimgop.filtercached=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filternull=disabled
|
||||
graphics.imaging.imageops.tests.rasterop.filtercached=disabled
|
||||
graphics.misc.copytests.copyAreaVert=disabled
|
||||
graphics.misc.copytests.copyAreaHoriz=disabled
|
||||
graphics.misc.copytests.copyAreaDiag=disabled
|
||||
pixel.opts.renderto=Off
|
||||
pixel.opts.renderfrom=Off
|
||||
pixel.src.1BitBinary=disabled
|
||||
pixel.src.2BitBinary=disabled
|
||||
pixel.src.4BitBinary=disabled
|
||||
pixel.src.ByteIndexed=disabled
|
||||
pixel.src.ByteGray=disabled
|
||||
pixel.src.Short555=disabled
|
||||
pixel.src.Short565=disabled
|
||||
pixel.src.ShortGray=disabled
|
||||
pixel.src.3ByteBgr=disabled
|
||||
pixel.src.4ByteAbgr=disabled
|
||||
pixel.src.IntXrgb=disabled
|
||||
pixel.src.IntXbgr=disabled
|
||||
pixel.src.IntArgb=disabled
|
||||
pixel.bimgtests.getrgb=disabled
|
||||
pixel.bimgtests.setrgb=disabled
|
||||
pixel.rastests.getdataelem=disabled
|
||||
pixel.rastests.setdataelem=disabled
|
||||
pixel.rastests.getpixel=disabled
|
||||
pixel.rastests.setpixel=disabled
|
||||
pixel.dbtests.getelem=disabled
|
||||
pixel.dbtests.setelem=disabled
|
||||
text.opts.data.tlength=16
|
||||
text.opts.data.tscript=english
|
||||
text.opts.font.fname=serif,physical
|
||||
text.opts.font.fstyle=0
|
||||
text.opts.font.fsize=13.0
|
||||
text.opts.font.ftx=Identity
|
||||
text.opts.graphics.textaa=Off
|
||||
text.opts.graphics.tfm=Off
|
||||
text.opts.graphics.gaa=Off
|
||||
text.opts.graphics.gtx=Identity
|
||||
text.opts.advopts.gvstyle=0
|
||||
text.opts.advopts.tlruns=1
|
||||
text.opts.advopts.maptype=FONT
|
||||
text.Rendering.tests.drawString=disabled
|
||||
text.Rendering.tests.drawChars=disabled
|
||||
text.Rendering.tests.drawBytes=disabled
|
||||
text.Rendering.tests.drawGlyphVectors=disabled
|
||||
text.Rendering.tests.drawTextLayout=disabled
|
||||
text.Measuring.tests.stringWidth=disabled
|
||||
text.Measuring.tests.stringBounds=disabled
|
||||
text.Measuring.tests.charsWidth=disabled
|
||||
text.Measuring.tests.charsBounds=disabled
|
||||
text.Measuring.tests.fontcandisplay=disabled
|
||||
text.Measuring.tests.gvWidth=disabled
|
||||
text.Measuring.tests.gvLogicalBounds=disabled
|
||||
text.Measuring.tests.gvVisualBounds=disabled
|
||||
text.Measuring.tests.gvPixelBounds=disabled
|
||||
text.Measuring.tests.gvOutline=disabled
|
||||
text.Measuring.tests.gvGlyphLogicalBounds=disabled
|
||||
text.Measuring.tests.gvGlyphVisualBounds=disabled
|
||||
text.Measuring.tests.gvGlyphPixelBounds=disabled
|
||||
text.Measuring.tests.gvGlyphOutline=disabled
|
||||
text.Measuring.tests.gvGlyphTransform=disabled
|
||||
text.Measuring.tests.gvGlyphMetrics=disabled
|
||||
text.Measuring.tests.tlAdvance=disabled
|
||||
text.Measuring.tests.tlAscent=disabled
|
||||
text.Measuring.tests.tlBounds=disabled
|
||||
text.Measuring.tests.tlGetCaretInfo=disabled
|
||||
text.Measuring.tests.tlGetNextHit=disabled
|
||||
text.Measuring.tests.tlGetCaretShape=disabled
|
||||
text.Measuring.tests.tlGetLogicalHighlightShape=disabled
|
||||
text.Measuring.tests.tlHitTest=disabled
|
||||
text.Measuring.tests.tlOutline=disabled
|
||||
text.construction.tests.gvfromfontstring=disabled
|
||||
text.construction.tests.gvfromfontchars=disabled
|
||||
text.construction.tests.gvfromfontci=disabled
|
||||
text.construction.tests.gvfromfontglyphs=disabled
|
||||
text.construction.tests.gvfromfontlayout=disabled
|
||||
text.construction.tests.tlfromfont=disabled
|
||||
text.construction.tests.tlfrommap=disabled
|
||||
imageio.opts.size=250
|
||||
imageio.opts.content=photo
|
||||
imageio.input.opts.general.source.file=disabled
|
||||
imageio.input.opts.general.source.url=disabled
|
||||
imageio.input.opts.general.source.byteArray=disabled
|
||||
imageio.input.opts.imageio.useCache=Off
|
||||
imageio.input.image.toolkit.opts.format=
|
||||
imageio.input.image.toolkit.tests.createImage=disabled
|
||||
imageio.input.image.imageio.opts.format=
|
||||
imageio.input.image.imageio.tests.imageioRead=disabled
|
||||
imageio.input.image.imageio.reader.opts.seekForwardOnly=On
|
||||
imageio.input.image.imageio.reader.opts.ignoreMetadata=On
|
||||
imageio.input.image.imageio.reader.opts.installListener=Off
|
||||
imageio.input.image.imageio.reader.tests.read=disabled
|
||||
imageio.input.image.imageio.reader.tests.getImageMetadata=disabled
|
||||
imageio.input.stream.tests.construct=disabled
|
||||
imageio.input.stream.tests.read=disabled
|
||||
imageio.input.stream.tests.readByteArray=disabled
|
||||
imageio.input.stream.tests.readFullyByteArray=disabled
|
||||
imageio.input.stream.tests.readBit=disabled
|
||||
imageio.input.stream.tests.readByte=disabled
|
||||
imageio.input.stream.tests.readUnsignedByte=disabled
|
||||
imageio.input.stream.tests.readShort=disabled
|
||||
imageio.input.stream.tests.readUnsignedShort=disabled
|
||||
imageio.input.stream.tests.readInt=disabled
|
||||
imageio.input.stream.tests.readUnsignedInt=disabled
|
||||
imageio.input.stream.tests.readFloat=disabled
|
||||
imageio.input.stream.tests.readLong=disabled
|
||||
imageio.input.stream.tests.readDouble=disabled
|
||||
imageio.input.stream.tests.skipBytes=disabled
|
||||
imageio.output.opts.general.dest.file=disabled
|
||||
imageio.output.opts.general.dest.byteArray=disabled
|
||||
imageio.output.opts.imageio.useCache=Off
|
||||
imageio.output.image.imageio.opts.format=
|
||||
imageio.output.image.imageio.tests.imageioWrite=disabled
|
||||
imageio.output.image.imageio.writer.opts.installListener=Off
|
||||
imageio.output.image.imageio.writer.tests.write=disabled
|
||||
imageio.output.stream.tests.construct=disabled
|
||||
imageio.output.stream.tests.write=disabled
|
||||
imageio.output.stream.tests.writeByteArray=disabled
|
||||
imageio.output.stream.tests.writeBit=disabled
|
||||
imageio.output.stream.tests.writeByte=disabled
|
||||
imageio.output.stream.tests.writeShort=disabled
|
||||
imageio.output.stream.tests.writeInt=disabled
|
||||
imageio.output.stream.tests.writeFloat=disabled
|
||||
imageio.output.stream.tests.writeLong=disabled
|
||||
imageio.output.stream.tests.writeDouble=disabled
|
||||
cmm.opts.profiles=1001
|
||||
cmm.colorconv.data.fromRGB=disabled
|
||||
cmm.colorconv.data.toRGB=disabled
|
||||
cmm.colorconv.data.fromCIEXYZ=disabled
|
||||
cmm.colorconv.data.toCIEXYZ=disabled
|
||||
cmm.colorconv.ccop.ccopOptions.size=250
|
||||
cmm.colorconv.ccop.ccopOptions.content=photo
|
||||
cmm.colorconv.ccop.ccopOptions.srcType=INT_RGB
|
||||
cmm.colorconv.ccop.ccopOptions.dstType=INT_RGB
|
||||
cmm.colorconv.ccop.op_img=disabled
|
||||
cmm.colorconv.ccop.op_rst=disabled
|
||||
cmm.colorconv.ccop.op_draw=disabled
|
||||
cmm.colorconv.embed.embedOptions.Images=512x512
|
||||
cmm.colorconv.embed.embd_img_read=disabled
|
||||
cmm.profiles.getHeader=disabled
|
||||
cmm.profiles.getNumComponents=disabled
|
||||
137
jb/project/tools/perf/run_inc.sh
Normal file
137
jb/project/tools/perf/run_inc.sh
Normal file
@@ -0,0 +1,137 @@
|
||||
export LC_ALL=C
|
||||
ST=1 # sleep between iterations
|
||||
|
||||
# number of iterations (jvm spawned)
|
||||
N=5
|
||||
# number of repeats (within jvm)
|
||||
R=3
|
||||
|
||||
type datamash 2>&1 > /dev/null ; ec=$?
|
||||
if [ $ec -ne 0 ] ; then
|
||||
echo "Missing datamash utility"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
DATAMASH_CMD="datamash --format=%.2f -H count x min x q1 x median x q3 x max x mad x"
|
||||
|
||||
J2D_OPTS=""
|
||||
OS=""
|
||||
case "$OSTYPE" in
|
||||
linux*) echo "Linux"
|
||||
;;
|
||||
darwin*) echo "OSX"
|
||||
;;
|
||||
*) echo "unknown: $OSTYPE"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
read -r -d '' RENDER_OPS_DOC << EOM
|
||||
rendering_options:
|
||||
-opengl # OpenGL pipeline (windows, linux, macOS)
|
||||
-metal # Metal pipeline (macOS)
|
||||
-vulkan # Vulkan pipeline (WLToolkit)
|
||||
-accelsd # Vulkan full acceleration (WLToolkit, Vulkan)
|
||||
-devnum num # Provide Vulkan device for rendering
|
||||
-tk tk_name # AWT toolkit (linux: WLToolkit|XToolkit)
|
||||
-scale # UI scale
|
||||
-N num # Number of iterations (JVM runs)
|
||||
-R num # Number of repeats in the test
|
||||
EOM
|
||||
|
||||
while [ $# -ge 1 ] ; do
|
||||
case "$1" in
|
||||
-opengl) J2D_OPTS=$J2D_OPTS" -Dsun.java2d.opengl=true"
|
||||
shift
|
||||
;;
|
||||
-metal) J2D_OPTS=$J2D_OPTS" -Dsun.java2d.metal=true"
|
||||
shift
|
||||
;;
|
||||
-vulkan) J2D_OPTS=$J2D_OPTS" -Dsun.java2d.vulkan=true"
|
||||
shift
|
||||
;;
|
||||
-accelsd) J2D_OPTS=$J2D_OPTS" -Dsun.java2d.vulkan.accelsd=true"
|
||||
shift
|
||||
;;
|
||||
-devnum) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
J2D_OPTS=$J2D_OPTS" -Dsun.java2d.vulkan.deviceNumber="$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -devnum option. Use: -devnum num"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-tk) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
J2D_OPTS=$J2D_OPTS" -Dawt.toolkit.name="$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -tk option. Use: -tk tkname"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-N) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
N=$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -N option. Use: -N <number>"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-R) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
R=$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -R option. Use: -R <number>"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-scale) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
J2D_OPTS=$J2D_OPTS" -Dsun.java2d.uiScale="$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -scale option. Use: -scale scale"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-dSync) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
J2D_OPTS=$J2D_OPTS" -Dsun.java2d.metal.displaySync="$1
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -dSync option. Use: -dSync [true|false]"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
-jdk) shift
|
||||
if [ $# -ge 1 ] ; then
|
||||
JAVA=$1/bin/java
|
||||
shift
|
||||
else
|
||||
echo "Invalid parameters for -jdk option"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
*) break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [ -z "$JAVA" ] ; then
|
||||
BUILD_DIR=`find $BASE_DIR/../../../../build -name '*-release' -type d | head -n 1`
|
||||
JAVA=`find $BUILD_DIR/images/jdk -name java -type f | head -n 1`
|
||||
fi
|
||||
|
||||
JAVA_HOME=`dirname $JAVA`/../
|
||||
"$JAVA" -version
|
||||
|
||||
LANG=C
|
||||
|
||||
WS_ROOT=$BASE_DIR/../../../..
|
||||
|
||||
echo "N: $N"
|
||||
echo "R: $R"
|
||||
echo "J2D_OPTS: $J2D_OPTS"
|
||||
53
jb/project/tools/perf/run_j2b.sh
Executable file
53
jb/project/tools/perf/run_j2b.sh
Executable file
@@ -0,0 +1,53 @@
|
||||
#!/bin/bash
|
||||
|
||||
BASE_DIR=$(dirname "$0")
|
||||
source $BASE_DIR/run_inc.sh
|
||||
|
||||
J2DBENCH_DIR=$WS_ROOT/src/demo/share/java2d/J2DBench
|
||||
|
||||
if [ -z "$J2DBENCH" ]; then
|
||||
if [ ! -f "$J2DBENCH_DIR/dist/J2DBench.jar" ]; then
|
||||
PATH=$JAVA_HOME/bin:$PATH make -C $J2DBENCH_DIR
|
||||
fi
|
||||
if [ ! -f "$J2DBENCH_DIR/dist/J2DBench.jar" ]; then
|
||||
echo "Cannot build J2DBench. You may use J2DBench env variable instead pointing to the J2DBench.jar."
|
||||
exit 1
|
||||
fi
|
||||
J2DBENCH=$J2DBENCH_DIR/dist/J2DBench.jar
|
||||
fi
|
||||
|
||||
if [ $# -ne 1 ] ; then
|
||||
echo "Usage: run_j2b.sh [rendering_options] bench_name"
|
||||
echo
|
||||
echo "bench_name: poly250 poly250-rand_col poly250-AA-rand_col"
|
||||
echo ""
|
||||
echo "$RENDER_OPS_DOC"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
if [ ! -f "$BASE_DIR/j2dbopts_$1.txt" ]; then
|
||||
echo "Unknown test: $1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
|
||||
OPTS="j2dbopts_$1.txt"
|
||||
#OPTS=j2dbopts_poly250.txt
|
||||
#OPTS=j2dbopts_poly250-rand_col.txt
|
||||
#OPTS=j2dbopts_poly250-AA-rand_col.txt
|
||||
|
||||
echo "OPTS: $OPTS"
|
||||
|
||||
for i in `seq $N`; do
|
||||
if [ $i -eq 1 ]; then
|
||||
echo x
|
||||
fi
|
||||
echo `$JAVA $J2D_OPTS -jar $J2DBENCH \
|
||||
-batch -loadopts $BASE_DIR/$OPTS -saveres pl.res \
|
||||
-title pl -desc pl | awk '/averaged/{print $3}' | head -n1`
|
||||
|
||||
if [ $i -ne $N ]; then
|
||||
sleep $ST
|
||||
fi
|
||||
done | $DATAMASH_CMD | expand -t12
|
||||
88
jb/project/tools/perf/run_rp.sh
Executable file
88
jb/project/tools/perf/run_rp.sh
Executable file
@@ -0,0 +1,88 @@
|
||||
#!/bin/bash
|
||||
|
||||
#set -euo pipefail
|
||||
#set -x
|
||||
|
||||
BASE_DIR=$(dirname "$0")
|
||||
source $BASE_DIR/run_inc.sh
|
||||
|
||||
RENDERPERFTEST_DIR=$WS_ROOT/test/jdk/performance/client/RenderPerfTest
|
||||
RENDERPERFTEST=""
|
||||
if [ -z "$RENDERPERFTEST" ]; then
|
||||
if [ ! -f "$RENDERPERFTEST_DIR/dist/RenderPerfTest.jar" ]; then
|
||||
PATH=$JAVA_HOME/bin:$PATH make -C $RENDERPERFTEST_DIR
|
||||
fi
|
||||
if [ ! -f "$RENDERPERFTEST_DIR/dist/RenderPerfTest.jar" ]; then
|
||||
echo "Cannot build RenderPerfTest. You may use RENDERPERFTEST env variable instead pointing to the RenderPerfTest.jar."
|
||||
exit 1
|
||||
fi
|
||||
RENDERPERFTEST=$RENDERPERFTEST_DIR/dist/RenderPerfTest.jar
|
||||
fi
|
||||
|
||||
TRACE=false
|
||||
|
||||
# removes leading hyphen
|
||||
mode_param="${1/-}"
|
||||
MODE="Robot"
|
||||
while [ $# -ge 1 ] ; do
|
||||
case "$1" in
|
||||
-onscreen) MODE="Robot"
|
||||
shift
|
||||
;;
|
||||
-volatile) MODE="Volatile"
|
||||
shift
|
||||
;;
|
||||
-buffer) MODE="Buffer"
|
||||
shift
|
||||
;;
|
||||
*) break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [[ ($# -eq 1 && "$1" == "-help") || ($# -eq 0) ]] ; then
|
||||
echo "Usage: run_rp.sh [rp_rendering_mode] [rendering_options] bench_name"
|
||||
echo
|
||||
echo "bench_name: ArgbSurfaceBlitImage ArgbSwBlitImage BgrSurfaceBlitImage BgrSwBlitImage"
|
||||
echo " Image ImageAA Image_XOR VolImage VolImageAA"
|
||||
echo " ClipFlatBox ClipFlatBoxAA ClipFlatOval ClipFlatOvalAA"
|
||||
echo " FlatBox FlatBoxAA FlatOval FlatOvalAA FlatOval_XOR FlatQuad FlatQuadAA"
|
||||
echo " RotatedBox RotatedBoxAA RotatedBox_XOR RotatedOval RotatedOvalAA"
|
||||
echo " WiredBox WiredBoxAA WiredBubbles WiredBubblesAA WiredQuad WiredQuadAA"
|
||||
echo " Lines LinesAA Lines_XOR"
|
||||
echo " TextGray TextLCD TextLCD_XOR TextNoAA TextNoAA_XOR"
|
||||
echo " LargeTextGray LargeTextLCD LargeTextNoAA WhiteTextGray WhiteTextLCD WhiteTextNoAA"
|
||||
echo " LinGrad3RotatedOval LinGrad3RotatedOvalAA LinGradRotatedOval LinGradRotatedOvalAA"
|
||||
echo " RadGrad3RotatedOval RadGrad3RotatedOvalAA"
|
||||
echo ""
|
||||
echo "rp_rendering_mode: "
|
||||
echo " -onscreen : rendering to the window and check it using Robot"
|
||||
echo " -volatile : rendering to volatile image (default)"
|
||||
echo " -buffer : rendering to buffered image"
|
||||
echo "$RENDER_OPS_DOC"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
OPTS=""
|
||||
# use time + repeat
|
||||
OPTS="$OPTS -t -n=$N -e$MODE $1"
|
||||
|
||||
echo "OPTS: $OPTS"
|
||||
|
||||
echo "Unit: Milliseconds (not FPS), lower is better"
|
||||
for i in `seq $R` ; do
|
||||
if [ $i -eq 1 ]; then
|
||||
echo x
|
||||
fi
|
||||
|
||||
# echo "[debug] " + "test run"
|
||||
# $JAVA $J2D_OPTS -DTRACE=$TRACE \
|
||||
# -jar $RENDERPERFTEST $OPTS 2>&1 | awk '/'$1'/{print $3 }' | tee test_run.log
|
||||
|
||||
$JAVA $J2D_OPTS -DTRACE=$TRACE \
|
||||
-jar $RENDERPERFTEST $OPTS -v 2>&1 | tee render_$1_${mode_param}_$i.log | grep -v "^#" | tail -n 1 | \
|
||||
awk '{print $3 }'
|
||||
if [ $i -ne $N ]; then
|
||||
sleep $ST
|
||||
fi
|
||||
done | $DATAMASH_CMD | expand -t12 | tee render_$1_${mode_param}.log
|
||||
39
jb/project/tools/perf/run_sm.sh
Executable file
39
jb/project/tools/perf/run_sm.sh
Executable file
@@ -0,0 +1,39 @@
|
||||
#!/bin/bash
|
||||
|
||||
BASE_DIR=$(dirname "$0")
|
||||
source $BASE_DIR/run_inc.sh
|
||||
|
||||
SWINGMARK_DIR=$WS_ROOT/test/jdk/performance/client/SwingMark
|
||||
|
||||
if [ -z "$SWINGMARK" ]; then
|
||||
if [ ! -f "$SWINGMARK_DIR/dist/SwingMark.jar" ]; then
|
||||
PATH=$JAVA_HOME/bin:$PATH make -C $SWINGMARK_DIR
|
||||
fi
|
||||
if [ ! -f "$SWINGMARK_DIR/dist/SwingMark.jar" ]; then
|
||||
echo "Cannot build SwingMark. You may use SWINGMARK env variable instead pointing to the SwingMark.jar."
|
||||
exit 1
|
||||
fi
|
||||
SWINGMARK=$SWINGMARK_DIR/dist/SwingMark.jar
|
||||
fi
|
||||
|
||||
if [ $# -eq 1 -a "$1" == "--help" ] ; then
|
||||
shift
|
||||
echo "Usage: run_sm [rendering_options]"
|
||||
echo ""
|
||||
echo "$RENDER_OPS_DOC"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for i in `seq $N` ; do
|
||||
if [ $i -eq 1 ]; then
|
||||
echo x
|
||||
fi
|
||||
|
||||
# SwingMark gives 1 global 'Score: <value>'
|
||||
echo `$JAVA $J2D_OPTS -jar $BASE_DIR/../../../../test/jdk/performance/client/SwingMark/dist/SwingMark.jar \
|
||||
-r $R -q -lf javax.swing.plaf.metal.MetalLookAndFeel | awk '/Score/{print $2}'`
|
||||
|
||||
if [ $i -ne $N ]; then
|
||||
sleep $ST
|
||||
fi
|
||||
done | $DATAMASH_CMD | expand -t12
|
||||
@@ -68,7 +68,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \
|
||||
-Duser.language=en -Duser.country=US \
|
||||
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
build.tools.classlist.HelloClasslist $(LOG_DEBUG)
|
||||
build.tools.classlist.HelloClasslist jdk/src/classes/build/tools/classlist/clear.classlist $(LOG_DEBUG)
|
||||
$(GREP) -v HelloClasslist $@.raw > $@.interim
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -Xshare:dump \
|
||||
-XX:SharedClassListFile=$@.interim -XX:SharedArchiveFile=$@.jsa \
|
||||
@@ -79,7 +79,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXECUTABLE_SUFFIX) $(CLASSLIST
|
||||
-Duser.language=en -Duser.country=US \
|
||||
--module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
build.tools.classlist.HelloClasslist \
|
||||
build.tools.classlist.HelloClasslist jdk/src/classes/build/tools/classlist/clear.classlist \
|
||||
2> $(LINK_OPT_DIR)/stderr > $(JLI_TRACE_FILE) \
|
||||
|| ( \
|
||||
exitcode=$$? ; \
|
||||
|
||||
114
make/autoconf/lib-vulkan.m4
Normal file
114
make/autoconf/lib-vulkan.m4
Normal file
@@ -0,0 +1,114 @@
|
||||
#
|
||||
# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2025, 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
|
||||
# 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.
|
||||
#
|
||||
|
||||
################################################################################
|
||||
# Setup vulkan
|
||||
################################################################################
|
||||
AC_DEFUN_ONCE([LIB_SETUP_VULKAN],
|
||||
[
|
||||
AC_ARG_WITH(vulkan, [AS_HELP_STRING([--with-vulkan],
|
||||
[specify whether we use vulkan])])
|
||||
AC_ARG_WITH(vulkan-include, [AS_HELP_STRING([--with-vulkan-include],
|
||||
[specify directory for the vulkan include files ({with-vulkan-include}/vulkan/vulkan.h)])])
|
||||
AC_ARG_WITH(vulkan-shader-compiler, [AS_HELP_STRING([--with-vulkan-shader-compiler],
|
||||
[specify which shader compiler to use: glslc/glslangValidator])])
|
||||
|
||||
VULKAN_ENABLED=false
|
||||
VULKAN_FLAGS=
|
||||
|
||||
# Find Vulkan SDK
|
||||
if test "x$NEEDS_LIB_VULKAN" = xtrue || test "x${with_vulkan}" = xyes || test "x${with_vulkan_include}" != x ; then
|
||||
|
||||
# Check custom directory
|
||||
if test "x${with_vulkan_include}" != x; then
|
||||
AC_MSG_CHECKING([for ${with_vulkan_include}/vulkan/vulkan.h])
|
||||
if test -s "${with_vulkan_include}/vulkan/vulkan.h"; then
|
||||
VULKAN_ENABLED=true
|
||||
VULKAN_FLAGS="-I${with_vulkan_include}"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find 'vulkan/vulkan.h' under '${with_vulkan_include}'])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check $VULKAN_SDK
|
||||
if test "x$VULKAN_ENABLED" = xfalse && test "x${VULKAN_SDK}" != x; then
|
||||
AC_MSG_CHECKING([for ${VULKAN_SDK}/include/vulkan/vulkan.h])
|
||||
if test -s "${VULKAN_SDK}/include/vulkan/vulkan.h"; then
|
||||
VULKAN_ENABLED=true
|
||||
VULKAN_FLAGS="-I${VULKAN_SDK}/include"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check default /usr/include location
|
||||
if test "x$VULKAN_ENABLED" = xfalse; then
|
||||
AC_CHECK_HEADERS([vulkan/vulkan.h],
|
||||
[ VULKAN_ENABLED=true ], [ break ]
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$VULKAN_ENABLED" = xfalse; then
|
||||
# Vulkan SDK not found
|
||||
HELP_MSG_MISSING_DEPENDENCY([vulkan])
|
||||
AC_MSG_ERROR([Could not find vulkan! $HELP_MSG ])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Find shader compiler - glslc or glslangValidator
|
||||
if test "x$VULKAN_ENABLED" = xtrue; then
|
||||
SHADER_COMPILER=
|
||||
|
||||
# Check glslc
|
||||
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslc); then
|
||||
UTIL_LOOKUP_PROGS(GLSLC, glslc)
|
||||
SHADER_COMPILER="$GLSLC"
|
||||
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num -o"
|
||||
fi
|
||||
|
||||
# Check glslangValidator
|
||||
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslangValidator) && \
|
||||
test "x$SHADER_COMPILER" = x; then
|
||||
UTIL_LOOKUP_PROGS(GLSLANG, glslangValidator)
|
||||
SHADER_COMPILER="$GLSLANG"
|
||||
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x -o"
|
||||
fi
|
||||
|
||||
if test "x$SHADER_COMPILER" = x; then
|
||||
# Compiler not found
|
||||
VULKAN_ENABLED=false
|
||||
VULKAN_FLAGS=
|
||||
AC_MSG_ERROR([Can't find vulkan shader compiler])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(VULKAN_ENABLED)
|
||||
AC_SUBST(VULKAN_FLAGS)
|
||||
AC_SUBST(VULKAN_SHADER_COMPILER)
|
||||
])
|
||||
@@ -45,8 +45,6 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
|
||||
fi
|
||||
WAYLAND_CFLAGS=
|
||||
WAYLAND_LIBS=
|
||||
VULKAN_FLAGS=
|
||||
VULKAN_ENABLED=false
|
||||
else
|
||||
WAYLAND_FOUND=no
|
||||
|
||||
@@ -79,7 +77,7 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
|
||||
if test "x${with_wayland_lib}" != x; then
|
||||
WAYLAND_LIBS="-L${with_wayland_lib} -lwayland-client -lwayland-cursor"
|
||||
fi
|
||||
|
||||
|
||||
if test "x$WAYLAND_FOUND" = xno; then
|
||||
# Are the wayland headers installed in the default /usr/include location?
|
||||
AC_CHECK_HEADERS([wayland-client.h wayland-cursor.h],
|
||||
@@ -97,98 +95,7 @@ AC_DEFUN_ONCE([LIB_SETUP_WAYLAND],
|
||||
AC_MSG_ERROR([Could not find wayland! $HELP_MSG ])
|
||||
fi
|
||||
|
||||
|
||||
# Checking for vulkan sdk
|
||||
|
||||
AC_ARG_WITH(vulkan, [AS_HELP_STRING([--with-vulkan],
|
||||
[specify whether we use vulkan])])
|
||||
|
||||
AC_ARG_WITH(vulkan-include, [AS_HELP_STRING([--with-vulkan-include],
|
||||
[specify directory for the vulkan include files ({with-vulkan-include}/vulkan/vulkan.h)])])
|
||||
|
||||
AC_ARG_WITH(vulkan-shader-compiler, [AS_HELP_STRING([--with-vulkan-shader-compiler],
|
||||
[specify which shader compiler to use: glslc/glslangValidator])])
|
||||
|
||||
if test "x$SUPPORTS_LIB_VULKAN" = xfalse; then
|
||||
|
||||
if (test "x${with_vulkan}" != x && test "x${with_vulkan}" != xno) || \
|
||||
(test "x${with_vulkan_include}" != x && test "x${with_vulkan_include}" != xno); then
|
||||
AC_MSG_WARN([[vulkan not used, so --with-vulkan-include is ignored]])
|
||||
fi
|
||||
VULKAN_FLAGS=
|
||||
VULKAN_ENABLED=false
|
||||
else
|
||||
# Do not build vulkan rendering pipeline by default
|
||||
if (test "x${with_vulkan}" = x && test "x${with_vulkan_include}" = x) || \
|
||||
test "x${with_vulkan}" = xno || test "x${with_vulkan_include}" = xno ; then
|
||||
VULKAN_FLAGS=
|
||||
VULKAN_ENABLED=false
|
||||
else
|
||||
VULKAN_FOUND=no
|
||||
|
||||
if test "x${with_vulkan_include}" != x; then
|
||||
AC_MSG_CHECKING([for ${with_vulkan_include}/vulkan/vulkan.h])
|
||||
if test -s "${with_vulkan_include}/vulkan/vulkan.h"; then
|
||||
VULKAN_FOUND=yes
|
||||
VULKAN_FLAGS="-DVK_USE_PLATFORM_WAYLAND_KHR -I${with_vulkan_include} -DVULKAN_ENABLED"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
AC_MSG_ERROR([Can't find 'vulkan/vulkan.h' under '${with_vulkan_include}'])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$VULKAN_FOUND" = xno && test "x${VULKAN_SDK}" != x; then
|
||||
AC_MSG_CHECKING([for ${VULKAN_SDK}/include/vulkan/vulkan.h])
|
||||
if test -s "${VULKAN_SDK}/include/vulkan/vulkan.h"; then
|
||||
VULKAN_FOUND=yes
|
||||
VULKAN_FLAGS="-DVK_USE_PLATFORM_WAYLAND_KHR -I${VULKAN_SDK}/include -DVULKAN_ENABLED"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$VULKAN_FOUND" = xno; then
|
||||
# Check default /usr/include location
|
||||
AC_CHECK_HEADERS([vulkan/vulkan.h],
|
||||
[ VULKAN_FOUND=yes
|
||||
VULKAN_FLAGS="-DVK_USE_PLATFORM_WAYLAND_KHR -DVULKAN_ENABLED"
|
||||
],
|
||||
[ VULKAN_FOUND=no; break ]
|
||||
)
|
||||
fi
|
||||
|
||||
if test "x$VULKAN_FOUND" = xno; then
|
||||
HELP_MSG_MISSING_DEPENDENCY([vulkan])
|
||||
AC_MSG_ERROR([Could not find vulkan! $HELP_MSG ])
|
||||
else
|
||||
# Find shader compiler - glslc or glslangValidator
|
||||
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslc); then
|
||||
UTIL_LOOKUP_PROGS(GLSLC, glslc)
|
||||
SHADER_COMPILER="$GLSLC"
|
||||
VULKAN_SHADER_COMPILER="glslc --target-env=vulkan1.2 -mfmt=num -o"
|
||||
fi
|
||||
|
||||
if (test "x${with_vulkan_shader_compiler}" = x || test "x${with_vulkan_shader_compiler}" = xglslangValidator) && \
|
||||
test "x$SHADER_COMPILER" = x; then
|
||||
UTIL_LOOKUP_PROGS(GLSLANG, glslangValidator)
|
||||
SHADER_COMPILER="$GLSLANG"
|
||||
VULKAN_SHADER_COMPILER="glslangValidator --target-env vulkan1.2 -x -o"
|
||||
fi
|
||||
|
||||
if test "x$SHADER_COMPILER" != x; then
|
||||
VULKAN_ENABLED=true
|
||||
else
|
||||
AC_MSG_ERROR([Can't find shader compiler])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(VULKAN_FLAGS)
|
||||
AC_SUBST(VULKAN_SHADER_COMPILER)
|
||||
AC_SUBST(VULKAN_ENABLED)
|
||||
AC_SUBST(WAYLAND_CFLAGS)
|
||||
AC_SUBST(WAYLAND_LIBS)
|
||||
])
|
||||
|
||||
@@ -35,8 +35,9 @@ m4_include([lib-std.m4])
|
||||
m4_include([lib-x11.m4])
|
||||
m4_include([lib-speechd.m4])
|
||||
m4_include([lib-nvdacontrollerclient.m4])
|
||||
m4_include([lib-wayland.m4])
|
||||
m4_include([lib-dbus.m4])
|
||||
m4_include([lib-vulkan.m4])
|
||||
m4_include([lib-wayland.m4])
|
||||
m4_include([lib-tests.m4])
|
||||
|
||||
################################################################################
|
||||
@@ -50,23 +51,23 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
|
||||
NEEDS_LIB_X11=false
|
||||
NEEDS_LIB_SPEECHD=false
|
||||
NEEDS_LIB_WAYLAND=false
|
||||
SUPPORTS_LIB_VULKAN=false
|
||||
elif test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
|
||||
# All other instances need X11, even if building headless only, libawt still
|
||||
# needs X11 headers.
|
||||
NEEDS_LIB_X11=true
|
||||
NEEDS_LIB_SPEECHD=false
|
||||
NEEDS_LIB_WAYLAND=false
|
||||
SUPPORTS_LIB_VULKAN=false
|
||||
else
|
||||
# All other instances need X11 and wayland, even if building headless only, libawt still
|
||||
# needs X11 headers.
|
||||
NEEDS_LIB_X11=true
|
||||
NEEDS_LIB_SPEECHD=true
|
||||
NEEDS_LIB_WAYLAND=true
|
||||
SUPPORTS_LIB_VULKAN=true
|
||||
fi
|
||||
|
||||
# Vulkan is not built by default
|
||||
NEEDS_LIB_VULKAN=false
|
||||
|
||||
# Check if fontconfig is needed
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
# No fontconfig support on windows or macosx
|
||||
@@ -153,6 +154,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
LIB_SETUP_X11
|
||||
LIB_SETUP_SPEECHD
|
||||
LIB_SETUP_NVDACONTROLLERCLIENT
|
||||
LIB_SETUP_VULKAN
|
||||
LIB_SETUP_WAYLAND
|
||||
LIB_SETUP_DBUS
|
||||
LIB_TESTS_SETUP_GTEST
|
||||
@@ -193,7 +195,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES],
|
||||
if test "x$OPENJDK_TARGET_OS" = xwindows; then
|
||||
BASIC_JVM_LIBS="$BASIC_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \
|
||||
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib powrprof.lib uuid.lib \
|
||||
ws2_32.lib winmm.lib version.lib psapi.lib"
|
||||
ws2_32.lib winmm.lib version.lib psapi.lib Synchronization.lib"
|
||||
fi
|
||||
LIB_SETUP_JVM_LIBS(BUILD)
|
||||
LIB_SETUP_JVM_LIBS(TARGET)
|
||||
|
||||
@@ -487,9 +487,9 @@ A11Y_JAWS_ANNOUNCING_ENABLED:=@A11Y_JAWS_ANNOUNCING_ENABLED@
|
||||
|
||||
WAYLAND_CFLAGS:=@WAYLAND_CFLAGS@
|
||||
WAYLAND_LIBS:=@WAYLAND_LIBS@
|
||||
VULKAN_ENABLED:=@VULKAN_ENABLED@
|
||||
VULKAN_FLAGS:=@VULKAN_FLAGS@
|
||||
VULKAN_SHADER_COMPILER:=@VULKAN_SHADER_COMPILER@
|
||||
VULKAN_ENABLED:=@VULKAN_ENABLED@
|
||||
|
||||
# The lowest required version of macosx
|
||||
MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@
|
||||
|
||||
@@ -36,6 +36,8 @@ import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@@ -153,6 +155,20 @@ public class HelloClasslist {
|
||||
// an inconsistency in the classlist between builds (see JDK-8295951).
|
||||
// To avoid the problem, load the class explicitly.
|
||||
Class<?> striped64Class = Class.forName("java.util.concurrent.atomic.Striped64$Cell");
|
||||
Files.lines(Path.of(args[0])).forEach(line -> {
|
||||
if (line.isEmpty() || line.charAt(0) == '#') {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
int index = line.indexOf(' ');
|
||||
if (index <= 0) {
|
||||
return;
|
||||
}
|
||||
String className = line.substring(0, index).replace('/', '.');
|
||||
Class.forName(className);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public HelloClasslist() {}
|
||||
|
||||
6756
make/jdk/src/classes/build/tools/classlist/clear.classlist
Normal file
6756
make/jdk/src/classes/build/tools/classlist/clear.classlist
Normal file
File diff suppressed because it is too large
Load Diff
@@ -73,7 +73,6 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
sun/awt/wl \
|
||||
sun/java2d/wl \
|
||||
sun/java2d/x11 \
|
||||
sun/java2d/vulkan \
|
||||
sun/java2d/jules \
|
||||
sun/java2d/xr \
|
||||
com/sun/java/swing/plaf/gtk \
|
||||
@@ -139,6 +138,13 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
EXCLUDE_FILES += sun/awt/AWTCharset.java
|
||||
endif
|
||||
|
||||
ifneq ($(VULKAN_ENABLED), true)
|
||||
# WLToolkit needs Vulkan java classes for initialization
|
||||
ifneq ($(call isTargetOs, linux), true)
|
||||
EXCLUDES += sun/java2d/vulkan
|
||||
endif
|
||||
endif
|
||||
|
||||
# These files do not appear in the build result of the old build. This
|
||||
# is because they are generated sources, but the AUTO_JAVA_FILES won't
|
||||
# pick them up since they aren't generated when the source dirs are
|
||||
|
||||
@@ -164,10 +164,23 @@ ifeq ($(call isTargetOs, windows), true)
|
||||
LIBAWT_CFLAGS += $(A11Y_JAWS_ANNOUNCING_CFLAGS)
|
||||
endif
|
||||
|
||||
# Setup Vulkan
|
||||
ifeq ($(VULKAN_ENABLED), true)
|
||||
LIBAWT_EXTRA_SRC += common/font common/java2d/vulkan
|
||||
LIBAWT_EXTRA_HEADER_DIRS += common/font common/java2d/vulkan common/java2d
|
||||
LIBAWT_CFLAGS += $(VULKAN_FLAGS)
|
||||
LIBAWT_EXTRA_FILES += $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/AccelTexturePool.c
|
||||
LIBAWT_EXFILES += $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/vulkan/VKStubs.c
|
||||
VULKAN_EXCLUDES := vulkan
|
||||
else
|
||||
LIBAWT_EXTRA_FILES += $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/vulkan/VKStubs.c
|
||||
VULKAN_EXCLUDES := vulkan java2d/vulkan
|
||||
endif
|
||||
|
||||
$(eval $(call SetupJdkLibrary, BUILD_LIBAWT, \
|
||||
NAME := awt, \
|
||||
EXTRA_SRC := $(LIBAWT_EXTRA_SRC), \
|
||||
EXCLUDES := $(LIBAWT_EXCLUDES), \
|
||||
EXTRA_FILES := $(LIBAWT_EXTRA_FILES), \
|
||||
EXCLUDE_FILES := $(LIBAWT_EXFILES), \
|
||||
OPTIMIZATION := HIGHEST, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_CFLAGS) $(DBUS_CFLAGS), \
|
||||
@@ -237,7 +250,7 @@ spirv-name = $(strip $1).h
|
||||
ifeq ($(VULKAN_ENABLED), true)
|
||||
$(eval $(call SetupCopyFiles, COMPILE_VULKAN_SHADERS, \
|
||||
SRC := $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan, \
|
||||
FILES := $(call FindFiles, $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan), \
|
||||
FILES := $(filter-out %.glsl, $(call FindFiles, $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan)), \
|
||||
DEST := $(SUPPORT_OUTPUTDIR)/headers/java.desktop/vulkan/spirv, \
|
||||
MACRO := compile-spirv, \
|
||||
NAME_MACRO := spirv-name, \
|
||||
@@ -245,14 +258,14 @@ ifeq ($(VULKAN_ENABLED), true)
|
||||
VULKAN_SHADER_LIST = $(SUPPORT_OUTPUTDIR)/headers/java.desktop/vulkan/shader_list.h
|
||||
$(VULKAN_SHADER_LIST): $(COMPILE_VULKAN_SHADERS)
|
||||
> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
$(foreach f, $(patsubst $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan/%,%,$(call FindFiles, $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan)), \
|
||||
$(foreach f, $(patsubst $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan/%,%,$(filter-out %.glsl, $(call FindFiles, $(TOPDIR)/src/$(MODULE)/share/glsl/vulkan))), \
|
||||
$(ECHO) SHADER_ENTRY\($(subst .,$(COMMA),$(subst /,_,$f))\) >> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
$(ECHO) '#ifdef INCLUDE_BYTECODE' >> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
$(ECHO) '#include "spirv/$f.h"' >> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
$(ECHO) BYTECODE_END >> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
$(ECHO) '#endif' >> $(VULKAN_SHADER_LIST) $(NEWLINE) \
|
||||
)
|
||||
$(BUILD_LIBAWT): $(VULKAN_SHADER_LIST)
|
||||
$(BUILD_LIBAWT_TARGET_DEPS): $(VULKAN_SHADER_LIST)
|
||||
endif
|
||||
|
||||
TARGETS += $(BUILD_LIBAWT)
|
||||
@@ -382,18 +395,13 @@ ifeq ($(call isTargetOs, windows macosx), false)
|
||||
common/wayland \
|
||||
#
|
||||
|
||||
LIBAWT_WLAWT_EXCLUDES := medialib debug opengl x11
|
||||
LIBAWT_WLAWT_EXCLUDES := medialib debug opengl x11 $(VULKAN_EXCLUDES)
|
||||
LIBAWT_WLAWT_EXCLUDE_FILES := common/awt/X11Color.c common/awt/awt_Font.c
|
||||
|
||||
# Substitute Vulkan with stubs if disabled.
|
||||
ifeq ($(VULKAN_ENABLED), false)
|
||||
LIBAWT_WLAWT_EXCLUDES += vulkan
|
||||
LIBAWT_WLAWT_EXTRA_FILES += $(TOPDIR)/src/$(MODULE)/share/native/common/java2d/vulkan/VKStubs.c
|
||||
endif
|
||||
|
||||
LIBAWT_WLAWT_EXTRA_HEADER_DIRS := \
|
||||
$(LIBAWT_DEFAULT_HEADER_DIRS) \
|
||||
libawt_wlawt/awt \
|
||||
$(SUPPORT_OUTPUTDIR)/gensrc/java.desktop/wayland \
|
||||
include \
|
||||
common/awt/debug \
|
||||
common/awt/systemscale \
|
||||
@@ -1103,8 +1111,7 @@ ifeq ($(call isTargetOs, macosx), true)
|
||||
LIBAWT_LWAWT_CFLAGS := $(X_CFLAGS) $(X_LIBS)
|
||||
|
||||
LIBAWT_LWAWT_EXFILES := fontpath.c awt_Font.c X11Color.c
|
||||
LIBAWT_LWAWT_EXCLUDES := \
|
||||
$(TOPDIR)/src/$(MODULE)/share/native/common/java2d/vulkan \
|
||||
LIBAWT_LWAWT_EXCLUDES := $(VULKAN_EXCLUDES) \
|
||||
$(TOPDIR)/src/$(MODULE)/unix/native/common/awt/medialib \
|
||||
#
|
||||
|
||||
|
||||
@@ -43,7 +43,10 @@ product(bool, UseOSErrorReporting, false, \
|
||||
"Let VM fatal error propagate to the OS (ie. WER on Windows)") \
|
||||
\
|
||||
product(bool, UseCriticalSection, true, EXPERIMENTAL, \
|
||||
"Use the critical section API instead of WaitForSingleObject")
|
||||
"Use the critical section API instead of WaitForSingleObject") \
|
||||
\
|
||||
product(bool, UseModernSynchAPI, true, EXPERIMENTAL, \
|
||||
"Use more modern WinAPI for synchronization instead of WaitForSingleObject")
|
||||
|
||||
// end of RUNTIME_OS_FLAGS
|
||||
|
||||
|
||||
@@ -5805,7 +5805,9 @@ int PlatformEvent::park(jlong Millis) {
|
||||
// 1 => 0 : pass - return immediately
|
||||
// 0 => -1 : block; then set _Event to 0 before returning
|
||||
|
||||
guarantee(_ParkHandle != nullptr , "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr , "Invariant");
|
||||
}
|
||||
guarantee(Millis > 0 , "Invariant");
|
||||
|
||||
// CONSIDER: defer assigning a CreateEvent() handle to the Event until
|
||||
@@ -5837,22 +5839,34 @@ int PlatformEvent::park(jlong Millis) {
|
||||
// adjust Millis accordingly if we encounter a spurious wakeup.
|
||||
|
||||
const int MAXTIMEOUT = 0x10000000;
|
||||
DWORD rv = WAIT_TIMEOUT;
|
||||
while (_Event < 0 && Millis > 0) {
|
||||
DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT)
|
||||
if (Millis > MAXTIMEOUT) {
|
||||
prd = MAXTIMEOUT;
|
||||
}
|
||||
|
||||
if (UseModernSynchAPI) {
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval(prd);
|
||||
phri = new HighResolutionInterval(Millis);
|
||||
}
|
||||
rv = ::WaitForSingleObject(_ParkHandle, prd);
|
||||
assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed");
|
||||
if (rv == WAIT_TIMEOUT) {
|
||||
Millis -= prd;
|
||||
if ((v = Atomic::load_acquire(&_Event)) < 0) {
|
||||
::WaitOnAddress(&_Event, &v, sizeof(_Event), Millis);
|
||||
}
|
||||
delete phri; // if it is null, harmless
|
||||
} else {
|
||||
DWORD rv = WAIT_TIMEOUT;
|
||||
while (_Event < 0 && Millis > 0) {
|
||||
DWORD prd = Millis; // set prd = MAX (Millis, MAXTIMEOUT)
|
||||
if (Millis > MAXTIMEOUT) {
|
||||
prd = MAXTIMEOUT;
|
||||
}
|
||||
HighResolutionInterval *phri = nullptr;
|
||||
if (!ForceTimeHighResolution) {
|
||||
phri = new HighResolutionInterval(prd);
|
||||
}
|
||||
rv = ::WaitForSingleObject(_ParkHandle, prd);
|
||||
assert(rv == WAIT_OBJECT_0 || rv == WAIT_TIMEOUT, "WaitForSingleObject failed");
|
||||
if (rv == WAIT_TIMEOUT) {
|
||||
Millis -= prd;
|
||||
}
|
||||
delete phri; // if it is null, harmless
|
||||
}
|
||||
}
|
||||
v = _Event;
|
||||
_Event = 0;
|
||||
@@ -5870,7 +5884,9 @@ void PlatformEvent::park() {
|
||||
// 1 => 0 : pass - return immediately
|
||||
// 0 => -1 : block; then set _Event to 0 before returning
|
||||
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
}
|
||||
// Invariant: Only the thread associated with the Event/PlatformEvent
|
||||
// may call park().
|
||||
// Consider: use atomic decrement instead of CAS-loop
|
||||
@@ -5882,12 +5898,18 @@ void PlatformEvent::park() {
|
||||
guarantee((v == 0) || (v == 1), "invariant");
|
||||
if (v != 0) return;
|
||||
|
||||
// Do this the hard way by blocking ...
|
||||
// TODO: consider a brief spin here, gated on the success of recent
|
||||
// spin attempts by this thread.
|
||||
while (_Event < 0) {
|
||||
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
|
||||
assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed");
|
||||
if (UseModernSynchAPI) {
|
||||
while ((v = Atomic::load_acquire(&_Event)) < 0) {
|
||||
::WaitOnAddress(&_Event, &v, sizeof(_Event), INFINITE);
|
||||
}
|
||||
} else {
|
||||
// Do this the hard way by blocking ...
|
||||
// TODO: consider a brief spin here, gated on the success of recent
|
||||
// spin attempts by this thread.
|
||||
while (_Event < 0) {
|
||||
DWORD rv = ::WaitForSingleObject(_ParkHandle, INFINITE);
|
||||
assert(rv == WAIT_OBJECT_0, "WaitForSingleObject failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Usually we'll find _Event == 0 at this point, but as
|
||||
@@ -5899,7 +5921,9 @@ void PlatformEvent::park() {
|
||||
}
|
||||
|
||||
void PlatformEvent::unpark() {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
if (!UseModernSynchAPI) {
|
||||
guarantee(_ParkHandle != nullptr, "Invariant");
|
||||
}
|
||||
|
||||
// Transitions for _Event:
|
||||
// 0 => 1 : just return
|
||||
@@ -5915,9 +5939,14 @@ void PlatformEvent::unpark() {
|
||||
// from the first park() call after an unpark() call which will help
|
||||
// shake out uses of park() and unpark() without condition variables.
|
||||
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
|
||||
::SetEvent(_ParkHandle);
|
||||
if (UseModernSynchAPI) {
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
// Changed from -1 to 1; the target thread's WaitOnAddress() must return now
|
||||
::WakeByAddressAll((PVOID) &_Event);
|
||||
} else {
|
||||
if (Atomic::xchg(&_Event, 1) >= 0) return;
|
||||
::SetEvent(_ParkHandle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5929,7 +5958,6 @@ void PlatformEvent::unpark() {
|
||||
// use them directly.
|
||||
|
||||
void Parker::park(bool isAbsolute, jlong time) {
|
||||
guarantee(_ParkHandle != nullptr, "invariant");
|
||||
// First, demultiplex/decode time arguments
|
||||
if (time < 0) { // don't wait
|
||||
return;
|
||||
@@ -5949,23 +5977,50 @@ void Parker::park(bool isAbsolute, jlong time) {
|
||||
|
||||
JavaThread* thread = JavaThread::current();
|
||||
|
||||
// Don't wait if interrupted or already triggered
|
||||
if (thread->is_interrupted(false) ||
|
||||
WaitForSingleObject(_ParkHandle, 0) == WAIT_OBJECT_0) {
|
||||
ResetEvent(_ParkHandle);
|
||||
return;
|
||||
} else {
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
|
||||
if (UseModernSynchAPI) {
|
||||
// Don't wait if interrupted or already triggered
|
||||
if (thread->is_interrupted(false)) {
|
||||
Atomic::release_store(&_TargetValue, 0);
|
||||
return;
|
||||
} else {
|
||||
int curHandle = Atomic::load_acquire(&_TargetValue);
|
||||
if (curHandle > 0) {
|
||||
// Already unparked
|
||||
Atomic::release_store(&_TargetValue, 0);
|
||||
return;
|
||||
} else {
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
|
||||
|
||||
WaitForSingleObject(_ParkHandle, time);
|
||||
ResetEvent(_ParkHandle);
|
||||
// Spurios wakeups are fine as per Unsafe.park() promise
|
||||
::WaitOnAddress(&_TargetValue, &curHandle, sizeof(_TargetValue), time);
|
||||
Atomic::release_store(&_TargetValue, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Don't wait if interrupted or already triggered
|
||||
if (thread->is_interrupted(false) ||
|
||||
WaitForSingleObject(_ParkHandle, 0) == WAIT_OBJECT_0) {
|
||||
ResetEvent(_ParkHandle);
|
||||
return;
|
||||
} else {
|
||||
ThreadBlockInVM tbivm(thread);
|
||||
OSThreadWaitState osts(thread->osthread(), false /* not Object.wait() */);
|
||||
|
||||
WaitForSingleObject(_ParkHandle, time);
|
||||
ResetEvent(_ParkHandle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Parker::unpark() {
|
||||
guarantee(_ParkHandle != nullptr, "invariant");
|
||||
SetEvent(_ParkHandle);
|
||||
if (UseModernSynchAPI) {
|
||||
Atomic::release_store(&_TargetValue, 1);
|
||||
::WakeByAddressAll(&_TargetValue);
|
||||
} else {
|
||||
guarantee(_ParkHandle != nullptr, "invariant");
|
||||
SetEvent(_ParkHandle);
|
||||
}
|
||||
}
|
||||
|
||||
// Platform Monitor implementation
|
||||
|
||||
@@ -41,8 +41,10 @@ class PlatformEvent : public CHeapObj<mtSynchronizer> {
|
||||
public:
|
||||
PlatformEvent() {
|
||||
_Event = 0 ;
|
||||
_ParkHandle = CreateEvent (nullptr, false, false, nullptr) ;
|
||||
guarantee (_ParkHandle != nullptr, "invariant") ;
|
||||
if (!UseModernSynchAPI) {
|
||||
_ParkHandle = CreateEvent (nullptr, false, false, nullptr) ;
|
||||
guarantee (_ParkHandle != nullptr, "invariant") ;
|
||||
}
|
||||
}
|
||||
|
||||
// Exercise caution using reset() and fired() - they may require MEMBARs
|
||||
@@ -57,16 +59,23 @@ class PlatformEvent : public CHeapObj<mtSynchronizer> {
|
||||
class PlatformParker {
|
||||
NONCOPYABLE(PlatformParker);
|
||||
|
||||
protected:
|
||||
protected:
|
||||
HANDLE _ParkHandle;
|
||||
int _TargetValue;
|
||||
|
||||
public:
|
||||
public:
|
||||
PlatformParker() {
|
||||
_ParkHandle = CreateEvent (nullptr, true, false, nullptr) ;
|
||||
guarantee(_ParkHandle != nullptr, "invariant") ;
|
||||
if (UseModernSynchAPI) {
|
||||
_TargetValue = 0;
|
||||
} else {
|
||||
_ParkHandle = CreateEvent (nullptr, true, false, nullptr) ;
|
||||
guarantee(_ParkHandle != nullptr, "invariant") ;
|
||||
}
|
||||
}
|
||||
~PlatformParker() {
|
||||
CloseHandle(_ParkHandle);
|
||||
if (! UseModernSynchAPI) {
|
||||
CloseHandle(_ParkHandle);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -404,7 +404,6 @@ bool SharedClassPathEntry::validate(bool is_class_path) const {
|
||||
// filters out any archived module classes that do not have a matching runtime
|
||||
// module path location.
|
||||
log_warning(cds)("Required classpath entry does not exist: %s", name);
|
||||
ok = false;
|
||||
} else if (is_dir()) {
|
||||
if (!os::dir_is_empty(name)) {
|
||||
log_warning(cds)("directory is not empty: %s", name);
|
||||
@@ -844,6 +843,20 @@ bool FileMapInfo::validate_boot_class_paths() {
|
||||
num = rp_len;
|
||||
}
|
||||
mismatch = check_paths(1, num, rp_array, 0, 0);
|
||||
if (mismatch) {
|
||||
// To facilitate app deployment, we allow the JAR files to be moved *together* to
|
||||
// a different location, as long as they are still stored under the same directory
|
||||
// structure. E.g., the following is OK.
|
||||
// Extends JDK-8279366 to boot classpath.
|
||||
unsigned int dumptime_prefix_len = header()->common_app_classpath_prefix_size();
|
||||
unsigned int runtime_prefix_len = longest_common_app_classpath_prefix_len(num, rp_array);
|
||||
if (dumptime_prefix_len != 0 || runtime_prefix_len != 0) {
|
||||
log_info(cds, path)("LCP length for boot classpath (dumptime: %u, runtime: %u)",
|
||||
dumptime_prefix_len, runtime_prefix_len);
|
||||
mismatch = check_paths(1, num, rp_array,
|
||||
dumptime_prefix_len, runtime_prefix_len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// create_path_array() ignores non-existing paths. Although the dump time and runtime boot classpath lengths
|
||||
// are the same initially, after the call to create_path_array(), the runtime boot classpath length could become
|
||||
|
||||
@@ -204,7 +204,7 @@ void LambdaFormInvokers::regenerate_class(char* class_name, ClassFileStream& st,
|
||||
class_name_sym,
|
||||
cld,
|
||||
cl_info,
|
||||
false, // pick_newest
|
||||
nullptr,
|
||||
CHECK);
|
||||
|
||||
assert(result->java_mirror() != nullptr, "must be");
|
||||
|
||||
@@ -5449,7 +5449,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||
ClassLoaderData* loader_data,
|
||||
const ClassLoadInfo* cl_info,
|
||||
Publicity pub_level,
|
||||
const bool pick_newest,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) :
|
||||
_stream(stream),
|
||||
_class_name(nullptr),
|
||||
@@ -5511,7 +5511,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||
_has_empty_finalizer(false),
|
||||
_has_vanilla_constructor(false),
|
||||
_max_bootstrap_specifier_index(-1),
|
||||
_pick_newest(pick_newest) {
|
||||
_old_2_new_klass_map(old_2_new_klass_map) {
|
||||
|
||||
_class_name = name != nullptr ? name : vmSymbols::unknown_class_name();
|
||||
_class_name->increment_refcount();
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/typeArrayOop.hpp"
|
||||
#include "utilities/accessFlags.hpp"
|
||||
#include "classFileParserDCEVM.hpp"
|
||||
|
||||
class Annotations;
|
||||
template <typename T>
|
||||
@@ -201,7 +202,7 @@ class ClassFileParser {
|
||||
int _max_bootstrap_specifier_index; // detects BSS values
|
||||
|
||||
// (DCEVM) Enhanced class redefinition
|
||||
const bool _pick_newest;
|
||||
const Old2NewKlassMap* _old_2_new_klass_map;
|
||||
|
||||
void parse_stream(const ClassFileStream* const stream, TRAPS);
|
||||
|
||||
@@ -534,7 +535,13 @@ class ClassFileParser {
|
||||
|
||||
void update_class_name(Symbol* new_name);
|
||||
// (DCEVM) Enhanced class redefinition
|
||||
inline const Klass* maybe_newest(const Klass* klass) const { return klass != NULL && _pick_newest ? klass->newest_version() : klass; }
|
||||
inline const Klass* maybe_newest(Klass* klass) const {
|
||||
if (klass != nullptr && _old_2_new_klass_map != nullptr) {
|
||||
Klass** new_klass = _old_2_new_klass_map->get(klass);
|
||||
return (new_klass != nullptr) ? *new_klass : klass;
|
||||
}
|
||||
return klass;
|
||||
}
|
||||
|
||||
public:
|
||||
ClassFileParser(ClassFileStream* stream,
|
||||
@@ -542,7 +549,7 @@ class ClassFileParser {
|
||||
ClassLoaderData* loader_data,
|
||||
const ClassLoadInfo* cl_info,
|
||||
Publicity pub_level,
|
||||
const bool pick_newest,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
|
||||
~ClassFileParser();
|
||||
|
||||
38
src/hotspot/share/classfile/classFileParserDCEVM.hpp
Normal file
38
src/hotspot/share/classfile/classFileParserDCEVM.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 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
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_CLASSFILE_CLASSFILEPARSER_DCEVM_HPP
|
||||
#define SHARE_CLASSFILE_CLASSFILEPARSER_DCEVM_HPP
|
||||
|
||||
#include "utilities/resourceHash.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/klass.hpp"
|
||||
|
||||
inline bool old2new_ptr_equals(Klass* const& a, Klass* const& b) { return a == b; }
|
||||
inline unsigned old2new_ptr_hash(Klass* const& p) { return (unsigned)((uintptr_t)p * 2654435761u); }
|
||||
|
||||
using Old2NewKlassMap =
|
||||
ResourceHashtable<Klass*, Klass*, 1031, AnyObj::C_HEAP, mtInternal, old2new_ptr_hash, old2new_ptr_equals>;
|
||||
|
||||
#endif //SHARE_CLASSFILE_CLASSFILEPARSER_DCEVM_HPP
|
||||
@@ -1220,7 +1220,7 @@ InstanceKlass* ClassLoader::load_class(Symbol* name, bool search_append_only, TR
|
||||
name,
|
||||
loader_data,
|
||||
cl_info,
|
||||
false, // pick_newest
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
result->set_classpath_index(classpath_index);
|
||||
return result;
|
||||
|
||||
@@ -375,8 +375,6 @@ inline int Backtrace::get_line_number(Method* method, int bci) {
|
||||
// "no LineNumberTable". JDK tests for -2.
|
||||
line_number = -2;
|
||||
} else {
|
||||
// (DCEVM): Line numbers from the newest version must be used
|
||||
method = method->newest_version();
|
||||
// Returns -1 if no LineNumberTable, and otherwise actual line number
|
||||
line_number = method->line_number_from_bci(bci);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ InstanceKlass* KlassFactory::check_shared_class_file_load_hook(
|
||||
loader_data,
|
||||
&cl_info,
|
||||
ClassFileParser::BROADCAST, // publicity level
|
||||
false,
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();
|
||||
InstanceKlass* new_ik = parser.create_instance_klass(true, // changed_by_loadhook
|
||||
@@ -170,7 +170,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
|
||||
Symbol* name,
|
||||
ClassLoaderData* loader_data,
|
||||
const ClassLoadInfo& cl_info,
|
||||
const bool pick_newest,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) {
|
||||
assert(stream != nullptr, "invariant");
|
||||
assert(loader_data != nullptr, "invariant");
|
||||
@@ -200,7 +200,7 @@ InstanceKlass* KlassFactory::create_from_stream(ClassFileStream* stream,
|
||||
loader_data,
|
||||
&cl_info,
|
||||
ClassFileParser::BROADCAST, // publicity level
|
||||
pick_newest,
|
||||
old_2_new_klass_map,
|
||||
CHECK_NULL);
|
||||
|
||||
const ClassInstanceInfo* cl_inst_info = cl_info.class_hidden_info_ptr();
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "memory/allStatic.hpp"
|
||||
#include "runtime/handles.hpp"
|
||||
#include "classfile/classFileParserDCEVM.hpp"
|
||||
|
||||
class ClassFileStream;
|
||||
class ClassLoaderData;
|
||||
@@ -64,7 +65,7 @@ class KlassFactory : AllStatic {
|
||||
Symbol* name,
|
||||
ClassLoaderData* loader_data,
|
||||
const ClassLoadInfo& cl_info,
|
||||
const bool pick_newest,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
static InstanceKlass* check_shared_class_file_load_hook(
|
||||
InstanceKlass* ik,
|
||||
|
||||
@@ -804,12 +804,13 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream(
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) {
|
||||
|
||||
EventClassLoad class_load_start_event;
|
||||
ClassLoaderData* loader_data;
|
||||
|
||||
bool is_redefining = (old_klass != NULL);
|
||||
bool is_redefining = (old_klass != nullptr);
|
||||
|
||||
// - for hidden classes that are not strong: create a new CLD that has a class holder and
|
||||
// whose loader is the Lookup class's loader.
|
||||
@@ -826,7 +827,7 @@ InstanceKlass* SystemDictionary::resolve_hidden_class_from_stream(
|
||||
class_name,
|
||||
loader_data,
|
||||
cl_info,
|
||||
is_redefining, // pick_newest
|
||||
old_2_new_klass_map, // pick_newest
|
||||
CHECK_NULL);
|
||||
assert(k != NULL, "no klass created");
|
||||
if (is_redefining && k != nullptr) {
|
||||
@@ -869,6 +870,7 @@ InstanceKlass* SystemDictionary::resolve_class_from_stream(
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) {
|
||||
|
||||
HandleMark hm(THREAD);
|
||||
@@ -899,7 +901,7 @@ InstanceKlass* SystemDictionary::resolve_class_from_stream(
|
||||
#endif
|
||||
|
||||
if (k == nullptr) {
|
||||
k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, is_redefining, CHECK_NULL);
|
||||
k = KlassFactory::create_from_stream(st, class_name, loader_data, cl_info, old_2_new_klass_map, CHECK_NULL);
|
||||
}
|
||||
|
||||
if (is_redefining && k != nullptr) {
|
||||
@@ -939,11 +941,12 @@ InstanceKlass* SystemDictionary::resolve_from_stream(ClassFileStream* st,
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) {
|
||||
if (cl_info.is_hidden()) {
|
||||
return resolve_hidden_class_from_stream(st, class_name, class_loader, cl_info, old_klass, CHECK_NULL);
|
||||
return resolve_hidden_class_from_stream(st, class_name, class_loader, cl_info, old_klass, old_2_new_klass_map, CHECK_NULL);
|
||||
} else {
|
||||
return resolve_class_from_stream(st, class_name, class_loader, cl_info, old_klass, CHECK_NULL);
|
||||
return resolve_class_from_stream(st, class_name, class_loader, cl_info, old_klass, old_2_new_klass_map, CHECK_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2334,7 +2337,7 @@ Handle SystemDictionary::link_method_handle_constant(Klass* caller,
|
||||
|
||||
// call java.lang.invoke.MethodHandleNatives::linkMethodHandleConstant(Class caller, int refKind, Class callee, String name, Object type) -> MethodHandle
|
||||
JavaCallArguments args;
|
||||
args.push_oop(Handle(THREAD, caller->newest_version()->java_mirror())); // the referring class
|
||||
args.push_oop(Handle(THREAD, caller->active_version()->java_mirror())); // the referring class
|
||||
args.push_int(ref_kind);
|
||||
args.push_oop(Handle(THREAD, callee->java_mirror())); // the target class
|
||||
args.push_oop(name_str);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "runtime/handles.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
#include "utilities/vmEnums.hpp"
|
||||
#include "classfile/classFileParserDCEVM.hpp"
|
||||
|
||||
// The dictionary in each ClassLoaderData stores all loaded classes, either
|
||||
// initiatied by its class loader or defined by its class loader:
|
||||
@@ -119,6 +120,7 @@ class SystemDictionary : AllStatic {
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
|
||||
// Resolve a class from stream (called by jni_DefineClass and JVM_DefineClass)
|
||||
@@ -128,6 +130,7 @@ class SystemDictionary : AllStatic {
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
|
||||
static oop get_system_class_loader_impl(TRAPS);
|
||||
@@ -140,6 +143,7 @@ class SystemDictionary : AllStatic {
|
||||
Handle class_loader,
|
||||
const ClassLoadInfo& cl_info,
|
||||
InstanceKlass* old_klass,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
|
||||
// Lookup an already loaded class. If not found null is returned.
|
||||
|
||||
@@ -34,17 +34,31 @@
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "utilities/copy.hpp"
|
||||
#include "runtime/fieldDescriptor.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
|
||||
DcevmSharedGC* DcevmSharedGC::_static_instance = nullptr;
|
||||
|
||||
void DcevmSharedGC::create_static_instance() {
|
||||
_static_instance = new DcevmSharedGC();
|
||||
}
|
||||
|
||||
void DcevmSharedGC::destroy_static_instance() {
|
||||
if (_static_instance != nullptr) {
|
||||
delete _static_instance;
|
||||
_static_instance = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_oops, bool must_be_new) {
|
||||
if (rescued_oops != NULL) {
|
||||
if (rescued_oops != nullptr) {
|
||||
copy_rescued_objects_back(rescued_oops, 0, rescued_oops->length(), must_be_new);
|
||||
}
|
||||
}
|
||||
|
||||
// (DCEVM) Copy the rescued objects to their destination address after compaction.
|
||||
void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_oops, int from, int to, bool must_be_new) {
|
||||
|
||||
if (rescued_oops != NULL) {
|
||||
if (rescued_oops != nullptr) {
|
||||
for (int i=from; i < to; i++) {
|
||||
HeapWord* rescued_ptr = rescued_oops->at(i);
|
||||
oop rescued_obj = cast_to_oop(rescued_ptr);
|
||||
@@ -52,10 +66,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_
|
||||
size_t size = rescued_obj->size();
|
||||
oop new_obj = rescued_obj->forwardee();
|
||||
|
||||
assert(!must_be_new || rescued_obj->klass()->new_version() != NULL, "Just checking");
|
||||
assert(!must_be_new || rescued_obj->klass()->new_version() != nullptr, "Just checking");
|
||||
Klass* new_klass = rescued_obj->klass()->new_version();
|
||||
if (new_klass!= NULL) {
|
||||
if (new_klass->update_information() != NULL) {
|
||||
if (new_klass!= nullptr) {
|
||||
if (new_klass->update_information() != nullptr) {
|
||||
DcevmSharedGC::update_fields(rescued_obj, new_obj);
|
||||
} else {
|
||||
rescued_obj->set_klass(new_klass);
|
||||
@@ -69,11 +83,10 @@ void DcevmSharedGC::copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_
|
||||
assert(oopDesc::is_oop(new_obj), "must be a valid oop");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void DcevmSharedGC::clear_rescued_objects_resource(GrowableArray<HeapWord*>* rescued_oops) {
|
||||
if (rescued_oops != NULL) {
|
||||
if (rescued_oops != nullptr) {
|
||||
for (int i=0; i < rescued_oops->length(); i++) {
|
||||
HeapWord* rescued_ptr = rescued_oops->at(i);
|
||||
size_t size = cast_to_oop(rescued_ptr)->size();
|
||||
@@ -84,7 +97,7 @@ void DcevmSharedGC::clear_rescued_objects_resource(GrowableArray<HeapWord*>* res
|
||||
}
|
||||
|
||||
void DcevmSharedGC::clear_rescued_objects_heap(GrowableArray<HeapWord*>* rescued_oops) {
|
||||
if (rescued_oops != NULL) {
|
||||
if (rescued_oops != nullptr) {
|
||||
for (int i=0; i < rescued_oops->length(); i++) {
|
||||
HeapWord* rescued_ptr = rescued_oops->at(i);
|
||||
FREE_C_HEAP_ARRAY(HeapWord, rescued_ptr);
|
||||
@@ -96,7 +109,7 @@ void DcevmSharedGC::clear_rescued_objects_heap(GrowableArray<HeapWord*>* rescued
|
||||
// (DCEVM) Update instances of a class whose fields changed.
|
||||
void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
||||
|
||||
assert(q->klass()->new_version() != NULL, "class of old object must have new version");
|
||||
assert(q->klass()->new_version() != nullptr, "class of old object must have new version");
|
||||
|
||||
Klass* old_klass_oop = q->klass();
|
||||
Klass* new_klass_oop = q->klass()->new_version();
|
||||
@@ -107,7 +120,7 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
||||
size_t size = q->size_given_klass(old_klass);
|
||||
size_t new_size = q->size_given_klass(new_klass);
|
||||
|
||||
HeapWord* tmp = NULL;
|
||||
HeapWord* tmp = nullptr;
|
||||
oop tmp_obj = q;
|
||||
|
||||
// Save object somewhere, there is an overlap in fields
|
||||
@@ -122,39 +135,141 @@ void DcevmSharedGC::update_fields(oop q, oop new_location) {
|
||||
|
||||
q->set_klass(new_klass_oop);
|
||||
int *cur = new_klass_oop->update_information();
|
||||
assert(cur != NULL, "just checking");
|
||||
DcevmSharedGC::update_fields(new_location, q, cur);
|
||||
assert(cur != nullptr, "just checking");
|
||||
_static_instance->update_fields(new_location, q, cur, false);
|
||||
|
||||
if (tmp != NULL) {
|
||||
if (tmp != nullptr) {
|
||||
FREE_RESOURCE_ARRAY(HeapWord, tmp, size);
|
||||
}
|
||||
}
|
||||
|
||||
void DcevmSharedGC::update_fields(oop new_location, oop tmp_obj, int *cur) {
|
||||
assert(cur != NULL, "just checking");
|
||||
char* to = (char*)cast_from_oop<HeapWord*>(new_location);
|
||||
void DcevmSharedGC::update_fields(oop new_obj, oop old_obj, int* cur, bool do_compat_check) {
|
||||
assert(cur != nullptr, "just checking");
|
||||
char* to = (char*)cast_from_oop<HeapWord*>(new_obj);
|
||||
char* src_base = (char *)cast_from_oop<HeapWord*>(old_obj);
|
||||
while (*cur != 0) {
|
||||
int size = *cur;
|
||||
if (size > 0) {
|
||||
int raw = *cur;
|
||||
if (raw > 0) {
|
||||
cur++;
|
||||
int offset = *cur;
|
||||
HeapWord* from = (HeapWord*)(((char *)cast_from_oop<HeapWord*>(tmp_obj)) + offset);
|
||||
if (size == HeapWordSize) {
|
||||
*((HeapWord*)to) = *from;
|
||||
} else if (size == HeapWordSize * 2) {
|
||||
*((HeapWord*)to) = *from;
|
||||
*(((HeapWord*)to) + 1) = *(from + 1);
|
||||
int src_offset = *cur;
|
||||
HeapWord* from = (HeapWord*)(src_base + src_offset);
|
||||
|
||||
bool compat_check = do_compat_check && ((raw & UpdateInfoCompatFlag) != 0);
|
||||
int size = (raw & UpdateInfoLengthMask);
|
||||
|
||||
if (!compat_check) {
|
||||
if (size == HeapWordSize) {
|
||||
*((HeapWord *) to) = *from;
|
||||
} else if (size == HeapWordSize * 2) {
|
||||
*((HeapWord *) to) = *from;
|
||||
*(((HeapWord *) to) + 1) = *(from + 1);
|
||||
} else {
|
||||
Copy::conjoint_jbytes(from, to, size);
|
||||
}
|
||||
} else {
|
||||
Copy::conjoint_jbytes(from, to, size);
|
||||
assert(size == heapOopSize, "Must be one oop");
|
||||
int dst_offset = (int)(to - (char*)cast_from_oop<HeapWord*>(new_obj));
|
||||
|
||||
oop obj = old_obj->obj_field(src_offset);
|
||||
|
||||
if (obj == nullptr) {
|
||||
new_obj->obj_field_put(dst_offset, nullptr);
|
||||
} else {
|
||||
bool compatible = is_compatible(new_obj, dst_offset, obj);
|
||||
new_obj->obj_field_put(dst_offset, compatible ? obj : (oop)nullptr);
|
||||
}
|
||||
}
|
||||
to += size;
|
||||
cur++;
|
||||
} else {
|
||||
assert(size < 0, "");
|
||||
int skip = -*cur;
|
||||
Copy::fill_to_bytes(to, skip, 0);
|
||||
to += skip;
|
||||
Copy::fill_to_bytes(to, -raw, 0);
|
||||
to += -raw;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DcevmSharedGC::update_fields_in_old(oop old_obj, int* cur) {
|
||||
assert(cur != nullptr, "just checking");
|
||||
int dst_offset = 0;
|
||||
while (*cur != 0) {
|
||||
int raw = *cur;
|
||||
if (raw > 0) {
|
||||
cur++;
|
||||
int size = (raw & UpdateInfoLengthMask);
|
||||
|
||||
if ((raw & UpdateInfoCompatFlag) != 0) {
|
||||
assert(size == heapOopSize, "Must be one oop");
|
||||
int src_offset = *cur;
|
||||
oop obj = old_obj->obj_field(src_offset);
|
||||
if (obj != nullptr) {
|
||||
bool compatible = is_compatible(old_obj, dst_offset, obj);
|
||||
if (!compatible) {
|
||||
old_obj->obj_field_put(src_offset, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
dst_offset += size;
|
||||
cur++;
|
||||
} else {
|
||||
dst_offset += -raw;
|
||||
cur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool signature_matches_name(Symbol* sig, Symbol* name) {
|
||||
const int sig_len = sig->utf8_length();
|
||||
const int name_len = name->utf8_length();
|
||||
if (sig_len != name_len + 2) {
|
||||
return false;
|
||||
}
|
||||
const u1* s = sig ->bytes();
|
||||
const u1* n = name->bytes();
|
||||
return (s[0] == 'L' && s[sig_len - 1] == ';' && memcmp(s + 1, n, name_len) == 0);
|
||||
}
|
||||
|
||||
bool DcevmSharedGC::is_compatible(oop fld_holder, int fld_offset, oop fld_val) {
|
||||
assert(oopDesc::is_oop(fld_val), "val has corrupted header");
|
||||
|
||||
bool result = false;
|
||||
Symbol *sig_wanted;
|
||||
|
||||
InstanceKlass* holder_ik = InstanceKlass::cast(fld_holder->klass()->newest_version());
|
||||
Symbol** sig_cached = _field_sig_table->get({holder_ik, fld_offset});
|
||||
|
||||
if (sig_cached != nullptr) {
|
||||
sig_wanted = *sig_cached;
|
||||
} else {
|
||||
fieldDescriptor fd_new;
|
||||
bool ok = holder_ik->find_field_from_offset(fld_offset, false, &fd_new);
|
||||
assert(ok, "Must exist");
|
||||
sig_wanted = fd_new.signature();
|
||||
_field_sig_table->put({holder_ik, fld_offset}, sig_wanted);
|
||||
}
|
||||
|
||||
InstanceKlass *ik = InstanceKlass::cast(fld_val->klass()->newest_version());
|
||||
bool* hit = _compat_table->get({ik, sig_wanted });
|
||||
|
||||
if (hit != nullptr) {
|
||||
result = *hit;
|
||||
} else {
|
||||
InstanceKlass* scan = ik;
|
||||
while (scan != nullptr && !result) {
|
||||
if (signature_matches_name(sig_wanted, scan->name())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
Array<InstanceKlass*>* ifaces = scan->local_interfaces();
|
||||
for (int j = 0; j < ifaces->length(); ++j) {
|
||||
if (signature_matches_name(sig_wanted, ifaces->at(j)->name())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
scan = (scan->super() != nullptr) ? InstanceKlass::cast(scan->super()) : nullptr;
|
||||
}
|
||||
_compat_table->put({ik, sig_wanted }, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -33,16 +33,76 @@
|
||||
#include "runtime/timer.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/stack.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
// Shared GC code used from different GC (Serial, CMS, G1) on enhanced redefinition
|
||||
class DcevmSharedGC : AllStatic {
|
||||
public:
|
||||
class DcevmSharedGC : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
struct SymbolKey {
|
||||
InstanceKlass* ik;
|
||||
Symbol* dst_sig;
|
||||
};
|
||||
static unsigned symbol_hash(const SymbolKey& k) {
|
||||
return (uintptr_t)k.ik ^ (uintptr_t)k.dst_sig;
|
||||
}
|
||||
static bool symbol_eq(const SymbolKey& a, const SymbolKey& b) {
|
||||
return a.ik == b.ik && a.dst_sig == b.dst_sig;
|
||||
}
|
||||
typedef ResourceHashtable<SymbolKey, bool, 512,
|
||||
AnyObj::C_HEAP, mtInternal,
|
||||
&symbol_hash, &symbol_eq> CompatTable;
|
||||
|
||||
struct OffsetKey {
|
||||
InstanceKlass* ik;
|
||||
int offset;
|
||||
};
|
||||
static unsigned offset_hash(const OffsetKey& k) {
|
||||
return uintptr_t(k.ik) ^ k.offset;
|
||||
}
|
||||
static bool offset_eq(const OffsetKey& a, const OffsetKey& b) {
|
||||
return a.ik == b.ik && a.offset == b.offset;
|
||||
}
|
||||
typedef ResourceHashtable<OffsetKey, Symbol*, 512,
|
||||
AnyObj::C_HEAP, mtInternal,
|
||||
&offset_hash, &offset_eq> FieldSigTable;
|
||||
|
||||
CompatTable* _compat_table;
|
||||
FieldSigTable* _field_sig_table;
|
||||
static DcevmSharedGC* _static_instance;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------
|
||||
// update info flags
|
||||
//
|
||||
// bit 31 : sign bit (<0 = fill, >0 = copy)
|
||||
// bit 30 : UpdateInfoCompatFlag – copy segment requires per-oop compatibility check
|
||||
// bits 0-29 : raw byte length of the segment
|
||||
// ------------------------------------------------------------------
|
||||
static const int UpdateInfoCompatFlag = 1U << 30;
|
||||
static const int UpdateInfoLengthMask = ~(1U << 31 | UpdateInfoCompatFlag);
|
||||
|
||||
DcevmSharedGC() {
|
||||
_compat_table = new (mtInternal) CompatTable();
|
||||
_field_sig_table = new (mtInternal) FieldSigTable();
|
||||
}
|
||||
|
||||
~DcevmSharedGC() {
|
||||
delete _compat_table;
|
||||
delete _field_sig_table;
|
||||
}
|
||||
|
||||
static void create_static_instance();
|
||||
static void destroy_static_instance();
|
||||
|
||||
static void copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_oops, bool must_be_new);
|
||||
static void copy_rescued_objects_back(GrowableArray<HeapWord*>* rescued_oops, int from, int to, bool must_be_new);
|
||||
static void clear_rescued_objects_resource(GrowableArray<HeapWord*>* rescued_oops);
|
||||
static void clear_rescued_objects_heap(GrowableArray<HeapWord*>* rescued_oops);
|
||||
static void update_fields(oop q, oop new_location);
|
||||
static void update_fields(oop new_location, oop tmp_obj, int *cur);
|
||||
|
||||
bool is_compatible(oop fld_holder, int fld_offset, oop fld_val);
|
||||
void update_fields(oop new_obj, oop old_obj, int *cur, bool do_compat_check);
|
||||
void update_fields_in_old(oop old_obj, int *cur);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -93,7 +93,9 @@ class SATBMarkQueueSet: public PtrQueueSet {
|
||||
size_t _buffer_enqueue_threshold;
|
||||
// SATB is only active during marking. Enqueuing is only done when active.
|
||||
bool _all_active;
|
||||
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 4 * sizeof(size_t));
|
||||
#if ! (defined(_WIN64) && DEFAULT_CACHE_LINE_SIZE == 32)
|
||||
DEFINE_PAD_MINUS_SIZE(2, DEFAULT_CACHE_LINE_SIZE, 4 * sizeof(size_t));
|
||||
#endif
|
||||
|
||||
BufferNode* get_completed_buffer();
|
||||
void abandon_completed_buffers();
|
||||
|
||||
@@ -294,8 +294,8 @@ void LinkResolver::check_klass_accessibility(Klass* ref_klass, Klass* sel_klass,
|
||||
Klass* refKlassNewest = ref_klass;
|
||||
Klass* baseKlassNewest = base_klass;
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
refKlassNewest = ref_klass->newest_version();
|
||||
baseKlassNewest = base_klass->newest_version();
|
||||
refKlassNewest = ref_klass->active_version();
|
||||
baseKlassNewest = base_klass->active_version();
|
||||
}
|
||||
Reflection::VerifyClassAccessResults vca_result =
|
||||
Reflection::verify_class_access(refKlassNewest, InstanceKlass::cast(baseKlassNewest), true);
|
||||
@@ -559,7 +559,7 @@ void LinkResolver::check_method_accessability(Klass* ref_klass,
|
||||
// to be false (so we'll short-circuit out of these tests).
|
||||
if (sel_method->name() == vmSymbols::clone_name() &&
|
||||
( (!AllowEnhancedClassRedefinition && sel_klass == vmClasses::Object_klass()) ||
|
||||
(AllowEnhancedClassRedefinition && sel_klass->newest_version() == vmClasses::Object_klass()->newest_version()) ) &&
|
||||
(AllowEnhancedClassRedefinition && sel_klass->active_version() == vmClasses::Object_klass()->active_version()) ) &&
|
||||
resolved_klass->is_array_klass()) {
|
||||
// We need to change "protected" to "public".
|
||||
assert(flags.is_protected(), "clone not protected?");
|
||||
@@ -734,7 +734,7 @@ Method* LinkResolver::resolve_method(const LinkInfo& link_info,
|
||||
Bytecodes::Code code, TRAPS) {
|
||||
|
||||
Handle nested_exception;
|
||||
Klass* resolved_klass = link_info.resolved_klass();
|
||||
Klass* resolved_klass = link_info.resolved_klass()->active_version();
|
||||
|
||||
// 1. For invokevirtual, cannot call an interface method
|
||||
if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) {
|
||||
|
||||
@@ -1693,7 +1693,7 @@ static InstanceKlass* create_new_instance_klass(InstanceKlass* ik, ClassFileStre
|
||||
cld,
|
||||
&cl_info,
|
||||
ClassFileParser::INTERNAL, // internal visibility
|
||||
false,
|
||||
nullptr,
|
||||
THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
log_pending_exception(PENDING_EXCEPTION);
|
||||
|
||||
@@ -369,18 +369,6 @@ void ConstantPool::remove_unshareable_info() {
|
||||
// we always set _on_stack to true to avoid having to change _flags during runtime.
|
||||
_flags |= (_on_stack | _is_shared);
|
||||
|
||||
if (!_pool_holder->is_linked() && !_pool_holder->verified_at_dump_time()) {
|
||||
return;
|
||||
}
|
||||
// Resolved references are not in the shared archive.
|
||||
// Save the length for restoration. It is not necessarily the same length
|
||||
// as reference_map.length() if invokedynamic is saved. It is needed when
|
||||
// re-creating the resolved reference array if archived heap data cannot be map
|
||||
// at runtime.
|
||||
set_resolved_reference_length(
|
||||
resolved_references() != nullptr ? resolved_references()->length() : 0);
|
||||
set_resolved_references(OopHandle());
|
||||
|
||||
bool archived = false;
|
||||
for (int index = 1; index < length(); index++) { // Index 0 is unused
|
||||
switch (tag_at(index).value()) {
|
||||
@@ -403,6 +391,19 @@ void ConstantPool::remove_unshareable_info() {
|
||||
}
|
||||
}
|
||||
|
||||
if (!_pool_holder->is_linked() && !_pool_holder->verified_at_dump_time()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolved references are not in the shared archive.
|
||||
// Save the length for restoration. It is not necessarily the same length
|
||||
// as reference_map.length() if invokedynamic is saved. It is needed when
|
||||
// re-creating the resolved reference array if archived heap data cannot be map
|
||||
// at runtime.
|
||||
set_resolved_reference_length(
|
||||
resolved_references() != nullptr ? resolved_references()->length() : 0);
|
||||
set_resolved_references(OopHandle());
|
||||
|
||||
if (cache() != nullptr) {
|
||||
// cache() is null if this class is not yet linked.
|
||||
cache()->remove_unshareable_info();
|
||||
|
||||
@@ -371,6 +371,11 @@ void InstanceKlass::set_nest_host(InstanceKlass* host) {
|
||||
// Can't assert this as package is not set yet:
|
||||
// assert(is_same_class_package(host), "proposed host is in wrong package");
|
||||
|
||||
// set dynamic nest host
|
||||
_nest_host = host;
|
||||
// Record dependency to keep nest host from being unloaded before this class.
|
||||
ClassLoaderData* this_key = class_loader_data();
|
||||
|
||||
if (log_is_enabled(Trace, class, nestmates)) {
|
||||
ResourceMark rm;
|
||||
const char* msg = "";
|
||||
@@ -379,18 +384,19 @@ void InstanceKlass::set_nest_host(InstanceKlass* host) {
|
||||
msg = "(the NestHost attribute in the current class is ignored)";
|
||||
} else if (_nest_members != nullptr && _nest_members != Universe::the_empty_short_array()) {
|
||||
msg = "(the NestMembers attribute in the current class is ignored)";
|
||||
} else if (this_key == nullptr) {
|
||||
msg = "(the NestMembers classloader data in the current class is ignored)";
|
||||
}
|
||||
|
||||
log_trace(class, nestmates)("Injected type %s into the nest of %s %s",
|
||||
this->external_name(),
|
||||
host->external_name(),
|
||||
msg);
|
||||
}
|
||||
// set dynamic nest host
|
||||
_nest_host = host;
|
||||
// Record dependency to keep nest host from being unloaded before this class.
|
||||
ClassLoaderData* this_key = class_loader_data();
|
||||
assert(this_key != nullptr, "sanity");
|
||||
this_key->record_dependency(host);
|
||||
|
||||
if (this_key != nullptr) {
|
||||
this_key->record_dependency(host);
|
||||
}
|
||||
}
|
||||
|
||||
// check if 'this' and k are nestmates (same nest_host), or k is our nest_host,
|
||||
@@ -1458,12 +1464,26 @@ bool InstanceKlass::implements_interface(Klass* k) const {
|
||||
|
||||
|
||||
// (DCEVM)
|
||||
bool InstanceKlass::implements_interface_any_version(Klass* k) const {
|
||||
k = k->newest_version();
|
||||
if (this->newest_version() == k) return true;
|
||||
bool InstanceKlass::implements_interface_dcevm(Klass* k, Old2NewKlassMap* old_2_new_klass_map) const {
|
||||
Klass** new_klass = old_2_new_klass_map->get(k);
|
||||
if (new_klass != nullptr) {
|
||||
k = *new_klass;
|
||||
}
|
||||
Klass* this_klass = (Klass*) this;
|
||||
Klass** new_this = old_2_new_klass_map->get(this_klass);
|
||||
if (new_this != nullptr) {
|
||||
this_klass = *new_this;
|
||||
}
|
||||
|
||||
if (this_klass == k) return true;
|
||||
assert(k->is_interface(), "should be an interface class");
|
||||
for (int i = 0; i < transitive_interfaces()->length(); i++) {
|
||||
if (transitive_interfaces()->at(i)->newest_version() == k) {
|
||||
Klass* ti = (Klass*) transitive_interfaces()->at(i);
|
||||
Klass** new_ti = old_2_new_klass_map->get(ti);
|
||||
if (new_ti != nullptr) {
|
||||
ti = *new_ti;
|
||||
}
|
||||
if (ti == k) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1767,6 +1787,18 @@ bool InstanceKlass::find_field_from_offset(int offset, bool is_static, fieldDesc
|
||||
}
|
||||
|
||||
|
||||
bool InstanceKlass::find_local_field_by_name(Symbol* name, fieldDescriptor* fd) const {
|
||||
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
|
||||
Symbol* f_name = fs.name();
|
||||
if (f_name == name) {
|
||||
fd->reinitialize(const_cast<InstanceKlass*>(this), fs.index());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void InstanceKlass::methods_do(void f(Method* method)) {
|
||||
// Methods aren't stable until they are loaded. This can be read outside
|
||||
// a lock through the ClassLoaderData for profiling
|
||||
@@ -4419,15 +4451,19 @@ Method* InstanceKlass::method_with_idnum(int idnum) {
|
||||
|
||||
Method* InstanceKlass::method_with_orig_idnum(int idnum) {
|
||||
if (idnum >= methods()->length()) {
|
||||
return nullptr;
|
||||
}
|
||||
Method* m = methods()->at(idnum);
|
||||
if (m != nullptr && m->orig_method_idnum() == idnum) {
|
||||
return m;
|
||||
// (DCEVM) The provided idnum may exceed the current number of methods.
|
||||
if (!AllowEnhancedClassRedefinition) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
Method* m = methods()->at(idnum);
|
||||
if (m != nullptr && m->orig_method_idnum() == idnum) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
// Obsolete method idnum does not match the original idnum
|
||||
for (int index = 0; index < methods()->length(); ++index) {
|
||||
m = methods()->at(index);
|
||||
Method* m = methods()->at(index);
|
||||
if (m->orig_method_idnum() == idnum) {
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "utilities/accessFlags.hpp"
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "classfile/classFileParserDCEVM.hpp"
|
||||
#if INCLUDE_JFR
|
||||
#include "jfr/support/jfrKlassExtension.hpp"
|
||||
#endif
|
||||
@@ -565,6 +566,7 @@ public:
|
||||
bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
|
||||
bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
|
||||
|
||||
bool find_local_field_by_name(Symbol* name, fieldDescriptor* fd) const;
|
||||
private:
|
||||
inline static int quick_search(const Array<Method*>* methods, const Symbol* name);
|
||||
|
||||
@@ -878,9 +880,11 @@ public:
|
||||
|
||||
// subclass/subinterface checks
|
||||
bool implements_interface(Klass* k) const;
|
||||
bool implements_interface_any_version(Klass* k) const;
|
||||
bool is_same_or_direct_interface(Klass* k) const;
|
||||
|
||||
// (DCEVM)
|
||||
bool implements_interface_dcevm(Klass* k, Old2NewKlassMap* old_2_new_klass_map) const;
|
||||
|
||||
#ifdef ASSERT
|
||||
// check whether this class or one of its superclasses was redefined
|
||||
bool has_redefined_this_or_super() const;
|
||||
|
||||
@@ -196,13 +196,14 @@ void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word
|
||||
// The constructor is also used from CppVtableCloner,
|
||||
// which doesn't zero out the memory before calling the constructor.
|
||||
Klass::Klass(KlassKind kind) : _kind(kind),
|
||||
_old_version(NULL),
|
||||
_new_version(NULL),
|
||||
_old_version(nullptr),
|
||||
_new_version(nullptr),
|
||||
_redefinition_flags(Klass::NoRedefinition),
|
||||
_is_redefining(false),
|
||||
_update_information(NULL),
|
||||
_update_information(nullptr),
|
||||
_is_copying_backwards(false),
|
||||
_is_rolled_back(false),
|
||||
_compat_check_field_offsets(nullptr),
|
||||
_shared_class_path_index(-1) {
|
||||
CDS_ONLY(_shared_class_flags = 0;)
|
||||
CDS_JAVA_HEAP_ONLY(_archived_mirror_index = -1;)
|
||||
|
||||
@@ -167,18 +167,18 @@ class Klass : public Metadata {
|
||||
|
||||
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
|
||||
|
||||
// Advanced class redefinition
|
||||
|
||||
// Enhanced class redefinition
|
||||
// Old version (used in advanced class redefinition)
|
||||
Klass* _old_version;
|
||||
// New version (used in advanced class redefinition)
|
||||
Klass* _new_version;
|
||||
|
||||
int _redefinition_flags; // Level of class redefinition
|
||||
bool _is_redefining;
|
||||
int* _update_information;
|
||||
bool _is_copying_backwards; // Does the class need to copy fields backwards? => possibly overwrite itself?
|
||||
bool _is_rolled_back; // true if class was rolled back in redefinition
|
||||
// offsets of fields used in compatibility check
|
||||
GrowableArray<int>* volatile _compat_check_field_offsets;
|
||||
|
||||
private:
|
||||
// This is an index into FileMapHeader::_shared_path_table[], to
|
||||
@@ -419,6 +419,13 @@ protected:
|
||||
void set_copying_backwards(bool b) { _is_copying_backwards = b; }
|
||||
bool is_rolled_back() { return _is_rolled_back; }
|
||||
void set_rolled_back(bool b) { _is_rolled_back = b;}
|
||||
GrowableArray<int>* compat_check_field_offsets() const { return Atomic::load_acquire(&_compat_check_field_offsets); }
|
||||
GrowableArray<int>* set_compat_check_field_offsets(GrowableArray<int>* offsets) {
|
||||
return Atomic::cmpxchg(&_compat_check_field_offsets, (GrowableArray<int>*) nullptr, offsets);
|
||||
}
|
||||
void clear_compat_check_field_offsets() {
|
||||
_compat_check_field_offsets = nullptr;
|
||||
}
|
||||
|
||||
protected: // internal accessors
|
||||
void set_subklass(Klass* s);
|
||||
@@ -431,7 +438,8 @@ protected:
|
||||
ModifyClassSize = ModifyClass << 1, // The size of the class meta data changes.
|
||||
ModifyInstances = ModifyClassSize << 1, // There are change to the instance format.
|
||||
ModifyInstanceSize = ModifyInstances << 1, // The size of instances changes.
|
||||
RemoveSuperType = ModifyInstanceSize << 1, // A super type of this class is removed.
|
||||
RemoveInterface = ModifyInstanceSize << 1, // A super type of this class is removed.
|
||||
RemoveSuperType = RemoveInterface << 1, // A super type of this class is removed.
|
||||
MarkedAsAffected = RemoveSuperType << 1, // This class has been marked as an affected class.
|
||||
PrimaryRedefine = MarkedAsAffected << 1 // This class is from primary redefinition set
|
||||
};
|
||||
|
||||
@@ -918,7 +918,7 @@ public:
|
||||
void release_C_heap_structures();
|
||||
|
||||
Method* get_new_method() const {
|
||||
InstanceKlass* holder = InstanceKlass::cast(method_holder()->newest_version());
|
||||
InstanceKlass* holder = InstanceKlass::cast(method_holder()->active_version());
|
||||
Method* new_method = holder->method_with_idnum(orig_method_idnum());
|
||||
|
||||
assert(new_method != nullptr, "method_with_idnum() should not be null");
|
||||
|
||||
@@ -306,10 +306,12 @@ JNI_ENTRY(jclass, jni_DefineClass(JNIEnv *env, const char *name, jobject loaderR
|
||||
Handle class_loader (THREAD, JNIHandles::resolve(loaderRef));
|
||||
Handle protection_domain;
|
||||
ClassLoadInfo cl_info(protection_domain);
|
||||
Klass* k = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
Klass* k = SystemDictionary::resolve_from_stream(&st,
|
||||
class_name,
|
||||
class_loader,
|
||||
cl_info,
|
||||
NULL,
|
||||
nullptr,
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
|
||||
@@ -896,7 +896,8 @@ static jclass jvm_define_class_common(const char *name,
|
||||
Klass* k = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
cl_info,
|
||||
NULL,
|
||||
nullptr,
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
@@ -984,7 +985,8 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name,
|
||||
ik = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
cl_info,
|
||||
NULL,
|
||||
nullptr,
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
|
||||
if (log_is_enabled(Debug, class, resolve)) {
|
||||
@@ -1001,7 +1003,8 @@ static jclass jvm_lookup_define_class(jclass lookup, const char *name,
|
||||
ik = SystemDictionary::resolve_from_stream(&st, class_name,
|
||||
class_loader,
|
||||
cl_info,
|
||||
NULL,
|
||||
nullptr,
|
||||
nullptr,
|
||||
CHECK_NULL);
|
||||
|
||||
// The hidden class loader data has been artificially been kept alive to
|
||||
|
||||
@@ -108,6 +108,7 @@ VM_EnhancedRedefineClasses::VM_EnhancedRedefineClasses(jint class_count, const j
|
||||
VM_GC_Operation(Universe::heap()->total_collections(), GCCause::_heap_inspection, Universe::heap()->total_full_collections(), true) {
|
||||
_new_classes = nullptr;
|
||||
_affected_klasses = nullptr;
|
||||
_removed_interfaces = nullptr;
|
||||
_class_count = class_count;
|
||||
_class_defs = class_defs;
|
||||
_class_load_kind = class_load_kind;
|
||||
@@ -128,7 +129,6 @@ static inline InstanceKlass* get_ik(jclass def) {
|
||||
// - Start mark&sweep GC.
|
||||
// - true if success, otherwise all chnages are rollbacked.
|
||||
bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
|
||||
if (_class_count == 0) {
|
||||
_res = JVMTI_ERROR_NONE;
|
||||
return false;
|
||||
@@ -202,7 +202,36 @@ bool VM_EnhancedRedefineClasses::doit_prologue() {
|
||||
|
||||
// Closer for static fields - copy value from old class to the new class.
|
||||
class FieldCopier : public FieldClosure {
|
||||
public:
|
||||
private:
|
||||
VM_EnhancedRedefineClasses::SymbolSet* _removed_interfaces;
|
||||
public:
|
||||
FieldCopier(VM_EnhancedRedefineClasses::SymbolSet* removed_interfaces)
|
||||
: _removed_interfaces(removed_interfaces) {}
|
||||
|
||||
bool is_compatible(oop fld_holder, int fld_offset, Symbol* sig_new) {
|
||||
oop oop = fld_holder->obj_field(fld_offset);
|
||||
if (oop != nullptr) {
|
||||
Klass* k = oop->klass();
|
||||
if (k->is_instance_klass() && k->is_redefining()) {
|
||||
InstanceKlass *scan = InstanceKlass::cast(k);
|
||||
while (scan != nullptr) {
|
||||
if (sig_new->equals(scan->signature_name())) {
|
||||
return true;
|
||||
}
|
||||
Array<InstanceKlass*>* local_interfaces = scan->local_interfaces();
|
||||
for (int j = 0; j < local_interfaces->length(); j++) {
|
||||
Klass* iface = local_interfaces->at(j);
|
||||
if (sig_new->equals(iface->signature_name())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
scan = (scan->super() != nullptr) ? InstanceKlass::cast(scan->super()) : nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void do_field(fieldDescriptor* fd) {
|
||||
InstanceKlass* cur = InstanceKlass::cast(fd->field_holder());
|
||||
oop cur_oop = cur->java_mirror();
|
||||
@@ -211,19 +240,36 @@ class FieldCopier : public FieldClosure {
|
||||
oop old_oop = old->java_mirror();
|
||||
|
||||
fieldDescriptor result;
|
||||
bool found = old->find_local_field(fd->name(), fd->signature(), &result);
|
||||
Symbol* sig_new = fd->signature();
|
||||
bool found = old->find_local_field_by_name(fd->name(), &result);
|
||||
if (found && result.is_static()) {
|
||||
log_trace(redefine, class, obsolete, metadata)("Copying static field value for field %s old_offset=%d new_offset=%d",
|
||||
fd->name()->as_C_string(), result.offset(), fd->offset());
|
||||
memcpy(cur_oop->field_addr<HeapWord>(fd->offset()),
|
||||
old_oop->field_addr<HeapWord>(result.offset()),
|
||||
type2aelembytes(fd->field_type()));
|
||||
Symbol* sig_old = result.signature();
|
||||
bool compatible = false;
|
||||
|
||||
// Static fields may have references to java.lang.Class
|
||||
if (fd->field_type() == T_OBJECT) {
|
||||
oop oop = cur_oop->obj_field(fd->offset());
|
||||
if (oop != nullptr && oop->is_instance() && InstanceKlass::cast(oop->klass())->is_mirror_instance_klass()) {
|
||||
Klass* klass = java_lang_Class::as_Klass(oop);
|
||||
if (sig_new == sig_old) {
|
||||
if (_removed_interfaces != nullptr && _removed_interfaces->contains(sig_old) && fd->field_type() == T_OBJECT && result.field_type() == T_OBJECT) {
|
||||
compatible = is_compatible(old_oop, result.offset(), sig_new);
|
||||
} else {
|
||||
compatible = true;
|
||||
}
|
||||
} else {
|
||||
if (fd->field_type() == T_OBJECT && result.field_type() == T_OBJECT) {
|
||||
compatible = is_compatible(old_oop, result.offset(), sig_new);
|
||||
}
|
||||
}
|
||||
|
||||
if (compatible) {
|
||||
log_trace(redefine, class, obsolete, metadata)("Copying static field value for field %s old_offset=%d new_offset=%d",
|
||||
fd->name()->as_C_string(), result.offset(), fd->offset());
|
||||
memcpy(cur_oop->field_addr<HeapWord>(fd->offset()),
|
||||
old_oop->field_addr<HeapWord>(result.offset()),
|
||||
type2aelembytes(fd->field_type()));
|
||||
|
||||
// Static fields may have references to java.lang.Class
|
||||
if (fd->field_type() == T_OBJECT) {
|
||||
oop oop = cur_oop->obj_field(fd->offset());
|
||||
if (oop != nullptr && oop->is_instance() && InstanceKlass::cast(oop->klass())->is_mirror_instance_klass()) {
|
||||
Klass *klass = java_lang_Class::as_Klass(oop);
|
||||
if (klass != nullptr && klass->is_instance_klass()) {
|
||||
assert(oop == InstanceKlass::cast(klass)->java_mirror(), "just checking");
|
||||
if (klass->new_version() != nullptr) {
|
||||
@@ -233,10 +279,36 @@ class FieldCopier : public FieldClosure {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_trace(redefine,class, obsolete, metadata)("Skipping incompatible static field %s, old_signature=%s, new_signature=%s",
|
||||
fd->name()->as_C_string(), sig_old->as_C_string(), sig_new->as_C_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class FieldCompatibilityChecker : public FieldClosure {
|
||||
private:
|
||||
VM_EnhancedRedefineClasses::SymbolSet* _removed_interfaces;
|
||||
GrowableArray<int>* _compat_check_field_offsets;
|
||||
public:
|
||||
FieldCompatibilityChecker(VM_EnhancedRedefineClasses::SymbolSet* removed_interfaces)
|
||||
: _removed_interfaces(removed_interfaces), _compat_check_field_offsets(nullptr) {}
|
||||
|
||||
void do_field(fieldDescriptor* fd) {
|
||||
Symbol *sig_new = fd->signature();
|
||||
if (_removed_interfaces->contains(fd->signature())) {
|
||||
if (_compat_check_field_offsets == nullptr) {
|
||||
_compat_check_field_offsets = new (mtInternal) GrowableArray<int>(2, mtInternal);
|
||||
}
|
||||
_compat_check_field_offsets->append(fd->offset());
|
||||
}
|
||||
}
|
||||
|
||||
GrowableArray<int>* compat_check_field_offsets() {
|
||||
return _compat_check_field_offsets;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: review...
|
||||
void VM_EnhancedRedefineClasses::mark_as_scavengable(nmethod* nm) {
|
||||
@@ -442,15 +514,23 @@ class ChangePointersOopClosure : public BasicOopIterateClosure {
|
||||
// - otherwise set the _needs_instance_update flag, we need to do full GC
|
||||
// and reshuffle object positions durring mark&sweep
|
||||
class ChangePointersObjectClosure : public ObjectClosure {
|
||||
private:
|
||||
|
||||
private:
|
||||
OopIterateClosure *_closure;
|
||||
VM_EnhancedRedefineClasses::SymbolSet* _removed_interfaces;
|
||||
DcevmSharedGC* _dcevm_shared_gc;
|
||||
bool _needs_instance_update;
|
||||
oop _tmp_obj;
|
||||
size_t _tmp_obj_size;
|
||||
|
||||
public:
|
||||
ChangePointersObjectClosure(OopIterateClosure *closure) : _closure(closure), _needs_instance_update(false), _tmp_obj(nullptr), _tmp_obj_size(0) {}
|
||||
ChangePointersObjectClosure(OopIterateClosure *closure, VM_EnhancedRedefineClasses::SymbolSet* removed_interfaces)
|
||||
: _closure(closure), _removed_interfaces(removed_interfaces), _needs_instance_update(false), _tmp_obj(nullptr), _tmp_obj_size(0) {
|
||||
_dcevm_shared_gc = new DcevmSharedGC();
|
||||
}
|
||||
|
||||
~ChangePointersObjectClosure() {
|
||||
delete _dcevm_shared_gc;
|
||||
}
|
||||
|
||||
bool needs_instance_update() {
|
||||
return _needs_instance_update;
|
||||
@@ -465,6 +545,36 @@ public:
|
||||
Copy::aligned_disjoint_words(cast_from_oop<HeapWord*>(o), cast_from_oop<HeapWord*>(_tmp_obj), size);
|
||||
}
|
||||
|
||||
void do_compat_check_field_offsets(oop obj) {
|
||||
// Non-redefined class may store fields of redefined types
|
||||
// check field-level compatibility to avoid invalid accesses.
|
||||
GrowableArray<int>* fields = obj->klass()->compat_check_field_offsets();
|
||||
if (fields == nullptr) {
|
||||
FieldCompatibilityChecker fld_compat_check(_removed_interfaces);
|
||||
InstanceKlass::cast(obj->klass())->do_nonstatic_fields(&fld_compat_check);
|
||||
fields = fld_compat_check.compat_check_field_offsets();
|
||||
if (fields != nullptr) {
|
||||
GrowableArray<int>* old = obj->klass()->set_compat_check_field_offsets(fields);
|
||||
if (old != nullptr) {
|
||||
delete fields;
|
||||
fields = old;
|
||||
}
|
||||
} else {
|
||||
fields = reinterpret_cast<GrowableArray<int>*>(-1);
|
||||
obj->klass()->set_compat_check_field_offsets(fields);
|
||||
}
|
||||
}
|
||||
if (reinterpret_cast<intptr_t>(fields) != -1) {
|
||||
for (int i = 0; i < fields->length(); i++) {
|
||||
int fld_offset = fields->at(i);
|
||||
oop fld_val = obj->obj_field(fld_offset);
|
||||
if (fld_val != nullptr && !_dcevm_shared_gc->is_compatible(obj, fld_offset, fld_val)) {
|
||||
obj->obj_field_put(fld_offset, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void do_object(oop obj) {
|
||||
if (obj->is_instance() && InstanceKlass::cast(obj->klass())->is_mirror_instance_klass()) {
|
||||
// static fields may have references to old java.lang.Class instances, update them
|
||||
@@ -473,6 +583,9 @@ public:
|
||||
//instanceMirrorKlass::oop_fields_iterate(obj, _closure);
|
||||
} else {
|
||||
obj->oop_iterate(_closure);
|
||||
if (_removed_interfaces != nullptr && obj->klass()->is_instance_klass() && obj->klass()->new_version() == nullptr) {
|
||||
do_compat_check_field_offsets(obj);
|
||||
}
|
||||
}
|
||||
|
||||
if (obj->klass()->new_version() != nullptr) {
|
||||
@@ -482,6 +595,7 @@ public:
|
||||
if (obj->size() - obj->size_given_klass(new_klass) != 0) {
|
||||
// We need an instance update => set back to old klass
|
||||
_needs_instance_update = true;
|
||||
_dcevm_shared_gc->update_fields_in_old(obj, new_klass->update_information());
|
||||
} else {
|
||||
// Either new size is bigger or gap is too small to be filled
|
||||
oop src = obj;
|
||||
@@ -492,7 +606,7 @@ public:
|
||||
src->set_klass(obj->klass()->new_version());
|
||||
// FIXME: instance updates...
|
||||
//guarantee(false, "instance updates!");
|
||||
DcevmSharedGC::update_fields(obj, src, new_klass->update_information());
|
||||
_dcevm_shared_gc->update_fields(obj, src, new_klass->update_information(), true);
|
||||
}
|
||||
} else {
|
||||
obj->set_klass(obj->klass()->new_version());
|
||||
@@ -505,14 +619,15 @@ class ChangePointersObjectTask : public WorkerTask {
|
||||
private:
|
||||
ChangePointersOopClosure<StoreBarrier>* _cl;
|
||||
ParallelObjectIterator* _poi;
|
||||
VM_EnhancedRedefineClasses::SymbolSet* _removed_interfaces;
|
||||
bool _needs_instance_update;
|
||||
public:
|
||||
ChangePointersObjectTask(ChangePointersOopClosure<StoreBarrier>* cl, ParallelObjectIterator* poi) : WorkerTask("IterateObject Closure"),
|
||||
_cl(cl), _poi(poi), _needs_instance_update(false) { }
|
||||
ChangePointersObjectTask(ChangePointersOopClosure<StoreBarrier>* cl, ParallelObjectIterator* poi, VM_EnhancedRedefineClasses::SymbolSet* removed_interfaces)
|
||||
: WorkerTask("IterateObject Closure"), _cl(cl), _poi(poi), _removed_interfaces(removed_interfaces), _needs_instance_update(false) { }
|
||||
|
||||
virtual void work(uint worker_id) {
|
||||
HandleMark hm(Thread::current()); // make sure any handles created are deleted
|
||||
ChangePointersObjectClosure objectClosure(_cl);
|
||||
ChangePointersObjectClosure objectClosure(_cl, _removed_interfaces);
|
||||
_poi->object_iterate(&objectClosure, worker_id);
|
||||
_needs_instance_update = _needs_instance_update || objectClosure.needs_instance_update();
|
||||
}
|
||||
@@ -521,6 +636,19 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ClearCompatCheckFields : public KlassClosure {
|
||||
public:
|
||||
ClearCompatCheckFields() {}
|
||||
void do_klass(Klass* k) {
|
||||
if (k->compat_check_field_offsets() != nullptr) {
|
||||
if (reinterpret_cast<intptr_t>(k->compat_check_field_offsets()) != -1) {
|
||||
delete k->compat_check_field_offsets();
|
||||
}
|
||||
k->clear_compat_check_field_offsets();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Main transformation method - runs in VM thread.
|
||||
// - for each scratch class call redefine_single_class
|
||||
// - clear code cache (flush_dependent_code)
|
||||
@@ -552,6 +680,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
|
||||
Universe::set_inside_redefinition(true);
|
||||
DcevmSharedGC::create_static_instance();
|
||||
|
||||
// Mark methods seen on stack and everywhere else so old methods are not
|
||||
// cleaned up if they're on the stack.
|
||||
@@ -562,6 +691,15 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// before the stack walk again.
|
||||
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
Klass *new_class = _new_classes->at(i);
|
||||
// MagicAccessorImpl new_class is set in load_new_class_versions
|
||||
if (new_class->old_version() != vmClasses::reflect_MagicAccessorImpl_klass() || new_class->old_version()->new_version() == nullptr) {
|
||||
new_class->old_version()->set_new_version(new_class);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
Klass* new_class = _new_classes->at(i);
|
||||
redefine_single_class(current, _new_classes->at(i));
|
||||
}
|
||||
|
||||
@@ -630,11 +768,11 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
WorkerThreads* workers = Universe::heap()->safepoint_workers();
|
||||
if (workers != nullptr && workers->active_workers() > 1) {
|
||||
ParallelObjectIterator poi(workers->active_workers());
|
||||
ChangePointersObjectTask objectTask(&oopClosure, &poi);
|
||||
ChangePointersObjectTask objectTask(&oopClosure, &poi, _removed_interfaces);
|
||||
workers->run_task(&objectTask);
|
||||
needs_instance_update = objectTask.needs_instance_update();
|
||||
} else {
|
||||
ChangePointersObjectClosure objectClosure(&oopClosure);
|
||||
ChangePointersObjectClosure objectClosure(&oopClosure, _removed_interfaces);
|
||||
Universe::heap()->object_iterate(&objectClosure);
|
||||
needs_instance_update = objectClosure.needs_instance_update();
|
||||
}
|
||||
@@ -670,7 +808,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
// Initialize the new class! Special static initialization that does not execute the
|
||||
// static constructor but copies static field values from the old class if name
|
||||
// and signature of a static field match.
|
||||
FieldCopier copier;
|
||||
FieldCopier copier(_removed_interfaces);
|
||||
cur->do_local_static_fields(&copier); // TODO (tw): What about internal static fields??
|
||||
//java_lang_Class::set_klass(old->java_mirror(), cur); // FIXME-isd (from JDK8): is that correct?
|
||||
//FIXME-isd (from JDK8): do we need this: ??? old->set_java_mirror(cur->java_mirror());
|
||||
@@ -744,6 +882,12 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
cur->clear_update_information();
|
||||
}
|
||||
|
||||
// delete compat_check_fields
|
||||
if (_removed_interfaces != nullptr) {
|
||||
ClearCompatCheckFields compat_check_fields;
|
||||
ClassLoaderDataGraph::classes_do(&compat_check_fields);
|
||||
}
|
||||
|
||||
// TODO: explain...
|
||||
LoaderConstraintTable::update_after_redefinition();
|
||||
|
||||
@@ -781,6 +925,7 @@ void VM_EnhancedRedefineClasses::doit() {
|
||||
}
|
||||
#endif
|
||||
|
||||
DcevmSharedGC::destroy_static_instance();
|
||||
Universe::set_inside_redefinition(false);
|
||||
_timer_vm_op_doit.stop();
|
||||
|
||||
@@ -807,8 +952,8 @@ void VM_EnhancedRedefineClasses::doit_epilogue() {
|
||||
_new_classes = nullptr;
|
||||
if (_affected_klasses != nullptr) {
|
||||
delete _affected_klasses;
|
||||
_affected_klasses = nullptr;
|
||||
}
|
||||
_affected_klasses = nullptr;
|
||||
|
||||
// Reset the_class_oop to null for error printing.
|
||||
_the_class_oop = nullptr;
|
||||
@@ -859,11 +1004,12 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
|
||||
_affected_klasses = new (mtInternal) GrowableArray<Klass*>(_class_count, mtInternal);
|
||||
_new_classes = new (mtInternal) GrowableArray<InstanceKlass*>(_class_count, mtInternal);
|
||||
Old2NewKlassMap old_2_new_klass_map;
|
||||
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
// Retrieve an array of all classes that need to be redefined into _affected_klasses
|
||||
jvmtiError err = find_sorted_affected_classes(true, nullptr, THREAD);
|
||||
jvmtiError err = find_sorted_affected_classes(true, nullptr, &old_2_new_klass_map, THREAD);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
return err;
|
||||
}
|
||||
@@ -871,9 +1017,10 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
_max_redefinition_flags = Klass::NoRedefinition;
|
||||
|
||||
GrowableArray<Klass*>* prev_affected_klasses = new (mtInternal) GrowableArray<Klass*>(_class_count, mtInternal);
|
||||
GrowableArray<int> klass_redefinition_flags(_class_count, mtInternal);
|
||||
|
||||
do {
|
||||
err = load_new_class_versions_single_step(THREAD);
|
||||
err = load_new_class_versions_single_step(&old_2_new_klass_map, &klass_redefinition_flags, THREAD);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
delete prev_affected_klasses;
|
||||
return err;
|
||||
@@ -886,7 +1033,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
_affected_klasses->clear();
|
||||
}
|
||||
|
||||
err = find_sorted_affected_classes(false, prev_affected_klasses, THREAD);
|
||||
err = find_sorted_affected_classes(false, prev_affected_klasses, &old_2_new_klass_map, THREAD);
|
||||
if (err != JVMTI_ERROR_NONE) {
|
||||
delete prev_affected_klasses;
|
||||
return err;
|
||||
@@ -896,12 +1043,21 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
delete _affected_klasses;
|
||||
_affected_klasses = prev_affected_klasses;
|
||||
|
||||
// Calculate instance update information after all new classes are resolved
|
||||
for (int i = 0; i < _new_classes->length(); i++) {
|
||||
int redefinition_flags = klass_redefinition_flags.at(i);
|
||||
if ((redefinition_flags & Klass::ModifyInstances) != 0) {
|
||||
Klass *new_class = _new_classes->at(i);
|
||||
calculate_instance_update_information(new_class);
|
||||
}
|
||||
}
|
||||
|
||||
// Link and verify new classes _after_ all classes have been updated in the system dictionary!
|
||||
for (int i = 0; i < _affected_klasses->length(); i++) {
|
||||
Klass* the_class = _affected_klasses->at(i);
|
||||
if (the_class != nullptr) {
|
||||
assert (the_class->new_version() != nullptr, "new version must be present");
|
||||
InstanceKlass *new_class(InstanceKlass::cast(the_class->new_version()));
|
||||
assert (old_2_new_klass_map.contains(the_class), "new version must be present");
|
||||
InstanceKlass *new_class(InstanceKlass::cast(*old_2_new_klass_map.get(the_class)));
|
||||
new_class->link_class(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
Symbol *ex_name = PENDING_EXCEPTION->klass()->name();
|
||||
@@ -918,7 +1074,8 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions(TRAPS) {
|
||||
return JVMTI_ERROR_NONE;
|
||||
}
|
||||
|
||||
jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS) {
|
||||
jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(Old2NewKlassMap* old_2_new_klass_map,
|
||||
GrowableArray<int>* klass_redefinition_flags, TRAPS) {
|
||||
|
||||
// thread local state - used to transfer class_being_redefined object to SystemDictonery::resolve_from_stream
|
||||
JvmtiThreadState *state = JvmtiThreadState::state_for(JavaThread::current());
|
||||
@@ -933,10 +1090,16 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
HandleMark hm(THREAD);
|
||||
InstanceKlass* the_class = InstanceKlass::cast(_affected_klasses->at(i));
|
||||
|
||||
if (the_class->new_version() != nullptr) {
|
||||
if (old_2_new_klass_map->contains(the_class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (the_class->new_version() != nullptr) {
|
||||
// the_class was redefined and now has a new version
|
||||
log_trace(redefine, class, load)("Class redefinition detected: '%s' has a new version.", the_class->name()->as_C_string());
|
||||
_affected_klasses->at_put(i, the_class);
|
||||
}
|
||||
|
||||
Symbol* the_class_sym = the_class->name();
|
||||
|
||||
// Ensure class is linked before redefine
|
||||
@@ -1014,6 +1177,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
the_class_loader,
|
||||
cl_info,
|
||||
the_class,
|
||||
old_2_new_klass_map,
|
||||
THREAD);
|
||||
|
||||
if (!HAS_PENDING_EXCEPTION) {
|
||||
@@ -1045,6 +1209,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
the_class_loader,
|
||||
cl_info,
|
||||
the_class,
|
||||
old_2_new_klass_map,
|
||||
THREAD);
|
||||
}
|
||||
// Clear class_being_redefined just to be sure.
|
||||
@@ -1083,9 +1248,17 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
the_class->clear_redefinition_flag(Klass::PrimaryRedefine);
|
||||
|
||||
InstanceKlass* new_class = k;
|
||||
the_class->set_new_version(new_class);
|
||||
old_2_new_klass_map->put(the_class, new_class);
|
||||
_new_classes->append(new_class);
|
||||
|
||||
// If MagicAccessorImpl is being redefined, we must set new_version,
|
||||
// because class loading may trigger Reflection::verify_class_access,
|
||||
// which performs superclass checks. This can occur when a subclass
|
||||
// of MagicAccessorImpl is being loaded as part of the same redefinition run.
|
||||
if (the_class == vmClasses::reflect_MagicAccessorImpl_klass()) {
|
||||
the_class->set_new_version(new_class);
|
||||
}
|
||||
|
||||
if (the_class == vmClasses::Reference_klass()) {
|
||||
// must set offset+count to skip field "referent". Look at InstanceRefKlass::update_nonstatic_oop_maps
|
||||
OopMapBlock* old_map = the_class->start_of_nonstatic_oop_maps();
|
||||
@@ -1102,7 +1275,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
if (not_changed) {
|
||||
redefinition_flags = Klass::NoRedefinition;
|
||||
} else {
|
||||
redefinition_flags = calculate_redefinition_flags(new_class);
|
||||
redefinition_flags = calculate_redefinition_flags(new_class, old_2_new_klass_map);
|
||||
if (redefinition_flags >= Klass::RemoveSuperType) {
|
||||
return JVMTI_ERROR_UNSUPPORTED_REDEFINITION_HIERARCHY_CHANGED;
|
||||
}
|
||||
@@ -1120,9 +1293,7 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
|
||||
_max_redefinition_flags = _max_redefinition_flags | redefinition_flags;
|
||||
|
||||
if ((redefinition_flags & Klass::ModifyInstances) != 0) {
|
||||
calculate_instance_update_information(new_class);
|
||||
}
|
||||
klass_redefinition_flags->append(redefinition_flags);
|
||||
|
||||
if (the_class == vmClasses::Object_klass()) {
|
||||
_object_klass_redefined = true;
|
||||
@@ -1136,7 +1307,8 @@ jvmtiError VM_EnhancedRedefineClasses::load_new_class_versions_single_step(TRAPS
|
||||
}
|
||||
|
||||
// Calculated the difference between new and old class (field change, method change, supertype change, ...).
|
||||
int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class) {
|
||||
int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_class,
|
||||
Old2NewKlassMap* old_2_new_klass_map) {
|
||||
int result = Klass::NoRedefinition;
|
||||
log_debug(redefine, class, load)("Comparing different class versions of class %s",new_class->name()->as_C_string());
|
||||
|
||||
@@ -1157,7 +1329,8 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
// Super class changed
|
||||
Klass* cur_klass = the_class->super();
|
||||
while (cur_klass != nullptr) {
|
||||
if (!new_class->is_subclass_of(cur_klass->newest_version())) {
|
||||
Klass** new_cur_klass = old_2_new_klass_map->get(cur_klass);
|
||||
if (!new_class->is_subclass_of(new_cur_klass != nullptr ? *new_cur_klass : cur_klass)) {
|
||||
log_info(redefine, class, load)("removed super class %s", cur_klass->name()->as_C_string());
|
||||
result = result | Klass::RemoveSuperType | Klass::ModifyInstances | Klass::ModifyClass;
|
||||
}
|
||||
@@ -1167,7 +1340,7 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
cur_klass = new_class->super();
|
||||
while (cur_klass != nullptr) {
|
||||
if (!the_class->is_subclass_of(cur_klass->is_redefining() ? cur_klass->old_version() : cur_klass)) {
|
||||
log_info(redefine, class, load)("added super class %s", cur_klass->name()->as_C_string());
|
||||
log_debug(redefine, class, load)("added super class %s", cur_klass->name()->as_C_string());
|
||||
result = result | Klass::ModifyClass | Klass::ModifyInstances;
|
||||
}
|
||||
cur_klass = cur_klass->super();
|
||||
@@ -1180,18 +1353,23 @@ int VM_EnhancedRedefineClasses::calculate_redefinition_flags(InstanceKlass* new_
|
||||
Array<InstanceKlass*>* old_interfaces = the_class->transitive_interfaces();
|
||||
for (i = 0; i < old_interfaces->length(); i++) {
|
||||
InstanceKlass* old_interface = InstanceKlass::cast(old_interfaces->at(i));
|
||||
if (!new_class->implements_interface_any_version(old_interface)) {
|
||||
result = result | Klass::RemoveSuperType | Klass::ModifyClass;
|
||||
log_info(redefine, class, load)("removed interface %s", old_interface->name()->as_C_string());
|
||||
if (!new_class->implements_interface_dcevm(old_interface, old_2_new_klass_map)) {
|
||||
result = result | Klass::RemoveInterface | Klass::ModifyClass;
|
||||
log_debug(redefine, class, load)("removed interface %s", old_interface->name()->as_C_string());
|
||||
if (_removed_interfaces == nullptr) {
|
||||
_removed_interfaces = new (mtInternal) SymbolSet();
|
||||
}
|
||||
Symbol* interf_sign_sym = SymbolTable::new_symbol(old_interface->signature_name());
|
||||
_removed_interfaces->put(interf_sign_sym, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Interfaces added?
|
||||
Array<InstanceKlass*>* new_interfaces = new_class->transitive_interfaces();
|
||||
for (i = 0; i<new_interfaces->length(); i++) {
|
||||
if (!the_class->implements_interface_any_version(new_interfaces->at(i))) {
|
||||
if (!the_class->implements_interface_dcevm(new_interfaces->at(i), old_2_new_klass_map)) {
|
||||
result = result | Klass::ModifyClass;
|
||||
log_info(redefine, class, load)("added interface %s", new_interfaces->at(i)->name()->as_C_string());
|
||||
log_debug(redefine, class, load)("added interface %s", new_interfaces->at(i)->name()->as_C_string());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1467,7 +1645,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_class_bytes(InstanceKlass* the_class
|
||||
|
||||
// Calculate difference between non static fields of old and new class and store the info into new class:
|
||||
// instanceKlass->store_update_information
|
||||
// instanceKlass->copy_backwards
|
||||
// instanceKlass->copying_backwards
|
||||
void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* new_version) {
|
||||
|
||||
class CalculateFieldUpdates : public FieldClosure {
|
||||
@@ -1475,17 +1653,24 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
private:
|
||||
InstanceKlass* _old_ik;
|
||||
GrowableArray<int> _update_info;
|
||||
VM_EnhancedRedefineClasses::SymbolSet* _removed_interfaces;
|
||||
int _position;
|
||||
bool _copy_backwards;
|
||||
bool _copying_backwards;
|
||||
bool _compat_check;
|
||||
|
||||
public:
|
||||
|
||||
bool does_copy_backwards() {
|
||||
return _copy_backwards;
|
||||
bool is_copying_backwards() {
|
||||
return _copying_backwards;
|
||||
}
|
||||
|
||||
CalculateFieldUpdates(InstanceKlass* old_ik) :
|
||||
_old_ik(old_ik), _position(instanceOopDesc::base_offset_in_bytes()), _copy_backwards(false) {
|
||||
bool is_compat_check() {
|
||||
return _compat_check;
|
||||
}
|
||||
|
||||
CalculateFieldUpdates(InstanceKlass* old_ik, VM_EnhancedRedefineClasses::SymbolSet* removed_interfaces) :
|
||||
_old_ik(old_ik), _removed_interfaces(removed_interfaces), _position(instanceOopDesc::base_offset_in_bytes()),
|
||||
_copying_backwards(false), _compat_check() {
|
||||
_update_info.append(_position);
|
||||
_update_info.append(0);
|
||||
}
|
||||
@@ -1507,43 +1692,78 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
assert(_position == fd->offset(), "must be correct offset!");
|
||||
|
||||
InstanceKlass* holder = fd->field_holder();
|
||||
InstanceKlass* maybe_old_holder = holder->is_redefining() ? InstanceKlass::cast(holder->old_version()) : holder;
|
||||
if (fd->index() < holder->java_fields_count()) {
|
||||
fieldDescriptor old_fd;
|
||||
if (_old_ik->find_field(fd->name(), fd->signature(), false, &old_fd) != nullptr) {
|
||||
// Found field in the old class, copy
|
||||
copy(old_fd.offset(), type2aelembytes(fd->field_type()));
|
||||
|
||||
if (old_fd.offset() < fd->offset()) {
|
||||
_copy_backwards = true;
|
||||
bool found = false;
|
||||
if (_old_ik->find_field(fd->name(), fd->signature(), false, &old_fd) != nullptr) {
|
||||
found = true;
|
||||
} else {
|
||||
if (maybe_old_holder->find_local_field_by_name(fd->name(), &old_fd) && !old_fd.is_static()) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
// Found field in the old class, copy
|
||||
Symbol *sig_new = fd->signature();
|
||||
Symbol *sig_old = old_fd.signature();
|
||||
int compat_flag;
|
||||
|
||||
if (sig_new == sig_old) {
|
||||
if (_removed_interfaces != nullptr && _removed_interfaces->contains(sig_old) && fd->field_type() == T_OBJECT && old_fd.field_type() == T_OBJECT) {
|
||||
compat_flag = 0;
|
||||
_compat_check = true;
|
||||
} else {
|
||||
compat_flag = 1;
|
||||
}
|
||||
} else {
|
||||
if (fd->field_type() == T_OBJECT && old_fd.field_type() == T_OBJECT) {
|
||||
compat_flag = 0;
|
||||
_compat_check = true;
|
||||
} else {
|
||||
compat_flag = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Transfer special flags
|
||||
fd->set_is_field_modification_watched(old_fd.is_field_modification_watched());
|
||||
fd->set_is_field_access_watched(old_fd.is_field_access_watched());
|
||||
if (compat_flag != -1) {
|
||||
copy(old_fd.offset(), type2aelembytes(fd->field_type()), (compat_flag == 0));
|
||||
|
||||
if (old_fd.offset() < fd->offset()) {
|
||||
_copying_backwards = true;
|
||||
}
|
||||
|
||||
// Transfer special flags
|
||||
fd->set_is_field_modification_watched(old_fd.is_field_modification_watched());
|
||||
fd->set_is_field_access_watched(old_fd.is_field_access_watched());
|
||||
} else {
|
||||
fill(type2aelembytes(fd->field_type()));
|
||||
}
|
||||
} else {
|
||||
// New field, fill
|
||||
fill(type2aelembytes(fd->field_type()));
|
||||
}
|
||||
} else {
|
||||
FieldInfo internal_field = holder->field(fd->index());
|
||||
InstanceKlass* maybe_old_klass = holder->is_redefining() ? InstanceKlass::cast(holder->old_version()) : holder;
|
||||
int java_fields_count = maybe_old_klass->java_fields_count();
|
||||
|
||||
int java_fields_count = maybe_old_holder->java_fields_count();
|
||||
int num_injected;
|
||||
const InjectedField* const injected = JavaClasses::get_injected(maybe_old_klass->name(), &num_injected);
|
||||
for (int i = java_fields_count; i < java_fields_count+num_injected; i++) {
|
||||
FieldInfo maybe_old_field = maybe_old_klass->field(i);
|
||||
const InjectedField *const injected = JavaClasses::get_injected(maybe_old_holder->name(), &num_injected);
|
||||
for (int i = java_fields_count; i < java_fields_count + num_injected; i++) {
|
||||
FieldInfo maybe_old_field = maybe_old_holder->field(i);
|
||||
if (maybe_old_field.field_flags().is_injected() &&
|
||||
internal_field.field_flags().is_injected() &&
|
||||
maybe_old_field.lookup_symbol(maybe_old_field.name_index()) == internal_field.lookup_symbol(internal_field.name_index())) {
|
||||
copy(maybe_old_field.offset(), type2aelembytes(Signature::basic_type(internal_field.signature_injected_dcevm())));
|
||||
copy(maybe_old_field.offset(), type2aelembytes(Signature::basic_type(internal_field.signature_injected_dcevm())), false);
|
||||
if (maybe_old_field.offset() < internal_field.offset()) {
|
||||
_copy_backwards = true;
|
||||
_copying_backwards = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void fill(int size) {
|
||||
@@ -1555,19 +1775,24 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
_position += size;
|
||||
}
|
||||
|
||||
void copy(int offset, int size) {
|
||||
int prev_end = -1;
|
||||
if (_update_info.length() > 0 && _update_info.at(_update_info.length() - 1) > 0) {
|
||||
prev_end = _update_info.at(_update_info.length() - 2) + _update_info.at(_update_info.length() - 1);
|
||||
}
|
||||
void copy(int offset, int size, bool needs_compat_check) {
|
||||
if (!needs_compat_check && _update_info.length() >= 2) {
|
||||
int last_size = _update_info.at(_update_info.length() - 2);
|
||||
int last_offset = _update_info.at(_update_info.length() - 1);
|
||||
|
||||
if (prev_end == offset) {
|
||||
(*_update_info.adr_at(_update_info.length() - 2)) += size;
|
||||
} else {
|
||||
_update_info.append(size);
|
||||
_update_info.append(offset);
|
||||
if (last_offset > 0 && (last_size & DcevmSharedGC::UpdateInfoCompatFlag) == 0) {
|
||||
int last_len = last_size & DcevmSharedGC::UpdateInfoLengthMask;
|
||||
int prev_end = last_offset + last_len;
|
||||
if (prev_end == offset) {
|
||||
(*_update_info.adr_at(_update_info.length() - 2)) += size;
|
||||
_position += size;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int tagged_size = needs_compat_check ? (size | DcevmSharedGC::UpdateInfoCompatFlag) : size;
|
||||
_update_info.append(tagged_size);
|
||||
_update_info.append(offset);
|
||||
_position += size;
|
||||
}
|
||||
};
|
||||
@@ -1576,15 +1801,16 @@ void VM_EnhancedRedefineClasses::calculate_instance_update_information(Klass* ne
|
||||
InstanceKlass* old_ik = InstanceKlass::cast(new_version->old_version());
|
||||
|
||||
//
|
||||
CalculateFieldUpdates cl(old_ik);
|
||||
CalculateFieldUpdates cl(old_ik, _removed_interfaces);
|
||||
ik->do_nonstatic_fields_dcevm(&cl);
|
||||
|
||||
GrowableArray<int> result = cl.finish();
|
||||
ik->store_update_information(result);
|
||||
ik->set_copying_backwards(cl.does_copy_backwards());
|
||||
ik->set_copying_backwards(cl.is_copying_backwards());
|
||||
|
||||
if (log_is_enabled(Trace, redefine, class, obsolete, metadata)) {
|
||||
log_trace(redefine, class, obsolete, metadata)("Instance update information for %s:", new_version->name()->as_C_string());
|
||||
if (cl.does_copy_backwards()) {
|
||||
if (cl.is_copying_backwards()) {
|
||||
log_trace(redefine, class, obsolete, metadata)("\tDoes copy backwards!");
|
||||
}
|
||||
for (int i=0; i<result.length(); i++) {
|
||||
@@ -1749,21 +1975,24 @@ u8 VM_EnhancedRedefineClasses::next_id() {
|
||||
}
|
||||
|
||||
// Clean method data for this class
|
||||
void VM_EnhancedRedefineClasses::MethodDataCleaner::do_klass(Klass* k) {
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
// Clean MethodData of this class's methods so they don't refer to
|
||||
// old methods that are no longer running.
|
||||
Array<Method*>* methods = ik->methods();
|
||||
int num_methods = methods->length();
|
||||
for (int index = 0; index < num_methods; ++index) {
|
||||
if (methods->at(index)->method_data() != nullptr) {
|
||||
methods->at(index)->method_data()->clean_weak_method_links();
|
||||
class MethodDataCleaner : public KlassClosure {
|
||||
public:
|
||||
MethodDataCleaner() {}
|
||||
void do_klass(Klass* k) {
|
||||
if (k->is_instance_klass()) {
|
||||
InstanceKlass *ik = InstanceKlass::cast(k);
|
||||
// Clean MethodData of this class's methods so they don't refer to
|
||||
// old methods that are no longer running.
|
||||
Array<Method*>* methods = ik->methods();
|
||||
int num_methods = methods->length();
|
||||
for (int index = 0; index < num_methods; ++index) {
|
||||
if (methods->at(index)->method_data() != nullptr) {
|
||||
methods->at(index)->method_data()->clean_weak_method_links();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
void VM_EnhancedRedefineClasses::update_jmethod_ids(Thread *current) {
|
||||
for (int j = 0; j < _matching_methods_length; ++j) {
|
||||
@@ -2285,7 +2514,10 @@ class AffectedKlassClosure : public KlassClosure {
|
||||
|
||||
// Find all affected classes by current redefinition (either because of redefine, class hierarchy or interface change).
|
||||
// Affected classes are stored in _affected_klasses and parent classes always precedes child class.
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(bool do_initial_mark, GrowableArray<Klass*>* prev_affected_klasses, TRAPS) {
|
||||
jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(bool do_initial_mark,
|
||||
GrowableArray<Klass*>* prev_affected_klasses,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS) {
|
||||
if (do_initial_mark) {
|
||||
for (int i = 0; i < _class_count; i++) {
|
||||
InstanceKlass* klass = get_ik(_class_defs[i].klass);
|
||||
@@ -2315,7 +2547,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(bool do_init
|
||||
log_trace(redefine, class, load)("%d classes affected", _affected_klasses->length());
|
||||
|
||||
// Sort the affected klasses such that a supertype is always on a smaller array index than its subtype.
|
||||
jvmtiError result = do_topological_class_sorting(THREAD);
|
||||
jvmtiError result = do_topological_class_sorting(old_2_new_klass_map, THREAD);
|
||||
|
||||
if (log_is_enabled(Trace, redefine, class, load)) {
|
||||
log_trace(redefine, class, load)("redefine order:");
|
||||
@@ -2323,7 +2555,7 @@ jvmtiError VM_EnhancedRedefineClasses::find_sorted_affected_classes(bool do_init
|
||||
log_trace(redefine, class, load)("%s", _affected_klasses->at(i)->name()->as_C_string());
|
||||
}
|
||||
}
|
||||
return JVMTI_ERROR_NONE;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Pairs of class dependencies (for topological sort)
|
||||
@@ -2344,7 +2576,7 @@ static bool match_second(void* value, KlassPair elem) {
|
||||
// Affected flag is cleared (clear_redefinition_flag(Klass::MarkedAsAffected))
|
||||
// For each dependency create a KlassPair instance. Finally, affected classes (_affected_klasses) are sorted according to pairs.
|
||||
// TODO - the class file is potentially parsed multiple times - introduce a cache?
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(Old2NewKlassMap* old_2_new_klass_map, TRAPS) {
|
||||
ResourceMark mark(THREAD);
|
||||
|
||||
// Collect dependencies
|
||||
@@ -2366,9 +2598,21 @@ jvmtiError VM_EnhancedRedefineClasses::do_topological_class_sorting(TRAPS) {
|
||||
klass->class_loader_data(),
|
||||
&cl_info,
|
||||
ClassFileParser::INTERNAL, // publicity level
|
||||
true,
|
||||
old_2_new_klass_map,
|
||||
THREAD);
|
||||
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
Symbol* ex_name = PENDING_EXCEPTION->klass()->name();
|
||||
oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
|
||||
if (message != nullptr) {
|
||||
char* ex_msg = java_lang_String::as_utf8_string(message);
|
||||
log_info(redefine, class, load, exceptions)("parse_class exception: '%s %s'", ex_name->as_C_string(), ex_msg);
|
||||
} else {
|
||||
log_info(redefine, class, load, exceptions)("parse_class exception: '%s'", ex_name->as_C_string());
|
||||
}
|
||||
return JVMTI_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
const Klass* super_klass = parser.super_klass();
|
||||
if (super_klass != nullptr && _affected_klasses->contains((Klass*) super_klass)) {
|
||||
links.append(KlassPair(super_klass, klass));
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "gc/shared/gcVMOperations.hpp"
|
||||
#include "../../../java.base/unix/native/include/jni_md.h"
|
||||
#include "classfile/classFileParserDCEVM.hpp"
|
||||
|
||||
//
|
||||
// Enhanced class redefiner.
|
||||
@@ -46,7 +47,11 @@
|
||||
// - doit() - main redefition, adjust existing objects on the heap, clear caches
|
||||
// - doit_epilogue() - cleanup
|
||||
class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
private:
|
||||
public:
|
||||
static unsigned int sym_hash (Symbol* const& s) { return (int)(uintptr_t)s; }
|
||||
static bool sym_equals(Symbol* const& a, Symbol* const& b) { return a == b; }
|
||||
typedef ResourceHashtable<Symbol*, char, 37, AnyObj::C_HEAP, mtInternal, &sym_hash, &sym_equals> SymbolSet;
|
||||
private:
|
||||
// These static fields are needed by ClassLoaderDataGraph::classes_do()
|
||||
// facility and the AdjustCpoolCacheAndVtable helper:
|
||||
static Array<Method*>* _old_methods;
|
||||
@@ -70,7 +75,7 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// RetransformClasses. Indicate which.
|
||||
JvmtiClassLoadKind _class_load_kind;
|
||||
|
||||
GrowableArray<InstanceKlass*>* _new_classes;
|
||||
GrowableArray<InstanceKlass*>* _new_classes;
|
||||
jvmtiError _res;
|
||||
|
||||
// Set if any of the InstanceKlasses have entries in the ResolvedMethodTable
|
||||
@@ -89,6 +94,8 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
int _max_redefinition_flags;
|
||||
|
||||
SymbolSet* _removed_interfaces;
|
||||
|
||||
// Performance measurement support. These timers do not cover all
|
||||
// the work done for JVM/TI RedefineClasses() but they do cover
|
||||
// the heavy lifting.
|
||||
@@ -112,16 +119,19 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
//
|
||||
// The result is sotred in _affected_klasses(old definitions) and _new_classes(new definitions) arrays.
|
||||
jvmtiError load_new_class_versions(TRAPS);
|
||||
jvmtiError load_new_class_versions_single_step(TRAPS);
|
||||
jvmtiError load_new_class_versions_single_step(Old2NewKlassMap* old_2_new_klass_map, GrowableArray<int>* klass_redefinition_flags, TRAPS);
|
||||
|
||||
// Searches for all affected classes and performs a sorting such tha
|
||||
// a supertype is always before a subtype.
|
||||
jvmtiError find_sorted_affected_classes(bool do_initial_mark, GrowableArray<Klass*>* prev_affected_klasses, TRAPS);
|
||||
jvmtiError find_sorted_affected_classes(bool do_initial_mark,
|
||||
GrowableArray<Klass*>* prev_affected_klasses,
|
||||
Old2NewKlassMap* old_2_new_klass_map,
|
||||
TRAPS);
|
||||
|
||||
jvmtiError do_topological_class_sorting(TRAPS);
|
||||
jvmtiError do_topological_class_sorting(Old2NewKlassMap* old_2_new_klass_map, TRAPS);
|
||||
|
||||
jvmtiError find_class_bytes(InstanceKlass* the_class, const unsigned char **class_bytes, jint *class_byte_count, jboolean *not_changed);
|
||||
int calculate_redefinition_flags(InstanceKlass* new_class);
|
||||
int calculate_redefinition_flags(InstanceKlass* new_class, Old2NewKlassMap* old_2_new_klass_map);
|
||||
void calculate_instance_update_information(Klass* new_version);
|
||||
|
||||
void rollback();
|
||||
@@ -149,7 +159,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
// and in all direct and indirect subclasses.
|
||||
void increment_class_counter(Thread* current, InstanceKlass *ik);
|
||||
|
||||
|
||||
void flush_dependent_code();
|
||||
|
||||
u8 next_id();
|
||||
@@ -158,14 +167,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
|
||||
static void dump_methods();
|
||||
|
||||
// Check that there are no old or obsolete methods
|
||||
class CheckClass : public KlassClosure {
|
||||
Thread* _thread;
|
||||
public:
|
||||
CheckClass(Thread* t) : _thread(t) {}
|
||||
void do_klass(Klass* k);
|
||||
};
|
||||
|
||||
// Unevolving classes may point to methods of the_class directly
|
||||
// from their constant pool caches, itables, and/or vtables. We
|
||||
// use the ClassLoaderDataGraph::classes_do() facility and this helper
|
||||
@@ -176,13 +177,6 @@ class VM_EnhancedRedefineClasses: public VM_GC_Operation {
|
||||
ClearCpoolCacheAndUnpatch(Thread* t) : _thread(t) {}
|
||||
void do_klass(Klass* k);
|
||||
};
|
||||
|
||||
// Clean MethodData out
|
||||
class MethodDataCleaner : public KlassClosure {
|
||||
public:
|
||||
MethodDataCleaner() {}
|
||||
void do_klass(Klass* k);
|
||||
};
|
||||
public:
|
||||
VM_EnhancedRedefineClasses(jint class_count,
|
||||
const jvmtiClassDefinition *class_defs,
|
||||
|
||||
@@ -91,6 +91,8 @@
|
||||
// FIXLATER: hook into JvmtiTrace
|
||||
#define TraceJVMTICalls false
|
||||
|
||||
static volatile int _active_redefinitions = 0;
|
||||
|
||||
JvmtiEnv::JvmtiEnv(jint version) : JvmtiEnvBase(version) {
|
||||
}
|
||||
|
||||
@@ -487,10 +489,14 @@ JvmtiEnv::RetransformClasses(jint class_count, const jclass* classes) {
|
||||
if (AllowEnhancedClassRedefinition) {
|
||||
// MutexLocker sd_mutex(EnhancedRedefineClasses_lock, Monitor::_no_safepoint_check_flag);
|
||||
// Stop compilation to avoid compilator race condition (crashes) with advanced redefinition
|
||||
Atomic::add(&_active_redefinitions, 1);
|
||||
CompileBroker::stopCompilationBeforeEnhancedRedefinition();
|
||||
VM_EnhancedRedefineClasses op(class_count, class_definitions, jvmti_class_load_kind_retransform);
|
||||
VMThread::execute(&op);
|
||||
CompileBroker::releaseCompilationAfterEnhancedRedefinition();
|
||||
Atomic::sub(&_active_redefinitions, 1);
|
||||
if (_active_redefinitions == 0) {
|
||||
CompileBroker::releaseCompilationAfterEnhancedRedefinition();
|
||||
}
|
||||
op_id = op.id();
|
||||
error = (op.check_error());
|
||||
} else {
|
||||
|
||||
@@ -1400,7 +1400,7 @@ jvmtiError VM_RedefineClasses::load_new_class_versions() {
|
||||
the_class->name(),
|
||||
the_class->class_loader_data(),
|
||||
cl_info,
|
||||
false,
|
||||
nullptr,
|
||||
THREAD);
|
||||
|
||||
// Clear class_being_redefined just to be sure.
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.nio.file.WatchEvent;
|
||||
import java.nio.file.WatchKey;
|
||||
import java.nio.file.WatchService;
|
||||
import java.nio.file.spi.FileSystemProvider;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
@@ -718,23 +719,7 @@ class UnixPath implements Path {
|
||||
|
||||
@Override
|
||||
public int compareTo(Path other) {
|
||||
int len1 = path.length;
|
||||
int len2 = ((UnixPath) other).path.length;
|
||||
|
||||
int n = Math.min(len1, len2);
|
||||
byte v1[] = path;
|
||||
byte v2[] = ((UnixPath) other).path;
|
||||
|
||||
int k = 0;
|
||||
while (k < n) {
|
||||
int c1 = v1[k] & 0xff;
|
||||
int c2 = v2[k] & 0xff;
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
return len1 - len2;
|
||||
return Arrays.compareUnsigned(path, ((UnixPath) other).path);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -64,6 +64,9 @@ class WindowsPath implements Path {
|
||||
// paths and has a long path prefix for all paths longer than MAX_PATH.
|
||||
private volatile WeakReference<String> pathForWin32Calls;
|
||||
|
||||
// Used for fast string comparison.
|
||||
private volatile WeakReference<byte[]> uppercasePath;
|
||||
|
||||
// offsets into name components (computed lazily)
|
||||
private volatile Integer[] offsets;
|
||||
|
||||
@@ -791,23 +794,7 @@ class WindowsPath implements Path {
|
||||
public int compareTo(Path obj) {
|
||||
if (obj == null)
|
||||
throw new NullPointerException();
|
||||
String s1 = path;
|
||||
String s2 = ((WindowsPath)obj).path;
|
||||
int n1 = s1.length();
|
||||
int n2 = s2.length();
|
||||
int min = Math.min(n1, n2);
|
||||
for (int i = 0; i < min; i++) {
|
||||
char c1 = s1.charAt(i);
|
||||
char c2 = s2.charAt(i);
|
||||
if (c1 != c2) {
|
||||
c1 = Character.toUpperCase(c1);
|
||||
c2 = Character.toUpperCase(c2);
|
||||
if (c1 != c2) {
|
||||
return c1 - c2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return n1 - n2;
|
||||
return Arrays.compareUnsigned(getUppercasePath(), ((WindowsPath)obj).getUppercasePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -917,6 +904,15 @@ class WindowsPath implements Path {
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] getUppercasePath() {
|
||||
byte[] result = uppercasePath != null ? uppercasePath.get() : null;
|
||||
if (result == null) {
|
||||
result = path.toUpperCase().getBytes();
|
||||
uppercasePath = new WeakReference<>(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI toUri() {
|
||||
return WindowsUriSupport.toUri(this);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@@ -45,6 +45,7 @@ import sun.java2d.MacOSFlags;
|
||||
import sun.java2d.MacosxSurfaceManagerFactory;
|
||||
import sun.java2d.SunGraphicsEnvironment;
|
||||
import sun.java2d.SurfaceManagerFactory;
|
||||
import sun.java2d.metal.MTLGraphicsConfig;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import com.jetbrains.exported.JBRApi;
|
||||
@@ -159,7 +160,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
}
|
||||
|
||||
/* Populate the device table */
|
||||
rebuildDevices();
|
||||
initDevices();
|
||||
|
||||
if (LogDisplay.ENABLED) {
|
||||
for (CGraphicsDevice gd : devices.values()) {
|
||||
@@ -178,11 +179,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
return mtlShadersLib;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of devices and notify listeners.
|
||||
*/
|
||||
private void rebuildDevices() {
|
||||
initDevices();
|
||||
private void doNotifyListeners() {
|
||||
// Do not notify devices, this was already done in initDevices.
|
||||
displayChanger.notifyListeners();
|
||||
}
|
||||
@@ -191,7 +188,7 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
* Called by the CoreGraphics Display Reconfiguration Callback.
|
||||
*
|
||||
* @param displayId CoreGraphics displayId
|
||||
* @param removed true if displayId was removed, false otherwise.
|
||||
* @param flags CGDisplayChangeSummaryFlags flags as integer
|
||||
*/
|
||||
void _displayReconfiguration(int displayId, int flags) {
|
||||
// See CGDisplayChangeSummaryFlags
|
||||
@@ -207,13 +204,35 @@ public final class CGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
// monitors are not added nor removed, but when the video card is
|
||||
// switched to/from the discrete video card, so we should try to map the
|
||||
// old to the new devices.
|
||||
rebuildDevices();
|
||||
initDevices();
|
||||
if (log != null && log != LogDisplay.REMOVED) {
|
||||
CGraphicsDevice gd = devices.get(displayId);
|
||||
log.log(displayId, gd != null ? gd.getBounds() : "UNKNOWN", gd != null ? gd.getScaleFactor() : Double.NaN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the CoreGraphics Display Reconfiguration Callback (once all displays processed = finished)
|
||||
*/
|
||||
void _displayReconfigurationFinished() {
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CGraphicsEnvironment._displayReconfigurationFinished(): enter");
|
||||
}
|
||||
try {
|
||||
doNotifyListeners();
|
||||
} catch (Exception e) {
|
||||
logger.severe("CGraphicsEnvironment._displayReconfigurationFinished: exception occurred: ", e);
|
||||
} finally {
|
||||
// notify the metal pipeline after processing listeners:
|
||||
if (CGraphicsEnvironment.usingMetalPipeline()) {
|
||||
MTLGraphicsConfig.displayReconfigurationDone();
|
||||
}
|
||||
}
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("_displayReconfigurationFinished(): exit");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
protected void finalize() throws Throwable {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -79,6 +79,8 @@ public final class MTLGraphicsConfig extends CGraphicsConfig
|
||||
private final Object disposerReferent = new Object();
|
||||
private final int maxTextureSize;
|
||||
|
||||
public static native void displayReconfigurationDone();
|
||||
|
||||
private static native boolean isMetalFrameworkAvailable();
|
||||
private static native long getMTLConfigInfo(int displayID, String mtlShadersLib);
|
||||
|
||||
|
||||
@@ -67,6 +67,7 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JScrollPane;
|
||||
import javax.swing.JTree;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
@@ -1096,4 +1097,23 @@ class CAccessibility implements PropertyChangeListener {
|
||||
}
|
||||
}, c, false);
|
||||
}
|
||||
|
||||
private static Accessible getScrollBar(Accessible a, Component c, int orientation) {
|
||||
if (a == null) return null;
|
||||
|
||||
return invokeAndWait(() -> {
|
||||
Accessible sa = CAccessible.getSwingAccessible(a);
|
||||
if (sa instanceof JScrollPane scrollPane) {
|
||||
// NSAccessibilityOrientationVertical
|
||||
if (orientation == 1) {
|
||||
return scrollPane.getVerticalScrollBar();
|
||||
}
|
||||
// NSAccessibilityOrientationHorizontal
|
||||
else if (orientation == 2) {
|
||||
return scrollPane.getHorizontalScrollBar();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}, c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -405,7 +405,8 @@ class CAccessible extends CFRetainedResource implements Accessible {
|
||||
AccessibleRole thisRole = accessible.getAccessibleContext()
|
||||
.getAccessibleRole();
|
||||
if (thisRole == AccessibleRole.SLIDER ||
|
||||
thisRole == AccessibleRole.PROGRESS_BAR) {
|
||||
thisRole == AccessibleRole.PROGRESS_BAR ||
|
||||
thisRole == AccessibleRole.SCROLL_BAR) {
|
||||
execute(ptr -> valueChanged(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,6 +244,13 @@ public class CDataTransferer extends DataTransferer {
|
||||
|
||||
@Override
|
||||
protected byte[] imageToPlatformBytes(Image image, long format) {
|
||||
String formatString = getNativeForFormat(format);
|
||||
byte[] result = CImage.getCreator().getPlatformImageBytesForFormat(image, formatString);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// fallback
|
||||
return CImage.getCreator().getPlatformImageBytes(image);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,9 +26,12 @@
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.geom.Dimension2D;
|
||||
import java.awt.image.*;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.awt.image.MultiResolutionImage;
|
||||
@@ -38,6 +41,8 @@ import sun.awt.image.MultiResolutionCachedImage;
|
||||
|
||||
import sun.awt.image.SunWritableRaster;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
public class CImage extends CFRetainedResource {
|
||||
private static native long nativeCreateNSImageFromArray(int[] buffer, int w, int h);
|
||||
private static native long nativeCreateNSImageFromBytes(byte[] buffer);
|
||||
@@ -176,6 +181,41 @@ public class CImage extends CFRetainedResource {
|
||||
return nativeGetPlatformImageBytes(buffer, image.getWidth(null), image.getHeight(null));
|
||||
}
|
||||
|
||||
public byte[] getPlatformImageBytesForFormat(final Image image, final String format) {
|
||||
if (format.equals("TIFF")) {
|
||||
return getPlatformImageBytes(image);
|
||||
}
|
||||
|
||||
BufferedImage bufferedImage;
|
||||
|
||||
if (image instanceof BufferedImage) {
|
||||
bufferedImage = (BufferedImage) image;
|
||||
} else {
|
||||
int width = image.getWidth(null);
|
||||
int height = image.getHeight(null);
|
||||
|
||||
if (width <= 0 || height <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g2d = bufferedImage.createGraphics();
|
||||
g2d.drawImage(image, 0, 0, null);
|
||||
g2d.dispose();
|
||||
}
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
try {
|
||||
if (!ImageIO.write(bufferedImage, format, out)) {
|
||||
return null;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates a byte array which contains platform-specific image data in the given format into an Image.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@@ -1192,8 +1192,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
new GetPropertyAction(invokeLaterKey));
|
||||
final int result;
|
||||
if (invokeLaterArg == null) {
|
||||
// default = 'enabled' to avoid any potential freeze (safe) until better solution:
|
||||
result = INVOKE_LATER_ENABLED;
|
||||
// default = 'false':
|
||||
result = INVOKE_LATER_DISABLED;
|
||||
} else {
|
||||
switch (invokeLaterArg.toLowerCase()) {
|
||||
default:
|
||||
@@ -1215,28 +1215,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private final static boolean INVOKE_LATER_USE_PWM = getInvokeLaterUsePWM();
|
||||
|
||||
private static boolean getInvokeLaterUsePWM() {
|
||||
final String usePwmKey = "awt.mac.flushBuffers.pwm";
|
||||
@SuppressWarnings("removal")
|
||||
final String usePwmArg = AccessController.doPrivileged(
|
||||
new GetPropertyAction(usePwmKey));
|
||||
final boolean result;
|
||||
if (usePwmArg == null) {
|
||||
// default = 'false':
|
||||
result = false;
|
||||
} else {
|
||||
result = "true".equalsIgnoreCase(usePwmArg);
|
||||
logger.info("CPlatformWindow: property \"{0}={1}\", using usePWM={2}.",
|
||||
usePwmKey, usePwmArg, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private final static long NANOS_PER_SEC = 1000000000L;
|
||||
/* 10s period arround reference times (sleep/wake-up...)
|
||||
* to ensure all displays are awaken properly */
|
||||
private final static long NANOS_PER_SEC = 1000000000L;
|
||||
private final static long STATE_CHANGE_PERIOD = 10L * NANOS_PER_SEC;
|
||||
|
||||
private final AtomicBoolean mirroringState = new AtomicBoolean(false);
|
||||
@@ -1244,23 +1225,36 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
private final AtomicLong mirroringDisablingTime = new AtomicLong(0L);
|
||||
|
||||
// Specific class needed to get obvious stack traces:
|
||||
private final class EmptyRunnable implements Runnable {
|
||||
private final static class EmptyRunnable implements Runnable {
|
||||
|
||||
private final String identifier;
|
||||
|
||||
EmptyRunnable(final String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Posting an empty to flush the EventQueue without blocking the main thread
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: run() invoked on {0}",
|
||||
getIdentifier(target));
|
||||
logger.fine("CPlatformWindow.flushBuffers: run() invoked on target: {0}", identifier);
|
||||
}
|
||||
}
|
||||
};
|
||||
private final EmptyRunnable emptyTask = new EmptyRunnable();
|
||||
|
||||
void flushBuffers() {
|
||||
// Only 1 usage by deliverMoveResizeEvent():
|
||||
// System-dependent appearance optimization.
|
||||
// May be blocking so postpone this event processing:
|
||||
|
||||
// Test only to validate LWCToolkit self-defense against freezes:
|
||||
final boolean checkLWCToolkitBlockingMainGuard = false;
|
||||
|
||||
if (!checkLWCToolkitBlockingMainGuard && LWCToolkit.isBlockingMainThread()) {
|
||||
logger.fine("Blocked main thread, skip flushBuffers().");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isVisible() && !nativeBounds.isEmpty() && !isFullScreenMode) {
|
||||
// use the system property 'awt.mac.flushBuffers.invokeLater' to true/auto (default: auto)
|
||||
// to avoid deadlocks caused by the LWCToolkit.invokeAndWait() call below:
|
||||
@@ -1276,7 +1270,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
// JBR-5497: force using invokeLater() when computer returns from sleep or displayChanged()
|
||||
// (mirroring case especially) to avoid deadlocks until solved definitely:
|
||||
|
||||
boolean mirroring = false;
|
||||
if (peer != null) {
|
||||
final GraphicsDevice device = peer.getGraphicsConfiguration().getDevice();
|
||||
@@ -1326,39 +1319,30 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
useInvokeLater = true;
|
||||
break;
|
||||
}
|
||||
if (!useInvokeLater && INVOKE_LATER_USE_PWM) {
|
||||
// If the system property 'awt.mac.flushBuffers.pwm' is true,
|
||||
// invokeLater is enforced during power transitions.
|
||||
final boolean inTransition = LWCToolkit.isWithinPowerTransition();
|
||||
if (inTransition) {
|
||||
logger.fine("CPlatformWindow.flushBuffers[pwm]: inTransition = true");
|
||||
useInvokeLater = true;
|
||||
}
|
||||
}
|
||||
try {
|
||||
final String identifier = logger.isLoggable(PlatformLogger.Level.FINE) ? getIdentifier(target) : null;
|
||||
final EmptyRunnable emptyTask = new EmptyRunnable(identifier);
|
||||
|
||||
// check invokeAndWait: KO (operations require AWTLock and main thread)
|
||||
// => use invokeLater as it is an empty event to force refresh ASAP
|
||||
// => use invokeLater as it is an empty event to force refresh
|
||||
if (useInvokeLater) {
|
||||
LWCToolkit.invokeLater(emptyTask, target);
|
||||
} else {
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: enter " +
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}",
|
||||
getIdentifier(target));
|
||||
}
|
||||
|
||||
/* Ensure >500ms = 666ms timeout to avoid any deadlock among
|
||||
/* Ensure >3000ms = 3.666ms timeout to avoid any deadlock among
|
||||
* appkit, EDT, Flusher & a11y threads, locks
|
||||
* and various synchronization patterns... */
|
||||
final double timeoutSeconds = 0.666; // seconds
|
||||
final double timeoutSeconds = 3.666; // seconds
|
||||
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: enter " +
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}", identifier);
|
||||
}
|
||||
|
||||
// FUCK: appKit is calling this method !
|
||||
LWCToolkit.invokeAndWait(emptyTask, target, timeoutSeconds);
|
||||
|
||||
if (logger.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
logger.fine("CPlatformWindow.flushBuffers: exit " +
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}",
|
||||
getIdentifier(target));
|
||||
"LWCToolkit.invokeAndWait(emptyTask) on target = {0}", identifier);
|
||||
}
|
||||
}
|
||||
} catch (InvocationTargetException ite) {
|
||||
@@ -1411,6 +1395,10 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
/* native call by AWTWindow._deliverMoveResizeEvent() */
|
||||
protected void deliverMoveResizeEvent(int x, int y, int width, int height,
|
||||
boolean byUser) {
|
||||
|
||||
/* Test only to generate more appkit freezes */
|
||||
final boolean bypassToHaveMoreFreezes = false;
|
||||
|
||||
AtomicBoolean ref = new AtomicBoolean();
|
||||
execute(ptr -> {
|
||||
ref.set(CWrapper.NSWindow.isZoomed(ptr));
|
||||
@@ -1429,10 +1417,9 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
}
|
||||
|
||||
// System-dependent appearance optimization.
|
||||
if ((byUser && !oldB.getSize().equals(nativeBounds.getSize()))
|
||||
if (bypassToHaveMoreFreezes
|
||||
|| (byUser && !oldB.getSize().equals(nativeBounds.getSize()))
|
||||
|| isFullScreenAnimationOn) {
|
||||
|
||||
// May be blocking so postpone this event processing:
|
||||
flushBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -766,7 +766,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
|
||||
public static <T> T invokeAndWait(final Callable<T> callable,
|
||||
Component component) throws Exception {
|
||||
return invokeAndWait(callable, component, -1);
|
||||
return invokeAndWait(callable, component, 0);
|
||||
}
|
||||
|
||||
public static <T> T invokeAndWait(final Callable<T> callable, Component component, int timeoutSeconds) throws Exception {
|
||||
@@ -818,7 +818,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
invokeAndWait(runnable, component, false, 0.0);
|
||||
}
|
||||
|
||||
/* 25.01.25: keep public methods with (int timeoutSeconds) */
|
||||
/* 25.04: keep public methods with (int timeoutSeconds) */
|
||||
@Deprecated(since = "25")
|
||||
public static void invokeAndWait(Runnable runnable, Component component, int timeoutSeconds)
|
||||
throws InvocationTargetException
|
||||
@@ -833,7 +833,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
invokeAndWait(runnable, component, processEvents, timeout);
|
||||
}
|
||||
|
||||
/* 25.01.25: added public methods with (double timeoutSeconds) to have timeouts between 0.0 and 1.0 */
|
||||
/* 25.04: added public methods with (double timeoutSeconds) to have more precise timeouts */
|
||||
|
||||
public static void invokeAndWait(Runnable runnable, Component component, double timeoutSeconds)
|
||||
throws InvocationTargetException
|
||||
@@ -905,9 +905,9 @@ public final class LWCToolkit extends LWToolkit {
|
||||
|
||||
private static native boolean isBlockingEventDispatchThread();
|
||||
|
||||
static native String getThreadTraceContexts();
|
||||
public static native boolean isBlockingMainThread();
|
||||
|
||||
static native boolean isWithinPowerTransition();
|
||||
static native String getThreadTraceContexts();
|
||||
|
||||
public static void invokeLater(Runnable event, Component component)
|
||||
throws InvocationTargetException {
|
||||
@@ -1084,7 +1084,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
static native long createAWTRunLoopMediator();
|
||||
/**
|
||||
* Method to run a nested run-loop. The nested loop is spinned in the javaRunLoop mode, so selectors sent
|
||||
* by [JNFRunLoop performOnMainThreadWaiting] are processed.
|
||||
* by [ThreadUtilities performOnMainThreadWaiting] are processed.
|
||||
* @param mediator a native pointer to the mediator object created by createAWTRunLoopMediator
|
||||
* @param processEvents if true - dispatches event while in the nested loop. Used in DnD.
|
||||
* Additional attention is needed when using this feature as we short-circuit normal event
|
||||
@@ -1098,7 +1098,7 @@ public final class LWCToolkit extends LWToolkit {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts run-loop with the provided timeout. Use (<=0.0) for the infinite value.
|
||||
* Starts run-loop with the provided timeout. Use (<= 0.0) for the infinite value.
|
||||
*/
|
||||
static boolean doAWTRunLoop(long mediator, boolean processEvents, double timeoutSeconds) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2023, 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
|
||||
@@ -41,7 +41,7 @@ static NSInteger architecture = -1;
|
||||
/*
|
||||
* Convert the mode string to the more convenient bits per pixel value
|
||||
*/
|
||||
int getBPPFromModeString(CFStringRef mode)
|
||||
static int getBPPFromModeString(CFStringRef mode)
|
||||
{
|
||||
if ((CFStringCompare(mode, CFSTR(kIO30BitDirectPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo)) {
|
||||
// This is a strange mode, where we using 10 bits per RGB component and pack it into 32 bits
|
||||
@@ -57,11 +57,105 @@ int getBPPFromModeString(CFStringRef mode)
|
||||
else if (CFStringCompare(mode, CFSTR(IO8BitIndexedPixels), kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static BOOL isValidDisplayMode(CGDisplayModeRef mode) {
|
||||
void dumpDisplayInfo(jint displayID)
|
||||
{
|
||||
// Returns a Boolean value indicating whether a display is active.
|
||||
jint displayIsActive = CGDisplayIsActive(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is always in a mirroring set.
|
||||
jint displayIsalwaysInMirrorSet = CGDisplayIsAlwaysInMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is sleeping (and is therefore not drawable).
|
||||
jint displayIsAsleep = CGDisplayIsAsleep(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is built-in, such as the internal display in portable systems.
|
||||
jint displayIsBuiltin = CGDisplayIsBuiltin(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is in a mirroring set.
|
||||
jint displayIsInMirrorSet = CGDisplayIsInMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is in a hardware mirroring set.
|
||||
jint displayIsInHWMirrorSet = CGDisplayIsInHWMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is the main display.
|
||||
jint displayIsMain = CGDisplayIsMain(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is connected or online.
|
||||
jint displayIsOnline = CGDisplayIsOnline(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is running in a stereo graphics mode.
|
||||
jint displayIsStereo = CGDisplayIsStereo(displayID);
|
||||
|
||||
// For a secondary display in a mirroring set, returns the primary display.
|
||||
CGDirectDisplayID displayMirrorsDisplay = CGDisplayMirrorsDisplay(displayID);
|
||||
|
||||
// Returns the primary display in a hardware mirroring set.
|
||||
CGDirectDisplayID displayPrimaryDisplay = CGDisplayPrimaryDisplay(displayID);
|
||||
|
||||
// Returns the width and height of a display in millimeters.
|
||||
CGSize size = CGDisplayScreenSize(displayID);
|
||||
|
||||
NSLog(@"CGDisplay[%d]{\n"
|
||||
"displayIsActive=%d\n"
|
||||
"displayIsalwaysInMirrorSet=%d\n"
|
||||
"displayIsAsleep=%d\n"
|
||||
"displayIsBuiltin=%d\n"
|
||||
"displayIsInMirrorSet=%d\n"
|
||||
"displayIsInHWMirrorSet=%d\n"
|
||||
"displayIsMain=%d\n"
|
||||
"displayIsOnline=%d\n"
|
||||
"displayIsStereo=%d\n"
|
||||
"displayMirrorsDisplay=%d\n"
|
||||
"displayPrimaryDisplay=%d\n"
|
||||
"displayScreenSizey=[%.1lf %.1lf]\n",
|
||||
displayID,
|
||||
displayIsActive,
|
||||
displayIsalwaysInMirrorSet,
|
||||
displayIsAsleep,
|
||||
displayIsBuiltin,
|
||||
displayIsInMirrorSet,
|
||||
displayIsInHWMirrorSet,
|
||||
displayIsMain,
|
||||
displayIsOnline,
|
||||
displayIsStereo,
|
||||
displayMirrorsDisplay,
|
||||
displayPrimaryDisplay,
|
||||
size.width, size.height
|
||||
);
|
||||
|
||||
// CGDisplayCopyDisplayMode can return NULL if displayID is invalid
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
|
||||
if (mode != NULL) {
|
||||
// Getting Information About a Display Mode
|
||||
jint h = -1, w = -1, bpp = -1;
|
||||
jdouble refreshRate = 0.0;
|
||||
|
||||
// Returns the width of the specified display mode.
|
||||
w = CGDisplayModeGetWidth(mode);
|
||||
|
||||
// Returns the height of the specified display mode.
|
||||
h = CGDisplayModeGetHeight(mode);
|
||||
|
||||
// Returns the pixel encoding of the specified display mode.
|
||||
// Deprecated
|
||||
CFStringRef currentBPP = CGDisplayModeCopyPixelEncoding(mode);
|
||||
bpp = getBPPFromModeString(currentBPP);
|
||||
CFRelease(currentBPP);
|
||||
|
||||
// Returns the refresh rate of the specified display mode.
|
||||
refreshRate = CGDisplayModeGetRefreshRate(mode);
|
||||
|
||||
NSLog(@"CGDisplayMode[%d]: w=%d, h=%d, bpp=%d, freq=%.2lf hz",
|
||||
displayID, w, h, bpp, refreshRate);
|
||||
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
}
|
||||
|
||||
BOOL isValidDisplayMode(CGDisplayModeRef mode) {
|
||||
if (!CGDisplayModeIsUsableForDesktopGUI(mode)) {
|
||||
return NO;
|
||||
}
|
||||
@@ -184,7 +278,7 @@ static jobject createJavaDisplayMode(CGDisplayModeRef mode, JNIEnv *env) {
|
||||
jint h = DEFAULT_DEVICE_HEIGHT, w = DEFAULT_DEVICE_WIDTH, bpp = 0, refrate = 0;
|
||||
JNI_COCOA_ENTER(env);
|
||||
BOOL isDisplayModeDefault = NO;
|
||||
if (mode) {
|
||||
if (mode != NULL) {
|
||||
CFStringRef currentBPP = CGDisplayModeCopyPixelEncoding(mode);
|
||||
bpp = getBPPFromModeString(currentBPP);
|
||||
CFRelease(currentBPP);
|
||||
@@ -342,10 +436,9 @@ JNI_COCOA_ENTER(env);
|
||||
configureDisplayLock = [[NSLock alloc] init];
|
||||
});
|
||||
|
||||
// Avoid reentrance and ensure consistency between the best mode and ConfigureDisplay transaction:
|
||||
[configureDisplayLock lock];
|
||||
@try {
|
||||
// Avoid reentrance and ensure consistency between the best mode and ConfigureDisplay transaction:
|
||||
[configureDisplayLock lock];
|
||||
|
||||
if (TRACE_DISPLAY_CHANGE_CONF) {
|
||||
NSLog(@"nativeSetDisplayMode: displayID: %d w:%d h:%d bpp: %d refrate:%d", displayID, w, h, bpp, refrate);
|
||||
}
|
||||
@@ -411,7 +504,9 @@ JNI_COCOA_ENTER(env);
|
||||
// CGDisplayCopyDisplayMode can return NULL if displayID is invalid
|
||||
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(displayID);
|
||||
ret = createJavaDisplayMode(currentMode, env);
|
||||
CGDisplayModeRelease(currentMode);
|
||||
if (currentMode != NULL) {
|
||||
CGDisplayModeRelease(currentMode);
|
||||
}
|
||||
JNI_COCOA_EXIT(env);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@@ -33,6 +33,10 @@
|
||||
|
||||
#define MAX_DISPLAYS 64
|
||||
|
||||
static const BOOL TRACE_DISPLAY_CALLBACKS = NO;
|
||||
|
||||
extern void dumpDisplayInfo(jint displayID);
|
||||
|
||||
/*
|
||||
* Class: sun_awt_CGraphicsEnvironment
|
||||
* Method: getDisplayIDs
|
||||
@@ -109,25 +113,78 @@ Java_sun_awt_CGraphicsEnvironment_getMainDisplayID
|
||||
* Post the display reconfiguration event.
|
||||
*/
|
||||
static void displaycb_handle
|
||||
(CGDirectDisplayID display, CGDisplayChangeSummaryFlags flags, void *userInfo)
|
||||
(CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo)
|
||||
{
|
||||
if (flags == kCGDisplayBeginConfigurationFlag) return;
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:NO block:^() {
|
||||
if (TRACE_DISPLAY_CALLBACKS) {
|
||||
NSLog(@"CGraphicsEnv::displaycb_handle(displayId: %d, flags: %d, userInfo: %p)",
|
||||
displayId, flags, userInfo);
|
||||
}
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
jobject cgeRef = (jobject)userInfo;
|
||||
/*
|
||||
* RunLoop interactions with callbacks means several RunLoop iterations may be needed to run these callbacks
|
||||
* within dispatch_queue (RunLoopBeforeSources -> RunLoopExit)
|
||||
*/
|
||||
const jobject cgeRef = (jobject)userInfo;
|
||||
|
||||
if (flags == kCGDisplayBeginConfigurationFlag) {
|
||||
/*
|
||||
* During the Reconfigure transaction consituted by
|
||||
* [Begin(each displayID) ... -> Finished(each displayID) callbacks]
|
||||
* run by RunLoop (__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__),
|
||||
* the begin and finished loops are running callbacks for each displayID which can not modify the RunLoop state
|
||||
* during the complete [Begin -> END] reconfigure transaction
|
||||
* ie appkit thread can not wait ie LWCToolkit.invokeAndWait(task, target ...) is forbidden.
|
||||
*/
|
||||
// Avoid LWCToolkit.invokeAndWait() calls since first Begin(each displayID) callback:
|
||||
[ThreadUtilities setBlockingMainThread:true];
|
||||
return;
|
||||
}
|
||||
|
||||
// Processing display changes (Finished called by _displayReconfigurationFinished):
|
||||
|
||||
// first register Main RunLoop callback to ensure blockingMainThread = false anyway:
|
||||
if ([ThreadUtilities hasMainThreadRunLoopCallback:MAIN_CALLBACK_CGDISPLAY_RECONFIGURE] == NO) {
|
||||
// avoid creating block if not needed:
|
||||
[ThreadUtilities registerMainThreadRunLoopCallback:MAIN_CALLBACK_CGDISPLAY_RECONFIGURE
|
||||
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");
|
||||
DECLARE_METHOD(jm_displayReconfigurationFinished,
|
||||
jc_CGraphicsEnvironment, "_displayReconfigurationFinished", "()V");
|
||||
(*env)->CallVoidMethod(env, graphicsEnv, jm_displayReconfigurationFinished);
|
||||
(*env)->DeleteLocalRef(env, graphicsEnv);
|
||||
CHECK_EXCEPTION();
|
||||
} @finally {
|
||||
// Allow LWCToolkit.invokeAndWait() once Finished callbacks:
|
||||
[ThreadUtilities setBlockingMainThread:false];
|
||||
}
|
||||
}];
|
||||
}
|
||||
if (TRACE_DISPLAY_CALLBACKS) {
|
||||
dumpDisplayInfo(displayId);
|
||||
}
|
||||
|
||||
// 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");
|
||||
DECLARE_METHOD(jm_displayReconfiguration,
|
||||
jc_CGraphicsEnvironment, "_displayReconfiguration","(II)V");
|
||||
(*env)->CallVoidMethod(env, graphicsEnv, jm_displayReconfiguration,
|
||||
(jint) display, (jint) flags);
|
||||
(jint) displayId, (jint) flags);
|
||||
(*env)->DeleteLocalRef(env, graphicsEnv);
|
||||
CHECK_EXCEPTION();
|
||||
}];
|
||||
}
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -602,6 +602,12 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_doAWTRunLoopImpl
|
||||
jboolean result = JNI_TRUE;
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
/* defensive programming (should not happen) */
|
||||
if ([ThreadUtilities blockingMainThread]) {
|
||||
NSLog(@"LWCToolkit_doAWTRunLoopImpl: invalid state: blockingMainThread = YES !");
|
||||
return JNI_FALSE;
|
||||
}
|
||||
|
||||
AWTRunLoopObject* mediatorObject = (AWTRunLoopObject*)jlong_to_ptr(mediator);
|
||||
|
||||
if (mediatorObject == nil) {
|
||||
@@ -612,7 +618,7 @@ JNI_COCOA_ENTER(env);
|
||||
* 2025.02: infinite timeout means possible deadlocks or freezes may happen.
|
||||
* To ensure responsiveness, infinite is limited to a huge delay (~10s)
|
||||
*/
|
||||
if (timeoutSeconds < WAIT_TIMEOUT_LIMIT) {
|
||||
if ((timeoutSeconds <= 0.0) || (timeoutSeconds > WAIT_TIMEOUT_LIMIT)) {
|
||||
timeoutSeconds = WAIT_TIMEOUT_LIMIT;
|
||||
}
|
||||
|
||||
@@ -696,6 +702,17 @@ JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isBlockingEventDispa
|
||||
return ThreadUtilities.blockingEventDispatchThread;
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: isBlockingMainThread
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isBlockingMainThread
|
||||
(JNIEnv *env, jclass clz)
|
||||
{
|
||||
return [ThreadUtilities blockingMainThread];
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: getThreadTraceContexts
|
||||
@@ -716,19 +733,6 @@ JNI_COCOA_ENTER(env);
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: isWithinPowerTransition
|
||||
* Signature: ()Z
|
||||
*/
|
||||
JNIEXPORT jboolean JNICALL Java_sun_lwawt_macosx_LWCToolkit_isWithinPowerTransition
|
||||
(JNIEnv *env, jclass clz)
|
||||
{
|
||||
JNI_COCOA_ENTER(env);
|
||||
return [ThreadUtilities isWithinPowerTransition:PWM_TRANSITION_PERIOD] ? JNI_TRUE : JNI_FALSE;
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_LWCToolkit
|
||||
* Method: stopAWTRunLoop
|
||||
|
||||
@@ -179,6 +179,26 @@ enum ShortcutID {
|
||||
Shortcut_ToggleSpeakSelection = 230,
|
||||
Shortcut_ToggleSpeakItemUnderPointer = 231,
|
||||
Shortcut_ToggleTypingFeedback = 232,
|
||||
Shortcut_MinimizeWindow = 233,
|
||||
Shortcut_ZoomWindow = 235,
|
||||
Shortcut_FillWindow = 237,
|
||||
Shortcut_CenterWindow = 238,
|
||||
Shortcut_RestoreWindow = 239,
|
||||
Shortcut_TileLeftHalf = 240,
|
||||
Shortcut_TileRightHalf = 241,
|
||||
Shortcut_TileTopHalf = 242,
|
||||
Shortcut_TileBottomHalf = 243,
|
||||
Shortcut_TileTopLeftQuarter = 244,
|
||||
Shortcut_TileTopRightQuarter = 245,
|
||||
Shortcut_TileBottomLeftQuarter = 246,
|
||||
Shortcut_TileBottomRightQuarter = 247,
|
||||
Shortcut_ArrangeLeftRight = 248,
|
||||
Shortcut_ArrangeRightLeft = 249,
|
||||
Shortcut_ArrangeTopBottom = 250,
|
||||
Shortcut_ArrangeBottomTop = 251,
|
||||
Shortcut_ArrangeQuarters = 256,
|
||||
Shortcut_FullScreenTileLeft = 257,
|
||||
Shortcut_FullScreenTileRight = 258,
|
||||
};
|
||||
|
||||
struct SymbolicHotKey {
|
||||
@@ -204,67 +224,88 @@ struct SymbolicHotKey {
|
||||
// Modifier mask using the NSEventModifierFlag* values for this shortcut
|
||||
int modifiers;
|
||||
|
||||
// The first major version of macOS that has this shortcut or -1 if unknown.
|
||||
int macOSVersion;
|
||||
// The first version of macOS that has this shortcut or -1 if unknown.
|
||||
int macOSVersionMajor;
|
||||
int macOSVersionMinor;
|
||||
};
|
||||
|
||||
static const struct SymbolicHotKey defaultSymbolicHotKeys[] = {
|
||||
[Shortcut_FocusMenuBar] = { "FocusMenuBar", "Move focus to the menu bar", YES, 65535, 120, 0x00840000, -1 },
|
||||
[Shortcut_FocusDock] = { "FocusDock", "Move focus to the Dock", YES, 65535, 99, 0x00840000, -1 },
|
||||
[Shortcut_FocusActiveWindow] = { "FocusActiveWindow", "Move focus to active or next window", YES, 65535, 118, 0x00840000, -1 },
|
||||
[Shortcut_FocusToolbar] = { "FocusToolbar", "Move focus to window toolbar", YES, 65535, 96, 0x00840000, -1 },
|
||||
[Shortcut_FocusFloatingWindow] = { "FocusFloatingWindow", "Move focus to floating window", YES, 65535, 97, 0x00840000, -1 },
|
||||
[Shortcut_ToggleKeyboardAccess] = { "ToggleKeyboardAccess", "Turn keyboard access on or off", YES, 65535, 122, 0x00840000, -1 },
|
||||
[Shortcut_ChangeTabMode] = { "ChangeTabMode", "Change the way Tab moves focus", YES, 65535, 98, 0x00840000, -1 },
|
||||
[Shortcut_ToggleZoom] = { "ToggleZoom", "Zoom: Turn zoom on or off", NO, 56, 28, 0x00180000, -1 },
|
||||
[Shortcut_ZoomIn] = { "ZoomIn", "Zoom: Zoom in", NO, 61, 24, 0x00180000, -1 },
|
||||
[Shortcut_ZoomOut] = { "ZoomOut", "Zoom: Zoom out", NO, 45, 27, 0x00180000, -1 },
|
||||
[Shortcut_InvertColors] = { "InvertColors", "Invert colors", YES, 56, 28, 0x001c0000, -1 },
|
||||
[Shortcut_ToggleZoomImageSmoothing] = { "ToggleZoomImageSmoothing", "Zoom: Turn image smoothing on or off", NO, 92, 42, 0x00180000, -1 },
|
||||
[Shortcut_IncreaseContrast] = { "IncreaseContrast", "Increase contrast", NO, 46, 47, 0x001c0000, -1 },
|
||||
[Shortcut_DecreaseContrast] = { "DecreaseContrast", "Decrease contrast", NO, 44, 43, 0x001c0000, -1 },
|
||||
[Shortcut_FocusNextApplicationWindow] = { "FocusNextApplicationWindow", "Move focus to the next window in application", YES, 96, 50, 0x00100000, -1 },
|
||||
[Shortcut_ScreenshotToFile] = { "ScreenshotToFile", "Save picture of screen as a file", YES, 51, 20, 0x00120000, -1 },
|
||||
[Shortcut_ScreenshotToClipboard] = { "ScreenshotToClipboard", "Copy picture of screen to the clipboard", YES, 51, 20, 0x00160000, -1 },
|
||||
[Shortcut_ScreenshotAreaToFile] = { "ScreenshotAreaToFile", "Save picture of selected area as a file", YES, 52, 21, 0x00120000, -1 },
|
||||
[Shortcut_ScreenshotAreaToClipboard] = { "ScreenshotAreaToClipboard", "Copy picture of selected area to the clipboard", YES, 52, 21, 0x00160000, -1 },
|
||||
[Shortcut_ShowAllWindows] = { "ShowAllWindows", "Mission Control", YES, 65535, 126, 0x00840000, -1 },
|
||||
[Shortcut_ShowApplicationWindows] = { "ShowApplicationWindows", "Application windows", YES, 65535, 125, 0x00840000, -1 },
|
||||
[Shortcut_ShowDesktop] = { "ShowDesktop", "Show desktop", YES, 65535, 103, 0x00800000, -1 },
|
||||
[Shortcut_ToggleDockHiding] = { "ToggleDockHiding", "Turn Dock hiding on/off", YES, 100, 2, 0x00180000, -1 },
|
||||
[Shortcut_DecreaseBrightness] = { "DecreaseBrightness", "Decrease display brightness", YES, 65535, 107, 0x00800000, -1 },
|
||||
[Shortcut_IncreaseBrightness] = { "IncreaseBrightness", "Increase display brightness", YES, 65535, 113, 0x00800000, -1 },
|
||||
[Shortcut_FocusStatusMenu] = { "FocusStatusMenu", "Move focus to the status menus", YES, 65535, 100, 0x00840000, -1 },
|
||||
[Shortcut_ToggleVoiceOver] = { "ToggleVoiceOver", "Turn VoiceOver on or off", YES, 65535, 96, 0x00900000, -1 },
|
||||
[Shortcut_SelectPreviousInputSource] = { "SelectPreviousInputSource", "Select the previous input source", YES, 32, 49, 0x00040000, -1 },
|
||||
[Shortcut_SelectNextInputSource] = { "SelectNextInputSource", "Select next source in Input menu", YES, 32, 49, 0x000c0000, -1 },
|
||||
[Shortcut_ShowSpotlight] = { "ShowSpotlight", "Show Spotlight Search", YES, 32, 49, 0x00100000, -1 },
|
||||
[Shortcut_ShowFinderSearch] = { "ShowFinderSearch", "Show Finder search window", YES, 32, 49, 0x00180000, -1 },
|
||||
[Shortcut_SwitchToDesktopLeft] = { "SwitchToDesktopLeft", "Move left a space", NO, 65535, 123, 0x00840000, -1 },
|
||||
[Shortcut_SwitchToDesktopRight] = { "SwitchToDesktopRight", "Move right a space", NO, 65535, 124, 0x00840000, -1 },
|
||||
[Shortcut_SwitchToDesktop1] = { "SwitchToDesktop1", "Switch to Desktop 1", NO, 65535, 18, 0x00040000, -1 },
|
||||
[Shortcut_SwitchToDesktop2] = { "SwitchToDesktop2", "Switch to Desktop 2", NO, 65535, 19, 0x00040000, -1 },
|
||||
[Shortcut_SwitchToDesktop3] = { "SwitchToDesktop3", "Switch to Desktop 3", NO, 65535, 20, 0x00040000, -1 },
|
||||
[Shortcut_SwitchToDesktop4] = { "SwitchToDesktop4", "Switch to Desktop 4", NO, 65535, 21, 0x00040000, -1 },
|
||||
[Shortcut_ShowContextualMenu] = { "ShowContextualMenu", "Show contextual menu", YES, 65535, 36, 0x00040000, 15 },
|
||||
[Shortcut_ShowLaunchpad] = { "ShowLaunchpad", "Show Launchpad", NO, 65535, 65535, 0, -1 },
|
||||
[Shortcut_ShowAccessibilityControls] = { "ShowAccessibilityControls", "Show Accessibility controls", YES, 65535, 96, 0x00980000, -1 },
|
||||
[Shortcut_ShowNotificationCenter] = { "ShowNotificationCenter", "Show Notification Center", NO, 65535, 65535, 0, -1 },
|
||||
[Shortcut_ToggleDoNotDisturb] = { "ToggleDoNotDisturb", "Turn Do Not Disturb on/off", YES, 65535, 65535, 0, -1 },
|
||||
[Shortcut_ToggleZoomFocusFollowing] = { "ToggleZoomFocusFollowing", "Zoom: Turn focus following on or off", NO, 65535, 65535, 0, -1 },
|
||||
[Shortcut_ScreenshotOptions] = { "ScreenshotOptions", "Screenshot and recording options", YES, 53, 23, 0x00120000, -1 },
|
||||
[Shortcut_OpenQuickNote] = { "OpenQuickNote", "Quick note", YES, 113, 12, 0x00800000, -1 },
|
||||
[Shortcut_ToggleStageManager] = { "ToggleStageManager", "Turn Stage Manager on/off", NO, 65535, 65535, 0, -1 },
|
||||
[Shortcut_TogglePresenterOverlayLarge] = { "TogglePresenterOverlayLarge", "Turn Presenter Overlay (large) on or off", YES, 65535, 65535, 0, -1 },
|
||||
[Shortcut_TogglePresenterOverlaySmall] = { "TogglePresenterOverlaySmall", "Turn Presenter Overlay (small) on or off", YES, 65535, 65535, 0, -1 },
|
||||
[Shortcut_ToggleLiveSpeech] = { "ToggleLiveSpeech", "LiveSpeech: Turn Live Speech on or off", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_ToggleLiveSpeechVisibility] = { "ToggleLiveSpeechVisibility", "LiveSpeech: Toggle visibility", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_PauseOrResumeLiveSpeech] = { "PauseOrResumeLiveSpeech", "LiveSpeech: Pause or resume speech", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_CancelLiveSpeech] = { "CancelLiveSpeech", "LiveSpeech: Cancel speech", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_ToggleLiveSpeechPhrases] = { "ToggleLiveSpeechPhrases", "LiveSpeech: Hide or show phrases", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_ToggleSpeakSelection] = { "ToggleSpeakSelection", "Turn speak selection on or off", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_ToggleSpeakItemUnderPointer] = { "ToggleSpeakItemUnderPointer", "Turn speak item under the pointer on or off", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_ToggleTypingFeedback] = { "ToggleTypingFeedback", "Turn typing feedback on or off", YES, 65535, 65535, 0, 14 },
|
||||
[Shortcut_FocusMenuBar] = { "FocusMenuBar", "Move focus to the menu bar", YES, 65535, 120, 0x00840000, -1, -1 },
|
||||
[Shortcut_FocusDock] = { "FocusDock", "Move focus to the Dock", YES, 65535, 99, 0x00840000, -1, -1 },
|
||||
[Shortcut_FocusActiveWindow] = { "FocusActiveWindow", "Move focus to active or next window", YES, 65535, 118, 0x00840000, -1, -1 },
|
||||
[Shortcut_FocusToolbar] = { "FocusToolbar", "Move focus to window toolbar", YES, 65535, 96, 0x00840000, -1, -1 },
|
||||
[Shortcut_FocusFloatingWindow] = { "FocusFloatingWindow", "Move focus to floating window", YES, 65535, 97, 0x00840000, -1, -1 },
|
||||
[Shortcut_ToggleKeyboardAccess] = { "ToggleKeyboardAccess", "Turn keyboard access on or off", YES, 65535, 122, 0x00840000, -1, -1 },
|
||||
[Shortcut_ChangeTabMode] = { "ChangeTabMode", "Change the way Tab moves focus", YES, 65535, 98, 0x00840000, -1, -1 },
|
||||
[Shortcut_ToggleZoom] = { "ToggleZoom", "Zoom: Turn zoom on or off", NO, 56, 28, 0x00180000, -1, -1 },
|
||||
[Shortcut_ZoomIn] = { "ZoomIn", "Zoom: Zoom in", NO, 61, 24, 0x00180000, -1, -1 },
|
||||
[Shortcut_ZoomOut] = { "ZoomOut", "Zoom: Zoom out", NO, 45, 27, 0x00180000, -1, -1 },
|
||||
[Shortcut_InvertColors] = { "InvertColors", "Invert colors", YES, 56, 28, 0x001c0000, -1, -1 },
|
||||
[Shortcut_ToggleZoomImageSmoothing] = { "ToggleZoomImageSmoothing", "Zoom: Turn image smoothing on or off", NO, 92, 42, 0x00180000, -1, -1 },
|
||||
[Shortcut_IncreaseContrast] = { "IncreaseContrast", "Increase contrast", NO, 46, 47, 0x001c0000, -1, -1 },
|
||||
[Shortcut_DecreaseContrast] = { "DecreaseContrast", "Decrease contrast", NO, 44, 43, 0x001c0000, -1, -1 },
|
||||
[Shortcut_FocusNextApplicationWindow] = { "FocusNextApplicationWindow", "Move focus to the next window in application", YES, 96, 50, 0x00100000, -1, -1 },
|
||||
[Shortcut_ScreenshotToFile] = { "ScreenshotToFile", "Save picture of screen as a file", YES, 51, 20, 0x00120000, -1, -1 },
|
||||
[Shortcut_ScreenshotToClipboard] = { "ScreenshotToClipboard", "Copy picture of screen to the clipboard", YES, 51, 20, 0x00160000, -1, -1 },
|
||||
[Shortcut_ScreenshotAreaToFile] = { "ScreenshotAreaToFile", "Save picture of selected area as a file", YES, 52, 21, 0x00120000, -1, -1 },
|
||||
[Shortcut_ScreenshotAreaToClipboard] = { "ScreenshotAreaToClipboard", "Copy picture of selected area to the clipboard", YES, 52, 21, 0x00160000, -1, -1 },
|
||||
[Shortcut_ShowAllWindows] = { "ShowAllWindows", "Mission Control", YES, 65535, 126, 0x00840000, -1, -1 },
|
||||
[Shortcut_ShowApplicationWindows] = { "ShowApplicationWindows", "Application windows", YES, 65535, 125, 0x00840000, -1, -1 },
|
||||
[Shortcut_ShowDesktop] = { "ShowDesktop", "Show desktop", YES, 65535, 103, 0x00800000, -1, -1 },
|
||||
[Shortcut_ToggleDockHiding] = { "ToggleDockHiding", "Turn Dock hiding on/off", YES, 100, 2, 0x00180000, -1, -1 },
|
||||
[Shortcut_DecreaseBrightness] = { "DecreaseBrightness", "Decrease display brightness", YES, 65535, 107, 0x00800000, -1, -1 },
|
||||
[Shortcut_IncreaseBrightness] = { "IncreaseBrightness", "Increase display brightness", YES, 65535, 113, 0x00800000, -1, -1 },
|
||||
[Shortcut_FocusStatusMenu] = { "FocusStatusMenu", "Move focus to the status menus", YES, 65535, 100, 0x00840000, -1, -1 },
|
||||
[Shortcut_ToggleVoiceOver] = { "ToggleVoiceOver", "Turn VoiceOver on or off", YES, 65535, 96, 0x00900000, -1, -1 },
|
||||
[Shortcut_SelectPreviousInputSource] = { "SelectPreviousInputSource", "Select the previous input source", YES, 32, 49, 0x00040000, -1, -1 },
|
||||
[Shortcut_SelectNextInputSource] = { "SelectNextInputSource", "Select next source in Input menu", YES, 32, 49, 0x000c0000, -1, -1 },
|
||||
[Shortcut_ShowSpotlight] = { "ShowSpotlight", "Show Spotlight Search", YES, 32, 49, 0x00100000, -1, -1 },
|
||||
[Shortcut_ShowFinderSearch] = { "ShowFinderSearch", "Show Finder search window", YES, 32, 49, 0x00180000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktopLeft] = { "SwitchToDesktopLeft", "Move left a space", NO, 65535, 123, 0x00840000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktopRight] = { "SwitchToDesktopRight", "Move right a space", NO, 65535, 124, 0x00840000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktop1] = { "SwitchToDesktop1", "Switch to Desktop 1", NO, 65535, 18, 0x00040000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktop2] = { "SwitchToDesktop2", "Switch to Desktop 2", NO, 65535, 19, 0x00040000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktop3] = { "SwitchToDesktop3", "Switch to Desktop 3", NO, 65535, 20, 0x00040000, -1, -1 },
|
||||
[Shortcut_SwitchToDesktop4] = { "SwitchToDesktop4", "Switch to Desktop 4", NO, 65535, 21, 0x00040000, -1, -1 },
|
||||
[Shortcut_ShowContextualMenu] = { "ShowContextualMenu", "Show contextual menu", YES, 65535, 36, 0x00040000, 15, 0 },
|
||||
[Shortcut_ShowLaunchpad] = { "ShowLaunchpad", "Show Launchpad", NO, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_ShowAccessibilityControls] = { "ShowAccessibilityControls", "Show Accessibility controls", YES, 65535, 96, 0x00980000, -1, -1 },
|
||||
[Shortcut_ShowNotificationCenter] = { "ShowNotificationCenter", "Show Notification Center", NO, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_ToggleDoNotDisturb] = { "ToggleDoNotDisturb", "Turn Do Not Disturb on/off", YES, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_ToggleZoomFocusFollowing] = { "ToggleZoomFocusFollowing", "Zoom: Turn focus following on or off", NO, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_ScreenshotOptions] = { "ScreenshotOptions", "Screenshot and recording options", YES, 53, 23, 0x00120000, -1, -1 },
|
||||
[Shortcut_OpenQuickNote] = { "OpenQuickNote", "Quick note", YES, 113, 12, 0x00800000, -1, -1 },
|
||||
[Shortcut_ToggleStageManager] = { "ToggleStageManager", "Turn Stage Manager on/off", NO, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_TogglePresenterOverlayLarge] = { "TogglePresenterOverlayLarge", "Turn Presenter Overlay (large) on or off", YES, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_TogglePresenterOverlaySmall] = { "TogglePresenterOverlaySmall", "Turn Presenter Overlay (small) on or off", YES, 65535, 65535, 0, -1, -1 },
|
||||
[Shortcut_ToggleLiveSpeech] = { "ToggleLiveSpeech", "LiveSpeech: Turn Live Speech on or off", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_ToggleLiveSpeechVisibility] = { "ToggleLiveSpeechVisibility", "LiveSpeech: Toggle visibility", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_PauseOrResumeLiveSpeech] = { "PauseOrResumeLiveSpeech", "LiveSpeech: Pause or resume speech", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_CancelLiveSpeech] = { "CancelLiveSpeech", "LiveSpeech: Cancel speech", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_ToggleLiveSpeechPhrases] = { "ToggleLiveSpeechPhrases", "LiveSpeech: Hide or show phrases", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_ToggleSpeakSelection] = { "ToggleSpeakSelection", "Turn speak selection on or off", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_ToggleSpeakItemUnderPointer] = { "ToggleSpeakItemUnderPointer", "Turn speak item under the pointer on or off", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_ToggleTypingFeedback] = { "ToggleTypingFeedback", "Turn typing feedback on or off", YES, 65535, 65535, 0, 14, 0 },
|
||||
[Shortcut_MinimizeWindow] = { "MinimizeWindow", "Windows: Minimize", YES, 109, 46, 0x00100000, 15, 4 },
|
||||
[Shortcut_ZoomWindow] = { "ZoomWindow", "Windows: Zoom", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_FillWindow] = { "FillWindow", "Windows: Fill", YES, 102, 3, 0x00840000, 15, 4 },
|
||||
[Shortcut_CenterWindow] = { "CenterWindow", "Windows: Center", YES, 99, 8, 0x00840000, 15, 4 },
|
||||
[Shortcut_RestoreWindow] = { "RestoreWindow", "Windows: Return to Previous Size", YES, 114, 15, 0x00840000, 15, 4 },
|
||||
[Shortcut_TileLeftHalf] = { "TileLeftHalf", "Windows: Tile Left Half", YES, 65535, 123, 0x00840000, 15, 4 },
|
||||
[Shortcut_TileRightHalf] = { "TileRightHalf", "Windows: Tile Right Half", YES, 65535, 124, 0x00840000, 15, 4 },
|
||||
[Shortcut_TileTopHalf] = { "TileTopHalf", "Windows: Tile Top Half", YES, 65535, 126, 0x00840000, 15, 4 },
|
||||
[Shortcut_TileBottomHalf] = { "TileBottomHalf", "Windows: Tile Bottom Half", YES, 65535, 125, 0x00840000, 15, 4 },
|
||||
[Shortcut_TileTopLeftQuarter] = { "TileTopLeftQuarter", "Windows: Tile Top-Left Quarter", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_TileTopRightQuarter] = { "TileTopRightQuarter", "Windows: Tile Top-Right Quarter", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_TileBottomLeftQuarter] = { "TileBottomLeftQuarter", "Windows: Tile Bottom-Left Quarter", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_TileBottomRightQuarter] = { "TileBottomRightQuarter", "Windows: Tile Bottom-Right Quarter", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_ArrangeLeftRight] = { "ArrangeLeftRight", "Windows: Arrange Left and Right", YES, 65535, 123, 0x00860000, 15, 4 },
|
||||
[Shortcut_ArrangeRightLeft] = { "ArrangeRightLeft", "Windows: Arrange Right and Left", YES, 65535, 124, 0x00860000, 15, 4 },
|
||||
[Shortcut_ArrangeTopBottom] = { "ArrangeTopBottom", "Windows: Arrange Top and Bottom", YES, 65535, 126, 0x00860000, 15, 4 },
|
||||
[Shortcut_ArrangeBottomTop] = { "ArrangeBottomTop", "Windows: Arrange Bottom and Top", YES, 65535, 125, 0x00860000, 15, 4 },
|
||||
[Shortcut_ArrangeQuarters] = { "ArrangeQuarters", "Windows: Arrange in Quarters", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_FullScreenTileLeft] = { "FullScreenTileLeft", "Windows: Full-Screen Tile Left", YES, 65535, 65535, 0, 15, 4 },
|
||||
[Shortcut_FullScreenTileRight] = { "FullScreenTileRight", "Windows: Full-Screen Tile Right", YES, 65535, 65535, 0, 15, 4 },
|
||||
};
|
||||
|
||||
static const int numSymbolicHotkeys = sizeof(defaultSymbolicHotKeys) / sizeof(defaultSymbolicHotKeys[0]);
|
||||
@@ -393,6 +434,11 @@ static void readAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymbolicHo
|
||||
|
||||
int uid = [hkNumber intValue];
|
||||
|
||||
// Ignore hotkeys out of range, as well as 0, which is the "invalid value" for intValue
|
||||
if (uid <= 0 || uid >= numSymbolicHotkeys) {
|
||||
continue;
|
||||
}
|
||||
|
||||
id hkDesc = hkObj[hkNumber];
|
||||
if (![hkDesc isKindOfClass:[NSDictionary class]]) {
|
||||
plog(LL_DEBUG, "hotkey descriptor '%s' isn't instance of NSDictionary (class=%s)", toCString(hkDesc),
|
||||
@@ -477,8 +523,19 @@ static void iterateAppleSymbolicHotkeys(struct SymbolicHotKey hotkeys[numSymboli
|
||||
|
||||
for (int uid = 0; uid < numSymbolicHotkeys; ++uid) {
|
||||
struct SymbolicHotKey* hotkey = &hotkeys[uid];
|
||||
if (!hotkey->enabled) continue;
|
||||
if (hotkey->macOSVersion > macOSVersion.majorVersion) continue;
|
||||
|
||||
if (!hotkey->enabled) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hotkey->macOSVersionMajor > macOSVersion.majorVersion ||
|
||||
(hotkey->macOSVersionMajor == macOSVersion.majorVersion && hotkey->macOSVersionMinor > macOSVersion.minorVersion)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (hotkey->character == 0xFFFF && hotkey->key == 0xFFFF) {
|
||||
continue;
|
||||
}
|
||||
|
||||
char keyCharBuf[64];
|
||||
const char *keyCharStr = keyCharBuf;
|
||||
@@ -577,15 +634,6 @@ static bool ensureInitializedAndEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
// JBR-8422
|
||||
const NSOperatingSystemVersion macOSVersion = [[NSProcessInfo processInfo] operatingSystemVersion];
|
||||
if (macOSVersion.majorVersion > 15 || (macOSVersion.majorVersion == 15 && macOSVersion.minorVersion >= 4)) {
|
||||
state.initialized = true;
|
||||
state.enabled = false;
|
||||
pthread_mutex_unlock(&state.mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
state.initialized = true;
|
||||
state.enabled = true;
|
||||
[SystemHotkey subscribeToChanges];
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
#import "JNIUtilities.h"
|
||||
#import "sun_lwawt_macosx_CAccessibility.h"
|
||||
|
||||
static jclass sjc_CAccessibility = NULL;
|
||||
static jmethodID sjm_getScrollBar = NULL;
|
||||
|
||||
/*
|
||||
* Implementation of the accessibility peer for the ScrollArea role
|
||||
*/
|
||||
@@ -57,10 +60,30 @@
|
||||
{
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
|
||||
// Firstly, try to get the scroll bar using getHorizontalScrollBar/getVerticalScrollBar methods of JScrollPane.
|
||||
jobject scrollBar = NULL;
|
||||
GET_CACCESSIBILITY_CLASS_RETURN(nil);
|
||||
GET_STATIC_METHOD_RETURN(sjm_getScrollBar, sjc_CAccessibility, "getScrollBar",
|
||||
"(Ljavax/accessibility/Accessible;Ljava/awt/Component;I)Ljavax/accessibility/Accessible;", nil);
|
||||
scrollBar = (*env)->CallStaticObjectMethod(env, sjc_CAccessibility, sjm_getScrollBar, fAccessible, fComponent, orientation);
|
||||
CHECK_EXCEPTION();
|
||||
|
||||
if (scrollBar != NULL) {
|
||||
CommonComponentAccessibility *axScrollBar = nil;
|
||||
DECLARE_CLASS_RETURN(sjc_Accessible, "javax/accessibility/Accessible", nil);
|
||||
if ((*env)->IsInstanceOf(env, scrollBar, sjc_Accessible)) {
|
||||
axScrollBar = [CommonComponentAccessibility createWithAccessible:scrollBar withEnv:env withView:fView];
|
||||
}
|
||||
(*env)->DeleteLocalRef(env, scrollBar);
|
||||
if (axScrollBar != nil) {
|
||||
return axScrollBar;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, try to search for the scroll bar within the children.
|
||||
NSArray *children = [CommonComponentAccessibility childrenOfParent:self withEnv:env withChildrenCode:sun_lwawt_macosx_CAccessibility_JAVA_AX_ALL_CHILDREN allowIgnored:YES];
|
||||
if ([children count] <= 0) return nil;
|
||||
|
||||
// The scroll bars are in the children.
|
||||
CommonComponentAccessibility *aElement;
|
||||
NSEnumerator *enumerator = [children objectEnumerator];
|
||||
while ((aElement = (CommonComponentAccessibility *)[enumerator nextObject])) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -48,6 +48,15 @@
|
||||
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||
#define MTL_GPU_FAMILY_MAC_TXT_SIZE 16384
|
||||
|
||||
typedef enum {
|
||||
MTLDCM_SYSTEM_UNDEFINED,
|
||||
MTLDCM_SYSTEM_SLEEP,
|
||||
MTLDCM_SYSTEM_WAKEUP,
|
||||
MTLDCM_DISPLAY_SLEEP,
|
||||
MTLDCM_DISPLAY_WAKEUP,
|
||||
MTLDCM_DISPLAY_RECONFIGURE
|
||||
} MTLContextStoreNotification;
|
||||
|
||||
/**
|
||||
* The MTLCommandBufferWrapper class contains command buffer and
|
||||
* associated resources that will be released in completion handler
|
||||
@@ -110,13 +119,14 @@
|
||||
+ (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst;
|
||||
|
||||
+ (NSMutableDictionary*) contextStore;
|
||||
+ (void) processContextStoreNotification:(MTLContextStoreNotification)notification;
|
||||
|
||||
+ (MTLContext*) createContextWithDeviceIfAbsent:(jint)displayID shadersLib:(NSString*)mtlShadersLib;
|
||||
- (id)initWithDevice:(id<MTLDevice>)device shadersLib:(NSString*)mtlShadersLib;
|
||||
- (void)dealloc;
|
||||
|
||||
- (NSArray<NSNumber*>*)getDisplayLinkDisplayIds;
|
||||
- (void)handleDisplayLink:(BOOL)enabled displayID:(jint)displayID source:(const char*)src;
|
||||
- (void)createDisplayLinkIfAbsent: (jint)displayID;
|
||||
- (void)createDisplayLinkIfAbsent: (NSNumber*)displayID;
|
||||
|
||||
/**
|
||||
* Resets the current clip state (disables both scissor and depth tests).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -38,6 +38,8 @@
|
||||
// to avoid multiple start/stop displaylink operations. It speeds up
|
||||
// scenarios with multiple subsequent updates.
|
||||
#define KEEP_ALIVE_COUNT 4
|
||||
#define CV_DISPLAYLINK_FAIL_DELAY 1.0
|
||||
#define MAX_DISPLAYLINK_FAIL_COUNT 5
|
||||
|
||||
#define TO_MS(x) (1000.0 * (x))
|
||||
#define TO_FPS(x) (1.0 / (x))
|
||||
@@ -55,11 +57,12 @@
|
||||
extern jboolean MTLSD_InitMTLWindow(JNIEnv *env, MTLSDOps *mtlsdo);
|
||||
extern BOOL isDisplaySyncEnabled();
|
||||
extern BOOL MTLLayer_isExtraRedrawEnabled();
|
||||
extern int getBPPFromModeString(CFStringRef mode);
|
||||
extern void dumpDisplayInfo(jint displayID);
|
||||
extern BOOL isValidDisplayMode(CGDisplayModeRef mode);
|
||||
|
||||
#define STATS_CVLINK 0
|
||||
|
||||
#define TRACE_PWM_NOTIF 0
|
||||
#define TRACE_NOTIF 0
|
||||
|
||||
#define TRACE_CVLINK 0
|
||||
#define TRACE_CVLINK_WARN 0
|
||||
@@ -79,10 +82,6 @@ extern int getBPPFromModeString(CFStringRef mode);
|
||||
} \
|
||||
}
|
||||
|
||||
boolean_t mtlc_IsDisplayReallyActive(CGDirectDisplayID displayID) {
|
||||
return CGDisplayIsActive(displayID) & !CGDisplayIsAsleep(displayID) && CGDisplayIsOnline(displayID);
|
||||
}
|
||||
|
||||
/* 60 fps typically => exponential smoothing on 0.5s */
|
||||
static const NSTimeInterval EXP_AVG_WEIGHT = (1.0 / 30.0);
|
||||
static const NSTimeInterval EXP_INV_WEIGHT = (1.0 - EXP_AVG_WEIGHT);
|
||||
@@ -101,15 +100,34 @@ typedef struct {
|
||||
CVDisplayLinkRef displayLink;
|
||||
MTLContext* mtlc;
|
||||
jint redrawCount;
|
||||
jint failCount;
|
||||
|
||||
jint avgDisplayLinkSamples;
|
||||
CFTimeInterval lastRedrawTime;
|
||||
CFTimeInterval lastDisplayLinkTime;
|
||||
CFTimeInterval avgDisplayLinkTime;
|
||||
CFTimeInterval lastStatTime;
|
||||
|
||||
} MTLDisplayLinkState;
|
||||
|
||||
/* debugging helper functions */
|
||||
static const char* mtlContextStoreNotificationToStr(MTLContextStoreNotification notification) {
|
||||
#undef CASE_MTL_OP
|
||||
#define CASE_MTL_OP(X) \
|
||||
case MTLDCM_##X: \
|
||||
return #X;
|
||||
|
||||
switch (notification) {
|
||||
CASE_MTL_OP(SYSTEM_SLEEP)
|
||||
CASE_MTL_OP(SYSTEM_WAKEUP)
|
||||
CASE_MTL_OP(DISPLAY_SLEEP)
|
||||
CASE_MTL_OP(DISPLAY_WAKEUP)
|
||||
CASE_MTL_OP(DISPLAY_RECONFIGURE)
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
#undef CASE_MTL_OP
|
||||
}
|
||||
|
||||
@implementation MTLCommandBufferWrapper {
|
||||
id<MTLCommandBuffer> _commandBuffer;
|
||||
NSMutableArray * _pooledTextures;
|
||||
@@ -194,69 +212,42 @@ typedef struct {
|
||||
extern void initSamplers(id<MTLDevice> device);
|
||||
|
||||
+ (void)mtlc_systemOrScreenWillSleep:(NSNotification*)notification {
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenWillSleep[%@]", [notification name]);
|
||||
}
|
||||
if (isDisplaySyncEnabled()) {
|
||||
[ThreadUtilities performOnMainThreadNowOrLater:NO // critical
|
||||
block:^(){
|
||||
|
||||
for (MTLContext *mtlc in [MTLContext.contextStore allValues]) {
|
||||
const NSArray<NSNumber*> *displayIDs = [mtlc getDisplayLinkDisplayIds]; // old ids
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenWillSleep: ctx=%p (%d displayLinks)",
|
||||
mtlc, (int) displayIDs.count);
|
||||
}
|
||||
for (NSNumber* displayIDVal in displayIDs) {
|
||||
const jint displayID = [displayIDVal intValue];
|
||||
const BOOL active = mtlc_IsDisplayReallyActive(displayID);
|
||||
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenWillSleep: displayId=%d active=%d", displayID, active);
|
||||
}
|
||||
if (TRACE_DISPLAY) {
|
||||
[MTLContext dumpDisplayInfo:displayID];
|
||||
}
|
||||
if ((notification.name == NSWorkspaceWillSleepNotification)|| !active) {
|
||||
[mtlc destroyDisplayLink:displayID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
MTLContextStoreNotification ctxNotif = MTLDCM_SYSTEM_UNDEFINED;
|
||||
if (notification.name == NSWorkspaceWillSleepNotification) {
|
||||
ctxNotif = MTLDCM_SYSTEM_SLEEP;
|
||||
} else if (notification.name == NSWorkspaceWillSleepNotification) {
|
||||
ctxNotif = MTLDCM_DISPLAY_SLEEP;
|
||||
}
|
||||
if (ctxNotif != MTLDCM_SYSTEM_UNDEFINED) {
|
||||
[ThreadUtilities performOnMainThreadNowOrLater:NO // critical
|
||||
block:^() {
|
||||
[MTLContext processContextStoreNotification:ctxNotif];
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)mtlc_systemOrScreenDidWake:(NSNotification*)notification {
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenDidWake[%@]", [notification name]);
|
||||
}
|
||||
if (isDisplaySyncEnabled()) {
|
||||
[ThreadUtilities performOnMainThreadNowOrLater:NO // critical
|
||||
block:^(){
|
||||
|
||||
for (MTLContext *mtlc in [MTLContext.contextStore allValues]) {
|
||||
const NSArray<NSNumber*>* displayIDs = [mtlc getDisplayLinkDisplayIds]; // old ids
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenDidWake: ctx=%p (%d displayLinks)",
|
||||
mtlc, (int)displayIDs.count);
|
||||
}
|
||||
for (NSNumber* displayIDVal in displayIDs) {
|
||||
const jint displayID = [displayIDVal intValue];
|
||||
const BOOL active = mtlc_IsDisplayReallyActive(displayID);
|
||||
|
||||
if (TRACE_PWM_NOTIF) {
|
||||
NSLog(@"MTLContext_systemOrScreenDidWake: displayId=%d active=%d", displayID, active);
|
||||
}
|
||||
if (TRACE_DISPLAY) {
|
||||
[MTLContext dumpDisplayInfo:displayID];
|
||||
}
|
||||
if (active) {
|
||||
// (if needed will start a new display link thread):
|
||||
[mtlc createDisplayLinkIfAbsent:displayID];
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
MTLContextStoreNotification ctxNotif = MTLDCM_SYSTEM_UNDEFINED;
|
||||
if (notification.name == NSWorkspaceDidWakeNotification) {
|
||||
ctxNotif = MTLDCM_SYSTEM_WAKEUP;
|
||||
} else if (notification.name == NSWorkspaceScreensDidWakeNotification) {
|
||||
ctxNotif = MTLDCM_DISPLAY_WAKEUP;
|
||||
}
|
||||
if (ctxNotif != MTLDCM_SYSTEM_UNDEFINED) {
|
||||
[ThreadUtilities performOnMainThreadNowOrLater:NO // critical
|
||||
block:^() {
|
||||
[MTLContext processContextStoreNotification:ctxNotif];
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -265,15 +256,17 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
if (!notificationRegistered) {
|
||||
notificationRegistered = true;
|
||||
|
||||
NSNotificationCenter *ctr = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
Class clz = [MTLContext class];
|
||||
if (isDisplaySyncEnabled()) {
|
||||
NSNotificationCenter *ctr = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
Class clz = [MTLContext class];
|
||||
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenWillSleep:) name:NSWorkspaceWillSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenDidWake:) name:NSWorkspaceDidWakeNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenWillSleep:) name:NSWorkspaceWillSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenDidWake:) name:NSWorkspaceDidWakeNotification object:nil];
|
||||
|
||||
// NSWorkspaceScreensDidWakeNotification is first sent:
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenWillSleep:) name:NSWorkspaceScreensDidSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenDidWake:) name:NSWorkspaceScreensDidWakeNotification object:nil];
|
||||
// NSWorkspaceScreensDidWakeNotification is first sent:
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenWillSleep:) name:NSWorkspaceScreensDidSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(mtlc_systemOrScreenDidWake:) name:NSWorkspaceScreensDidWakeNotification object:nil];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +282,82 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
return _contextStore;
|
||||
}
|
||||
|
||||
+ (void) processContextStoreNotification:(MTLContextStoreNotification)notification {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
if (isDisplaySyncEnabled()) {
|
||||
const char* name = mtlContextStoreNotificationToStr(notification);
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_processContextStoreNotification[%s]: enter", name);
|
||||
}
|
||||
|
||||
for (MTLContext *mtlc in [MTLContext.contextStore allValues]) {
|
||||
const NSArray<NSNumber*>* displayIDs = [mtlc getDisplayLinkDisplayIds]; // old ids
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_processContextStoreNotification[%s]: ctx=%p (%d displayLinks)",
|
||||
name, mtlc, (int)displayIDs.count);
|
||||
}
|
||||
for (NSNumber* displayIDVal in displayIDs) {
|
||||
const jint displayID = [displayIDVal intValue];
|
||||
// CGDisplayIsActive is not always reliable:
|
||||
BOOL active = CGDisplayIsActive(displayID) ? YES : NO;
|
||||
|
||||
if (active) {
|
||||
// Ensure mode is really valid:
|
||||
// CGDisplayCopyDisplayMode can return NULL if displayID is invalid
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
|
||||
if (mode != NULL) {
|
||||
active = isValidDisplayMode(mode);
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
}
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_processContextStoreNotification[%s]: displayId=%d active=%d",
|
||||
name, displayID, active);
|
||||
}
|
||||
if (TRACE_DISPLAY) {
|
||||
dumpDisplayInfo(displayID);
|
||||
}
|
||||
|
||||
switch (notification) {
|
||||
case MTLDCM_SYSTEM_SLEEP:
|
||||
// kill all CVDisplayLinks:
|
||||
[mtlc destroyDisplayLink:displayID];
|
||||
break;
|
||||
case MTLDCM_DISPLAY_SLEEP:
|
||||
if (!active) {
|
||||
// kill CVDisplayLinks for inactive displays:
|
||||
[mtlc destroyDisplayLink:displayID];
|
||||
}
|
||||
break;
|
||||
case MTLDCM_SYSTEM_WAKEUP:
|
||||
case MTLDCM_DISPLAY_WAKEUP:
|
||||
if (active) {
|
||||
// (if needed will start a new display link thread):
|
||||
[mtlc createDisplayLinkIfAbsent:@(displayID)];
|
||||
}
|
||||
break;
|
||||
case MTLDCM_DISPLAY_RECONFIGURE:
|
||||
if (active) {
|
||||
// (if needed will start a new display link thread):
|
||||
[mtlc createDisplayLinkIfAbsent:@(displayID)];
|
||||
} else {
|
||||
// kill CVDisplayLinks for inactive displays:
|
||||
[mtlc destroyDisplayLink:displayID];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NSLog(@"Unsupported notification : %d", notification);
|
||||
}
|
||||
}
|
||||
if (TRACE_NOTIF) {
|
||||
NSLog(@"MTLContext_processContextStoreNotification[%s]: exit", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (MTLContext*) createContextWithDeviceIfAbsent:(jint)displayID shadersLib:(NSString*)mtlShadersLib {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
// Initialization code here.
|
||||
// note: the device reference is NS_RETURNS_RETAINED, should be released by the caller:
|
||||
bool shouldReleaseDevice = true;
|
||||
@@ -326,8 +394,7 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
[mtlc release];
|
||||
J2dRlsTraceLn4(J2D_TRACE_INFO,
|
||||
"MTLContext_createContextWithDeviceIfAbsent: new context(%p) for display=%d device=\"%s\" "
|
||||
"retainCount=%d", mtlc, displayID, [mtlc.device.name UTF8String],
|
||||
mtlc.retainCount);
|
||||
"retainCount=%d", mtlc, displayID, [mtlc.device.name UTF8String], mtlc.retainCount);
|
||||
}
|
||||
} else {
|
||||
if (![mtlc.shadersLib isEqualToString:mtlShadersLib]) {
|
||||
@@ -340,18 +407,18 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
[mtlc retain];
|
||||
J2dRlsTraceLn4(J2D_TRACE_INFO,
|
||||
"MTLContext_createContextWithDeviceIfAbsent: reuse context(%p) for display=%d device=\"%s\" "
|
||||
"retainCount=%d", mtlc, displayID, [mtlc.device.name UTF8String],
|
||||
mtlc.retainCount);
|
||||
"retainCount=%d", mtlc, displayID, [mtlc.device.name UTF8String], mtlc.retainCount);
|
||||
}
|
||||
if (shouldReleaseDevice) {
|
||||
[device release];
|
||||
}
|
||||
// (will start a new display link thread if needed):
|
||||
[mtlc createDisplayLinkIfAbsent:displayID];
|
||||
[mtlc createDisplayLinkIfAbsent:@(displayID)];
|
||||
return mtlc;
|
||||
}
|
||||
|
||||
+ (void) releaseContext:(MTLContext*) mtlc {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
id<NSCopying> deviceID = nil;
|
||||
if (@available(macOS 10.13, *)) {
|
||||
deviceID = @(mtlc.device.registryID);
|
||||
@@ -377,6 +444,7 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
}
|
||||
|
||||
- (id)initWithDevice:(id<MTLDevice>)mtlDevice shadersLib:(NSString*)mtlShadersLib {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
self = [super init];
|
||||
if (self) {
|
||||
device = mtlDevice;
|
||||
@@ -424,126 +492,53 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (void)dumpDisplayInfo: (jint)displayID {
|
||||
// Returns a Boolean value indicating whether a display is active.
|
||||
jint displayIsActive = CGDisplayIsActive(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is always in a mirroring set.
|
||||
jint displayIsalwaysInMirrorSet = CGDisplayIsAlwaysInMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is sleeping (and is therefore not drawable).
|
||||
jint displayIsAsleep = CGDisplayIsAsleep(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is built-in, such as the internal display in portable systems.
|
||||
jint displayIsBuiltin = CGDisplayIsBuiltin(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is in a mirroring set.
|
||||
jint displayIsInMirrorSet = CGDisplayIsInMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is in a hardware mirroring set.
|
||||
jint displayIsInHWMirrorSet = CGDisplayIsInHWMirrorSet(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is the main display.
|
||||
jint displayIsMain = CGDisplayIsMain(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is connected or online.
|
||||
jint displayIsOnline = CGDisplayIsOnline(displayID);
|
||||
|
||||
// Returns a Boolean value indicating whether a display is running in a stereo graphics mode.
|
||||
jint displayIsStereo = CGDisplayIsStereo(displayID);
|
||||
|
||||
// For a secondary display in a mirroring set, returns the primary display.
|
||||
CGDirectDisplayID displayMirrorsDisplay = CGDisplayMirrorsDisplay(displayID);
|
||||
|
||||
// Returns the primary display in a hardware mirroring set.
|
||||
CGDirectDisplayID displayPrimaryDisplay = CGDisplayPrimaryDisplay(displayID);
|
||||
|
||||
// Returns the width and height of a display in millimeters.
|
||||
CGSize size = CGDisplayScreenSize(displayID);
|
||||
|
||||
NSLog(@"CGDisplay[%d]{\n"
|
||||
"displayIsActive=%d\n"
|
||||
"displayIsalwaysInMirrorSet=%d\n"
|
||||
"displayIsAsleep=%d\n"
|
||||
"displayIsBuiltin=%d\n"
|
||||
"displayIsInMirrorSet=%d\n"
|
||||
"displayIsInHWMirrorSet=%d\n"
|
||||
"displayIsMain=%d\n"
|
||||
"displayIsOnline=%d\n"
|
||||
"displayIsStereo=%d\n"
|
||||
"displayMirrorsDisplay=%d\n"
|
||||
"displayPrimaryDisplay=%d\n"
|
||||
"displayScreenSizey=[%.1lf %.1lf]\n",
|
||||
displayID,
|
||||
displayIsActive,
|
||||
displayIsalwaysInMirrorSet,
|
||||
displayIsAsleep,
|
||||
displayIsBuiltin,
|
||||
displayIsInMirrorSet,
|
||||
displayIsInHWMirrorSet,
|
||||
displayIsMain,
|
||||
displayIsOnline,
|
||||
displayIsStereo,
|
||||
displayMirrorsDisplay,
|
||||
displayPrimaryDisplay,
|
||||
size.width, size.height
|
||||
);
|
||||
|
||||
// CGDisplayCopyDisplayMode can return NULL if displayID is invalid
|
||||
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayID);
|
||||
if (mode) {
|
||||
// Getting Information About a Display Mode
|
||||
jint h = -1, w = -1, bpp = -1;
|
||||
jdouble refreshRate = 0.0;
|
||||
|
||||
// Returns the width of the specified display mode.
|
||||
w = CGDisplayModeGetWidth(mode);
|
||||
|
||||
// Returns the height of the specified display mode.
|
||||
h = CGDisplayModeGetHeight(mode);
|
||||
|
||||
// Returns the pixel encoding of the specified display mode.
|
||||
// Deprecated
|
||||
CFStringRef currentBPP = CGDisplayModeCopyPixelEncoding(mode);
|
||||
bpp = getBPPFromModeString(currentBPP);
|
||||
CFRelease(currentBPP);
|
||||
|
||||
// Returns the refresh rate of the specified display mode.
|
||||
refreshRate = CGDisplayModeGetRefreshRate(mode);
|
||||
|
||||
NSLog(@"CGDisplayMode[%d]: w=%d, h=%d, bpp=%d, freq=%.2lf hz",
|
||||
displayID, w, h, bpp, refreshRate);
|
||||
|
||||
CGDisplayModeRelease(mode);
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray<NSNumber*>*)getDisplayLinkDisplayIds {
|
||||
return [_displayLinkStates allKeys];
|
||||
}
|
||||
|
||||
- (void)createDisplayLinkIfAbsent: (jint)displayID {
|
||||
if (isDisplaySyncEnabled()) {
|
||||
MTLDisplayLinkState *dlState = [self getDisplayLinkState:displayID];
|
||||
- (void)createDisplayLinkIfAbsent: (NSNumber*)displayID {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
if (_displayLinkStates != nil) {
|
||||
MTLDisplayLinkState *dlState = [self getDisplayLinkState:[displayID intValue]];
|
||||
if ((dlState != nil) && (dlState->displayLink != nil)) {
|
||||
return;
|
||||
}
|
||||
if (TRACE_DISPLAY) {
|
||||
[MTLContext dumpDisplayInfo:displayID];
|
||||
dumpDisplayInfo([displayID intValue]);
|
||||
}
|
||||
CVDisplayLinkRef _displayLink;
|
||||
if (TRACE_CVLINK) {
|
||||
J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "MTLContext_createDisplayLinkIfAbsent: "
|
||||
"ctx=%p displayID=%d", self, displayID);
|
||||
"ctx=%p displayID=%d", self, [displayID intValue]);
|
||||
}
|
||||
|
||||
CHECK_CVLINK("CreateWithCGDisplay", nil, &_displayLink,
|
||||
CVDisplayLinkCreateWithCGDisplay(displayID, &_displayLink));
|
||||
CVDisplayLinkCreateWithCGDisplay([displayID intValue], &_displayLink));
|
||||
|
||||
if (_displayLink == nil) {
|
||||
J2dRlsTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLContext_createDisplayLinkIfAbsent: Failed to initialize CVDisplayLink.");
|
||||
|
||||
if (dlState == nil) {
|
||||
dlState = malloc(sizeof(MTLDisplayLinkState));
|
||||
dlState->displayID = [displayID intValue];
|
||||
dlState->displayLink = nil;
|
||||
dlState->failCount = 0;
|
||||
_displayLinkStates[displayID] = [NSValue valueWithPointer:dlState];
|
||||
}
|
||||
|
||||
if (dlState->failCount >= MAX_DISPLAYLINK_FAIL_COUNT) {
|
||||
J2dTraceLn(J2D_TRACE_ERROR,
|
||||
"MTLLayer.createDisplayLink --- unable to create CVDisplayLink.");
|
||||
dlState->failCount = 0;
|
||||
return;
|
||||
}
|
||||
dlState->failCount++;
|
||||
[self performSelector:@selector(createDisplayLinkIfAbsent:)
|
||||
withObject:displayID
|
||||
afterDelay:CV_DISPLAYLINK_FAIL_DELAY];
|
||||
} else {
|
||||
J2dRlsTraceLn3(J2D_TRACE_INFO, "MTLContext_destroyDisplayLinkMTLContext_createDisplayLinkIfAbsent["
|
||||
J2dRlsTraceLn3(J2D_TRACE_INFO, "MTLContext_createDisplayLinkIfAbsent["
|
||||
"ctx=%p displayID=%d] displayLink=%p",
|
||||
self, displayID, _displayLink);
|
||||
bool isNewDisplayLink = false;
|
||||
@@ -552,11 +547,12 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
isNewDisplayLink = true;
|
||||
}
|
||||
// update:
|
||||
dlState->displayID = displayID;
|
||||
dlState->displayID = [displayID intValue];
|
||||
dlState->displayLink = _displayLink;
|
||||
dlState->mtlc = self;
|
||||
|
||||
dlState->redrawCount = 0;
|
||||
dlState->failCount = 0;
|
||||
dlState->avgDisplayLinkSamples = 0;
|
||||
dlState->lastRedrawTime = 0.0;
|
||||
dlState->lastDisplayLinkTime = 0.0;
|
||||
@@ -565,7 +561,7 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
|
||||
if (isNewDisplayLink) {
|
||||
// publish fully initialized object:
|
||||
_displayLinkStates[@(displayID)] = [NSValue valueWithPointer:dlState];
|
||||
_displayLinkStates[displayID] = [NSValue valueWithPointer:dlState];
|
||||
}
|
||||
|
||||
CHECK_CVLINK("SetOutputCallback", nil, &_displayLink,
|
||||
@@ -595,7 +591,8 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
}
|
||||
|
||||
- (void)destroyDisplayLink: (jint)displayID {
|
||||
if (isDisplaySyncEnabled()) {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
if (_displayLinkStates != nil) {
|
||||
MTLDisplayLinkState *dlState = [self getDisplayLinkState:displayID];
|
||||
if (dlState == nil) {
|
||||
return;
|
||||
@@ -620,17 +617,21 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
// Release display link thread:
|
||||
CVDisplayLinkRelease(_displayLink);
|
||||
dlState->displayLink = nil;
|
||||
J2dRlsTraceLn2(J2D_TRACE_INFO, "MTLContext_destroyDisplayLink["
|
||||
"ctx=%p displayID=%d] done",
|
||||
self, displayID);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleDisplayLink: (BOOL)enabled displayID:(jint)displayID source:(const char*)src {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
MTLDisplayLinkState *dlState = [self getDisplayLinkState:displayID];
|
||||
if (dlState == nil) {
|
||||
return;
|
||||
}
|
||||
CVDisplayLinkRef _displayLink = dlState->displayLink;
|
||||
if (_displayLink == nil) {
|
||||
if (TRACE_CVLINK) {
|
||||
if (TRACE_CVLINK_DEBUG) {
|
||||
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, "MTLContext_handleDisplayLink[%s]: "
|
||||
"displayLink is nil (disabled).", src);
|
||||
}
|
||||
@@ -1023,7 +1024,6 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
|
||||
- (void) redraw:(NSNumber*)displayIDNumber {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
const CFTimeInterval now = CACurrentMediaTime();
|
||||
|
||||
const jint displayID = [displayIDNumber intValue];
|
||||
MTLDisplayLinkState *dlState = [self getDisplayLinkState:displayID];
|
||||
@@ -1034,6 +1034,7 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
* Avoid repeated invocations by UIKit Main Thread
|
||||
* if blocked while many mtlDisplayLinkCallback() are dispatched
|
||||
*/
|
||||
const CFTimeInterval now = CACurrentMediaTime();
|
||||
const CFTimeInterval elapsed = (dlState->lastRedrawTime != 0.0) ? (now - dlState->lastRedrawTime) : -1.0;
|
||||
|
||||
CFTimeInterval threshold = (dlState->avgDisplayLinkSamples >= 10) ?
|
||||
@@ -1078,7 +1079,7 @@ extern void initSamplers(id<MTLDevice> device);
|
||||
}
|
||||
|
||||
CVReturn mtlDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* nowTime, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) {
|
||||
JNI_COCOA_ENTER(env);
|
||||
JNI_COCOA_ENTER();
|
||||
J2dTraceLn1(J2D_TRACE_VERBOSE, "MTLContext_mtlDisplayLinkCallback: ctx=%p", displayLinkContext);
|
||||
|
||||
MTLDisplayLinkState *dlState = (__bridge MTLDisplayLinkState*) displayLinkContext;
|
||||
@@ -1110,25 +1111,18 @@ CVReturn mtlDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp*
|
||||
}
|
||||
}
|
||||
|
||||
const BOOL active = mtlc_IsDisplayReallyActive(displayID);
|
||||
if (TRACE_CVLINK_DEBUG) {
|
||||
NSLog(@"MTLContext_mtlDisplayLinkCallback: ctx=%p displayID=%d active=%d (display link = %p)",
|
||||
mtlc, displayID, active, dlState->displayLink);
|
||||
}
|
||||
if (!active) {
|
||||
if (TRACE_CVLINK) {
|
||||
NSLog(@"MTLContext_mtlDisplayLinkCallback: displayId=%d active=%d "
|
||||
"=> destroyDisplayLink", displayID, active);
|
||||
/* defensive programming (should not happen) */
|
||||
if ([ThreadUtilities blockingMainThread]) {
|
||||
if (TRACE_CVLINK_WARN) {
|
||||
NSLog(@"MTLContext_mtlDisplayLinkCallback: ctx=%p - invalid state: blockingMainThread = YES !",
|
||||
displayLinkContext);
|
||||
}
|
||||
if (TRACE_DISPLAY) {
|
||||
[MTLContext dumpDisplayInfo:displayID];
|
||||
}
|
||||
[mtlc destroyDisplayLink:displayID];
|
||||
} else {
|
||||
[ThreadUtilities performOnMainThread:@selector(redraw:) on:mtlc withObject:@(displayID)
|
||||
waitUntilDone:NO useJavaModes:NO]; // critical
|
||||
return kCVReturnError;
|
||||
}
|
||||
JNI_COCOA_EXIT(env);
|
||||
|
||||
[ThreadUtilities performOnMainThread:@selector(redraw:) on:mtlc withObject:@(displayID)
|
||||
waitUntilDone:NO useJavaModes:NO]; // critical
|
||||
JNI_COCOA_EXIT();
|
||||
return kCVReturnSuccess;
|
||||
}
|
||||
|
||||
@@ -1183,6 +1177,7 @@ CVReturn mtlDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp*
|
||||
}
|
||||
|
||||
- (void)haltRedraw {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
if (_displayLinkStates != nil) {
|
||||
if (TRACE_CVLINK) {
|
||||
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, "MTLContext_haltRedraw: ctx=%p", self);
|
||||
@@ -1194,7 +1189,12 @@ CVReturn mtlDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp*
|
||||
[_layers removeAllObjects];
|
||||
}
|
||||
if (_displayLinkStates.count > 0) {
|
||||
for (NSNumber* displayIDVal in [self getDisplayLinkDisplayIds]) {
|
||||
const NSArray<NSNumber*>* displayIDs = [self getDisplayLinkDisplayIds]; // old ids
|
||||
if (TRACE_CVLINK) {
|
||||
NSLog(@"MTLContext_haltRedraw: ctx=%p (%d displayLinks)",
|
||||
self, (int) displayIDs.count);
|
||||
}
|
||||
for (NSNumber* displayIDVal in displayIDs) {
|
||||
const jint displayID = [displayIDVal intValue];
|
||||
[self destroyDisplayLink:displayID];
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@@ -127,3 +127,14 @@ Java_sun_java2d_metal_MTLGraphicsConfig_nativeGetMaxTextureSize
|
||||
|
||||
return (jint)MTL_GPU_FAMILY_MAC_TXT_SIZE;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_sun_java2d_metal_MTLGraphicsConfig_displayReconfigurationDone
|
||||
(JNIEnv *env, jclass mtlgc)
|
||||
{
|
||||
JNI_COCOA_ENTER(env);
|
||||
|
||||
[MTLContext processContextStoreNotification:MTLDCM_DISPLAY_RECONFIGURE];
|
||||
|
||||
JNI_COCOA_EXIT(env);
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "[%.6lf] MTLLayer_blitTexture: skip drawable [skip blit] nextDrawableCount = %d",
|
||||
CACurrentMediaTime(), self.nextDrawableCount);
|
||||
}
|
||||
[self startRedraw];
|
||||
[self startRedrawIfNeeded];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
}
|
||||
|
||||
- (void) blitCallback {
|
||||
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnv];
|
||||
GET_MTL_LAYER_CLASS();
|
||||
DECLARE_METHOD(jm_drawInMTLContext, jc_JavaLayer, "drawInMTLContext", "()V");
|
||||
@@ -395,10 +395,8 @@ BOOL MTLLayer_isExtraRedrawEnabled() {
|
||||
|
||||
- (void)startRedrawIfNeeded {
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
if (isDisplaySyncEnabled()) {
|
||||
if (self.redrawCount == 0) {
|
||||
[self.ctx startRedraw:self];
|
||||
}
|
||||
if (isDisplaySyncEnabled() && (self.redrawCount == 0)) {
|
||||
[self.ctx startRedraw:self];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -121,8 +121,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_getCGLConfigInfo
|
||||
{
|
||||
__block jlong ret = 0L;
|
||||
JNI_COCOA_ENTER(env);
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES useJavaModes:NO // critical
|
||||
block:^(){
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
|
||||
@@ -351,8 +350,7 @@ Java_sun_java2d_opengl_CGLGraphicsConfig_nativeGetMaxTextureSize
|
||||
|
||||
__block int max = 0;
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES useJavaModes:NO // critical
|
||||
block:^(){
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
[sharedContext makeCurrentContext];
|
||||
j2d_glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max);
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@@ -176,8 +176,7 @@ JNI_COCOA_ENTER(env);
|
||||
|
||||
jobject javaLayer = (*env)->NewWeakGlobalRef(env, obj);
|
||||
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES useJavaModes:NO // critical
|
||||
block:^(){
|
||||
[ThreadUtilities performOnMainThreadWaiting:YES block:^(){
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
layer = [[CGLLayer alloc] initWithJavaLayer: javaLayer];
|
||||
}];
|
||||
@@ -225,8 +224,7 @@ Java_sun_java2d_opengl_CGLLayer_nativeSetScale
|
||||
// this method where we need to change native texture size and layer's scale
|
||||
// in one call on appkit, otherwise we'll get window's contents blinking,
|
||||
// during screen-2-screen moving.
|
||||
[ThreadUtilities performOnMainThreadNowOrLater:NO // critical
|
||||
block:^(){
|
||||
[ThreadUtilities performOnMainThreadWaiting:[NSThread isMainThread] block:^(){
|
||||
layer.contentsScale = scale;
|
||||
}];
|
||||
JNI_COCOA_EXIT(env);
|
||||
|
||||
@@ -315,8 +315,7 @@ OGLSD_Flush(JNIEnv *env)
|
||||
CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps;
|
||||
CGLLayer *layer = (CGLLayer*)dstCGLOps->layer;
|
||||
if (layer != NULL) {
|
||||
[ThreadUtilities performOnMainThreadWaiting:NO useJavaModes:NO // critical
|
||||
block:^(){
|
||||
[ThreadUtilities performOnMainThreadWaiting:NO block:^(){
|
||||
AWT_ASSERT_APPKIT_THREAD;
|
||||
[layer setNeedsDisplay];
|
||||
}];
|
||||
|
||||
@@ -127,25 +127,46 @@ do { \
|
||||
#endif /* AWT_THREAD_ASSERTS */
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
/* bit flag to coalesce CGDisplayReconfigureCallbacks */
|
||||
#define MAIN_CALLBACK_CGDISPLAY_RECONFIGURE 1
|
||||
|
||||
@interface RunLoopCallbackQueue : NSObject
|
||||
|
||||
@property(readwrite, atomic) u_long coalesingflags;
|
||||
@property(retain) NSMutableArray* queue;
|
||||
|
||||
+ (RunLoopCallbackQueue*) shared;
|
||||
|
||||
- (id) init;
|
||||
- (void) dealloc;
|
||||
|
||||
- (BOOL)hasCallback:(u_long)bit;
|
||||
|
||||
- (BOOL)addCallback:(u_long)bit block:(void (^)())block;
|
||||
- (void)processQueuedCallbacks;
|
||||
@end
|
||||
|
||||
|
||||
@interface ThreadTraceContext : NSObject <NSCopying>
|
||||
@property (readwrite, atomic) BOOL sleep;
|
||||
@property (readwrite, atomic) BOOL useJavaModes;
|
||||
@property (readwrite, atomic) long actionId;
|
||||
@property (readwrite, atomic) char* operation;
|
||||
@property (readwrite, atomic) CFTimeInterval timestamp;
|
||||
@property (readwrite, atomic, retain) NSString* threadName;
|
||||
@property (readwrite, atomic, retain) NSString* caller;
|
||||
@property (readwrite, atomic, retain) NSString* callStack;
|
||||
|
||||
/* autorelease in init and copy */
|
||||
- (id)init;
|
||||
- (void)reset;
|
||||
- (void)updateThreadState:(BOOL)sleepValue;
|
||||
@property (readwrite, atomic) BOOL sleep;
|
||||
@property (readwrite, atomic) BOOL useJavaModes;
|
||||
@property (readwrite, atomic) long actionId;
|
||||
@property (readwrite, atomic) const char* operation;
|
||||
@property (readwrite, atomic) CFTimeInterval timestamp;
|
||||
@property (readwrite, atomic, retain) NSString* threadName;
|
||||
@property (readwrite, atomic, retain) NSString* caller;
|
||||
@property (readwrite, atomic, retain) NSString* callStack;
|
||||
|
||||
- (void)set:(long)pActionId operation:(char*)pOperation useJavaModes:(BOOL)pUseJavaModes
|
||||
caller:(NSString *)pCaller callstack:(NSString *)pCallStack;
|
||||
/* autorelease in init and copy */
|
||||
- (id)init:(NSString*)threadName;
|
||||
- (void)reset;
|
||||
- (void)updateThreadState:(BOOL)sleepValue;
|
||||
|
||||
- (const char*)identifier;
|
||||
- (void)set:(long)pActionId operation:(const char*)pOperation useJavaModes:(BOOL)pUseJavaModes
|
||||
caller:(NSString *)pCaller callstack:(NSString *)pCallStack;
|
||||
|
||||
- (const char*)identifier;
|
||||
@end
|
||||
|
||||
|
||||
@@ -175,20 +196,24 @@ __attribute__((visibility("default")))
|
||||
+ (NSString*)criticalRunLoopMode;
|
||||
+ (NSString*)javaRunLoopMode;
|
||||
|
||||
+ (void)setBlockingMainThread:(BOOL)value;
|
||||
+ (BOOL)blockingMainThread;
|
||||
|
||||
/* internal special RunLoop callbacks */
|
||||
+ (void)registerMainThreadRunLoopCallback:(u_long)coalesingBit block:(void (^)())block;
|
||||
|
||||
/* native thread tracing */
|
||||
+ (ThreadTraceContext*)getTraceContext;
|
||||
+ (void)removeTraceContext;
|
||||
+ (void)resetTraceContext;
|
||||
|
||||
+ (ThreadTraceContext*)recordTraceContext;
|
||||
+ (ThreadTraceContext*)recordTraceContext:(NSString*)prefix;
|
||||
+ (ThreadTraceContext*)recordTraceContext:(NSString*)prefix actionId:(long)actionId useJavaModes:(BOOL)useJavaModes operation:(char*) operation;
|
||||
+ (ThreadTraceContext*)recordTraceContext:(NSString*)prefix actionId:(long)actionId useJavaModes:(BOOL)useJavaModes operation:(const char*)pOperation;
|
||||
|
||||
+ (void)dumpThreadTraceContext;
|
||||
+ (void)dumpThreadTraceContext:(const char*)pOperation;
|
||||
|
||||
+ (NSString*)getThreadTraceContexts;
|
||||
|
||||
+ (void)registerForSystemAndScreenNotifications;
|
||||
+ (BOOL)isWithinPowerTransition:(double)periodInSeconds;
|
||||
@end
|
||||
|
||||
JNIEXPORT void OSXAPP_SetJavaVM(JavaVM *vm);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@@ -37,8 +37,8 @@
|
||||
return; \
|
||||
}
|
||||
|
||||
#define RUN_BLOCK_IF_MAIN(block) \
|
||||
RUN_BLOCK_IF([NSThread isMainThread], block)
|
||||
/* See LWCToolkit.APPKIT_THREAD_NAME */
|
||||
#define MAIN_THREAD_NAME "AppKit Thread"
|
||||
|
||||
/* Returns the MainThread latency threshold in milliseconds
|
||||
* used to detect slow operations that may cause high latencies or delays.
|
||||
@@ -62,7 +62,7 @@ int getMainThreadLatencyThreshold() {
|
||||
}
|
||||
|
||||
static const char* toCString(id obj) {
|
||||
return obj == nil ? "nil" : [NSString stringWithFormat:@"%@", obj].UTF8String;
|
||||
return (obj == nil) ? "nil" : [NSString stringWithFormat:@"%@", obj].UTF8String;
|
||||
}
|
||||
|
||||
// The following must be named "jvm", as there are extern references to it in AWT
|
||||
@@ -78,47 +78,18 @@ static NSArray<NSString*> *allModesExceptJava = nil;
|
||||
/* Traceability data */
|
||||
static const BOOL forceTracing = NO;
|
||||
static const BOOL enableTracing = NO || forceTracing;
|
||||
static const BOOL enableTracingLog = YES && enableTracing;
|
||||
static const BOOL enableCallStacks = YES && enableTracing;
|
||||
|
||||
static const BOOL enableRunLoopObserver = NO;
|
||||
static const BOOL enableTracingLog = NO;
|
||||
static const BOOL enableTracingNSLog = YES && enableTracingLog;
|
||||
static const BOOL enableCallStacks = YES;
|
||||
|
||||
/* Traceability data */
|
||||
static const BOOL TRACE_PWM = NO;
|
||||
static const BOOL TRACE_PWM_EVENTS = NO;
|
||||
static const BOOL TRACE_CLOCKS = NO;
|
||||
|
||||
static const uint64_t NANOS_PER_SEC = 1000000000ULL;
|
||||
static const double SEC_PER_NANOS = 1e9;
|
||||
static const int TRACE_BLOCKING_FLAGS = 0;
|
||||
|
||||
/* RunLoop traceability identifier generators */
|
||||
static atomic_long runLoopId = 0L;
|
||||
static atomic_long mainThreadActionId = 0L;
|
||||
|
||||
static atomic_uint_least64_t sleepTime = 0LL;
|
||||
static atomic_uint_least64_t wakeUpTime = 0LL;
|
||||
|
||||
bool _getTime_nanos(clockid_t clock_id, atomic_uint_least64_t *nanotime) {
|
||||
struct timespec tp;
|
||||
// Use the given clock:
|
||||
int status = clock_gettime(clock_id, &tp);
|
||||
if (status != 0) {
|
||||
return false;
|
||||
}
|
||||
*nanotime = tp.tv_sec * NANOS_PER_SEC + tp.tv_nsec;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _nanoUpTime(atomic_uint_least64_t *nanotime) {
|
||||
// Use a monotonic clock (linearly increasing by each tick)
|
||||
// but not counting the time while sleeping.
|
||||
// NOTE:CLOCK_UPTIME_RAW seems counting more elapsed time
|
||||
// arround sleep/wake-up cycle than CLOCK_PROCESS_CPUTIME_ID (adopted):
|
||||
return _getTime_nanos(CLOCK_PROCESS_CPUTIME_ID, nanotime);
|
||||
}
|
||||
|
||||
static inline void doLog(JNIEnv* env, const char *formatMsg, ...) {
|
||||
if (forceTracing) {
|
||||
if (enableTracingNSLog) {
|
||||
va_list args;
|
||||
va_start(args, formatMsg);
|
||||
|
||||
@@ -145,7 +116,7 @@ static inline void attachCurrentThread(void** env) {
|
||||
if ([NSThread isMainThread]) {
|
||||
JavaVMAttachArgs args;
|
||||
args.version = JNI_VERSION_1_4;
|
||||
args.name = "AppKit Thread";
|
||||
args.name = MAIN_THREAD_NAME;
|
||||
args.group = appkitThreadGroup;
|
||||
(*jvm)->AttachCurrentThreadAsDaemon(jvm, env, &args);
|
||||
} else {
|
||||
@@ -155,8 +126,9 @@ static inline void attachCurrentThread(void** env) {
|
||||
|
||||
@implementation ThreadUtilities
|
||||
|
||||
static BOOL _blockingEventDispatchThread = NO;
|
||||
static long eventDispatchThreadPtr = (long)nil;
|
||||
static BOOL _blockingEventDispatchThread = NO;
|
||||
static BOOL _blockingMainThread = NO;
|
||||
|
||||
static BOOL isEventDispatchThread() {
|
||||
return (long)[NSThread currentThread] == eventDispatchThreadPtr;
|
||||
@@ -165,6 +137,9 @@ static BOOL isEventDispatchThread() {
|
||||
// The [blockingEventDispatchThread] property is readonly, so we implement a private setter
|
||||
static void setBlockingEventDispatchThread(BOOL value) {
|
||||
assert([NSThread isMainThread]);
|
||||
if ((TRACE_BLOCKING_FLAGS & 1) != 0) {
|
||||
NSLog(@"setBlockingEventDispatchThread(%s)", value ? "YES" : "NO");
|
||||
}
|
||||
_blockingEventDispatchThread = value;
|
||||
}
|
||||
|
||||
@@ -173,6 +148,18 @@ static void setBlockingEventDispatchThread(BOOL value) {
|
||||
return _blockingEventDispatchThread;
|
||||
}
|
||||
|
||||
+ (void)setBlockingMainThread:(BOOL)value {
|
||||
assert([NSThread isMainThread]);
|
||||
if ((TRACE_BLOCKING_FLAGS & 2) != 0) {
|
||||
NSLog(@"setBlockingMainThread(%s)", value ? "YES" : "NO");
|
||||
}
|
||||
_blockingMainThread = value;
|
||||
}
|
||||
|
||||
+ (BOOL)blockingMainThread {
|
||||
return _blockingMainThread;
|
||||
}
|
||||
|
||||
+ (void)initialize {
|
||||
/* All the standard modes plus the Critical mode */
|
||||
allModesExceptJava = [[NSArray alloc] initWithObjects:NSRunLoopCommonModes,
|
||||
@@ -214,71 +201,41 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
if (enableTracing) {
|
||||
// Record thread stack now and return another copy (auto-released):
|
||||
[ThreadUtilities recordTraceContext];
|
||||
@try {
|
||||
if (enableRunLoopObserver) {
|
||||
CFRunLoopObserverRef logObserver = CFRunLoopObserverCreateWithHandler(
|
||||
NULL, // CFAllocator
|
||||
kCFRunLoopAllActivities, // CFOptionFlags
|
||||
true, // repeats
|
||||
NSIntegerMin, // order = max priority
|
||||
^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
|
||||
if ([[NSThread currentThread] isMainThread]) {
|
||||
char *activityName = NULL;
|
||||
switch (activity) {
|
||||
default:
|
||||
break;
|
||||
case kCFRunLoopEntry:
|
||||
activityName = "RunLoopEntry";
|
||||
/* Increment global main RunLoop id */
|
||||
runLoopId++;
|
||||
break;
|
||||
case kCFRunLoopBeforeTimers:
|
||||
activityName = "RunLoopBeforeTimers";
|
||||
break;
|
||||
case kCFRunLoopBeforeSources :
|
||||
activityName = "RunLoopBeforeSources";
|
||||
break;
|
||||
case kCFRunLoopBeforeWaiting:
|
||||
activityName = "RunLoopBeforeWaiting";
|
||||
break;
|
||||
case kCFRunLoopAfterWaiting:
|
||||
activityName = "RunLoopAfterWaiting";
|
||||
break;
|
||||
case kCFRunLoopExit:
|
||||
activityName = "RunLoopExit";
|
||||
break;
|
||||
case kCFRunLoopAllActivities:
|
||||
activityName = "RunLoopAllActivities";
|
||||
break;
|
||||
}
|
||||
if (activityName != NULL) {
|
||||
NSLog(@"RunLoop[on %s][%lu]: processing %s on mode = '%@'",
|
||||
NSThread.currentThread.name.UTF8String, runLoopId, activityName,
|
||||
NSRunLoop.currentRunLoop.currentMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
@try {
|
||||
// Start callback queue:
|
||||
[RunLoopCallbackQueue shared];
|
||||
|
||||
CFRunLoopRef runLoop = [[NSRunLoop mainRunLoop] getCFRunLoop];
|
||||
CFRunLoopAddObserver(runLoop, logObserver, kCFRunLoopDefaultMode);
|
||||
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(
|
||||
NULL, // CFAllocator
|
||||
kCFRunLoopAllActivities, // CFOptionFlags
|
||||
true, // repeats
|
||||
NSIntegerMin, // order (Highest priority = earliest)
|
||||
^(CFRunLoopObserverRef observerRef, CFRunLoopActivity activity)
|
||||
{
|
||||
// Run any registered callback:
|
||||
[[RunLoopCallbackQueue shared] processQueuedCallbacks];
|
||||
}
|
||||
);
|
||||
// Register observer on the Main RunLoop for all modes (common, critical & java):
|
||||
CFRunLoopRef mainRunLoop = [[NSRunLoop mainRunLoop] getCFRunLoop];
|
||||
CFRunLoopAddObserver(mainRunLoop, observer, kCFRunLoopCommonModes);
|
||||
|
||||
CFStringRef criticalModeRef = (__bridge CFStringRef) CriticalRunLoopMode;
|
||||
CFRunLoopAddObserver(runLoop, logObserver, criticalModeRef);
|
||||
CFStringRef criticalModeRef = (__bridge CFStringRef) CriticalRunLoopMode;
|
||||
CFRunLoopAddObserver(mainRunLoop, observer, criticalModeRef);
|
||||
CFRelease(criticalModeRef);
|
||||
|
||||
CFStringRef javaModeRef = (__bridge CFStringRef) JavaRunLoopMode;
|
||||
CFRunLoopAddObserver(runLoop, logObserver, javaModeRef);
|
||||
CFStringRef javaModeRef = (__bridge CFStringRef) JavaRunLoopMode;
|
||||
CFRunLoopAddObserver(mainRunLoop, observer, javaModeRef);
|
||||
CFRelease(javaModeRef);
|
||||
CFRelease(observer);
|
||||
|
||||
CFRelease(javaModeRef);
|
||||
CFRelease(criticalModeRef);
|
||||
CFRelease(logObserver);
|
||||
}
|
||||
} @finally {
|
||||
} @finally {
|
||||
if (enableTracing) {
|
||||
// Finally reset Main thread context in context store:
|
||||
[ThreadUtilities resetTraceContext];
|
||||
}
|
||||
}
|
||||
[ThreadUtilities registerForSystemAndScreenNotifications];
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -331,7 +288,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
+ (void)performOnMainThreadNowOrLater:(BOOL)useJavaModes
|
||||
block:(void (^)())block
|
||||
{
|
||||
RUN_BLOCK_IF_MAIN(block);
|
||||
RUN_BLOCK_IF([NSThread isMainThread], block);
|
||||
|
||||
[ThreadUtilities performOnMainThread:@selector(invokeBlockCopy:) on:self withObject:Block_copy(block)
|
||||
waitUntilDone:NO useJavaModes:useJavaModes];
|
||||
@@ -353,7 +310,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
useJavaModes:(BOOL)useJavaModes
|
||||
block:(void (^)())block
|
||||
{
|
||||
RUN_BLOCK_IF_MAIN(block);
|
||||
RUN_BLOCK_IF([NSThread isMainThread] && wait, block);
|
||||
|
||||
[ThreadUtilities performOnMainThread:@selector(invokeBlockCopy:) on:self withObject:Block_copy(block)
|
||||
waitUntilDone:wait useJavaModes:useJavaModes];
|
||||
@@ -434,7 +391,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
waitUntilDone:(BOOL)wait
|
||||
useJavaModes:(BOOL)useJavaModes
|
||||
{
|
||||
const BOOL invokeDirect = NSThread.isMainThread && wait;
|
||||
const BOOL invokeDirect = [NSThread isMainThread] && wait;
|
||||
const BOOL doWait = !invokeDirect && wait;
|
||||
const BOOL blockingEDT = doWait && isEventDispatchThread();
|
||||
|
||||
@@ -551,6 +508,22 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
return JavaRunLoopMode;
|
||||
}
|
||||
|
||||
/* internal special RunLoop callbacks */
|
||||
|
||||
+ (BOOL)hasMainThreadRunLoopCallback:(u_long)coalesingBit {
|
||||
return [[RunLoopCallbackQueue shared] hasCallback:coalesingBit];
|
||||
}
|
||||
|
||||
+ (void)registerMainThreadRunLoopCallback:(u_long)coalesingBit block:(void (^)())block {
|
||||
[[RunLoopCallbackQueue shared] addCallback:coalesingBit block:block];
|
||||
}
|
||||
|
||||
/* native thread tracing */
|
||||
|
||||
+ (NSString*) getCurrentThreadName {
|
||||
return ([NSThread isMainThread]) ? @MAIN_THREAD_NAME : [[NSThread currentThread] name];
|
||||
}
|
||||
|
||||
+ (NSMutableDictionary*)threadContextStore {
|
||||
static NSMutableDictionary<NSString*, ThreadTraceContext*>* _threadTraceContextPerName;
|
||||
static dispatch_once_t oncePredicate;
|
||||
@@ -562,14 +535,14 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
}
|
||||
|
||||
+ (ThreadTraceContext*)getTraceContext {
|
||||
const NSString* thName = [[NSThread currentThread] name];
|
||||
NSString* thName = [ThreadUtilities getCurrentThreadName];
|
||||
|
||||
NSMutableDictionary* allContexts = [ThreadUtilities threadContextStore];
|
||||
ThreadTraceContext* thCtx = allContexts[thName];
|
||||
|
||||
if (thCtx == nil) {
|
||||
// Create the empty thread context (auto-released):
|
||||
thCtx = [[[ThreadTraceContext alloc] init] autorelease];
|
||||
thCtx = [[[ThreadTraceContext alloc] init:thName] autorelease];
|
||||
allContexts[thName] = thCtx;
|
||||
}
|
||||
return thCtx;
|
||||
@@ -579,7 +552,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
* TODO: call when Threads are destroyed.
|
||||
*/
|
||||
+ (void)removeTraceContext {
|
||||
const NSString* thName = [[NSThread currentThread] name];
|
||||
const NSString* thName = [ThreadUtilities getCurrentThreadName];
|
||||
[[ThreadUtilities threadContextStore] removeObjectForKey:thName];
|
||||
}
|
||||
|
||||
@@ -595,10 +568,14 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
return [ThreadUtilities recordTraceContext:prefix actionId:-1 useJavaModes:NO operation:""];
|
||||
}
|
||||
|
||||
+ (ThreadTraceContext*)recordTraceContext:(NSString*) prefix operation:(const char*)pOperation {
|
||||
return [ThreadUtilities recordTraceContext:prefix actionId:-1 useJavaModes:NO operation:pOperation];
|
||||
}
|
||||
|
||||
+ (ThreadTraceContext*)recordTraceContext:(NSString*) prefix
|
||||
actionId:(long) actionId
|
||||
useJavaModes:(BOOL) useJavaModes
|
||||
operation:(char*) operation
|
||||
operation:(const char*)pOperation
|
||||
{
|
||||
ThreadTraceContext *thCtx = [ThreadUtilities getTraceContext];
|
||||
|
||||
@@ -606,18 +583,18 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
NSString *caller = [ThreadUtilities getCaller:prefix];
|
||||
NSString *callStack = (enableCallStacks) ? [ThreadUtilities getCallerStack:prefix] : nil;
|
||||
// update recorded thread state:
|
||||
[thCtx set:actionId operation:operation useJavaModes:useJavaModes caller:caller callstack:callStack];
|
||||
[thCtx set:actionId operation:pOperation useJavaModes:useJavaModes caller:caller callstack:callStack];
|
||||
|
||||
// Record thread stack now and return another copy (auto-released):
|
||||
return [[thCtx copy] autorelease];
|
||||
}
|
||||
|
||||
+ (void)dumpThreadTraceContext {
|
||||
+ (void)dumpThreadTraceContext:(const char*)pOperation {
|
||||
if (enableTracingLog) {
|
||||
JNIEnv *env = [ThreadUtilities getJNIEnvUncached];
|
||||
// Record thread stack now and return another copy (auto-released):
|
||||
ThreadTraceContext* thCtx = [ThreadUtilities recordTraceContext];
|
||||
doLog(env, "dumpThreadTraceContext: %s", toCString([thCtx description]));
|
||||
ThreadTraceContext* thCtx = [ThreadUtilities recordTraceContext:@"dumpThreadTraceContext" operation:pOperation];
|
||||
doLog(env, "dumpThreadTraceContext: {\n%s\n}", toCString([thCtx description]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -649,163 +626,6 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[dump retain];
|
||||
return dump;
|
||||
}
|
||||
|
||||
+ (BOOL)isWithinPowerTransition:(double)periodInSeconds {
|
||||
if (wakeUpTime != 0LL) {
|
||||
// check last wake-up time:
|
||||
if (_nowNearTime("wake-up", &wakeUpTime, (SEC_PER_NANOS * periodInSeconds))) {
|
||||
return true;
|
||||
}
|
||||
// reset invalid time:
|
||||
wakeUpTime = 0LL;
|
||||
} else if (sleepTime != 0LL) {
|
||||
// check last sleep time:
|
||||
if (_nowNearTime("sleep", &sleepTime, (SEC_PER_NANOS * periodInSeconds))) {
|
||||
return true;
|
||||
}
|
||||
// reset invalid time:
|
||||
sleepTime = 0LL;
|
||||
} else if (TRACE_PWM) {
|
||||
NSLog(@"EAWT: isWithinPowerTransition: no times");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
+ (void)_systemOrScreenWillSleep:(NSNotification*)notification {
|
||||
atomic_uint_least64_t now;
|
||||
if (_nanoUpTime(&now))
|
||||
{
|
||||
// keep most-recent wake-up time (system or display):
|
||||
sleepTime = now;
|
||||
|
||||
if (TRACE_PWM_EVENTS) {
|
||||
NSLog(@"EAWT: _systemOrScreenWillSleep[%@]: sleep time = %.5lf (%.5lf)",
|
||||
[notification name], 1e-9 * sleepTime,
|
||||
[NSProcessInfo processInfo].systemUptime);
|
||||
}
|
||||
// reset wake-up time (system or display):
|
||||
wakeUpTime = 0LL;
|
||||
|
||||
if (TRACE_CLOCKS) {
|
||||
dumpClocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_systemOrScreenDidWake:(NSNotification*)notification {
|
||||
atomic_uint_least64_t now;
|
||||
if (_nanoUpTime(&now))
|
||||
{
|
||||
// keep most-recent wake-up time (system or display):
|
||||
wakeUpTime = now;
|
||||
|
||||
if (TRACE_PWM_EVENTS) {
|
||||
NSLog(@"EAWT: _systemOrScreenDidWake[%@]: wake-up time = %.5lf (%.5lf)",
|
||||
[notification name], 1e-9 * wakeUpTime,
|
||||
[NSProcessInfo processInfo].systemUptime);
|
||||
}
|
||||
// CHECK
|
||||
if (sleepTime != 0LL) {
|
||||
if (now > sleepTime) {
|
||||
// check last sleep time:
|
||||
now -= sleepTime; // delta in ns
|
||||
if (TRACE_PWM_EVENTS) {
|
||||
NSLog(@"EAWT: _systemOrScreenDidWake: SLEEP duration = %.5lf ms", 1e-6 * now);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TRACE_CLOCKS) {
|
||||
dumpClocks();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool _nowNearTime(const char* src, atomic_uint_least64_t *refTime, atomic_uint_least64_t periodNanos) {
|
||||
if (*refTime != 0LL) {
|
||||
atomic_uint_least64_t now;
|
||||
if (_nanoUpTime(&now)) {
|
||||
if (now < *refTime) {
|
||||
// should not happen with monotonic clocks, but:
|
||||
now = *refTime;
|
||||
}
|
||||
// check absolute delta in nanoseconds:
|
||||
now -= *refTime;
|
||||
|
||||
if (TRACE_PWM) {
|
||||
NSLog(@"EAWT: nowNearTime[%s]: delta time = %.5lf ms", src, 1e-6 * now);
|
||||
}
|
||||
return (now <= periodNanos);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void dumpClocks() {
|
||||
if (TRACE_CLOCKS) {
|
||||
logTime_nanos(CLOCK_REALTIME);
|
||||
logTime_nanos(CLOCK_MONOTONIC);
|
||||
logTime_nanos(CLOCK_MONOTONIC_RAW);
|
||||
logTime_nanos(CLOCK_MONOTONIC_RAW_APPROX);
|
||||
logTime_nanos(CLOCK_UPTIME_RAW);
|
||||
logTime_nanos(CLOCK_UPTIME_RAW_APPROX);
|
||||
logTime_nanos(CLOCK_PROCESS_CPUTIME_ID);
|
||||
logTime_nanos(CLOCK_THREAD_CPUTIME_ID);
|
||||
}
|
||||
}
|
||||
|
||||
void logTime_nanos(clockid_t clock_id) {
|
||||
if (TRACE_CLOCKS) {
|
||||
atomic_uint_least64_t now;
|
||||
if (_getTime_nanos(clock_id, &now)) {
|
||||
const char *clock_name;
|
||||
switch (clock_id) {
|
||||
case CLOCK_REALTIME:
|
||||
clock_name = "CLOCK_REALTIME";
|
||||
break;
|
||||
case CLOCK_MONOTONIC:
|
||||
clock_name = "CLOCK_MONOTONIC";
|
||||
break;
|
||||
case CLOCK_MONOTONIC_RAW:
|
||||
clock_name = "CLOCK_MONOTONIC_RAW";
|
||||
break;
|
||||
case CLOCK_MONOTONIC_RAW_APPROX:
|
||||
clock_name = "CLOCK_MONOTONIC_RAW_APPROX";
|
||||
break;
|
||||
case CLOCK_UPTIME_RAW:
|
||||
clock_name = "CLOCK_UPTIME_RAW";
|
||||
break;
|
||||
case CLOCK_UPTIME_RAW_APPROX:
|
||||
clock_name = "CLOCK_UPTIME_RAW_APPROX";
|
||||
break;
|
||||
case CLOCK_PROCESS_CPUTIME_ID:
|
||||
clock_name = "CLOCK_PROCESS_CPUTIME_ID";
|
||||
break;
|
||||
case CLOCK_THREAD_CPUTIME_ID:
|
||||
clock_name = "CLOCK_THREAD_CPUTIME_ID";
|
||||
break;
|
||||
default:
|
||||
clock_name = "unknown";
|
||||
}
|
||||
NSLog(@"EAWT: logTime_nanos[%27s] time: %.6lf s", clock_name, 1e-9 * now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)registerForSystemAndScreenNotifications {
|
||||
static BOOL notificationRegistered = false;
|
||||
if (!notificationRegistered) {
|
||||
notificationRegistered = true;
|
||||
|
||||
NSNotificationCenter *ctr = [[NSWorkspace sharedWorkspace] notificationCenter];
|
||||
Class clz = [ThreadUtilities class];
|
||||
|
||||
[ctr addObserver:clz selector:@selector(_systemOrScreenWillSleep:) name:NSWorkspaceWillSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(_systemOrScreenDidWake:) name:NSWorkspaceDidWakeNotification object:nil];
|
||||
|
||||
[ctr addObserver:clz selector:@selector(_systemOrScreenWillSleep:) name:NSWorkspaceScreensDidSleepNotification object:nil];
|
||||
[ctr addObserver:clz selector:@selector(_systemOrScreenDidWake:) name:NSWorkspaceScreensDidWakeNotification object:nil];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
void OSXAPP_SetJavaVM(JavaVM *vm)
|
||||
@@ -885,17 +705,91 @@ JNIEXPORT void lwc_plog(JNIEnv* env, const char *formatMsg, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Traceability data */
|
||||
@implementation ThreadTraceContext {
|
||||
/* RunLoop Callback Queue */
|
||||
|
||||
@implementation RunLoopCallbackQueue
|
||||
|
||||
+ (RunLoopCallbackQueue*) shared {
|
||||
static RunLoopCallbackQueue* _runLoopCallbackQueue = nil;
|
||||
static dispatch_once_t oncePredicate;
|
||||
|
||||
dispatch_once(&oncePredicate, ^{
|
||||
_runLoopCallbackQueue = [RunLoopCallbackQueue new];
|
||||
});
|
||||
return _runLoopCallbackQueue;
|
||||
}
|
||||
|
||||
- (id) init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.queue = [NSMutableArray arrayWithCapacity: 8];
|
||||
[self reset];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self reset];
|
||||
self.queue = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)reset {
|
||||
[self.queue removeAllObjects];
|
||||
self.coalesingflags = 0;
|
||||
}
|
||||
|
||||
- (BOOL)coalesingFlag:(u_long)bit {
|
||||
return (self.coalesingflags & (1L << bit)) != 0;
|
||||
}
|
||||
- (void)setCoalesingFlag:(u_long)bit {
|
||||
self.coalesingflags |= (1L << bit);
|
||||
}
|
||||
|
||||
- (BOOL)hasCallback:(u_long)bit {
|
||||
return (bit != 0) && [self coalesingFlag:bit];
|
||||
}
|
||||
|
||||
- (BOOL)addCallback:(u_long)bit block:(void (^)())block {
|
||||
if ([NSThread isMainThread] == NO) {
|
||||
NSLog(@"addCallback should be called on main thread");
|
||||
return NO;
|
||||
}
|
||||
// check coalesing flag:
|
||||
if (bit != 0) {
|
||||
if ([self coalesingFlag:bit]) {
|
||||
// skip coalesing callback:
|
||||
return NO;
|
||||
}
|
||||
[self setCoalesingFlag:bit];
|
||||
}
|
||||
[self.queue addObject:Block_copy(block)];
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)processQueuedCallbacks {
|
||||
const NSUInteger count = [self.queue count];
|
||||
if (count != 0) {
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
void (^blockCopy)(void) = (void (^)())[self.queue objectAtIndex: i];
|
||||
// invoke callback:
|
||||
[ThreadUtilities invokeBlockCopy:blockCopy];
|
||||
}
|
||||
// reset queue anyway:
|
||||
[self reset];
|
||||
}
|
||||
}
|
||||
@end
|
||||
|
||||
/* Traceability data */
|
||||
@implementation ThreadTraceContext
|
||||
|
||||
@synthesize sleep, useJavaModes, actionId, operation, timestamp, caller, callStack;
|
||||
|
||||
- (id _Nonnull)init
|
||||
{
|
||||
- (id)init:(NSString*)threadName {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.threadName = [[NSThread currentThread] name];
|
||||
self.threadName = threadName;
|
||||
[self reset];
|
||||
}
|
||||
return self;
|
||||
@@ -938,8 +832,12 @@ JNIEXPORT void lwc_plog(JNIEnv* env, const char *formatMsg, ...) {
|
||||
self.sleep = sleepValue;
|
||||
}
|
||||
|
||||
- (void)set:(long)pActionId operation:(char*) pOperation useJavaModes:(BOOL) pUseJavaModes
|
||||
caller:(NSString*) pCaller callstack:(NSString*) pCallStack {
|
||||
- (void) set:(long) pActionId
|
||||
operation:(const char*) pOperation
|
||||
useJavaModes:(BOOL) pUseJavaModes
|
||||
caller:(NSString*) pCaller
|
||||
callstack:(NSString*) pCallStack
|
||||
{
|
||||
[self updateThreadState:NO];
|
||||
self.useJavaModes = pUseJavaModes;
|
||||
self.actionId = pActionId;
|
||||
|
||||
@@ -63,7 +63,7 @@ public class AWTThreading {
|
||||
* or waits a notification from Toolkit. The method is re-entrant.
|
||||
* <p>
|
||||
* Currently only macOS is supported. The callable can wrap a native obj-c selector. The selector should be executed via
|
||||
* [JNFRunLoop performOnMainThreadWaiting:YES ...] so that doAWTRunLoop on AppKit (which is run in [JNFRunLoop javaRunLoopMode]) accepts it.
|
||||
* [ThreadUtilities performOnMainThreadWaiting:YES ...] so that doAWTRunLoop on AppKit (which is run in [ThreadUtilities javaRunLoopMode]) accepts it.
|
||||
* The callable should not call any Java code that would normally be called on EDT.
|
||||
* <p>
|
||||
* A deadlock can happen when the callable triggers any blocking invocation from Toolkit to EDT, or when Toolkit already waits in
|
||||
@@ -310,7 +310,7 @@ public class AWTThreading {
|
||||
} else if (logger.isLoggable(PlatformLogger.Level.INFO)) {
|
||||
StackTraceElement[] stack = throwable.getStackTrace();
|
||||
logger.info(message + ". Originated at " + stack[stack.length - 1]);
|
||||
} else {
|
||||
} else if (TRACE_RUN_LOOP) {
|
||||
logger.severe("AWTThreading.TrackedInvocationEvent.whenComplete: failure", ex);
|
||||
logger.severe("AWTThreading.TrackedInvocationEvent.whenComplete: caller:", throwable);
|
||||
}
|
||||
|
||||
@@ -173,6 +173,10 @@ public abstract class SunDropTargetContextPeer implements DropTargetContextPeer,
|
||||
return currentA;
|
||||
}
|
||||
|
||||
protected int getDropAction() {
|
||||
return currentDA;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the Transferable associated with the drop
|
||||
*/
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,7 @@ class VKBufImgOps extends BufferedBufImgOps {
|
||||
/**
|
||||
* This method is called from VKDrawImage.transformImage() only. It
|
||||
* validates the provided BufferedImageOp to determine whether the op
|
||||
* is one that can be accelerated by the MTL pipeline. If the operation
|
||||
* is one that can be accelerated by the Vulkan pipeline. If the operation
|
||||
* cannot be completed for any reason, this method returns false;
|
||||
* otherwise, the given BufferedImage is rendered to the destination
|
||||
* using the provided BufferedImageOp and this method returns true.
|
||||
@@ -53,65 +53,66 @@ class VKBufImgOps extends BufferedBufImgOps {
|
||||
static boolean renderImageWithOp(SunGraphics2D sg, BufferedImage img,
|
||||
BufferedImageOp biop, int x, int y)
|
||||
{
|
||||
// Validate the provided BufferedImage (make sure it is one that
|
||||
// is supported, and that its properties are acceleratable)
|
||||
if (biop instanceof ConvolveOp) {
|
||||
if (!isConvolveOpValid((ConvolveOp)biop)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof RescaleOp) {
|
||||
if (!isRescaleOpValid((RescaleOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else if (biop instanceof LookupOp) {
|
||||
if (!isLookupOpValid((LookupOp)biop, img)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// No acceleration for other BufferedImageOps (yet)
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
if (!(dstData instanceof VKSurfaceData) ||
|
||||
(sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
|
||||
(sg.compositeState > SunGraphics2D.COMP_ALPHA))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceData srcData =
|
||||
dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof VKSurfaceData)) {
|
||||
// REMIND: this hack tries to ensure that we have a cached texture
|
||||
srcData =
|
||||
dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
CompositeType.SrcOver, null);
|
||||
if (!(srcData instanceof VKSurfaceData)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that the source surface is actually a texture and
|
||||
// that the operation is supported
|
||||
VKSurfaceData vkSrc = (VKSurfaceData)srcData;
|
||||
VKGraphicsConfig gc = vkSrc.getGraphicsConfig();
|
||||
if (vkSrc.getType() != VKSurfaceData.TEXTURE || !gc.isCapPresent(CAPS_EXT_BIOP_SHADER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int sw = img.getWidth();
|
||||
int sh = img.getHeight();
|
||||
VKBlitLoops.IsoBlit(srcData, dstData,
|
||||
img, biop,
|
||||
sg.composite, sg.getCompClip(),
|
||||
sg.transform, sg.interpolationType,
|
||||
0, 0, sw, sh,
|
||||
x, y, x+sw, y+sh,
|
||||
true);
|
||||
|
||||
return true;
|
||||
// TODO No acceleration for image ops yet.
|
||||
return false;
|
||||
// // Validate the provided BufferedImage (make sure it is one that
|
||||
// // is supported, and that its properties are acceleratable)
|
||||
// if (biop instanceof ConvolveOp) {
|
||||
// if (!isConvolveOpValid((ConvolveOp)biop)) {
|
||||
// return false;
|
||||
// }
|
||||
// } else if (biop instanceof RescaleOp) {
|
||||
// if (!isRescaleOpValid((RescaleOp)biop, img)) {
|
||||
// return false;
|
||||
// }
|
||||
// } else if (biop instanceof LookupOp) {
|
||||
// if (!isLookupOpValid((LookupOp)biop, img)) {
|
||||
// return false;
|
||||
// }
|
||||
// } else {
|
||||
// // No acceleration for other BufferedImageOps (yet)
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// SurfaceData dstData = sg.surfaceData;
|
||||
// if (!(dstData instanceof VKSurfaceData) ||
|
||||
// (sg.interpolationType == AffineTransformOp.TYPE_BICUBIC) ||
|
||||
// (sg.compositeState > SunGraphics2D.COMP_ALPHA))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// SurfaceData srcData =
|
||||
// dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
// CompositeType.SrcOver, null);
|
||||
// if (!(srcData instanceof VKSurfaceData)) {
|
||||
// // REMIND: this hack tries to ensure that we have a cached texture
|
||||
// srcData =
|
||||
// dstData.getSourceSurfaceData(img, SunGraphics2D.TRANSFORM_ISIDENT,
|
||||
// CompositeType.SrcOver, null);
|
||||
// if (!(srcData instanceof VKSurfaceData)) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Verify that the source surface is actually a texture and
|
||||
// // that the operation is supported
|
||||
// VKSurfaceData vkSrc = (VKSurfaceData)srcData;
|
||||
// VKGraphicsConfig gc = vkSrc.getGraphicsConfig();
|
||||
// if (vkSrc.getType() != VKSurfaceData.TEXTURE || !gc.isCapPresent(CAPS_EXT_BIOP_SHADER))
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// int sw = img.getWidth();
|
||||
// int sh = img.getHeight();
|
||||
// VKBlitLoops.IsoBlit(srcData, dstData,
|
||||
// img, biop,
|
||||
// sg.composite, sg.getCompClip(),
|
||||
// sg.transform, sg.interpolationType,
|
||||
// 0, 0, sw, sh,
|
||||
// x, y, x+sw, y+sh);
|
||||
//
|
||||
// return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,8 @@ import sun.java2d.pipe.RenderQueue;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.lang.annotation.Native;
|
||||
|
||||
/**
|
||||
@@ -41,6 +43,8 @@ final class VKContext extends BufferedContext {
|
||||
private static final PlatformLogger log =
|
||||
PlatformLogger.getLogger("sun.java2d.vulkan.VKContext");
|
||||
|
||||
public static final VKContext INSTANCE = new VKContext(VKRenderQueue.getInstance());
|
||||
|
||||
public VKContext(RenderQueue rq) {
|
||||
super(rq);
|
||||
}
|
||||
@@ -73,6 +77,26 @@ final class VKContext extends BufferedContext {
|
||||
@Native
|
||||
static final int CAPS_EXT_GRAD_SHADER = (FIRST_PRIVATE_CAP << 3);
|
||||
|
||||
public static final VKContextCaps CONTEXT_CAPS = new VKContextCaps(
|
||||
CAPS_PS30 | CAPS_PS20 | CAPS_RT_TEXTURE_ALPHA |
|
||||
CAPS_RT_TEXTURE_OPAQUE | CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 |
|
||||
CAPS_TEXNONSQUARE, null);
|
||||
|
||||
public static final ImageCapabilities IMAGE_CAPS = new ImageCapabilities(true) {
|
||||
@Override
|
||||
public boolean isTrueVolatile() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public static final BufferCapabilities BUFFER_CAPS = new BufferCapabilities(IMAGE_CAPS, IMAGE_CAPS,
|
||||
BufferCapabilities.FlipContents.COPIED) {
|
||||
@Override
|
||||
public boolean isMultiBufferAvailable() {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
public VKContextCaps(int caps, String adapterId) {
|
||||
super(caps, adapterId);
|
||||
}
|
||||
|
||||
@@ -50,13 +50,6 @@ public class VKDrawImage extends DrawImage {
|
||||
// punt to the MediaLib-based transformImage() in the superclass if:
|
||||
// - bicubic interpolation is specified
|
||||
// - a background color is specified and will be used
|
||||
// - the source surface is neither a texture nor render-to-texture
|
||||
// surface, and a non-default interpolation hint is specified
|
||||
// (we can only control the filtering for texture->surface
|
||||
// copies)
|
||||
// REMIND: we should tweak the sw->texture->surface
|
||||
// transform case to handle filtering appropriately
|
||||
// (see 4841762)...
|
||||
// - an appropriate TransformBlit primitive could not be found
|
||||
if (interpType != AffineTransformOp.TYPE_BICUBIC) {
|
||||
SurfaceData dstData = sg.surfaceData;
|
||||
@@ -66,12 +59,7 @@ public class VKDrawImage extends DrawImage {
|
||||
sg.imageComp,
|
||||
bgColor);
|
||||
|
||||
if (srcData != null &&
|
||||
!isBgOperation(srcData, bgColor) &&
|
||||
(srcData.getSurfaceType() == VKSurfaceData.VKTexture ||
|
||||
srcData.getSurfaceType() == VKSurfaceData.VKSurfaceRTT ||
|
||||
interpType == AffineTransformOp.TYPE_NEAREST_NEIGHBOR))
|
||||
{
|
||||
if (srcData != null && !isBgOperation(srcData, bgColor)) {
|
||||
SurfaceType srcType = srcData.getSurfaceType();
|
||||
SurfaceType dstType = dstData.getSurfaceType();
|
||||
TransformBlit blit = TransformBlit.getFromCache(srcType,
|
||||
|
||||
141
src/java.desktop/share/classes/sun/java2d/vulkan/VKEnv.java
Normal file
141
src/java.desktop/share/classes/sun/java2d/vulkan/VKEnv.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 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
|
||||
* 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.vulkan;
|
||||
|
||||
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 {
|
||||
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.java2d.vulkan.VKInstance");
|
||||
|
||||
private static final class Options {
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final boolean vulkan = "true".equalsIgnoreCase(AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan", "")));
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final boolean accelsd = vulkan && "true".equalsIgnoreCase(AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", "")));
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static final int deviceNumber = !vulkan ? 0 : AccessController.doPrivileged(
|
||||
(PrivilegedAction<Integer>) () -> Integer.getInteger("sun.java2d.vulkan.deviceNumber", 0));
|
||||
}
|
||||
|
||||
private static final int UNINITIALIZED = 0;
|
||||
private static final int INITIALIZING = 1;
|
||||
private static final int DISABLED = 2;
|
||||
private static final int ENABLED = 3;
|
||||
private static final int ACCELSD_BIT = 4;
|
||||
private static final int PRESENT_BIT = 8;
|
||||
|
||||
private static int state = UNINITIALIZED;
|
||||
private static VKGPU[] devices;
|
||||
private static VKGPU defaultDevice;
|
||||
|
||||
private static native long initPlatform(long nativePtr);
|
||||
private static native VKGPU[] initNative(long platformData);
|
||||
|
||||
public static synchronized void init(long nativePtr) {
|
||||
if (state > INITIALIZING) return;
|
||||
long platformData = nativePtr == 0 ? 0 : initPlatform(nativePtr);
|
||||
int newState = DISABLED;
|
||||
if (Options.vulkan) {
|
||||
devices = initNative(platformData);
|
||||
if (devices != null) {
|
||||
newState = ENABLED;
|
||||
if (Options.accelsd) newState |= ACCELSD_BIT;
|
||||
defaultDevice = devices[Options.deviceNumber >= 0 && Options.deviceNumber < devices.length ?
|
||||
Options.deviceNumber : 0];
|
||||
// Check whether the presentation is supported.
|
||||
for (VKGPU device : devices) {
|
||||
if (device.hasCap(VKGPU.CAP_PRESENTABLE_BIT) &&
|
||||
device.getPresentableGraphicsConfigs().findAny().isPresent()) {
|
||||
newState |= PRESENT_BIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
VKBlitLoops.register();
|
||||
VKMaskFill.register();
|
||||
VKMaskBlit.register();
|
||||
}
|
||||
}
|
||||
state = newState;
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
if (isVulkanEnabled()) {
|
||||
log.fine("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 log.fine("Vulkan rendering enabled: NO");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkInit() {
|
||||
if (state > INITIALIZING) return;
|
||||
synchronized (VKEnv.class) {
|
||||
if (state == UNINITIALIZED) {
|
||||
// Try initializing the Toolkit first to give it a chance to init Vulkan with proper platform data.
|
||||
state = INITIALIZING;
|
||||
Toolkit.getDefaultToolkit();
|
||||
}
|
||||
// Still not initialized? Init without platform data.
|
||||
if (state == INITIALIZING) init(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isVulkanEnabled() {
|
||||
checkInit();
|
||||
return (state & ENABLED) == ENABLED;
|
||||
}
|
||||
|
||||
public static boolean isPresentationEnabled() {
|
||||
checkInit();
|
||||
return (state & PRESENT_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isSurfaceDataAccelerated() {
|
||||
checkInit();
|
||||
return (state & ACCELSD_BIT) != 0;
|
||||
}
|
||||
|
||||
public static Stream<VKGPU> getDevices() {
|
||||
checkInit();
|
||||
final VKGPU first = defaultDevice;
|
||||
return Stream.concat(Stream.of(first), Stream.of(devices).filter(d -> d != first));
|
||||
}
|
||||
}
|
||||
173
src/java.desktop/share/classes/sun/java2d/vulkan/VKFormat.java
Normal file
173
src/java.desktop/share/classes/sun/java2d/vulkan/VKFormat.java
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* 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.vulkan;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.DataBuffer;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.SinglePixelPackedSampleModel;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.SampleModel;
|
||||
import java.awt.image.WritableRaster;
|
||||
import java.nio.ByteOrder;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
import sun.awt.image.BufImgSurfaceData;
|
||||
import sun.awt.image.ByteComponentRaster;
|
||||
import sun.awt.image.IntegerComponentRaster;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
|
||||
/**
|
||||
* Vulkan format description, which allows creation of compatible BufferedImages.
|
||||
*/
|
||||
public enum VKFormat {
|
||||
// VK_FORMAT_B8G8R8A8_UNORM doesn't have a matching standard format in Java,
|
||||
// but it can be aliased as TYPE_INT_ARGB on little-endian systems.
|
||||
B8G8R8A8_UNORM(44,
|
||||
LEOptimizations.ENABLED ? VKFormatModel.INT_ARGB_PRE : VKFormatModel.CUSTOM_4BYTE_BGRA_PRE,
|
||||
LEOptimizations.ENABLED ? VKFormatModel.INT_RGB : VKFormatModel.CUSTOM_4BYTE_BGRx),
|
||||
|
||||
R8G8B8A8_UNORM(37, VKFormatModel.CUSTOM_4BYTE_RGBA_PRE, VKFormatModel.CUSTOM_4BYTE_RGBx),
|
||||
|
||||
A8B8G8R8_UNORM_PACK32(51, VKFormatModel.CUSTOM_INT_ABGR_PRE, VKFormatModel.INT_BGR);
|
||||
|
||||
private final int value;
|
||||
private final SurfaceType surfaceType, translucentSurfaceType, opaqueSurfaceType;
|
||||
private final VKFormatModel translucentModel, opaqueModel;
|
||||
private final VKBufImgGraphicsConfig bufferedGraphicsConfig = new VKBufImgGraphicsConfig(this);
|
||||
|
||||
VKFormat(int value, VKFormatModel translucentModel, VKFormatModel opaqueModel) {
|
||||
this.value = value;
|
||||
this.surfaceType = VKSurfaceData.VKSurface.deriveSubType("Vulkan surface (" + name() + ")");
|
||||
this.translucentSurfaceType = translucentModel == null ? null :
|
||||
this.surfaceType.deriveSubType("Vulkan surface (" + name() + ", TRANSLUCENT)");
|
||||
this.opaqueSurfaceType = this.surfaceType.deriveSubType("Vulkan surface (" + name() + ", OPAQUE)");
|
||||
this.translucentModel = translucentModel;
|
||||
this.opaqueModel = opaqueModel;
|
||||
}
|
||||
|
||||
public int getValue(int transparency) {
|
||||
final int FORMAT_OPAQUE_BIT = 0x80000000;
|
||||
return transparency != Transparency.OPAQUE ? value : value | FORMAT_OPAQUE_BIT;
|
||||
}
|
||||
|
||||
public SurfaceType getSurfaceType(int transparency) {
|
||||
return switch (transparency) {
|
||||
case 0 -> surfaceType; // Any transparency.
|
||||
case Transparency.TRANSLUCENT, Transparency.BITMASK -> translucentSurfaceType;
|
||||
case Transparency.OPAQUE -> opaqueSurfaceType;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
|
||||
public VKFormatModel getFormatModel(int transparency) {
|
||||
return transparency != Transparency.OPAQUE ? translucentModel : opaqueModel;
|
||||
}
|
||||
|
||||
public BufferedImage createCompatibleImage(int width, int height, int transparency) {
|
||||
VKFormatModel formatModel = getFormatModel(transparency);
|
||||
ColorModel colorModel = formatModel.getColorModel();
|
||||
SampleModel sampleModel = formatModel.createSampleModel(width, height);
|
||||
SurfaceType surfaceType = formatModel.getSurfaceType();
|
||||
WritableRaster raster = Raster.createWritableRaster(sampleModel, null);
|
||||
BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
|
||||
VKBufImgSurfaceData surfaceData = new VKBufImgSurfaceData(bufferedGraphicsConfig, raster, image, surfaceType);
|
||||
SurfaceManager.setManager(image, new VKBufImgSurfaceManager(image, surfaceData));
|
||||
return image;
|
||||
}
|
||||
|
||||
public boolean isTranslucencyCapable() {
|
||||
return translucentModel != VKFormatModel.NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some Vulkan formats can be more efficiently aliased as built-in Java formats on little-endian systems.
|
||||
*/
|
||||
private interface LEOptimizations {
|
||||
@SuppressWarnings("removal")
|
||||
boolean ENABLED = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN &&
|
||||
"true".equalsIgnoreCase(AccessController.doPrivileged((PrivilegedAction<String>) () ->
|
||||
System.getProperty("sun.java2d.vulkan.leOptimizations", "true")));
|
||||
}
|
||||
|
||||
private static class VKBufImgSurfaceManager extends SurfaceManager {
|
||||
private final BufferedImage image;
|
||||
private final VKBufImgSurfaceData sd;
|
||||
private VKBufImgSurfaceManager(BufferedImage image, VKBufImgSurfaceData sd) {
|
||||
this.image = image;
|
||||
this.sd = sd;
|
||||
}
|
||||
public SurfaceData getPrimarySurfaceData() { return sd; }
|
||||
public SurfaceData restoreContents() { return sd; }
|
||||
}
|
||||
|
||||
private static class VKBufImgSurfaceData extends BufImgSurfaceData {
|
||||
private final GraphicsConfiguration gc;
|
||||
private VKBufImgSurfaceData(GraphicsConfiguration gc,
|
||||
WritableRaster raster, BufferedImage image, SurfaceType surfaceType) {
|
||||
super(raster.getDataBuffer(), image, surfaceType, 1, 1);
|
||||
this.gc = gc;
|
||||
|
||||
Object array;
|
||||
if (raster instanceof IntegerComponentRaster r) array = r.getDataStorage();
|
||||
else if (raster instanceof ByteComponentRaster r) array = r.getDataStorage();
|
||||
else throw new IllegalArgumentException("Unsupported raster type: " + raster.getClass().getCanonicalName());
|
||||
|
||||
int pixStr, scanStr;
|
||||
if (raster.getSampleModel() instanceof PixelInterleavedSampleModel sm) {
|
||||
pixStr = sm.getPixelStride();
|
||||
scanStr = sm.getScanlineStride();
|
||||
} else if (raster.getSampleModel() instanceof SinglePixelPackedSampleModel sm) {
|
||||
pixStr = DataBuffer.getDataTypeSize(sm.getDataType()) / 8;
|
||||
scanStr = sm.getScanlineStride() * pixStr;
|
||||
} else throw new IllegalArgumentException("Unsupported sample model: " +
|
||||
raster.getSampleModel().getClass().getCanonicalName());
|
||||
|
||||
initRaster(array, 0, 0, image.getWidth(), image.getHeight(), pixStr, scanStr, null);
|
||||
initSolidLoops();
|
||||
}
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return gc;
|
||||
}
|
||||
}
|
||||
|
||||
private static class VKBufImgGraphicsConfig extends VKOffscreenGraphicsConfig {
|
||||
private VKBufImgGraphicsConfig(VKFormat format) {
|
||||
super(null, format);
|
||||
}
|
||||
@Override
|
||||
public VKGPU getGPU() {
|
||||
throw new UnsupportedOperationException("No VKGPU associated with VKBufImgGraphicsConfig");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* 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.vulkan;
|
||||
|
||||
import java.awt.color.ColorSpace;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.ComponentColorModel;
|
||||
import java.awt.image.DirectColorModel;
|
||||
import java.awt.image.PixelInterleavedSampleModel;
|
||||
import java.awt.image.SampleModel;
|
||||
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
|
||||
import static java.awt.image.DataBuffer.TYPE_BYTE;
|
||||
import static java.awt.image.DataBuffer.TYPE_INT;
|
||||
import static java.awt.Transparency.OPAQUE;
|
||||
import static java.awt.Transparency.TRANSLUCENT;
|
||||
|
||||
/**
|
||||
* Format model describes properties of the surface, necessary for the creation of compatible BufferedImages.
|
||||
*/
|
||||
public enum VKFormatModel {
|
||||
NONE(BufferedImage.TYPE_CUSTOM, null, null, null, null),
|
||||
|
||||
INT_ARGB_PRE(BufferedImage.TYPE_INT_ARGB_PRE, SurfaceType.IntArgbPre, PixelConverter.ArgbPre.instance,
|
||||
new DirectColorModel(sRGB(), 32, 0xff0000, 0xff00, 0xff, 0xff000000, true, TYPE_INT), null),
|
||||
|
||||
INT_RGB(BufferedImage.TYPE_INT_RGB, SurfaceType.IntRgb, PixelConverter.Xrgb.instance,
|
||||
new DirectColorModel(sRGB(), 24, 0xff0000, 0xff00, 0xff, 0x00000000, false, TYPE_INT), null),
|
||||
|
||||
CUSTOM_4BYTE_BGRA_PRE(BufferedImage.TYPE_CUSTOM, SurfaceType.Any4Byte, PixelConverter.ArgbPre.instance,
|
||||
new ComponentColorModel(sRGB(), true, true, TRANSLUCENT, TYPE_BYTE), sampleModel(TYPE_BYTE, 4, 2, 1, 0, 3)),
|
||||
|
||||
CUSTOM_4BYTE_BGRx(BufferedImage.TYPE_CUSTOM, SurfaceType.Any4Byte, PixelConverter.Xrgb.instance,
|
||||
new ComponentColorModel(sRGB(), false, false, OPAQUE, TYPE_BYTE), sampleModel(TYPE_BYTE, 4, 2, 1, 0)),
|
||||
|
||||
CUSTOM_4BYTE_RGBA_PRE(BufferedImage.TYPE_CUSTOM, SurfaceType.Any4Byte, CustomPixelConverter.AbgrPre,
|
||||
new ComponentColorModel(sRGB(), true, true, TRANSLUCENT, TYPE_BYTE), sampleModel(TYPE_BYTE, 4, 0, 1, 2, 3)),
|
||||
|
||||
CUSTOM_4BYTE_RGBx(BufferedImage.TYPE_CUSTOM, SurfaceType.Any4Byte, PixelConverter.Xbgr.instance,
|
||||
new ComponentColorModel(sRGB(), false, false, OPAQUE, TYPE_BYTE), sampleModel(TYPE_BYTE, 4, 0, 1, 2)),
|
||||
|
||||
CUSTOM_INT_ABGR_PRE(BufferedImage.TYPE_CUSTOM, SurfaceType.AnyDcm, CustomPixelConverter.AbgrPre,
|
||||
new DirectColorModel(sRGB(), 32, 0xff, 0xff00, 0xff0000, 0xff000000, true, TYPE_INT), null),
|
||||
|
||||
INT_BGR(BufferedImage.TYPE_INT_BGR, SurfaceType.IntBgr, PixelConverter.Xbgr.instance,
|
||||
new DirectColorModel(sRGB(), 24, 0xff, 0xff00, 0xff0000, 0x00000000, false, TYPE_INT), null);
|
||||
|
||||
private final int type;
|
||||
private final SurfaceType surfaceType;
|
||||
private final ColorModel colorModel;
|
||||
private final SampleModelFactory sampleModelFactory;
|
||||
|
||||
VKFormatModel(int type, SurfaceType surfaceType, PixelConverter pixelConverter,
|
||||
ColorModel colorModel, SampleModelFactory sampleModelFactory) {
|
||||
this.type = type;
|
||||
this.surfaceType = surfaceType == null ? null : surfaceType.deriveSubType(
|
||||
"Vulkan-compatible buffered surface (" + surfaceType.getDescriptor() + ")", pixelConverter);
|
||||
this.colorModel = colorModel;
|
||||
this.sampleModelFactory = sampleModelFactory == null && colorModel != null ?
|
||||
this.colorModel::createCompatibleSampleModel : sampleModelFactory;
|
||||
}
|
||||
|
||||
public SurfaceType getSurfaceType() {
|
||||
return surfaceType;
|
||||
}
|
||||
|
||||
public ColorModel getColorModel() {
|
||||
return colorModel;
|
||||
}
|
||||
|
||||
public SampleModel createSampleModel(int width, int height) {
|
||||
return sampleModelFactory.createSampleModel(width, height);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface SampleModelFactory {
|
||||
SampleModel createSampleModel(int w, int h);
|
||||
}
|
||||
|
||||
private static SampleModelFactory sampleModel(int dataType, int components, int... bandOffsets) {
|
||||
return (w, h) -> new PixelInterleavedSampleModel(dataType, w, h, components, w*components, bandOffsets);
|
||||
}
|
||||
|
||||
private static ColorSpace sRGB() {
|
||||
return ColorSpace.getInstance(ColorSpace. CS_sRGB);
|
||||
}
|
||||
|
||||
private static abstract class CustomPixelConverter extends PixelConverter {
|
||||
|
||||
private static final PixelConverter AbgrPre = new CustomPixelConverter(0xff000000) {
|
||||
@Override
|
||||
public int rgbToPixel(int rgb, ColorModel cm) {
|
||||
int a = rgb >>> 24;
|
||||
int r = (rgb >> 16) & 0xff;
|
||||
int g = (rgb >> 8) & 0xff;
|
||||
int b = (rgb ) & 0xff;
|
||||
int a2 = a + (a >> 7);
|
||||
r = (r * a2) >> 8;
|
||||
g = (g * a2) >> 8;
|
||||
b = (b * a2) >> 8;
|
||||
return ((a << 24) | (b << 16) | (g << 8) | (r));
|
||||
}
|
||||
@Override
|
||||
public int pixelToRgb(int pixel, ColorModel cm) {
|
||||
int a = pixel >>> 24;
|
||||
int r = (pixel ) & 0xff;
|
||||
int g = (pixel >> 8) & 0xff;
|
||||
int b = (pixel >> 16) & 0xff;
|
||||
if (a != 0) {
|
||||
r = ((r << 8) - r) / a;
|
||||
g = ((g << 8) - g) / a;
|
||||
b = ((b << 8) - b) / a;
|
||||
}
|
||||
return ((a << 24) | (r << 16) | (g << 8) | (b));
|
||||
}
|
||||
};
|
||||
|
||||
private CustomPixelConverter(int alphaMask) { this.alphaMask = alphaMask; }
|
||||
@Override
|
||||
public abstract int rgbToPixel(int rgb, ColorModel cm);
|
||||
@Override
|
||||
public abstract int pixelToRgb(int pixel, ColorModel cm);
|
||||
}
|
||||
}
|
||||
135
src/java.desktop/share/classes/sun/java2d/vulkan/VKGPU.java
Normal file
135
src/java.desktop/share/classes/sun/java2d/vulkan/VKGPU.java
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.vulkan;
|
||||
|
||||
import sun.awt.image.SurfaceManager;
|
||||
|
||||
import java.awt.Transparency;
|
||||
import java.lang.annotation.Native;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* VKDevice wrapper.
|
||||
*/
|
||||
public class VKGPU {
|
||||
|
||||
@Native public static final int CAP_PRESENTABLE_BIT = 0x80000000;
|
||||
@Native public static final int CAP_LOGIC_OP_BIT = 0x40000000;
|
||||
@Native public static final int CAP_SAMPLED_4BYTE_BIT = 0; // Considered always supported.
|
||||
@Native public static final int CAP_SAMPLED_3BYTE_BIT = 1;
|
||||
@Native public static final int CAP_SAMPLED_565_BIT = 2;
|
||||
@Native public static final int CAP_SAMPLED_555_BIT = 4;
|
||||
|
||||
private boolean initialized;
|
||||
|
||||
private final SurfaceManager.ProxyCache surfaceDataProxyCache = new SurfaceManager.ProxyCache();
|
||||
private final long nativeHandle;
|
||||
private final String name;
|
||||
private final Type type;
|
||||
private final int caps;
|
||||
private final List<VKGraphicsConfig> offscreenGraphicsConfigs, presentableGraphicsConfigs;
|
||||
|
||||
private static native void init(long nativeHandle);
|
||||
private static native void reset(long nativeHandle);
|
||||
|
||||
/**
|
||||
* Instantiated from native code, see createJavaDevices in VKInstance.c
|
||||
* Fresh devices are created in uninitialized state. They can be queried for their properties
|
||||
* but cannot be used for rendering until initialized via getNativeHandle().
|
||||
*/
|
||||
private VKGPU(long nativeHandle, String name, int type, int caps, int[] supportedFormats) {
|
||||
this.nativeHandle = nativeHandle;
|
||||
this.name = name;
|
||||
this.type = Type.VALUES[type];
|
||||
this.caps = caps;
|
||||
offscreenGraphicsConfigs = new ArrayList<>();
|
||||
presentableGraphicsConfigs = new ArrayList<>();
|
||||
VKFormat[] allFormats = VKFormat.values();
|
||||
for (int supportedFormat : supportedFormats) {
|
||||
int formatValue = supportedFormat & ~CAP_PRESENTABLE_BIT;
|
||||
for (VKFormat format : allFormats) {
|
||||
if (formatValue == format.getValue(Transparency.TRANSLUCENT)) {
|
||||
VKOffscreenGraphicsConfig gc = new VKOffscreenGraphicsConfig(this, format);
|
||||
offscreenGraphicsConfigs.add(gc);
|
||||
if ((supportedFormat & caps & CAP_PRESENTABLE_BIT) != 0) presentableGraphicsConfigs.add(gc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SurfaceManager.ProxyCache getSurfaceDataProxyCache() { return surfaceDataProxyCache; }
|
||||
public String getName() { return name; }
|
||||
public Type getType() { return type; }
|
||||
|
||||
public Stream<VKGraphicsConfig> getOffscreenGraphicsConfigs() {
|
||||
return offscreenGraphicsConfigs.stream();
|
||||
}
|
||||
|
||||
public Stream<VKGraphicsConfig> getPresentableGraphicsConfigs() {
|
||||
return presentableGraphicsConfigs.stream();
|
||||
}
|
||||
|
||||
public int getCaps() {
|
||||
return caps;
|
||||
}
|
||||
|
||||
public boolean hasCap(int cap) {
|
||||
return (caps & cap) == cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the device and return its native handle.
|
||||
*/
|
||||
public synchronized long getNativeHandle() {
|
||||
if (!initialized) {
|
||||
try {
|
||||
init(nativeHandle);
|
||||
} catch (RuntimeException e) {
|
||||
throw new RuntimeException("Failed to initialize Vulkan device: " + name, e);
|
||||
}
|
||||
initialized = true;
|
||||
}
|
||||
return nativeHandle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name + " (" + type + ")";
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
OTHER,
|
||||
INTEGRATED_GPU,
|
||||
DISCRETE_GPU,
|
||||
VIRTUAL_GPU,
|
||||
CPU;
|
||||
private static final Type[] VALUES = values();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,9 +26,124 @@
|
||||
|
||||
package sun.java2d.vulkan;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.SurfaceManager;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.Surface;
|
||||
import sun.java2d.SurfaceManagerFactory;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.hw.AccelGraphicsConfig;
|
||||
import sun.java2d.pipe.hw.AccelTypedVolatileImage;
|
||||
import sun.java2d.pipe.hw.ContextCapabilities;
|
||||
|
||||
public interface VKGraphicsConfig extends AccelGraphicsConfig, SurfaceManager.ProxiedGraphicsConfig {
|
||||
boolean isCapPresent(int capsExtGradShader);
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.ImageCapabilities;
|
||||
|
||||
import static java.awt.Transparency.OPAQUE;
|
||||
import static java.awt.Transparency.TRANSLUCENT;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.RT_TEXTURE;
|
||||
import static sun.java2d.pipe.hw.AccelSurface.TEXTURE;
|
||||
|
||||
/**
|
||||
* Base type for Vulkan graphics config.
|
||||
* Despite it being an interface, it contains a (preferred) default implementation
|
||||
* for most of the methods, including base methods of GraphicsConfiguration class.
|
||||
*/
|
||||
public interface VKGraphicsConfig extends AccelGraphicsConfig,
|
||||
SurfaceManager.ProxiedGraphicsConfig {
|
||||
|
||||
default VolatileSurfaceManager createVolatileManager(SunVolatileImage image,
|
||||
Object context) {
|
||||
return new VKVolatileSurfaceManager(image, context);
|
||||
}
|
||||
|
||||
VKGraphicsConfig getOffscreenConfig();
|
||||
|
||||
default VKGPU getGPU() {
|
||||
return getOffscreenConfig().getGPU();
|
||||
}
|
||||
|
||||
default VKFormat getFormat() {
|
||||
return getOffscreenConfig().getFormat();
|
||||
}
|
||||
|
||||
default double getScale() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
default SurfaceManager.ProxyCache getSurfaceDataProxyCache() {
|
||||
return getGPU().getSurfaceDataProxyCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
default BufferedContext getContext() {
|
||||
return VKContext.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the provided capability bit is present for this config.
|
||||
* See VKContext.java for a list of supported capabilities.
|
||||
*/
|
||||
default boolean isCapPresent(int cap) { // TODO refactor capability checks.
|
||||
return ((getContextCapabilities().getCaps() & cap) != 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
default ContextCapabilities getContextCapabilities() {
|
||||
return VKContext.VKContextCaps.CONTEXT_CAPS;
|
||||
}
|
||||
|
||||
@Override
|
||||
default VolatileImage createCompatibleVolatileImage(int width, int height, int transparency, int type) {
|
||||
if (type != RT_TEXTURE && type != TEXTURE) return null;
|
||||
if (transparency != OPAQUE && (transparency != TRANSLUCENT || !isTranslucencyCapable())) return null;
|
||||
SunVolatileImage vi =
|
||||
new AccelTypedVolatileImage((GraphicsConfiguration) this, width, height, transparency, type);
|
||||
Surface sd = vi.getDestSurface();
|
||||
if (!(sd instanceof VKSurfaceData vsd) || vsd.getType() != type) {
|
||||
vi.flush();
|
||||
vi = null;
|
||||
}
|
||||
return vi;
|
||||
}
|
||||
|
||||
default String descriptorString() {
|
||||
return getFormat().name() + ", " + getGPU();
|
||||
}
|
||||
|
||||
// Default implementation of GraphicsConfiguration methods.
|
||||
// Those need to be explicitly overridden by subclasses using VKGraphicsConfig.super.
|
||||
|
||||
default BufferedImage createCompatibleImage(int width, int height) {
|
||||
return createCompatibleImage(width, height, isTranslucencyCapable() ? TRANSLUCENT : OPAQUE);
|
||||
}
|
||||
|
||||
default BufferedImage createCompatibleImage(int width, int height, int transparency) {
|
||||
return getFormat().createCompatibleImage(width, height, transparency);
|
||||
}
|
||||
|
||||
default ColorModel getColorModel() {
|
||||
return getColorModel(isTranslucencyCapable() ? TRANSLUCENT : OPAQUE);
|
||||
}
|
||||
|
||||
default ColorModel getColorModel(int transparency) {
|
||||
return getFormat().getFormatModel(transparency).getColorModel();
|
||||
}
|
||||
|
||||
default BufferCapabilities getBufferCapabilities() {
|
||||
return VKContext.VKContextCaps.BUFFER_CAPS;
|
||||
}
|
||||
|
||||
default ImageCapabilities getImageCapabilities() {
|
||||
return VKContext.VKContextCaps.IMAGE_CAPS;
|
||||
}
|
||||
|
||||
default boolean isTranslucencyCapable() {
|
||||
return getFormat().isTranslucencyCapable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 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
|
||||
* 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.vulkan;
|
||||
|
||||
import sun.util.logging.PlatformLogger;
|
||||
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
public class VKInstance {
|
||||
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.java2d.vulkan.VKInstance");
|
||||
private static Boolean initialized;
|
||||
private static Boolean sdAccelerated;
|
||||
|
||||
private static native boolean initNative(long nativePtr, boolean verbose, int deviceNumber);
|
||||
|
||||
public static void init(long nativePtr) {
|
||||
@SuppressWarnings("removal")
|
||||
String vulkanOption = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan", ""));
|
||||
if ("true".equalsIgnoreCase(vulkanOption)) {
|
||||
@SuppressWarnings("removal")
|
||||
String deviceNumberOption = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.deviceNumber", "0"));
|
||||
int parsedDeviceNumber = 0;
|
||||
try {
|
||||
parsedDeviceNumber = Integer.parseInt(deviceNumberOption);
|
||||
} catch (NumberFormatException e) {
|
||||
log.warning("Invalid Vulkan device number:" + deviceNumberOption);
|
||||
}
|
||||
final int deviceNumber = parsedDeviceNumber;
|
||||
final boolean verbose = "True".equals(vulkanOption);
|
||||
System.loadLibrary("awt");
|
||||
@SuppressWarnings("removal")
|
||||
String sdOption = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("sun.java2d.vulkan.accelsd", ""));
|
||||
initialized = initNative(nativePtr, verbose, deviceNumber);
|
||||
sdAccelerated = initialized && "true".equalsIgnoreCase(sdOption);
|
||||
} else initialized = false;
|
||||
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("Vulkan rendering enabled: " + (initialized ? "YES" : "NO"));
|
||||
log.fine("Vulkan accelerated surface data enabled: " + (sdAccelerated ? "YES" : "NO"));
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isVulkanEnabled() {
|
||||
if (initialized == null) throw new RuntimeException("Vulkan not initialized");
|
||||
return initialized;
|
||||
}
|
||||
|
||||
public static boolean isSurfaceDataAccelerated() {
|
||||
if (initialized == null) throw new RuntimeException("Vulkan not initialized");
|
||||
return sdAccelerated;
|
||||
}
|
||||
}
|
||||
@@ -25,26 +25,28 @@
|
||||
|
||||
package sun.java2d.vulkan;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Image;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
|
||||
/**
|
||||
* SurfaceData object representing an off-screen buffer
|
||||
*/
|
||||
public class VKOffScreenSurfaceData extends VKSurfaceData {
|
||||
private final Image offscreenImage;
|
||||
private native void initOps(int width, int height);
|
||||
|
||||
public VKOffScreenSurfaceData(VKGraphicsConfig gc, Image image, ColorModel cm,
|
||||
int type, int width, int height)
|
||||
{
|
||||
super(gc, cm, type, width, height);
|
||||
private final Image offscreenImage;
|
||||
private final int userWidth, userHeight; // In logical units.
|
||||
|
||||
private native void initOps(int format);
|
||||
|
||||
public VKOffScreenSurfaceData(Image image, VKFormat format, int transparency, int type, int width, int height) {
|
||||
super(format, transparency, type);
|
||||
this.userWidth = width;
|
||||
this.userHeight = height;
|
||||
offscreenImage = image;
|
||||
initOps(width, height);
|
||||
initOps(format.getValue(transparency));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,11 +54,6 @@ public class VKOffScreenSurfaceData extends VKSurfaceData {
|
||||
return restoreContents(offscreenImage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getNativeResource(int resType) {
|
||||
return 0;
|
||||
@@ -76,13 +73,13 @@ public class VKOffScreenSurfaceData extends VKSurfaceData {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedContext getContext() {
|
||||
return getGraphicsConfig().getContext();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isOnScreen() {
|
||||
return false;
|
||||
protected int revalidate(VKGraphicsConfig gc) {
|
||||
int result = super.revalidate(gc);
|
||||
if (result != VolatileImage.IMAGE_INCOMPATIBLE) {
|
||||
scale = gc.getScale();
|
||||
width = (int) Math.ceil(scale * userWidth);
|
||||
height = (int) Math.ceil(scale * userHeight);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.vulkan;
|
||||
|
||||
import java.awt.BufferCapabilities;
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
import java.awt.ImageCapabilities;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
|
||||
public class VKOffscreenGraphicsConfig extends GraphicsConfiguration implements VKGraphicsConfig {
|
||||
private final VKOffsecreenGraphicsDevice graphicsDevice = new VKOffsecreenGraphicsDevice(this);
|
||||
private final VKGPU gpu;
|
||||
private final VKFormat format;
|
||||
|
||||
VKOffscreenGraphicsConfig(VKGPU gpu, VKFormat format) {
|
||||
this.gpu = gpu;
|
||||
this.format = format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsDevice getDevice() {
|
||||
return graphicsDevice;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKGraphicsConfig getOffscreenConfig() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKGPU getGPU() {
|
||||
return gpu;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VKFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getDefaultTransform() {
|
||||
return new AffineTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AffineTransform getNormalizingTransform() {
|
||||
return new AffineTransform();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(0, 0, Integer.MAX_VALUE, Integer.MAX_VALUE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedImage createCompatibleImage(int width, int height) {
|
||||
return VKGraphicsConfig.super.createCompatibleImage(width, height);
|
||||
}
|
||||
@Override
|
||||
public BufferedImage createCompatibleImage(int width, int height, int transparency) {
|
||||
return VKGraphicsConfig.super.createCompatibleImage(width, height, transparency);
|
||||
}
|
||||
@Override
|
||||
public ColorModel getColorModel() {
|
||||
return VKGraphicsConfig.super.getColorModel();
|
||||
}
|
||||
@Override
|
||||
public ColorModel getColorModel(int transparency) {
|
||||
return VKGraphicsConfig.super.getColorModel(transparency);
|
||||
}
|
||||
@Override
|
||||
public BufferCapabilities getBufferCapabilities() {
|
||||
return VKGraphicsConfig.super.getBufferCapabilities();
|
||||
}
|
||||
@Override
|
||||
public ImageCapabilities getImageCapabilities() {
|
||||
return VKGraphicsConfig.super.getImageCapabilities();
|
||||
}
|
||||
@Override
|
||||
public boolean isTranslucencyCapable() {
|
||||
return VKGraphicsConfig.super.isTranslucencyCapable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VKOffscreenGraphicsConfig[" + descriptorString() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.vulkan;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.GraphicsDevice;
|
||||
|
||||
public class VKOffsecreenGraphicsDevice extends GraphicsDevice {
|
||||
|
||||
private final VKGraphicsConfig config;
|
||||
|
||||
VKOffsecreenGraphicsDevice(VKGraphicsConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return GraphicsDevice.TYPE_IMAGE_BUFFER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIDstring() {
|
||||
return "VKOffscreenGraphicsDevice";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration[] getConfigurations() {
|
||||
return new GraphicsConfiguration[]{ getDefaultConfiguration() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDefaultConfiguration() {
|
||||
return (GraphicsConfiguration) config;
|
||||
}
|
||||
}
|
||||
@@ -31,19 +31,24 @@ import sun.awt.SunHints;
|
||||
import sun.awt.image.PixelConverter;
|
||||
import sun.java2d.SunGraphics2D;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.loops.Blit;
|
||||
import sun.java2d.loops.CompositeType;
|
||||
import sun.java2d.loops.GraphicsPrimitive;
|
||||
import sun.java2d.loops.SurfaceType;
|
||||
import static sun.java2d.pipe.BufferedOpCodes.CONFIGURE_SURFACE;
|
||||
import sun.java2d.pipe.BufferedContext;
|
||||
import sun.java2d.pipe.ParallelogramPipe;
|
||||
import sun.java2d.pipe.PixelToParallelogramConverter;
|
||||
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.ColorModel;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.Raster;
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
import static sun.java2d.pipe.BufferedOpCodes.FLUSH_SURFACE;
|
||||
import static sun.java2d.pipe.hw.ContextCapabilities.CAPS_PS30;
|
||||
|
||||
@@ -51,40 +56,9 @@ import static sun.java2d.pipe.hw.ContextCapabilities.CAPS_PS30;
|
||||
public abstract class VKSurfaceData extends SurfaceData
|
||||
implements AccelSurface {
|
||||
|
||||
/**
|
||||
* Pixel formats
|
||||
*/
|
||||
public static final int PF_INT_ARGB = 0;
|
||||
public static final int PF_INT_ARGB_PRE = 1;
|
||||
public static final int PF_INT_RGB = 2;
|
||||
public static final int PF_INT_RGBX = 3;
|
||||
public static final int PF_INT_BGR = 4;
|
||||
public static final int PF_INT_BGRX = 5;
|
||||
public static final int PF_USHORT_565_RGB = 6;
|
||||
public static final int PF_USHORT_555_RGB = 7;
|
||||
public static final int PF_USHORT_555_RGBX = 8;
|
||||
public static final int PF_BYTE_GRAY = 9;
|
||||
public static final int PF_USHORT_GRAY = 10;
|
||||
public static final int PF_3BYTE_BGR = 11;
|
||||
/**
|
||||
* SurfaceTypes
|
||||
*/
|
||||
|
||||
private static final String DESC_VK_SURFACE = "VK Surface";
|
||||
private static final String DESC_VK_SURFACE_RTT =
|
||||
"VK Surface (render-to-texture)";
|
||||
private static final String DESC_VK_TEXTURE = "VK Texture";
|
||||
|
||||
|
||||
// We want non-premultiplied alpha to prevent precision loss, so use PixelConverter.Argb
|
||||
// See also VKUtil_DecodeJavaColor.
|
||||
static final SurfaceType VKSurface =
|
||||
SurfaceType.Any.deriveSubType(DESC_VK_SURFACE,
|
||||
PixelConverter.Argb.instance);
|
||||
static final SurfaceType VKSurfaceRTT =
|
||||
VKSurface.deriveSubType(DESC_VK_SURFACE_RTT);
|
||||
static final SurfaceType VKTexture =
|
||||
SurfaceType.Any.deriveSubType(DESC_VK_TEXTURE);
|
||||
static final SurfaceType VKSurface = SurfaceType.Any.deriveSubType("VK Surface", PixelConverter.Argb.instance);
|
||||
|
||||
protected static VKRenderer vkRenderPipe;
|
||||
protected static PixelToParallelogramConverter vkTxRenderPipe;
|
||||
@@ -93,74 +67,59 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
protected static VKDrawImage vkImagePipe;
|
||||
|
||||
static {
|
||||
if (!GraphicsEnvironment.isHeadless()) {
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
vkImagePipe = new VKDrawImage();
|
||||
vkTextPipe = new VKTextRenderer(rq);
|
||||
vkRenderPipe = new VKRenderer(rq);
|
||||
if (GraphicsPrimitive.tracingEnabled()) {
|
||||
vkTextPipe = vkTextPipe.traceWrap();
|
||||
//The wrapped vkRenderPipe will wrap the AA pipe as well...
|
||||
vkAAPgramPipe = vkRenderPipe.traceWrap();
|
||||
}
|
||||
vkAAPgramPipe = vkRenderPipe.getAAParallelogramPipe();
|
||||
vkTxRenderPipe =
|
||||
new PixelToParallelogramConverter(vkRenderPipe, vkRenderPipe, 1.0, 0.25, true);
|
||||
|
||||
VKBlitLoops.register();
|
||||
VKMaskFill.register();
|
||||
VKMaskBlit.register();
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
vkImagePipe = new VKDrawImage();
|
||||
vkTextPipe = new VKTextRenderer(rq);
|
||||
vkRenderPipe = new VKRenderer(rq);
|
||||
if (GraphicsPrimitive.tracingEnabled()) {
|
||||
vkTextPipe = vkTextPipe.traceWrap();
|
||||
//The wrapped vkRenderPipe will wrap the AA pipe as well...
|
||||
vkAAPgramPipe = vkRenderPipe.traceWrap();
|
||||
}
|
||||
vkAAPgramPipe = vkRenderPipe.getAAParallelogramPipe();
|
||||
vkTxRenderPipe = new PixelToParallelogramConverter(vkRenderPipe, vkRenderPipe, 1.0, 0.25, true);
|
||||
}
|
||||
|
||||
// TODO Do we really want to have scale there? It is used by getDefaultScaleX/Y...
|
||||
protected int scale;
|
||||
private final VKFormat format;
|
||||
protected VKGraphicsConfig gc;
|
||||
protected double scale;
|
||||
protected int width;
|
||||
protected int height;
|
||||
protected int type;
|
||||
private VKGraphicsConfig graphicsConfig;
|
||||
// these fields are set from the native code when the surface is
|
||||
// initialized
|
||||
private int nativeWidth;
|
||||
private int nativeHeight;
|
||||
private int type;
|
||||
|
||||
/**
|
||||
* Returns the appropriate SurfaceType corresponding to the given Metal
|
||||
* surface type constant (e.g. TEXTURE -> MTLTexture).
|
||||
*/
|
||||
private static SurfaceType getCustomSurfaceType(int vkType) {
|
||||
switch (vkType) {
|
||||
case TEXTURE:
|
||||
return VKTexture;
|
||||
case RT_TEXTURE:
|
||||
return VKSurfaceRTT;
|
||||
default:
|
||||
return VKSurface;
|
||||
}
|
||||
}
|
||||
|
||||
protected VKSurfaceData(VKGraphicsConfig gc, ColorModel cm, int type, int width, int height)
|
||||
{
|
||||
super(getCustomSurfaceType(type), cm);
|
||||
this.graphicsConfig = gc;
|
||||
protected VKSurfaceData(VKFormat format, int transparency, int type) {
|
||||
super(format.getSurfaceType(transparency), format.getFormatModel(transparency).getColorModel());
|
||||
this.format = format;
|
||||
this.type = type;
|
||||
setBlitProxyCache(gc.getSurfaceDataProxyCache());
|
||||
|
||||
// TEXTURE shouldn't be scaled, it is used for managed BufferedImages.
|
||||
scale = 1;
|
||||
this.width = width * scale;
|
||||
this.height = height * scale;
|
||||
}
|
||||
|
||||
public VKFormat getFormat() {
|
||||
return format;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultScaleX() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultScaleY() {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one of the surface type constants defined above.
|
||||
*/
|
||||
@Override
|
||||
public final int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphicsConfiguration getDeviceConfiguration() {
|
||||
return (GraphicsConfiguration) gc;
|
||||
}
|
||||
|
||||
public void flush() {
|
||||
invalidate();
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
@@ -178,28 +137,28 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
throw new InternalError("not implemented yet");
|
||||
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());
|
||||
blit.Blit(this, sd, AlphaComposite.Src, null, x, y, 0, 0, width, height);
|
||||
return image;
|
||||
}
|
||||
|
||||
public Raster getRaster(int x, int y, int w, int h) {
|
||||
return getSnapshot(x, y, w, h).getRaster().createTranslatedChild(x, y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Rectangle getNativeBounds() {
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
return new Rectangle(nativeWidth, nativeHeight);
|
||||
} finally {
|
||||
rq.unlock();
|
||||
}
|
||||
return new Rectangle(width, height);
|
||||
}
|
||||
|
||||
public void validatePipe(SunGraphics2D sg2d) {
|
||||
TextPipe textpipe;
|
||||
boolean validated = false;
|
||||
|
||||
// MTLTextRenderer handles both AA and non-AA text, but
|
||||
// VKTextRenderer handles both AA and non-AA text, but
|
||||
// only works with the following modes:
|
||||
// (Note: For LCD text we only enter this code path if
|
||||
// canRenderLCDText() has already validated that the mode is
|
||||
@@ -247,7 +206,7 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
}
|
||||
} else {
|
||||
if (sg2d.paintState <= SunGraphics2D.PAINT_ALPHACOLOR) {
|
||||
if (graphicsConfig.isCapPresent(CAPS_PS30) &&
|
||||
if (getGraphicsConfig().isCapPresent(CAPS_PS30) &&
|
||||
(sg2d.imageComp == CompositeType.SrcOverNoEa ||
|
||||
sg2d.imageComp == CompositeType.SrcOver))
|
||||
{
|
||||
@@ -300,18 +259,29 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
sg2d.imagepipe = vkImagePipe;
|
||||
}
|
||||
|
||||
// TODO this is only used for caps checks, refactor and remove this method
|
||||
public VKGraphicsConfig getGraphicsConfig() {
|
||||
return graphicsConfig;
|
||||
return (VKGraphicsConfig) getDeviceConfiguration();
|
||||
}
|
||||
|
||||
protected synchronized void configure() {
|
||||
protected int revalidate(VKGraphicsConfig gc) {
|
||||
if (gc.getFormat() != format) return VolatileImage.IMAGE_INCOMPATIBLE;
|
||||
else if (this.gc == gc) return VolatileImage.IMAGE_OK;
|
||||
// TODO proxy cache needs to be cleared for this surface data?
|
||||
setBlitProxyCache(gc.getGPU().getSurfaceDataProxyCache());
|
||||
this.gc = gc;
|
||||
return VolatileImage.IMAGE_RESTORED;
|
||||
}
|
||||
|
||||
protected void configure() {
|
||||
VKRenderQueue rq = VKRenderQueue.getInstance();
|
||||
rq.lock();
|
||||
try {
|
||||
RenderBuffer buf = rq.getBuffer();
|
||||
rq.ensureCapacityAndAlignment(20, 4);
|
||||
rq.ensureCapacityAndAlignment(24, 4);
|
||||
buf.putInt(CONFIGURE_SURFACE);
|
||||
buf.putLong(getNativeOps());
|
||||
buf.putLong(gc.getGPU().getNativeHandle());
|
||||
buf.putInt(width);
|
||||
buf.putInt(height);
|
||||
|
||||
@@ -321,5 +291,8 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
}
|
||||
}
|
||||
|
||||
public abstract boolean isOnScreen();
|
||||
@Override
|
||||
public BufferedContext getContext() {
|
||||
return VKContext.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, JetBrains s.r.o.. 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
|
||||
@@ -29,17 +28,17 @@ package sun.java2d.vulkan;
|
||||
import sun.awt.image.SunVolatileImage;
|
||||
import sun.awt.image.VolatileSurfaceManager;
|
||||
import sun.java2d.SurfaceData;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
|
||||
import java.awt.GraphicsConfiguration;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.image.ColorModel;
|
||||
import sun.java2d.pipe.hw.AccelSurface;
|
||||
import java.awt.image.VolatileImage;
|
||||
|
||||
public class WLVKVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
public class VKVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
|
||||
private final boolean accelerationEnabled;
|
||||
|
||||
public WLVKVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
public VKVolatileSurfaceManager(SunVolatileImage vImg, Object context) {
|
||||
super(vImg, context);
|
||||
|
||||
/*
|
||||
@@ -48,7 +47,7 @@ public class WLVKVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
*/
|
||||
int transparency = vImg.getTransparency();
|
||||
|
||||
accelerationEnabled = VKInstance.isSurfaceDataAccelerated() &&
|
||||
accelerationEnabled = VKEnv.isSurfaceDataAccelerated() &&
|
||||
transparency != Transparency.BITMASK;
|
||||
}
|
||||
|
||||
@@ -62,25 +61,43 @@ public class WLVKVolatileSurfaceManager extends VolatileSurfaceManager {
|
||||
*/
|
||||
protected SurfaceData initAcceleratedSurface() {
|
||||
try {
|
||||
WLVKGraphicsConfig gc =
|
||||
(WLVKGraphicsConfig)vImg.getGraphicsConfig();
|
||||
ColorModel cm = gc.getColorModel(vImg.getTransparency());
|
||||
VKGraphicsConfig gc = (VKGraphicsConfig) vImg.getGraphicsConfig();
|
||||
int type = vImg.getForcedAccelSurfaceType();
|
||||
// if acceleration type is forced (type != UNDEFINED) then
|
||||
// use the forced type, otherwise choose RT_TEXTURE
|
||||
if (type == AccelSurface.UNDEFINED) {
|
||||
type = AccelSurface.RT_TEXTURE;
|
||||
}
|
||||
return new VKOffScreenSurfaceData(
|
||||
gc, vImg, cm, type, vImg.getWidth(), vImg.getHeight());
|
||||
VKOffScreenSurfaceData sd = new VKOffScreenSurfaceData(vImg, gc.getFormat(), vImg.getTransparency(), type,
|
||||
vImg.getWidth(), vImg.getHeight());
|
||||
sd.revalidate(gc);
|
||||
sd.configure();
|
||||
return sd;
|
||||
} catch (NullPointerException | OutOfMemoryError ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int validate(GraphicsConfiguration gc) {
|
||||
if (gc != null && sdAccel != null && isAccelerationEnabled() && isConfigValid(gc)) {
|
||||
VKSurfaceData vksd = (VKSurfaceData) sdAccel;
|
||||
switch (vksd.revalidate((VKGraphicsConfig) gc)) {
|
||||
case VolatileImage.IMAGE_INCOMPATIBLE:
|
||||
return VolatileImage.IMAGE_INCOMPATIBLE;
|
||||
case VolatileImage.IMAGE_RESTORED:
|
||||
vksd.setSurfaceLost(true);
|
||||
vksd.configure();
|
||||
}
|
||||
}
|
||||
return super.validate(gc);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isConfigValid(GraphicsConfiguration gc) {
|
||||
return ((gc == null) || (gc == vImg.getGraphicsConfig()));
|
||||
// We consider configs with the same format compatible across Vulkan devices.
|
||||
return gc == null || vImg.getGraphicsConfig() == null ||
|
||||
((VKGraphicsConfig) gc).getFormat() == ((VKGraphicsConfig) vImg.getGraphicsConfig()).getFormat();
|
||||
}
|
||||
|
||||
@Override
|
||||
20
src/java.desktop/share/glsl/vulkan/alpha_type.glsl
Normal file
20
src/java.desktop/share/glsl/vulkan/alpha_type.glsl
Normal 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
|
||||
@@ -1,11 +1,13 @@
|
||||
#version 450
|
||||
#extension GL_GOOGLE_include_directive: require
|
||||
#define ALPHA_TYPE_SPEC_INDEX 0
|
||||
#include "alpha_type.glsl"
|
||||
|
||||
layout(binding = 0) uniform sampler2D u_TexSampler;
|
||||
layout(set = 0, binding = 0) uniform texture2D u_Texture;
|
||||
layout(set = 1, binding = 0) uniform sampler u_Sampler;
|
||||
layout(location = 0) in vec2 in_TexCoord;
|
||||
layout(location = 0) out vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
out_Color = texture(u_TexSampler, in_TexCoord);
|
||||
// TODO: Temporary fix of unexpected transparency with blit operations
|
||||
out_Color.a = 1.0;
|
||||
out_Color = convertAlpha(texture(sampler2D(u_Texture, u_Sampler), in_TexCoord));
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec2 viewportNormalizer; // 2.0 / viewport
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
@@ -9,6 +9,6 @@ layout(location = 1) in vec2 in_TexCoord;
|
||||
layout(location = 0) out vec2 out_TexCoord;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(in_Position * push.viewportNormalizer - vec2(1.0), 0.0, 1.0);
|
||||
gl_Position = vec4(vec3(in_Position, 1.0)*push.transform, 0.0, 1.0);
|
||||
out_TexCoord = in_TexCoord;
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec2 viewportNormalizer; // 2.0 / viewport
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in ivec2 in_Position;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(vec2(in_Position) * push.viewportNormalizer - vec2(1.0), 0.0, 1.0);
|
||||
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec2 viewportNormalizer; // 2.0 / viewport
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in vec2 in_Position;
|
||||
@@ -9,6 +9,6 @@ layout(location = 1) in vec4 in_Color;
|
||||
layout(location = 0) out flat vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(in_Position * push.viewportNormalizer - vec2(1.0), 0.0, 1.0);
|
||||
gl_Position = vec4(vec3(in_Position, 1)*push.transform, 0.0, 1.0);
|
||||
out_Color = in_Color;
|
||||
}
|
||||
@@ -10,7 +10,7 @@ layout(location = 1) in flat vec4 in_Color;
|
||||
layout(location = 0) out vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
ivec2 maskPos = ivec2(gl_FragCoord.xy) - in_OriginOffsetAndScanline.xy;
|
||||
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);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#version 450
|
||||
|
||||
layout(push_constant) uniform PushConstants {
|
||||
vec2 viewportNormalizer; // 2.0 / viewport
|
||||
mat2x3 transform;
|
||||
} push;
|
||||
|
||||
layout(location = 0) in ivec4 in_PositionOffsetAndScanline;
|
||||
@@ -14,7 +14,7 @@ layout(location = 0) out flat ivec4 out_OriginOffsetAndScanline;
|
||||
layout(location = 1) out flat vec4 out_Color;
|
||||
|
||||
void main() {
|
||||
gl_Position = vec4(vec2(in_PositionOffsetAndScanline.xy) * push.viewportNormalizer - vec2(1.0), 0.0, 1.0);
|
||||
gl_Position = vec4(vec3(in_PositionOffsetAndScanline.xy, 1)*push.transform, 0.0, 1.0);
|
||||
out_OriginOffsetAndScanline = in_PositionOffsetAndScanline;
|
||||
out_Color = in_Color;
|
||||
}
|
||||
@@ -432,22 +432,22 @@ bool CARR_hash_map_linear_probing_rehash(CARR_MAP_LAYOUT_ARGS, void** handle, CA
|
||||
/**
|
||||
* Find a value for the provided key.
|
||||
* @param P map
|
||||
* @param KEY key to find, can be a compound literal, like (int){0}
|
||||
* @param ... key to find, can be a compound literal, like (int){0}
|
||||
* @return pointer to the found value, or NULL
|
||||
*/
|
||||
#define MAP_FIND(P, KEY) \
|
||||
CARR_MAP_VALUE_PTR((P), CARR_MAP_DISPATCH((P), find, (P), CARR_MAP_KEY_GUARD((P), &(KEY)), NULL, false))
|
||||
#define MAP_FIND(P, ...) \
|
||||
CARR_MAP_VALUE_PTR((P), CARR_MAP_DISPATCH((P), find, (P), CARR_MAP_KEY_GUARD((P), &(__VA_ARGS__)), NULL, false))
|
||||
|
||||
/**
|
||||
* Find a value for the provided key, or insert a new one.
|
||||
* Value is zeroed for newly inserted items.
|
||||
* On allocation failure, C_ARRAY_UTIL_ALLOCATION_FAILED is called.
|
||||
* @param P map
|
||||
* @param KEY key to find, can be a compound literal, like (int){0}
|
||||
* @param ... key to find, can be a compound literal, like (int){0}
|
||||
* @return dereferenced pointer to the found value
|
||||
*/
|
||||
#define MAP_AT(P, KEY) (*(MAP_ENSURE_EXTRA_CAPACITY((P), 1), \
|
||||
CARR_MAP_VALUE_PTR((P), CARR_MAP_DISPATCH((P), find, (P), CARR_MAP_KEY_GUARD((P), &(KEY)), NULL, true))))
|
||||
#define MAP_AT(P, ...) (*(MAP_ENSURE_EXTRA_CAPACITY((P), 1), \
|
||||
CARR_MAP_VALUE_PTR((P), CARR_MAP_DISPATCH((P), find, (P), CARR_MAP_KEY_GUARD((P), &(__VA_ARGS__)), NULL, true))))
|
||||
|
||||
/**
|
||||
* Resolve provided key and find corresponding value.
|
||||
@@ -474,10 +474,10 @@ bool CARR_hash_map_linear_probing_rehash(CARR_MAP_LAYOUT_ARGS, void** handle, CA
|
||||
/**
|
||||
* Remove the provided key, if one exists.
|
||||
* @param P map
|
||||
* @param KEY key to remove, can be a compound literal, like (int){0}
|
||||
* @param ... key to remove, can be a compound literal, like (int){0}
|
||||
* @return true if the key was removed
|
||||
*/
|
||||
#define MAP_REMOVE(P, KEY) CARR_MAP_DISPATCH((P), remove, (P), CARR_MAP_KEY_GUARD((P), &(KEY)))
|
||||
#define MAP_REMOVE(P, ...) CARR_MAP_DISPATCH((P), remove, (P), CARR_MAP_KEY_GUARD((P), &(__VA_ARGS__)))
|
||||
|
||||
/**
|
||||
* Ensure that map has enough capacity to insert COUNT more items without reallocation.
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include "VKUtil.h"
|
||||
#include "VKBase.h"
|
||||
#include "VKAllocator.h"
|
||||
#include "VKEnv.h"
|
||||
|
||||
/**
|
||||
* Block size is a minimum allocation size.
|
||||
@@ -165,9 +165,11 @@ VKMemoryRequirements VKAllocator_ImageRequirements(VKAllocator* allocator, VkIma
|
||||
return r;
|
||||
}
|
||||
|
||||
void VKAllocator_PadToAlignment(VKMemoryRequirements* requirements) {
|
||||
void VKAllocator_PadToAlignment(VKAllocator* allocator, VKMemoryRequirements* requirements) {
|
||||
assert(allocator != NULL);
|
||||
assert(requirements != NULL);
|
||||
VkMemoryRequirements* t = &requirements->requirements.memoryRequirements;
|
||||
if (t->alignment < allocator->device->nonCoherentAtomSize) t->alignment = allocator->device->nonCoherentAtomSize;
|
||||
t->size = ((t->size + t->alignment - 1) / t->alignment) * t->alignment;
|
||||
requirements->dedicatedRequirements.requiresDedicatedAllocation = VK_FALSE;
|
||||
requirements->dedicatedRequirements.prefersDedicatedAllocation = VK_FALSE;
|
||||
@@ -562,8 +564,7 @@ void VKAllocator_Invalidate(VKAllocator* allocator, VKMemory memory, VkDeviceSiz
|
||||
}
|
||||
|
||||
VKAllocator* VKAllocator_Create(VKDevice* device) {
|
||||
VKGraphicsEnvironment* ge = VKGE_graphics_environment();
|
||||
VKAllocator* allocator = (VKAllocator*) calloc(1, sizeof(VKAllocator));
|
||||
VKAllocator* allocator = calloc(1, sizeof(VKAllocator));
|
||||
allocator->device = device;
|
||||
allocator->freePageIndex = NO_PAGE_INDEX;
|
||||
for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
|
||||
@@ -572,7 +573,7 @@ VKAllocator* VKAllocator_Create(VKDevice* device) {
|
||||
.allocationLevelTracker = MIN_SHARED_PAGE_LEVEL * 2
|
||||
};
|
||||
}
|
||||
ge->vkGetPhysicalDeviceMemoryProperties(device->physicalDevice, &allocator->memoryProperties);
|
||||
VKEnv_GetInstance()->vkGetPhysicalDeviceMemoryProperties(device->physicalDevice, &allocator->memoryProperties);
|
||||
|
||||
J2dRlsTraceLn1(J2D_TRACE_INFO, "VKAllocator_Create: allocator=%p", allocator);
|
||||
return allocator;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user