Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/java2d/opengl/OGLRenderQueue.java
38918 views
/*1* Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.java2d.opengl;2627import sun.misc.ThreadGroupUtils;28import sun.java2d.pipe.RenderBuffer;29import sun.java2d.pipe.RenderQueue;30import static sun.java2d.pipe.BufferedOpCodes.*;31import java.security.AccessController;32import java.security.PrivilegedAction;3334/**35* OGL-specific implementation of RenderQueue. This class provides a36* single (daemon) thread that is responsible for periodically flushing37* the queue, thus ensuring that only one thread communicates with the native38* OpenGL libraries for the entire process.39*/40public class OGLRenderQueue extends RenderQueue {4142private static OGLRenderQueue theInstance;43private final QueueFlusher flusher;4445private OGLRenderQueue() {46/*47* The thread must be a member of a thread group48* which will not get GCed before VM exit.49*/50flusher = AccessController.doPrivileged((PrivilegedAction<QueueFlusher>) () -> {51return new QueueFlusher(ThreadGroupUtils.getRootThreadGroup());52});53}5455/**56* Returns the single OGLRenderQueue instance. If it has not yet been57* initialized, this method will first construct the single instance58* before returning it.59*/60public static synchronized OGLRenderQueue getInstance() {61if (theInstance == null) {62theInstance = new OGLRenderQueue();63}64return theInstance;65}6667/**68* Flushes the single OGLRenderQueue instance synchronously. If an69* OGLRenderQueue has not yet been instantiated, this method is a no-op.70* This method is useful in the case of Toolkit.sync(), in which we want71* to flush the OGL pipeline, but only if the OGL pipeline is currently72* enabled. Since this class has few external dependencies, callers need73* not be concerned that calling this method will trigger initialization74* of the OGL pipeline and related classes.75*/76public static void sync() {77if (theInstance != null) {78theInstance.lock();79try {80theInstance.ensureCapacity(4);81theInstance.getBuffer().putInt(SYNC);82theInstance.flushNow();83} finally {84theInstance.unlock();85}86}87}8889/**90* Disposes the native memory associated with the given native91* graphics config info pointer on the single queue flushing thread.92*/93public static void disposeGraphicsConfig(long pConfigInfo) {94OGLRenderQueue rq = getInstance();95rq.lock();96try {97// make sure we make the context associated with the given98// GraphicsConfig current before disposing the native resources99OGLContext.setScratchSurface(pConfigInfo);100101RenderBuffer buf = rq.getBuffer();102rq.ensureCapacityAndAlignment(12, 4);103buf.putInt(DISPOSE_CONFIG);104buf.putLong(pConfigInfo);105106// this call is expected to complete synchronously, so flush now107rq.flushNow();108} finally {109rq.unlock();110}111}112113/**114* Returns true if the current thread is the OGL QueueFlusher thread.115*/116public static boolean isQueueFlusherThread() {117return (Thread.currentThread() == getInstance().flusher);118}119120public void flushNow() {121// assert lock.isHeldByCurrentThread();122try {123flusher.flushNow();124} catch (Exception e) {125System.err.println("exception in flushNow:");126e.printStackTrace();127}128}129130public void flushAndInvokeNow(Runnable r) {131// assert lock.isHeldByCurrentThread();132try {133flusher.flushAndInvokeNow(r);134} catch (Exception e) {135System.err.println("exception in flushAndInvokeNow:");136e.printStackTrace();137}138}139140private native void flushBuffer(long buf, int limit);141142private void flushBuffer() {143// assert lock.isHeldByCurrentThread();144int limit = buf.position();145if (limit > 0) {146// process the queue147flushBuffer(buf.getAddress(), limit);148}149// reset the buffer position150buf.clear();151// clear the set of references, since we no longer need them152refSet.clear();153}154155private class QueueFlusher extends Thread {156private boolean needsFlush;157private Runnable task;158private Error error;159160public QueueFlusher(ThreadGroup threadGroup) {161super(threadGroup, "Java2D Queue Flusher");162setDaemon(true);163setPriority(Thread.MAX_PRIORITY);164start();165}166167public synchronized void flushNow() {168// wake up the flusher169needsFlush = true;170notify();171172// wait for flush to complete173while (needsFlush) {174try {175wait();176} catch (InterruptedException e) {177}178}179180// re-throw any error that may have occurred during the flush181if (error != null) {182throw error;183}184}185186public synchronized void flushAndInvokeNow(Runnable task) {187this.task = task;188flushNow();189}190191public synchronized void run() {192boolean timedOut = false;193while (true) {194while (!needsFlush) {195try {196timedOut = false;197/*198* Wait until we're woken up with a flushNow() call,199* or the timeout period elapses (so that we can200* flush the queue periodically).201*/202wait(100);203/*204* We will automatically flush the queue if the205* following conditions apply:206* - the wait() timed out207* - we can lock the queue (without blocking)208* - there is something in the queue to flush209* Otherwise, just continue (we'll flush eventually).210*/211if (!needsFlush && (timedOut = tryLock())) {212if (buf.position() > 0) {213needsFlush = true;214} else {215unlock();216}217}218} catch (InterruptedException e) {219}220}221try {222// reset the throwable state223error = null;224// flush the buffer now225flushBuffer();226// if there's a task, invoke that now as well227if (task != null) {228task.run();229}230} catch (Error e) {231error = e;232} catch (Exception x) {233System.err.println("exception in QueueFlusher:");234x.printStackTrace();235} finally {236if (timedOut) {237unlock();238}239task = null;240// allow the waiting thread to continue241needsFlush = false;242notify();243}244}245}246}247}248249250