| 1 |
/******************************************************************************* |
|---|
| 2 |
* Copyright (c) 2000, 2008 IBM Corporation and others. |
|---|
| 3 |
* All rights reserved. This program and the accompanying materials |
|---|
| 4 |
* are made available under the terms of the Eclipse Public License v1.0 |
|---|
| 5 |
* which accompanies this distribution, and is available at |
|---|
| 6 |
* http://www.eclipse.org/legal/epl-v10.html |
|---|
| 7 |
* |
|---|
| 8 |
* Contributors: |
|---|
| 9 |
* IBM Corporation - initial API and implementation |
|---|
| 10 |
* Port to the D Programming Language: |
|---|
| 11 |
* John Reimer <terminal.node@gmail.com> |
|---|
| 12 |
*******************************************************************************/ |
|---|
| 13 |
module dwt.opengl.GLCanvas; |
|---|
| 14 |
|
|---|
| 15 |
import dwt.DWT; |
|---|
| 16 |
import dwt.DWTException; |
|---|
| 17 |
import dwt.internal.opengl.win32.WGL; |
|---|
| 18 |
import dwt.internal.win32.OS; |
|---|
| 19 |
import dwt.widgets.Canvas; |
|---|
| 20 |
import dwt.widgets.Composite; |
|---|
| 21 |
import dwt.widgets.Event; |
|---|
| 22 |
import dwt.widgets.Listener; |
|---|
| 23 |
import dwt.opengl.GLData; |
|---|
| 24 |
|
|---|
| 25 |
/** |
|---|
| 26 |
* GLCanvas is a widget capable of displaying OpenGL content. |
|---|
| 27 |
* |
|---|
| 28 |
* @see GLData |
|---|
| 29 |
* @see <a href="http://www.eclipse.org/swt/snippets/#opengl">OpenGL snippets</a> |
|---|
| 30 |
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a> |
|---|
| 31 |
* |
|---|
| 32 |
* @since 3.2 |
|---|
| 33 |
*/ |
|---|
| 34 |
|
|---|
| 35 |
public class GLCanvas : Canvas { |
|---|
| 36 |
HGLRC context; |
|---|
| 37 |
int pixelFormat; |
|---|
| 38 |
|
|---|
| 39 |
/** |
|---|
| 40 |
* Create a GLCanvas widget using the attributes described in the GLData |
|---|
| 41 |
* object provided. |
|---|
| 42 |
* |
|---|
| 43 |
* @param parent a composite widget |
|---|
| 44 |
* @param style the bitwise OR'ing of widget styles |
|---|
| 45 |
* @param data the requested attributes of the GLCanvas |
|---|
| 46 |
* |
|---|
| 47 |
* @exception IllegalArgumentException |
|---|
| 48 |
* <ul><li>ERROR_NULL_ARGUMENT when the data is null |
|---|
| 49 |
* <li>ERROR_UNSUPPORTED_DEPTH when the requested attributes cannot be provided</ul> |
|---|
| 50 |
* </ul> |
|---|
| 51 |
*/ |
|---|
| 52 |
public this (Composite parent, int style, GLData data) { |
|---|
| 53 |
super (parent, style); |
|---|
| 54 |
if (data is null) DWT.error (DWT.ERROR_NULL_ARGUMENT); |
|---|
| 55 |
PIXELFORMATDESCRIPTOR pfd; |
|---|
| 56 |
pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof; |
|---|
| 57 |
pfd.nVersion = 1; |
|---|
| 58 |
pfd.dwFlags = WGL.PFD_DRAW_TO_WINDOW | WGL.PFD_SUPPORT_OPENGL; |
|---|
| 59 |
pfd.dwLayerMask = WGL.PFD_MAIN_PLANE; |
|---|
| 60 |
pfd.iPixelType = cast(byte) WGL.PFD_TYPE_RGBA; |
|---|
| 61 |
if (data.doubleBuffer) pfd.dwFlags |= WGL.PFD_DOUBLEBUFFER; |
|---|
| 62 |
if (data.stereo) pfd.dwFlags |= WGL.PFD_STEREO; |
|---|
| 63 |
pfd.cRedBits = cast(byte) data.redSize; |
|---|
| 64 |
pfd.cGreenBits = cast(byte) data.greenSize; |
|---|
| 65 |
pfd.cBlueBits = cast(byte) data.blueSize; |
|---|
| 66 |
pfd.cAlphaBits = cast(byte) data.alphaSize; |
|---|
| 67 |
pfd.cDepthBits = cast(byte) data.depthSize; |
|---|
| 68 |
pfd.cStencilBits = cast(byte) data.stencilSize; |
|---|
| 69 |
pfd.cAccumRedBits = cast(byte) data.accumRedSize; |
|---|
| 70 |
pfd.cAccumGreenBits = cast(byte) data.accumGreenSize; |
|---|
| 71 |
pfd.cAccumBlueBits = cast(byte) data.accumBlueSize; |
|---|
| 72 |
pfd.cAccumAlphaBits = cast(byte) data.accumAlphaSize; |
|---|
| 73 |
pfd.cAccumBits = cast(byte) (pfd.cAccumRedBits + pfd.cAccumGreenBits + pfd.cAccumBlueBits + pfd.cAccumAlphaBits); |
|---|
| 74 |
|
|---|
| 75 |
//FIXME - use wglChoosePixelFormatARB |
|---|
| 76 |
// if (data.sampleBuffers > 0) { |
|---|
| 77 |
// wglAttrib [pos++] = WGL.WGL_SAMPLE_BUFFERS_ARB; |
|---|
| 78 |
// wglAttrib [pos++] = data.sampleBuffers; |
|---|
| 79 |
// } |
|---|
| 80 |
// if (data.samples > 0) { |
|---|
| 81 |
// wglAttrib [pos++] = WGL.WGL_SAMPLES_ARB; |
|---|
| 82 |
// wglAttrib [pos++] = data.samples; |
|---|
| 83 |
// } |
|---|
| 84 |
|
|---|
| 85 |
auto hDC = OS.GetDC (handle); |
|---|
| 86 |
pixelFormat = WGL.ChoosePixelFormat (hDC, &pfd); |
|---|
| 87 |
if (pixelFormat is 0 || !WGL.SetPixelFormat (hDC, pixelFormat, &pfd)) { |
|---|
| 88 |
OS.ReleaseDC (handle, hDC); |
|---|
| 89 |
dispose (); |
|---|
| 90 |
DWT.error (DWT.ERROR_UNSUPPORTED_DEPTH); |
|---|
| 91 |
} |
|---|
| 92 |
context = WGL.wglCreateContext (hDC); |
|---|
| 93 |
if (context is null) { |
|---|
| 94 |
OS.ReleaseDC (handle, hDC); |
|---|
| 95 |
DWT.error (DWT.ERROR_NO_HANDLES); |
|---|
| 96 |
} |
|---|
| 97 |
OS.ReleaseDC (handle, hDC); |
|---|
| 98 |
//FIXME- share lists |
|---|
| 99 |
//if (share !is null) WGL.wglShareLists (context, share.context); |
|---|
| 100 |
|
|---|
| 101 |
Listener listener = new class() Listener { |
|---|
| 102 |
public void handleEvent (Event event) { |
|---|
| 103 |
switch (event.type) { |
|---|
| 104 |
case DWT.Dispose: |
|---|
| 105 |
WGL.wglDeleteContext (context); |
|---|
| 106 |
break; |
|---|
| 107 |
default: |
|---|
| 108 |
} |
|---|
| 109 |
} |
|---|
| 110 |
}; |
|---|
| 111 |
addListener (DWT.Dispose, listener); |
|---|
| 112 |
} |
|---|
| 113 |
|
|---|
| 114 |
/** |
|---|
| 115 |
* Returns a GLData object describing the created context. |
|---|
| 116 |
* |
|---|
| 117 |
* @return GLData description of the OpenGL context attributes |
|---|
| 118 |
* @exception DWTException <ul> |
|---|
| 119 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 120 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 121 |
* </ul> |
|---|
| 122 |
*/ |
|---|
| 123 |
public GLData getGLData () { |
|---|
| 124 |
checkWidget (); |
|---|
| 125 |
GLData data = new GLData (); |
|---|
| 126 |
PIXELFORMATDESCRIPTOR pfd; |
|---|
| 127 |
pfd.nSize = cast(short) PIXELFORMATDESCRIPTOR.sizeof; |
|---|
| 128 |
auto hDC = OS.GetDC (handle); |
|---|
| 129 |
WGL.DescribePixelFormat (hDC, pixelFormat, PIXELFORMATDESCRIPTOR.sizeof, &pfd); |
|---|
| 130 |
OS.ReleaseDC (handle, hDC); |
|---|
| 131 |
data.doubleBuffer = (pfd.dwFlags & WGL.PFD_DOUBLEBUFFER) !is 0; |
|---|
| 132 |
data.stereo = (pfd.dwFlags & WGL.PFD_STEREO) !is 0; |
|---|
| 133 |
data.redSize = pfd.cRedBits; |
|---|
| 134 |
data.greenSize = pfd.cGreenBits; |
|---|
| 135 |
data.blueSize = pfd.cBlueBits; |
|---|
| 136 |
data.alphaSize = pfd.cAlphaBits; |
|---|
| 137 |
data.depthSize = pfd.cDepthBits; |
|---|
| 138 |
data.stencilSize = pfd.cStencilBits; |
|---|
| 139 |
data.accumRedSize = pfd.cAccumRedBits; |
|---|
| 140 |
data.accumGreenSize = pfd.cAccumGreenBits; |
|---|
| 141 |
data.accumBlueSize = pfd.cAccumBlueBits; |
|---|
| 142 |
data.accumAlphaSize = pfd.cAccumAlphaBits; |
|---|
| 143 |
return data; |
|---|
| 144 |
} |
|---|
| 145 |
|
|---|
| 146 |
/** |
|---|
| 147 |
* Returns a bool indicating whether the receiver's OpenGL context |
|---|
| 148 |
* is the current context. |
|---|
| 149 |
* |
|---|
| 150 |
* @return true if the receiver holds the current OpenGL context, |
|---|
| 151 |
* false otherwise |
|---|
| 152 |
* @exception DWTException <ul> |
|---|
| 153 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 154 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 155 |
* </ul> |
|---|
| 156 |
*/ |
|---|
| 157 |
public bool isCurrent () { |
|---|
| 158 |
checkWidget (); |
|---|
| 159 |
return (WGL.wglGetCurrentContext is context); |
|---|
| 160 |
} |
|---|
| 161 |
|
|---|
| 162 |
/** |
|---|
| 163 |
* Sets the OpenGL context associated with this GLCanvas to be the |
|---|
| 164 |
* current GL context. |
|---|
| 165 |
* |
|---|
| 166 |
* @exception DWTException <ul> |
|---|
| 167 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 168 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 169 |
* </ul> |
|---|
| 170 |
*/ |
|---|
| 171 |
public void setCurrent () { |
|---|
| 172 |
checkWidget (); |
|---|
| 173 |
if (WGL.wglGetCurrentContext is context) return; |
|---|
| 174 |
auto hDC = OS.GetDC (handle); |
|---|
| 175 |
WGL.wglMakeCurrent (hDC, context); |
|---|
| 176 |
OS.ReleaseDC (handle, hDC); |
|---|
| 177 |
} |
|---|
| 178 |
|
|---|
| 179 |
/** |
|---|
| 180 |
* Swaps the front and back color buffers. |
|---|
| 181 |
* |
|---|
| 182 |
* @exception DWTException <ul> |
|---|
| 183 |
* <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li> |
|---|
| 184 |
* <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li> |
|---|
| 185 |
* </ul> |
|---|
| 186 |
*/ |
|---|
| 187 |
public void swapBuffers () { |
|---|
| 188 |
checkWidget (); |
|---|
| 189 |
auto hDC = OS.GetDC (handle); |
|---|
| 190 |
WGL.SwapBuffers (hDC); |
|---|
| 191 |
OS.ReleaseDC (handle, hDC); |
|---|
| 192 |
} |
|---|
| 193 |
} |
|---|