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 AMD_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 AMDDebugOutputCallback extends PointerWrapperAbstract {
45 
46 	/** Severity levels. */
47 	private static final int GL_DEBUG_SEVERITY_HIGH_AMD = 0x9146,
48 		GL_DEBUG_SEVERITY_MEDIUM_AMD = 0x9147,
49 		GL_DEBUG_SEVERITY_LOW_AMD = 0x9148;
50 
51 	/** Categories */
52 	private static final int GL_DEBUG_CATEGORY_API_ERROR_AMD = 0x9149,
53 		GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD = 0x914A,
54 		GL_DEBUG_CATEGORY_DEPRECATION_AMD = 0x914B,
55 		GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD = 0x914C,
56 		GL_DEBUG_CATEGORY_PERFORMANCE_AMD = 0x914D,
57 		GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD = 0x914E,
58 		GL_DEBUG_CATEGORY_APPLICATION_AMD = 0x914F,
59 		GL_DEBUG_CATEGORY_OTHER_AMD = 0x9150;
60 
61 	private static final long CALLBACK_POINTER;
62 
63 	static {
64 		long pointer = 0;
65 		try {
66 			// Call reflectively so that we can compile this class for the Generator.
67 			pointer = (Long)Class.forName("org.lwjgl.opengl.CallbackUtil").getDeclaredMethod("getDebugOutputCallbackAMD").invoke(null);
68 		} catch (Exception e) {
69 			// ignore
70 		}
71 		CALLBACK_POINTER = pointer;
72 	}
73 
74 	private final Handler handler;
75 
76 	/**
77 	 * Creates an AMDDebugOutputCallback with a default callback handler.
78 	 * The default handler will simply print the message on System.err.
79 	 */
AMDDebugOutputCallback()80 	public AMDDebugOutputCallback() {
81 		this(new Handler() {
82 			public void handleMessage(final int id, final int category, final int severity, final String message) {
83 				System.err.println("[LWJGL] AMD_debug_output message");
84 				System.err.println("\tID: " + id);
85 
86 				String description;
87 				switch ( category ) {
88 					case GL_DEBUG_CATEGORY_API_ERROR_AMD:
89 						description = "API ERROR";
90 						break;
91 					case GL_DEBUG_CATEGORY_WINDOW_SYSTEM_AMD:
92 						description = "WINDOW SYSTEM";
93 						break;
94 					case GL_DEBUG_CATEGORY_DEPRECATION_AMD:
95 						description = "DEPRECATION";
96 						break;
97 					case GL_DEBUG_CATEGORY_UNDEFINED_BEHAVIOR_AMD:
98 						description = "UNDEFINED BEHAVIOR";
99 						break;
100 					case GL_DEBUG_CATEGORY_PERFORMANCE_AMD:
101 						description = "PERFORMANCE";
102 						break;
103 					case GL_DEBUG_CATEGORY_SHADER_COMPILER_AMD:
104 						description = "SHADER COMPILER";
105 						break;
106 					case GL_DEBUG_CATEGORY_APPLICATION_AMD:
107 						description = "APPLICATION";
108 						break;
109 					case GL_DEBUG_CATEGORY_OTHER_AMD:
110 						description = "OTHER";
111 						break;
112 					default:
113 						description = printUnknownToken(category);
114 				}
115 				System.err.println("\tCategory: " + description);
116 
117 				switch ( severity ) {
118 					case GL_DEBUG_SEVERITY_HIGH_AMD:
119 						description = "HIGH";
120 						break;
121 					case GL_DEBUG_SEVERITY_MEDIUM_AMD:
122 						description = "MEDIUM";
123 						break;
124 					case GL_DEBUG_SEVERITY_LOW_AMD:
125 						description = "LOW";
126 						break;
127 					default:
128 						description = printUnknownToken(severity);
129 				}
130 				System.err.println("\tSeverity: " + description);
131 
132 				System.err.println("\tMessage: " + message);
133 			}
134 
135 			private String printUnknownToken(final int token) {
136 				return "Unknown (0x" + Integer.toHexString(token).toUpperCase() + ")";
137 			}
138 		});
139 	}
140 
141 	/**
142 	 * Creates an AMDDebugOutputCallback with the specified callback handler.
143 	 * The handler's {@code handleMessage} method will be called whenever
144 	 * debug output is generated by the GL.
145 	 *
146 	 * @param handler the callback handler
147 	 */
AMDDebugOutputCallback(final Handler handler)148 	public AMDDebugOutputCallback(final Handler handler) {
149 		super(CALLBACK_POINTER);
150 
151 		this.handler = handler;
152 	}
153 
getHandler()154 	Handler getHandler() {
155 		return handler;
156 	}
157 
158 	/** Implementations of this interface can be used to receive AMD_debug_output notifications. */
159 	public interface Handler {
160 
161 		/**
162 		 * This method will be called when an AMD_debug_output message is generated.
163 		 *
164 		 * @param id       the message ID
165 		 * @param category the message category
166 		 * @param severity the message severity
167 		 * @param message  the string representation of the message.
168 		 */
handleMessage(int id, int category, int severity, String message)169 		void handleMessage(int id, int category, int severity, String message);
170 
171 	}
172 
173 }
174