Is there a way in Java to detect when the monitor backlight turns on?
I'm using Windows 8.1.
I just want to run a function whenever the screen turns on, like when you wiggle the mouse after 20 minutes.
Thanks!
Not that I know of.
I used JNA library (which requires a .dll/.so in your path) to call native OS apis to poll if screensaver was on or not (win32) or pull the lib pthread self thread id on linux, for examples.
But you will need to dig a bit to learn the native api related (not that hard to google). JNA will be the learning curve, but once you got it, it's quite enabling!
There are also callbacks in JNA, but I didn't get to try them. Beware, this is definitely not pure java!
java.awt.window has a function that reads the following:
getGraphicsConfiguration()
public GraphicsConfiguration getGraphicsConfiguration()
Gets the GraphicsConfiguration associated with this Component. If
the Component has not been assigned a specific
GraphicsConfiguration, the GraphicsConfiguration of the
Component object's top-level container is returned. If the
Component has been created, but not yet added to a Container, this
method returns null.
Returns:
the GraphicsConfiguration used by this Component or null
This might not be exactly what you are looking for but you may work around this and maybe use it to detect if a monitor is null or not.
Full docs:
https://docs.oracle.com/javase/7/docs/api/java/awt/Component.html#getGraphicsConfiguration()
I'm pretty sure there is no pure Java way. But if your monitor screensaver situation is entirely in your hands, you can use a pure black screensaver.
This solution is not rock solid, but it may hit the spot >95% of the time.
1) Set a pure black screensaver in accordance with your energy settings (i.e. when the screen should turn off).
2) Have a 0.5 second interval Thread check if the mouse's position on screen was changed.
3) If so, use Robot's createScreenCapture() to get a BufferedImage of the whole screen.
4) Analyze the image. Fastest way is to directly access its bytes: final DataBufferByte dbi = (DataBufferByte) img.getRaster().getDataBuffer(); If it's pure black, the backlight should still be off.
To save cycles (The screenshot + analysis would eat a lot of energy.), you could prevent the screen capture stuff until the mouse hasn't moved for 20 minutes or whatever your energy time was. Maybe there's a Java-way to obtain this information from the system so you don't have to change your parameters in two places (Windows and your app).
Related
I'm working on a libGDX (library on top of LWJGL) game project, and use the Intellij IDEA IDE from several different workstations:
Windows 7 x64 laptop with two displays (1920x1080 and 1600x1200), nVidia GT540M.
Ubuntu 12.04 LTS on a laptop with a single display (1366x768), Intel integrated graphics.
Ubuntu 12.04 LTS on a desktop with two displays (1920x1080 and 1280x1024), nVidia GTS 450.
I'm using the OpenJDK for Java 6 on the Ubuntu boxes, and Sun/Oracle Java 6 on the Windows box (I heard Java 6 was the one to use for Android compatibility).
When running on full-screen:
Windows 7 laptop: works fine.
Ubuntu laptop: works fine.
Ubuntu desktop: background image is shown enlarged, and only part of it fits on the screen. +
Looking into this further, I see that the calls to Gdx.graphics.getHeight() and Gdx.graphics.getWidth() return the size of the rectangle needed to cover both displays, in my case 3200x1080, but when I tell my game to run full-screen, it only uses one of the displays, so the cameras get set to 1920x1080, but my camera movement and Tiled map panning think they've got 3200x1080 to work with, making things distorted and unusable (since character can walk off of the screen to the right).
I'm guessing my problem actually comes from the sizes returned by the awt.Toolkit's getScreenSize() call, but I don't know how to interrogate it more deeply to get the size of the screen it will actually use when I go fullscreen.
My DesktopStarter gets the screen size and sets fullscreen as follows:
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
cfg.width = screenDimension.width;
cfg.height = screenDimension.height;
cfg.fullscreen = true;
new LwjglApplication(new Game1(), cfg);
Is there a work-around to get the height/width of just the display that "full screen" will actually launch into?
So the trouble I'm seeing, is that executing the game.jar file, exiting the game, then executing again, repeatedly, results in different display modes showing up in the list of modes returned by Gdx.graphics.getDisplayModes() -- as P.T. pointed out below, this is a thin wrapper around LWJGL's Display.getAvailableDisplayModes(). Why is this happening? Why would it be a different set of modes presented on subsequent runs on Ubuntu?
edit: per P.T.'s suggestion, put LWJGL references in question, since it seems to be LWJGL that's providing the list of display modes.
Thanks!
I would refrain from using Toolkit.getDefaultToolkit() and use solely lwjgl.util.Display.getAvailableDisplayModes() or the method described by libgdx.
Once you have set up a fullscreen window, fetch its size (if your set-up method doesn't already know that) and only use this information from thereon.
If Display.getAvailableDisplayModes() changes its sort order on different executions, simply re-sort them and use the biggest one available or use a standard one and provide in-game settings to change them.
GraphicsDevice monitors[]=GraphicsEnvironment.getScreenDevices();
Dimension screen_resolution[monitors.length];
for (int monitorID = 0; monitorID < monitors.length; monitorID++)
{
screen_resolution[monitorID] = new Dimension(monitors[monitorID].getDisplyMode().getWidth(),monitors[monitorID].getDisplyMode().getHeight());
}
You could use javafx.stage.screen to work around this issue, but you'd either have to add JavaFX if you stick with Java 6, or upgrade to Java 7 (It's included with the Java 7 SDK.)
From the documentation:
"Describes the characteristics of a graphics destination such as
monitor. In a virtual device multi-screen environment in which the
desktop area could span multiple physical screen devices, the bounds
of the Screen objects are relative to the Screen.primary.
For example:
Rectangle2D primaryScreenBounds =
Screen.getPrimary().getVisualBounds();
//set Stage boundaries to visible bounds of the main screen
stage.setX(primaryScreenBounds.getMinX());
stage.setY(primaryScreenBounds.getMinY());
stage.setWidth(primaryScreenBounds.getWidth());
stage.setHeight(primaryScreenBounds.getHeight());
stage.show();"
There are a variety of other methods (getBounds(), getDpi(), getScreens(), etc.) that would also likely be very useful for you.
Maybe get the dimensions of the monitor your currently using, so on the different sized monitors, just get the dimensions. You may have to do things differently for different sized monitors.
Maybe the background image is enlarged due to it thinking it's still working on the other screens.
Hope this helps, if not gl
I would refrain from using lwjgl completely. It may seem simple enough on the surface, but as you try to add in more advanced features, you'll realize that a wrapper over OpenGL won't give you that functionality, or it'll make the program 3x slower. I suggest moving into c++ and OpenGL (if this is an option). You will be surprised at its simplicity.
Otherwise, cross-platform libraries generally do have these sorts of glitches. To solve your problem, you need to stop relying on the library to determine your viewport resolutions. Instead, enumerate through all the possible display modes and pick the best one according to you. This will result in much more defined behavior and will be easier to debug than utilizing a default config which appears as if by magic. In general, you want to always be sure you know what data you are using. Even worse, I just noticed that you are using a wrapper over a wrapper. This over-complicates and will slow down rendering much more that you can imagine (20x on average).
Here
http://www.lwjgl.org/wiki/index.php?title=LWJGL_Basics_5_%28Fullscreen%29
you will find a convenience method for lwjgl to chose a suitable full screen display mode for your desktop. You can use the same method to determine the resolution as well and use it for your gl ops later.
I am not sure but it worked for me. Just set the size after "start" the game, like in the following code:
public static void main(String[] args) {
LwjglApplicationConfiguration cfg = new LwjglApplicationConfiguration();
cfg.title = "Palmeiras!!";
cfg.vSyncEnabled = false;
cfg.forceExit = true;
cfg.allowSoftwareMode = true;
new LwjglApplication(new Palmeiras(null), cfg);
Gdx.graphics.setDisplayMode(Gdx.graphics.getDesktopDisplayMode().width,
Gdx.graphics.getDesktopDisplayMode().height, true);
}
Let me know if it worked for you.
I would refrain from using Toolkit.getDefaultToolkit() and use solely lwjgl.util.Display.getAvailableDisplayModes() or the method described by libgdx.
Once you have set up a fullscreen window, fetch its size (if your set-up method doesn't already know that) and only use this information from thereon.
If Display.getAvailableDisplayModes() changes its sort order on different executions, simply re-sort them and use the biggest one available or use a standard one and provide in-game settings to change them.
I have a very simple application in libgdx. It currently is supposed to cover half of the screen with pink texture. And it does that, the texture however is blinking. Basing on my own understanding of subject, as well as this thread:
LibGDX blinking
I need to enable double buffering. Or alternatively, write to my buffer. The thing is, either I am inept with google or it's very difficult to find any information how to manipulate buffers in libgdx. If someone could provide me with resources, explaining how to manipulate buffers, and how to create one, how to swap them with current display etc. I would be very grateful.
EDIT:
After searching the web some more, I found post on badlogic forum, claiming that libgdx has double buffering set by default. The question is, how does it work? When are the buffers swapped?
Libgdx has double buffering enabled by default (its really part of the underlying OpenGL infrastructure, not Libgdx). I don't think Libgdx exposes any controls over double buffering. There are some controls to disable vsync which might create some tearing, but are unlikely to be related.
The more likely way to get this behavior is if, somehow, your render method is only invoked once. This will draw into one buffer. Then, assuming render has become a no-op, nothing is drawn into the other buffer, they're switched, nothing is drawn into the original buffer, they're switched, etc. This can lead to the blinking behavior you're seeing.
If that guess doesn't cover it you'll have to provide more details. Which platform are you running on? Are you running a stable version of Libgdx or one of the nightly builds? How are you setting up the libgdx app configuration? What does your render method actually look like?
I'm currently working on a project where I need to plot the predicted footprint of a satellite on a mercator-projected world map with possible scaling/cropping/etc. done to the map.
I thought Cairo would be a good library to use for this purpose. There are Java-bindings available for it. However, I just can't find a way to make it render onto a SWING GUI (e. g. onto the surface of a JPanel). I thought about rendering into a byte buffer and plotting it out pixel by pixel using Java2D, but I can't find any API call to make Cairo render into a buffer (which is weird, as this is one of the most fundamental functionalities I'd expect to get supported by such a library).
Any way I can achieve this? I know there is Java2D, but it is fairly basic. I'd really appreciate a more powerful, widespread, well-tested, high-quality, free (LGPL) graphics library for this purpose. Cairo would be such a perfect fit, if I could get it to work with SWING somehow.
Thank you very much for your proposals.
One of the fundamentals in Cairo is that any non-abstract image context is bound to one of the supported back ends.
I've never tried the Java bindings, but it is likely they are a thin layer, not providing a a new surface type - you should use the "Image Surface" type.
On the C documentation for the Library, there is a "cairo_image_surface_get_data()" call
(here: http://cairographics.org/manual/cairo-Image-Surfaces.html ) which gives one acess to the buffer.
Maybe the bindings didn't expose this to Java due to the low level memory access required to actually use its contents. If that is true, then I propose you the following work-around:
(1)Render your results to a Cairo Image Surface, (2) Write a temporary file with the surface contents,(3) Read and display the temporary file with the Java 2D API.
Here is a example.
I found this examples on http://java-gnome.sourceforge.net
It create a gtk window, and actually a gtk DrawingArea widget, the onDraw() event uses cairo.
I compiled and run it on linux, it works good.
however java-gnome seems only have linux binary. Maybe somebody could make a windows binary, but need some work.
It is a gtk window, so have nothing to do with swing.
Maybe you don't need swing if gtk(java-gnome) can fit your needs.
If you must use swing, you can use cairo to render to a image in memory, then show it to JComponent by somthing like overriding paintComponent() method. I don't know the performance.
I want to be able to draw consecutive bitmaps (of type BufferedImage.TYPE_INT_RGB) of a video as quickly as possible in java. I want to know the best method in doing so. Does anyone have any advice where I should start? From what I've read, 2 options are:
1) Use GDI/GDI+ routines in a JNI dll working with JAWT (Im on Windows)
2) Use Java3D and apply Textures to a Box's face and rotate it to the camera
Im interesting in any advice on these topics as well as any others.
I have done a decent amount of GDI/GDI+ programming in VB when i created an ActiveX control, so using GDI should be painless, but im guessing Java3D will utilize the GPU more (I could be wrong) and give better performance. What do you think? GDI and JAWT with my previous experience, or start and new API journey with Java3D.
Thanks in advance. :)
To obtain a fluid animation (if it what you want to get), you need to use double buffering. For doing this, you will need to create a new java.awt.Image (or a subclass like BufferedImage, or if you want OpenGL accelerated processing, VolatileImage) for each frame you want to display. If you haven't already done so, call Image.getGraphics() to get a java.awt.Graphics object (can also be useful to add your content to the Image). At the end, when you hidden Image is complete, call Graphics.draw() to replace the current display smoothly.
VolatileImage is OpenGL accelerated and much faster. When VolatileImage.getGraphics() is called, it actually returns a Graphics2D, which is also part of the accelerated graphic pipeline.
It works on Windows, Linux and Solaris, but you need to have OpenGL drivers installed for your graphic card.
Some additional refs:
Accelerated graphic pipeline:
http://download.oracle.com/javase/1.5.0/docs/guide/2d/new_features.html
http://www.javalobby.org/forums/thread.jspa?threadID=16840&tstart=0
Double buffering:
http://www.java2s.com/Code/Java/2D-Graphics-GUI/Smoothmoveusingdoublebuffer.htm
http://www.heatonresearch.com/articles/23/page2.html
http://www.javacooperation.gmxhome.de/BildschirmflackernEng.html
I'm having a strange problem, basically in Java Graphics.drawImage() is extremely slow on some computers and faster on others. This isn't related to the computers power either, some weaker computers run it fine while some stronger ones seem to choke up at the drawImage call.
It may or may not be related to the width and height, I have a very, very large width and height defined (something like 5000 by 2500). I wouldn't think it's the issue except like I said it runs in real time speed on some computers and slower on others and doesn't seem to be tied to the computers relative power.
Both computers have the same version of Java, both use Vista. One has a 1.83ghz Core 2 Duo with 1gb RAM and onboard graphics (runs everything fine), the other has a 2.53 ghz core 2 duo with a 9600GS (latest nVidia drivers) and 4gb of RAM and it literally chugs on the drawImage call.
Any ideas?
edit: ok this is really wierd, I'm drawing the image to a window in Swing, now when I resize the window and make it really small the image gets scaled down too and it becomes small. Suddenly everything runs smoothly, when I scale it back up to the size it was before it's still running smoothly!
It also has multiple monitor issues, if I do the resize trick to make it run faster on one monitor then scroll it over to another monitor when more than half of the window is in the new monitor it starts chugging again. I have to resize the window again to small then back to its original size to get back the speed.
If I do the resize trick on one monitor, move it over to the other it of course chugs, but if I return it back to the original monitor on which I did the resize trick it works 100%
If I have two swing windows open (displaying the same image) they both run slow, but if I do the resize trick on one window they both start running smoothly (however this isn't always the case).
*when I say resize the window I mean make it as small as possible to the point the image can't actually be seen.
Could this be a bug in Java maybe?
Performance of writing an image to a screen is very much affected by the format in which the image is stored. If the format is the same as the screen memory wants then it can be very fast; if it is not then a conversion must be done, sometimes pixel by pixel, which is very slow.
If you have any control over how the image is stored, you should store it in a format that the screen is looking for. Here is some sample code:
GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice device = env.getDefaultScreenDevice();
GraphicsConfiguration config = device.getDefaultConfiguration();
BufferedImage buffy = config.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
Graphics g = buffy.getGraphics();
If you are going to draw the image many times it may be worth converting to a compatible format even if it came in some other format.
Drawing an image will also be slower if you are transforming it as you draw, which the 'resizing' part of your description makes me think you might be. Again, do the resize once (when the window is resized) and cache the resized and compatible image so that it can be redrawn quickly.
If you are using sun's Java try some of the following system properties, either as command line parameters or the first lines in main
sun.java2d.opengl=true //force ogl
sun.java2d.ddscale=true //only when using direct3d
sun.java2d.translaccel=true //only when using direct3d
more flags can be viewed at this page
Look at sun.java2d.trace which can allow you to determine the source of less-than-desirable graphics performance.
There are several things that could influence performance here:
Available RAM
CPU speed
Graphic card (onboard or seperate)
Graphic driver
Java version
Used video mode (resolution, bitdepth, acceleration support)
EDIT:
Having a look at the edited question, I'd propose to check if the 9600GS system has the newest NVIDIA drivers installed. I recently installed a driver for an Intel onboard graphics card that replaced the generic Windows driver and made moving windows, watching videos, browsing etc. a lot faster.
All the other specs look good. Perhaps Java doesn't detect the 9600GS and doesn't use hardware acceleration, but I doubt this.
Also check the OS configuration. On Windows, you can turn off hardware acceleration for debugging purposes.
Of course the best way to handle this would be to change your code - resize the image or split it up into chunks as DNS proposed. You'll never be able to see the whole image as it is on the screen.
How are you judging the computers' power? A 50x25 K 32-bit image takes more than 4.5 GB RAM to hold in memory (50000 * 25000 * 4 bytes). If one computer has more RAM than another, that can make a huge difference in speed, because it won't have to swap to disk as often. You should consider grabbing subsections of the image and working with those, instead of the whole thing.
Edit: Are you using the latest Java & graphics drivers? If your image is only 5Kx2.5K, the only thing I can think of is that it's doing it without any hardware acceleration.
Check the screen settings. My bet is that pixel depth is different on the two systems, and that the slow one has an odd pixel depth related to the image object you are trying to display.
Since Java uses OpenGL to do 2D drawing, the performance of your app will be affected by the OpenGL performance of the graphics chip in the respective computer. Support for OpenGL is dwindling in the 3D industry, which means that (ironically) newer chips may be slower at OpenGL rendering than older ones - not only due to hardware but also drivers.
Have you tried Full-Screen Exclusive Mode?
This might help:
http://download.oracle.com/javase/tutorial/extra/fullscreen/index.html