1 /*
2  * Copyright (c) 2002-2008 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 org.lwjgl.PointerWrapperAbstract;
35 
36 /**
37  * Instances of this class are needed to use the callback functionality of the ARB_debug_output extension.
38  * A debug context must be current before creating instances of this class. Users of this class may provide
39  * implementations of the {@code Handler} interface to receive notifications. The same {@code Handler}
40  * instance may be used by different contexts but it is not recommended. Handler notifications are synchronized.
41  *
42  * @author Spasi
43  */
44 public final class ARBDebugOutputCallback extends PointerWrapperAbstract {
45 
46 	/** Severity levels. */
47 	private static final int
48 		GL_DEBUG_SEVERITY_HIGH_ARB = 0x9146,
49 		GL_DEBUG_SEVERITY_MEDIUM_ARB = 0x9147,
50 		GL_DEBUG_SEVERITY_LOW_ARB = 0x9148;
51 
52 	/** Sources. */
53 	private static final int
54 		GL_DEBUG_SOURCE_API_ARB = 0x8246,
55 		GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB = 0x8247,
56 		GL_DEBUG_SOURCE_SHADER_COMPILER_ARB = 0x8248,
57 		GL_DEBUG_SOURCE_THIRD_PARTY_ARB = 0x8249,
58 		GL_DEBUG_SOURCE_APPLICATION_ARB = 0x824A,
59 		GL_DEBUG_SOURCE_OTHER_ARB = 0x824B;
60 
61 	/** Types. */
62 	private static final int
63 		GL_DEBUG_TYPE_ERROR_ARB = 0x824C,
64 		GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB = 0x824D,
65 		GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB = 0x824E,
66 		GL_DEBUG_TYPE_PORTABILITY_ARB = 0x824F,
67 		GL_DEBUG_TYPE_PERFORMANCE_ARB = 0x8250,
68 		GL_DEBUG_TYPE_OTHER_ARB = 0x8251;
69 
70 	private static final long CALLBACK_POINTER;
71 
72 	static {
73 		long pointer = 0;
74 		try {
75 			// Call reflectively so that we can compile this class for the Generator.
76 			pointer = (Long)Class.forName("org.lwjgl.opengl.CallbackUtil").getDeclaredMethod("getDebugOutputCallbackARB").invoke(null);
77 		} catch (Exception e) {
78 			// ignore
79 		}
80 		CALLBACK_POINTER = pointer;
81 	}
82 
83 	private final Handler handler;
84 
85 	/**
86 	 * Creates an ARBDebugOutputCallback with a default callback handler.
87 	 * The default handler will simply print the message on System.err.
88 	 */
ARBDebugOutputCallback()89 	public ARBDebugOutputCallback() {
90 		this(new Handler() {
91 			public void handleMessage(final int source, final int type, final int id, final int severity, final String message) {
92 				System.err.println("[LWJGL] ARB_debug_output message");
93 				System.err.println("\tID: " + id);
94 
95 				String description;
96 				switch ( source ) {
97 					case GL_DEBUG_SOURCE_API_ARB:
98 						description = "API";
99 						break;
100 					case GL_DEBUG_SOURCE_WINDOW_SYSTEM_ARB:
101 						description = "WINDOW SYSTEM";
102 						break;
103 					case GL_DEBUG_SOURCE_SHADER_COMPILER_ARB:
104 						description = "SHADER COMPILER";
105 						break;
106 					case GL_DEBUG_SOURCE_THIRD_PARTY_ARB:
107 						description = "THIRD PARTY";
108 						break;
109 					case GL_DEBUG_SOURCE_APPLICATION_ARB:
110 						description = "APPLICATION";
111 						break;
112 					case GL_DEBUG_SOURCE_OTHER_ARB:
113 						description = "OTHER";
114 						break;
115 					default:
116 						description = printUnknownToken(source);
117 				}
118 				System.err.println("\tSource: " + description);
119 
120 				switch ( type ) {
121 					case GL_DEBUG_TYPE_ERROR_ARB:
122 						description = "ERROR";
123 						break;
124 					case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB:
125 						description = "DEPRECATED BEHAVIOR";
126 						break;
127 					case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_ARB:
128 						description = "UNDEFINED BEHAVIOR";
129 						break;
130 					case GL_DEBUG_TYPE_PORTABILITY_ARB:
131 						description = "PORTABILITY";
132 						break;
133 					case GL_DEBUG_TYPE_PERFORMANCE_ARB:
134 						description = "PERFORMANCE";
135 						break;
136 					case GL_DEBUG_TYPE_OTHER_ARB:
137 						description = "OTHER";
138 						break;
139 					default:
140 						description = printUnknownToken(type);
141 				}
142 				System.err.println("\tType: " + description);
143 
144 				switch ( severity ) {
145 					case GL_DEBUG_SEVERITY_HIGH_ARB:
146 						description = "HIGH";
147 						break;
148 					case GL_DEBUG_SEVERITY_MEDIUM_ARB:
149 						description = "MEDIUM";
150 						break;
151 					case GL_DEBUG_SEVERITY_LOW_ARB:
152 						description = "LOW";
153 						break;
154 					default:
155 						description = printUnknownToken(severity);
156 				}
157 				System.err.println("\tSeverity: " + description);
158 
159 				System.err.println("\tMessage: " + message);
160 			}
161 
162 			private  String printUnknownToken(final int token) {
163 				return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
164 			}
165 		});
166 	}
167 
168 	/**
169 	 * Creates an ARBDebugOutputCallback with the specified callback handler.
170 	 * The handler's {@code handleMessage} method will be called whenever
171 	 * debug output is generated by the GL.
172 	 *
173 	 * @param handler the callback handler
174 	 */
ARBDebugOutputCallback(final Handler handler)175 	public ARBDebugOutputCallback(final Handler handler) {
176 		super(CALLBACK_POINTER);
177 
178 		this.handler = handler;
179 	}
180 
getHandler()181 	Handler getHandler() {
182 		return handler;
183 	}
184 
185 	/** Implementations of this interface can be used to receive ARB_debug_output notifications. */
186 	public interface Handler {
187 
188 		/**
189 		 * This method will be called when an ARB_debug_output message is generated.
190 		 *
191 		 * @param source   the message source
192 		 * @param type     the message type
193 		 * @param id       the message ID
194 		 * @param severity the message severity
195 		 * @param message  the string representation of the message.
196 		 */
handleMessage(int source, int type, int id, int severity, String message)197 		void handleMessage(int source, int type, int id, int severity, String message);
198 
199 	}
200 
201 }