1 /*
2  * Copyright (c) 2002-2010 LWJGL Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  *   notice, this list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright
13  *   notice, this list of conditions and the following disclaimer in the
14  *   documentation and/or other materials provided with the distribution.
15  *
16  * * Neither the name of 'LWJGL' nor the names of
17  *   its contributors may be used to endorse or promote products derived
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 package org.lwjgl.opengl;
33 
34 import java.util.HashMap;
35 import java.util.Map;
36 
37 /**
38  * Utility class that handles OpenGL API callbacks.
39  *
40  * @author Spasi
41  */
42 final class CallbackUtil {
43 
44 	/** Context -> Long */
45 	private static final Map<ContextCapabilities, Long> contextUserParamsARB = new HashMap<ContextCapabilities, Long>();
46 	/** Context -> Long */
47 	private static final Map<ContextCapabilities, Long> contextUserParamsAMD = new HashMap<ContextCapabilities, Long>();
48 	/** Context -> Long */
49 	private static final Map<ContextCapabilities, Long> contextUserParamsKHR = new HashMap<ContextCapabilities, Long>();
50 
CallbackUtil()51 	private CallbackUtil() {}
52 
53 	/**
54 	 * Creates a new global reference to the specified Object.
55 	 *
56 	 * @param obj the Object
57 	 *
58 	 * @return the GlobalRef memory address or 0 if the Object is null.
59 	 */
createGlobalRef(final Object obj)60 	static long createGlobalRef(final Object obj) {
61 		return obj == null ? 0 : ncreateGlobalRef(obj);
62 	}
63 
64 	/**
65 	 * Creates a new global reference to the specified Object.
66 	 *
67 	 * @param obj the Object
68 	 *
69 	 * @return the GlobalRef memory address.
70 	 */
ncreateGlobalRef(Object obj)71 	private static native long ncreateGlobalRef(Object obj);
72 
73 	/**
74 	 * Deletes a global reference.
75 	 *
76 	 * @param ref the GlobalRef memory address.
77 	 */
deleteGlobalRef(long ref)78 	private static native void deleteGlobalRef(long ref);
79 
80 	// --------- [ XXX_debug_output ] ---------
81 
82 	/**
83 	 * Associates the current OpenGL context with the specified global reference. If there
84 	 * is no context current, the global reference is deleted and an exception is thrown.
85 	 * Any previous callback registrations will be cleared.
86 	 *
87 	 * @param userParam the global reference pointer
88 	 */
registerContextCallback(final long userParam, final Map<ContextCapabilities, Long> contextUserData)89 	private static void registerContextCallback(final long userParam, final Map<ContextCapabilities, Long> contextUserData) {
90 		ContextCapabilities caps = GLContext.getCapabilities();
91 		if ( caps == null ) {
92 			deleteGlobalRef(userParam);
93 			throw new IllegalStateException("No context is current.");
94 		}
95 
96 		final Long userParam_old = contextUserData.remove(caps);
97 		if ( userParam_old != null )
98 			deleteGlobalRef(userParam_old);
99 
100 		if ( userParam != 0 )
101 			contextUserData.put(caps, userParam);
102 	}
103 
104 	/**
105 	 * Releases references to any callbacks associated with the specified GL context.
106 	 *
107 	 * @param context the Context to unregister
108 	 */
unregisterCallbacks(final Object context)109 	static void unregisterCallbacks(final Object context) {
110 		// TODO: This is never called for custom contexts. Need to fix for LWJGL 3.0
111 		final ContextCapabilities caps = GLContext.getCapabilities(context);
112 
113 		Long userParam = contextUserParamsARB.remove(caps);
114 		if ( userParam != null )
115 			deleteGlobalRef(userParam);
116 
117 		userParam = contextUserParamsAMD.remove(caps);
118 		if ( userParam != null )
119 			deleteGlobalRef(userParam);
120 
121 		userParam = contextUserParamsKHR.remove(caps);
122 		if ( userParam != null )
123 			deleteGlobalRef(userParam);
124 	}
125 
126 	// --------- [ ARB_debug_output ] ---------
127 
128 	/**
129 	 * Returns the memory address of the native function we pass to glDebugMessageCallbackARB.
130 	 *
131 	 * @return the callback function address
132 	 */
getDebugOutputCallbackARB()133 	static native long getDebugOutputCallbackARB();
134 
135 	/**
136 	 * Associates the current OpenGL context with the specified global reference. If there
137 	 * is no context current, the global reference is deleted and an exception is thrown.
138 	 * Any previous callback registrations will be cleared.
139 	 *
140 	 * @param userParam the global reference pointer
141 	 */
registerContextCallbackARB(final long userParam)142 	static void registerContextCallbackARB(final long userParam) {
143 		registerContextCallback(userParam, contextUserParamsARB);
144 	}
145 
146 	// --------- [ AMD_debug_output ] ---------
147 
148 	/**
149 	 * Returns the memory address of the native function we pass to glDebugMessageCallbackAMD.
150 	 *
151 	 * @return the callback function address
152 	 */
getDebugOutputCallbackAMD()153 	static native long getDebugOutputCallbackAMD();
154 
155 	/**
156 	 * Associates the current OpenGL context with the specified global reference. If there
157 	 * is no context current, the global reference is deleted and an exception is thrown.
158 	 * Any previous callback registrations will be cleared.
159 	 *
160 	 * @param userParam the global reference pointer
161 	 */
registerContextCallbackAMD(final long userParam)162 	static void registerContextCallbackAMD(final long userParam) {
163 		registerContextCallback(userParam, contextUserParamsAMD);
164 	}
165 
166 	// --------- [ KHR_debug ] ---------
167 
168 	/**
169 	 * Returns the memory address of the native function we pass to glDebugMessageCallback.
170 	 *
171 	 * @return the callback function address
172 	 */
getDebugCallbackKHR()173 	static native long getDebugCallbackKHR();
174 
175 	/**
176 	 * Associates the current OpenGL context with the specified global reference. If there
177 	 * is no context current, the global reference is deleted and an exception is thrown.
178 	 * Any previous callback registrations will be cleared.
179 	 *
180 	 * @param userParam the global reference pointer
181 	 */
registerContextCallbackKHR(final long userParam)182 	static void registerContextCallbackKHR(final long userParam) {
183 		registerContextCallback(userParam, contextUserParamsKHR);
184 	}
185 
186 }