Project

General

Profile

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

examples / src / main / java / org / distorted / examples / surfaceview / RenderThread.java @ 627e0ea2

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
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

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

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

    
81
    Static3D pLeft = new Static3D( 90-320/2, 108-366/2,0);
82
    Static3D pRight= new Static3D(176-320/2, 111-366/2,0);
83

    
84
    Static4D rLeft = new Static4D(-10, 10, 0,25);
85
    Static4D rRight= new Static4D( 10,  5, 0,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.apply( new VertexEffectDistort(dLeft , pLeft , rLeft ) );
98
    mEffects.apply( new VertexEffectDistort(dRight, pRight, rRight) );
99

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

    
103
    mScreen = new DistortedScreen();
104
    }
105

    
106
///////////////////////////////////////////////////////////////////////////////////////////////////
107

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

    
113
///////////////////////////////////////////////////////////////////////////////////////////////////
114

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

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

    
127
///////////////////////////////////////////////////////////////////////////////////////////////////
128

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

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

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

    
145
    checkGlError("releaseGl start");
146

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

    
153
    checkGlError("releaseGl done");
154

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

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

    
164
///////////////////////////////////////////////////////////////////////////////////////////////////
165

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

    
181
///////////////////////////////////////////////////////////////////////////////////////////////////
182

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

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

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

    
196
///////////////////////////////////////////////////////////////////////////////////////////////////
197

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

    
202
    Surface surface = mSurfaceHolder.getSurface();
203

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

    
207
    createResources();
208
    }
209

    
210
///////////////////////////////////////////////////////////////////////////////////////////////////
211

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

    
216
    float horiRatio = (float)width / mTexture.getWidth();
217
    float vertRatio = (float)height/ mTexture.getHeight();
218
    float factor    = horiRatio > vertRatio ? vertRatio : horiRatio;
219

    
220
    mScale.set( factor,factor,factor );
221
    mScreen.resize(width, height);
222
    }
223

    
224
///////////////////////////////////////////////////////////////////////////////////////////////////
225

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

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

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

    
246
    int bmpHeight = bmp.getHeight();
247
    int bmpWidth  = bmp.getWidth();
248

    
249
    if( mTexture==null ) mTexture = new DistortedTexture();
250
    mTexture.setTexture(bmp);
251

    
252
    if( mMesh==null )
253
      {
254
      mMesh = new MeshRectangles(9,9*bmpHeight/bmpWidth);
255
      mMesh.setStretch(bmpWidth,bmpHeight,0);
256
      }
257

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

    
261
    VertexEffectDistort.enable();
262

    
263
    try
264
      {
265
      DistortedLibrary.onCreate(mView.getContext());
266
      }
267
    catch(Exception ex)
268
      {
269
      Log.e("PlainMonaLisa", ex.getMessage() );
270
      }
271
    }
272

    
273
///////////////////////////////////////////////////////////////////////////////////////////////////
274

    
275
  void doFrame(long frameTimeNs)
276
    {
277
    // We can still get here after onPaused - ignore such calls.
278
    if( SurfaceViewSurfaceView.isPaused() )
279
      {
280
      android.util.Log.e("Thread", "Got here after onPaused- ignoring frame draw call!!");
281
      return;
282
      }
283

    
284
    // This will happen if we just briefly went into the background (press 'POWER')
285
    // Then surfaceCreated/changed is not called
286
    if( !resourcesCreated )
287
      {
288
      Log.e("Thread", "resources not created!!");
289
      createResources();
290
      }
291

    
292
    eglCore.makeCurrent(eglSurface);
293
    mScreen.render( frameTimeNs/1000000 );  // 1 nanosecond = 1 millisecond / 10^-6
294
    eglCore.swapBuffers(eglSurface);
295
    }
296

    
297
  }
(3-3/5)