1 /*
2 * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.java2d.d3d;
27
28 import java.awt.Dialog;
29 import java.awt.DisplayMode;
30 import java.awt.Frame;
31 import java.awt.GraphicsConfiguration;
32 import java.awt.Rectangle;
33 import java.awt.Toolkit;
34 import java.awt.Window;
35 import java.awt.event.WindowAdapter;
36 import java.awt.event.WindowEvent;
37 import java.awt.event.WindowListener;
38 import java.awt.peer.WindowPeer;
39 import java.util.ArrayList;
40 import sun.awt.Win32GraphicsDevice;
41 import sun.awt.windows.WWindowPeer;
42 import sun.java2d.pipe.hw.ContextCapabilities;
43 import sun.java2d.windows.WindowsFlags;
44 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
45 import sun.java2d.d3d.D3DContext.D3DContextCaps;
46
47 /**
48 * This class implements D3D-specific functionality, such as fullscreen
49 * exclusive mode and display changes. It is kept separate from
50 * Win32GraphicsDevice to help avoid overburdening the parent class.
51 */
52 public class D3DGraphicsDevice extends Win32GraphicsDevice {
53 private D3DContext context;
54
55 private static boolean d3dAvailable;
56
57 private ContextCapabilities d3dCaps;
58
59 private static native boolean initD3D();
159 while (owner != null) {
160 owner = owner.getOwner();
161 if (owner instanceof Frame) {
162 return (Frame) owner;
163 }
164 }
165 // could get here if passed Window is an owner-less Dialog
166 return null;
167 }
168
169 private boolean fsStatus;
170 private Rectangle ownerOrigBounds = null;
171 private boolean ownerWasVisible;
172 private Window realFSWindow;
173 private WindowListener fsWindowListener;
174 private boolean fsWindowWasAlwaysOnTop;
175 private static native boolean enterFullScreenExclusiveNative(int screen,
176 long hwnd);
177
178 @Override
179 @SuppressWarnings("deprecation")
180 protected void enterFullScreenExclusive(final int screen, WindowPeer wp)
181 {
182 final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
183
184 D3DRenderQueue rq = D3DRenderQueue.getInstance();
185 rq.lock();
186 try {
187 rq.flushAndInvokeNow(new Runnable() {
188 public void run() {
189 long hwnd = wpeer.getHWnd();
190 if (hwnd == 0l) {
191 // window is disposed
192 fsStatus = false;
193 return;
194 }
195 fsStatus = enterFullScreenExclusiveNative(screen, hwnd);
196 }
197 });
198 } finally {
199 rq.unlock();
200 }
201 if (!fsStatus) {
202 super.enterFullScreenExclusive(screen, wp);
203 }
230 * This is a problem for windows for which we do not do any d3d-related
231 * operations (like when we disabled on-screen rendering).
232 *
233 * REMIND: we create an instance per each full-screen device while a single
234 * instance would suffice (but requires more management).
235 */
236 private static class D3DFSWindowAdapter extends WindowAdapter {
237 @Override
238 @SuppressWarnings("static")
239 public void windowDeactivated(WindowEvent e) {
240 D3DRenderQueue.getInstance().restoreDevices();
241 }
242 @Override
243 @SuppressWarnings("static")
244 public void windowActivated(WindowEvent e) {
245 D3DRenderQueue.getInstance().restoreDevices();
246 }
247 }
248
249 @Override
250 @SuppressWarnings("deprecation")
251 protected void addFSWindowListener(Window w) {
252 // if the window is not a toplevel (has an owner) we have to use the
253 // real toplevel to enter the full-screen mode with (4933099).
254 if (!(w instanceof Frame) && !(w instanceof Dialog) &&
255 (realFSWindow = getToplevelOwner(w)) != null)
256 {
257 ownerOrigBounds = realFSWindow.getBounds();
258 WWindowPeer fp = (WWindowPeer)realFSWindow.getPeer();
259
260 ownerWasVisible = realFSWindow.isVisible();
261 Rectangle r = w.getBounds();
262 // we use operations on peer instead of component because calling
263 // them on component will take the tree lock
264 fp.reshape(r.x, r.y, r.width, r.height);
265 fp.setVisible(true);
266 } else {
267 realFSWindow = w;
268 }
269
270 fsWindowWasAlwaysOnTop = realFSWindow.isAlwaysOnTop();
271 ((WWindowPeer)realFSWindow.getPeer()).setAlwaysOnTop(true);
272
273 fsWindowListener = new D3DFSWindowAdapter();
274 realFSWindow.addWindowListener(fsWindowListener);
275 }
276
277 @Override
278 @SuppressWarnings("deprecation")
279 protected void removeFSWindowListener(Window w) {
280 realFSWindow.removeWindowListener(fsWindowListener);
281 fsWindowListener = null;
282
283 /**
284 * Bug 4933099: There is some funny-business to deal with when this
285 * method is called with a Window instead of a Frame. See 4836744
286 * for more information on this. One side-effect of our workaround
287 * for the problem is that the owning Frame of a Window may end
288 * up getting resized during the fullscreen process. When we
289 * return from fullscreen mode, we should resize the Frame to
290 * its original size (just like the Window is being resized
291 * to its original size in GraphicsDevice).
292 */
293 WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
294 if (wpeer != null) {
295 if (ownerOrigBounds != null) {
296 // if the window went into fs mode before it was realized it
297 // could have (0,0) dimensions
298 if (ownerOrigBounds.width == 0) ownerOrigBounds.width = 1;
299 if (ownerOrigBounds.height == 0) ownerOrigBounds.height = 1;
300 wpeer.reshape(ownerOrigBounds.x, ownerOrigBounds.y,
301 ownerOrigBounds.width, ownerOrigBounds.height);
302 if (!ownerWasVisible) {
303 wpeer.setVisible(false);
304 }
305 ownerOrigBounds = null;
306 }
307 if (!fsWindowWasAlwaysOnTop) {
308 wpeer.setAlwaysOnTop(false);
309 }
310 }
311
312 realFSWindow = null;
313 }
323 };
324 final Result res = new Result();
325 rq.flushAndInvokeNow(new Runnable() {
326 public void run() {
327 res.dm = getCurrentDisplayModeNative(screen);
328 }
329 });
330 if (res.dm == null) {
331 return super.getCurrentDisplayMode(screen);
332 }
333 return res.dm;
334 } finally {
335 rq.unlock();
336 }
337 }
338 private static native void configDisplayModeNative(int screen, long hwnd,
339 int width, int height,
340 int bitDepth,
341 int refreshRate);
342 @Override
343 @SuppressWarnings("deprecation")
344 protected void configDisplayMode(final int screen, final WindowPeer w,
345 final int width, final int height,
346 final int bitDepth, final int refreshRate)
347 {
348 // we entered fs mode via gdi
349 if (!fsStatus) {
350 super.configDisplayMode(screen, w, width, height, bitDepth,
351 refreshRate);
352 return;
353 }
354
355 final WWindowPeer wpeer = (WWindowPeer)realFSWindow.getPeer();
356
357 // REMIND: we do this before we switch the display mode, so
358 // the dimensions may be exceeding the dimensions of the screen,
359 // is this a problem?
360
361 // update the bounds of the owner frame
362 if (getFullScreenWindow() != realFSWindow) {
363 Rectangle screenBounds = getDefaultConfiguration().getBounds();
364 wpeer.reshape(screenBounds.x, screenBounds.y, width, height);
365 }
366
367 D3DRenderQueue rq = D3DRenderQueue.getInstance();
368 rq.lock();
369 try {
370 rq.flushAndInvokeNow(new Runnable() {
371 public void run() {
372 long hwnd = wpeer.getHWnd();
373 if (hwnd == 0l) {
374 // window is disposed
375 return;
|
1 /*
2 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.java2d.d3d;
27
28 import java.awt.Dialog;
29 import java.awt.DisplayMode;
30 import java.awt.Frame;
31 import java.awt.GraphicsConfiguration;
32 import java.awt.Rectangle;
33 import java.awt.Toolkit;
34 import java.awt.Window;
35 import java.awt.event.WindowAdapter;
36 import java.awt.event.WindowEvent;
37 import java.awt.event.WindowListener;
38 import java.awt.peer.WindowPeer;
39 import java.util.ArrayList;
40
41 import sun.awt.AWTAccessor;
42 import sun.awt.AWTAccessor.ComponentAccessor;
43 import sun.awt.Win32GraphicsDevice;
44 import sun.awt.windows.WWindowPeer;
45 import sun.java2d.pipe.hw.ContextCapabilities;
46 import sun.java2d.windows.WindowsFlags;
47 import static sun.java2d.d3d.D3DContext.D3DContextCaps.*;
48 import sun.java2d.d3d.D3DContext.D3DContextCaps;
49
50 /**
51 * This class implements D3D-specific functionality, such as fullscreen
52 * exclusive mode and display changes. It is kept separate from
53 * Win32GraphicsDevice to help avoid overburdening the parent class.
54 */
55 public class D3DGraphicsDevice extends Win32GraphicsDevice {
56 private D3DContext context;
57
58 private static boolean d3dAvailable;
59
60 private ContextCapabilities d3dCaps;
61
62 private static native boolean initD3D();
162 while (owner != null) {
163 owner = owner.getOwner();
164 if (owner instanceof Frame) {
165 return (Frame) owner;
166 }
167 }
168 // could get here if passed Window is an owner-less Dialog
169 return null;
170 }
171
172 private boolean fsStatus;
173 private Rectangle ownerOrigBounds = null;
174 private boolean ownerWasVisible;
175 private Window realFSWindow;
176 private WindowListener fsWindowListener;
177 private boolean fsWindowWasAlwaysOnTop;
178 private static native boolean enterFullScreenExclusiveNative(int screen,
179 long hwnd);
180
181 @Override
182 protected void enterFullScreenExclusive(final int screen, WindowPeer wp)
183 {
184 final WWindowPeer wpeer = AWTAccessor.getComponentAccessor()
185 .getPeer(realFSWindow);
186 D3DRenderQueue rq = D3DRenderQueue.getInstance();
187 rq.lock();
188 try {
189 rq.flushAndInvokeNow(new Runnable() {
190 public void run() {
191 long hwnd = wpeer.getHWnd();
192 if (hwnd == 0l) {
193 // window is disposed
194 fsStatus = false;
195 return;
196 }
197 fsStatus = enterFullScreenExclusiveNative(screen, hwnd);
198 }
199 });
200 } finally {
201 rq.unlock();
202 }
203 if (!fsStatus) {
204 super.enterFullScreenExclusive(screen, wp);
205 }
232 * This is a problem for windows for which we do not do any d3d-related
233 * operations (like when we disabled on-screen rendering).
234 *
235 * REMIND: we create an instance per each full-screen device while a single
236 * instance would suffice (but requires more management).
237 */
238 private static class D3DFSWindowAdapter extends WindowAdapter {
239 @Override
240 @SuppressWarnings("static")
241 public void windowDeactivated(WindowEvent e) {
242 D3DRenderQueue.getInstance().restoreDevices();
243 }
244 @Override
245 @SuppressWarnings("static")
246 public void windowActivated(WindowEvent e) {
247 D3DRenderQueue.getInstance().restoreDevices();
248 }
249 }
250
251 @Override
252 protected void addFSWindowListener(Window w) {
253 // if the window is not a toplevel (has an owner) we have to use the
254 // real toplevel to enter the full-screen mode with (4933099).
255 final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
256 if (!(w instanceof Frame) && !(w instanceof Dialog) &&
257 (realFSWindow = getToplevelOwner(w)) != null)
258 {
259 ownerOrigBounds = realFSWindow.getBounds();
260 WWindowPeer fp = acc.getPeer(realFSWindow);
261 ownerWasVisible = realFSWindow.isVisible();
262 Rectangle r = w.getBounds();
263 // we use operations on peer instead of component because calling
264 // them on component will take the tree lock
265 fp.reshape(r.x, r.y, r.width, r.height);
266 fp.setVisible(true);
267 } else {
268 realFSWindow = w;
269 }
270
271 fsWindowWasAlwaysOnTop = realFSWindow.isAlwaysOnTop();
272 ((WWindowPeer) acc.getPeer(realFSWindow)).setAlwaysOnTop(true);
273
274 fsWindowListener = new D3DFSWindowAdapter();
275 realFSWindow.addWindowListener(fsWindowListener);
276 }
277
278 @Override
279 protected void removeFSWindowListener(Window w) {
280 realFSWindow.removeWindowListener(fsWindowListener);
281 fsWindowListener = null;
282
283 /**
284 * Bug 4933099: There is some funny-business to deal with when this
285 * method is called with a Window instead of a Frame. See 4836744
286 * for more information on this. One side-effect of our workaround
287 * for the problem is that the owning Frame of a Window may end
288 * up getting resized during the fullscreen process. When we
289 * return from fullscreen mode, we should resize the Frame to
290 * its original size (just like the Window is being resized
291 * to its original size in GraphicsDevice).
292 */
293 final WWindowPeer wpeer = AWTAccessor.getComponentAccessor()
294 .getPeer(realFSWindow);
295 if (wpeer != null) {
296 if (ownerOrigBounds != null) {
297 // if the window went into fs mode before it was realized it
298 // could have (0,0) dimensions
299 if (ownerOrigBounds.width == 0) ownerOrigBounds.width = 1;
300 if (ownerOrigBounds.height == 0) ownerOrigBounds.height = 1;
301 wpeer.reshape(ownerOrigBounds.x, ownerOrigBounds.y,
302 ownerOrigBounds.width, ownerOrigBounds.height);
303 if (!ownerWasVisible) {
304 wpeer.setVisible(false);
305 }
306 ownerOrigBounds = null;
307 }
308 if (!fsWindowWasAlwaysOnTop) {
309 wpeer.setAlwaysOnTop(false);
310 }
311 }
312
313 realFSWindow = null;
314 }
324 };
325 final Result res = new Result();
326 rq.flushAndInvokeNow(new Runnable() {
327 public void run() {
328 res.dm = getCurrentDisplayModeNative(screen);
329 }
330 });
331 if (res.dm == null) {
332 return super.getCurrentDisplayMode(screen);
333 }
334 return res.dm;
335 } finally {
336 rq.unlock();
337 }
338 }
339 private static native void configDisplayModeNative(int screen, long hwnd,
340 int width, int height,
341 int bitDepth,
342 int refreshRate);
343 @Override
344 protected void configDisplayMode(final int screen, final WindowPeer w,
345 final int width, final int height,
346 final int bitDepth, final int refreshRate)
347 {
348 // we entered fs mode via gdi
349 if (!fsStatus) {
350 super.configDisplayMode(screen, w, width, height, bitDepth,
351 refreshRate);
352 return;
353 }
354 final WWindowPeer wpeer = AWTAccessor.getComponentAccessor()
355 .getPeer(realFSWindow);
356
357 // REMIND: we do this before we switch the display mode, so
358 // the dimensions may be exceeding the dimensions of the screen,
359 // is this a problem?
360
361 // update the bounds of the owner frame
362 if (getFullScreenWindow() != realFSWindow) {
363 Rectangle screenBounds = getDefaultConfiguration().getBounds();
364 wpeer.reshape(screenBounds.x, screenBounds.y, width, height);
365 }
366
367 D3DRenderQueue rq = D3DRenderQueue.getInstance();
368 rq.lock();
369 try {
370 rq.flushAndInvokeNow(new Runnable() {
371 public void run() {
372 long hwnd = wpeer.getHWnd();
373 if (hwnd == 0l) {
374 // window is disposed
375 return;
|