Project

General

Profile

Download (9.22 KB) Statistics
| Branch: | Revision:

examples / src / main / java / org / distorted / examples / plainmonalisa / RenderThread.java @ 01782e85

1
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19

    
20
package org.distorted.examples.plainmonalisa;
21

    
22
import android.graphics.Bitmap;
23
import android.graphics.BitmapFactory;
24
import android.opengl.EGL14;
25
import android.opengl.EGLSurface;
26
import android.opengl.GLES30;
27
import android.os.Looper;
28
import android.util.Log;
29
import android.view.Surface;
30
import android.view.SurfaceHolder;
31
import android.view.SurfaceView;
32

    
33
import org.distorted.library.main.Distorted;
34
import org.distorted.library.main.DistortedEffects;
35
import org.distorted.library.main.DistortedScreen;
36
import org.distorted.library.EffectNames;
37
import org.distorted.library.main.MeshFlat;
38
import org.distorted.library.main.DistortedTexture;
39
import org.distorted.library.EffectTypes;
40
import org.distorted.library.type.Dynamic3D;
41
import org.distorted.library.type.Static3D;
42
import org.distorted.library.type.Static4D;
43
import org.distorted.examples.R;
44

    
45
import java.io.IOException;
46
import java.io.InputStream;
47

    
48
///////////////////////////////////////////////////////////////////////////////////////////////////
49

    
50
class RenderThread extends Thread
51
  {
52
  private static final String TAG = "RenderThread";
53

    
54
  // Object must be created on render thread to get correct Looper, but is used from
55
  // UI thread, so we need to declare it volatile to ensure the UI thread sees a fully
56
  // constructed object.
57
  private volatile RenderHandler mHandler;
58

    
59
  // Used to wait for the thread to start.
60
  private final Object mStartLock = new Object();
61
  private boolean mReady = false;
62
  private volatile SurfaceHolder mSurfaceHolder;  // may be updated by UI thread
63
  private EglCore eglCore;
64
  private EGLSurface eglSurface;
65

    
66
  private DistortedEffects mEffects;
67
  private DistortedTexture mTexture;
68
  private MeshFlat mMesh;
69
  private DistortedScreen mScreen;
70
  private int bmpHeight, bmpWidth;
71
  private SurfaceView mView;
72
  private static boolean resourcesCreated = false;
73

    
74
///////////////////////////////////////////////////////////////////////////////////////////////////
75

    
76
  RenderThread(SurfaceHolder holder, SurfaceView view)
77
    {
78
    mSurfaceHolder = holder;
79
    mView = view;
80

    
81
    Static3D pLeft = new Static3D( 90, 258, 0);
82
    Static3D pRight= new Static3D(176, 255, 0);
83

    
84
    Static4D rLeft = new Static4D(-10,-10,25,25);
85
    Static4D rRight= new Static4D( 10, -5,25,25);
86

    
87
    Dynamic3D dLeft = new Dynamic3D(1000,0.0f);
88
    Dynamic3D dRight= new Dynamic3D(1000,0.0f);
89

    
90
    dLeft.add( new Static3D(  0,  0,0) );
91
    dLeft.add( new Static3D(-20,-20,0) );
92

    
93
    dRight.add( new Static3D(  0,  0,0) );
94
    dRight.add( new Static3D( 20,-10,0) );
95

    
96
    mEffects = new DistortedEffects();
97
    mEffects.distort( dLeft, pLeft , rLeft );
98
    mEffects.distort(dRight, pRight, rRight);
99

    
100
    mScreen = new DistortedScreen(null);
101
    }
102

    
103
///////////////////////////////////////////////////////////////////////////////////////////////////
104

    
105
  static void setResourcesCreated()
106
    {
107
    resourcesCreated = false;
108
    }
109

    
110
///////////////////////////////////////////////////////////////////////////////////////////////////
111

    
112
  private static void checkGlError(String op)
113
    {
114
    int error = GLES30.glGetError();
115

    
116
    if (error != GLES30.GL_NO_ERROR)
117
      {
118
      String msg = op + ": glError 0x" + Integer.toHexString(error);
119
      Log.e(TAG, msg);
120
//      throw new RuntimeException(msg);
121
      }
122
    }
123

    
124
///////////////////////////////////////////////////////////////////////////////////////////////////
125

    
126
  @Override
127
  public void run()
128
    {
129
    Looper.prepare();
130
    mHandler = new RenderHandler(this);
131
    eglCore = new EglCore(null, EglCore.FLAG_RECORDABLE | EglCore.FLAG_TRY_GLES3);
132

    
133
    synchronized (mStartLock)
134
      {
135
      mReady = true;
136
      mStartLock.notify();    // signal waitUntilReady()
137
      }
138

    
139
    Looper.loop();
140
    Log.d(TAG, "looper quit");
141

    
142
    checkGlError("releaseGl start");
143

    
144
    if (eglSurface != null)
145
      {
146
      eglCore.releaseSurface(eglSurface);
147
      eglSurface = EGL14.EGL_NO_SURFACE;
148
      }
149

    
150
    checkGlError("releaseGl done");
151

    
152
    eglCore.makeNothingCurrent();
153
    eglCore.release();
154

    
155
    synchronized (mStartLock)
156
      {
157
      mReady = false;
158
      }
159
    }
160

    
161
///////////////////////////////////////////////////////////////////////////////////////////////////
162

    
163
  void waitUntilReady()
164
    {
165
    synchronized (mStartLock)
166
      {
167
      while (!mReady)
168
        {
169
        try
170
          {
171
          mStartLock.wait();
172
          }
173
        catch (InterruptedException ie) {  }
174
        }
175
      }
176
    }
177

    
178
///////////////////////////////////////////////////////////////////////////////////////////////////
179

    
180
  void shutdown()
181
    {
182
    Log.d(TAG, "shutdown");
183
    Looper.myLooper().quit();
184
    }
185

    
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187

    
188
  RenderHandler getHandler()
189
    {
190
    return mHandler;
191
    }
192

    
193
///////////////////////////////////////////////////////////////////////////////////////////////////
194

    
195
  void surfaceCreated()
196
    {
197
    Log.d(TAG, "surfaceCreated");
198

    
199
    Surface surface = mSurfaceHolder.getSurface();
200

    
201
    eglSurface = eglCore.createWindowSurface(surface);
202
    eglCore.makeCurrent(eglSurface);
203

    
204
    createResources();
205
    }
206

    
207
///////////////////////////////////////////////////////////////////////////////////////////////////
208

    
209
  void surfaceChanged(int width, int height)
210
    {
211
    Log.d(TAG, "surfaceChanged " + width + "x" + height);
212

    
213
    mEffects.abortEffects(EffectTypes.MATRIX);
214

    
215
    if( (float)bmpHeight/bmpWidth > (float)height/width )
216
      {
217
      int w = (height*bmpWidth)/bmpHeight;
218
      float factor = (float)height/bmpHeight;
219

    
220
      mEffects.move( new Static3D((width-w)/2,0,0) );
221
      mEffects.scale( factor );
222
      }
223
    else
224
      {
225
      int h = (width*bmpHeight)/bmpWidth;
226
      float factor = (float)width/bmpWidth;
227

    
228
      mEffects.move( new Static3D(0,(height-h)/2,0) );
229
      mEffects.scale( factor );
230
      }
231

    
232
    mScreen.resize(width, height);
233
    }
234

    
235
///////////////////////////////////////////////////////////////////////////////////////////////////
236

    
237
  void createResources()
238
    {
239
    resourcesCreated = true;
240

    
241
    InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
242
    Bitmap bmp;
243

    
244
    try
245
      {
246
      bmp = BitmapFactory.decodeStream(is);
247
      }
248
    finally
249
      {
250
      try
251
        {
252
        is.close();
253
        }
254
      catch(IOException io) {}
255
      }
256

    
257
    bmpHeight = bmp.getHeight();
258
    bmpWidth  = bmp.getWidth();
259

    
260
    if( mTexture==null ) mTexture = new DistortedTexture(bmpWidth,bmpHeight);
261
    mTexture.setTexture(bmp);
262

    
263
    if( mMesh==null ) mMesh = new MeshFlat(9,9*bmpHeight/bmpWidth);
264

    
265
    mScreen.detachAll();
266
    mScreen.attach(mTexture,mEffects,mMesh);
267

    
268
    DistortedEffects.enableEffect(EffectNames.DISTORT);
269

    
270
    try
271
      {
272
      Distorted.onCreate(mView.getContext());
273
      }
274
    catch(Exception ex)
275
      {
276
      Log.e("PlainMonaLisa", ex.getMessage() );
277
      }
278
    }
279

    
280
///////////////////////////////////////////////////////////////////////////////////////////////////
281

    
282
  void doFrame(long frameTimeNs)
283
    {
284
    // We can still get here after onPaused - ignore such calls.
285
    if( PlainMonaLisaSurfaceView.isPaused() )
286
      {
287
      android.util.Log.e("Thread", "Got here after onPaused- ignoring frame draw call!!");
288
      return;
289
      }
290

    
291
    // This will happen if we just briefly went into the background (press 'POWER')
292
    // Then surfaceCreated/changed is not called
293
    if( !resourcesCreated )
294
      {
295
      Log.e("Thread", "resources not created!!");
296
      createResources();
297
      }
298

    
299
    eglCore.makeCurrent(eglSurface);
300
    mScreen.render( frameTimeNs/1000000 );  // 1 nanosecond = 1 millisecond / 10^-6
301
    eglCore.swapBuffers(eglSurface);
302
    }
303

    
304
  }
(5-5/5)