summaryrefslogtreecommitdiffstats
path: root/examples/org.eclipse.swt.opengl.examples/src/org/eclipse/swt/opengl/examples/OpenGLTab.java
blob: d8523b9e0c6718d558ee10da664c1825ed574bf9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.opengl.examples;


import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.opengl.*;

/**
 * <code>OpenGLTab</code> is the abstract superclass of every page
 * in the example's tab folder.  Each page in the tab folder
 * displays a different example.
 *
 * An OpenGLTab itself is not a control but instead provides a hierarchy
 * with which to share code that is common to every page in the folder.
 */
abstract class OpenGLTab {
	private Canvas glCanvas;
	private Composite tabFolderPage;
	private GLContext context;
	private boolean stencilSupport;
	private final static int DEFAULT_SLEEP_LENGTH = 100;

	/**
	 * Creates this tab's controls.  Subclasses must override.
	 *
	 * @param composite the parent composite
	 */
	abstract void createControls(Composite composite);

	/**
	 * Creates the OpenGL canvas on which all drawing is done.
	 */
	void createOpenGLContext() {
		context = new GLContext(glCanvas);
		setCurrent();
		setupViewingArea();
	}

	/**
	 * Creates the tab folder page.
	 *
	 * @param tabFolder the parent tab folder
	 * @return the new page
	 */
	Composite createTabFolderPage(TabFolder tabFolder) {
		tabFolderPage = new Composite(tabFolder, SWT.NONE);
		tabFolderPage.setLayout(new GridLayout(2, false));

		GridData gridData = new GridData();
		gridData.heightHint = 400;
		gridData.widthHint = 400;
		gridData.verticalAlignment = GridData.BEGINNING;
		glCanvas = new Canvas(tabFolderPage, SWT.NONE);
		glCanvas.setLayout(new GridLayout());
		glCanvas.setLayoutData(gridData);
		glCanvas.setSize(400, 400);		// needed for windows

		gridData = new GridData();
		gridData.verticalAlignment = GridData.BEGINNING;
		Composite controlComposite = new Composite(tabFolderPage, SWT.NONE);
		controlComposite.setLayout(new GridLayout());
		controlComposite.setLayoutData(gridData);

		// create the OpenGL Screen and controls
		createOpenGLContext();

		// determine if native stencil support is available
		int[] param = new int[1];
		GL.glGetIntegerv(GL.GL_STENCIL_BITS, param);
		stencilSupport = param[0] != 0;

		init();

		if (!isStencilSupportNeeded() || hasStencilSupport()) {
			createControls(controlComposite);
		} else {
			Label label = new Label(controlComposite, SWT.NONE);
			label.setText("This tab requires native stencil support.");
		}

		return tabFolderPage;
	}

	/**
	 * Disposes all resources allocated by this tab.
	 */
	void dispose() {
		context.dispose();
	}

	/**
	 * Returns the context for this tab.
	 * 
	 * @return GLContext
	 */
	GLContext getContext() {
		return context;
	}

	/**
	 * Returns the glCanvas for this tab.
	 * 
	 * @return Canvas
	 */
	Canvas getGlCanvas() {
		return glCanvas;
	}

	/**
	 * Returns the length of time in milliseconds that the example
	 * should sleep between animation redraws.  As this length
	 * increases, user responsiveness increases and the frequency of
	 * animation redraws decreases.  Subclasses with moving animations
	 * may wish to override this default implementation to return a
	 * smaller value if their animations do not occur frequently enough. 
	 *
	 * @return the length of time in milliseconds to sleep between redraws
	 */
	int getSleepLength() {
		return DEFAULT_SLEEP_LENGTH;	
	}

	/**
	 * Returns the text for this tab.  Subclasses must override.
	 *
	 * @return the text for the tab item
	 */
	abstract String getTabText();

	/**
	 * Returns whether this machine has native stencils support.
	 * 
	 * @return boolean
	 */
	boolean hasStencilSupport() {
		return stencilSupport;
	}

	/**
	 * Initialize OpenGL resources for this tab.  Subclasses must override.
	 */
	abstract void init();

	/**
	 * Loads a texture.
	 * 
	 * @param context
	 * @param fileName
	 * @param index
	 * @param texture[]
	 */
	static void loadTexture(GLContext context, String fileName, int index, int[] texture) {
		GL.glBindTexture(GL.GL_TEXTURE_2D, texture[index]);
		ImageData source =
			new ImageData(OpenGLTab.class.getResourceAsStream(fileName));
		Image image = new Image(Display.getCurrent(), source);
		Image newImage = new Image(Display.getCurrent(), 256, 256);
		GC gc = new GC(newImage);
		gc.drawImage(image, 0, 0, source.width, source.height, 0, 0, 256, 256);
		source = newImage.getImageData();
		gc.dispose();
		source = context.convertImageData(source);
		newImage.dispose();
		image.dispose();
		GL.glTexImage2D(
			GL.GL_TEXTURE_2D, 0, 3, 
			source.width, source.height, 0,
			GL.GL_RGB, GL.GL_UNSIGNED_BYTE, source.data);
		GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
		GL.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
	}

	/**
	 * Renders this tab.
	 */
	void render() {
		if (!isStencilSupportNeeded() || hasStencilSupport()) {
			renderScene();
		} else {
			GL.glClear(GL.GL_COLOR_BUFFER_BIT);
		}
	}

	/**
	 * Renders the scene for this tab.  Subclasses must override.
	 */
	abstract void renderScene();

	/**
	 * Returns whether this tab requires stencil support in order to display
	 * properly. Subclasses may wish to override this method.
	 * 
	 * @return boolean
	 */
	boolean isStencilSupportNeeded() {
		return false;
	}

	/**
	 * Sets this rendering context to be current.
	 */
	void setCurrent() {
		context.setCurrent();
	}
	
	/**
	 * Sets up the viewing area for the OpenGL screen.  The default
	 * behavior is to use a perspective view, but there also exist frustrum
	 * and ortho views.  Subclasses may wish to override this method.
	 */
	void setupViewingArea() {
		Rectangle rect = glCanvas.getClientArea();
		int width = rect.width;
		int height = rect.height;
		height = Math.max(height, 1);
		GL.glViewport(0, 0, width, height);
		GL.glMatrixMode(GL.GL_PROJECTION);	// select the projection matrix
		GL.glLoadIdentity();				// reset the projection matrix
		float fAspect = (float) width / (float) height;
		GLU.gluPerspective(45.0f, fAspect, 0.5f, 400.0f);
		GL.glMatrixMode(GL.GL_MODELVIEW);	// select the modelview matrix
		GL.glLoadIdentity();
	}

	/**
	 * Swaps the buffers.
	 */
	void swap() {
		context.swapBuffers();
	}
}