Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

First working stuff

  • Loading branch information...
commit 0f3bc1829d1a527968339f5287e17889f0e2512d 1 parent 5c09caf
@pcwalton authored
View
3  AndroidManifest.xml
@@ -3,7 +3,8 @@
package="org.mozilla.testuniversalsurfacetexture"
android:versionCode="1"
android:versionName="1.0">
- <application android:label="@string/app_name" android:icon="@drawable/icon">
+ <application android:label="@string/app_name" android:icon="@drawable/icon"
+ android:debuggable="true">
<activity android:name="TestUniversalSurfaceTexture"
android:label="@string/app_name">
<intent-filter>
View
11 jni/Android.mk
@@ -0,0 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_LDLIBS := -llog -lGLESv2 -lEGL
+
+LOCAL_MODULE := ndk1
+LOCAL_SRC_FILES := jni.cpp
+
+include $(BUILD_SHARED_LIBRARY)
+
View
2  jni/Application.mk
@@ -0,0 +1,2 @@
+APP_STL := stlport_static
+
View
472 jni/jni.cpp
@@ -0,0 +1,472 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Corporation code.
+ *
+ * The Initial Developer of the Original Code is Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * James Willcox <jwillcox@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#define EGL_EGLEXT_PROTOTYPES
+
+#include <jni.h>
+#include <cassert>
+#include <cstdint>
+#include <dlfcn.h>
+#include <android/log.h>
+#include <sys/time.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <GLES2/gl2.h>
+#include <map>
+
+/*
+ * Android stuff
+ */
+
+enum {
+ /* buffer is never read in software */
+ GRALLOC_USAGE_SW_READ_NEVER = 0x00000000,
+ /* buffer is rarely read in software */
+ GRALLOC_USAGE_SW_READ_RARELY = 0x00000002,
+ /* buffer is often read in software */
+ GRALLOC_USAGE_SW_READ_OFTEN = 0x00000003,
+ /* mask for the software read values */
+ GRALLOC_USAGE_SW_READ_MASK = 0x0000000F,
+
+ /* buffer is never written in software */
+ GRALLOC_USAGE_SW_WRITE_NEVER = 0x00000000,
+ /* buffer is never written in software */
+ GRALLOC_USAGE_SW_WRITE_RARELY = 0x00000020,
+ /* buffer is never written in software */
+ GRALLOC_USAGE_SW_WRITE_OFTEN = 0x00000030,
+ /* mask for the software write values */
+ GRALLOC_USAGE_SW_WRITE_MASK = 0x000000F0,
+
+ /* buffer will be used as an OpenGL ES texture */
+ GRALLOC_USAGE_HW_TEXTURE = 0x00000100,
+ /* buffer will be used as an OpenGL ES render target */
+ GRALLOC_USAGE_HW_RENDER = 0x00000200,
+ /* buffer will be used by the 2D hardware blitter */
+ GRALLOC_USAGE_HW_2D = 0x00000400,
+ /* buffer will be used with the framebuffer device */
+ GRALLOC_USAGE_HW_FB = 0x00001000,
+ /* mask for the software usage bit-mask */
+ GRALLOC_USAGE_HW_MASK = 0x00001F00,
+};
+
+struct hw_module_methods_t;
+typedef void* buffer_handle_t;
+
+typedef struct hw_module_t {
+ /** tag must be initialized to HARDWARE_MODULE_TAG */
+ uint32_t tag;
+
+ /** major version number for the module */
+ uint16_t version_major;
+
+ /** minor version number of the module */
+ uint16_t version_minor;
+
+ /** Identifier of module */
+ const char *id;
+
+ /** Name of this module */
+ const char *name;
+
+ /** Author/owner/implementor of the module */
+ const char *author;
+
+ /** Modules methods */
+ struct hw_module_methods_t* methods;
+
+ /** module's dso */
+ void* dso;
+
+ /** padding to 128 bytes, reserved for future use */
+ uint32_t reserved[32-7];
+
+} hw_module_t;
+
+typedef struct gralloc_module_t {
+ struct hw_module_t common;
+
+ /*
+ * (*registerBuffer)() must be called before a buffer_handle_t that has not
+ * been created with (*alloc_device_t::alloc)() can be used.
+ *
+ * This is intended to be used with buffer_handle_t's that have been
+ * received in this process through IPC.
+ *
+ * This function checks that the handle is indeed a valid one and prepares
+ * it for use with (*lock)() and (*unlock)().
+ *
+ * It is not necessary to call (*registerBuffer)() on a handle created
+ * with (*alloc_device_t::alloc)().
+ *
+ * returns an error if this buffer_handle_t is not valid.
+ */
+ int (*registerBuffer)(struct gralloc_module_t const* module,
+ buffer_handle_t handle);
+
+ /*
+ * (*unregisterBuffer)() is called once this handle is no longer needed in
+ * this process. After this call, it is an error to call (*lock)(),
+ * (*unlock)(), or (*registerBuffer)().
+ *
+ * This function doesn't close or free the handle itself; this is done
+ * by other means, usually through libcutils's native_handle_close() and
+ * native_handle_free().
+ *
+ * It is an error to call (*unregisterBuffer)() on a buffer that wasn't
+ * explicitly registered first.
+ */
+ int (*unregisterBuffer)(struct gralloc_module_t const* module,
+ buffer_handle_t handle);
+
+ /*
+ * The (*lock)() method is called before a buffer is accessed for the
+ * specified usage. This call may block, for instance if the h/w needs
+ * to finish rendering or if CPU caches need to be synchronized.
+ *
+ * The caller promises to modify only pixels in the area specified
+ * by (l,t,w,h).
+ *
+ * The content of the buffer outside of the specified area is NOT modified
+ * by this call.
+ *
+ * If usage specifies GRALLOC_USAGE_SW_*, vaddr is filled with the address
+ * of the buffer in virtual memory.
+ *
+ * THREADING CONSIDERATIONS:
+ *
+ * It is legal for several different threads to lock a buffer from
+ * read access, none of the threads are blocked.
+ *
+ * However, locking a buffer simultaneously for write or read/write is
+ * undefined, but:
+ * - shall not result in termination of the process
+ * - shall not block the caller
+ * It is acceptable to return an error or to leave the buffer's content
+ * into an indeterminate state.
+ *
+ * If the buffer was created with a usage mask incompatible with the
+ * requested usage flags here, -EINVAL is returned.
+ *
+ */
+
+ int (*lock)(struct gralloc_module_t const* module,
+ buffer_handle_t handle, int usage,
+ int l, int t, int w, int h,
+ void** vaddr);
+
+
+ /*
+ * The (*unlock)() method must be called after all changes to the buffer
+ * are completed.
+ */
+
+ int (*unlock)(struct gralloc_module_t const* module,
+ buffer_handle_t handle);
+
+
+ /* reserved for future use */
+ int (*perform)(struct gralloc_module_t const* module,
+ int operation, ... );
+
+ /* reserved for future use */
+ void* reserved_proc[7];
+} gralloc_module_t;
+
+typedef void* buffer_handle_t;
+
+typedef struct android_native_base_t
+{
+ /* a magic value defined by the actual EGL native type */
+ int magic;
+
+ /* the sizeof() of the actual EGL native type */
+ int version;
+
+ void* reserved[4];
+
+ /* reference-counting interface */
+ void (*incRef)(struct android_native_base_t* base);
+ void (*decRef)(struct android_native_base_t* base);
+} android_native_base_t;
+
+struct ANativeWindow
+{
+ struct android_native_base_t common;
+
+ /* flags describing some attributes of this surface or its updater */
+ const uint32_t flags;
+
+ /* min swap interval supported by this updated */
+ const int minSwapInterval;
+
+ /* max swap interval supported by this updated */
+ const int maxSwapInterval;
+
+ /* horizontal and vertical resolution in DPI */
+ const float xdpi;
+ const float ydpi;
+
+ /* Some storage reserved for the OEM's driver. */
+ intptr_t oem[4];
+
+
+ /*
+ * Set the swap interval for this surface.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*setSwapInterval)(struct ANativeWindow* window,
+ int interval);
+
+ /*
+ * hook called by EGL to acquire a buffer. After this call, the buffer
+ * is not locked, so its content cannot be modified.
+ * this call may block if no buffers are available.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*dequeueBuffer)(struct ANativeWindow* window,
+ struct android_native_buffer_t** buffer);
+
+ /*
+ * hook called by EGL to lock a buffer. This MUST be called before modifying
+ * the content of a buffer. The buffer must have been acquired with
+ * dequeueBuffer first.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*lockBuffer)(struct ANativeWindow* window,
+ struct android_native_buffer_t* buffer);
+ /*
+ * hook called by EGL when modifications to the render buffer are done.
+ * This unlocks and post the buffer.
+ *
+ * Buffers MUST be queued in the same order than they were dequeued.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*queueBuffer)(struct ANativeWindow* window,
+ struct android_native_buffer_t* buffer);
+
+ /*
+ * hook used to retrieve information about the native window.
+ *
+ * Returns 0 on success or -errno on error.
+ */
+ int (*query)(struct ANativeWindow* window,
+ int what, int* value);
+
+ /*
+ * hook used to perform various operations on the surface.
+ * (*perform)() is a generic mechanism to add functionality to
+ * ANativeWindow while keeping backward binary compatibility.
+ *
+ * This hook should not be called directly, instead use the helper functions
+ * defined below.
+ *
+ * (*perform)() returns -ENOENT if the 'what' parameter is not supported
+ * by the surface's implementation.
+ *
+ * The valid operations are:
+ * NATIVE_WINDOW_SET_USAGE
+ * NATIVE_WINDOW_CONNECT
+ * NATIVE_WINDOW_DISCONNECT
+ * NATIVE_WINDOW_SET_CROP
+ * NATIVE_WINDOW_SET_BUFFER_COUNT
+ * NATIVE_WINDOW_SET_BUFFERS_GEOMETRY
+ * NATIVE_WINDOW_SET_BUFFERS_TRANSFORM
+ *
+ */
+
+ int (*perform)(struct ANativeWindow* window,
+ int operation, ... );
+
+ /*
+ * hook used to cancel a buffer that has been dequeued.
+ * No synchronization is performed between dequeue() and cancel(), so
+ * either external synchronization is needed, or these functions must be
+ * called from the same thread.
+ */
+ int (*cancelBuffer)(struct ANativeWindow* window,
+ struct android_native_buffer_t* buffer);
+
+
+ void* reserved_proc[2];
+};
+
+struct android_native_buffer_t {
+ android_native_base_t common;
+
+ int width;
+ int height;
+ int stride;
+ int format;
+ int usage;
+
+ void* reserved[2];
+
+ buffer_handle_t handle;
+
+ void* reserved_proc[8];
+};
+
+enum {
+ NATIVE_WINDOW_SET_USAGE = 0,
+ NATIVE_WINDOW_CONNECT,
+ NATIVE_WINDOW_DISCONNECT,
+ NATIVE_WINDOW_SET_CROP,
+ NATIVE_WINDOW_SET_BUFFER_COUNT,
+ NATIVE_WINDOW_SET_BUFFERS_GEOMETRY,
+ NATIVE_WINDOW_SET_BUFFERS_TRANSFORM,
+};
+
+jclass sSurfaceClass = 0;
+jfieldID sNativeSurfaceField = 0;
+jfieldID sSurfaceControlField = 0;
+
+struct EGLImages {
+ EGLImageKHR a;
+ EGLImageKHR b;
+};
+
+struct Rect {
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+static EGLImageKHR sImage = 0;
+static android_native_buffer_t* sBuffer = 0;
+static gralloc_module_t *sModule;
+
+int (*sw_gralloc_handle_t_lock)(void* handle, int usage, int x, int y, int width, int height,
+ void** addr) = 0;
+int (*sw_gralloc_handle_t_unlock)(void* handle) = 0;
+
+void (*hw_get_module)(const char* id, hw_module_t** module);
+
+
+extern "C" void
+Java_org_mozilla_testuniversalsurfacetexture_TestUniversalSurfaceTexture_attachTexture(JNIEnv*
+ aJEnv, jclass klass, jobject aSurface, int aDestroyed)
+{
+ __android_log_print(ANDROID_LOG_ERROR, "TUST", "### point a");
+
+ if (!sSurfaceClass) {
+ sSurfaceClass = reinterpret_cast<jclass>
+ (aJEnv->NewGlobalRef(aJEnv->FindClass("android/view/Surface")));
+ sNativeSurfaceField = aJEnv->GetFieldID(sSurfaceClass, "mNativeSurface", "I");
+ sSurfaceControlField = aJEnv->GetFieldID(sSurfaceClass, "mSurfaceControl", "I");
+
+ void* lib = dlopen("libui.so", RTLD_LAZY);
+ sw_gralloc_handle_t_lock = (typeof(sw_gralloc_handle_t_lock))
+ dlsym(lib, "_ZN7android19sw_gralloc_handle_t4lockEPS0_iiiiiPPv");
+ sw_gralloc_handle_t_unlock = (typeof(sw_gralloc_handle_t_unlock))
+ dlsym(lib, "_ZN7android19sw_gralloc_handle_t6unlockEPS0_");
+ __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Lock=%p, unlock=%p",
+ sw_gralloc_handle_t_lock, sw_gralloc_handle_t_unlock);
+
+ lib = dlopen("libhardware.so", RTLD_LAZY);
+ hw_get_module = (typeof(hw_get_module))dlsym(lib, "hw_get_module");
+
+ hw_module_t* pModule;
+ hw_get_module("gralloc", &pModule);
+ sModule = reinterpret_cast<gralloc_module_t*>(pModule);
+ __android_log_print(ANDROID_LOG_ERROR, "TUST", "### Gralloc module=%p", pModule);
+ }
+
+ if (!sImage) {
+ ANativeWindow* nativeWindow = reinterpret_cast<ANativeWindow*>
+ (aJEnv->GetIntField(aSurface, sNativeSurfaceField) + 8);
+
+ /*Rect rect;
+ rect.left = rect.top = rect.right = rect.bottom = 0;
+ nativeWindow->perform(nativeWindow, NATIVE_WINDOW_SET_CROP, &rect);*/
+
+ // NB: nativeWindow->common.magic is '_wnd' as a FourCC.
+ // My version is 104.
+
+ __android_log_print(ANDROID_LOG_ERROR, "TUST",
+ "### Native window ptr %p, magic %08x, version %d, reserved %p, flags %d, dpi %g\n",
+ nativeWindow, (unsigned)nativeWindow->common.magic,
+ nativeWindow->common.version, nativeWindow->common.reserved[0],
+ (int)nativeWindow->flags, (double)nativeWindow->xdpi);
+
+ nativeWindow->dequeueBuffer(nativeWindow, &sBuffer);
+ nativeWindow->lockBuffer(nativeWindow, sBuffer);
+
+ // Must increment the refcount on the native window to avoid crashes on Mali (Galaxy S2).
+ nativeWindow->common.incRef(&nativeWindow->common);
+
+ const EGLint eglImgAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE, EGL_NONE };
+
+ sBuffer->common.incRef(&sBuffer->common);
+
+ sImage = eglCreateImageKHR(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_NO_CONTEXT,
+ EGL_NATIVE_BUFFER_ANDROID,
+ reinterpret_cast<EGLClientBuffer>(sBuffer), eglImgAttrs);
+
+ //nativeWindow->queueBuffer(nativeWindow, sBuffer);
+ }
+
+ uint8_t *bits = 0;
+ int err = sModule->lock(sModule, sBuffer->handle, GRALLOC_USAGE_SW_READ_OFTEN |
+ GRALLOC_USAGE_SW_WRITE_OFTEN, 0, 0, 512, 512, (void**)&bits);
+ /*__android_log_print(ANDROID_LOG_ERROR, "TUST",
+ "### Buffer width=%d height=%d stride=%d format=%d usage=%d Bits are: %p, err=%d",
+ sBuffer->width, sBuffer->height, sBuffer->stride, sBuffer->format, sBuffer->usage,
+ bits, err);*/
+
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+
+ static int x = 0;
+
+ for (int i = 0; i < 512*512*2; i += 2) {
+ bits[i] = bits[i+1] = (tv.tv_usec / 100000) % 256;
+ }
+ sModule->unlock(sModule, sBuffer->handle);
+
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, sImage);
+
+ /*__android_log_print(ANDROID_LOG_ERROR, "TUST", "### Success! GL error is: %d",
+ (int)glGetError());*/
+}
+
View
377 src/org/mozilla/testuniversalsurfacetexture/TestUniversalSurfaceTexture.java
@@ -1,15 +1,382 @@
package org.mozilla.testuniversalsurfacetexture;
import android.app.Activity;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.opengl.GLSurfaceView;
+import android.opengl.GLU;
+import android.opengl.GLUtils;
import android.os.Bundle;
+import android.os.Process;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.view.Display;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.RelativeLayout;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+public class TestUniversalSurfaceTexture extends Activity implements GLSurfaceView.Renderer,
+ SurfaceHolder.Callback {
+ private GLSurfaceView mGLSurfaceView;
+ private SurfaceView mSurfaceView;
+ private Square mSquare;
+ private int mFrameCount;
+
+ private Surface mSurface;
+ private boolean mSurfaceDestroyed;
-public class TestUniversalSurfaceTexture extends Activity
-{
/** Called when the activity is first created. */
@Override
- public void onCreate(Bundle savedInstanceState)
- {
+ public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
+
+ mSurfaceDestroyed = false;
+
+ mSquare = new Square();
+
+ final DisplayMetrics metrics = new DisplayMetrics();
+ getWindowManager().getDefaultDisplay().getMetrics(metrics);
+
+ RelativeLayout layout = new RelativeLayout(this);
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(512, 512);
+ params.leftMargin = metrics.widthPixels + 1000;
+ params.topMargin = 0;
+
+ mSurfaceView = new SurfaceView(this) {
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // If this is not done, the surface gets clipped to the visible rect.
+ setMeasuredDimension(512, 512);
+ }
+ };
+
+ mSurfaceView.getHolder().addCallback(this);
+ layout.addView(mSurfaceView, params);
+
+ mGLSurfaceView = new GLSurfaceView(this);
+ mGLSurfaceView.setRenderer(this);
+
+ params = new RelativeLayout.LayoutParams(metrics.widthPixels - 1, metrics.heightPixels);
+ params.leftMargin = 0;
+ params.topMargin = 0;
+ layout.addView(mGLSurfaceView, params);
+
+ setContentView(layout);
+
+ mSurfaceView.postDelayed(new Runnable() {
+ public void run() {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(512, 512);
+ params.leftMargin = 1000;
+ params.topMargin = 0;
+ mSurfaceView.setLayoutParams(params);
+ }
+ }, 3000);
+
+ /*try {
+ Method method = SurfaceView.class.getMethod("setWindowType", Integer.TYPE);
+ method.invoke(mSurfaceView, WindowManager.LayoutParams.TYPE_WALLPAPER);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException(e);
+ }*/
+
+ /*try {
+ Class surfaceSessionClass = Class.forName("android.view.SurfaceSession");
+ Object surfaceSession = surfaceSessionClass.newInstance();
+ Constructor<?>[] constructors = Surface.class.getConstructors();
+ Constructor<?> surfaceConstructor = null;
+ for (Constructor<?> constructor : constructors) {
+ if (constructor.getParameterTypes().length == 7) {
+ surfaceConstructor = constructor;
+ break;
+ }
+ }
+
+ Display display = getWindowManager().getDefaultDisplay();
+ Object mySurface = surfaceConstructor.newInstance(surfaceSession, Process.myPid(),
+ display.getDisplayId(), 512, 512,
+ PixelFormat.RGB_565, 0);
+ Log.e("TUST", "### Surface is " + mySurface);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException(e);
+ }*/
+ }
+
+ // SurfaceView interface
+
+ public void surfaceChanged(final SurfaceHolder holder, int format, int width, int height) {
+ Log.e("TUST", "### surfaceChanged " + format + " " + width + " " + height + " " +
+ ((holder.getSurface() == null) ? "null!" : holder.getSurface()));
+
+ synchronized (this) {
+ mSurface = holder.getSurface();
+ try {
+ Canvas c = mSurface.lockCanvas(new Rect(0, 0, 512, 512));
+ c.drawColor(Color.BLUE);
+ mSurface.unlockCanvasAndPost(c);
+ } catch (Surface.OutOfResourcesException e) {
+ throw new RuntimeException(e);
+ }
+
+ notifyAll();
+ }
+ }
+
+ private synchronized void paint() {
+ if (mSurface == null) {
+ return;
+ }
+
+ try {
+ Canvas c = mSurface.lockCanvas(new Rect(0, 0, 512, 512));
+ c.drawColor(Color.rgb(mFrameCount % 256, mFrameCount % 256, mFrameCount % 256));
+ mSurface.unlockCanvasAndPost(c);
+ } catch (Surface.OutOfResourcesException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void surfaceCreated(SurfaceHolder holder) {
+ Log.e("TUST", "### surfaceCreated");
+ Canvas c = holder.lockCanvas();
+ c.drawColor(Color.BLUE);
+ holder.unlockCanvasAndPost(c);
+ }
+
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.e("TUST", "### surfaceDestroyed");
+ synchronized (this) {
+ mSurface = null;
+ mSurfaceDestroyed = true;
+ this.notifyAll();
+ }
+ }
+
+ // GLSurfaceView interface
+
+ /**
+ * The Surface is created/init()
+ */
+ public void onSurfaceCreated(GL10 gl, EGLConfig config) {
+ gl.glEnable(GL10.GL_TEXTURE_2D); //Enable Texture Mapping ( NEW )
+ gl.glShadeModel(GL10.GL_SMOOTH); //Enable Smooth Shading
+ gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //Black Background
+ gl.glClearDepthf(1.0f); //Depth Buffer Setup
+ gl.glEnable(GL10.GL_DEPTH_TEST); //Enables Depth Testing
+ gl.glDepthFunc(GL10.GL_LEQUAL); //The Type Of Depth Testing To Do
+
+ //Really Nice Perspective Calculations
+ gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
+
+ //Load the texture for the square once during Surface creation
+ mSquare.loadGLTexture(gl, this);
+ }
+
+ /**
+ * Here we do our drawing
+ */
+ public void onDrawFrame(GL10 gl) {
+ //Clear Screen And Depth Buffer
+ gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
+ gl.glLoadIdentity(); //Reset The Current Modelview Matrix
+
+ /*
+ * Minor changes to the original tutorial
+ *
+ * Instead of drawing our objects here,
+ * we fire their own drawing methods on
+ * the current instance
+ */
+ gl.glTranslatef(0.0f, -1.2f, -6.0f); //Move down 1.2 Unit And Into The Screen 6.0
+ mSquare.draw(gl); //Draw the square
+ }
+
+ /**
+ * If the surface changes, reset the view
+ */
+ public void onSurfaceChanged(GL10 gl, int width, int height) {
+ if(height == 0) { //Prevent A Divide By Zero By
+ height = 1; //Making Height Equal One
+ }
+
+ gl.glViewport(0, 0, width, height); //Reset The Current Viewport
+ gl.glMatrixMode(GL10.GL_PROJECTION); //Select The Projection Matrix
+ gl.glLoadIdentity(); //Reset The Projection Matrix
+
+ //Calculate The Aspect Ratio Of The Window
+ GLU.gluPerspective(gl, 45.0f, (float)width / (float)height, 0.1f, 100.0f);
+
+ gl.glMatrixMode(GL10.GL_MODELVIEW); //Select The Modelview Matrix
+ gl.glLoadIdentity(); //Reset The Modelview Matrix
+ }
+
+ private class Square {
+
+ /** The buffer holding the vertices */
+ private FloatBuffer vertexBuffer;
+ /** The buffer holding the texture coordinates */
+ private FloatBuffer textureBuffer;
+ /** Our texture pointer */
+ private int[] textures = new int[1];
+
+ /** The initial vertex definition */
+ private float vertices[] = {
+ -1.0f, -1.0f, 0.0f, //Bottom Left
+ 1.0f, -1.0f, 0.0f, //Bottom Right
+ -1.0f, 1.0f, 0.0f, //Top Left
+ 1.0f, 1.0f, 0.0f //Top Right
+ };
+
+ private float texture[] = {
+ //Mapping coordinates for the vertices
+ 0.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 0.0f,
+ 1.0f, 1.0f
+ };
+
+ /**
+ * The Square constructor.
+ *
+ * Initiate the buffers.
+ */
+ public Square() {
+ //
+ ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
+ byteBuf.order(ByteOrder.nativeOrder());
+ vertexBuffer = byteBuf.asFloatBuffer();
+ vertexBuffer.put(vertices);
+ vertexBuffer.position(0);
+
+ byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
+ byteBuf.order(ByteOrder.nativeOrder());
+ textureBuffer = byteBuf.asFloatBuffer();
+ textureBuffer.put(texture);
+ textureBuffer.position(0);
+ }
+
+ /**
+ * The object own drawing function.
+ * Called from the renderer to redraw this instance
+ * with possible changes in values.
+ *
+ * @param gl - The GL context
+ */
+ public void draw(GL10 gl) {
+ mFrameCount++;
+ if (mFrameCount % 30 == 0) {
+ //paint();
+ }
+
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
+ attachTexture(mSurface, mSurfaceDestroyed);
+
+ //Set the face rotation
+ gl.glFrontFace(GL10.GL_CW);
+
+ //Point to our vertex buffer
+ gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuffer);
+ gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuffer);
+
+ //Enable vertex buffer
+ gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+
+ //Draw the vertices as triangle strip
+ gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, vertices.length / 3);
+
+ //Disable the client state before leaving
+ gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
+ gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ }
+
+ /**
+ * Load the textures
+ *
+ * @param gl - The GL Context
+ * @param context - The Activity context
+ */
+ public void loadGLTexture(GL10 gl, Context context) {
+ Log.e("TUST", "### Loading GL texture");
+
+ //Get the texture from the Android resource directory
+ InputStream is = context.getResources().openRawResource(R.drawable.nehe);
+ Bitmap bitmap = null;
+ try {
+ //BitmapFactory is an Android graphics utility for images
+ bitmap = BitmapFactory.decodeStream(is);
+
+ } finally {
+ //Always clear and close
+ try {
+ is.close();
+ is = null;
+ } catch (IOException e) {
+ }
+ }
+
+ //Generate one texture pointer...
+ gl.glGenTextures(1, textures, 0);
+ //...and bind it to our array
+ gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
+
+ //Create Nearest Filtered Texture
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
+
+ //Different possible texture parameters, e.g. GL10.GL_CLAMP_TO_EDGE
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_REPEAT);
+ gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_REPEAT);
+
+ //Clean up
+ bitmap.recycle();
+ }
+ }
+
+ static {
+ System.loadLibrary("ndk1");
}
+
+ private synchronized void attachTextureToSurface() {
+ synchronized (TestUniversalSurfaceTexture.this) {
+ try {
+ while (mSurface == null) {
+ this.wait();
+ }
+ attachTexture(mSurface, mSurfaceDestroyed);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static native void attachTexture(Surface surface, boolean surfaceDestroyed);
}
Please sign in to comment.
Something went wrong with that request. Please try again.