mirror of https://github.com/opencv/opencv.git
Camera and Camera2 preview is rendered via OpenGL textures and can be modified on CPU via C++ code. No OpenCL yet.
parent
11c3fa527a
commit
2a6d4b6ee2
21 changed files with 1103 additions and 0 deletions
@ -0,0 +1,9 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> |
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/> |
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/> |
||||
<classpathentry kind="src" path="src"/> |
||||
<classpathentry kind="src" path="gen"/> |
||||
<classpathentry kind="output" path="bin/classes"/> |
||||
</classpath> |
@ -0,0 +1,61 @@ |
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage"> |
||||
<storageModule moduleId="org.eclipse.cdt.core.settings"> |
||||
<cconfiguration id="com.android.toolchain.gcc.2119826334"> |
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.2119826334" moduleId="org.eclipse.cdt.core.settings" name="Default"> |
||||
<externalSettings/> |
||||
<extensions> |
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/> |
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/> |
||||
</extensions> |
||||
</storageModule> |
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> |
||||
<configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.2119826334" name="Default" parent="org.eclipse.cdt.build.core.emptycfg"> |
||||
<folderInfo id="com.android.toolchain.gcc.2119826334.1853372756" name="/" resourcePath=""> |
||||
<toolChain id="com.android.toolchain.gcc.344648270" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc"> |
||||
<targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.443518540" isAbstract="false" superClass="com.android.targetPlatform"/> |
||||
<builder command="ndk-build.cmd" id="com.android.builder.1393780489" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder"> |
||||
<outputEntries> |
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/> |
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/> |
||||
</outputEntries> |
||||
</builder> |
||||
<tool id="com.android.gcc.compiler.1725706653" name="Android GCC Compiler" superClass="com.android.gcc.compiler"> |
||||
<option id="com.android.gcc.option.includePath.1852635009" superClass="com.android.gcc.option.includePath" valueType="includePath"> |
||||
<listOptionValue builtIn="false" value="../$(O4A_SDK_ROOT)/sdk/native/jni/include"/> |
||||
</option> |
||||
<inputType id="com.android.gcc.inputType.193477776" superClass="com.android.gcc.inputType"/> |
||||
</tool> |
||||
</toolChain> |
||||
</folderInfo> |
||||
<sourceEntries> |
||||
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/> |
||||
</sourceEntries> |
||||
</configuration> |
||||
</storageModule> |
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/> |
||||
</cconfiguration> |
||||
</storageModule> |
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0"> |
||||
<project id="tutorial-4-opencl.null.126354959" name="tutorial-4-opencl"/> |
||||
</storageModule> |
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/> |
||||
<storageModule moduleId="scannerConfiguration"> |
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/> |
||||
<scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.2119826334;com.android.toolchain.gcc.2119826334.1853372756;com.android.gcc.compiler.1725706653;com.android.gcc.inputType.193477776"> |
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/> |
||||
</scannerConfigBuildInfo> |
||||
</storageModule> |
||||
<storageModule moduleId="refreshScope" versionNumber="2"> |
||||
<configuration configurationName="Default"> |
||||
<resource resourceType="FOLDER" workspacePath="/tutorial-4-opencl/jni"/> |
||||
</configuration> |
||||
</storageModule> |
||||
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/> |
||||
</cproject> |
@ -0,0 +1,49 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>OpenCV Tutorial 4 - Use OpenCL</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name> |
||||
<triggers>clean,full,incremental,</triggers> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>com.android.ide.eclipse.adt.ApkBuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
<buildCommand> |
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name> |
||||
<triggers>full,incremental,</triggers> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>com.android.ide.eclipse.adt.AndroidNature</nature> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
<nature>org.eclipse.cdt.core.cnature</nature> |
||||
<nature>org.eclipse.cdt.core.ccnature</nature> |
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature> |
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature> |
||||
</natures> |
||||
</projectDescription> |
@ -0,0 +1,4 @@ |
||||
eclipse.preferences.version=1 |
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 |
||||
org.eclipse.jdt.core.compiler.compliance=1.6 |
||||
org.eclipse.jdt.core.compiler.source=1.6 |
@ -0,0 +1,32 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" |
||||
package="org.opencv.samples.tutorial4" |
||||
android:versionCode="1" |
||||
android:versionName="1.0" > |
||||
|
||||
<uses-sdk |
||||
android:minSdkVersion="14" |
||||
android:targetSdkVersion="21" /> |
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true"/> |
||||
<uses-feature android:name="android.hardware.camera"/> |
||||
<uses-feature android:name="android.hardware.camera2" android:required="false"/> |
||||
<uses-permission android:name="android.permission.CAMERA"/> |
||||
|
||||
<application |
||||
android:allowBackup="true" |
||||
android:icon="@drawable/icon" |
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" > |
||||
<activity |
||||
android:name=".Tutorial4Activity" |
||||
android:label="@string/app_name" |
||||
android:screenOrientation="landscape" |
||||
android:configChanges="keyboardHidden|orientation"> |
||||
<intent-filter> |
||||
<action android:name="android.intent.action.MAIN" /> |
||||
<category android:name="android.intent.category.LAUNCHER" /> |
||||
</intent-filter> |
||||
</activity> |
||||
</application> |
||||
|
||||
</manifest> |
@ -0,0 +1,12 @@ |
||||
set(sample example-tutorial-4-opencl) |
||||
|
||||
if(BUILD_FAT_JAVA_LIB) |
||||
set(native_deps opencv_java) |
||||
else() |
||||
set(native_deps opencv_imgproc) |
||||
endif() |
||||
|
||||
add_android_project(${sample} "${CMAKE_CURRENT_SOURCE_DIR}" LIBRARY_DEPS ${OpenCV_BINARY_DIR} SDK_TARGET 21 ${ANDROID_SDK_TARGET} NATIVE_DEPS ${native_deps}) |
||||
if(TARGET ${sample}) |
||||
add_dependencies(opencv_android_examples ${sample}) |
||||
endif() |
@ -0,0 +1,9 @@ |
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS) |
||||
|
||||
LOCAL_MODULE := JNIrender
|
||||
LOCAL_SRC_FILES := jni.c GLrender.cpp
|
||||
LOCAL_LDLIBS += -llog -lGLESv2 -lEGL
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY) |
@ -0,0 +1,4 @@ |
||||
#APP_STL := gnustl_shared
|
||||
#APP_GNUSTL_FORCE_CPP_FEATURES := exceptions rtti
|
||||
APP_ABI := armeabi-v7a
|
||||
APP_PLATFORM := android-14
|
@ -0,0 +1,300 @@ |
||||
#include <GLES2/gl2.h> |
||||
#include <GLES2/gl2ext.h> |
||||
|
||||
#include "common.hpp" |
||||
|
||||
float vertexes[] = { |
||||
-1.0f, -1.0f, |
||||
-1.0f, 1.0f, |
||||
1.0f, -1.0f, |
||||
1.0f, 1.0f |
||||
}; |
||||
float texCoordOES[] = { |
||||
0.0f, 1.0f, |
||||
0.0f, 0.0f, |
||||
1.0f, 1.0f, |
||||
1.0f, 0.0f |
||||
}; |
||||
float texCoord2D[] = { |
||||
0.0f, 0.0f, |
||||
0.0f, 1.0f, |
||||
1.0f, 0.0f, |
||||
1.0f, 1.0f |
||||
}; |
||||
|
||||
const char vss[] = \
|
||||
"attribute vec2 vPosition;\n" \
|
||||
"attribute vec2 vTexCoord;\n" \
|
||||
"varying vec2 texCoord;\n" \
|
||||
"void main() {\n" \
|
||||
" texCoord = vTexCoord;\n" \
|
||||
" gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" \
|
||||
"}"; |
||||
|
||||
const char fssOES[] = \
|
||||
"#extension GL_OES_EGL_image_external : require\n" \
|
||||
"precision mediump float;\n" \
|
||||
"uniform samplerExternalOES sTexture;\n" \
|
||||
"varying vec2 texCoord;\n" \
|
||||
"void main() {\n" \
|
||||
" gl_FragColor = texture2D(sTexture,texCoord);\n" \
|
||||
"}"; |
||||
|
||||
const char fss2D[] = \
|
||||
"precision mediump float;\n" \
|
||||
"uniform sampler2D sTexture;\n" \
|
||||
"varying vec2 texCoord;\n" \
|
||||
"void main() {\n" \
|
||||
" gl_FragColor = texture2D(sTexture,texCoord);\n" \
|
||||
"}"; |
||||
|
||||
int progOES = 0; |
||||
int prog2D = 0; |
||||
|
||||
GLuint FBOtex = 0; |
||||
GLuint FBO = 0; |
||||
|
||||
GLuint texOES = 0; |
||||
int texWidth = 0, texHeight = 0; |
||||
|
||||
static inline void deleteTex(GLuint* tex) |
||||
{ |
||||
if(tex && *tex) |
||||
{ |
||||
glDeleteTextures(1, tex); |
||||
*tex = 0; |
||||
} |
||||
} |
||||
|
||||
static void releaseFBO() |
||||
{ |
||||
if (FBO != 0) |
||||
{ |
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||||
glDeleteFramebuffers(1, &FBO); |
||||
FBO = 0; |
||||
} |
||||
deleteTex(&FBOtex); |
||||
glDeleteProgram(prog2D); |
||||
prog2D = 0; |
||||
} |
||||
|
||||
static inline void logShaderCompileError(GLuint shader) |
||||
{ |
||||
GLchar msg[512]; |
||||
msg[0] = 0; |
||||
GLsizei len; |
||||
glGetShaderInfoLog(shader, sizeof(msg) - 1, &len, msg); |
||||
LOGE("Could not compile shader: %s", msg); |
||||
} |
||||
|
||||
static int makeShaderProg(const char* vss, const char* fss) |
||||
{ |
||||
LOGD("makeShaderProg: setup GL_VERTEX_SHADER"); |
||||
GLuint vshader = glCreateShader(GL_VERTEX_SHADER); |
||||
const GLchar* text = vss; |
||||
glShaderSource(vshader, 1, &text, 0); |
||||
glCompileShader(vshader); |
||||
int compiled; |
||||
glGetShaderiv(vshader, GL_COMPILE_STATUS, &compiled); |
||||
if (compiled == 0) { |
||||
logShaderCompileError(vshader); |
||||
glDeleteShader(vshader); |
||||
vshader = 0; |
||||
} |
||||
|
||||
LOGD("makeShaderProg: setup GL_FRAGMENT_SHADER"); |
||||
GLuint fshader = glCreateShader(GL_FRAGMENT_SHADER); |
||||
text = fss; |
||||
glShaderSource(fshader, 1, &text, 0); |
||||
glCompileShader(fshader); |
||||
glGetShaderiv(fshader, GL_COMPILE_STATUS, &compiled); |
||||
if (compiled == 0) { |
||||
logShaderCompileError(fshader); |
||||
glDeleteShader(fshader); |
||||
fshader = 0; |
||||
} |
||||
|
||||
LOGD("makeShaderProg: glCreateProgram"); |
||||
GLuint program = glCreateProgram(); |
||||
glAttachShader(program, vshader); |
||||
glAttachShader(program, fshader); |
||||
glLinkProgram(program); |
||||
|
||||
if(vshader) glDeleteShader(vshader); |
||||
if(fshader) glDeleteShader(fshader); |
||||
|
||||
return program; |
||||
} |
||||
|
||||
static void initFBO(int width, int height) |
||||
{ |
||||
releaseFBO(); |
||||
|
||||
glGenTextures(1, &FBOtex); |
||||
glBindTexture(GL_TEXTURE_2D, FBOtex); |
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
||||
//int hFBO;
|
||||
glGenFramebuffers(1, &FBO); |
||||
glBindFramebuffer(GL_FRAMEBUFFER, FBO); |
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, FBOtex, 0); |
||||
LOGD("initFBO status: %d", glGetError()); |
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) |
||||
LOGE("initFBO failed: %d", glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
||||
|
||||
prog2D = makeShaderProg(vss, fss2D); |
||||
} |
||||
|
||||
void drawTex(int tex, GLenum texType, GLuint fbo) |
||||
{ |
||||
int64_t t = getTimeMs(); |
||||
//draw texture to FBO or to screen
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
||||
glViewport(0, 0, texWidth, texHeight); |
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT); |
||||
|
||||
int prog = texType == GL_TEXTURE_EXTERNAL_OES ? progOES : prog2D; |
||||
glUseProgram(prog); |
||||
int vPos = glGetAttribLocation(prog, "vPosition"); |
||||
int vTC = glGetAttribLocation(prog, "vTexCoord"); |
||||
|
||||
glActiveTexture(GL_TEXTURE0); |
||||
glBindTexture(texType, tex); |
||||
glUniform1i(glGetUniformLocation(prog, "sTexture"), 0); |
||||
|
||||
glVertexAttribPointer(vPos, 2, GL_FLOAT, false, 4*2, vertexes); |
||||
glVertexAttribPointer(vTC, 2, GL_FLOAT, false, 4*2, texType == GL_TEXTURE_EXTERNAL_OES ? texCoordOES : texCoord2D); |
||||
glEnableVertexAttribArray(vPos); |
||||
glEnableVertexAttribArray(vTC); |
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
||||
glFlush(); |
||||
LOGD("drawTex(%u) costs %d ms", tex, getTimeInterval(t)); |
||||
} |
||||
|
||||
void drawFrameOrig() |
||||
{ |
||||
drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, 0); |
||||
} |
||||
|
||||
void procCPU(char* buff, int w, int h) |
||||
{ |
||||
int64_t t = getTimeMs(); |
||||
for(int i=0; i<h; i++) |
||||
{ |
||||
buff[i*w*4+i*4+0] = 255; |
||||
buff[i*w*4+i*4+4] = 255; |
||||
buff[i*w*4+i*4+8] = 255; |
||||
} |
||||
LOGD("procCPU() costs %d ms", getTimeInterval(t)); |
||||
} |
||||
|
||||
void drawFrameProcCPU() |
||||
{ |
||||
int64_t t; |
||||
drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); |
||||
|
||||
// let's modify pixels in FBO texture in C++ code (on CPU)
|
||||
const int BUFF_SIZE = 1<<24;//2k*2k*4;
|
||||
static char tmpBuff[BUFF_SIZE]; |
||||
if(texWidth*texHeight > BUFF_SIZE) |
||||
{ |
||||
LOGE("Internal temp buffer is too small, can't make CPU frame processing"); |
||||
return; |
||||
} |
||||
|
||||
// read
|
||||
t = getTimeMs(); |
||||
glReadPixels(0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); |
||||
LOGD("glReadPixels() costs %d ms", getTimeInterval(t)); |
||||
|
||||
// modify
|
||||
procCPU(tmpBuff, texWidth, texHeight); |
||||
|
||||
// write back
|
||||
t = getTimeMs(); |
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, tmpBuff); |
||||
LOGD("glTexSubImage2D() costs %d ms", getTimeInterval(t)); |
||||
|
||||
// render to screen
|
||||
drawTex(FBOtex, GL_TEXTURE_2D, 0); |
||||
} |
||||
|
||||
void procOCL(int tex, int w, int h) |
||||
{ |
||||
//TODO: not yet implemented
|
||||
} |
||||
|
||||
void drawFrameProcOCL() |
||||
{ |
||||
drawTex(texOES, GL_TEXTURE_EXTERNAL_OES, FBO); |
||||
|
||||
// modify pixels in FBO texture using OpenCL and CL-GL interop
|
||||
procOCL(FBOtex, texWidth, texHeight); |
||||
|
||||
// render to screen
|
||||
drawTex(FBOtex, GL_TEXTURE_2D, 0); |
||||
} |
||||
|
||||
|
||||
extern "C" void drawFrame() |
||||
{ |
||||
LOGD("*** drawFrame() ***"); |
||||
int64_t t = getTimeMs(); |
||||
//drawFrameOrig();
|
||||
drawFrameProcCPU(); |
||||
glFinish(); |
||||
LOGD("*** drawFrame() costs %d ms ***", getTimeInterval(t)); |
||||
} |
||||
|
||||
extern "C" void closeGL() |
||||
{ |
||||
LOGD("closeGL"); |
||||
deleteTex(&texOES); |
||||
|
||||
glUseProgram(0); |
||||
glDeleteProgram(progOES); |
||||
progOES = 0; |
||||
|
||||
releaseFBO(); |
||||
} |
||||
|
||||
extern "C" int initGL() |
||||
{ |
||||
LOGD("initGL"); |
||||
|
||||
closeGL(); |
||||
|
||||
const char* vs = (const char*)glGetString(GL_VERSION); |
||||
LOGD("GL_VERSION = %s", vs); |
||||
|
||||
progOES = makeShaderProg(vss, fssOES); |
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f); |
||||
|
||||
texOES = 0; |
||||
glGenTextures(1, &texOES); |
||||
glBindTexture(GL_TEXTURE_EXTERNAL_OES, texOES); |
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
||||
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
||||
|
||||
return texOES; |
||||
} |
||||
|
||||
extern "C" void changeSize(int width, int height) |
||||
{ |
||||
const int MAX_W=1<<11, MAX_H=1<<11; |
||||
LOGD("changeSize: %dx%d", width, height); |
||||
texWidth = width <= MAX_W ? width : MAX_W; |
||||
texHeight = height <= MAX_H ? height : MAX_H; |
||||
initFBO(texWidth, texHeight); |
||||
} |
@ -0,0 +1,19 @@ |
||||
#include <android/log.h> |
||||
#define LOG_TAG "JNIRenderer" |
||||
//#define LOGD(...)
|
||||
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)) |
||||
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)) |
||||
|
||||
#include <time.h> // clock_gettime |
||||
|
||||
static inline int64_t getTimeMs() |
||||
{ |
||||
struct timespec now; |
||||
clock_gettime(CLOCK_MONOTONIC, &now); |
||||
return (int64_t) now.tv_sec*1000 + now.tv_nsec/1000000; |
||||
} |
||||
|
||||
static inline int getTimeInterval(int64_t startTime) |
||||
{ |
||||
return int(getTimeMs() - startTime); |
||||
} |
@ -0,0 +1,26 @@ |
||||
#include <jni.h> |
||||
|
||||
int initGL(); |
||||
void closeGL(); |
||||
void changeSize(int width, int height); |
||||
void drawFrame(); |
||||
|
||||
JNIEXPORT jint JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_initGL(JNIEnv * env, jclass cls) |
||||
{ |
||||
return initGL(); |
||||
} |
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_closeGL(JNIEnv * env, jclass cls) |
||||
{ |
||||
closeGL(); |
||||
} |
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_changeSize(JNIEnv * env, jclass cls, jint width, jint height) |
||||
{ |
||||
changeSize(width, height); |
||||
} |
||||
|
||||
JNIEXPORT void JNICALL Java_org_opencv_samples_tutorial4_NativeGLRenderer_drawFrame(JNIEnv * env, jclass cls) |
||||
{ |
||||
drawFrame(); |
||||
} |
@ -0,0 +1,3 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<lint> |
||||
</lint> |
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,12 @@ |
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:tools="http://schemas.android.com/tools" |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
tools:context="${relativePackage}.${activityClass}" > |
||||
|
||||
<TextView |
||||
android:layout_width="wrap_content" |
||||
android:layout_height="wrap_content" |
||||
android:text="@string/app_name" /> |
||||
|
||||
</RelativeLayout> |
@ -0,0 +1,6 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<resources> |
||||
|
||||
<string name="app_name">OpenCV Tutorial 4 - Use OpenCL</string> |
||||
|
||||
</resources> |
@ -0,0 +1,282 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.concurrent.Semaphore; |
||||
import java.util.concurrent.TimeUnit; |
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig; |
||||
import javax.microedition.khronos.opengles.GL10; |
||||
|
||||
import android.annotation.SuppressLint; |
||||
import android.content.Context; |
||||
import android.graphics.Point; |
||||
import android.graphics.SurfaceTexture; |
||||
import android.hardware.camera2.CameraAccessException; |
||||
import android.hardware.camera2.CameraCaptureSession; |
||||
import android.hardware.camera2.CameraCharacteristics; |
||||
import android.hardware.camera2.CameraDevice; |
||||
import android.hardware.camera2.CameraManager; |
||||
import android.hardware.camera2.CaptureRequest; |
||||
import android.hardware.camera2.params.StreamConfigurationMap; |
||||
import android.os.Handler; |
||||
import android.os.HandlerThread; |
||||
import android.util.Log; |
||||
import android.util.Size; |
||||
import android.view.Surface; |
||||
|
||||
@SuppressLint("NewApi") public class Camera2Renderer extends MyGLRendererBase { |
||||
|
||||
protected final String LOGTAG = "Camera2Renderer"; |
||||
private CameraDevice mCameraDevice; |
||||
private CameraCaptureSession mCaptureSession; |
||||
private CaptureRequest.Builder mPreviewRequestBuilder; |
||||
private String mCameraID; |
||||
private Size mPreviewSize = new Size(1280, 720); |
||||
|
||||
private HandlerThread mBackgroundThread; |
||||
private Handler mBackgroundHandler; |
||||
private Semaphore mCameraOpenCloseLock = new Semaphore(1); |
||||
|
||||
Camera2Renderer(MyGLSurfaceView view) { |
||||
super(view); |
||||
} |
||||
|
||||
public void onResume() { |
||||
stopBackgroundThread(); |
||||
super.onResume(); |
||||
startBackgroundThread(); |
||||
} |
||||
|
||||
public void onPause() { |
||||
super.onPause(); |
||||
stopBackgroundThread(); |
||||
} |
||||
|
||||
boolean cacPreviewSize(final int width, final int height) { |
||||
Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height); |
||||
if(mCameraID == null) |
||||
return false; |
||||
CameraManager manager = (CameraManager) mView.getContext() |
||||
.getSystemService(Context.CAMERA_SERVICE); |
||||
try { |
||||
CameraCharacteristics characteristics = manager |
||||
.getCameraCharacteristics(mCameraID); |
||||
StreamConfigurationMap map = characteristics |
||||
.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); |
||||
int bestWidth = 0, bestHeight = 0; |
||||
float aspect = (float)width / height; |
||||
for (Size psize : map.getOutputSizes(SurfaceTexture.class)) { |
||||
int w = psize.getWidth(), h = psize.getHeight(); |
||||
Log.d(LOGTAG, "trying size: "+w+"x"+h); |
||||
if ( width >= w && height >= h && |
||||
bestWidth <= w && bestHeight <= h && |
||||
Math.abs(aspect - (float)w/h) < 0.2 ) { |
||||
bestWidth = w; |
||||
bestHeight = h; |
||||
//mPreviewSize = psize;
|
||||
} |
||||
} |
||||
Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight); |
||||
if( mPreviewSize.getWidth() == bestWidth && |
||||
mPreviewSize.getHeight() == bestHeight ) |
||||
return false; |
||||
else { |
||||
mPreviewSize = new Size(bestWidth, bestHeight); |
||||
return true; |
||||
} |
||||
} catch (CameraAccessException e) { |
||||
Log.e(LOGTAG, "cacPreviewSize - Camera Access Exception"); |
||||
} catch (IllegalArgumentException e) { |
||||
Log.e(LOGTAG, "cacPreviewSize - Illegal Argument Exception"); |
||||
} catch (SecurityException e) { |
||||
Log.e(LOGTAG, "cacPreviewSize - Security Exception"); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
protected void openCamera() { |
||||
Log.i(LOGTAG, "openCamera"); |
||||
//closeCamera();
|
||||
CameraManager manager = (CameraManager) mView.getContext() |
||||
.getSystemService(Context.CAMERA_SERVICE); |
||||
try { |
||||
for (String cameraID : manager.getCameraIdList()) { |
||||
CameraCharacteristics characteristics = manager |
||||
.getCameraCharacteristics(cameraID); |
||||
if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) |
||||
continue; |
||||
|
||||
mCameraID = cameraID; |
||||
break; |
||||
} |
||||
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { |
||||
throw new RuntimeException( |
||||
"Time out waiting to lock camera opening."); |
||||
} |
||||
manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); |
||||
} catch (CameraAccessException e) { |
||||
Log.e(LOGTAG, "OpenCamera - Camera Access Exception"); |
||||
} catch (IllegalArgumentException e) { |
||||
Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception"); |
||||
} catch (SecurityException e) { |
||||
Log.e(LOGTAG, "OpenCamera - Security Exception"); |
||||
} catch (InterruptedException e) { |
||||
Log.e(LOGTAG, "OpenCamera - Interrupted Exception"); |
||||
} |
||||
} |
||||
|
||||
protected void closeCamera() { |
||||
Log.i(LOGTAG, "closeCamera"); |
||||
try { |
||||
mCameraOpenCloseLock.acquire(); |
||||
if (null != mCaptureSession) { |
||||
mCaptureSession.close(); |
||||
mCaptureSession = null; |
||||
} |
||||
if (null != mCameraDevice) { |
||||
mCameraDevice.close(); |
||||
mCameraDevice = null; |
||||
} |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException( |
||||
"Interrupted while trying to lock camera closing.", e); |
||||
} finally { |
||||
mCameraOpenCloseLock.release(); |
||||
} |
||||
} |
||||
|
||||
private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { |
||||
|
||||
@Override |
||||
public void onOpened(CameraDevice cameraDevice) { |
||||
mCameraDevice = cameraDevice; |
||||
mCameraOpenCloseLock.release(); |
||||
createCameraPreviewSession(); |
||||
} |
||||
|
||||
@Override |
||||
public void onDisconnected(CameraDevice cameraDevice) { |
||||
//mCameraOpenCloseLock.release();
|
||||
cameraDevice.close(); |
||||
mCameraDevice = null; |
||||
} |
||||
|
||||
@Override |
||||
public void onError(CameraDevice cameraDevice, int error) { |
||||
cameraDevice.close(); |
||||
mCameraDevice = null; |
||||
mCameraOpenCloseLock.release(); |
||||
} |
||||
|
||||
}; |
||||
|
||||
private void createCameraPreviewSession() { |
||||
Log.i(LOGTAG, "createCameraPreviewSession"); |
||||
try { |
||||
mCameraOpenCloseLock.acquire(); |
||||
if (null == mCameraDevice) { |
||||
mCameraOpenCloseLock.release(); |
||||
Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened"); |
||||
return; |
||||
} |
||||
if (null != mCaptureSession) { |
||||
mCameraOpenCloseLock.release(); |
||||
Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); |
||||
return; |
||||
} |
||||
if(null == mSTex) { |
||||
Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null"); |
||||
return; |
||||
} |
||||
Log.d(LOGTAG, "starting preview "+mPreviewSize.getWidth()+"x"+mPreviewSize.getHeight()); |
||||
mSTex.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight()); |
||||
|
||||
Surface surface = new Surface(mSTex); |
||||
Log.d(LOGTAG, "createCameraPreviewSession: surface = " + surface); |
||||
|
||||
mPreviewRequestBuilder = mCameraDevice |
||||
.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); |
||||
mPreviewRequestBuilder.addTarget(surface); |
||||
|
||||
mCameraDevice.createCaptureSession(Arrays.asList(surface), |
||||
new CameraCaptureSession.StateCallback() { |
||||
@Override |
||||
public void onConfigured( |
||||
CameraCaptureSession cameraCaptureSession) { |
||||
mCaptureSession = cameraCaptureSession; |
||||
try { |
||||
mPreviewRequestBuilder |
||||
.set(CaptureRequest.CONTROL_AF_MODE, |
||||
CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); |
||||
mPreviewRequestBuilder |
||||
.set(CaptureRequest.CONTROL_AE_MODE, |
||||
CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); |
||||
|
||||
mCaptureSession.setRepeatingRequest( |
||||
mPreviewRequestBuilder.build(), null, |
||||
mBackgroundHandler); |
||||
} catch (CameraAccessException e) { |
||||
Log.e(LOGTAG, "createCaptureSession failed"); |
||||
} |
||||
mCameraOpenCloseLock.release(); |
||||
} |
||||
|
||||
@Override |
||||
public void onConfigureFailed( |
||||
CameraCaptureSession cameraCaptureSession) { |
||||
Log.e(LOGTAG, "createCameraPreviewSession failed"); |
||||
mCameraOpenCloseLock.release(); |
||||
} |
||||
}, null); |
||||
} catch (CameraAccessException e) { |
||||
Log.e(LOGTAG, "createCameraPreviewSession"); |
||||
} catch (InterruptedException e) { |
||||
throw new RuntimeException( |
||||
"Interrupted while createCameraPreviewSession", e); |
||||
} |
||||
finally { |
||||
mCameraOpenCloseLock.release(); |
||||
} |
||||
} |
||||
|
||||
private void startBackgroundThread() { |
||||
Log.i(LOGTAG, "startBackgroundThread"); |
||||
mBackgroundThread = new HandlerThread("CameraBackground"); |
||||
mBackgroundThread.start(); |
||||
mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); |
||||
} |
||||
|
||||
private void stopBackgroundThread() { |
||||
Log.i(LOGTAG, "stopBackgroundThread"); |
||||
if(mBackgroundThread == null) |
||||
return; |
||||
mBackgroundThread.quitSafely(); |
||||
try { |
||||
mBackgroundThread.join(); |
||||
mBackgroundThread = null; |
||||
mBackgroundHandler = null; |
||||
} catch (InterruptedException e) { |
||||
Log.e(LOGTAG, "stopBackgroundThread"); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
protected void setCameraPreviewSize(int width, int height) { |
||||
//mPreviewSize = new Size(width, height);
|
||||
if( !cacPreviewSize(width, height) ) |
||||
return; |
||||
try { |
||||
mCameraOpenCloseLock.acquire(); |
||||
if (null != mCaptureSession) { |
||||
mCaptureSession.close(); |
||||
mCaptureSession = null; |
||||
} |
||||
mCameraOpenCloseLock.release(); |
||||
createCameraPreviewSession(); |
||||
} catch (InterruptedException e) { |
||||
mCameraOpenCloseLock.release(); |
||||
throw new RuntimeException( |
||||
"Interrupted while setCameraPreviewSize.", e); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,75 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
import java.io.IOException; |
||||
import java.util.List; |
||||
|
||||
import android.hardware.Camera; |
||||
import android.hardware.Camera.Size; |
||||
import android.util.Log; |
||||
|
||||
@SuppressWarnings("deprecation") |
||||
public class CameraRenderer extends MyGLRendererBase { |
||||
|
||||
protected final String LOGTAG = "CameraRenderer"; |
||||
private Camera mCamera; |
||||
boolean mPreviewStarted = false; |
||||
|
||||
CameraRenderer(MyGLSurfaceView view) { |
||||
super(view); |
||||
} |
||||
|
||||
protected void closeCamera() { |
||||
Log.i(LOGTAG, "closeCamera"); |
||||
if(mCamera != null) { |
||||
mCamera.stopPreview(); |
||||
mPreviewStarted = false; |
||||
mCamera.release(); |
||||
mCamera = null; |
||||
} |
||||
} |
||||
|
||||
protected void openCamera() { |
||||
Log.i(LOGTAG, "openCamera"); |
||||
closeCamera(); |
||||
mCamera = Camera.open(); |
||||
try { |
||||
mCamera.setPreviewTexture(mSTex); |
||||
} catch (IOException ioe) { |
||||
Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); |
||||
} |
||||
} |
||||
|
||||
public void setCameraPreviewSize(int width, int height) { |
||||
Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); |
||||
if(mCamera == null) |
||||
return; |
||||
if(mPreviewStarted) { |
||||
mCamera.stopPreview(); |
||||
mPreviewStarted = false; |
||||
} |
||||
Camera.Parameters param = mCamera.getParameters(); |
||||
List<Size> psize = param.getSupportedPreviewSizes(); |
||||
int bestWidth = 0, bestHeight = 0; |
||||
if (psize.size() > 0) { |
||||
float aspect = (float)width / height; |
||||
for (Size size : psize) { |
||||
int w = size.width, h = size.height; |
||||
Log.d("Renderer", "checking camera preview size: "+w+"x"+h); |
||||
if ( w <= width && h <= height && |
||||
w >= bestWidth && h >= bestHeight && |
||||
Math.abs(aspect - (float)w/h) < 0.2 ) { |
||||
bestWidth = w; |
||||
bestHeight = h; |
||||
} |
||||
} |
||||
if(bestWidth > 0 && bestHeight > 0) { |
||||
param.setPreviewSize(bestWidth, bestHeight); |
||||
Log.i(LOGTAG, "size: "+bestWidth+" x "+bestHeight); |
||||
} |
||||
} |
||||
param.set("orientation", "landscape"); |
||||
mCamera.setParameters(param); |
||||
mCamera.startPreview(); |
||||
mPreviewStarted = true; |
||||
} |
||||
} |
@ -0,0 +1,100 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
import javax.microedition.khronos.egl.EGLConfig; |
||||
import javax.microedition.khronos.opengles.GL10; |
||||
|
||||
import android.graphics.SurfaceTexture; |
||||
import android.opengl.GLES20; |
||||
import android.opengl.GLSurfaceView; |
||||
import android.util.Log; |
||||
|
||||
public abstract class MyGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { |
||||
protected final String LOGTAG = "MyGLRendererBase"; |
||||
protected int frameCounter; |
||||
protected long lastNanoTime; |
||||
|
||||
protected SurfaceTexture mSTex; |
||||
protected MyGLSurfaceView mView; |
||||
|
||||
protected boolean mGLInit = false; |
||||
protected boolean mTexUpdate = false; |
||||
|
||||
MyGLRendererBase(MyGLSurfaceView view) { |
||||
mView = view; |
||||
} |
||||
|
||||
protected abstract void openCamera(); |
||||
protected abstract void closeCamera(); |
||||
protected abstract void setCameraPreviewSize(int width, int height); |
||||
|
||||
public void onResume() { |
||||
Log.i(LOGTAG, "onResume"); |
||||
frameCounter = 0; |
||||
lastNanoTime = System.nanoTime(); |
||||
} |
||||
|
||||
public void onPause() { |
||||
Log.i(LOGTAG, "onPause"); |
||||
mGLInit = false; |
||||
mTexUpdate = false; |
||||
closeCamera(); |
||||
if(mSTex != null) { |
||||
mSTex.release(); |
||||
mSTex = null; |
||||
NativeGLRenderer.closeGL(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { |
||||
//Log.i(LOGTAG, "onFrameAvailable");
|
||||
mTexUpdate = true; |
||||
mView.requestRender(); |
||||
} |
||||
|
||||
@Override |
||||
public void onDrawFrame(GL10 gl) { |
||||
//Log.i(LOGTAG, "onDrawFrame");
|
||||
if (!mGLInit) |
||||
return; |
||||
|
||||
synchronized (this) { |
||||
if (mTexUpdate) { |
||||
mSTex.updateTexImage(); |
||||
mTexUpdate = false; |
||||
} |
||||
} |
||||
NativeGLRenderer.drawFrame(); |
||||
|
||||
// log FPS
|
||||
frameCounter++; |
||||
if(frameCounter >= 10) |
||||
{ |
||||
int fps = (int) (frameCounter * 1e9 / (System.nanoTime() - lastNanoTime)); |
||||
Log.i(LOGTAG, "drawFrame() FPS: "+fps); |
||||
frameCounter = 0; |
||||
lastNanoTime = System.nanoTime(); |
||||
} |
||||
} |
||||
|
||||
@Override |
||||
public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { |
||||
Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); |
||||
NativeGLRenderer.changeSize(surfaceWidth, surfaceHeight); |
||||
setCameraPreviewSize(surfaceWidth, surfaceHeight); |
||||
} |
||||
|
||||
@Override |
||||
public void onSurfaceCreated(GL10 gl, EGLConfig config) { |
||||
Log.i(LOGTAG, "onSurfaceCreated"); |
||||
String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); |
||||
if (strGLVersion != null) |
||||
Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); |
||||
|
||||
int hTex = NativeGLRenderer.initGL(); |
||||
mSTex = new SurfaceTexture(hTex); |
||||
mSTex.setOnFrameAvailableListener(this); |
||||
openCamera(); |
||||
mGLInit = true; |
||||
} |
||||
} |
@ -0,0 +1,50 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
import android.content.Context; |
||||
import android.opengl.GLSurfaceView; |
||||
import android.view.SurfaceHolder; |
||||
|
||||
class MyGLSurfaceView extends GLSurfaceView { |
||||
|
||||
MyGLRendererBase mRenderer; |
||||
|
||||
MyGLSurfaceView(Context context) { |
||||
super(context); |
||||
|
||||
if(android.os.Build.VERSION.SDK_INT >= 21) |
||||
mRenderer = new Camera2Renderer(this); |
||||
else |
||||
mRenderer = new CameraRenderer(this); |
||||
|
||||
setEGLContextClientVersion(2); |
||||
setRenderer(mRenderer); |
||||
setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); |
||||
} |
||||
|
||||
@Override |
||||
public void surfaceCreated(SurfaceHolder holder) { |
||||
super.surfaceCreated(holder); |
||||
} |
||||
|
||||
@Override |
||||
public void surfaceDestroyed(SurfaceHolder holder) { |
||||
super.surfaceDestroyed(holder); |
||||
} |
||||
|
||||
@Override |
||||
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { |
||||
super.surfaceChanged(holder, format, w, h); |
||||
} |
||||
|
||||
@Override |
||||
public void onResume() { |
||||
super.onResume(); |
||||
mRenderer.onResume(); |
||||
} |
||||
|
||||
@Override |
||||
public void onPause() { |
||||
mRenderer.onPause(); |
||||
super.onPause(); |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
public class NativeGLRenderer { |
||||
static |
||||
{ |
||||
System.loadLibrary("JNIrender"); |
||||
} |
||||
public static native int initGL(); |
||||
public static native void closeGL(); |
||||
public static native void drawFrame(); |
||||
public static native void changeSize(int width, int height); |
||||
} |
@ -0,0 +1,38 @@ |
||||
package org.opencv.samples.tutorial4; |
||||
|
||||
import android.app.Activity; |
||||
import android.content.pm.ActivityInfo; |
||||
import android.os.Bundle; |
||||
import android.view.Window; |
||||
import android.view.WindowManager; |
||||
|
||||
public class Tutorial4Activity extends Activity { |
||||
|
||||
private MyGLSurfaceView mView; |
||||
|
||||
@Override |
||||
public void onCreate(Bundle savedInstanceState) { |
||||
super.onCreate(savedInstanceState); |
||||
requestWindowFeature(Window.FEATURE_NO_TITLE); |
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, |
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN); |
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, |
||||
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); |
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); |
||||
|
||||
mView = new MyGLSurfaceView(this); |
||||
setContentView(mView); |
||||
} |
||||
|
||||
@Override |
||||
protected void onPause() { |
||||
mView.onPause(); |
||||
super.onPause(); |
||||
} |
||||
|
||||
@Override |
||||
protected void onResume() { |
||||
super.onResume(); |
||||
mView.onResume(); |
||||
} |
||||
} |
Loading…
Reference in new issue