00001 #region --- License ---
00002
00003
00004
00005
00006
00007 #endregion
00008
00009 using System;
00010 using System.Collections.Generic;
00011 using System.Text;
00012 using System.Diagnostics;
00013
00014 using OpenTK.Platform;
00015
00016 namespace OpenTK.Graphics
00017 {
00021 public sealed class GraphicsContext : IGraphicsContext, IGraphicsContextInternal
00022 {
00023 #region --- Fields ---
00024
00025 IGraphicsContext implementation;
00026 bool disposed;
00027
00028
00029
00030 readonly bool IsExternal;
00031 bool check_errors = true;
00032
00033 static bool share_contexts = true;
00034 static bool direct_rendering = true;
00035 readonly static object SyncRoot = new object();
00036
00037 readonly static Dictionary<ContextHandle, WeakReference> available_contexts = new Dictionary<ContextHandle, WeakReference>();
00038
00039 #endregion
00040
00041 #region --- Constructors ---
00042
00043
00044 GraphicsContext(ContextHandle handle)
00045 {
00046 implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
00047
00048 lock (SyncRoot)
00049 {
00050 available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this));
00051 }
00052 }
00053
00059 public GraphicsContext(GraphicsMode mode, IWindowInfo window)
00060 : this(mode, window, 1, 0, GraphicsContextFlags.Default)
00061 { }
00062
00074 public GraphicsContext(GraphicsMode mode, IWindowInfo window, int major, int minor, GraphicsContextFlags flags)
00075 {
00076 lock (SyncRoot)
00077 {
00078 bool designMode = false;
00079 if (mode == null && window == null)
00080 designMode = true;
00081 else if (mode == null) throw new ArgumentNullException("mode", "Must be a valid GraphicsMode.");
00082 else if (window == null) throw new ArgumentNullException("window", "Must point to a valid window.");
00083
00084
00085 if (major <= 0)
00086 major = 1;
00087 if (minor < 0)
00088 minor = 0;
00089
00090 Debug.Print("Creating GraphicsContext.");
00091 try
00092 {
00093 Debug.Indent();
00094 Debug.Print("GraphicsMode: {0}", mode);
00095 Debug.Print("IWindowInfo: {0}", window);
00096 Debug.Print("GraphicsContextFlags: {0}", flags);
00097 Debug.Print("Requested version: {0}.{1}", major, minor);
00098
00099 IGraphicsContext shareContext = shareContext = FindSharedContext();
00100
00101
00102 if (designMode)
00103 {
00104 implementation = new Platform.Dummy.DummyGLContext();
00105 }
00106 else
00107 {
00108 IPlatformFactory factory = null;
00109 switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded)
00110 {
00111 case false: factory = Factory.Default; break;
00112 case true: factory = Factory.Embedded; break;
00113 }
00114
00115 implementation = factory.CreateGLContext(mode, window, shareContext, direct_rendering, major, minor, flags);
00116
00117
00118 if (GetCurrentContext == null)
00119 GetCurrentContext = factory.CreateGetCurrentGraphicsContext();
00120 }
00121
00122 available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this));
00123 }
00124 finally
00125 {
00126 Debug.Unindent();
00127 }
00128 }
00129 }
00130
00137 public GraphicsContext(ContextHandle handle, IWindowInfo window)
00138 : this(handle, window, null, 1, 0, GraphicsContextFlags.Default)
00139 { }
00140
00152 public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags)
00153 {
00154 lock (SyncRoot)
00155 {
00156 IsExternal = true;
00157
00158 if (handle == ContextHandle.Zero)
00159 {
00160 implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
00161 }
00162 else if (available_contexts.ContainsKey(handle))
00163 {
00164 throw new GraphicsContextException("Context already exists.");
00165 }
00166 else
00167 {
00168 switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded)
00169 {
00170 case false: implementation = Factory.Default.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
00171 case true: implementation = Factory.Embedded.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
00172 }
00173 }
00174
00175 available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this));
00176
00177 (this as IGraphicsContextInternal).LoadAll();
00178 }
00179 }
00180
00181 #endregion
00182
00183 #region Private Members
00184
00185 static IGraphicsContext FindSharedContext()
00186 {
00187 if (GraphicsContext.ShareContexts)
00188 {
00189
00190 foreach (WeakReference r in GraphicsContext.available_contexts.Values)
00191 {
00192 return (IGraphicsContext)r.Target;
00193 }
00194 }
00195 return null;
00196 }
00197
00198 #endregion
00199
00200 #region --- Static Members ---
00201
00202 #region public static GraphicsContext CreateDummyContext()
00203
00212 public static GraphicsContext CreateDummyContext()
00213 {
00214 ContextHandle handle = GetCurrentContext();
00215 if (handle == ContextHandle.Zero)
00216 throw new InvalidOperationException("No GraphicsContext is current on the calling thread.");
00217
00218 return CreateDummyContext(handle);
00219 }
00220
00229 public static GraphicsContext CreateDummyContext(ContextHandle handle)
00230 {
00231 if (handle == ContextHandle.Zero)
00232 throw new ArgumentOutOfRangeException("handle");
00233
00234 return new GraphicsContext(handle);
00235 }
00236
00237 #endregion
00238
00239 #region public static void Assert()
00240
00245 public static void Assert()
00246 {
00247 if (GraphicsContext.CurrentContext == null)
00248 throw new GraphicsContextMissingException();
00249 }
00250
00251 #endregion
00252
00253 #region public static IGraphicsContext CurrentContext
00254
00255 internal delegate ContextHandle GetCurrentContextDelegate();
00256 internal static GetCurrentContextDelegate GetCurrentContext;
00257
00265 public static IGraphicsContext CurrentContext
00266 {
00267 get
00268 {
00269 lock (SyncRoot)
00270 {
00271 if (available_contexts.Count > 0)
00272 {
00273 ContextHandle handle = GetCurrentContext();
00274 if (handle.Handle != IntPtr.Zero)
00275 return (GraphicsContext)available_contexts[handle].Target;
00276 }
00277 return null;
00278 }
00279 }
00280 }
00281
00282 #endregion
00283
00284 #region public static bool ShareContexts
00285
00292 public static bool ShareContexts { get { return share_contexts; } set { share_contexts = value; } }
00293
00294 #endregion
00295
00296 #region public static bool DirectRendering
00297
00309 public static bool DirectRendering
00310 {
00311 get { return direct_rendering; }
00312 set { direct_rendering = value; }
00313 }
00314
00315 #endregion
00316
00317 #endregion
00318
00319 #region --- IGraphicsContext Members ---
00320
00327 public bool ErrorChecking
00328 {
00329 get { return check_errors; }
00330 set { check_errors = value; }
00331 }
00348 void CreateContext(bool direct, IGraphicsContext source)
00349 {
00350 lock (SyncRoot)
00351 {
00352 available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this));
00353 }
00354 }
00355
00359 public void SwapBuffers()
00360 {
00361 implementation.SwapBuffers();
00362 }
00363
00371 public void MakeCurrent(IWindowInfo window)
00372 {
00373 implementation.MakeCurrent(window);
00374 }
00375
00379 public bool IsCurrent
00380 {
00381 get { return implementation.IsCurrent; }
00382 }
00383
00388 public bool IsDisposed
00389 {
00390 get { return disposed && implementation.IsDisposed; }
00391 private set { disposed = value; }
00392 }
00393
00397 public bool VSync
00398 {
00399 get { return implementation.VSync; }
00400 set { implementation.VSync = value; }
00401 }
00402
00408 public void Update(IWindowInfo window)
00409 {
00410 implementation.Update(window);
00411 }
00412
00413 #endregion
00414
00415 #region --- IGraphicsContextInternal Members ---
00416
00420 IGraphicsContext IGraphicsContextInternal.Implementation
00421 {
00422 get { return implementation; }
00423 }
00424
00431 void IGraphicsContextInternal.LoadAll()
00432 {
00433 if (GraphicsContext.CurrentContext != this)
00434 throw new GraphicsContextException();
00435
00436 (implementation as IGraphicsContextInternal).LoadAll();
00437 }
00438
00442 ContextHandle IGraphicsContextInternal.Context
00443 {
00444 get { return ((IGraphicsContextInternal)implementation).Context; }
00445 }
00446
00450 public GraphicsMode GraphicsMode
00451 {
00452 get { return (implementation as IGraphicsContext).GraphicsMode; }
00453 }
00454
00463 IntPtr IGraphicsContextInternal.GetAddress(string function)
00464 {
00465 return (implementation as IGraphicsContextInternal).GetAddress(function);
00466 }
00467
00468 #endregion
00469
00470 #region --- IDisposable Members ---
00471
00475 public void Dispose()
00476 {
00477 this.Dispose(true);
00478 GC.SuppressFinalize(this);
00479 }
00480
00481 void Dispose(bool manual)
00482 {
00483 if (!IsDisposed)
00484 {
00485 Debug.Print("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString());
00486 lock (SyncRoot)
00487 {
00488 available_contexts.Remove((this as IGraphicsContextInternal).Context);
00489 }
00490
00491 if (manual && !IsExternal)
00492 {
00493 if (implementation != null)
00494 implementation.Dispose();
00495 }
00496 IsDisposed = true;
00497 }
00498 }
00499
00500 #endregion
00501 }
00502 }