32 import java.awt.Graphics2D;
33 import java.awt.Rectangle;
34 import java.awt.Window;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39
40 import sun.awt.AWTAccessor;
41 import sun.awt.AWTAccessor.ComponentAccessor;
42 import sun.awt.util.ThreadGroupUtils;
43 import sun.awt.Win32GraphicsConfig;
44 import sun.awt.windows.WComponentPeer;
45 import sun.java2d.InvalidPipeException;
46 import sun.java2d.ScreenUpdateManager;
47 import sun.java2d.SunGraphics2D;
48 import sun.java2d.SurfaceData;
49 import sun.java2d.windows.GDIWindowSurfaceData;
50 import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
51 import sun.java2d.windows.WindowsFlags;
52 import sun.misc.ManagedLocalsThread;
53
54 /**
55 * This class handles rendering to the screen with the D3D pipeline.
56 *
57 * Since it is not possible to render directly to the front buffer
58 * with D3D9, we create a swap chain surface (with COPY effect) in place of the
59 * GDIWindowSurfaceData. A background thread handles the swap chain flips.
60 *
61 * There are some restrictions to which windows we would use this for.
62 * @see #createScreenSurface
63 */
64 public class D3DScreenUpdateManager extends ScreenUpdateManager
65 implements Runnable
66 {
67 /**
68 * A window must be at least MIN_WIN_SIZE in one or both dimensions
69 * to be considered for the update manager.
70 */
71 private static final int MIN_WIN_SIZE = 150;
72
82 * List of D3DWindowSurfaceData surfaces. Surfaces are added to the
83 * list when a graphics object is created, and removed when the surface
84 * is invalidated.
85 */
86 private ArrayList<D3DWindowSurfaceData> d3dwSurfaces;
87 /**
88 * Cache of GDIWindowSurfaceData surfaces corresponding to the
89 * D3DWindowSurfaceData surfaces. Surfaces are added to the list when
90 * a d3dw surface is lost and could not be restored (due to lack of vram,
91 * for example), and removed then the d3dw surface is invalidated.
92 */
93 private HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData> gdiSurfaces;
94
95 public D3DScreenUpdateManager() {
96 done = false;
97 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
98 Runnable shutdownRunnable = () -> {
99 done = true;
100 wakeUpUpdateThread();
101 };
102 Thread shutdown = new ManagedLocalsThread(
103 ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable);
104 shutdown.setContextClassLoader(null);
105 try {
106 Runtime.getRuntime().addShutdownHook(shutdown);
107 } catch (Exception e) {
108 done = true;
109 }
110 return null;
111 });
112 }
113
114 /**
115 * If possible, creates a D3DWindowSurfaceData (which is actually
116 * a back-buffer surface). If the creation fails, returns GDI
117 * onscreen surface instead.
118 *
119 * Note that the created D3D surface does not initialize the native
120 * resources (and is marked lost) to avoid wasting video memory. It is
121 * restored when a graphics object is requested from the peer.
122 *
123 * Note that this method is called from a synchronized block in
331 * @param d3dw surface for which associated gdi surface is to be removed
332 */
333 private void removeGdiSurface(final D3DWindowSurfaceData d3dw) {
334 if (gdiSurfaces != null) {
335 GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
336 if (gdisd != null) {
337 gdisd.invalidate();
338 gdiSurfaces.remove(d3dw);
339 }
340 }
341 }
342
343 /**
344 * If the update thread hasn't yet been created, it will be;
345 * otherwise it is awaken
346 */
347 private synchronized void startUpdateThread() {
348 if (screenUpdater == null) {
349 screenUpdater = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
350 String name = "D3D Screen Updater";
351 Thread t = new ManagedLocalsThread(
352 ThreadGroupUtils.getRootThreadGroup(), this, name);
353 // REMIND: should it be higher?
354 t.setPriority(Thread.NORM_PRIORITY + 2);
355 t.setDaemon(true);
356 return t;
357 });
358 screenUpdater.start();
359 } else {
360 wakeUpUpdateThread();
361 }
362 }
363
364 /**
365 * Wakes up the screen updater thread.
366 *
367 * This method is not synchronous, it doesn't wait
368 * for the updater thread to complete the updates.
369 *
370 * It should be used when it is not necessary to wait for the
371 * completion, for example, when a new surface had been added
372 * to the list of tracked surfaces (which means that it's about
|
32 import java.awt.Graphics2D;
33 import java.awt.Rectangle;
34 import java.awt.Window;
35 import java.security.AccessController;
36 import java.security.PrivilegedAction;
37 import java.util.ArrayList;
38 import java.util.HashMap;
39
40 import sun.awt.AWTAccessor;
41 import sun.awt.AWTAccessor.ComponentAccessor;
42 import sun.awt.util.ThreadGroupUtils;
43 import sun.awt.Win32GraphicsConfig;
44 import sun.awt.windows.WComponentPeer;
45 import sun.java2d.InvalidPipeException;
46 import sun.java2d.ScreenUpdateManager;
47 import sun.java2d.SunGraphics2D;
48 import sun.java2d.SurfaceData;
49 import sun.java2d.windows.GDIWindowSurfaceData;
50 import sun.java2d.d3d.D3DSurfaceData.D3DWindowSurfaceData;
51 import sun.java2d.windows.WindowsFlags;
52
53 /**
54 * This class handles rendering to the screen with the D3D pipeline.
55 *
56 * Since it is not possible to render directly to the front buffer
57 * with D3D9, we create a swap chain surface (with COPY effect) in place of the
58 * GDIWindowSurfaceData. A background thread handles the swap chain flips.
59 *
60 * There are some restrictions to which windows we would use this for.
61 * @see #createScreenSurface
62 */
63 public class D3DScreenUpdateManager extends ScreenUpdateManager
64 implements Runnable
65 {
66 /**
67 * A window must be at least MIN_WIN_SIZE in one or both dimensions
68 * to be considered for the update manager.
69 */
70 private static final int MIN_WIN_SIZE = 150;
71
81 * List of D3DWindowSurfaceData surfaces. Surfaces are added to the
82 * list when a graphics object is created, and removed when the surface
83 * is invalidated.
84 */
85 private ArrayList<D3DWindowSurfaceData> d3dwSurfaces;
86 /**
87 * Cache of GDIWindowSurfaceData surfaces corresponding to the
88 * D3DWindowSurfaceData surfaces. Surfaces are added to the list when
89 * a d3dw surface is lost and could not be restored (due to lack of vram,
90 * for example), and removed then the d3dw surface is invalidated.
91 */
92 private HashMap<D3DWindowSurfaceData, GDIWindowSurfaceData> gdiSurfaces;
93
94 public D3DScreenUpdateManager() {
95 done = false;
96 AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
97 Runnable shutdownRunnable = () -> {
98 done = true;
99 wakeUpUpdateThread();
100 };
101 Thread shutdown = new Thread(
102 ThreadGroupUtils.getRootThreadGroup(), shutdownRunnable,
103 "ScreenUpdater", 0, false);
104 shutdown.setContextClassLoader(null);
105 try {
106 Runtime.getRuntime().addShutdownHook(shutdown);
107 } catch (Exception e) {
108 done = true;
109 }
110 return null;
111 });
112 }
113
114 /**
115 * If possible, creates a D3DWindowSurfaceData (which is actually
116 * a back-buffer surface). If the creation fails, returns GDI
117 * onscreen surface instead.
118 *
119 * Note that the created D3D surface does not initialize the native
120 * resources (and is marked lost) to avoid wasting video memory. It is
121 * restored when a graphics object is requested from the peer.
122 *
123 * Note that this method is called from a synchronized block in
331 * @param d3dw surface for which associated gdi surface is to be removed
332 */
333 private void removeGdiSurface(final D3DWindowSurfaceData d3dw) {
334 if (gdiSurfaces != null) {
335 GDIWindowSurfaceData gdisd = gdiSurfaces.get(d3dw);
336 if (gdisd != null) {
337 gdisd.invalidate();
338 gdiSurfaces.remove(d3dw);
339 }
340 }
341 }
342
343 /**
344 * If the update thread hasn't yet been created, it will be;
345 * otherwise it is awaken
346 */
347 private synchronized void startUpdateThread() {
348 if (screenUpdater == null) {
349 screenUpdater = AccessController.doPrivileged((PrivilegedAction<Thread>) () -> {
350 String name = "D3D Screen Updater";
351 Thread t = new Thread(
352 ThreadGroupUtils.getRootThreadGroup(), this, name,
353 0, false);
354 // REMIND: should it be higher?
355 t.setPriority(Thread.NORM_PRIORITY + 2);
356 t.setDaemon(true);
357 return t;
358 });
359 screenUpdater.start();
360 } else {
361 wakeUpUpdateThread();
362 }
363 }
364
365 /**
366 * Wakes up the screen updater thread.
367 *
368 * This method is not synchronous, it doesn't wait
369 * for the updater thread to complete the updates.
370 *
371 * It should be used when it is not necessary to wait for the
372 * completion, for example, when a new surface had been added
373 * to the list of tracked surfaces (which means that it's about
|