1a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk/*
2a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Copyright (C) 2011 The Android Open Source Project
3a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
4a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Licensed under the Apache License, Version 2.0 (the "License");
5a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * you may not use this file except in compliance with the License.
6a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * You may obtain a copy of the License at
7a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
8a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *      http://www.apache.org/licenses/LICENSE-2.0
9a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk *
10a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * Unless required by applicable law or agreed to in writing, software
11a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * distributed under the License is distributed on an "AS IS" BASIS,
12a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * See the License for the specific language governing permissions and
14a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk * limitations under the License.
15a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk */
16a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
17d4cb9c587c23e3c24d928b0ac1a4de5679846f93Alex Sakhartchoukpackage com.android.testapp;
18a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
19a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.io.Writer;
20a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.ArrayList;
21a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport java.util.concurrent.Semaphore;
22a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
23a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.RSSurfaceView;
24a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.RenderScript;
25a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.renderscript.RenderScriptGL;
26a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
27a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.content.Context;
28a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.content.res.Resources;
29a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.graphics.Bitmap;
30a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.graphics.drawable.BitmapDrawable;
31a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.graphics.drawable.Drawable;
32a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.os.Handler;
33a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.os.Message;
34a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.util.AttributeSet;
35a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.util.Log;
36a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.Surface;
37a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.SurfaceHolder;
38a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.SurfaceView;
39a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.KeyEvent;
40a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.MotionEvent;
41a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchoukimport android.view.ScaleGestureDetector;
42a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
433fc86ec3d03bb4a0ae61e41d0cfba43595ecc23dAlex Sakhartchoukpublic class TestAppView extends RSSurfaceView {
44a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
453fc86ec3d03bb4a0ae61e41d0cfba43595ecc23dAlex Sakhartchouk    public TestAppView(Context context) {
46a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        super(context);
47a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
48a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
49a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
50a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private RenderScriptGL mRS;
513fc86ec3d03bb4a0ae61e41d0cfba43595ecc23dAlex Sakhartchouk    TestAppRS mRender;
52a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
53a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private ScaleGestureDetector mScaleDetector;
54a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private static final int INVALID_POINTER_ID = -1;
55a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private int mActivePointerId = INVALID_POINTER_ID;
56a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
57a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
58a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        super.surfaceChanged(holder, format, w, h);
59a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        if (mRS == null) {
60a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
61a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            sc.setDepth(16, 24);
62b23b58ad343ccbf8835c7067698a60fc6bc1a870Alex Sakhartchouk            sc.setSamples(1, 2, 1);
63a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRS = createRenderScriptGL(sc);
64a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRS.setSurface(holder, w, h);
653fc86ec3d03bb4a0ae61e41d0cfba43595ecc23dAlex Sakhartchouk            mRender = new TestAppRS();
66a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRender.init(mRS, getResources(), w, h);
67a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
68a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
69a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
70a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    @Override
71a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    protected void onDetachedFromWindow() {
72a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        if (mRS != null) {
73a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRender = null;
74a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRS = null;
75a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            destroyRenderScriptGL();
76a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
77a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
78a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
79a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    @Override
80a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    public boolean onKeyDown(int keyCode, KeyEvent event)
81a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    {
82a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        // break point at here
83a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        // this method doesn't work when 'extends View' include 'extends ScrollView'.
84a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        return super.onKeyDown(keyCode, event);
85a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
86a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
87a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
88a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    @Override
89a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    public boolean onTouchEvent(MotionEvent ev) {
90a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        mScaleDetector.onTouchEvent(ev);
91a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
92a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        boolean ret = false;
93a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        float x = ev.getX();
94a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        float y = ev.getY();
95a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
96a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        final int action = ev.getAction();
97a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
98a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        switch (action & MotionEvent.ACTION_MASK) {
99a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        case MotionEvent.ACTION_DOWN: {
100a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRender.onActionDown(x, y);
101a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mActivePointerId = ev.getPointerId(0);
102a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            ret = true;
103a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            break;
104a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
105a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        case MotionEvent.ACTION_MOVE: {
106a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            if (!mScaleDetector.isInProgress()) {
107a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                mRender.onActionMove(x, y);
108a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
109a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRender.onActionDown(x, y);
110a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            ret = true;
111a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            break;
112a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
113a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
114a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        case MotionEvent.ACTION_UP: {
115a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mActivePointerId = INVALID_POINTER_ID;
116a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            break;
117a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
118a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
119a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        case MotionEvent.ACTION_CANCEL: {
120a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mActivePointerId = INVALID_POINTER_ID;
121a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            break;
122a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
123a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
124a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        case MotionEvent.ACTION_POINTER_UP: {
125a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
126a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
127a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            final int pointerId = ev.getPointerId(pointerIndex);
128a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            if (pointerId == mActivePointerId) {
129a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                // This was our active pointer going up. Choose a new
130a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                // active pointer and adjust accordingly.
131a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
132a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                x = ev.getX(newPointerIndex);
133a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                y = ev.getY(newPointerIndex);
134a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                mRender.onActionDown(x, y);
135a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk                mActivePointerId = ev.getPointerId(newPointerIndex);
136a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            }
137a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            break;
138a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
139a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
140a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
141a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        return ret;
142a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
143a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
144a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
145a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        @Override
146a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        public boolean onScale(ScaleGestureDetector detector) {
147a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            mRender.onActionScale(detector.getScaleFactor());
148a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk            return true;
149a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk        }
150a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk    }
151a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk}
152a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
153a7a211b8a68a7d3f5ff4409aa286db07f96c0550Alex Sakhartchouk
154