1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
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 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   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
33package com.jme3.system.lwjgl;
34
35import com.jme3.input.lwjgl.JInputJoyInput;
36import com.jme3.input.lwjgl.LwjglKeyInput;
37import com.jme3.input.lwjgl.LwjglMouseInput;
38import com.jme3.renderer.Renderer;
39import com.jme3.renderer.lwjgl.LwjglGL1Renderer;
40import com.jme3.renderer.lwjgl.LwjglRenderer;
41import com.jme3.system.AppSettings;
42import com.jme3.system.JmeContext;
43import com.jme3.system.SystemListener;
44import com.jme3.system.Timer;
45import java.util.concurrent.atomic.AtomicBoolean;
46import java.util.logging.Level;
47import java.util.logging.Logger;
48import org.lwjgl.opengl.*;
49
50/**
51 * A LWJGL implementation of a graphics context.
52 */
53public abstract class LwjglContext implements JmeContext {
54
55    private static final Logger logger = Logger.getLogger(LwjglContext.class.getName());
56
57    protected AtomicBoolean created = new AtomicBoolean(false);
58    protected AtomicBoolean renderable = new AtomicBoolean(false);
59    protected final Object createdLock = new Object();
60
61    protected AppSettings settings = new AppSettings(true);
62    protected Renderer renderer;
63    protected LwjglKeyInput keyInput;
64    protected LwjglMouseInput mouseInput;
65    protected JInputJoyInput joyInput;
66    protected Timer timer;
67    protected SystemListener listener;
68
69    public void setSystemListener(SystemListener listener){
70        this.listener = listener;
71    }
72
73    protected void printContextInitInfo(){
74        logger.log(Level.FINE, "Running on thread: {0}", Thread.currentThread().getName());
75
76        logger.log(Level.INFO, "Adapter: {0}", Display.getAdapter());
77        logger.log(Level.INFO, "Driver Version: {0}", Display.getVersion());
78
79        String vendor = GL11.glGetString(GL11.GL_VENDOR);
80        logger.log(Level.INFO, "Vendor: {0}", vendor);
81
82        String version = GL11.glGetString(GL11.GL_VERSION);
83        logger.log(Level.INFO, "OpenGL Version: {0}", version);
84
85        String renderGl = GL11.glGetString(GL11.GL_RENDERER);
86        logger.log(Level.INFO, "Renderer: {0}", renderGl);
87
88        if (GLContext.getCapabilities().OpenGL20){
89            String shadingLang = GL11.glGetString(GL20.GL_SHADING_LANGUAGE_VERSION);
90            logger.log(Level.INFO, "GLSL Ver: {0}", shadingLang);
91        }
92    }
93
94    protected ContextAttribs createContextAttribs(){
95        if (settings.getBoolean("GraphicsDebug") || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
96            ContextAttribs attr;
97            if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
98                attr = new ContextAttribs(3, 3);
99                attr = attr.withProfileCore(true).withForwardCompatible(true).withProfileCompatibility(false);
100            }else{
101                attr = new ContextAttribs();
102            }
103            if (settings.getBoolean("GraphicsDebug")){
104                attr = attr.withDebug(true);
105            }
106            return attr;
107        }else{
108            return null;
109        }
110    }
111
112    protected void initContextFirstTime(){
113        if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL2)
114         || settings.getRenderer().equals(AppSettings.LWJGL_OPENGL3)){
115            renderer = new LwjglRenderer();
116        }else if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL1)){
117            renderer = new LwjglGL1Renderer();
118        }else if (settings.getRenderer().equals(AppSettings.LWJGL_OPENGL_ANY)){
119            // Choose an appropriate renderer based on capabilities
120            if (GLContext.getCapabilities().OpenGL20){
121                renderer = new LwjglRenderer();
122            }else{
123                renderer = new LwjglGL1Renderer();
124            }
125        }else{
126            throw new UnsupportedOperationException("Unsupported renderer: " + settings.getRenderer());
127        }
128
129        // Init renderer
130        if (renderer instanceof LwjglRenderer){
131            ((LwjglRenderer)renderer).initialize();
132        }else if (renderer instanceof LwjglGL1Renderer){
133            ((LwjglGL1Renderer)renderer).initialize();
134        }else{
135            assert false;
136        }
137
138        // Init input
139        if (keyInput != null)
140            keyInput.initialize();
141
142        if (mouseInput != null)
143            mouseInput.initialize();
144
145        if (joyInput != null)
146            joyInput.initialize();
147    }
148
149    public void internalDestroy(){
150        renderer = null;
151        timer = null;
152        renderable.set(false);
153        synchronized (createdLock){
154            created.set(false);
155            createdLock.notifyAll();
156        }
157    }
158
159    public void internalCreate(){
160        timer = new LwjglTimer();
161
162        synchronized (createdLock){
163            created.set(true);
164            createdLock.notifyAll();
165        }
166
167        if (renderable.get()){
168            initContextFirstTime();
169        }else{
170            assert getType() == Type.Canvas;
171        }
172    }
173
174    public void create(){
175        create(false);
176    }
177
178    public void destroy(){
179        destroy(false);
180    }
181
182    protected void waitFor(boolean createdVal){
183        synchronized (createdLock){
184            while (created.get() != createdVal){
185                try {
186                    createdLock.wait();
187                } catch (InterruptedException ex) {
188                }
189            }
190        }
191    }
192
193    public boolean isCreated(){
194        return created.get();
195    }
196
197    public boolean isRenderable(){
198        return renderable.get();
199    }
200
201    public void setSettings(AppSettings settings) {
202        this.settings.copyFrom(settings);
203    }
204
205    public AppSettings getSettings(){
206        return settings;
207    }
208
209    public Renderer getRenderer() {
210        return renderer;
211    }
212
213    public Timer getTimer() {
214        return timer;
215    }
216
217}
218