Project

General

Profile

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

examples / src / main / java / org / distorted / examples / surfaceview / RenderThread.java @ 30f337e5

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.surfaceview;
21

    
22
import android.app.ActivityManager;
23
import android.content.Context;
24
import android.content.pm.ConfigurationInfo;
25
import android.content.res.Resources;
26
import android.graphics.Bitmap;
27
import android.graphics.BitmapFactory;
28
import android.opengl.EGL14;
29
import android.opengl.EGLSurface;
30
import android.opengl.GLES31;
31
import android.os.Looper;
32
import android.util.Log;
33
import android.view.Surface;
34
import android.view.SurfaceHolder;
35
import android.view.SurfaceView;
36

    
37
import org.distorted.library.effect.MatrixEffectScale;
38
import org.distorted.library.effect.VertexEffectDistort;
39
import org.distorted.library.main.DistortedLibrary;
40
import org.distorted.library.main.DistortedEffects;
41
import org.distorted.library.main.DistortedScreen;
42
import org.distorted.library.mesh.MeshSquare;
43
import org.distorted.library.main.DistortedTexture;
44
import org.distorted.library.type.Dynamic3D;
45
import org.distorted.library.type.Static3D;
46
import org.distorted.library.type.Static4D;
47
import org.distorted.examples.R;
48

    
49
import java.io.IOException;
50
import java.io.InputStream;
51

    
52
///////////////////////////////////////////////////////////////////////////////////////////////////
53

    
54
class RenderThread extends Thread implements DistortedLibrary.LibraryUser
55
  {
56
  private static final String TAG = "RenderThread";
57

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

    
63
  // Used to wait for the thread to start.
64
  private final Object mStartLock = new Object();
65
  private final Static3D mScale;
66
  private final DistortedEffects mEffects;
67
  private final DistortedScreen mScreen;
68
  private final SurfaceView mView;
69
  private final Resources mResources;
70

    
71
  private EglCore eglCore;
72
  private EGLSurface eglSurface;
73
  private DistortedTexture mTexture;
74
  private MeshSquare mMesh;
75
  private final SurfaceHolder mSurfaceHolder;  // may be updated by UI thread
76
  private float mBmpRatio;
77
  private boolean mReady = false;
78

    
79
  private static boolean resourcesCreated = false;
80

    
81
///////////////////////////////////////////////////////////////////////////////////////////////////
82

    
83
  RenderThread(SurfaceHolder holder, SurfaceView view)
84
    {
85
    mSurfaceHolder = holder;
86
    mView = view;
87
    mResources = view.getResources();
88

    
89
    Static3D pLeft = new Static3D( ( 90-320*0.5f)/320.0f, (108-366*0.5f)/366.0f, 0);
90
    Static3D pRight= new Static3D( (176-320*0.5f)/320.0f, (111-366*0.5f)/366.0f, 0);
91

    
92
    Static4D rLeft = new Static4D( -10/320.0f, 10/366.0f, 0, 25/320.0f);
93
    Static4D rRight= new Static4D(  10/320.0f,  5/366.0f, 0, 25/320.0f);
94

    
95
    Dynamic3D dLeft = new Dynamic3D(1000,0.0f);
96
    Dynamic3D dRight= new Dynamic3D(1000,0.0f);
97

    
98
    dLeft.add( new Static3D(         0,         0, 0) );
99
    dLeft.add( new Static3D(-20/320.0f, 20/366.0f, 0) );
100

    
101
    dRight.add( new Static3D(         0,         0, 0) );
102
    dRight.add( new Static3D( 20/320.0f, 10/366.0f, 0) );
103

    
104
    mEffects = new DistortedEffects();
105
    mEffects.apply( new VertexEffectDistort(dLeft , pLeft , rLeft ) );
106
    mEffects.apply( new VertexEffectDistort(dRight, pRight, rRight) );
107

    
108
    mScale= new Static3D(1,1,1);
109
    mEffects.apply(new MatrixEffectScale(mScale));
110

    
111
    mScreen = new DistortedScreen();
112
    }
113

    
114
///////////////////////////////////////////////////////////////////////////////////////////////////
115

    
116
  static void setResourcesCreated()
117
    {
118
    resourcesCreated = false;
119
    }
120

    
121
///////////////////////////////////////////////////////////////////////////////////////////////////
122

    
123
  private static void checkGlError(String op)
124
    {
125
    int error = GLES31.glGetError();
126

    
127
    if (error != GLES31.GL_NO_ERROR)
128
      {
129
      String msg = op + ": glError 0x" + Integer.toHexString(error);
130
      Log.e(TAG, msg);
131
//    throw new RuntimeException(msg);
132
      }
133
    }
134

    
135
///////////////////////////////////////////////////////////////////////////////////////////////////
136

    
137
  @Override
138
  public void run()
139
    {
140
    Looper.prepare();
141
    mHandler = new RenderHandler(this);
142
    eglCore = new EglCore(null, EglCore.FLAG_RECORDABLE | EglCore.FLAG_TRY_GLES3);
143

    
144
    synchronized (mStartLock)
145
      {
146
      mReady = true;
147
      mStartLock.notify();    // signal waitUntilReady()
148
      }
149

    
150
    Looper.loop();
151
    Log.d(TAG, "looper quit");
152

    
153
    checkGlError("releaseGl start");
154

    
155
    if (eglSurface != null)
156
      {
157
      eglCore.releaseSurface(eglSurface);
158
      eglSurface = EGL14.EGL_NO_SURFACE;
159
      }
160

    
161
    checkGlError("releaseGl done");
162

    
163
    eglCore.makeNothingCurrent();
164
    eglCore.release();
165

    
166
    synchronized (mStartLock)
167
      {
168
      mReady = false;
169
      }
170
    }
171

    
172
///////////////////////////////////////////////////////////////////////////////////////////////////
173

    
174
  void waitUntilReady()
175
    {
176
    synchronized (mStartLock)
177
      {
178
      while (!mReady)
179
        {
180
        try
181
          {
182
          mStartLock.wait();
183
          }
184
        catch (InterruptedException ignored) {  }
185
        }
186
      }
187
    }
188

    
189
///////////////////////////////////////////////////////////////////////////////////////////////////
190

    
191
  void shutdown()
192
    {
193
    Log.d(TAG, "shutdown");
194
    Looper.myLooper().quit();
195
    }
196

    
197
///////////////////////////////////////////////////////////////////////////////////////////////////
198

    
199
  RenderHandler getHandler()
200
    {
201
    return mHandler;
202
    }
203

    
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205

    
206
  void surfaceCreated()
207
    {
208
    Log.d(TAG, "surfaceCreated");
209

    
210
    Surface surface = mSurfaceHolder.getSurface();
211

    
212
    eglSurface = eglCore.createWindowSurface(surface);
213
    eglCore.makeCurrent(eglSurface);
214

    
215
    createResources();
216
    }
217

    
218
///////////////////////////////////////////////////////////////////////////////////////////////////
219

    
220
  void surfaceChanged(int width, int height)
221
    {
222
    Log.d(TAG, "surfaceChanged " + width + "x" + height);
223

    
224
    if( width<height ) mScale.set( width,   width*mBmpRatio, 1 );
225
    else               mScale.set( height/mBmpRatio, height, 1 );
226

    
227
    mScreen.resize(width, height);
228
    }
229

    
230
///////////////////////////////////////////////////////////////////////////////////////////////////
231

    
232
  private void createResources()
233
    {
234
    resourcesCreated = true;
235

    
236
    InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
237
    Bitmap bmp;
238

    
239
    try
240
      {
241
      bmp = BitmapFactory.decodeStream(is);
242
      }
243
    finally
244
      {
245
      try
246
        {
247
        is.close();
248
        }
249
      catch(IOException ignored) {}
250
      }
251

    
252
    mBmpRatio = (float)bmp.getHeight()/bmp.getWidth();
253

    
254
    if( mTexture==null ) mTexture = new DistortedTexture();
255
    mTexture.setTexture(bmp);
256

    
257
    if( mMesh==null ) mMesh = new MeshSquare(9,(int)(9*mBmpRatio));
258

    
259
    mScreen.detachAll();
260
    mScreen.attach(mTexture,mEffects,mMesh);
261

    
262
    VertexEffectDistort.enable();
263
    DistortedLibrary.onSurfaceCreated(this);
264
    }
265

    
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267

    
268
  void doFrame(long frameTimeNs)
269
    {
270
    // We can still get here after onPaused - ignore such calls.
271
    if( SurfaceViewSurfaceView.isPaused() )
272
      {
273
      android.util.Log.e("Thread", "Got here after onPaused- ignoring frame draw call!!");
274
      return;
275
      }
276

    
277
    // This will happen if we just briefly went into the background (press 'POWER')
278
    // Then surfaceCreated/changed is not called
279
    if( !resourcesCreated )
280
      {
281
      Log.e("Thread", "resources not created!!");
282
      createResources();
283
      }
284

    
285
    eglCore.makeCurrent(eglSurface);
286
    mScreen.render( frameTimeNs/1000000 );  // 1 nanosecond = 1 millisecond / 10^-6
287
    eglCore.swapBuffers(eglSurface);
288
    }
289

    
290
///////////////////////////////////////////////////////////////////////////////////////////////////
291

    
292
  public void distortedException(Exception ex)
293
    {
294
    android.util.Log.e("SurfaceView", ex.getMessage() );
295
    }
296

    
297
///////////////////////////////////////////////////////////////////////////////////////////////////
298

    
299
  public InputStream localFile(int fileID)
300
    {
301
    return mResources.openRawResource(fileID);
302
    }
303

    
304
///////////////////////////////////////////////////////////////////////////////////////////////////
305

    
306
  public void logMessage(String message)
307
    {
308
    android.util.Log.e("SurfaceView", message );
309
    }
310
  }
(3-3/5)