001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: /**
018: * @author Oleg V. Khaschansky
019: * @version $Revision$
020: */package org.apache.harmony.awt.gl.windows;
021:
022: import org.apache.harmony.awt.gl.opengl.OGLContextManager;
023: import org.apache.harmony.awt.gl.opengl.GLDefs;
024: import org.apache.harmony.awt.gl.opengl.OGLVolatileImage;
025: import org.apache.harmony.awt.nativebridge.windows.*;
026: import org.apache.harmony.awt.nativebridge.NativeBridge;
027: import org.apache.harmony.awt.nativebridge.Int32Pointer;
028: import org.apache.harmony.awt.wtk.windows.WindowProcHandler;
029: import org.apache.harmony.awt.wtk.windows.WinEventQueue;
030: import org.apache.harmony.awt.ContextStorage;
031:
032: import java.util.ArrayList;
033: import java.util.HashSet;
034: import java.awt.image.VolatileImage;
035:
036: public class WGLGraphicsConfiguration extends WinGraphicsConfiguration
037: implements OGLContextManager {
038: private static final Win32 w32 = Win32.getInstance();
039: private static final WGL wgl = WGL.getInstance();
040:
041: private static final String WINDOW_CLASS_NAME = "org.apache.harmony.awt.gl.tmpWindow";
042: private static final int FORMATTED_DRAWABLES_CACHE_SIZE = 255;
043:
044: private static final ThreadLocal oglContextThreadLocal = new ThreadLocal();
045:
046: private static long currentOGLContext;
047: private static long currentDrawable;
048:
049: private static final ArrayList existingContexts = new ArrayList();
050: private static final HashSet formattedDrawables = new HashSet(255);
051:
052: private static boolean wndClassRegistetred;
053:
054: private long hTmpWnd;
055: private long hTmpDC;
056: private long tmpCtx;
057:
058: // XXX - todo - maybe we need different pointers for different configurations?
059: //private static boolean resolvedEXT = false; // Are ext funcs resolved?
060:
061: private long getLocalOGLContext() {
062: Long ctxId = (Long) oglContextThreadLocal.get();
063: return ctxId == null ? 0 : ctxId.longValue();
064: }
065:
066: public WGLGraphicsConfiguration(WinGraphicsDevice device,
067: int index, Win32.PIXELFORMATDESCRIPTOR pfd) {
068: super (device, index, pfd);
069: }
070:
071: public WGLGraphicsConfiguration(long hwnd, long hdc) {
072: super (hwnd, hdc);
073: }
074:
075: public long windowProc(long hwnd, int msg, long wParam, long lParam) {
076: return w32.DefWindowProcW(hwnd, msg, wParam, lParam);
077: }
078:
079: private final long getHWND() {
080: if (!wndClassRegistetred) {
081: WindowProcHandler.registerWindowClass(WINDOW_CLASS_NAME);
082: wndClassRegistetred = true;
083: }
084:
085: WinEventQueue.Task task = new WinEventQueue.Task() {
086: public void perform() {
087: returnValue = new Long(w32.CreateWindowExW(0,
088: WINDOW_CLASS_NAME, "TmpWindow", 0, 0, 0, 0, 0,
089: 0, 0, 0, null));
090: }
091: };
092:
093: WinEventQueue winEventQueue = ((WinEventQueue) ContextStorage
094: .getNativeEventQueue());
095: winEventQueue.performTask(task);
096:
097: return ((Long) task.returnValue).longValue();
098: }
099:
100: private void activateTmpCtx() {
101: if (hTmpWnd == 0) {
102: hTmpWnd = getHWND();
103: hTmpDC = w32.GetDC(hTmpWnd);
104:
105: Win32.PIXELFORMATDESCRIPTOR pfd = w32
106: .createPIXELFORMATDESCRIPTOR(false);
107: pfd.set_nSize((short) pfd.size());
108: pfd.set_nVersion((short) 1);
109: pfd.set_dwFlags(WindowsDefs.PFD_DRAW_TO_WINDOW
110: | WindowsDefs.PFD_SUPPORT_OPENGL);
111: pfd.set_iPixelType((byte) WindowsDefs.PFD_TYPE_RGBA);
112: pfd.set_cAlphaBits((byte) 8);
113: pfd.set_cStencilBits((byte) 1);
114: pfd.set_iLayerType((byte) WindowsDefs.PFD_MAIN_PLANE);
115:
116: int pixelFormat = w32.ChoosePixelFormat(hTmpDC, pfd);
117: w32.SetPixelFormat(hTmpDC, pixelFormat, pfd);
118: tmpCtx = wgl.wglCreateContext(hTmpDC);
119: }
120:
121: wgl.wglMakeCurrent(hTmpDC, tmpCtx);
122: }
123:
124: protected void finalize() throws Throwable {
125: wgl.wglDeleteContext(tmpCtx);
126: w32.ReleaseDC(hTmpWnd, hTmpDC);
127: w32.DestroyWindow(hTmpWnd);
128: }
129:
130: private final int choosePixelFormatARB(long hdc) {
131: /*
132: if (!resolvedEXT) {
133: resolveEXT();
134: }
135: */
136: activateTmpCtx();
137:
138: Int32Pointer nFormats = NativeBridge.getInstance()
139: .createInt32Pointer(1, true);
140: Int32Pointer formatPtr = NativeBridge.getInstance()
141: .createInt32Pointer(1, true);
142: Int32Pointer attribList = NativeBridge.getInstance()
143: .createInt32Pointer(13, true);
144:
145: // Fill in FB config attributes
146: attribList.set(0, WGLDefs.WGL_PIXEL_TYPE_ARB);
147: attribList.set(1, WGLDefs.WGL_TYPE_RGBA_ARB);
148: attribList.set(2, WGLDefs.WGL_DRAW_TO_WINDOW_ARB);
149: attribList.set(3, GLDefs.GL_TRUE);
150: attribList.set(4, WGLDefs.WGL_DRAW_TO_PBUFFER_ARB);
151: attribList.set(5, GLDefs.GL_TRUE);
152: attribList.set(6, WGLDefs.WGL_STENCIL_BITS_ARB);
153: attribList.set(7, 1);
154: attribList.set(8, WGLDefs.WGL_ALPHA_BITS_ARB);
155: attribList.set(9, 8);
156: attribList.set(10, WGLDefs.WGL_ACCELERATION_ARB);
157: attribList.set(11, WGLDefs.WGL_FULL_ACCELERATION_ARB);
158: //attribList.set(12, WGLDefs.WGL_DOUBLE_BUFFER_ARB);
159: //attribList.set(13, GLDefs.GL_TRUE);
160: attribList.set(12, 0);
161:
162: wgl.wglChoosePixelFormatARB(hdc, attribList, null, 1,
163: formatPtr, nFormats);
164:
165: int res = formatPtr.get(0);
166:
167: formatPtr.free();
168: nFormats.free();
169: attribList.free();
170:
171: return res;
172: }
173:
174: /**
175: * This method calls ext (ARB) functions to resolve its addresses.
176: * For now it calls only one - wglChoosePixelFormatARB
177: */
178: /*
179: private final void resolveEXT() {
180: long hwnd = getHWND();
181: long hdc = w32.GetDC(hwnd);
182:
183: Win32.PIXELFORMATDESCRIPTOR pfd = w32.createPIXELFORMATDESCRIPTOR(false);
184: pfd.set_nSize((short)pfd.size());
185: pfd.set_nVersion((short)1);
186: pfd.set_dwFlags(WindowsDefs.PFD_DRAW_TO_WINDOW | WindowsDefs.PFD_SUPPORT_OPENGL);
187: pfd.set_iPixelType((byte)WindowsDefs.PFD_TYPE_RGBA);
188: pfd.set_cColorBits((byte)32);
189: pfd.set_cAlphaBits((byte)8);
190: pfd.set_cStencilBits((byte)1);
191: pfd.set_iLayerType((byte)WindowsDefs.PFD_MAIN_PLANE);
192:
193: int pixelFormat = w32.ChoosePixelFormat(hdc, pfd);
194: w32.SetPixelFormat(hdc, pixelFormat, pfd);
195: // XXX - todo - check for success
196: long ctx = wgl.wglCreateContext(hdc);
197: wgl.wglMakeCurrent(hdc, ctx);
198:
199: WGL.init(); // Initialize function pointers
200:
201: wgl.wglMakeCurrent(0, 0);
202: wgl.wglDeleteContext(ctx);
203:
204: w32.ReleaseDC(hwnd, hdc);
205: w32.DestroyWindow(hwnd);
206:
207: resolvedEXT = true;
208: }
209: */
210: public long getOGLContext(long drawable, long oshdc) {
211: long oglContext = getLocalOGLContext();
212:
213: if (oglContext == 0) {
214: long hdc = (oshdc == 0) ? w32.GetDC(drawable) : oshdc;
215:
216: if (oshdc == 0) {
217: int pixelFormat = choosePixelFormatARB(hdc);
218: w32.SetPixelFormat(hdc, pixelFormat, w32
219: .createPIXELFORMATDESCRIPTOR(false));
220: if (formattedDrawables.size() > FORMATTED_DRAWABLES_CACHE_SIZE) {
221: formattedDrawables.clear();
222: }
223: formattedDrawables.add(new Long(drawable));
224: }
225:
226: oglContext = wgl.wglCreateContext(hdc);
227:
228: if (oshdc == 0) {
229: w32.ReleaseDC(drawable, hdc);
230: }
231:
232: // Share display lists if there are othe contexts
233: if (existingContexts.size() > 0) {
234: wgl.wglShareLists(((Long) existingContexts.get(0))
235: .longValue(), oglContext);
236: }
237:
238: existingContexts.add(new Long(oglContext));
239: oglContextThreadLocal.set(new Long(oglContext));
240: }
241:
242: return oglContext;
243: }
244:
245: public void destroyOGLContext(long oglContext) {
246: if (oglContext == currentOGLContext) {
247: currentOGLContext = 0;
248: }
249:
250: wgl.wglDeleteContext(oglContext);
251: existingContexts.remove(new Long(oglContext));
252: }
253:
254: public boolean makeCurrent(long oglContext, long drawable,
255: long oshdc) {
256: if (oglContext != currentOGLContext
257: || drawable != currentDrawable) {
258:
259: long hdc = (oshdc == 0) ? w32.GetDC(drawable) : oshdc;
260:
261: if (oshdc == 0
262: && !formattedDrawables.contains(new Long(drawable))) { // Need to set pixel format
263: int pixelFormat = choosePixelFormatARB(hdc);
264: w32.SetPixelFormat(hdc, pixelFormat, w32
265: .createPIXELFORMATDESCRIPTOR(false));
266: if (formattedDrawables.size() > FORMATTED_DRAWABLES_CACHE_SIZE) {
267: formattedDrawables.clear();
268: }
269: formattedDrawables.add(new Long(drawable));
270: }
271:
272: if (wgl.wglMakeCurrent(hdc, oglContext) == 0) {
273: w32.ReleaseDC(drawable, hdc);
274: throw new IllegalStateException(
275: "Cannot make opengl context current");
276: }
277:
278: if (oshdc == 0) {
279: w32.ReleaseDC(drawable, hdc);
280: }
281:
282: currentOGLContext = oglContext;
283: currentDrawable = drawable;
284:
285: return true;
286: }
287:
288: return false;
289: }
290:
291: public boolean makeContextCurrent(long oglContext, long draw,
292: long read, long drawHDC, long readHDC) {
293: return makeCurrent(oglContext, draw, drawHDC); // XXX - todo - implement
294: }
295:
296: public void swapBuffers(long drawable, long oshdc) {
297: long hdc = (oshdc == 0) ? w32.GetDC(drawable) : oshdc;
298: wgl.SwapBuffers(hdc);
299: if (oshdc == 0) {
300: w32.ReleaseDC(drawable, hdc);
301: }
302: }
303:
304: public OffscreenBufferObject createOffscreenBuffer(int w, int h) {
305: // Try to get pbuffer from cache
306: OffscreenBufferObject pbuffer = OffscreenBufferObject
307: .getCachedBuffer(w, h, this );
308: if (pbuffer != null) {
309: return pbuffer;
310: }
311:
312: long hwnd = getHWND();
313: long hdc = w32.GetDC(hwnd);
314:
315: int pixelFormat = choosePixelFormatARB(hdc);
316:
317: Int32Pointer attribList = NativeBridge.getInstance()
318: .createInt32Pointer(1, true);
319: attribList.set(0, 0);
320: long id = wgl.wglCreatePbufferARB(hdc, pixelFormat, w, h,
321: attribList.lock());
322: attribList.unlock();
323: attribList.free();
324:
325: long buffHdc = wgl.wglGetPbufferDCARB(id);
326:
327: w32.ReleaseDC(hwnd, hdc);
328: w32.DestroyWindow(hwnd);
329:
330: return new OffscreenBufferObject(id, buffHdc, w, h, this );
331: }
332:
333: public void freeOffscreenBuffer(OffscreenBufferObject pbuffer) {
334: pbuffer = OffscreenBufferObject.freeCachedBuffer(pbuffer);
335:
336: if (pbuffer != null) {
337: wgl.wglReleasePbufferDCARB(pbuffer.id, pbuffer.hdc);
338: wgl.wglDestroyPbufferARB(pbuffer.id);
339: }
340: }
341:
342: public void freeOffscreenBuffer(long id, long hdc) {
343: wgl.wglReleasePbufferDCARB(id, hdc);
344: wgl.wglDestroyPbufferARB(id);
345: }
346:
347: public VolatileImage createCompatibleVolatileImage(int width,
348: int height) {
349: return new OGLVolatileImage(this, width, height);
350: }
351: }
|