Project

General

Profile

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

examples / src / main / java / org / distorted / examples / surfaceview / RenderThread.java @ 061449ed

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.graphics.Bitmap;
23
import android.graphics.BitmapFactory;
24
import android.opengl.EGL14;
25
import android.opengl.EGLSurface;
26
import android.opengl.GLES31;
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.effect.MatrixEffectScale;
34
import org.distorted.library.effect.VertexEffectDistort;
35
import org.distorted.library.main.DistortedLibrary;
36
import org.distorted.library.main.DistortedEffects;
37
import org.distorted.library.main.DistortedScreen;
38
import org.distorted.library.mesh.MeshRectangles;
39
import org.distorted.library.main.DistortedTexture;
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 implements DistortedLibrary.ExceptionListener
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 MeshRectangles mMesh;
69
  private DistortedScreen mScreen;
70
  private SurfaceView mView;
71
  private static boolean resourcesCreated = false;
72
  private Static3D mScale;
73
  private float mBmpRatio;
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76

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

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

    
85
    Static4D rLeft = new Static4D( -10/320.0f, 10/366.0f, 0, 25/320.0f);
86
    Static4D rRight= new Static4D(  10/320.0f,  5/366.0f, 0, 25/320.0f);
87

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

    
91
    dLeft.add( new Static3D(         0,         0, 0) );
92
    dLeft.add( new Static3D(-20/320.0f, 20/366.0f, 0) );
93

    
94
    dRight.add( new Static3D(         0,         0, 0) );
95
    dRight.add( new Static3D( 20/320.0f, 10/366.0f, 0) );
96

    
97
    mEffects = new DistortedEffects();
98
    mEffects.apply( new VertexEffectDistort(dLeft , pLeft , rLeft ) );
99
    mEffects.apply( new VertexEffectDistort(dRight, pRight, rRight) );
100

    
101
    mScale= new Static3D(1,1,1);
102
    mEffects.apply(new MatrixEffectScale(mScale));
103

    
104
    mScreen = new DistortedScreen();
105
    }
106

    
107
///////////////////////////////////////////////////////////////////////////////////////////////////
108

    
109
  static void setResourcesCreated()
110
    {
111
    resourcesCreated = false;
112
    }
113

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

    
116
  private static void checkGlError(String op)
117
    {
118
    int error = GLES31.glGetError();
119

    
120
    if (error != GLES31.GL_NO_ERROR)
121
      {
122
      String msg = op + ": glError 0x" + Integer.toHexString(error);
123
      Log.e(TAG, msg);
124
//    throw new RuntimeException(msg);
125
      }
126
    }
127

    
128
///////////////////////////////////////////////////////////////////////////////////////////////////
129

    
130
  @Override
131
  public void run()
132
    {
133
    Looper.prepare();
134
    mHandler = new RenderHandler(this);
135
    eglCore = new EglCore(null, EglCore.FLAG_RECORDABLE | EglCore.FLAG_TRY_GLES3);
136

    
137
    synchronized (mStartLock)
138
      {
139
      mReady = true;
140
      mStartLock.notify();    // signal waitUntilReady()
141
      }
142

    
143
    Looper.loop();
144
    Log.d(TAG, "looper quit");
145

    
146
    checkGlError("releaseGl start");
147

    
148
    if (eglSurface != null)
149
      {
150
      eglCore.releaseSurface(eglSurface);
151
      eglSurface = EGL14.EGL_NO_SURFACE;
152
      }
153

    
154
    checkGlError("releaseGl done");
155

    
156
    eglCore.makeNothingCurrent();
157
    eglCore.release();
158

    
159
    synchronized (mStartLock)
160
      {
161
      mReady = false;
162
      }
163
    }
164

    
165
///////////////////////////////////////////////////////////////////////////////////////////////////
166

    
167
  void waitUntilReady()
168
    {
169
    synchronized (mStartLock)
170
      {
171
      while (!mReady)
172
        {
173
        try
174
          {
175
          mStartLock.wait();
176
          }
177
        catch (InterruptedException ie) {  }
178
        }
179
      }
180
    }
181

    
182
///////////////////////////////////////////////////////////////////////////////////////////////////
183

    
184
  void shutdown()
185
    {
186
    Log.d(TAG, "shutdown");
187
    Looper.myLooper().quit();
188
    }
189

    
190
///////////////////////////////////////////////////////////////////////////////////////////////////
191

    
192
  RenderHandler getHandler()
193
    {
194
    return mHandler;
195
    }
196

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

    
199
  void surfaceCreated()
200
    {
201
    Log.d(TAG, "surfaceCreated");
202

    
203
    Surface surface = mSurfaceHolder.getSurface();
204

    
205
    eglSurface = eglCore.createWindowSurface(surface);
206
    eglCore.makeCurrent(eglSurface);
207

    
208
    createResources();
209
    }
210

    
211
///////////////////////////////////////////////////////////////////////////////////////////////////
212

    
213
  void surfaceChanged(int width, int height)
214
    {
215
    Log.d(TAG, "surfaceChanged " + width + "x" + height);
216

    
217
    if( width<height ) mScale.set( width,   width*mBmpRatio, 1 );
218
    else               mScale.set( height/mBmpRatio, height, 1 );
219

    
220
    mScreen.resize(width, height);
221
    }
222

    
223
///////////////////////////////////////////////////////////////////////////////////////////////////
224

    
225
  private void createResources()
226
    {
227
    resourcesCreated = true;
228

    
229
    InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
230
    Bitmap bmp;
231

    
232
    try
233
      {
234
      bmp = BitmapFactory.decodeStream(is);
235
      }
236
    finally
237
      {
238
      try
239
        {
240
        is.close();
241
        }
242
      catch(IOException io) {}
243
      }
244

    
245
    mBmpRatio = (float)bmp.getHeight()/bmp.getWidth();
246

    
247
    if( mTexture==null ) mTexture = new DistortedTexture();
248
    mTexture.setTexture(bmp);
249

    
250
    if( mMesh==null ) mMesh = new MeshRectangles(9,(int)(9*mBmpRatio));
251

    
252
    mScreen.detachAll();
253
    mScreen.attach(mTexture,mEffects,mMesh);
254

    
255
    VertexEffectDistort.enable();
256
    DistortedLibrary.onCreate(mView.getContext(), this);
257
    }
258

    
259
///////////////////////////////////////////////////////////////////////////////////////////////////
260

    
261
  public void distortedException(Exception ex)
262
    {
263
    android.util.Log.e("SurfaceView", ex.getMessage() );
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
  }
(3-3/5)