Project

General

Profile

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

examples / src / main / java / org / distorted / examples / plainmonalisa / RenderThread.java @ 89a0d841

1
package org.distorted.examples.plainmonalisa;
2

    
3
import android.graphics.Bitmap;
4
import android.graphics.BitmapFactory;
5
import android.opengl.EGL14;
6
import android.opengl.EGLSurface;
7
import android.opengl.GLES20;
8
import android.os.Looper;
9
import android.os.Trace;
10
import android.util.Log;
11
import android.view.Surface;
12
import android.view.SurfaceHolder;
13
import android.view.SurfaceView;
14

    
15
import org.distorted.library.Distorted;
16
import org.distorted.library.DistortedBitmap;
17
import org.distorted.library.Float2D;
18
import org.distorted.library.Float3D;
19
import org.distorted.library.Float4D;
20
import org.distorted.examples.R;
21

    
22
import java.io.IOException;
23
import java.io.InputStream;
24

    
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26
/**
27
 * This class handles all OpenGL rendering.
28
 * <p>
29
 * Start the render thread after the Surface has been created.
30
 */
31
public class RenderThread extends Thread
32
  {
33
  private static final String TAG = "RenderThread";
34

    
35
  // Object must be created on render thread to get correct Looper, but is used from
36
  // UI thread, so we need to declare it volatile to ensure the UI thread sees a fully
37
  // constructed object.
38
  private volatile RenderHandler mHandler;
39

    
40
  // Used to wait for the thread to start.
41
  private Object mStartLock = new Object();
42
  private boolean mReady = false;
43
  private volatile SurfaceHolder mSurfaceHolder;  // may be updated by UI thread
44
  private EglCore eglCore;
45
  private EGLSurface eglSurface;
46

    
47
  private DistortedBitmap monaLisa;
48
  private int bmpHeight, bmpWidth;
49

    
50
  private Float2D pLeft, pRight;
51
  private Float4D rLeft, rRight;
52
  private Float3D vLeft, vRight;
53

    
54
  SurfaceView mView;
55

    
56
///////////////////////////////////////////////////////////////////////////////////////////////////
57
  /**
58
   * Pass in the SurfaceView's SurfaceHolder.  Note the Surface may not yet exist.
59
   */
60
  public RenderThread(SurfaceHolder holder, SurfaceView view)
61
    {
62
    mSurfaceHolder = holder;
63
    mView = view;
64

    
65
    pLeft = new Float2D( 90, 258);
66
    pRight= new Float2D(176, 255);
67

    
68
    rLeft = new Float4D(-10,-10,25,25);
69
    rRight= new Float4D( 10, -5,25,25);
70

    
71
    vLeft = new Float3D(-20,-20,0);
72
    vRight= new Float3D( 20,-10,0);
73
    }
74

    
75
///////////////////////////////////////////////////////////////////////////////////////////////////
76
  /**
77
   * Thread entry point.
78
   * <p>
79
   * The thread should not be started until the Surface associated with the SurfaceHolder
80
   * has been created.  That way we don't have to wait for a separate "surface created"
81
   * message to arrive.
82
   */
83
  @Override
84
  public void run()
85
    {
86
    Looper.prepare();
87
    mHandler = new RenderHandler(this);
88
    eglCore = new EglCore(null, EglCore.FLAG_RECORDABLE | EglCore.FLAG_TRY_GLES3);
89

    
90
    synchronized (mStartLock)
91
      {
92
      mReady = true;
93
      mStartLock.notify();    // signal waitUntilReady()
94
      }
95

    
96
    Looper.loop();
97
    Log.d(TAG, "looper quit");
98

    
99
    checkGlError("releaseGl start");
100

    
101
    if (eglSurface != null)
102
      {
103
      eglCore.releaseSurface(eglSurface);
104
      eglSurface = EGL14.EGL_NO_SURFACE;
105
      }
106

    
107
    checkGlError("releaseGl done");
108

    
109
    eglCore.makeNothingCurrent();
110
    eglCore.release();
111

    
112
    synchronized (mStartLock)
113
      {
114
      mReady = false;
115
      }
116
    }
117

    
118
///////////////////////////////////////////////////////////////////////////////////////////////////
119
  /**
120
   * Waits until the render thread is ready to receive messages.
121
   * <p>
122
   * Call from the UI thread.
123
   */
124
  public void waitUntilReady()
125
    {
126
    synchronized (mStartLock)
127
      {
128
      while (!mReady)
129
        {
130
        try
131
          {
132
          mStartLock.wait();
133
          }
134
        catch (InterruptedException ie) { /* not expected */ }
135
        }
136
      }
137
    }
138

    
139
///////////////////////////////////////////////////////////////////////////////////////////////////
140
  /**
141
   * Shuts everything down.
142
   */
143
  void shutdown()
144
    {
145
    Log.d(TAG, "shutdown");
146
    Looper.myLooper().quit();
147
    }
148

    
149
///////////////////////////////////////////////////////////////////////////////////////////////////
150
  /**
151
   * Returns the render thread's Handler.  This may be called from any thread.
152
   */
153
  public RenderHandler getHandler()
154
      {
155
      return mHandler;
156
      }
157

    
158
///////////////////////////////////////////////////////////////////////////////////////////////////
159
  /**
160
   * Prepares the surface.
161
   */
162
  void surfaceCreated()
163
    {
164
    Surface surface = mSurfaceHolder.getSurface();
165

    
166
    eglSurface = eglCore.createWindowSurface(surface);
167
    eglCore.makeCurrent(eglSurface);
168

    
169
    InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
170
    Bitmap bmp;
171

    
172
    try
173
      {
174
      bmp = BitmapFactory.decodeStream(is);
175
      }
176
    finally
177
      {
178
      try
179
        {
180
        is.close();
181
        }
182
      catch(IOException io) {}
183
      }
184

    
185
    monaLisa = new DistortedBitmap(bmp, 10);
186
    monaLisa.distort( vLeft, rLeft , pLeft, 1000, 0);
187
    monaLisa.distort(vRight, rRight, pRight,1000, 0);
188

    
189
    bmpHeight = bmp.getHeight();
190
    bmpWidth  = bmp.getWidth();
191

    
192
    try
193
      {
194
      Distorted.onSurfaceCreated(mView.getContext());
195
      }
196
    catch(Exception ex)
197
      {
198
      Log.e("MonaLisa", ex.getMessage() );
199
      }
200
    }
201

    
202
///////////////////////////////////////////////////////////////////////////////////////////////////
203

    
204
  void surfaceChanged(int width, int height)
205
    {
206
    Log.d(TAG, "surfaceChanged " + width + "x" + height);
207

    
208
    monaLisa.abortAllEffects(Distorted.TYPE_PRE);
209

    
210
    if( bmpHeight/bmpWidth > height/width )
211
      {
212
      int w = (height*bmpWidth)/bmpHeight;
213
      monaLisa.move((width-w)/2 ,0, 0);
214
      monaLisa.scale((float)height/bmpHeight);
215
      }
216
    else
217
      {
218
      int h = (width*bmpHeight)/bmpWidth;
219
      monaLisa.move(0 ,(height-h)/2, 0);
220
      monaLisa.scale((float)width/bmpWidth);
221
      }
222

    
223
    Distorted.onSurfaceChanged(width, height);
224
    }
225

    
226
///////////////////////////////////////////////////////////////////////////////////////////////////
227

    
228
  public void doFrame(long frameTimeNs)
229
    {
230
    Trace.beginSection("doFrame draw");
231
    eglCore.makeCurrent(eglSurface);
232

    
233
    GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
234
    GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
235
    monaLisa.draw(System.currentTimeMillis());
236

    
237
    eglCore.swapBuffers(eglSurface);
238
    Trace.endSection();
239
    }
240

    
241
///////////////////////////////////////////////////////////////////////////////////////////////////
242

    
243
  public static void checkGlError(String op)
244
    {
245
    int error = GLES20.glGetError();
246

    
247
    if (error != GLES20.GL_NO_ERROR)
248
      {
249
      String msg = op + ": glError 0x" + Integer.toHexString(error);
250
      Log.e(TAG, msg);
251
      throw new RuntimeException(msg);
252
      }
253
    }
254
  }
255
///////////////////////////////////////////////////////////////////////////////////////////////////
(5-5/5)