/android/LGame-Android-0.3.1/src/org/loon/framework/android/game/LGameGLOld.java

http://loon-simple.googlecode.com/ · Java · 634 lines · 502 code · 111 blank · 21 comment · 66 complexity · 17bb502fb687b5d0b64a8a6afa6f0469 MD5 · raw file

  1. package org.loon.framework.android.game;
  2. import java.io.Writer;
  3. import java.util.ArrayList;
  4. import java.util.concurrent.Semaphore;
  5. import javax.microedition.khronos.egl.EGL10;
  6. import javax.microedition.khronos.egl.EGL11;
  7. import javax.microedition.khronos.egl.EGLConfig;
  8. import javax.microedition.khronos.egl.EGLContext;
  9. import javax.microedition.khronos.egl.EGLDisplay;
  10. import javax.microedition.khronos.egl.EGLSurface;
  11. import javax.microedition.khronos.opengles.GL;
  12. import javax.microedition.khronos.opengles.GL10;
  13. import org.loon.framework.android.game.LGameAndroid2DView.GLType;
  14. import android.content.Context;
  15. import android.opengl.GLSurfaceView.EGLConfigChooser;
  16. import android.opengl.GLSurfaceView.Renderer;
  17. import android.util.AttributeSet;
  18. import android.util.Log;
  19. import android.view.SurfaceHolder;
  20. import android.view.SurfaceView;
  21. /**
  22. *
  23. * Copyright 2008 - 2011
  24. *
  25. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  26. * use this file except in compliance with the License. You may obtain a copy of
  27. * the License at
  28. *
  29. * http://www.apache.org/licenses/LICENSE-2.0
  30. *
  31. * Unless required by applicable law or agreed to in writing, software
  32. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  33. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  34. * License for the specific language governing permissions and limitations under
  35. * the License.
  36. *
  37. * @project loonframework
  38. * @author chenpeng
  39. * @email??šceponline@yahoo.com.cn
  40. * @version 0.1.1
  41. */
  42. public class LGameGLOld extends SurfaceView implements SurfaceHolder.Callback {
  43. static final Semaphore sEglSemaphore = new Semaphore(1);
  44. private GLThread mGLThread;
  45. private EGLConfigChooser mEGLConfigChooser;
  46. private GLWrapper mGLWrapper;
  47. private int mDebugFlags;
  48. private int mRenderMode;
  49. private Renderer mRenderer;
  50. private int mSurfaceWidth;
  51. private int mSurfaceHeight;
  52. private boolean mHasSurface;
  53. public final static int RENDERMODE_WHEN_DIRTY = 0;
  54. public final static int RENDERMODE_CONTINUOUSLY = 1;
  55. public final static int DEBUG_CHECK_GL_ERROR = 1;
  56. public final static int DEBUG_LOG_GL_CALLS = 2;
  57. private SurfaceHolder holder;
  58. public LGameGLOld(Context context) {
  59. super(context);
  60. init();
  61. }
  62. public LGameGLOld(Context context, AttributeSet attrs) {
  63. super(context, attrs);
  64. init();
  65. }
  66. private void init() {
  67. holder = GLType.updateSurfaceHolder(getHolder(), this);
  68. mRenderMode = RENDERMODE_CONTINUOUSLY;
  69. }
  70. public SurfaceHolder getSurfaceHolder() {
  71. return holder;
  72. }
  73. public void setGLWrapper(GLWrapper glWrapper) {
  74. mGLWrapper = glWrapper;
  75. }
  76. public void setDebugFlags(int debugFlags) {
  77. mDebugFlags = debugFlags;
  78. }
  79. public int getDebugFlags() {
  80. return mDebugFlags;
  81. }
  82. public void setRenderer(Renderer renderer) {
  83. if (mRenderer != null) {
  84. throw new IllegalStateException(
  85. "setRenderer has already been called for this instance.");
  86. }
  87. mRenderer = renderer;
  88. }
  89. public void setEGLConfigChooser(EGLConfigChooser configChooser) {
  90. if (mRenderer != null) {
  91. throw new IllegalStateException(
  92. "setRenderer has already been called for this instance.");
  93. }
  94. mEGLConfigChooser = configChooser;
  95. }
  96. public void setEGLConfigChooser(boolean needDepth) {
  97. setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));
  98. }
  99. public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,
  100. int alphaSize, int depthSize, int stencilSize) {
  101. setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,
  102. blueSize, alphaSize, depthSize, stencilSize));
  103. }
  104. public void setRenderMode(int renderMode) {
  105. mRenderMode = renderMode;
  106. if (mGLThread != null) {
  107. mGLThread.setRenderMode(renderMode);
  108. }
  109. }
  110. public int getRenderMode() {
  111. return mRenderMode;
  112. }
  113. public void requestRender() {
  114. mGLThread.requestRender();
  115. }
  116. public void surfaceCreated(SurfaceHolder holder) {
  117. if (mGLThread != null) {
  118. mGLThread.surfaceCreated();
  119. }
  120. mHasSurface = true;
  121. }
  122. public void surfaceDestroyed(SurfaceHolder holder) {
  123. if (mGLThread != null) {
  124. mGLThread.surfaceDestroyed();
  125. }
  126. mHasSurface = false;
  127. }
  128. public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
  129. if (mGLThread != null) {
  130. mGLThread.onWindowResize(w, h);
  131. }
  132. mSurfaceWidth = w;
  133. mSurfaceHeight = h;
  134. }
  135. public void onPause() {
  136. mGLThread.onPause();
  137. mGLThread.requestExitAndWait();
  138. mGLThread = null;
  139. }
  140. public void onResume() {
  141. if (mEGLConfigChooser == null) {
  142. mEGLConfigChooser = new SimpleEGLConfigChooser(true);
  143. }
  144. mGLThread = new GLThread(mRenderer);
  145. mGLThread.start();
  146. mGLThread.setRenderMode(mRenderMode);
  147. if (mHasSurface) {
  148. mGLThread.surfaceCreated();
  149. }
  150. if (mSurfaceWidth > 0 && mSurfaceHeight > 0) {
  151. mGLThread.onWindowResize(mSurfaceWidth, mSurfaceHeight);
  152. }
  153. mGLThread.onResume();
  154. }
  155. public void queueEvent(Runnable r) {
  156. if (mGLThread != null) {
  157. mGLThread.queueEvent(r);
  158. }
  159. }
  160. public interface GLWrapper {
  161. GL wrap(GL gl);
  162. }
  163. private static abstract class BaseConfigChooser implements EGLConfigChooser {
  164. public BaseConfigChooser(int[] configSpec) {
  165. mConfigSpec = configSpec;
  166. }
  167. public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
  168. int[] num_config = new int[1];
  169. egl.eglChooseConfig(display, mConfigSpec, null, 0, num_config);
  170. int numConfigs = num_config[0];
  171. if (numConfigs <= 0) {
  172. throw new IllegalArgumentException(
  173. "No configs match configSpec");
  174. }
  175. EGLConfig[] configs = new EGLConfig[numConfigs];
  176. egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
  177. num_config);
  178. EGLConfig config = chooseConfig(egl, display, configs);
  179. if (config == null) {
  180. throw new IllegalArgumentException("No config chosen");
  181. }
  182. return config;
  183. }
  184. abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
  185. EGLConfig[] configs);
  186. protected int[] mConfigSpec;
  187. }
  188. private static class ComponentSizeChooser extends BaseConfigChooser {
  189. public ComponentSizeChooser(int redSize, int greenSize, int blueSize,
  190. int alphaSize, int depthSize, int stencilSize) {
  191. super(new int[] { EGL10.EGL_RED_SIZE, redSize,
  192. EGL10.EGL_GREEN_SIZE, greenSize, EGL10.EGL_BLUE_SIZE,
  193. blueSize, EGL10.EGL_ALPHA_SIZE, alphaSize,
  194. EGL10.EGL_DEPTH_SIZE, depthSize, EGL10.EGL_STENCIL_SIZE,
  195. stencilSize, EGL10.EGL_NONE });
  196. mValue = new int[1];
  197. mRedSize = redSize;
  198. mGreenSize = greenSize;
  199. mBlueSize = blueSize;
  200. mAlphaSize = alphaSize;
  201. mDepthSize = depthSize;
  202. mStencilSize = stencilSize;
  203. }
  204. @Override
  205. public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
  206. EGLConfig[] configs) {
  207. EGLConfig closestConfig = null;
  208. int closestDistance = 1000;
  209. for (EGLConfig config : configs) {
  210. int r = findConfigAttrib(egl, display, config,
  211. EGL10.EGL_RED_SIZE, 0);
  212. int g = findConfigAttrib(egl, display, config,
  213. EGL10.EGL_GREEN_SIZE, 0);
  214. int b = findConfigAttrib(egl, display, config,
  215. EGL10.EGL_BLUE_SIZE, 0);
  216. int a = findConfigAttrib(egl, display, config,
  217. EGL10.EGL_ALPHA_SIZE, 0);
  218. int d = findConfigAttrib(egl, display, config,
  219. EGL10.EGL_DEPTH_SIZE, 0);
  220. int s = findConfigAttrib(egl, display, config,
  221. EGL10.EGL_STENCIL_SIZE, 0);
  222. int distance = Math.abs(r - mRedSize)
  223. + Math.abs(g - mGreenSize) + Math.abs(b - mBlueSize)
  224. + Math.abs(a - mAlphaSize) + Math.abs(d - mDepthSize)
  225. + Math.abs(s - mStencilSize);
  226. if (distance < closestDistance) {
  227. closestDistance = distance;
  228. closestConfig = config;
  229. }
  230. }
  231. return closestConfig;
  232. }
  233. private int findConfigAttrib(EGL10 egl, EGLDisplay display,
  234. EGLConfig config, int attribute, int defaultValue) {
  235. if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
  236. return mValue[0];
  237. }
  238. return defaultValue;
  239. }
  240. private int[] mValue;
  241. protected int mRedSize;
  242. protected int mGreenSize;
  243. protected int mBlueSize;
  244. protected int mAlphaSize;
  245. protected int mDepthSize;
  246. protected int mStencilSize;
  247. }
  248. private static class SimpleEGLConfigChooser extends ComponentSizeChooser {
  249. public SimpleEGLConfigChooser(boolean withDepthBuffer) {
  250. super(4, 4, 4, 0, withDepthBuffer ? 16 : 0, 0);
  251. mRedSize = 5;
  252. mGreenSize = 6;
  253. mBlueSize = 5;
  254. }
  255. }
  256. private class EglHelper {
  257. public EglHelper() {
  258. }
  259. public void start() {
  260. mEgl = (EGL10) EGLContext.getEGL();
  261. mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
  262. int[] version = new int[2];
  263. mEgl.eglInitialize(mEglDisplay, version);
  264. mEglConfig = mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);
  265. mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig,
  266. EGL10.EGL_NO_CONTEXT, null);
  267. mEglSurface = null;
  268. }
  269. public GL createSurface(SurfaceHolder holder) {
  270. if (mEglSurface != null) {
  271. mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
  272. EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
  273. mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
  274. }
  275. mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig,
  276. holder, null);
  277. mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
  278. mEglContext);
  279. GL gl = mEglContext.getGL();
  280. if (mGLWrapper != null) {
  281. gl = mGLWrapper.wrap(gl);
  282. }
  283. return gl;
  284. }
  285. public boolean swap() {
  286. mEgl.eglSwapBuffers(mEglDisplay, mEglSurface);
  287. return mEgl.eglGetError() != EGL11.EGL_CONTEXT_LOST;
  288. }
  289. public void finish() {
  290. if (mEglSurface != null) {
  291. mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
  292. EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
  293. mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
  294. mEglSurface = null;
  295. }
  296. if (mEglContext != null) {
  297. mEgl.eglDestroyContext(mEglDisplay, mEglContext);
  298. mEglContext = null;
  299. }
  300. if (mEglDisplay != null) {
  301. mEgl.eglTerminate(mEglDisplay);
  302. mEglDisplay = null;
  303. }
  304. }
  305. EGL10 mEgl;
  306. EGLDisplay mEglDisplay;
  307. EGLSurface mEglSurface;
  308. EGLConfig mEglConfig;
  309. EGLContext mEglContext;
  310. }
  311. class GLThread extends Thread {
  312. GLThread(Renderer renderer) {
  313. super();
  314. mDone = false;
  315. mWidth = 0;
  316. mHeight = 0;
  317. mRequestRender = true;
  318. mRenderMode = RENDERMODE_CONTINUOUSLY;
  319. mRenderer = renderer;
  320. mSizeChanged = true;
  321. setName("GLThread");
  322. }
  323. @Override
  324. public void run() {
  325. try {
  326. try {
  327. sEglSemaphore.acquire();
  328. } catch (InterruptedException e) {
  329. return;
  330. }
  331. guardedRun();
  332. } catch (InterruptedException e) {
  333. } finally {
  334. sEglSemaphore.release();
  335. }
  336. }
  337. private void guardedRun() throws InterruptedException {
  338. mEglHelper = new EglHelper();
  339. mEglHelper.start();
  340. GL10 gl = null;
  341. boolean tellRendererSurfaceCreated = true;
  342. boolean tellRendererSurfaceChanged = true;
  343. while (!mDone) {
  344. int w, h;
  345. boolean changed;
  346. boolean needStart = false;
  347. synchronized (this) {
  348. Runnable r;
  349. while ((r = getEvent()) != null) {
  350. r.run();
  351. }
  352. if (mPaused) {
  353. mEglHelper.finish();
  354. needStart = true;
  355. }
  356. while (needToWait()) {
  357. wait();
  358. }
  359. if (mDone) {
  360. break;
  361. }
  362. changed = mSizeChanged;
  363. w = mWidth;
  364. h = mHeight;
  365. mSizeChanged = false;
  366. mRequestRender = false;
  367. }
  368. if (needStart) {
  369. mEglHelper.start();
  370. tellRendererSurfaceCreated = true;
  371. changed = true;
  372. }
  373. if (changed) {
  374. gl = (GL10) mEglHelper.createSurface(getHolder());
  375. tellRendererSurfaceChanged = true;
  376. }
  377. if (tellRendererSurfaceCreated) {
  378. mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
  379. tellRendererSurfaceCreated = false;
  380. }
  381. if (tellRendererSurfaceChanged) {
  382. mRenderer.onSurfaceChanged(gl, w, h);
  383. tellRendererSurfaceChanged = false;
  384. }
  385. if ((w > 0) && (h > 0)) {
  386. mRenderer.onDrawFrame(gl);
  387. mEglHelper.swap();
  388. }
  389. }
  390. mEglHelper.finish();
  391. }
  392. private boolean needToWait() {
  393. if (mDone) {
  394. return false;
  395. }
  396. if (mPaused || (!mHasSurface)) {
  397. return true;
  398. }
  399. if ((mWidth > 0)
  400. && (mHeight > 0)
  401. && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY))) {
  402. return false;
  403. }
  404. return true;
  405. }
  406. public void setRenderMode(int renderMode) {
  407. if (!((RENDERMODE_WHEN_DIRTY <= renderMode) && (renderMode <= RENDERMODE_CONTINUOUSLY))) {
  408. throw new IllegalArgumentException("renderMode");
  409. }
  410. synchronized (this) {
  411. mRenderMode = renderMode;
  412. if (renderMode == RENDERMODE_CONTINUOUSLY) {
  413. notify();
  414. }
  415. }
  416. }
  417. public int getRenderMode() {
  418. synchronized (this) {
  419. return mRenderMode;
  420. }
  421. }
  422. public void requestRender() {
  423. synchronized (this) {
  424. mRequestRender = true;
  425. notify();
  426. }
  427. }
  428. public void surfaceCreated() {
  429. synchronized (this) {
  430. mHasSurface = true;
  431. notify();
  432. }
  433. }
  434. public void surfaceDestroyed() {
  435. synchronized (this) {
  436. mHasSurface = false;
  437. notify();
  438. }
  439. }
  440. public void onPause() {
  441. synchronized (this) {
  442. mPaused = true;
  443. }
  444. }
  445. public void onResume() {
  446. synchronized (this) {
  447. mPaused = false;
  448. notify();
  449. }
  450. }
  451. public void onWindowResize(int w, int h) {
  452. synchronized (this) {
  453. mWidth = w;
  454. mHeight = h;
  455. mSizeChanged = true;
  456. notify();
  457. }
  458. }
  459. public void requestExitAndWait() {
  460. synchronized (this) {
  461. mDone = true;
  462. notify();
  463. }
  464. try {
  465. join();
  466. } catch (InterruptedException ex) {
  467. Thread.currentThread().interrupt();
  468. }
  469. }
  470. public void queueEvent(Runnable r) {
  471. synchronized (this) {
  472. mEventQueue.add(r);
  473. }
  474. }
  475. private Runnable getEvent() {
  476. synchronized (this) {
  477. if (mEventQueue.size() > 0) {
  478. return mEventQueue.remove(0);
  479. }
  480. }
  481. return null;
  482. }
  483. private boolean mDone;
  484. private boolean mPaused;
  485. private boolean mHasSurface;
  486. private int mWidth;
  487. private int mHeight;
  488. private int mRenderMode;
  489. private boolean mRequestRender;
  490. private Renderer mRenderer;
  491. private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();
  492. private EglHelper mEglHelper;
  493. private boolean mSizeChanged;
  494. }
  495. static class LogWriter extends Writer {
  496. @Override
  497. public void close() {
  498. flushBuilder();
  499. }
  500. @Override
  501. public void flush() {
  502. flushBuilder();
  503. }
  504. @Override
  505. public void write(char[] buf, int offset, int count) {
  506. for (int i = 0; i < count; i++) {
  507. char c = buf[offset + i];
  508. if (c == '\n') {
  509. flushBuilder();
  510. } else {
  511. mBuilder.append(c);
  512. }
  513. }
  514. }
  515. private void flushBuilder() {
  516. if (mBuilder.length() > 0) {
  517. Log.v("GLSurfaceView", mBuilder.toString());
  518. mBuilder.delete(0, mBuilder.length());
  519. }
  520. }
  521. private StringBuilder mBuilder = new StringBuilder();
  522. }
  523. }