1 /*
2 * Copyright (c) 2010, 2013, 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 com.sun.javafx.tk.quantum;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.List;
32 import java.util.concurrent.CountDownLatch;
33 import com.sun.javafx.PlatformUtil;
34
35 import com.sun.glass.ui.Application;
36 import com.sun.glass.ui.Window;
37 import com.sun.javafx.tk.CompletionListener;
38 import com.sun.javafx.tk.RenderJob;
39
40 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
41 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGER;
42
43 /**
44 * Manages the collection and rendering of dirty scenes. This class has
45 * methods which may be called from one of several threads, depending
46 * on the method.
47 *
48 * <ul>
49 * <li>createInstance: Called by QuantumToolkit once during initialization</li>
50 * <li>getInstance: May be called from any thread</li>
51 * <li>hasDirty: May be called from any thread</li>
52 * <li>addDirtyScene: Called only on the FX Thread</li>
53 * <li>removeDirtyScene: Called only on the FX Thread</li>
54 * <li>getRendered: May be called from any thread</li>
55 * <li>liveRepaintRenderJob: Called only on the FX Thread</li>
56 * <li>renderAll: Called only on the FX Thread</li>
57 * </ul>
58 *
59 * Assertions have been added to each method to verify whether the calling
60 * thread is the expected thread.
61 */
287
288 // Work to be done after all rendering is completed. Note that
289 // I check against "1" to indicate all rendering is done, and
290 // only decrement the allWorkCompletedLatch after wards. This is
291 // because as soon as I decrement the allWorkCompletedLatch to 0,
292 // then whatever code remains in this method will run concurrently
293 // with the FX app thread, and I'd prefer to minimize the number
294 // of things here that could be happening in parallel.
295 if (allWorkCompletedLatch.getCount() == 1) {
296 // In some cases we need to tell the toolkit that
297 // now would be a great time to vsync!
298 if (needsHint && !toolkit.hasNativeSystemVsync()) {
299 toolkit.vsyncHint();
300 }
301
302 Application.GetApplication().notifyRenderingFinished();
303
304 // If pulse logging is enabled, then we must call renderEnd now
305 // that we know that all of the scene's being rendered are finished
306 if (PULSE_LOGGING_ENABLED) {
307 PULSE_LOGGER.renderEnd();
308 }
309 }
310
311 // Count down the latch, indicating that drawing has
312 // completed for some scene.
313 allWorkCompletedLatch.countDown();
314 }
315
316 /**
317 * Run a full pulse and repaint before returning.
318 */
319 final void liveRepaintRenderJob(final ViewScene scene) {
320 ViewPainter viewPainter = scene.getPainter();
321 QuantumToolkit quantum = (QuantumToolkit)QuantumToolkit.getToolkit();
322 quantum.pulse(false);
323 final CountDownLatch latch = new CountDownLatch(1);
324 boolean locked = ViewPainter.renderLock.isHeldByCurrentThread();
325 if (locked) {
326 ViewPainter.renderLock.unlock();
327 }
363 return;
364 }
365
366 // Because hasDirty is tied to dirtyScenes, it should
367 // not be possible that we reach this point if dirtyScenes
368 // is empty (since hasDirty was true)
369 assert !dirtyScenes.isEmpty();
370
371 // Sort the dirty scenes based on whether they are
372 // synchronous or not. If they are not synchronous,
373 // then we want to process them first.
374 Collections.sort(dirtyScenes, DIRTY_SCENE_SORTER);
375
376 // Reset the fields
377 hasDirty = false;
378 needsHint = false;
379
380 // If pulse logging is enabled, then we must call renderStart
381 // BEFORE we actually call repaint on any of the dirty scenes.
382 if (PULSE_LOGGING_ENABLED) {
383 PULSE_LOGGER.renderStart();
384 }
385
386 // This part needs to be handled a bit differently depending on whether our platform has a native
387 // window manager or not.
388 // So, check to see if we do (Note: how we determine this need to be improved, this should
389 // eventually call down into platform-specific glass code and not rely on
390 // a system property, but we will use this for now)
391 if (!Application.GetApplication().hasWindowManager()) {
392 // No native window manager. We call repaint on every scene (to make sure it gets recopied
393 // to the screen) but we may be able to skip some steps in the repaint.
394
395 // Obtain a z-ordered window list from glass. For platforms without a native window manager,
396 // we need to recopy the all of the window contents to the screen on every frame.
397 final List<com.sun.glass.ui.Window> glassWindowList = com.sun.glass.ui.Window.getWindows();
398 allWorkCompletedLatch = new CountDownLatch(glassWindowList.size());
399 for (int i = 0, n = glassWindowList.size(); i < n; i++) {
400 final Window w = glassWindowList.get(i);
401 final WindowStage ws = WindowStage.findWindowStage(w);
402 if (ws != null) {
403 final ViewScene vs = ws.getViewScene();
|
1 /*
2 * Copyright (c) 2010, 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 com.sun.javafx.tk.quantum;
27
28 import java.util.ArrayList;
29 import java.util.Collections;
30 import java.util.Comparator;
31 import java.util.List;
32 import java.util.concurrent.CountDownLatch;
33 import com.sun.javafx.PlatformUtil;
34
35 import com.sun.glass.ui.Application;
36 import com.sun.glass.ui.Window;
37 import com.sun.javafx.tk.CompletionListener;
38 import com.sun.javafx.tk.RenderJob;
39
40 import static com.sun.javafx.logging.PulseLogger.PULSE_LOGGING_ENABLED;
41 import com.sun.javafx.logging.PulseLogger;
42
43 /**
44 * Manages the collection and rendering of dirty scenes. This class has
45 * methods which may be called from one of several threads, depending
46 * on the method.
47 *
48 * <ul>
49 * <li>createInstance: Called by QuantumToolkit once during initialization</li>
50 * <li>getInstance: May be called from any thread</li>
51 * <li>hasDirty: May be called from any thread</li>
52 * <li>addDirtyScene: Called only on the FX Thread</li>
53 * <li>removeDirtyScene: Called only on the FX Thread</li>
54 * <li>getRendered: May be called from any thread</li>
55 * <li>liveRepaintRenderJob: Called only on the FX Thread</li>
56 * <li>renderAll: Called only on the FX Thread</li>
57 * </ul>
58 *
59 * Assertions have been added to each method to verify whether the calling
60 * thread is the expected thread.
61 */
287
288 // Work to be done after all rendering is completed. Note that
289 // I check against "1" to indicate all rendering is done, and
290 // only decrement the allWorkCompletedLatch after wards. This is
291 // because as soon as I decrement the allWorkCompletedLatch to 0,
292 // then whatever code remains in this method will run concurrently
293 // with the FX app thread, and I'd prefer to minimize the number
294 // of things here that could be happening in parallel.
295 if (allWorkCompletedLatch.getCount() == 1) {
296 // In some cases we need to tell the toolkit that
297 // now would be a great time to vsync!
298 if (needsHint && !toolkit.hasNativeSystemVsync()) {
299 toolkit.vsyncHint();
300 }
301
302 Application.GetApplication().notifyRenderingFinished();
303
304 // If pulse logging is enabled, then we must call renderEnd now
305 // that we know that all of the scene's being rendered are finished
306 if (PULSE_LOGGING_ENABLED) {
307 PulseLogger.renderEnd();
308 }
309 }
310
311 // Count down the latch, indicating that drawing has
312 // completed for some scene.
313 allWorkCompletedLatch.countDown();
314 }
315
316 /**
317 * Run a full pulse and repaint before returning.
318 */
319 final void liveRepaintRenderJob(final ViewScene scene) {
320 ViewPainter viewPainter = scene.getPainter();
321 QuantumToolkit quantum = (QuantumToolkit)QuantumToolkit.getToolkit();
322 quantum.pulse(false);
323 final CountDownLatch latch = new CountDownLatch(1);
324 boolean locked = ViewPainter.renderLock.isHeldByCurrentThread();
325 if (locked) {
326 ViewPainter.renderLock.unlock();
327 }
363 return;
364 }
365
366 // Because hasDirty is tied to dirtyScenes, it should
367 // not be possible that we reach this point if dirtyScenes
368 // is empty (since hasDirty was true)
369 assert !dirtyScenes.isEmpty();
370
371 // Sort the dirty scenes based on whether they are
372 // synchronous or not. If they are not synchronous,
373 // then we want to process them first.
374 Collections.sort(dirtyScenes, DIRTY_SCENE_SORTER);
375
376 // Reset the fields
377 hasDirty = false;
378 needsHint = false;
379
380 // If pulse logging is enabled, then we must call renderStart
381 // BEFORE we actually call repaint on any of the dirty scenes.
382 if (PULSE_LOGGING_ENABLED) {
383 PulseLogger.renderStart();
384 }
385
386 // This part needs to be handled a bit differently depending on whether our platform has a native
387 // window manager or not.
388 // So, check to see if we do (Note: how we determine this need to be improved, this should
389 // eventually call down into platform-specific glass code and not rely on
390 // a system property, but we will use this for now)
391 if (!Application.GetApplication().hasWindowManager()) {
392 // No native window manager. We call repaint on every scene (to make sure it gets recopied
393 // to the screen) but we may be able to skip some steps in the repaint.
394
395 // Obtain a z-ordered window list from glass. For platforms without a native window manager,
396 // we need to recopy the all of the window contents to the screen on every frame.
397 final List<com.sun.glass.ui.Window> glassWindowList = com.sun.glass.ui.Window.getWindows();
398 allWorkCompletedLatch = new CountDownLatch(glassWindowList.size());
399 for (int i = 0, n = glassWindowList.size(); i < n; i++) {
400 final Window w = glassWindowList.get(i);
401 final WindowStage ws = WindowStage.findWindowStage(w);
402 if (ws != null) {
403 final ViewScene vs = ws.getViewScene();
|