Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
AndroidAsyncGraphicsContext.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_PLATFORM_ANDROID
4 using System;
5 using Android.Runtime;
6 using Javax.Microedition.Khronos.Egl;
7 using OpenTK;
8 using OpenTK.Graphics;
9 using OpenTK.Platform;
10 using OpenTK.Platform.Android;
11 using System.Linq;
12 
13 namespace SiliconStudio.Paradox.Graphics
14 {
15  /// <summary>
16  /// Used internally on Android to provide a context for async resource creation (through <see cref="UseOpenGLCreationContext"/>).
17  /// </summary>
18  internal class AndroidAsyncGraphicsContext : IGraphicsContext, IGraphicsContextInternal
19  {
20  private readonly IEGL10 egl;
21 
22  public EGLContext EGLContext { get; private set; }
23  public EGLDisplay EGLDisplay { get; private set; }
24  public EGLSurface EGLSurface { get; private set; }
25 
26  public EGLConfig EGLConfig { get; private set; }
27 
28 
29  private bool isDisposed;
30 
31  internal AndroidAsyncGraphicsContext(AndroidGraphicsContext graphicsContext, AndroidWindow androidWindow)
32  {
33  egl = EGLContext.EGL.JavaCast<IEGL10>();
34 
35  var pbufferAttribList = new[]
36  {
37  EGL10.EglWidth, 1,
38  EGL10.EglHeight, 1,
39  EGL10.EglNone
40  };
41 
42  EGLDisplay = androidWindow.Display;
43  var androidGraphicsContext = graphicsContext;
44  var config = androidGraphicsContext.EGLConfig;
45 
46  var attribList = new[]
47  {
48  EGL10.EglSurfaceType, EGL10.EglPbufferBit,
49  EGL10.EglRenderableType, 4, // (opengl es 2.0)
50 
51  EGL10.EglRedSize, graphicsContext.GraphicsMode.ColorFormat.Red,
52  EGL10.EglGreenSize, graphicsContext.GraphicsMode.ColorFormat.Green,
53  EGL10.EglBlueSize, graphicsContext.GraphicsMode.ColorFormat.Blue,
54  EGL10.EglAlphaSize, graphicsContext.GraphicsMode.ColorFormat.Alpha,
55 
56  EGL10.EglDepthSize, graphicsContext.GraphicsMode.Depth,
57  EGL10.EglStencilSize, graphicsContext.GraphicsMode.Stencil,
58 
59  //Egl.SAMPLE_BUFFERS, samples > 0 ? 1 : 0,
60  EGL10.EglSamples, 0,
61 
62  EGL10.EglNone,
63  };
64 
65  // first ask the number of config available
66  var numConfig = new int[1];
67  if (!egl.EglChooseConfig(EGLDisplay, attribList, null, 0, numConfig))
68  {
69  throw new InvalidOperationException(string.Format("EglChooseConfig {0:x}", egl.EglGetError()));
70  }
71 
72  // retrieve the available configs
73  var configs = new EGLConfig[numConfig[0]];
74  if (!egl.EglChooseConfig(EGLDisplay, attribList, configs, configs.Length, numConfig))
75  {
76  throw new InvalidOperationException(string.Format("EglChooseConfig {0:x}", egl.EglGetError()));
77  }
78 
79  // choose the best config
80  EGLConfig = ChooseConfigEGL(configs);
81 
82  // create the surface
83  EGLSurface = egl.EglCreatePbufferSurface(EGLDisplay, EGLConfig, pbufferAttribList);
84  if (EGLSurface == EGL10.EglNoSurface)
85  {
86  throw new InvalidOperationException(string.Format("EglCreatePBufferSurface {0:x}", egl.EglGetError()));
87  }
88 
89  var attribList3 = new[] { 0x3098, 2, EGL10.EglNone };
90  EGLContext = egl.EglCreateContext(EGLDisplay, config, androidGraphicsContext.EGLContext, attribList3);
91  if (EGLContext == EGL10.EglNoContext)
92  {
93  throw new InvalidOperationException(string.Format("EglCreateContext {0:x}", egl.EglGetError()));
94  }
95  }
96 
97  private struct UserReadableEglConfig
98  {
99  public int SurfaceType;
100  public int RenderableType;
101  public int RedSize;
102  public int GreenSize;
103  public int BlueSize;
104  public int AlphaSize;
105  public int DepthSize;
106  public int StencilSize;
107  public int Samples;
108  }
109 
110  private UserReadableEglConfig EglConfigToUserReadableEglConfig(EGLConfig eglConfig)
111  {
112  var surfaceType = new int[1];
113  var renderableType = new int[1];
114  var redSize = new int[1];
115  var greenSize = new int[1];
116  var blueSize = new int[1];
117  var alphaSize = new int[1];
118  var depthSize = new int[1];
119  var stencilSize = new int[1];
120  var samples = new int[1];
121 
122  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglSurfaceType, surfaceType))
123  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
124  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglRenderableType, renderableType))
125  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
126  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglRedSize, redSize))
127  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
128  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglGreenSize, greenSize))
129  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
130  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglBlueSize, blueSize))
131  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
132  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglAlphaSize, alphaSize))
133  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
134  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglDepthSize, depthSize))
135  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
136  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglStencilSize, stencilSize))
137  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
138  if (!egl.EglGetConfigAttrib(EGLDisplay, eglConfig, EGL10.EglSamples, samples))
139  throw new InvalidOperationException(string.Format("EglGetConfigAttrib {0:x}", egl.EglGetError()));
140 
141  return new UserReadableEglConfig
142  {
143  SurfaceType = surfaceType[0],
144  RenderableType = renderableType[0],
145  RedSize = redSize[0],
146  GreenSize = greenSize[0],
147  BlueSize = blueSize[0],
148  AlphaSize = alphaSize[0],
149  DepthSize = depthSize[0],
150  StencilSize = stencilSize[0],
151  Samples = samples[0]
152  };
153  }
154 
155  private EGLConfig ChooseConfigEGL(EGLConfig[] configs)
156  {
157  if(configs.Length == 0)
158  throw new NotSupportedException("The graphic device configuration demanded is not supported.");
159 
160  var readableConfigs = new UserReadableEglConfig[configs.Length];
161 
162  // convert the configs into user readable configs
163  for (int i = 0; i < configs.Length; i++)
164  readableConfigs[i] = EglConfigToUserReadableEglConfig(configs[i]);
165 
166  return configs[0];
167  }
168 
169  public void Dispose()
170  {
171  EGLContext.Dispose();
172  EGLSurface.Dispose();
173  }
174 
175  public void SwapBuffers()
176  {
177  if (!egl.EglSwapBuffers(EGLDisplay, EGLSurface))
178  {
179  var error = egl.EglGetError();
180  if (error == 0x300e)
181  throw new InvalidOperationException(string.Format("EglSwapBuffers {0:x}", error));
182  }
183  }
184 
185  public void MakeCurrent(IWindowInfo window)
186  {
187  if (window != null)
188  {
189  if (!egl.EglMakeCurrent(EGLDisplay, EGLSurface, EGLSurface, EGLContext))
190  throw new InvalidOperationException();
191  }
192  else
193  {
194  if (!egl.EglMakeCurrent(EGLDisplay, EGL10.EglNoSurface, EGL10.EglNoSurface, EGL10.EglNoContext))
195  throw new InvalidOperationException();
196  }
197  }
198 
199  public void Update(IWindowInfo window)
200  {
201  MakeCurrent(null);
202  MakeCurrent(window);
203  }
204 
205  public void LoadAll()
206  {
207  }
208 
209  public bool IsCurrent
210  {
211  get { return (egl.EglGetCurrentContext() == EGLContext);
212  }
213  }
214 
215  public bool IsDisposed
216  {
217  get { return isDisposed; }
218  }
219 
220  public bool VSync
221  {
222  get { return false; }
223  set {}
224  }
225 
226  public int SwapInterval { get; set; }
227 
228  public GraphicsMode GraphicsMode
229  {
230  get { throw new NotImplementedException(); }
231  }
232 
233  public bool ErrorChecking
234  {
235  get { return false; }
236  set {}
237  }
238 
239  IntPtr IGraphicsContextInternal.GetAddress(string function)
240  {
241  return IntPtr.Zero;
242  }
243 
244  public IGraphicsContext Implementation
245  {
246  get { return this; }
247  }
248 
249  public ContextHandle Context
250  {
251  get { return new ContextHandle(EGLContext.Handle); }
252  }
253  }
254 }
255 #endif