Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
UseOpenGLCreationContext.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGL
4 using System;
5 using System.Linq;
6 using System.Runtime.InteropServices;
7 using System.Threading;
8 using OpenTK.Graphics;
9 #if SILICONSTUDIO_PARADOX_GRAPHICS_API_OPENGLES
10 using OpenTK.Graphics.ES30;
11 #else
12 using OpenTK.Graphics.OpenGL;
13 #endif
14 
15 namespace SiliconStudio.Paradox.Graphics
16 {
17  /// <summary>
18  /// Used internally to provide a context for async resource creation
19  /// (such as texture or buffer created on a thread where no context is active).
20  /// </summary>
21  internal struct UseOpenGLCreationContext : IDisposable
22  {
23  private readonly bool useDeviceCreationContext;
24  private readonly bool needUnbindContext;
25 
26  private readonly bool asyncCreationLockTaken;
27  private readonly object asyncCreationLockObject;
28 
29  private readonly IGraphicsContext deviceCreationContext;
30 
31 #if SILICONSTUDIO_PLATFORM_ANDROID
32  private readonly IGraphicsContext androidDeviceCreationContext;
33  private bool tegraWorkaround;
34 #endif
35 
36  public bool UseDeviceCreationContext
37  {
38  get { return useDeviceCreationContext; }
39  }
40 
41  public UseOpenGLCreationContext(GraphicsDevice graphicsDevice)
42  : this()
43  {
44 #if SILICONSTUDIO_PLATFORM_ANDROID
45  // Unfortunately, android seems to not use GraphicsContext.CurrentContext to register its AndroidGraphicsContext,
46  // so let's query EGL directly.
47  if (GraphicsDevice.EglGetCurrentContext() == IntPtr.Zero)
48 #elif SILICONSTUDIO_PLATFORM_IOS
49  if (MonoTouch.OpenGLES.EAGLContext.CurrentContext == null)
50 #else
51  if (GraphicsContext.CurrentContext == null)
52 #endif
53  {
54  needUnbindContext = true;
55  useDeviceCreationContext = true;
56 
57 #if SILICONSTUDIO_PLATFORM_ANDROID
58  tegraWorkaround = graphicsDevice.Workaround_Context_Tegra2_Tegra3;
59 
60  // Notify main rendering thread there is some pending async work to do
61  if (tegraWorkaround)
62  {
63  useDeviceCreationContext = false; // We actually use real main context, so states will be kept
64  graphicsDevice.AsyncPendingTaskWaiting = true;
65  }
66 #endif
67 
68  // Lock, since there is only one deviceCreationContext.
69  // TODO: Support multiple deviceCreationContext (TLS creation of context was crashing, need to investigate why)
70  asyncCreationLockObject = graphicsDevice.asyncCreationLockObject;
71  Monitor.Enter(graphicsDevice.asyncCreationLockObject, ref asyncCreationLockTaken);
72 
73 #if SILICONSTUDIO_PLATFORM_ANDROID
74  if (tegraWorkaround)
75  graphicsDevice.AsyncPendingTaskWaiting = false;
76 
77  // On android, bind the actual android context
78  // The deviceCreationContext is a dummy one, so that CurrentContext works.
79  androidDeviceCreationContext = graphicsDevice.androidAsyncDeviceCreationContext;
80  if (androidDeviceCreationContext != null)
81  androidDeviceCreationContext.MakeCurrent(graphicsDevice.deviceCreationWindowInfo);
82 #endif
83 
84  // Bind the context
85  deviceCreationContext = graphicsDevice.deviceCreationContext;
86  deviceCreationContext.MakeCurrent(graphicsDevice.deviceCreationWindowInfo);
87  }
88  }
89 
90  public void Dispose()
91  {
92  try
93  {
94  if (needUnbindContext)
95  {
96  GL.Flush();
97 
98 #if SILICONSTUDIO_PLATFORM_ANDROID
99  // On Android, the graphics context was just dummy so unbind the actual one.
100  // Best would be integration within OpenTK but since everything is internal and closed source,
101  // couldn't find a way around that
102  if (androidDeviceCreationContext != null)
103  androidDeviceCreationContext.MakeCurrent(null);
104 #endif
105 
106  // Restore graphics context
107  GraphicsDevice.UnbindGraphicsContext(deviceCreationContext);
108  }
109  }
110  finally
111  {
112  // Unlock
113  if (asyncCreationLockTaken)
114  {
115 #if SILICONSTUDIO_PLATFORM_ANDROID
116  if (tegraWorkaround)
117  {
118  // Notify GraphicsDevice.ExecutePendingTasks() that we are done.
119  Monitor.Pulse(asyncCreationLockObject);
120  }
121 #endif
122  Monitor.Exit(asyncCreationLockObject);
123  }
124  }
125  }
126  }
127 }
128 #endif