├── .gitignore
├── AndroidExample
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── piasy
│ │ └── ugi
│ │ └── example
│ │ ├── EglContextHacker.java
│ │ ├── LandscapePreviewActivity.java
│ │ ├── MainActivity.java
│ │ └── SelectorActivity.java
│ └── res
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ ├── awesomeface.png
│ └── ic_launcher_background.xml
│ ├── layout
│ ├── activity_main.xml
│ └── activity_selector.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── styles.xml
├── LICENSE
├── README.md
├── UltraGpuImage-Android
├── .gitignore
├── CMakeLists.txt
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── ultra_gpu_image_filters_jni.cpp
│ └── ultra_gpu_image_jni.cpp
│ └── java
│ └── com
│ └── piasy
│ └── ugi
│ ├── UgiFilter.java
│ ├── UgiRenderer.java
│ ├── UgiRendererView.java
│ ├── UgiTransformation.java
│ ├── egl
│ ├── EglBase.java
│ ├── EglBase10.java
│ └── EglBase14.java
│ ├── filters
│ ├── UgiBrightnessFilter.java
│ ├── UgiColorInvertFilter.java
│ ├── UgiFilterGroup.java
│ └── UgiPreprocessFilter.java
│ └── utils
│ ├── Logging.java
│ └── ThreadUtils.java
├── UltraGpuImage-iOS
├── module.modulemap
├── project.yml
└── src
│ ├── Info.plist
│ ├── UgiFilter.h
│ ├── UgiLogging.h
│ ├── UgiLogging.m
│ ├── UgiRenderer.h
│ ├── UgiRenderer.mm
│ ├── UgiRendererView.h
│ ├── UgiRendererView.m
│ ├── UgiTransformation+Native.h
│ ├── UgiTransformation.h
│ ├── UgiTransformation.mm
│ ├── UltraGpuImage_iOS.h
│ └── filters
│ ├── UgiBrightnessFilter.h
│ ├── UgiBrightnessFilter.mm
│ ├── UgiColorInvertFilter.h
│ ├── UgiColorInvertFilter.mm
│ ├── UgiFilterGroup.h
│ ├── UgiFilterGroup.mm
│ ├── UgiPreprocessFilter.h
│ └── UgiPreprocessFilter.mm
├── UltraGpuImage.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── UltraGpuImage
├── project.yml
└── src
│ ├── filters
│ ├── ugi_brightness_filter.cpp
│ ├── ugi_brightness_filter.h
│ ├── ugi_color_invert_filter.cpp
│ ├── ugi_color_invert_filter.h
│ ├── ugi_filter_group.cpp
│ ├── ugi_filter_group.h
│ ├── ugi_preprocess_filter.cpp
│ └── ugi_preprocess_filter.h
│ ├── ugi_filter.cpp
│ ├── ugi_filter.h
│ ├── ugi_gl.h
│ ├── ugi_gl_utils.cpp
│ ├── ugi_gl_utils.h
│ ├── ugi_logging.cpp
│ ├── ugi_logging.h
│ ├── ugi_renderer.cpp
│ ├── ugi_renderer.h
│ ├── ugi_transformation.cpp
│ └── ugi_transformation.h
├── build.gradle
├── collect_src.sh
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── iOSExample
├── Podfile
├── Podfile.lock
├── iOSExample
│ ├── AppDelegate.h
│ ├── AppDelegate.m
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ └── Contents.json
│ │ ├── Contents.json
│ │ └── awesomeface.imageset
│ │ │ ├── Contents.json
│ │ │ └── awesomeface.png
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ ├── ViewController.h
│ ├── ViewController.m
│ └── main.m
└── project.yml
├── settings.gradle
└── setup_xcode_project.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | **.iml
2 | .gradle
3 | /local.properties
4 | /.idea/
5 | .DS_Store
6 | **/build
7 | /captures
8 | **/.externalNativeBuild
9 |
10 | **/*.xcodeproj
11 | **/xcuserdata/
12 | **/Pods/
13 |
14 | libs/
15 |
--------------------------------------------------------------------------------
/AndroidExample/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/AndroidExample/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion rootProject.ext.androidCompileSdkVersion
5 | defaultConfig {
6 | minSdkVersion rootProject.ext.androidMinSdkVersion
7 | targetSdkVersion rootProject.ext.androidTargetSdkVersion
8 | versionCode rootProject.ext.releaseVersionCode
9 | versionName rootProject.ext.releaseVersionName
10 |
11 | applicationId "com.piasy.ugi.example"
12 |
13 | ndk.abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | compileOptions {
22 | sourceCompatibility JavaVersion.VERSION_1_8
23 | targetCompatibility JavaVersion.VERSION_1_8
24 | }
25 | }
26 |
27 | dependencies {
28 | implementation project(':UltraGpuImage-Android')
29 |
30 | implementation 'com.jakewharton:butterknife:9.0.0-rc3'
31 | annotationProcessor 'com.jakewharton:butterknife-compiler:9.0.0-rc3'
32 |
33 | implementation 'com.github.hotchemi:permissionsdispatcher:3.0.1'
34 | annotationProcessor 'com.github.hotchemi:permissionsdispatcher-processor:3.0.1'
35 |
36 | implementation 'org.webrtc:google-webrtc:1.0.25821'
37 | }
38 |
--------------------------------------------------------------------------------
/AndroidExample/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/java/com/piasy/ugi/example/EglContextHacker.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.example;
2 |
3 | import android.opengl.EGLContext;
4 | import java.lang.reflect.Field;
5 | import org.webrtc.EglBase;
6 |
7 | /**
8 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
9 | */
10 | public class EglContextHacker {
11 | public static EGLContext getContextFromEglBase(EglBase eglBase) {
12 | EglBase.Context context = eglBase.getEglBaseContext();
13 | try {
14 | Field f = context.getClass().getDeclaredField("egl14Context");
15 | f.setAccessible(true);
16 | return (EGLContext) f.get(context);
17 | } catch (NoSuchFieldException | IllegalAccessException e) {
18 | e.printStackTrace();
19 | }
20 | return null;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/java/com/piasy/ugi/example/LandscapePreviewActivity.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.example;
2 |
3 | /**
4 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
5 | */
6 | public class LandscapePreviewActivity extends MainActivity {
7 | }
8 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/java/com/piasy/ugi/example/SelectorActivity.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.example;
2 |
3 | import android.Manifest;
4 | import android.app.Activity;
5 | import android.content.Intent;
6 | import android.hardware.Camera;
7 | import android.os.Bundle;
8 | import android.widget.CheckBox;
9 | import androidx.annotation.NonNull;
10 | import butterknife.BindView;
11 | import butterknife.ButterKnife;
12 | import butterknife.OnClick;
13 | import com.piasy.ugi.UgiRendererView;
14 | import permissions.dispatcher.NeedsPermission;
15 | import permissions.dispatcher.RuntimePermissions;
16 |
17 | @RuntimePermissions
18 | public class SelectorActivity extends Activity {
19 |
20 | @BindView(R.id.frontCamera)
21 | CheckBox frontCamera;
22 | @BindView(R.id.portrait)
23 | CheckBox portrait;
24 |
25 | @Override
26 | protected void onCreate(Bundle savedInstanceState) {
27 | super.onCreate(savedInstanceState);
28 | setContentView(R.layout.activity_selector);
29 |
30 | SelectorActivityPermissionsDispatcher.checkPermissionWithPermissionCheck(this);
31 | }
32 |
33 | @Override
34 | public void onRequestPermissionsResult(final int requestCode,
35 | @NonNull final String[] permissions, @NonNull final int[] grantResults) {
36 | super.onRequestPermissionsResult(requestCode, permissions, grantResults);
37 | SelectorActivityPermissionsDispatcher.onRequestPermissionsResult(this, requestCode,
38 | grantResults);
39 | }
40 |
41 | @OnClick(R.id.picture)
42 | void picture() {
43 | startDemo(UgiRendererView.RENDER_MODE_PICTURE);
44 | }
45 |
46 | @OnClick(R.id.camera)
47 | void camera() {
48 | startDemo(UgiRendererView.RENDER_MODE_CAMERA_PREVIEW);
49 | }
50 |
51 | @NeedsPermission({
52 | Manifest.permission.CAMERA,
53 | Manifest.permission.WRITE_EXTERNAL_STORAGE,
54 | })
55 | void checkPermission() {
56 | ButterKnife.bind(this);
57 | }
58 |
59 | private void startDemo(int renderMode) {
60 | Intent intent = new Intent(this,
61 | portrait.isChecked() ? MainActivity.class : LandscapePreviewActivity.class);
62 | intent.putExtra(MainActivity.MODE_EXTRA_KEY, renderMode);
63 | intent.putExtra(MainActivity.CAMERA_FACE_EXTRA_KEY,
64 | frontCamera.isChecked() ? Camera.CameraInfo.CAMERA_FACING_FRONT
65 | : Camera.CameraInfo.CAMERA_FACING_BACK);
66 | startActivity(intent);
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/drawable/awesomeface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/drawable/awesomeface.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
10 |
12 |
14 |
16 |
18 |
20 |
22 |
24 |
26 |
28 |
30 |
32 |
34 |
36 |
38 |
40 |
42 |
44 |
46 |
48 |
50 |
52 |
54 |
56 |
58 |
60 |
62 |
64 |
66 |
68 |
70 |
72 |
74 |
75 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
21 |
22 |
27 |
28 |
37 |
38 |
47 |
48 |
57 |
58 |
66 |
67 |
68 |
73 |
74 |
83 |
84 |
93 |
94 |
95 |
100 |
101 |
110 |
111 |
120 |
121 |
122 |
127 |
128 |
133 |
134 |
139 |
140 |
145 |
146 |
152 |
153 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/layout/activity_selector.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
17 |
24 |
25 |
32 |
33 |
39 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/AndroidExample/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | UltraGpuImage
3 |
4 |
--------------------------------------------------------------------------------
/AndroidExample/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Piasy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UltraGpuImage
2 |
3 | The ultimate 2D image rendering engine, inspired from [cats-oss/android-gpuimage](https://github.com/cats-oss/android-gpuimage), reinventing the wheel as my first OpenGL project after walking through the [Learn OpenGL](https://learnopengl.com/) tutorial.
4 |
5 | _This project is still under development, stay tuned!_
6 |
7 | ## Architecture
8 |
9 | UltraGpuImage has 3 layers:
10 |
11 | + Core OpenGL logic, including filter hierarchy, writing in C++ (cross-platform);
12 | + OpenGL context and window management, together with Renderer API, writing in platform-specific code (Java, ObjC, etc.);
13 | + View wrapper, providing the most easy-to-use API, writing in platform-specific code (Java, ObjC, etc.);
14 |
15 | ## Get started
16 |
17 | TODO
18 |
19 | ### iOS project setup
20 |
21 | Install [yonaskolb/XcodeGen](https://github.com/yonaskolb/XcodeGen) and CocoaPods, then run `setup_xcode_project.sh`, then open `UltraGpuImage.xcworkspace` with Xcode.
22 |
23 | ## Check points
24 |
25 | + [x] Android Bitmap rendering
26 | + [x] Android OES camera preview
27 | + [x] iOS UIImage rendering
28 | + [ ] iOS camera preview
29 | + [ ] more filters
30 | + [ ] support other platforms
31 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | include_directories(
4 | ../UltraGpuImage/src
5 | )
6 |
7 | file(GLOB_RECURSE ugi_filter_sources
8 | ../UltraGpuImage/src/filters/*.cpp
9 | )
10 |
11 | file(GLOB_RECURSE ugi_sources
12 | ../UltraGpuImage/src/ugi_logging.cpp
13 | ../UltraGpuImage/src/ugi_renderer.cpp
14 | ../UltraGpuImage/src/ugi_transformation.cpp
15 | ../UltraGpuImage/src/ugi_filter.cpp
16 | ../UltraGpuImage/src/ugi_gl_utils.cpp
17 | )
18 |
19 | add_library(
20 | UltraGpuImage
21 |
22 | SHARED
23 |
24 | ${ugi_sources}
25 | ${ugi_filter_sources}
26 | src/main/cpp/ultra_gpu_image_jni.cpp
27 | src/main/cpp/ultra_gpu_image_filters_jni.cpp
28 | )
29 |
30 |
31 | target_link_libraries(
32 | UltraGpuImage
33 |
34 | log
35 | EGL
36 | GLESv3
37 | )
38 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion rootProject.ext.androidCompileSdkVersion
5 | defaultConfig {
6 | minSdkVersion rootProject.ext.androidMinSdkVersion
7 | targetSdkVersion rootProject.ext.androidTargetSdkVersion
8 | versionCode rootProject.ext.releaseVersionCode
9 | versionName rootProject.ext.releaseVersionName
10 |
11 | externalNativeBuild {
12 | cmake {
13 | arguments '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=c++_shared'
14 | cppFlags "-std=c++11"
15 | abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
16 | }
17 | }
18 |
19 | sourceSets.main.jni.srcDirs += '../UltraGpuImage/src'
20 | }
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | compileOptions {
28 | sourceCompatibility JavaVersion.VERSION_1_8
29 | targetCompatibility JavaVersion.VERSION_1_8
30 | }
31 | externalNativeBuild {
32 | cmake {
33 | path "CMakeLists.txt"
34 | }
35 | }
36 | }
37 |
38 | dependencies {
39 | api 'com.google.code.findbugs:jsr305:3.0.2'
40 | implementation "androidx.annotation:annotation:1.0.1"
41 | }
42 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/cpp/ultra_gpu_image_filters_jni.cpp:
--------------------------------------------------------------------------------
1 | #include
2 |
3 | #include "filters/ugi_filter_group.h"
4 | #include "filters/ugi_preprocess_filter.h"
5 | #include "filters/ugi_color_invert_filter.h"
6 | #include "filters/ugi_brightness_filter.h"
7 |
8 | extern "C" {
9 |
10 | JNIEXPORT jlong JNICALL
11 | Java_com_piasy_ugi_UgiFilter_nativeCreate(JNIEnv* env, jclass type, jint filterType) {
12 | Ugi::Filter* filter = nullptr;
13 | switch (Ugi::FilterType(filterType)) {
14 | case Ugi::kFilterGroup:
15 | filter = new Ugi::FilterGroup();
16 | break;
17 | case Ugi::kFilterPreprocess:
18 | filter = new Ugi::PreprocessFilter();
19 | break;
20 | case Ugi::kFilterColorInvert:
21 | filter = new Ugi::ColorInvertFilter();
22 | break;
23 | case Ugi::kFilterBrightness:
24 | filter = new Ugi::BrightnessFilter();
25 | break;
26 | default:
27 | break;
28 | }
29 | return reinterpret_cast(filter);
30 | }
31 |
32 | JNIEXPORT void JNICALL
33 | Java_com_piasy_ugi_filters_UgiFilterGroup_nativeAddFilter(
34 | JNIEnv* env, jclass type, jlong handle, jlong filterHandle) {
35 | Ugi::FilterGroup* group = reinterpret_cast(handle);
36 | Ugi::Filter* filter = reinterpret_cast(filterHandle);
37 | if (group && filter) {
38 | group->AddFilter(filter);
39 | }
40 | }
41 |
42 | JNIEXPORT void JNICALL
43 | Java_com_piasy_ugi_filters_UgiBrightnessFilter_nativeSetBrightness(
44 | JNIEnv* env, jclass type, jlong handle, jfloat brightness) {
45 | Ugi::BrightnessFilter* filter = reinterpret_cast(handle);
46 | if (filter) {
47 | filter->SetBrightness(brightness);
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/cpp/ultra_gpu_image_jni.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #include "ugi_renderer.h"
5 | #include "ugi_transformation.h"
6 | #include "ugi_logging.h"
7 |
8 | extern "C" {
9 |
10 | static bool g_log_func_set_ = false;
11 |
12 | static void ugi_android_log(int level, const char* log) {
13 | if (level == UGI_LOG_LEVEL_ERROR) {
14 | __android_log_write(ANDROID_LOG_ERROR, "ugi", log);
15 | } else {
16 | __android_log_write(ANDROID_LOG_INFO, "ugi", log);
17 | }
18 | }
19 |
20 | JNIEXPORT jlong JNICALL
21 | Java_com_piasy_ugi_UgiRenderer_nativeCreate(JNIEnv* env, jclass type, jlong nativeTransformation) {
22 | if (!g_log_func_set_) {
23 | g_log_func_set_ = true;
24 | ugi_set_log_func(ugi_android_log);
25 | }
26 |
27 | Ugi::Transformation* transformation
28 | = reinterpret_cast(nativeTransformation);
29 | if (transformation) {
30 | Ugi::Renderer* renderer = new Ugi::Renderer(*transformation);
31 | return reinterpret_cast(renderer);
32 | } else {
33 | return 0;
34 | }
35 | }
36 |
37 | JNIEXPORT void JNICALL
38 | Java_com_piasy_ugi_UgiRenderer_nativeOnSurfaceCreated(
39 | JNIEnv* env, jclass type, jlong handle) {
40 | Ugi::Renderer* renderer = reinterpret_cast(handle);
41 | if (renderer) {
42 | renderer->OnSurfaceCreated();
43 | }
44 | }
45 |
46 | JNIEXPORT void JNICALL
47 | Java_com_piasy_ugi_UgiRenderer_nativeOnSurfaceDestroyed(JNIEnv* env, jclass type, jlong handle) {
48 | Ugi::Renderer* renderer = reinterpret_cast(handle);
49 | if (renderer) {
50 | renderer->OnSurfaceDestroyed();
51 | }
52 | }
53 |
54 | JNIEXPORT void JNICALL
55 | Java_com_piasy_ugi_UgiRenderer_nativeRenderTexture(
56 | JNIEnv* env, jclass type, jlong handle, jint textureType, jint textureId) {
57 | Ugi::Renderer* renderer = reinterpret_cast(handle);
58 | if (renderer) {
59 | renderer->RenderTexture(Ugi::TextureType(textureType), static_cast(textureId));
60 | }
61 | }
62 |
63 | JNIEXPORT void JNICALL
64 | Java_com_piasy_ugi_UgiRenderer_nativeUpdateTransformation(
65 | JNIEnv* env, jclass type, jlong handle, jlong nativeTransformation) {
66 | Ugi::Renderer* renderer = reinterpret_cast(handle);
67 | Ugi::Transformation* transformation
68 | = reinterpret_cast(nativeTransformation);
69 | if (renderer && transformation) {
70 | renderer->UpdateTransformation(*transformation);
71 | }
72 | }
73 |
74 | JNIEXPORT void JNICALL
75 | Java_com_piasy_ugi_UgiRenderer_nativeSetFilter(
76 | JNIEnv* env, jclass type, jlong handle, jlong filterHandle) {
77 | Ugi::Renderer* renderer = reinterpret_cast(handle);
78 | Ugi::Filter* filter = reinterpret_cast(filterHandle);
79 | if (renderer && filter) {
80 | renderer->SetFilter(filter);
81 | }
82 | }
83 |
84 | JNIEXPORT void JNICALL
85 | Java_com_piasy_ugi_UgiRenderer_nativeDestroy(JNIEnv* env, jclass type, jlong handle) {
86 | Ugi::Renderer* renderer = reinterpret_cast(handle);
87 | if (renderer) {
88 | delete renderer;
89 | }
90 | }
91 |
92 | JNIEXPORT jlong JNICALL
93 | Java_com_piasy_ugi_UgiTransformation_nativeCreate(
94 | JNIEnv* env, jclass type, jint inputWidth, jint inputHeight, jint outputWidth,
95 | jint outputHeight) {
96 | Ugi::Transformation* transformation
97 | = new Ugi::Transformation(Ugi::Transformation::Size(inputWidth, inputHeight),
98 | Ugi::Transformation::Size(outputWidth, outputHeight));
99 | return reinterpret_cast(transformation);
100 | }
101 |
102 | JNIEXPORT void JNICALL
103 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateInput(
104 | JNIEnv* env, jclass type, jlong handle, jint width, jint height) {
105 | Ugi::Transformation* transformation = reinterpret_cast(handle);
106 | if (transformation) {
107 | transformation->UpdateInput(Ugi::Transformation::Size(width, height));
108 | }
109 | }
110 |
111 | JNIEXPORT void JNICALL
112 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateOutput(
113 | JNIEnv* env, jclass type, jlong handle, jint width, jint height) {
114 | Ugi::Transformation* transformation = reinterpret_cast(handle);
115 | if (transformation) {
116 | transformation->UpdateOutput(Ugi::Transformation::Size(width, height));
117 | }
118 | }
119 |
120 | JNIEXPORT void JNICALL
121 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateCrop(
122 | JNIEnv* env, jclass type, jlong handle, jint x, jint y, jint width, jint height) {
123 | Ugi::Transformation* transformation = reinterpret_cast(handle);
124 | if (transformation) {
125 | transformation->UpdateCrop(Ugi::Transformation::Rect(x, y, width, height));
126 | }
127 | }
128 |
129 | JNIEXPORT void JNICALL
130 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateFlip(
131 | JNIEnv* env, jclass type, jlong handle, jint flip) {
132 | Ugi::Transformation* transformation = reinterpret_cast(handle);
133 | if (transformation) {
134 | transformation->UpdateFlip(Ugi::Transformation::Flip(flip));
135 | }
136 | }
137 |
138 | JNIEXPORT void JNICALL
139 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateRotation(
140 | JNIEnv* env, jclass type, jlong handle, jint rotation) {
141 | Ugi::Transformation* transformation = reinterpret_cast(handle);
142 | if (transformation) {
143 | transformation->UpdateRotation(Ugi::Transformation::Rotation(rotation));
144 | }
145 | }
146 |
147 | JNIEXPORT void JNICALL
148 | Java_com_piasy_ugi_UgiTransformation_nativeUpdateScaleType(
149 | JNIEnv* env, jclass type, jlong handle, jint scaleType) {
150 | Ugi::Transformation* transformation = reinterpret_cast(handle);
151 | if (transformation) {
152 | transformation->UpdateScaleType(Ugi::Transformation::ScaleType(scaleType));
153 | }
154 | }
155 |
156 | JNIEXPORT jint JNICALL
157 | Java_com_piasy_ugi_UgiTransformation_nativeGetInputWidth(JNIEnv* env, jclass type, jlong handle) {
158 | Ugi::Transformation* transformation = reinterpret_cast(handle);
159 | return transformation ? transformation->input_width() : 0;
160 | }
161 |
162 | JNIEXPORT jint JNICALL
163 | Java_com_piasy_ugi_UgiTransformation_nativeGetInputHeight(JNIEnv* env, jclass type, jlong handle) {
164 | Ugi::Transformation* transformation = reinterpret_cast(handle);
165 | return transformation ? transformation->input_height() : 0;
166 | }
167 |
168 | JNIEXPORT jint JNICALL
169 | Java_com_piasy_ugi_UgiTransformation_nativeGetRotation(JNIEnv* env, jclass type, jlong handle) {
170 | Ugi::Transformation* transformation = reinterpret_cast(handle);
171 | return transformation ? transformation->rotation() : 0;
172 | }
173 |
174 | JNIEXPORT jint JNICALL
175 | Java_com_piasy_ugi_UgiTransformation_nativeGetFlip(JNIEnv* env, jclass type, jlong handle) {
176 | Ugi::Transformation* transformation = reinterpret_cast(handle);
177 | return transformation ? transformation->flip() : 0;
178 | }
179 |
180 | JNIEXPORT void JNICALL
181 | Java_com_piasy_ugi_UgiTransformation_nativeDestroy(JNIEnv* env, jclass type, jlong handle) {
182 | Ugi::Transformation* transformation = reinterpret_cast(handle);
183 | if (transformation) {
184 | delete transformation;
185 | }
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/UgiFilter.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi;
2 |
3 | import androidx.annotation.IntDef;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
7 | *
8 | * Warning: instance can't be reused for multiple renderer.
9 | */
10 | public abstract class UgiFilter {
11 | public static final int FILTER_GROUP = 0;
12 | public static final int FILTER_PREPROCESS = 1;
13 | public static final int FILTER_COLOR_INVERT = 2;
14 | public static final int FILTER_BRIGHTNESS = 3;
15 |
16 | protected long mNativeHandle;
17 |
18 | public UgiFilter(final @FilterType int filterType) {
19 | mNativeHandle = nativeCreate(filterType);
20 | }
21 |
22 | private static native long nativeCreate(int filterType);
23 |
24 | public long getNativeHandle() {
25 | return mNativeHandle;
26 | }
27 |
28 | void releaseHandle() {
29 | mNativeHandle = 0;
30 | }
31 |
32 | @IntDef(value = {
33 | FILTER_GROUP,
34 | FILTER_PREPROCESS,
35 | FILTER_COLOR_INVERT,
36 | FILTER_BRIGHTNESS,
37 | })
38 | @interface FilterType {
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/UgiRenderer.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi;
2 |
3 | import android.graphics.SurfaceTexture;
4 | import android.opengl.EGLContext;
5 | import android.opengl.GLES20;
6 | import android.os.Handler;
7 | import android.os.HandlerThread;
8 | import android.view.Surface;
9 | import com.piasy.ugi.egl.EglBase;
10 | import com.piasy.ugi.egl.EglBase14;
11 | import com.piasy.ugi.utils.Logging;
12 | import com.piasy.ugi.utils.ThreadUtils;
13 |
14 | /**
15 | * Created by Piasy{github.com/Piasy} on 2018/12/17.
16 | */
17 | public class UgiRenderer {
18 | private static final String TAG = "UgiRenderer";
19 |
20 | private static final int TEXTURE_TYPE_RGB = 0;
21 | private static final int TEXTURE_TYPE_OES = 1;
22 |
23 | static {
24 | System.loadLibrary("UltraGpuImage");
25 | }
26 |
27 | private final String mName;
28 | private final Handler mRenderHandler;
29 | private final UgiTransformation mTransformation;
30 | private final EglSurfaceCreation mEglSurfaceCreationRunnable = new EglSurfaceCreation();
31 |
32 | private EglBase mEglBase;
33 | private UgiFilter mFilter;
34 |
35 | private long mNativeHandle;
36 |
37 | public UgiRenderer(EGLContext sharedContext, int[] configAttributes) {
38 | this("", sharedContext, configAttributes);
39 | }
40 |
41 | public UgiRenderer(String name, EGLContext sharedContext, int[] configAttributes) {
42 | mName = name;
43 | mTransformation = new UgiTransformation(480, 640, 480, 640);
44 | mNativeHandle = nativeCreate(mTransformation.mNativeHandle);
45 |
46 | logInfo("new UgiRenderer, handle " + mNativeHandle);
47 |
48 | HandlerThread renderThread = new HandlerThread("UgiRenderer-" + name);
49 | renderThread.start();
50 | mRenderHandler = new Handler(renderThread.getLooper());
51 |
52 | // Create EGL context on the newly created render thread. It should be possibly to create
53 | // the context on this thread and make it current on the render thread, but this causes
54 | // failure on some Marvel based JB devices.
55 | // https://bugs.chromium.org/p/webrtc/issues/detail?id=6350.
56 | ThreadUtils.invokeAtFrontUninterruptibly(mRenderHandler,
57 | () -> mEglBase = EglBase.create(
58 | sharedContext == null ? null : new EglBase14.Context(sharedContext),
59 | configAttributes));
60 | logInfo("new UgiRenderer success");
61 | }
62 |
63 | private static native long nativeCreate(long nativeTransformation);
64 |
65 | private static native void nativeOnSurfaceCreated(long handle);
66 |
67 | private static native void nativeOnSurfaceDestroyed(long handle);
68 |
69 | private static native void nativeRenderTexture(long handle, int textureType, int textureId);
70 |
71 | private static native void nativeUpdateTransformation(long handle, long nativeTransformation);
72 |
73 | private static native void nativeSetFilter(long handle, long filterHandle);
74 |
75 | private static native void nativeDestroy(long handle);
76 |
77 | public void onSurfaceCreated(Surface surface) {
78 | logInfo("onSurfaceCreated " + surface);
79 | createEglSurfaceInternal(surface);
80 | }
81 |
82 | public void onSurfaceCreated(SurfaceTexture surfaceTexture) {
83 | logInfo("onSurfaceCreated " + surfaceTexture);
84 | createEglSurfaceInternal(surfaceTexture);
85 | }
86 |
87 | public void onSurfaceDestroyed() {
88 | logInfo("onSurfaceDestroyed");
89 | mEglSurfaceCreationRunnable.setSurface(null);
90 | mRenderHandler.removeCallbacks(mEglSurfaceCreationRunnable);
91 | ThreadUtils.invokeAtFrontUninterruptibly(mRenderHandler, () -> {
92 | if (mNativeHandle != 0) {
93 | nativeOnSurfaceDestroyed(mNativeHandle);
94 | }
95 | if (mEglBase != null) {
96 | mEglBase.release();
97 | mEglBase = null;
98 | }
99 | });
100 | logInfo("onSurfaceDestroyed success");
101 | }
102 |
103 | public void renderRgb(int textureId, long timestamp) {
104 | renderTexture(TEXTURE_TYPE_RGB, textureId, timestamp);
105 | }
106 |
107 | public void renderOes(int textureId, long timestamp) {
108 | renderTexture(TEXTURE_TYPE_OES, textureId, timestamp);
109 | }
110 |
111 | public void runOnRenderThread(Runnable runnable) {
112 | mRenderHandler.post(runnable);
113 | }
114 |
115 | public UgiTransformation getTransformation() {
116 | return mTransformation;
117 | }
118 |
119 | public void notifyTransformationUpdated() {
120 | mRenderHandler.post(() -> {
121 | if (mNativeHandle != 0) {
122 | nativeUpdateTransformation(mNativeHandle, mTransformation.mNativeHandle);
123 | }
124 | });
125 | }
126 |
127 | public void setFilter(UgiFilter filter) {
128 | if (mNativeHandle != 0 && filter.getNativeHandle() != 0) {
129 | if (mFilter != null) {
130 | mFilter.releaseHandle();
131 | }
132 | mFilter = filter;
133 | nativeSetFilter(mNativeHandle, filter.getNativeHandle());
134 | }
135 | }
136 |
137 | public void destroy() {
138 | logInfo("destroy");
139 | mRenderHandler.post(() -> {
140 | if (mFilter != null) {
141 | mFilter.releaseHandle();
142 | mFilter = null;
143 | }
144 | if (mNativeHandle != 0) {
145 | nativeDestroy(mNativeHandle);
146 | mNativeHandle = 0;
147 | }
148 | mTransformation.destroy();
149 | mRenderHandler.getLooper().quit();
150 | });
151 | }
152 |
153 | private void renderTexture(int textureType, int textureId, long timestamp) {
154 | mRenderHandler.post(() -> {
155 | if (mNativeHandle != 0) {
156 | nativeRenderTexture(mNativeHandle, textureType, textureId);
157 | mEglBase.swapBuffers(timestamp);
158 | }
159 | });
160 | }
161 |
162 | private void createEglSurfaceInternal(Object surface) {
163 | mEglSurfaceCreationRunnable.setSurface(surface);
164 | mRenderHandler.post(mEglSurfaceCreationRunnable);
165 | }
166 |
167 | private void logInfo(String content) {
168 | Logging.info(TAG, mName + "(" + hashCode() + ") " + content);
169 | }
170 |
171 | private void logError(String content) {
172 | Logging.error(TAG, mName + "(" + hashCode() + ") " + content);
173 | }
174 |
175 | private class EglSurfaceCreation implements Runnable {
176 | private Object mSurface;
177 |
178 | synchronized void setSurface(Object surface) {
179 | this.mSurface = surface;
180 | }
181 |
182 | @Override
183 | public synchronized void run() {
184 | if (mSurface != null && mEglBase != null && !mEglBase.hasSurface()
185 | && mNativeHandle != 0) {
186 | if (mSurface instanceof Surface) {
187 | mEglBase.createSurface((Surface) mSurface);
188 | } else if (mSurface instanceof SurfaceTexture) {
189 | mEglBase.createSurface((SurfaceTexture) mSurface);
190 | } else {
191 | logError("EglSurfaceCreation error: invalid surface " + mSurface);
192 | return;
193 | }
194 | mEglBase.makeCurrent();
195 | // Necessary for YUV frames with odd width.
196 | GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
197 |
198 | nativeOnSurfaceCreated(mNativeHandle);
199 | }
200 | }
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/UgiRendererView.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.Matrix;
6 | import android.graphics.SurfaceTexture;
7 | import android.opengl.EGLContext;
8 | import android.opengl.GLES20;
9 | import android.opengl.GLUtils;
10 | import android.util.AttributeSet;
11 | import android.view.TextureView;
12 | import androidx.annotation.IntDef;
13 | import androidx.annotation.NonNull;
14 | import com.piasy.ugi.egl.EglBase;
15 |
16 | /**
17 | * Created by Piasy{github.com/Piasy} on 2018/12/21.
18 | */
19 | public class UgiRendererView extends TextureView implements TextureView.SurfaceTextureListener {
20 | public static final int RENDER_MODE_PICTURE = 1;
21 | public static final int RENDER_MODE_CAMERA_PREVIEW = 2;
22 |
23 | private int mRenderMode;
24 | private UgiRenderer mRenderer;
25 | private SurfaceTexture mSurfaceTexture;
26 |
27 | private int mTextureWidth;
28 | private int mTextureHeight;
29 |
30 | private Bitmap mPicture;
31 | private boolean mRecycleAfterUpload;
32 | private int mPictureTextureId = -1;
33 | private int mPictureWidth;
34 | private int mPictureHeight;
35 |
36 | private TextureView.SurfaceTextureListener mSurfaceTextureListener;
37 |
38 | public UgiRendererView(final Context context) {
39 | this(context, null);
40 | }
41 |
42 | public UgiRendererView(final Context context, final AttributeSet attrs) {
43 | this(context, attrs, 0);
44 | }
45 |
46 | public UgiRendererView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
47 | super(context, attrs, defStyleAttr);
48 |
49 | super.setSurfaceTextureListener(this);
50 | }
51 |
52 | private static int loadTexture(Bitmap bitmap, boolean recycle) {
53 | int textures[] = new int[1];
54 | GLES20.glGenTextures(1, textures, 0);
55 | GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
56 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
57 | GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
58 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
59 | GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
60 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
61 | GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
62 | GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
63 | GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
64 | GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
65 |
66 | if (recycle) {
67 | bitmap.recycle();
68 | }
69 |
70 | return textures[0];
71 | }
72 |
73 | private static void destroyTexture(int textureId) {
74 | int textures[] = new int[] { textureId };
75 | GLES20.glDeleteTextures(1, textures, 0);
76 | }
77 |
78 | public void initialize(EGLContext sharedContext, @RenderMode int renderMode) {
79 | initialize("", sharedContext, renderMode);
80 | }
81 |
82 | public synchronized void initialize(String name, EGLContext sharedContext,
83 | @RenderMode int renderMode) {
84 | mRenderMode = renderMode;
85 | mRenderer = new UgiRenderer(name, sharedContext, EglBase.CONFIG_PLAIN);
86 | tryCreateRendererSurface();
87 | }
88 |
89 | public synchronized void destroy() {
90 | if (mRenderer != null) {
91 | if (mPictureTextureId != -1) {
92 | mRenderer.runOnRenderThread(() -> {
93 | destroyTexture(mPictureTextureId);
94 | mPictureTextureId = -1;
95 | });
96 | }
97 | if (mPicture != null && mRecycleAfterUpload) {
98 | mPicture.recycle();
99 | mPicture = null;
100 | }
101 | mRenderer.destroy();
102 | mRenderer = null;
103 | }
104 | }
105 |
106 | public synchronized void updateCameraInfo(int width, int height, int sensorDegree,
107 | boolean frontFace, boolean isLandscape) {
108 | if (mRenderer != null) {
109 | UgiTransformation transformation = mRenderer.getTransformation();
110 | if (isLandscape) {
111 | transformation.updateRotation(360 - sensorDegree + 90);
112 | transformation.updateInput(width, height);
113 | } else {
114 | transformation.updateRotation(360 - sensorDegree);
115 | transformation.updateInput(height, width);
116 | }
117 | if (!frontFace && sensorDegree % 180 != 0) {
118 | transformation.updateFlip(UgiTransformation.FLIP_VERTICAL);
119 | } else {
120 | transformation.updateFlip(UgiTransformation.FLIP_NONE);
121 | }
122 | notifyTransformationUpdated();
123 | }
124 | }
125 |
126 | public synchronized UgiTransformation getTransformation() {
127 | return mRenderer == null ? null : mRenderer.getTransformation();
128 | }
129 |
130 | public synchronized void notifyTransformationUpdated() {
131 | if (mRenderer != null && mSurfaceTexture != null) {
132 | mRenderer.notifyTransformationUpdated();
133 |
134 | if (mRenderMode == RENDER_MODE_PICTURE && mPictureTextureId != -1) {
135 | mRenderer.renderRgb(mPictureTextureId, 0);
136 | }
137 | }
138 | }
139 |
140 | public synchronized void notifyFilterUpdated() {
141 | if (mRenderer != null && mSurfaceTexture != null
142 | && mRenderMode == RENDER_MODE_PICTURE && mPictureTextureId != -1) {
143 | mRenderer.renderRgb(mPictureTextureId, 0);
144 | }
145 | }
146 |
147 | public synchronized void setFilter(UgiFilter filter) {
148 | if (mRenderer != null) {
149 | mRenderer.setFilter(filter);
150 | notifyFilterUpdated();
151 | }
152 | }
153 |
154 | public synchronized void renderOes(int textureId) {
155 | if (mRenderer != null && mSurfaceTexture != null) {
156 | mRenderer.renderOes(textureId, 0);
157 | }
158 | }
159 |
160 | public void renderPicture(@NonNull Bitmap bitmap) {
161 | renderPicture(bitmap, true, true);
162 | }
163 |
164 | public synchronized void renderPicture(@NonNull Bitmap bitmap, boolean needFlipVertically,
165 | boolean recycle) {
166 | if (mRenderMode == RENDER_MODE_PICTURE && mRenderer != null && !bitmap.isRecycled()) {
167 | mPictureWidth = bitmap.getWidth();
168 | mPictureHeight = bitmap.getHeight();
169 | if (needFlipVertically) {
170 | Matrix matrix = new Matrix();
171 | matrix.postScale(1, -1, mPictureWidth / 2F, mPictureHeight / 2F);
172 | mPicture = Bitmap.createBitmap(bitmap, 0, 0, mPictureWidth, mPictureHeight,
173 | matrix, true);
174 | if (recycle) {
175 | bitmap.recycle();
176 | }
177 | } else {
178 | mPicture = bitmap;
179 | }
180 | mRecycleAfterUpload = recycle;
181 | tryUploadPicture();
182 | }
183 | }
184 |
185 | private void tryCreateRendererSurface() {
186 | if (mRenderer != null && mSurfaceTexture != null) {
187 | mRenderer.onSurfaceCreated(mSurfaceTexture);
188 | tryUploadPicture();
189 | }
190 | }
191 |
192 | private void tryUploadPicture() {
193 | mRenderer.runOnRenderThread(() -> {
194 | synchronized (UgiRendererView.this) {
195 | if (mPicture != null && mSurfaceTexture != null) {
196 | if (mPictureTextureId != -1) {
197 | destroyTexture(mPictureTextureId);
198 | }
199 | mPictureTextureId = loadTexture(mPicture, mRecycleAfterUpload);
200 | mPicture = null;
201 |
202 | updateInputOutputSize();
203 | }
204 | }
205 | });
206 | }
207 |
208 | private void updateInputOutputSize() {
209 | if (mRenderer != null) {
210 | UgiTransformation transformation = mRenderer.getTransformation();
211 | transformation.updateOutput(mPictureWidth, mPictureHeight);
212 | transformation.updateOutput(mTextureWidth, mTextureHeight);
213 | notifyTransformationUpdated();
214 | }
215 | }
216 |
217 | @Override
218 | public synchronized void setSurfaceTextureListener(
219 | final SurfaceTextureListener surfaceTextureListener) {
220 | mSurfaceTextureListener = surfaceTextureListener;
221 | }
222 |
223 | @Override
224 | public synchronized void onSurfaceTextureAvailable(final SurfaceTexture surface,
225 | final int width, final int height) {
226 | mSurfaceTexture = surface;
227 | mTextureWidth = width;
228 | mTextureHeight = height;
229 | tryCreateRendererSurface();
230 |
231 | if (mSurfaceTextureListener != null) {
232 | mSurfaceTextureListener.onSurfaceTextureAvailable(surface, width, height);
233 | }
234 | }
235 |
236 | @Override
237 | public synchronized void onSurfaceTextureSizeChanged(final SurfaceTexture surface,
238 | final int width, final int height) {
239 | mTextureWidth = width;
240 | mTextureHeight = height;
241 | updateInputOutputSize();
242 |
243 | if (mSurfaceTextureListener != null) {
244 | mSurfaceTextureListener.onSurfaceTextureSizeChanged(surface, width, height);
245 | }
246 | }
247 |
248 | @Override
249 | public synchronized boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) {
250 | if (mRenderer != null) {
251 | mRenderer.onSurfaceDestroyed();
252 | }
253 | mSurfaceTexture = null;
254 |
255 | if (mSurfaceTextureListener != null) {
256 | mSurfaceTextureListener.onSurfaceTextureDestroyed(surface);
257 | }
258 |
259 | return true;
260 | }
261 |
262 | @Override
263 | public void onSurfaceTextureUpdated(final SurfaceTexture surface) {
264 | if (mSurfaceTextureListener != null) {
265 | mSurfaceTextureListener.onSurfaceTextureUpdated(surface);
266 | }
267 | }
268 |
269 | @IntDef(value = {
270 | RENDER_MODE_PICTURE,
271 | RENDER_MODE_CAMERA_PREVIEW,
272 | })
273 | @interface RenderMode {
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/UgiTransformation.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi;
2 |
3 | import androidx.annotation.IntDef;
4 | import com.piasy.ugi.utils.Logging;
5 |
6 | /**
7 | * Created by Piasy{github.com/Piasy} on 2018/12/19.
8 | */
9 | public class UgiTransformation {
10 |
11 | public static final int COORDS_SCALE = 10000;
12 |
13 | public static final int FLIP_NONE = 0;
14 | public static final int FLIP_HORIZONTAL = 1;
15 | public static final int FLIP_VERTICAL = 2;
16 | public static final int FLIP_HORIZONTAL_VERTICAL = 3;
17 |
18 | public static final int ROTATION_0 = 0;
19 | public static final int ROTATION_90 = 90;
20 | public static final int ROTATION_180 = 180;
21 | public static final int ROTATION_270 = 270;
22 |
23 | public static final int SCALE_TYPE_FIT_XY = 0;
24 | public static final int SCALE_TYPE_CENTER_CROP = 1;
25 | public static final int SCALE_TYPE_CENTER_INSIDE = 2;
26 |
27 | private static final String TAG = "UgiTransformation";
28 |
29 | long mNativeHandle;
30 |
31 | UgiTransformation(int inputWidth, int inputHeight, int outputWidth, int outputHeight) {
32 | mNativeHandle = nativeCreate(inputWidth, inputHeight, outputWidth, outputHeight);
33 | }
34 |
35 | private static native long nativeCreate(int inputWidth, int inputHeight,
36 | int outputWidth, int outputHeight);
37 |
38 | private static native void nativeUpdateInput(long handle, int width, int height);
39 |
40 | private static native void nativeUpdateOutput(long handle, int width, int height);
41 |
42 | private static native void nativeUpdateCrop(long handle, int x, int y, int width, int height);
43 |
44 | private static native void nativeUpdateFlip(long handle, int flip);
45 |
46 | private static native void nativeUpdateRotation(long handle, int rotation);
47 |
48 | private static native void nativeUpdateScaleType(long handle, int scaleType);
49 |
50 | private static native int nativeGetInputWidth(long handle);
51 |
52 | private static native int nativeGetInputHeight(long handle);
53 |
54 | private static native int nativeGetRotation(long handle);
55 |
56 | private static native int nativeGetFlip(long handle);
57 |
58 | public static native void nativeDestroy(long handle);
59 |
60 | public void updateInput(int width, int height) {
61 | Logging.info(TAG, "updateInput " + width + "x" + height);
62 | if (mNativeHandle != 0) {
63 | nativeUpdateInput(mNativeHandle, width, height);
64 | }
65 | }
66 |
67 | public void updateOutput(int width, int height) {
68 | Logging.info(TAG, "updateOutput " + width + "x" + height);
69 | if (mNativeHandle != 0) {
70 | nativeUpdateOutput(mNativeHandle, width, height);
71 | }
72 | }
73 |
74 | public void updateCrop(int x, int y, int width, int height) {
75 | Logging.info(TAG, "updateCrop (" + x + ", " + y + ", " + width + ", " + height + ")");
76 | if (mNativeHandle != 0
77 | && 0 <= x && x <= COORDS_SCALE
78 | && 0 <= y && y <= COORDS_SCALE
79 | && 0 <= width && width <= COORDS_SCALE
80 | && 0 <= height && height <= COORDS_SCALE) {
81 | nativeUpdateCrop(mNativeHandle, x, y, width, height);
82 | }
83 | }
84 |
85 | public void updateFlip(@Flip int flip) {
86 | Logging.info(TAG, "updateFlip " + flip);
87 | if (mNativeHandle != 0) {
88 | nativeUpdateFlip(mNativeHandle, flip);
89 | }
90 | }
91 |
92 | public void updateRotation(@Rotation int rotation) {
93 | Logging.info(TAG, "updateRotation " + rotation);
94 | if (mNativeHandle != 0) {
95 | nativeUpdateRotation(mNativeHandle, rotation);
96 | }
97 | }
98 |
99 | public void updateScaleType(@ScaleType int scaleType) {
100 | Logging.info(TAG, "updateScaleType " + scaleType);
101 | if (mNativeHandle != 0) {
102 | nativeUpdateScaleType(mNativeHandle, scaleType);
103 | }
104 | }
105 |
106 | public int getInputWidth() {
107 | return mNativeHandle == 0 ? 0 : nativeGetInputWidth(mNativeHandle);
108 | }
109 |
110 | public int getInputHeight() {
111 | return mNativeHandle == 0 ? 0 : nativeGetInputHeight(mNativeHandle);
112 | }
113 |
114 | public int getRotation() {
115 | return mNativeHandle == 0 ? 0 : nativeGetRotation(mNativeHandle);
116 | }
117 |
118 | public int getFlip() {
119 | return mNativeHandle == 0 ? 0 : nativeGetFlip(mNativeHandle);
120 | }
121 |
122 | void destroy() {
123 | if (mNativeHandle != 0) {
124 | nativeDestroy(mNativeHandle);
125 | mNativeHandle = 0;
126 | }
127 | }
128 |
129 | @IntDef(value = {
130 | FLIP_NONE,
131 | FLIP_HORIZONTAL,
132 | FLIP_VERTICAL,
133 | FLIP_HORIZONTAL_VERTICAL,
134 | })
135 | @interface Flip {
136 | }
137 |
138 | @IntDef(value = {
139 | ROTATION_0,
140 | ROTATION_90,
141 | ROTATION_180,
142 | ROTATION_270,
143 | })
144 | @interface Rotation {
145 | }
146 |
147 | @IntDef(value = {
148 | SCALE_TYPE_FIT_XY,
149 | SCALE_TYPE_CENTER_CROP,
150 | SCALE_TYPE_CENTER_INSIDE,
151 | })
152 | @interface ScaleType {
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/egl/EglBase.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | package com.piasy.ugi.egl;
12 |
13 | import android.graphics.SurfaceTexture;
14 | import android.view.Surface;
15 | import javax.annotation.Nullable;
16 | import javax.microedition.khronos.egl.EGL10;
17 |
18 | /**
19 | * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EGLDisplay,
20 | * and an EGLSurface.
21 | */
22 | public interface EglBase {
23 | // EGL wrapper for an actual EGLContext.
24 | public interface Context {
25 | /**
26 | * Returns an EGL context that can be used by native code. Returns 0 if the method is
27 | * unsupported.
28 | *
29 | * @note This is currently only supported for EGL 1.4 and not for EGL 1.0.
30 | */
31 | long getNativeEglContext();
32 | }
33 |
34 | // According to the documentation, EGL can be used from multiple threads at the same time if each
35 | // thread has its own EGLContext, but in practice it deadlocks on some devices when doing this.
36 | // Therefore, synchronize on this global lock before calling dangerous EGL functions that might
37 | // deadlock. See https://bugs.chromium.org/p/webrtc/issues/detail?id=5702 for more info.
38 | public static final Object lock = new Object();
39 |
40 | // These constants are taken from EGL14.EGL_OPENGL_ES2_BIT and EGL14.EGL_CONTEXT_CLIENT_VERSION.
41 | // https://android.googlesource.com/platform/frameworks/base/+/master/opengl/java/android/opengl/EGL14.java
42 | // This is similar to how GlSurfaceView does:
43 | // http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/opengl/GLSurfaceView.java#760
44 | public static final int EGL_OPENGL_ES2_BIT = 4;
45 | // Android-specific extension.
46 | public static final int EGL_RECORDABLE_ANDROID = 0x3142;
47 |
48 | // clang-format off
49 | public static final int[] CONFIG_PLAIN = {
50 | EGL10.EGL_RED_SIZE, 8,
51 | EGL10.EGL_GREEN_SIZE, 8,
52 | EGL10.EGL_BLUE_SIZE, 8,
53 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
54 | EGL10.EGL_NONE
55 | };
56 | public static final int[] CONFIG_RGBA = {
57 | EGL10.EGL_RED_SIZE, 8,
58 | EGL10.EGL_GREEN_SIZE, 8,
59 | EGL10.EGL_BLUE_SIZE, 8,
60 | EGL10.EGL_ALPHA_SIZE, 8,
61 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
62 | EGL10.EGL_NONE
63 | };
64 | public static final int[] CONFIG_PIXEL_BUFFER = {
65 | EGL10.EGL_RED_SIZE, 8,
66 | EGL10.EGL_GREEN_SIZE, 8,
67 | EGL10.EGL_BLUE_SIZE, 8,
68 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
69 | EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
70 | EGL10.EGL_NONE
71 | };
72 | public static final int[] CONFIG_PIXEL_RGBA_BUFFER = {
73 | EGL10.EGL_RED_SIZE, 8,
74 | EGL10.EGL_GREEN_SIZE, 8,
75 | EGL10.EGL_BLUE_SIZE, 8,
76 | EGL10.EGL_ALPHA_SIZE, 8,
77 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
78 | EGL10.EGL_SURFACE_TYPE, EGL10.EGL_PBUFFER_BIT,
79 | EGL10.EGL_NONE
80 | };
81 | public static final int[] CONFIG_RECORDABLE = {
82 | EGL10.EGL_RED_SIZE, 8,
83 | EGL10.EGL_GREEN_SIZE, 8,
84 | EGL10.EGL_BLUE_SIZE, 8,
85 | EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
86 | EGL_RECORDABLE_ANDROID, 1,
87 | EGL10.EGL_NONE
88 | };
89 | // clang-format on
90 |
91 | /**
92 | * Create a new context with the specified config attributes, sharing data with |sharedContext|.
93 | * If |sharedContext| is null, a root context is created. This function will try to create an EGL
94 | * 1.4 context if possible, and an EGL 1.0 context otherwise.
95 | */
96 | public static EglBase create(@Nullable Context sharedContext, int[] configAttributes) {
97 | return (EglBase14.isEGL14Supported()
98 | && (sharedContext == null || sharedContext instanceof EglBase14.Context))
99 | ? new EglBase14((EglBase14.Context) sharedContext, configAttributes)
100 | : new EglBase10((EglBase10.Context) sharedContext, configAttributes);
101 | }
102 |
103 | /**
104 | * Helper function for creating a plain root context. This function will try to create an EGL 1.4
105 | * context if possible, and an EGL 1.0 context otherwise.
106 | */
107 | public static EglBase create() {
108 | return create(null /* shaderContext */, CONFIG_PLAIN);
109 | }
110 |
111 | /**
112 | * Helper function for creating a plain context, sharing data with |sharedContext|. This function
113 | * will try to create an EGL 1.4 context if possible, and an EGL 1.0 context otherwise.
114 | */
115 | public static EglBase create(Context sharedContext) {
116 | return create(sharedContext, CONFIG_PLAIN);
117 | }
118 |
119 | /**
120 | * Explicitly create a root EGl 1.0 context with the specified config attributes.
121 | */
122 | public static EglBase createEgl10(int[] configAttributes) {
123 | return new EglBase10(null /* shaderContext */, configAttributes);
124 | }
125 |
126 | /**
127 | * Explicitly create a root EGl 1.0 context with the specified config attributes
128 | * and shared context.
129 | */
130 | public static EglBase createEgl10(
131 | javax.microedition.khronos.egl.EGLContext sharedContext, int[] configAttributes) {
132 | return new EglBase10(new EglBase10.Context(sharedContext), configAttributes);
133 | }
134 |
135 | /**
136 | * Explicitly create a root EGl 1.4 context with the specified config attributes.
137 | */
138 | public static EglBase createEgl14(int[] configAttributes) {
139 | return new EglBase14(null /* shaderContext */, configAttributes);
140 | }
141 |
142 | /**
143 | * Explicitly create a root EGl 1.4 context with the specified config attributes
144 | * and shared context.
145 | */
146 | public static EglBase createEgl14(
147 | android.opengl.EGLContext sharedContext, int[] configAttributes) {
148 | return new EglBase14(new EglBase14.Context(sharedContext), configAttributes);
149 | }
150 |
151 | void createSurface(Surface surface);
152 |
153 | // Create EGLSurface from the Android SurfaceTexture.
154 | void createSurface(SurfaceTexture surfaceTexture);
155 |
156 | // Create dummy 1x1 pixel buffer surface so the context can be made current.
157 | void createDummyPbufferSurface();
158 |
159 | void createPbufferSurface(int width, int height);
160 |
161 | Context getEglBaseContext();
162 |
163 | boolean hasSurface();
164 |
165 | int surfaceWidth();
166 |
167 | int surfaceHeight();
168 |
169 | void releaseSurface();
170 |
171 | void release();
172 |
173 | void makeCurrent();
174 |
175 | // Detach the current EGL context, so that it can be made current on another thread.
176 | void detachCurrent();
177 |
178 | void swapBuffers();
179 |
180 | void swapBuffers(long presentationTimeStampNs);
181 | }
182 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/egl/EglBase10.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | package com.piasy.ugi.egl;
12 |
13 | import android.graphics.Canvas;
14 | import android.graphics.Rect;
15 | import android.graphics.SurfaceTexture;
16 | import javax.annotation.Nullable;
17 | import android.view.Surface;
18 | import android.view.SurfaceHolder;
19 | import javax.microedition.khronos.egl.EGL10;
20 | import javax.microedition.khronos.egl.EGLConfig;
21 | import javax.microedition.khronos.egl.EGLContext;
22 | import javax.microedition.khronos.egl.EGLDisplay;
23 | import javax.microedition.khronos.egl.EGLSurface;
24 |
25 | /**
26 | * Holds EGL state and utility methods for handling an egl 1.0 EGLContext, an EGLDisplay,
27 | * and an EGLSurface.
28 | */
29 | class EglBase10 implements EglBase {
30 | // This constant is taken from EGL14.EGL_CONTEXT_CLIENT_VERSION.
31 | private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
32 |
33 | private final EGL10 egl;
34 | private EGLContext eglContext;
35 | @Nullable private EGLConfig eglConfig;
36 | private EGLDisplay eglDisplay;
37 | private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
38 |
39 | // EGL wrapper for an actual EGLContext.
40 | public static class Context implements EglBase.Context {
41 | private final EGLContext eglContext;
42 |
43 | @Override
44 | public long getNativeEglContext() {
45 | // TODO(magjed): Implement. There is no easy way of getting the native context for EGL 1.0. We
46 | // need to make sure to have an EglSurface, then make the context current using that surface,
47 | // and then call into JNI and call the native version of eglGetCurrentContext. Then we need to
48 | // restore the state and return the native context.
49 | return 0 /* EGL_NO_CONTEXT */;
50 | }
51 |
52 | public Context(EGLContext eglContext) {
53 | this.eglContext = eglContext;
54 | }
55 | }
56 |
57 | // Create a new context with the specified config type, sharing data with sharedContext.
58 | public EglBase10(Context sharedContext, int[] configAttributes) {
59 | this.egl = (EGL10) EGLContext.getEGL();
60 | eglDisplay = getEglDisplay();
61 | eglConfig = getEglConfig(eglDisplay, configAttributes);
62 | eglContext = createEglContext(sharedContext, eglDisplay, eglConfig);
63 | }
64 |
65 | @Override
66 | public void createSurface(Surface surface) {
67 | /**
68 | * We have to wrap Surface in a SurfaceHolder because for some reason eglCreateWindowSurface
69 | * couldn't actually take a Surface object until API 17. Older versions fortunately just call
70 | * SurfaceHolder.getSurface(), so we'll do that. No other methods are relevant.
71 | */
72 | class FakeSurfaceHolder implements SurfaceHolder {
73 | private final Surface surface;
74 |
75 | FakeSurfaceHolder(Surface surface) {
76 | this.surface = surface;
77 | }
78 |
79 | @Override
80 | public void addCallback(Callback callback) {}
81 |
82 | @Override
83 | public void removeCallback(Callback callback) {}
84 |
85 | @Override
86 | public boolean isCreating() {
87 | return false;
88 | }
89 |
90 | @Deprecated
91 | @Override
92 | public void setType(int i) {}
93 |
94 | @Override
95 | public void setFixedSize(int i, int i2) {}
96 |
97 | @Override
98 | public void setSizeFromLayout() {}
99 |
100 | @Override
101 | public void setFormat(int i) {}
102 |
103 | @Override
104 | public void setKeepScreenOn(boolean b) {}
105 |
106 | @Nullable
107 | @Override
108 | public Canvas lockCanvas() {
109 | return null;
110 | }
111 |
112 | @Nullable
113 | @Override
114 | public Canvas lockCanvas(Rect rect) {
115 | return null;
116 | }
117 |
118 | @Override
119 | public void unlockCanvasAndPost(Canvas canvas) {}
120 |
121 | @Nullable
122 | @Override
123 | public Rect getSurfaceFrame() {
124 | return null;
125 | }
126 |
127 | @Override
128 | public Surface getSurface() {
129 | return surface;
130 | }
131 | }
132 |
133 | createSurfaceInternal(new FakeSurfaceHolder(surface));
134 | }
135 |
136 | // Create EGLSurface from the Android SurfaceTexture.
137 | @Override
138 | public void createSurface(SurfaceTexture surfaceTexture) {
139 | createSurfaceInternal(surfaceTexture);
140 | }
141 |
142 | // Create EGLSurface from either a SurfaceHolder or a SurfaceTexture.
143 | private void createSurfaceInternal(Object nativeWindow) {
144 | if (!(nativeWindow instanceof SurfaceHolder) && !(nativeWindow instanceof SurfaceTexture)) {
145 | throw new IllegalStateException("Input must be either a SurfaceHolder or SurfaceTexture");
146 | }
147 | checkIsNotReleased();
148 | if (eglSurface != EGL10.EGL_NO_SURFACE) {
149 | throw new RuntimeException("Already has an EGLSurface");
150 | }
151 | int[] surfaceAttribs = {EGL10.EGL_NONE};
152 | eglSurface = egl.eglCreateWindowSurface(eglDisplay, eglConfig, nativeWindow, surfaceAttribs);
153 | if (eglSurface == EGL10.EGL_NO_SURFACE) {
154 | throw new RuntimeException(
155 | "Failed to create window surface: 0x" + Integer.toHexString(egl.eglGetError()));
156 | }
157 | }
158 |
159 | // Create dummy 1x1 pixel buffer surface so the context can be made current.
160 | @Override
161 | public void createDummyPbufferSurface() {
162 | createPbufferSurface(1, 1);
163 | }
164 |
165 | @Override
166 | public void createPbufferSurface(int width, int height) {
167 | checkIsNotReleased();
168 | if (eglSurface != EGL10.EGL_NO_SURFACE) {
169 | throw new RuntimeException("Already has an EGLSurface");
170 | }
171 | int[] surfaceAttribs = {EGL10.EGL_WIDTH, width, EGL10.EGL_HEIGHT, height, EGL10.EGL_NONE};
172 | eglSurface = egl.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttribs);
173 | if (eglSurface == EGL10.EGL_NO_SURFACE) {
174 | throw new RuntimeException("Failed to create pixel buffer surface with size " + width + "x"
175 | + height + ": 0x" + Integer.toHexString(egl.eglGetError()));
176 | }
177 | }
178 |
179 | @Override
180 | public com.piasy.ugi.egl.EglBase.Context getEglBaseContext() {
181 | return new EglBase10.Context(eglContext);
182 | }
183 |
184 | @Override
185 | public boolean hasSurface() {
186 | return eglSurface != EGL10.EGL_NO_SURFACE;
187 | }
188 |
189 | @Override
190 | public int surfaceWidth() {
191 | final int widthArray[] = new int[1];
192 | egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_WIDTH, widthArray);
193 | return widthArray[0];
194 | }
195 |
196 | @Override
197 | public int surfaceHeight() {
198 | final int heightArray[] = new int[1];
199 | egl.eglQuerySurface(eglDisplay, eglSurface, EGL10.EGL_HEIGHT, heightArray);
200 | return heightArray[0];
201 | }
202 |
203 | @Override
204 | public void releaseSurface() {
205 | if (eglSurface != EGL10.EGL_NO_SURFACE) {
206 | egl.eglDestroySurface(eglDisplay, eglSurface);
207 | eglSurface = EGL10.EGL_NO_SURFACE;
208 | }
209 | }
210 |
211 | private void checkIsNotReleased() {
212 | if (eglDisplay == EGL10.EGL_NO_DISPLAY || eglContext == EGL10.EGL_NO_CONTEXT
213 | || eglConfig == null) {
214 | throw new RuntimeException("This object has been released");
215 | }
216 | }
217 |
218 | @Override
219 | public void release() {
220 | checkIsNotReleased();
221 | releaseSurface();
222 | detachCurrent();
223 | egl.eglDestroyContext(eglDisplay, eglContext);
224 | egl.eglTerminate(eglDisplay);
225 | eglContext = EGL10.EGL_NO_CONTEXT;
226 | eglDisplay = EGL10.EGL_NO_DISPLAY;
227 | eglConfig = null;
228 | }
229 |
230 | @Override
231 | public void makeCurrent() {
232 | checkIsNotReleased();
233 | if (eglSurface == EGL10.EGL_NO_SURFACE) {
234 | throw new RuntimeException("No EGLSurface - can't make current");
235 | }
236 | synchronized (EglBase.lock) {
237 | if (!egl.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
238 | throw new RuntimeException(
239 | "eglMakeCurrent failed: 0x" + Integer.toHexString(egl.eglGetError()));
240 | }
241 | }
242 | }
243 |
244 | // Detach the current EGL context, so that it can be made current on another thread.
245 | @Override
246 | public void detachCurrent() {
247 | synchronized (EglBase.lock) {
248 | if (!egl.eglMakeCurrent(
249 | eglDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT)) {
250 | throw new RuntimeException(
251 | "eglDetachCurrent failed: 0x" + Integer.toHexString(egl.eglGetError()));
252 | }
253 | }
254 | }
255 |
256 | @Override
257 | public void swapBuffers() {
258 | checkIsNotReleased();
259 | if (eglSurface == EGL10.EGL_NO_SURFACE) {
260 | throw new RuntimeException("No EGLSurface - can't swap buffers");
261 | }
262 | synchronized (EglBase.lock) {
263 | egl.eglSwapBuffers(eglDisplay, eglSurface);
264 | }
265 | }
266 |
267 | @Override
268 | public void swapBuffers(long timeStampNs) {
269 | // Setting presentation time is not supported for EGL 1.0.
270 | swapBuffers();
271 | }
272 |
273 | // Return an EGLDisplay, or die trying.
274 | private EGLDisplay getEglDisplay() {
275 | EGLDisplay eglDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
276 | if (eglDisplay == EGL10.EGL_NO_DISPLAY) {
277 | throw new RuntimeException(
278 | "Unable to get EGL10 display: 0x" + Integer.toHexString(egl.eglGetError()));
279 | }
280 | int[] version = new int[2];
281 | if (!egl.eglInitialize(eglDisplay, version)) {
282 | throw new RuntimeException(
283 | "Unable to initialize EGL10: 0x" + Integer.toHexString(egl.eglGetError()));
284 | }
285 | return eglDisplay;
286 | }
287 |
288 | // Return an EGLConfig, or die trying.
289 | private EGLConfig getEglConfig(EGLDisplay eglDisplay, int[] configAttributes) {
290 | EGLConfig[] configs = new EGLConfig[1];
291 | int[] numConfigs = new int[1];
292 | if (!egl.eglChooseConfig(eglDisplay, configAttributes, configs, configs.length, numConfigs)) {
293 | throw new RuntimeException(
294 | "eglChooseConfig failed: 0x" + Integer.toHexString(egl.eglGetError()));
295 | }
296 | if (numConfigs[0] <= 0) {
297 | throw new RuntimeException("Unable to find any matching EGL config");
298 | }
299 | final EGLConfig eglConfig = configs[0];
300 | if (eglConfig == null) {
301 | throw new RuntimeException("eglChooseConfig returned null");
302 | }
303 | return eglConfig;
304 | }
305 |
306 | // Return an EGLConfig, or die trying.
307 | private EGLContext createEglContext(
308 | @Nullable Context sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) {
309 | if (sharedContext != null && sharedContext.eglContext == EGL10.EGL_NO_CONTEXT) {
310 | throw new RuntimeException("Invalid sharedContext");
311 | }
312 | int[] contextAttributes = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
313 | EGLContext rootContext =
314 | sharedContext == null ? EGL10.EGL_NO_CONTEXT : sharedContext.eglContext;
315 | final EGLContext eglContext;
316 | synchronized (EglBase.lock) {
317 | eglContext = egl.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttributes);
318 | }
319 | if (eglContext == EGL10.EGL_NO_CONTEXT) {
320 | throw new RuntimeException(
321 | "Failed to create EGL context: 0x" + Integer.toHexString(egl.eglGetError()));
322 | }
323 | return eglContext;
324 | }
325 | }
326 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/egl/EglBase14.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | package com.piasy.ugi.egl;
12 |
13 | import android.annotation.TargetApi;
14 | import android.graphics.SurfaceTexture;
15 | import android.opengl.EGL14;
16 | import android.opengl.EGLConfig;
17 | import android.opengl.EGLContext;
18 | import android.opengl.EGLDisplay;
19 | import android.opengl.EGLExt;
20 | import android.opengl.EGLSurface;
21 | import android.os.Build;
22 | import android.view.Surface;
23 | import com.piasy.ugi.utils.Logging;
24 | import javax.annotation.Nullable;
25 |
26 | /**
27 | * Holds EGL state and utility methods for handling an EGL14 EGLContext, an EGLDisplay,
28 | * and an EGLSurface.
29 | */
30 | @SuppressWarnings("ReferenceEquality") // We want to compare to EGL14 constants.
31 | @TargetApi(18)
32 | public class EglBase14 implements EglBase {
33 | private static final String TAG = "EglBase14";
34 | private static final int EGLExt_SDK_VERSION = android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
35 | private static final int CURRENT_SDK_VERSION = android.os.Build.VERSION.SDK_INT;
36 | private EGLContext eglContext;
37 | @Nullable private EGLConfig eglConfig;
38 | private EGLDisplay eglDisplay;
39 | private EGLSurface eglSurface = EGL14.EGL_NO_SURFACE;
40 |
41 | // EGL 1.4 is supported from API 17. But EGLExt that is used for setting presentation
42 | // time stamp on a surface is supported from 18 so we require 18.
43 | public static boolean isEGL14Supported() {
44 | Logging.info(TAG,
45 | "SDK version: " + CURRENT_SDK_VERSION
46 | + ". isEGL14Supported: " + (CURRENT_SDK_VERSION >= EGLExt_SDK_VERSION));
47 | return (CURRENT_SDK_VERSION >= EGLExt_SDK_VERSION);
48 | }
49 |
50 | public static class Context implements EglBase.Context {
51 | private final android.opengl.EGLContext egl14Context;
52 |
53 | @Override
54 | @SuppressWarnings("deprecation")
55 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
56 | public long getNativeEglContext() {
57 | return CURRENT_SDK_VERSION >= Build.VERSION_CODES.LOLLIPOP ? egl14Context.getNativeHandle()
58 | : egl14Context.getHandle();
59 | }
60 |
61 | public Context(android.opengl.EGLContext eglContext) {
62 | this.egl14Context = eglContext;
63 | }
64 | }
65 |
66 | // Create a new context with the specified config type, sharing data with sharedContext.
67 | // |sharedContext| may be null.
68 | public EglBase14(EglBase14.Context sharedContext, int[] configAttributes) {
69 | eglDisplay = getEglDisplay();
70 | eglConfig = getEglConfig(eglDisplay, configAttributes);
71 | eglContext = createEglContext(sharedContext, eglDisplay, eglConfig);
72 | }
73 |
74 | // Create EGLSurface from the Android Surface.
75 | @Override
76 | public void createSurface(Surface surface) {
77 | createSurfaceInternal(surface);
78 | }
79 |
80 | // Create EGLSurface from the Android SurfaceTexture.
81 | @Override
82 | public void createSurface(SurfaceTexture surfaceTexture) {
83 | createSurfaceInternal(surfaceTexture);
84 | }
85 |
86 | // Create EGLSurface from either Surface or SurfaceTexture.
87 | private void createSurfaceInternal(Object surface) {
88 | if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) {
89 | throw new IllegalStateException("Input must be either a Surface or SurfaceTexture");
90 | }
91 | checkIsNotReleased();
92 | if (eglSurface != EGL14.EGL_NO_SURFACE) {
93 | throw new RuntimeException("Already has an EGLSurface");
94 | }
95 | int[] surfaceAttribs = {EGL14.EGL_NONE};
96 | eglSurface = EGL14.eglCreateWindowSurface(eglDisplay, eglConfig, surface, surfaceAttribs, 0);
97 | if (eglSurface == EGL14.EGL_NO_SURFACE) {
98 | throw new RuntimeException(
99 | "Failed to create window surface: 0x" + Integer.toHexString(EGL14.eglGetError()));
100 | }
101 | }
102 |
103 | @Override
104 | public void createDummyPbufferSurface() {
105 | createPbufferSurface(1, 1);
106 | }
107 |
108 | @Override
109 | public void createPbufferSurface(int width, int height) {
110 | checkIsNotReleased();
111 | if (eglSurface != EGL14.EGL_NO_SURFACE) {
112 | throw new RuntimeException("Already has an EGLSurface");
113 | }
114 | int[] surfaceAttribs = {EGL14.EGL_WIDTH, width, EGL14.EGL_HEIGHT, height, EGL14.EGL_NONE};
115 | eglSurface = EGL14.eglCreatePbufferSurface(eglDisplay, eglConfig, surfaceAttribs, 0);
116 | if (eglSurface == EGL14.EGL_NO_SURFACE) {
117 | throw new RuntimeException("Failed to create pixel buffer surface with size " + width + "x"
118 | + height + ": 0x" + Integer.toHexString(EGL14.eglGetError()));
119 | }
120 | }
121 |
122 | @Override
123 | public Context getEglBaseContext() {
124 | return new EglBase14.Context(eglContext);
125 | }
126 |
127 | @Override
128 | public boolean hasSurface() {
129 | return eglSurface != EGL14.EGL_NO_SURFACE;
130 | }
131 |
132 | @Override
133 | public int surfaceWidth() {
134 | final int widthArray[] = new int[1];
135 | EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_WIDTH, widthArray, 0);
136 | return widthArray[0];
137 | }
138 |
139 | @Override
140 | public int surfaceHeight() {
141 | final int heightArray[] = new int[1];
142 | EGL14.eglQuerySurface(eglDisplay, eglSurface, EGL14.EGL_HEIGHT, heightArray, 0);
143 | return heightArray[0];
144 | }
145 |
146 | @Override
147 | public void releaseSurface() {
148 | if (eglSurface != EGL14.EGL_NO_SURFACE) {
149 | EGL14.eglDestroySurface(eglDisplay, eglSurface);
150 | eglSurface = EGL14.EGL_NO_SURFACE;
151 | }
152 | }
153 |
154 | private void checkIsNotReleased() {
155 | if (eglDisplay == EGL14.EGL_NO_DISPLAY || eglContext == EGL14.EGL_NO_CONTEXT
156 | || eglConfig == null) {
157 | throw new RuntimeException("This object has been released");
158 | }
159 | }
160 |
161 | @Override
162 | public void release() {
163 | checkIsNotReleased();
164 | releaseSurface();
165 | detachCurrent();
166 | EGL14.eglDestroyContext(eglDisplay, eglContext);
167 | EGL14.eglReleaseThread();
168 | EGL14.eglTerminate(eglDisplay);
169 | eglContext = EGL14.EGL_NO_CONTEXT;
170 | eglDisplay = EGL14.EGL_NO_DISPLAY;
171 | eglConfig = null;
172 | }
173 |
174 | @Override
175 | public void makeCurrent() {
176 | checkIsNotReleased();
177 | if (eglSurface == EGL14.EGL_NO_SURFACE) {
178 | throw new RuntimeException("No EGLSurface - can't make current");
179 | }
180 | synchronized (EglBase.lock) {
181 | if (!EGL14.eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) {
182 | throw new RuntimeException(
183 | "eglMakeCurrent failed: 0x" + Integer.toHexString(EGL14.eglGetError()));
184 | }
185 | }
186 | }
187 |
188 | // Detach the current EGL context, so that it can be made current on another thread.
189 | @Override
190 | public void detachCurrent() {
191 | synchronized (EglBase.lock) {
192 | if (!EGL14.eglMakeCurrent(
193 | eglDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT)) {
194 | throw new RuntimeException(
195 | "eglDetachCurrent failed: 0x" + Integer.toHexString(EGL14.eglGetError()));
196 | }
197 | }
198 | }
199 |
200 | @Override
201 | public void swapBuffers() {
202 | checkIsNotReleased();
203 | if (eglSurface == EGL14.EGL_NO_SURFACE) {
204 | throw new RuntimeException("No EGLSurface - can't swap buffers");
205 | }
206 | synchronized (EglBase.lock) {
207 | EGL14.eglSwapBuffers(eglDisplay, eglSurface);
208 | }
209 | }
210 |
211 | @Override
212 | public void swapBuffers(long timeStampNs) {
213 | checkIsNotReleased();
214 | if (eglSurface == EGL14.EGL_NO_SURFACE) {
215 | throw new RuntimeException("No EGLSurface - can't swap buffers");
216 | }
217 | synchronized (EglBase.lock) {
218 | // See
219 | // https://android.googlesource.com/platform/frameworks/native/+/tools_r22.2/opengl/specs/EGL_ANDROID_presentation_time.txt
220 | EGLExt.eglPresentationTimeANDROID(eglDisplay, eglSurface, timeStampNs);
221 | EGL14.eglSwapBuffers(eglDisplay, eglSurface);
222 | }
223 | }
224 |
225 | // Return an EGLDisplay, or die trying.
226 | private static EGLDisplay getEglDisplay() {
227 | EGLDisplay eglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
228 | if (eglDisplay == EGL14.EGL_NO_DISPLAY) {
229 | throw new RuntimeException(
230 | "Unable to get EGL14 display: 0x" + Integer.toHexString(EGL14.eglGetError()));
231 | }
232 | int[] version = new int[2];
233 | if (!EGL14.eglInitialize(eglDisplay, version, 0, version, 1)) {
234 | throw new RuntimeException(
235 | "Unable to initialize EGL14: 0x" + Integer.toHexString(EGL14.eglGetError()));
236 | }
237 | return eglDisplay;
238 | }
239 |
240 | // Return an EGLConfig, or die trying.
241 | private static EGLConfig getEglConfig(EGLDisplay eglDisplay, int[] configAttributes) {
242 | EGLConfig[] configs = new EGLConfig[1];
243 | int[] numConfigs = new int[1];
244 | if (!EGL14.eglChooseConfig(
245 | eglDisplay, configAttributes, 0, configs, 0, configs.length, numConfigs, 0)) {
246 | throw new RuntimeException(
247 | "eglChooseConfig failed: 0x" + Integer.toHexString(EGL14.eglGetError()));
248 | }
249 | if (numConfigs[0] <= 0) {
250 | throw new RuntimeException("Unable to find any matching EGL config");
251 | }
252 | final EGLConfig eglConfig = configs[0];
253 | if (eglConfig == null) {
254 | throw new RuntimeException("eglChooseConfig returned null");
255 | }
256 | return eglConfig;
257 | }
258 |
259 | // Return an EGLConfig, or die trying.
260 | private static EGLContext createEglContext(
261 | @Nullable EglBase14.Context sharedContext, EGLDisplay eglDisplay, EGLConfig eglConfig) {
262 | if (sharedContext != null && sharedContext.egl14Context == EGL14.EGL_NO_CONTEXT) {
263 | throw new RuntimeException("Invalid sharedContext");
264 | }
265 | int[] contextAttributes = {EGL14.EGL_CONTEXT_CLIENT_VERSION, 2, EGL14.EGL_NONE};
266 | EGLContext rootContext =
267 | sharedContext == null ? EGL14.EGL_NO_CONTEXT : sharedContext.egl14Context;
268 | final EGLContext eglContext;
269 | synchronized (EglBase.lock) {
270 | eglContext = EGL14.eglCreateContext(eglDisplay, eglConfig, rootContext, contextAttributes, 0);
271 | }
272 | if (eglContext == EGL14.EGL_NO_CONTEXT) {
273 | throw new RuntimeException(
274 | "Failed to create EGL context: 0x" + Integer.toHexString(EGL14.eglGetError()));
275 | }
276 | return eglContext;
277 | }
278 | }
279 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/filters/UgiBrightnessFilter.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.filters;
2 |
3 | import com.piasy.ugi.UgiFilter;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
7 | */
8 | public class UgiBrightnessFilter extends UgiFilter {
9 | public UgiBrightnessFilter() {
10 | super(FILTER_BRIGHTNESS);
11 | }
12 |
13 | private static native void nativeSetBrightness(long handle, float brightness);
14 |
15 | public void setBrightness(float brightness) {
16 | if (mNativeHandle != 0) {
17 | nativeSetBrightness(mNativeHandle, brightness);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/filters/UgiColorInvertFilter.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.filters;
2 |
3 | import com.piasy.ugi.UgiFilter;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
7 | */
8 | public class UgiColorInvertFilter extends UgiFilter {
9 | public UgiColorInvertFilter() {
10 | super(FILTER_COLOR_INVERT);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/filters/UgiFilterGroup.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.filters;
2 |
3 | import com.piasy.ugi.UgiFilter;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
7 | */
8 | public class UgiFilterGroup extends UgiFilter {
9 | public UgiFilterGroup() {
10 | super(FILTER_GROUP);
11 | }
12 |
13 | private static native void nativeAddFilter(long handle, long filterHandle);
14 |
15 | public void addFilter(UgiFilter filter) {
16 | if (mNativeHandle != 0 && filter.getNativeHandle() != 0) {
17 | nativeAddFilter(mNativeHandle, filter.getNativeHandle());
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/filters/UgiPreprocessFilter.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.filters;
2 |
3 | import com.piasy.ugi.UgiFilter;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/22.
7 | */
8 | public class UgiPreprocessFilter extends UgiFilter {
9 | public UgiPreprocessFilter() {
10 | super(FILTER_PREPROCESS);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/utils/Logging.java:
--------------------------------------------------------------------------------
1 | package com.piasy.ugi.utils;
2 |
3 | import android.util.Log;
4 |
5 | /**
6 | * Created by Piasy{github.com/Piasy} on 2018/12/17.
7 | */
8 | public class Logging {
9 | private static Loggable sLoggable;
10 | private static boolean sLogToConsole;
11 |
12 | public static void setLoggable(final Loggable loggable) {
13 | sLoggable = loggable;
14 | }
15 |
16 | public static void setLogToConsole(final boolean logToConsole) {
17 | sLogToConsole = logToConsole;
18 | }
19 |
20 | public static void info(String tag, String message) {
21 | if (sLoggable != null) {
22 | sLoggable.info(tag, message);
23 | }
24 | if (sLogToConsole) {
25 | Log.i(tag, message);
26 | }
27 | }
28 |
29 | public static void error(String tag, String message) {
30 | error(tag, message, null);
31 | }
32 |
33 | public static void error(String tag, String message, Throwable e) {
34 | if (sLoggable != null) {
35 | sLoggable.error(tag, message, e);
36 | }
37 | if (sLogToConsole) {
38 | Log.e(tag, message, e);
39 | }
40 | }
41 |
42 | public interface Loggable {
43 | void info(String tag, String message);
44 |
45 | void error(String tag, String message, Throwable e);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/UltraGpuImage-Android/src/main/java/com/piasy/ugi/utils/ThreadUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2015 The WebRTC project authors. All Rights Reserved.
3 | *
4 | * Use of this source code is governed by a BSD-style license
5 | * that can be found in the LICENSE file in the root of the source
6 | * tree. An additional intellectual property rights grant can be found
7 | * in the file PATENTS. All contributing project authors may
8 | * be found in the AUTHORS file in the root of the source tree.
9 | */
10 |
11 | package com.piasy.ugi.utils;
12 |
13 | import android.os.Handler;
14 | import android.os.Looper;
15 | import android.os.SystemClock;
16 | import java.util.concurrent.Callable;
17 | import java.util.concurrent.CountDownLatch;
18 | import java.util.concurrent.TimeUnit;
19 | import javax.annotation.Nullable;
20 |
21 | public class ThreadUtils {
22 | /**
23 | * Utility class to be used for checking that a method is called on the correct thread.
24 | */
25 | public static class ThreadChecker {
26 | @Nullable private Thread thread = Thread.currentThread();
27 |
28 | public void checkIsOnValidThread() {
29 | if (thread == null) {
30 | thread = Thread.currentThread();
31 | }
32 | if (Thread.currentThread() != thread) {
33 | throw new IllegalStateException("Wrong thread");
34 | }
35 | }
36 |
37 | public void detachThread() {
38 | thread = null;
39 | }
40 | }
41 |
42 | /**
43 | * Throws exception if called from other than main thread.
44 | */
45 | public static void checkIsOnMainThread() {
46 | if (Thread.currentThread() != Looper.getMainLooper().getThread()) {
47 | throw new IllegalStateException("Not on main thread!");
48 | }
49 | }
50 |
51 | /**
52 | * Utility interface to be used with executeUninterruptibly() to wait for blocking operations
53 | * to complete without getting interrupted..
54 | */
55 | public interface BlockingOperation { void run() throws InterruptedException; }
56 |
57 | /**
58 | * Utility method to make sure a blocking operation is executed to completion without getting
59 | * interrupted. This should be used in cases where the operation is waiting for some critical
60 | * work, e.g. cleanup, that must complete before returning. If the thread is interrupted during
61 | * the blocking operation, this function will re-run the operation until completion, and only then
62 | * re-interrupt the thread.
63 | */
64 | public static void executeUninterruptibly(BlockingOperation operation) {
65 | boolean wasInterrupted = false;
66 | while (true) {
67 | try {
68 | operation.run();
69 | break;
70 | } catch (InterruptedException e) {
71 | // Someone is asking us to return early at our convenience. We can't cancel this operation,
72 | // but we should preserve the information and pass it along.
73 | wasInterrupted = true;
74 | }
75 | }
76 | // Pass interruption information along.
77 | if (wasInterrupted) {
78 | Thread.currentThread().interrupt();
79 | }
80 | }
81 |
82 | public static boolean joinUninterruptibly(final Thread thread, long timeoutMs) {
83 | final long startTimeMs = SystemClock.elapsedRealtime();
84 | long timeRemainingMs = timeoutMs;
85 | boolean wasInterrupted = false;
86 | while (timeRemainingMs > 0) {
87 | try {
88 | thread.join(timeRemainingMs);
89 | break;
90 | } catch (InterruptedException e) {
91 | // Someone is asking us to return early at our convenience. We can't cancel this operation,
92 | // but we should preserve the information and pass it along.
93 | wasInterrupted = true;
94 | final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
95 | timeRemainingMs = timeoutMs - elapsedTimeMs;
96 | }
97 | }
98 | // Pass interruption information along.
99 | if (wasInterrupted) {
100 | Thread.currentThread().interrupt();
101 | }
102 | return !thread.isAlive();
103 | }
104 |
105 | public static void joinUninterruptibly(final Thread thread) {
106 | executeUninterruptibly(new BlockingOperation() {
107 | @Override
108 | public void run() throws InterruptedException {
109 | thread.join();
110 | }
111 | });
112 | }
113 |
114 | public static void awaitUninterruptibly(final CountDownLatch latch) {
115 | executeUninterruptibly(new BlockingOperation() {
116 | @Override
117 | public void run() throws InterruptedException {
118 | latch.await();
119 | }
120 | });
121 | }
122 |
123 | public static boolean awaitUninterruptibly(CountDownLatch barrier, long timeoutMs) {
124 | final long startTimeMs = SystemClock.elapsedRealtime();
125 | long timeRemainingMs = timeoutMs;
126 | boolean wasInterrupted = false;
127 | boolean result = false;
128 | do {
129 | try {
130 | result = barrier.await(timeRemainingMs, TimeUnit.MILLISECONDS);
131 | break;
132 | } catch (InterruptedException e) {
133 | // Someone is asking us to return early at our convenience. We can't cancel this operation,
134 | // but we should preserve the information and pass it along.
135 | wasInterrupted = true;
136 | final long elapsedTimeMs = SystemClock.elapsedRealtime() - startTimeMs;
137 | timeRemainingMs = timeoutMs - elapsedTimeMs;
138 | }
139 | } while (timeRemainingMs > 0);
140 | // Pass interruption information along.
141 | if (wasInterrupted) {
142 | Thread.currentThread().interrupt();
143 | }
144 | return result;
145 | }
146 |
147 | /**
148 | * Post |callable| to |handler| and wait for the result.
149 | */
150 | public static V invokeAtFrontUninterruptibly(
151 | final Handler handler, final Callable callable) {
152 | if (handler.getLooper().getThread() == Thread.currentThread()) {
153 | try {
154 | return callable.call();
155 | } catch (Exception e) {
156 | throw new RuntimeException(e);
157 | }
158 | }
159 | // Place-holder classes that are assignable inside nested class.
160 | class CaughtException {
161 | Exception e;
162 | }
163 | class Result {
164 | public V value;
165 | }
166 | final Result result = new Result();
167 | final CaughtException caughtException = new CaughtException();
168 | final CountDownLatch barrier = new CountDownLatch(1);
169 | handler.post(new Runnable() {
170 | @Override
171 | public void run() {
172 | try {
173 | result.value = callable.call();
174 | } catch (Exception e) {
175 | caughtException.e = e;
176 | }
177 | barrier.countDown();
178 | }
179 | });
180 | awaitUninterruptibly(barrier);
181 | // Re-throw any runtime exception caught inside the other thread. Since this is an invoke, add
182 | // stack trace for the waiting thread as well.
183 | if (caughtException.e != null) {
184 | final RuntimeException runtimeException = new RuntimeException(caughtException.e);
185 | runtimeException.setStackTrace(
186 | concatStackTraces(caughtException.e.getStackTrace(), runtimeException.getStackTrace()));
187 | throw runtimeException;
188 | }
189 | return result.value;
190 | }
191 |
192 | /**
193 | * Post |runner| to |handler|, at the front, and wait for completion.
194 | */
195 | public static void invokeAtFrontUninterruptibly(final Handler handler, final Runnable runner) {
196 | invokeAtFrontUninterruptibly(handler, new Callable() {
197 | @Override
198 | public Void call() {
199 | runner.run();
200 | return null;
201 | }
202 | });
203 | }
204 |
205 | static StackTraceElement[] concatStackTraces(
206 | StackTraceElement[] inner, StackTraceElement[] outer) {
207 | final StackTraceElement[] combined = new StackTraceElement[inner.length + outer.length];
208 | System.arraycopy(inner, 0, combined, 0, inner.length);
209 | System.arraycopy(outer, 0, combined, inner.length, outer.length);
210 | return combined;
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/module.modulemap:
--------------------------------------------------------------------------------
1 | framework module UltraGpuImage_iOS {
2 | umbrella header "UltraGpuImage_iOS.h"
3 |
4 | export *
5 | module * { export * }
6 | }
7 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/project.yml:
--------------------------------------------------------------------------------
1 | name: UltraGpuImage-iOS
2 | targets:
3 | UltraGpuImage_iOS:
4 | type: framework
5 | platform: iOS
6 | deploymentTarget: "9.0"
7 | sources:
8 | - path: src
9 | dependencies:
10 | - framework: "$(PROJECT_DIR)/../libs/libUltraGpuImage.a"
11 | implicit: true
12 | - sdk: OpenGLES.framework
13 | settings:
14 | LIBRARY_SEARCH_PATHS: "$(inherited) $(PROJECT_DIR)/../libs"
15 | FRAMEWORK_SEARCH_PATHS: "$(inherited)"
16 | USER_HEADER_SEARCH_PATHS: "$(inherited) $(PROJECT_DIR)/../UltraGpuImage/src"
17 | PRODUCT_BUNDLE_IDENTIFIER: "com.piasy.ugi.UltraGpuImage"
18 | CONFIGURATION_BUILD_DIR: "$(PROJECT_DIR)/../libs/"
19 | CLANG_WARN_DOCUMENTATION_COMMENTS: "NO"
20 | ENABLE_BITCODE: "NO"
21 | ONLY_ACTIVE_ARCH: "NO"
22 | CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES: "YES"
23 | DEFINES_MODULE: "YES"
24 | SKIP_INSTALL: "YES"
25 | VALID_ARCHS: "arm64"
26 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | UltraGpuImage
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | com.piasy.ugi
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | FMWK
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | NS_ASSUME_NONNULL_BEGIN
31 |
32 | @protocol UgiFilter
33 |
34 | - (void*)nativeFilter;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiLogging.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | NS_ASSUME_NONNULL_BEGIN
31 |
32 | @interface UgiLogging : NSObject
33 |
34 | + (void)setLogToConsole:(bool)logToConsole;
35 |
36 | + (void)info:(NSString*)fmt, ...;
37 | + (void)error:(NSString*)fmt, ...;
38 |
39 | @end
40 |
41 | NS_ASSUME_NONNULL_END
42 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiLogging.m:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiLogging.h"
29 |
30 | static bool gLogToConsole = false;
31 |
32 | @implementation UgiLogging
33 |
34 | + (void)setLogToConsole:(bool)logToConsole {
35 | gLogToConsole = logToConsole;
36 | }
37 |
38 | + (void)info:(NSString*)fmt, ... {
39 | if (gLogToConsole) {
40 | va_list args;
41 | va_start(args, fmt);
42 | NSLog(fmt, args);
43 | va_end(args);
44 | }
45 | }
46 |
47 | + (void)error:(NSString*)fmt, ... {
48 | if (gLogToConsole) {
49 | va_list args;
50 | va_start(args, fmt);
51 | NSLog(fmt, args);
52 | va_end(args);
53 | }
54 | }
55 |
56 | @end
57 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiRenderer.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | #import
31 |
32 | #import "UgiTransformation.h"
33 | #import "UgiFilter.h"
34 |
35 | NS_ASSUME_NONNULL_BEGIN
36 |
37 | @interface UgiRenderer : NSObject
38 |
39 | @property UgiTransformation* transformation;
40 |
41 | - (instancetype)init;
42 |
43 | - (instancetype)initWithName:(NSString*)name;
44 |
45 | - (void)onSurfaceCreated:(CAEAGLLayer*)eaglLayer;
46 |
47 | - (void)onSurfaceDestroyed;
48 |
49 | - (void)renderRgb:(GLuint)textureId;
50 |
51 | - (void)runOnRenderThread:(void (^)(void))task;
52 |
53 | - (void)notifyTransformationUpdated;
54 |
55 | - (void)setFilter:(id)filter;
56 |
57 | @end
58 |
59 | NS_ASSUME_NONNULL_END
60 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiRenderer.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiRenderer.h"
29 |
30 | #import
31 |
32 | #import "UgiLogging.h"
33 | #import "UgiTransformation+Native.h"
34 |
35 | #include "ugi_renderer.h"
36 | #include "filters/ugi_preprocess_filter.h"
37 |
38 | #define TAG "UgiRenderer"
39 |
40 | @implementation UgiRenderer {
41 | NSString* _name;
42 |
43 | dispatch_queue_t _renderQueue;
44 |
45 | EAGLContext* _glContext;
46 | GLuint _fbo;
47 | GLuint _rbo;
48 |
49 | Ugi::Renderer* _renderer;
50 | id _filter;
51 | }
52 |
53 | - (instancetype)init {
54 | return [self initWithName:@""];
55 | }
56 |
57 | - (instancetype)initWithName:(NSString*)name {
58 | if (self = [super init]) {
59 | _name = name;
60 |
61 | NSString* queueName =
62 | [NSString stringWithFormat:@"UgiRenderer-%@", _name];
63 | _renderQueue = dispatch_queue_create(queueName.UTF8String, NULL);
64 |
65 | __block EAGLContext* context = nil;
66 | // TODO: do we need this dispatch?
67 | dispatch_sync(_renderQueue, ^{
68 | context =
69 | [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
70 | });
71 | if (!context) {
72 | [self logError:@"Failed to create EAGLContext"];
73 | _renderQueue = nil;
74 | return nil;
75 | }
76 | _glContext = context;
77 |
78 | _transformation = [[UgiTransformation alloc] init];
79 | _renderer = new Ugi::Renderer(*(_transformation.transformation));
80 | }
81 |
82 | [self logInfo:@"new UgiRenderer success"];
83 |
84 | return self;
85 | }
86 |
87 | - (void)dealloc {
88 | _renderQueue = nil;
89 | if (_renderer) {
90 | delete _renderer;
91 | _renderer = nullptr;
92 | }
93 | }
94 |
95 | - (void)onSurfaceCreated:(CAEAGLLayer*)eaglLayer {
96 | __weak UgiRenderer* weakSelf = self;
97 | [self runOnRenderThread:^{
98 | UgiRenderer* strongSelf = weakSelf;
99 | if (!strongSelf) {
100 | return;
101 | }
102 | eaglLayer.opaque = YES;
103 | eaglLayer.drawableProperties = @{
104 | kEAGLDrawablePropertyRetainedBacking : @(NO),
105 | kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8
106 | };
107 |
108 | glGenFramebuffers(1, &strongSelf->_fbo);
109 | glGenRenderbuffers(1, &strongSelf->_rbo);
110 | glBindFramebuffer(GL_FRAMEBUFFER, strongSelf->_fbo);
111 | glBindRenderbuffer(GL_RENDERBUFFER, strongSelf->_rbo);
112 | dispatch_sync(dispatch_get_main_queue(), ^{
113 | [strongSelf->_glContext renderbufferStorage:GL_RENDERBUFFER
114 | fromDrawable:eaglLayer];
115 | });
116 |
117 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
118 | GL_RENDERBUFFER, strongSelf->_rbo);
119 |
120 | strongSelf->_renderer->OnSurfaceCreated();
121 | }];
122 | }
123 |
124 | - (void)onSurfaceDestroyed {
125 | __weak UgiRenderer* weakSelf = self;
126 | [self runOnRenderThread:^{
127 | UgiRenderer* strongSelf = weakSelf;
128 | if (!strongSelf) {
129 | return;
130 | }
131 |
132 | if (strongSelf->_fbo) {
133 | glDeleteFramebuffers(1, &(strongSelf->_fbo));
134 | strongSelf->_fbo = 0;
135 | }
136 | if (strongSelf->_rbo) {
137 | glDeleteRenderbuffers(1, &(strongSelf->_rbo));
138 | strongSelf->_rbo = 0;
139 | }
140 | }];
141 | }
142 |
143 | - (void)renderRgb:(GLuint)textureId {
144 | __weak UgiRenderer* weakSelf = self;
145 | [self runOnRenderThread:^{
146 | UgiRenderer* strongSelf = weakSelf;
147 | if (!strongSelf) {
148 | return;
149 | }
150 | strongSelf->_renderer->RenderTexture(Ugi::kTextureTypeRgb, textureId);
151 | [strongSelf->_glContext presentRenderbuffer:GL_RENDERBUFFER];
152 | }];
153 | }
154 |
155 | - (void)runOnRenderThread:(void (^)(void))task {
156 | __weak UgiRenderer* weakSelf = self;
157 | dispatch_async(_renderQueue, ^{
158 | UgiRenderer* strongSelf = weakSelf;
159 | if (!strongSelf) {
160 | return;
161 | }
162 | [EAGLContext setCurrentContext:strongSelf->_glContext];
163 | task();
164 | [EAGLContext setCurrentContext:nil];
165 | });
166 | }
167 |
168 | - (void)notifyTransformationUpdated {
169 | __weak UgiRenderer* weakSelf = self;
170 | [self runOnRenderThread:^{
171 | UgiRenderer* strongSelf = weakSelf;
172 | if (!strongSelf) {
173 | return;
174 | }
175 | strongSelf->_renderer->UpdateTransformation(
176 | *(strongSelf->_transformation.transformation));
177 | }];
178 | }
179 |
180 | - (void)setFilter:(id)filter {
181 | _filter = filter;
182 | Ugi::Filter* nativeFilter = (Ugi::Filter*) [filter nativeFilter];
183 | if (_renderer && nativeFilter) {
184 | _renderer->SetFilter(nativeFilter);
185 | }
186 | }
187 |
188 | - (void)logInfo:(NSString*)fmt, ... {
189 | va_list args;
190 | va_start(args, fmt);
191 | NSString* log = [NSString stringWithFormat:fmt, args];
192 | va_end(args);
193 |
194 | [UgiLogging info:@"%s %@(%p) %@", TAG, _name, self, log];
195 | }
196 |
197 | - (void)logError:(NSString*)fmt, ... {
198 | va_list args;
199 | va_start(args, fmt);
200 | NSString* log = [NSString stringWithFormat:fmt, args];
201 | va_end(args);
202 |
203 | [UgiLogging error:@"%s %@(%p) %@", TAG, _name, self, log];
204 | }
205 |
206 | @end
207 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiRendererView.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | #import "UgiTransformation.h"
31 | #import "UgiFilter.h"
32 |
33 | NS_ASSUME_NONNULL_BEGIN
34 |
35 | typedef enum : NSUInteger {
36 | kUgiRenderModePicture,
37 | kUgiRenderModeCameraPreview,
38 | } UgiRenderMode;
39 |
40 | @interface UgiRendererView : UIView
41 |
42 | - (void)initialize:(NSString*)name renderMode:(UgiRenderMode)renderMode;
43 |
44 | - (UgiTransformation*)transformation;
45 | - (void)notifyTransformationUpdated;
46 |
47 | - (void)setFilter:(id)filter;
48 | - (void)notifyFilterUpdated;
49 |
50 | - (void)renderPicture:(UIImage*)picture;
51 | - (void)renderPicture:(UIImage*)picture
52 | needFlipVertically:(bool)needFlipVertically;
53 |
54 | @end
55 |
56 | NS_ASSUME_NONNULL_END
57 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiRendererView.m:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiRendererView.h"
29 |
30 | #include "ugi_gl.h"
31 |
32 | #import "UgiRenderer.h"
33 | #import "UgiLogging.h"
34 |
35 | @implementation UgiRendererView {
36 | UgiRenderMode _renderMode;
37 | UgiRenderer* _renderer;
38 |
39 | GLuint _pictureTextureId;
40 | int _pictureWidth;
41 | int _pictureHeight;
42 | }
43 |
44 | - (instancetype)initWithFrame:(CGRect)frame andName:(NSString*)name {
45 | if (self = [super initWithFrame:frame]) {
46 | _pictureTextureId = -1;
47 | }
48 | return self;
49 | }
50 |
51 | + (Class)layerClass {
52 | return [CAEAGLLayer class];
53 | }
54 |
55 | - (void)initialize:(NSString*)name renderMode:(UgiRenderMode)renderMode {
56 | if (!self.layer) {
57 | [UgiLogging error:@"UgiRendererView initialize error: no layer"];
58 | return;
59 | }
60 | _renderMode = renderMode;
61 | _renderer = [[UgiRenderer alloc] initWithName:name];
62 | if (!_renderer) {
63 | return;
64 | }
65 |
66 | [_renderer onSurfaceCreated:(CAEAGLLayer*)self.layer];
67 | }
68 |
69 | - (UgiTransformation*)transformation {
70 | return _renderer.transformation;
71 | }
72 |
73 | - (void)notifyTransformationUpdated {
74 | [_renderer notifyTransformationUpdated];
75 | if (_renderMode == kUgiRenderModePicture && _pictureTextureId != -1) {
76 | [_renderer renderRgb:_pictureTextureId];
77 | }
78 | }
79 |
80 | - (void)setFilter:(id)filter {
81 | [_renderer setFilter:filter];
82 | [self notifyFilterUpdated];
83 | }
84 |
85 | - (void)notifyFilterUpdated {
86 | if (_renderMode == kUgiRenderModePicture && _pictureTextureId != -1) {
87 | [_renderer renderRgb:_pictureTextureId];
88 | }
89 | }
90 |
91 | - (void)renderPicture:(UIImage*)picture {
92 | [self renderPicture:picture needFlipVertically:true];
93 | }
94 |
95 | - (void)renderPicture:(UIImage*)picture
96 | needFlipVertically:(bool)needFlipVertically {
97 | __weak UgiRendererView* weakSelf = self;
98 | [_renderer runOnRenderThread:^{
99 | UgiRendererView* strongSelf = weakSelf;
100 | if (!strongSelf) {
101 | return;
102 | }
103 |
104 | CGImageRef image;
105 | if (needFlipVertically) {
106 | // credit: https://stackoverflow.com/a/24799281/3077508
107 | UIGraphicsBeginImageContextWithOptions(picture.size, NO,
108 | picture.scale);
109 | CGContextDrawImage(
110 | UIGraphicsGetCurrentContext(),
111 | CGRectMake(0, 0, picture.size.width, picture.size.height),
112 | picture.CGImage);
113 | UIImage* flippedPicture =
114 | UIGraphicsGetImageFromCurrentImageContext();
115 | UIGraphicsEndImageContext();
116 | image = flippedPicture.CGImage;
117 | } else {
118 | image = picture.CGImage;
119 | }
120 | strongSelf->_pictureWidth = (int)CGImageGetWidth(image);
121 | strongSelf->_pictureHeight = (int)CGImageGetHeight(image);
122 |
123 | CGSize size = strongSelf.layer.bounds.size;
124 |
125 | [strongSelf->_renderer.transformation
126 | updateInput:strongSelf->_pictureWidth
127 | height:strongSelf->_pictureHeight];
128 | [strongSelf->_renderer.transformation updateOutput:(int)size.width
129 | height:(int)size.height];
130 | [strongSelf->_renderer notifyTransformationUpdated];
131 |
132 | strongSelf->_pictureTextureId = [UgiRendererView loadTexture:image];
133 | [strongSelf->_renderer renderRgb:strongSelf->_pictureTextureId];
134 | }];
135 | }
136 |
137 | + (GLuint)loadTexture:(CGImageRef)image {
138 | CGFloat width = CGImageGetWidth(image);
139 | CGFloat height = CGImageGetHeight(image);
140 | CFDataRef dataFromImageDataProvider =
141 | CGDataProviderCopyData(CGImageGetDataProvider(image));
142 | GLubyte* imageData = (GLubyte*)CFDataGetBytePtr(dataFromImageDataProvider);
143 | GLuint textureId = 0;
144 | glGenTextures(1, &textureId);
145 | glBindTexture(GL_TEXTURE_2D, textureId);
146 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
147 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
148 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
149 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
150 | // TODO: GL_BGRA or GL_RGBA
151 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)width, (int)height, 0, GL_BGRA,
152 | GL_UNSIGNED_BYTE, imageData);
153 | return textureId;
154 | }
155 |
156 | @end
157 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiTransformation+Native.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #ifndef UgiTransformation_Native_h
29 | #define UgiTransformation_Native_h
30 |
31 | #import "UgiTransformation.h"
32 |
33 | #include "ugi_transformation.h"
34 |
35 | @interface UgiTransformation ()
36 |
37 | @property Ugi::Transformation* transformation;
38 |
39 | @end
40 |
41 | #endif /* UgiTransformation_Native_h */
42 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiTransformation.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | NS_ASSUME_NONNULL_BEGIN
31 |
32 | #define UGI_COORDS_SCALE 10000
33 |
34 | typedef enum : NSUInteger {
35 | kUgiFlipNone = 0,
36 | kUgiFlipHorizontal = 1,
37 | kUgiFlipVertical = 2,
38 | kUgiFlipHorizontalVertical = 3,
39 | } UgiFlip;
40 |
41 | typedef enum : NSUInteger {
42 | kUgiRotation0 = 0,
43 | kUgiRotation90 = 90,
44 | kUgiRotation180 = 180,
45 | kUgiRotation270 = 270,
46 | } UgiRotation;
47 |
48 | typedef enum : NSUInteger {
49 | kUgiScaleFitXY = 0,
50 | kUgiScaleCenterCrop = 1,
51 | kUgiScaleCenterInside = 2,
52 | } UgiScaleType;
53 |
54 | @interface UgiTransformation : NSObject
55 |
56 | - (void)updateInput:(int)width height:(int)height;
57 |
58 | - (void)updateOutput:(int)width height:(int)height;
59 |
60 | @end
61 |
62 | NS_ASSUME_NONNULL_END
63 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UgiTransformation.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiTransformation+Native.h"
29 |
30 | #include "ugi_transformation.h"
31 |
32 | @implementation UgiTransformation
33 |
34 | - (instancetype)init {
35 | self = [super init];
36 | if (self) {
37 | Ugi::Transformation::Size size(480, 640);
38 | _transformation = new Ugi::Transformation(size, size);
39 | }
40 | return self;
41 | }
42 |
43 | - (void)dealloc {
44 | if (_transformation) {
45 | delete _transformation;
46 | _transformation = nullptr;
47 | }
48 | }
49 |
50 | - (void)updateInput:(int)width height:(int)height {
51 | if (_transformation) {
52 | _transformation->UpdateInput(Ugi::Transformation::Size(width, height));
53 | }
54 | }
55 |
56 | - (void)updateOutput:(int)width height:(int)height {
57 | if (_transformation) {
58 | _transformation->UpdateOutput(Ugi::Transformation::Size(width, height));
59 | }
60 | }
61 |
62 | @end
63 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/UltraGpuImage_iOS.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #ifndef UltraGpuImage_iOS_h
29 | #define UltraGpuImage_iOS_h
30 |
31 | #import "UgiRenderer.h"
32 | #import "UgiRendererView.h"
33 | #import "UgiTransformation.h"
34 |
35 | #import "UgiBrightnessFilter.h"
36 | #import "UgiColorInvertFilter.h"
37 | #import "UgiFilterGroup.h"
38 | #import "UgiPreprocessFilter.h"
39 |
40 | #endif /* UltraGpuImage_iOS_h */
41 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiBrightnessFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | #import "UgiFilter.h"
31 |
32 | NS_ASSUME_NONNULL_BEGIN
33 |
34 | @interface UgiBrightnessFilter : NSObject
35 |
36 | - (void)setBrightness:(float)brightness;
37 |
38 | @end
39 |
40 | NS_ASSUME_NONNULL_END
41 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiBrightnessFilter.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiBrightnessFilter.h"
29 |
30 | #include "filters/ugi_brightness_filter.h"
31 |
32 | @implementation UgiBrightnessFilter {
33 | Ugi::BrightnessFilter* _filter;
34 | }
35 |
36 | - (instancetype)init {
37 | self = [super init];
38 | if (self) {
39 | _filter = new Ugi::BrightnessFilter();
40 | }
41 | return self;
42 | }
43 |
44 | - (void*)nativeFilter {
45 | return _filter;
46 | }
47 |
48 | - (void)setBrightness:(float)brightness {
49 | if (_filter) {
50 | _filter->SetBrightness(brightness);
51 | }
52 | }
53 |
54 | @end
55 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiColorInvertFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | #import "UgiFilter.h"
31 |
32 | NS_ASSUME_NONNULL_BEGIN
33 |
34 | @interface UgiColorInvertFilter : NSObject
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiColorInvertFilter.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiColorInvertFilter.h"
29 |
30 | #include "filters/ugi_color_invert_filter.h"
31 |
32 | @implementation UgiColorInvertFilter {
33 | Ugi::ColorInvertFilter* _filter;
34 | }
35 |
36 | - (instancetype)init {
37 | self = [super init];
38 | if (self) {
39 | _filter = new Ugi::ColorInvertFilter();
40 | }
41 | return self;
42 | }
43 |
44 | - (void*)nativeFilter {
45 | return _filter;
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiFilterGroup.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiFilter.h"
29 |
30 | NS_ASSUME_NONNULL_BEGIN
31 |
32 | @interface UgiFilterGroup : NSObject
33 |
34 | - (void)addFilter:(id)filter;
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiFilterGroup.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiFilterGroup.h"
29 |
30 | #include "filters/ugi_filter_group.h"
31 |
32 | @implementation UgiFilterGroup {
33 | Ugi::FilterGroup* _filter;
34 | }
35 |
36 | - (instancetype)init {
37 | self = [super init];
38 | if (self) {
39 | _filter = new Ugi::FilterGroup();
40 | }
41 | return self;
42 | }
43 |
44 | - (void*)nativeFilter {
45 | return _filter;
46 | }
47 |
48 | - (void)addFilter:(id)filter {
49 | Ugi::Filter* nativeFilter = (Ugi::Filter*) [filter nativeFilter];
50 | if (_filter && nativeFilter) {
51 | _filter->AddFilter(nativeFilter);
52 | }
53 | }
54 |
55 | @end
56 |
57 |
58 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiPreprocessFilter.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | #import "UgiFilter.h"
31 |
32 | NS_ASSUME_NONNULL_BEGIN
33 |
34 | @interface UgiPreprocessFilter : NSObject
35 |
36 | @end
37 |
38 | NS_ASSUME_NONNULL_END
39 |
--------------------------------------------------------------------------------
/UltraGpuImage-iOS/src/filters/UgiPreprocessFilter.mm:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "UgiPreprocessFilter.h"
29 |
30 | #include "filters/ugi_preprocess_filter.h"
31 |
32 | @implementation UgiPreprocessFilter {
33 | Ugi::PreprocessFilter* _filter;
34 | }
35 |
36 | - (instancetype)init {
37 | self = [super init];
38 | if (self) {
39 | _filter = new Ugi::PreprocessFilter();
40 | }
41 | return self;
42 | }
43 |
44 | - (void*)nativeFilter {
45 | return _filter;
46 | }
47 |
48 | @end
49 |
--------------------------------------------------------------------------------
/UltraGpuImage.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/UltraGpuImage.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/UltraGpuImage/project.yml:
--------------------------------------------------------------------------------
1 | name: UltraGpuImage
2 | targets:
3 | UltraGpuImage:
4 | type: library.static
5 | platform: iOS
6 | deploymentTarget: "9.0"
7 | sources:
8 | - path: src
9 | settings:
10 | GCC_PREPROCESSOR_DEFINITIONS: "$(inherited) GLES_SILENCE_DEPRECATION=1"
11 | CONFIGURATION_BUILD_DIR: "$(PROJECT_DIR)/../libs/"
12 | CLANG_WARN_DOCUMENTATION_COMMENTS: "NO"
13 | ENABLE_BITCODE: "NO"
14 | ONLY_ACTIVE_ARCH: "NO"
15 | SKIP_INSTALL: "YES"
16 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_brightness_filter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/23.
3 | //
4 |
5 | #include "ugi_brightness_filter.h"
6 |
7 | namespace Ugi {
8 |
9 | static const GLchar* kFragmentShader
10 | = "#version " UGI_GLSL_VERSION "\n"
11 | "#ifdef GL_ES\n"
12 | "precision mediump float;\n"
13 | "#endif\n"
14 | "in vec2 texCoords;\n"
15 | "uniform sampler2D tex;\n"
16 | "uniform float brightness;\n"
17 | "out vec4 fragColor;\n"
18 | "void main() {\n"
19 | " vec4 color = texture(tex, texCoords);\n"
20 | " fragColor = vec4((color.rgb + vec3(brightness)), color.a);\n"
21 | "}\n";
22 |
23 | BrightnessFilter::BrightnessFilter() : Filter(kDirectVertexShader, kFragmentShader),
24 | brightness_(0) {
25 |
26 | }
27 |
28 | int BrightnessFilter::Init(int32_t width, int32_t height) {
29 | int result = Filter::Init(width, height);
30 |
31 | if (result == 0) {
32 | brightness_loc_ = glGetUniformLocation(program_, "brightness");
33 | }
34 |
35 | return result;
36 | }
37 |
38 | void BrightnessFilter::PreDraw() {
39 | Filter::PreDraw();
40 |
41 | glUniform1f(brightness_loc_, brightness_);
42 | }
43 |
44 | void BrightnessFilter::SetBrightness(GLfloat brightness) {
45 | brightness_ = brightness;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_brightness_filter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/23.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_BRIGHTNESS_FILTER_H
6 | #define ULTRAGPUIMAGE_UGI_BRIGHTNESS_FILTER_H
7 |
8 | #include "ugi_filter.h"
9 |
10 | namespace Ugi {
11 |
12 | class BrightnessFilter : public Filter {
13 | public:
14 | BrightnessFilter();
15 |
16 | int Init(int32_t width, int32_t height) override;
17 |
18 | void PreDraw() override;
19 |
20 | void SetBrightness(GLfloat brightness);
21 |
22 | private:
23 | GLint brightness_loc_;
24 | GLfloat brightness_;
25 | };
26 |
27 | }
28 |
29 | #endif //ULTRAGPUIMAGE_UGI_BRIGHTNESS_FILTER_H
30 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_color_invert_filter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #include "ugi_color_invert_filter.h"
6 |
7 | namespace Ugi {
8 |
9 | static const GLchar* kFragmentShader
10 | = "#version " UGI_GLSL_VERSION "\n"
11 | "#ifdef GL_ES\n"
12 | "precision mediump float;\n"
13 | "#endif\n"
14 | "in vec2 texCoords;\n"
15 | "uniform sampler2D tex;\n"
16 | "out vec4 fragColor;\n"
17 | "void main() {\n"
18 | " vec4 color = texture(tex, texCoords);\n"
19 | " fragColor = vec4((1.0 - color.rgb), color.a);\n"
20 | "}\n";
21 |
22 | ColorInvertFilter::ColorInvertFilter() : Filter(kDirectVertexShader, kFragmentShader) {}
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_color_invert_filter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_COLOR_INVERT_FILTER_H
6 | #define ULTRAGPUIMAGE_UGI_COLOR_INVERT_FILTER_H
7 |
8 | #include "ugi_filter.h"
9 |
10 | namespace Ugi {
11 |
12 | class ColorInvertFilter : public Filter {
13 | public:
14 | ColorInvertFilter();
15 | };
16 |
17 | }
18 |
19 | #endif //ULTRAGPUIMAGE_UGI_COLOR_INVERT_FILTER_H
20 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_filter_group.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #include "ugi_gl_utils.h"
6 | #include "ugi_filter_group.h"
7 |
8 | #include "ugi_transformation.h"
9 | #include "ugi_gl_utils.h"
10 |
11 | namespace Ugi {
12 |
13 | FilterGroup::FilterGroup() : Filter("", ""),
14 | fbo_num_(0), fbo_(nullptr), fbo_textures_(nullptr),
15 | initialized_(false), error_(false),
16 | output_width_(0), output_height_(0) {}
17 |
18 | void FilterGroup::AddFilter(Filter* filter) {
19 | filters_.push_back(std::shared_ptr(filter));
20 | flattenFilters();
21 | }
22 |
23 | int FilterGroup::Init(int32_t output_width, int32_t output_height) {
24 | if (initialized_ || error_) {
25 | return 0;
26 | }
27 |
28 | for (auto& filter : flat_filters_) {
29 | int result = filter->Init(output_width, output_height);
30 | if (result != 0) {
31 | error_ = true;
32 | return result;
33 | }
34 | }
35 |
36 | if (!flat_filters_.empty()
37 | && (output_width_ != output_width || output_height_ != output_height)) {
38 | if (fbo_) {
39 | destroyFbo();
40 | }
41 |
42 | output_width_ = output_width;
43 | output_height_ = output_height;
44 |
45 | fbo_num_ = static_cast(flat_filters_.size() - 1);
46 | fbo_ = new GLuint[fbo_num_];
47 | fbo_textures_ = new GLuint[fbo_num_];
48 | glGenFramebuffers(fbo_num_, fbo_);
49 | glGenTextures(fbo_num_, fbo_textures_);
50 |
51 | for (int32_t i = 0; i < fbo_num_; i++) {
52 | glBindTexture(GL_TEXTURE_2D, fbo_textures_[i]);
53 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, output_width_, output_height_, 0, GL_RGBA,
54 | GL_UNSIGNED_BYTE, nullptr);
55 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
56 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
57 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
58 | glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
59 |
60 | glBindFramebuffer(GL_FRAMEBUFFER, fbo_[i]);
61 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
62 | fbo_textures_[i], 0);
63 |
64 | glBindTexture(GL_TEXTURE_2D, 0);
65 | glBindFramebuffer(GL_FRAMEBUFFER, 0);
66 | }
67 | }
68 |
69 | GLuint buffers[] = {0, 0, 0};
70 | glGenVertexArrays(1, buffers);
71 | glGenBuffers(2, buffers + 1);
72 | vao_fc_ = buffers[0];
73 | vbo_fc_ = buffers[1];
74 | ebo_fc_ = buffers[2];
75 |
76 | Transformation::Size size(output_width_, output_height_);
77 | Transformation transformation(size, size);
78 | transformation.UpdateScaleType(Transformation::kScaleTypeFitXY);
79 | transformation.Resolve(vertex_attributes_fc_);
80 |
81 | GlUtils::BindBuffers(vertex_attributes_fc_, vao_fc_, vbo_fc_, ebo_fc_);
82 |
83 | initialized_ = true;
84 | return 0;
85 | }
86 |
87 | int FilterGroup::Apply(TextureType type, GLuint texture_id, GLuint vao) {
88 | if (error_) {
89 | return -1;
90 | }
91 | if (!fbo_) {
92 | return -2;
93 | }
94 |
95 | GLuint prev_texture_id = texture_id;
96 | for (size_t i = 0; i < flat_filters_.size(); i++) {
97 | bool notLast = i < flat_filters_.size() - 1;
98 | auto& filter = flat_filters_[i];
99 | if (notLast) {
100 | glBindFramebuffer(GL_FRAMEBUFFER, fbo_[i]);
101 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
102 | glViewport(0, 0, output_width_, output_height_);
103 | }
104 |
105 | if (i == 0) {
106 | filter->Apply(type, prev_texture_id, vao);
107 | } else {
108 | filter->Apply(kTextureTypeRgb, prev_texture_id, vao_fc_);
109 | }
110 |
111 | if (notLast) {
112 | glBindFramebuffer(GL_FRAMEBUFFER, 0);
113 | prev_texture_id = fbo_textures_[i];
114 | }
115 | }
116 |
117 | return 0;
118 | }
119 |
120 | int FilterGroup::Destroy() {
121 | for (auto& filter : flat_filters_) {
122 | filter->Destroy();
123 | }
124 |
125 | destroyFbo();
126 |
127 | GLuint buffers[] = {vao_fc_, vbo_fc_, ebo_fc_};
128 | glDeleteVertexArrays(1, buffers);
129 | glDeleteBuffers(2, buffers + 1);
130 |
131 | return 0;
132 | }
133 |
134 | bool FilterGroup::IsGroup() {
135 | return true;
136 | }
137 |
138 | void FilterGroup::flattenFilters() {
139 | flat_filters_.clear();
140 |
141 | for (auto& filter : filters_) {
142 | if (filter->IsGroup()) {
143 | FilterGroup* group = reinterpret_cast(filter.get());
144 | group->flattenFilters();
145 | flat_filters_.insert(flat_filters_.end(),
146 | group->flat_filters_.begin(), group->flat_filters_.end());
147 | } else {
148 | flat_filters_.push_back(filter);
149 | }
150 | }
151 | }
152 |
153 | void FilterGroup::destroyFbo() {
154 | if (fbo_textures_) {
155 | glDeleteTextures(fbo_num_, fbo_textures_);
156 | delete fbo_textures_;
157 | fbo_textures_ = nullptr;
158 | }
159 | if (fbo_) {
160 | glDeleteFramebuffers(fbo_num_, fbo_);
161 | delete[] fbo_;
162 | fbo_ = nullptr;
163 | }
164 | fbo_num_ = 0;
165 | }
166 |
167 | }
168 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_filter_group.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_FILTER_GROUP_H
6 | #define ULTRAGPUIMAGE_UGI_FILTER_GROUP_H
7 |
8 | #include
9 | #include
10 |
11 | #include "ugi_filter.h"
12 |
13 | namespace Ugi {
14 |
15 | class FilterGroup : public Filter {
16 | public:
17 | FilterGroup();
18 |
19 | void AddFilter(Filter* filter);
20 |
21 | int Init(int32_t output_width, int32_t output_height) override;
22 |
23 | int Apply(TextureType type, GLuint texture_id, GLuint vao) override;
24 |
25 | int Destroy() override;
26 |
27 | bool IsGroup() override;
28 |
29 | private:
30 | void flattenFilters();
31 |
32 | void destroyFbo();
33 |
34 | std::vector> filters_;
35 | std::vector> flat_filters_;
36 |
37 | int32_t fbo_num_;
38 | GLuint* fbo_;
39 | GLuint* fbo_textures_;
40 |
41 | GLuint vao_fc_;
42 | GLuint vbo_fc_;
43 | GLuint ebo_fc_;
44 | GLfloat vertex_attributes_fc_[16];
45 |
46 | bool initialized_;
47 | bool error_;
48 |
49 | int32_t output_width_;
50 | int32_t output_height_;
51 | };
52 |
53 | }
54 |
55 | #endif //ULTRAGPUIMAGE_UGI_FILTER_GROUP_H
56 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_preprocess_filter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #include "ugi_preprocess_filter.h"
6 |
7 | namespace Ugi {
8 |
9 | #if defined(__ANDROID__)
10 | static const GLchar* kFragmentShaderOes
11 | = "#version " UGI_GLSL_VERSION "\n"
12 | "#extension GL_OES_EGL_image_external_essl3: require\n"
13 | "#ifdef GL_ES\n"
14 | "precision mediump float;\n"
15 | "#endif\n"
16 | "in vec2 texCoords;\n"
17 | "uniform samplerExternalOES tex;\n"
18 | "out vec4 fragColor;\n"
19 | "void main() {\n"
20 | " fragColor = texture(tex, texCoords);\n"
21 | "}\n";
22 | #endif
23 |
24 | int PreprocessFilter::Init(int32_t output_width, int32_t output_height) {
25 | int result = Filter::Init(output_width, output_height);
26 | if (result != 0) {
27 | return result;
28 | }
29 |
30 | #if defined(__ANDROID__)
31 | oes_program_ = CreateProgram(kDirectVertexShader, kFragmentShaderOes);
32 | if (oes_program_ == 0) {
33 | return -1;
34 | }
35 | #endif
36 | return 0;
37 | }
38 |
39 | int PreprocessFilter::Apply(TextureType type, GLuint texture_id, GLuint vao) {
40 | switch (type) {
41 | #if defined(__ANDROID__)
42 | case kTextureTypeOes:
43 | return DoApply(oes_program_, type, texture_id, vao);
44 | #endif
45 | case kTextureTypeRgb:
46 | default:
47 | return DoApply(program_, type, texture_id, vao);
48 | }
49 | }
50 |
51 | int PreprocessFilter::Destroy() {
52 | #if defined(__ANDROID__)
53 | if (oes_program_ != 0) {
54 | glDeleteProgram(oes_program_);
55 | oes_program_ = 0;
56 | }
57 | #endif
58 |
59 | return Filter::Destroy();
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/filters/ugi_preprocess_filter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_PREPROCESS_FILTER_H
6 | #define ULTRAGPUIMAGE_UGI_PREPROCESS_FILTER_H
7 |
8 | #include "ugi_filter.h"
9 |
10 | namespace Ugi {
11 |
12 | class PreprocessFilter : public Filter {
13 | public:
14 | int Init(int32_t output_width, int32_t output_height) override;
15 |
16 | int Apply(TextureType type, GLuint texture_id, GLuint vao) override;
17 |
18 | int Destroy() override;
19 |
20 | private:
21 | #if defined(__ANDROID__)
22 | GLuint oes_program_;
23 | #endif
24 | };
25 |
26 | }
27 |
28 | #endif //ULTRAGPUIMAGE_UGI_PREPROCESS_FILTER_H
29 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_filter.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #include
6 |
7 | #include "ugi_filter.h"
8 | #include "ugi_logging.h"
9 |
10 | namespace Ugi {
11 |
12 | static constexpr GLint kUgiTextureEnum = GL_TEXTURE0;
13 |
14 | const GLchar* Filter::kDirectVertexShader
15 | = "#version " UGI_GLSL_VERSION "\n"
16 | "layout(location = 0) in vec2 aVertCoords;\n"
17 | "layout(location = 1) in vec2 aTexCoords;\n"
18 | "out vec2 texCoords;\n"
19 | "void main() {\n"
20 | " gl_Position = vec4(aVertCoords, 0.0, 1.0);\n"
21 | " texCoords = aTexCoords;\n"
22 | "}\n";
23 | const GLchar* Filter::kDirectFragmentShader
24 | = "#version " UGI_GLSL_VERSION "\n"
25 | "#ifdef GL_ES\n"
26 | "precision mediump float;\n"
27 | "#endif\n"
28 | "in vec2 texCoords;\n"
29 | "uniform sampler2D tex;\n"
30 | "out vec4 fragColor;\n"
31 | "void main() {\n"
32 | " fragColor = texture(tex, texCoords);\n"
33 | "}\n";
34 |
35 | Filter::Filter() : Filter(kDirectVertexShader, kDirectFragmentShader) {
36 | }
37 |
38 | Filter::Filter(const GLchar* vertex_shader, const GLchar* fragment_shader)
39 | : vertex_shader_(vertex_shader),
40 | fragment_shader_(fragment_shader),
41 | program_(0) {
42 | }
43 |
44 | Filter::~Filter() {
45 | }
46 |
47 | int Filter::Init(int32_t output_width, int32_t output_height) {
48 | if (program_ != 0 || strlen(vertex_shader_) == 0 || strlen(fragment_shader_) == 0) {
49 | return 0;
50 | }
51 |
52 | program_ = CreateProgram(vertex_shader_, fragment_shader_);
53 |
54 | return 0;
55 | }
56 |
57 | int Filter::Apply(TextureType type, GLuint texture_id, GLuint vao) {
58 | return DoApply(program_, type, texture_id, vao);
59 | }
60 |
61 | int Filter::Destroy() {
62 | if (program_ == 0) {
63 | return 0;
64 | }
65 |
66 | glDeleteProgram(program_);
67 | program_ = 0;
68 |
69 | return 0;
70 | }
71 |
72 | void Filter::PreDraw() {
73 | }
74 |
75 | int Filter::DoApply(GLuint program, TextureType type, GLuint texture_id, GLuint vao) {
76 | if (program_ == 0) {
77 | return -1;
78 | }
79 |
80 | glClear(GL_COLOR_BUFFER_BIT);
81 |
82 | glUseProgram(program);
83 |
84 | glActiveTexture(kUgiTextureEnum);
85 | glBindTexture(textureType(type), texture_id);
86 |
87 | glBindVertexArray(vao);
88 |
89 | PreDraw();
90 |
91 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
92 |
93 | return 0;
94 | }
95 |
96 | GLenum Filter::textureType(TextureType type) {
97 | switch (type) {
98 | #if defined(__ANDROID__)
99 | case kTextureTypeOes:
100 | return GL_TEXTURE_EXTERNAL_OES;
101 | #endif
102 | case kTextureTypeRgb:
103 | default:
104 | return GL_TEXTURE_2D;
105 | }
106 | }
107 |
108 | GLuint Filter::CreateProgram(const GLchar* vertex_shader_src, const GLchar* fragment_shader_src) {
109 | GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
110 | glShaderSource(vertex_shader, 1, &vertex_shader_src, nullptr);
111 | glCompileShader(vertex_shader);
112 |
113 | int success;
114 | char infoLog[512];
115 | glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success);
116 | if (!success) {
117 | glGetShaderInfoLog(vertex_shader, 512, NULL, infoLog);
118 | ugi_log(UGI_LOG_LEVEL_ERROR, "compile vertex shader error: %s", infoLog);
119 | return 0;
120 | }
121 |
122 | GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
123 | glShaderSource(fragment_shader, 1, &fragment_shader_src, nullptr);
124 | glCompileShader(fragment_shader);
125 | glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success);
126 | if (!success) {
127 | glGetShaderInfoLog(fragment_shader, 512, NULL, infoLog);
128 | ugi_log(UGI_LOG_LEVEL_ERROR, "compile fragment shader error: %s", infoLog);
129 | return 0;
130 | }
131 |
132 | GLuint program = glCreateProgram();
133 | glAttachShader(program, vertex_shader);
134 | glAttachShader(program, fragment_shader);
135 | glLinkProgram(program);
136 | glGetProgramiv(program, GL_LINK_STATUS, &success);
137 | if (!success) {
138 | glGetProgramInfoLog(program, 512, NULL, infoLog);
139 | ugi_log(UGI_LOG_LEVEL_ERROR, "link program error: %s", infoLog);
140 | return 0;
141 | }
142 |
143 | glDetachShader(program, vertex_shader);
144 | glDeleteShader(vertex_shader);
145 | glDetachShader(program, fragment_shader);
146 | glDeleteShader(fragment_shader);
147 |
148 | GLint tex_loc = glGetUniformLocation(program, "tex");
149 |
150 | glUseProgram(program);
151 | glUniform1i(tex_loc, kUgiTextureEnum - GL_TEXTURE0);
152 |
153 | return program;
154 | }
155 |
156 | bool Filter::IsGroup() {
157 | return false;
158 | }
159 |
160 | }
161 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_filter.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_FILTER_H
6 | #define ULTRAGPUIMAGE_UGI_FILTER_H
7 |
8 | #include "ugi_gl.h"
9 | #include "ugi_transformation.h"
10 |
11 | namespace Ugi {
12 |
13 | #define UGI_GLSL_VERSION "300 es"
14 |
15 | enum TextureType {
16 | kTextureTypeRgb,
17 | #if defined(__ANDROID__)
18 | kTextureTypeOes,
19 | #endif
20 | kTextureTypeMax,
21 | };
22 |
23 | enum FilterType {
24 | kFilterGroup = 0,
25 | kFilterPreprocess = 1,
26 | kFilterColorInvert = 2,
27 | kFilterBrightness = 3,
28 | };
29 |
30 | class Filter {
31 | public:
32 | Filter();
33 |
34 | virtual ~Filter();
35 |
36 | Filter(const GLchar* vertex_shader, const GLchar* fragment_shader);
37 |
38 | static const GLchar* kDirectVertexShader;
39 | static const GLchar* kDirectFragmentShader;
40 |
41 | virtual int Init(int32_t output_width, int32_t output_height);
42 |
43 | virtual int Apply(TextureType type, GLuint texture_id, GLuint vao);
44 |
45 | virtual int Destroy();
46 |
47 | virtual bool IsGroup();
48 |
49 | protected:
50 | GLuint CreateProgram(const GLchar* vertex_shader, const GLchar* fragment_shader);
51 |
52 | virtual void PreDraw();
53 |
54 | int DoApply(GLuint program, TextureType type, GLuint texture_id, GLuint vao);
55 |
56 | GLuint program_;
57 |
58 | private:
59 | GLenum textureType(TextureType type);
60 |
61 | const GLchar* vertex_shader_;
62 | const GLchar* fragment_shader_;
63 | };
64 |
65 | }
66 |
67 | #endif //ULTRAGPUIMAGE_UGI_FILTER_H
68 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_gl.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/17.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_GL_H
6 | #define ULTRAGPUIMAGE_UGI_GL_H
7 |
8 | #if defined(__ANDROID__)
9 |
10 | #include
11 | #include // https://stackoverflow.com/q/31003863/3077508
12 |
13 | #elif defined(__APPLE__)
14 |
15 | #include
16 | #include
17 |
18 | #else
19 | #error Unknown platform
20 | #endif
21 |
22 | #endif //ULTRAGPUIMAGE_UGI_GL_H
23 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_gl_utils.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #include "ugi_gl_utils.h"
6 |
7 | namespace Ugi {
8 |
9 | static constexpr GLuint kVertexIndices[] = {
10 | 0, 1, 3, 1, 2, 3,
11 | };
12 |
13 | void GlUtils::BindBuffers(GLfloat* vertex_attributes, GLuint vao, GLuint vbo, GLuint ebo) {
14 | glBindVertexArray(vao);
15 | glBindBuffer(GL_ARRAY_BUFFER, vbo);
16 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, vertex_attributes, GL_STATIC_DRAW);
17 |
18 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
19 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(kVertexIndices), kVertexIndices,
20 | GL_STATIC_DRAW);
21 |
22 | glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
23 | glEnableVertexAttribArray(0);
24 |
25 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
26 | reinterpret_cast(2 * sizeof(GLfloat)));
27 | glEnableVertexAttribArray(1);
28 |
29 | glBindVertexArray(0);
30 | glBindBuffer(GL_ARRAY_BUFFER, 0);
31 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_gl_utils.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/22.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_GL_UTILS_H
6 | #define ULTRAGPUIMAGE_UGI_GL_UTILS_H
7 |
8 | #include "ugi_gl.h"
9 |
10 | namespace Ugi {
11 |
12 | class GlUtils {
13 |
14 | public:
15 |
16 | static void BindBuffers(GLfloat* vertex_attributes, GLuint vao, GLuint vbo, GLuint ebo);
17 |
18 | };
19 |
20 | }
21 |
22 | #endif //ULTRAGPUIMAGE_UGI_GL_UTILS_H
23 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_logging.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/21.
3 | //
4 |
5 | #include
6 | #include
7 |
8 | #include "ugi_logging.h"
9 |
10 | extern "C" {
11 |
12 | static ugi_log_func g_log_func = nullptr;
13 |
14 | void ugi_set_log_func(ugi_log_func log_func) {
15 | g_log_func = log_func;
16 | }
17 |
18 | void ugi_log(int level, const char* fmt, ...) {
19 | if (g_log_func) {
20 | char buf[1024];
21 |
22 | va_list args;
23 | va_start(args, fmt);
24 | vsnprintf(buf, sizeof(buf), fmt, args);
25 | va_end(args);
26 |
27 | g_log_func(level, buf);
28 | }
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_logging.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/21.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_LOGGING_H
6 | #define ULTRAGPUIMAGE_UGI_LOGGING_H
7 |
8 | #if __cplusplus
9 | extern "C" {
10 | #endif
11 |
12 | #define UGI_LOG_LEVEL_INFO 3
13 | #define UGI_LOG_LEVEL_ERROR 4
14 |
15 | typedef void (* ugi_log_func)(int level, const char* log);
16 | void ugi_set_log_func(ugi_log_func log_func);
17 |
18 | void ugi_log(int level, const char* fmt, ...);
19 |
20 | #if __cplusplus
21 | }
22 | #endif
23 |
24 | #endif //ULTRAGPUIMAGE_UGI_LOGGING_H
25 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_renderer.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/17.
3 | //
4 |
5 | #include "ugi_renderer.h"
6 |
7 | #include "ugi_logging.h"
8 | #include "ugi_gl_utils.h"
9 |
10 | namespace Ugi {
11 |
12 | Renderer::Renderer(Transformation transformation) : vao_(0), vbo_(0), ebo_(0),
13 | transformation_(transformation),
14 | filter_(nullptr) {
15 | }
16 |
17 | Renderer::~Renderer() {
18 | }
19 |
20 | void Renderer::OnSurfaceCreated() {
21 | GLuint buffers[] = {0, 0, 0};
22 | glGenVertexArrays(1, buffers);
23 | glGenBuffers(2, buffers + 1);
24 | vao_ = buffers[0];
25 | vbo_ = buffers[1];
26 | ebo_ = buffers[2];
27 |
28 | bindBuffers();
29 |
30 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
31 | }
32 |
33 | void Renderer::OnSurfaceDestroyed() {
34 | if (filter_) {
35 | filter_->Destroy();
36 | }
37 |
38 | GLuint buffers[] = {vao_, vbo_, ebo_};
39 | glDeleteVertexArrays(1, buffers);
40 | glDeleteBuffers(2, buffers + 1);
41 | }
42 |
43 | void Renderer::UpdateTransformation(Transformation transformation) {
44 | if (transformation_ != transformation) {
45 | ugi_log(UGI_LOG_LEVEL_INFO, "UpdateTransformation from %s to %s",
46 | transformation_.Describe(), transformation.Describe());
47 |
48 | transformation_ = transformation;
49 | bindBuffers();
50 | } else {
51 | ugi_log(UGI_LOG_LEVEL_INFO, "UpdateTransformation with same %s", transformation.Describe());
52 | }
53 | }
54 |
55 | void Renderer::SetFilter(Filter* filter) {
56 | filter_.reset(filter);
57 | }
58 |
59 | void Renderer::RenderTexture(TextureType type, GLuint texture_id) {
60 | if (!filter_
61 | || filter_->Init(transformation_.output_width(), transformation_.output_height()) != 0) {
62 | return;
63 | }
64 |
65 | filter_->Apply(type, texture_id, vao_);
66 | }
67 |
68 | void Renderer::bindBuffers() {
69 | glViewport(0, 0, transformation_.output_width(), transformation_.output_height());
70 | transformation_.Resolve(vertex_attributes_);
71 |
72 | GlUtils::BindBuffers(vertex_attributes_, vao_, vbo_, ebo_);
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_renderer.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/17.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_RENDERER_H
6 | #define ULTRAGPUIMAGE_UGI_RENDERER_H
7 |
8 | #include
9 | #include
10 |
11 | #include "ugi_gl.h"
12 | #include "ugi_transformation.h"
13 | #include "ugi_filter.h"
14 |
15 | namespace Ugi {
16 |
17 | class Renderer {
18 | public:
19 | Renderer(Transformation transformation);
20 |
21 | ~Renderer();
22 |
23 | void OnSurfaceCreated();
24 |
25 | void OnSurfaceDestroyed();
26 |
27 | void UpdateTransformation(Transformation transformation);
28 |
29 | void RenderTexture(TextureType type, GLuint texture_id);
30 |
31 | void SetFilter(Filter* filter);
32 |
33 | private:
34 | void bindBuffers();
35 |
36 | GLuint vao_;
37 | GLuint vbo_;
38 | GLuint ebo_;
39 |
40 | Transformation transformation_;
41 | GLfloat vertex_attributes_[16];
42 |
43 | std::unique_ptr filter_;
44 | };
45 |
46 | }
47 |
48 | #endif //ULTRAGPUIMAGE_UGI_RENDERER_H
49 |
--------------------------------------------------------------------------------
/UltraGpuImage/src/ugi_transformation.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by Piasy on 2018/12/19.
3 | //
4 |
5 | #ifndef ULTRAGPUIMAGE_UGI_TRANSFORMATION_H
6 | #define ULTRAGPUIMAGE_UGI_TRANSFORMATION_H
7 |
8 |
9 | #include
10 |
11 | #include "ugi_gl.h"
12 |
13 | namespace Ugi {
14 |
15 | class Transformation {
16 | public:
17 | enum Flip {
18 | kFlipNone = 0,
19 | kFlipHorizontal = 1,
20 | kFlipVertical = 2,
21 | kFlipHorizontalVertical = 3,
22 | };
23 |
24 | enum Rotation {
25 | kRotation_0 = 0,
26 | kRotation_90 = 90,
27 | kRotation_180 = 180,
28 | kRotation_270 = 270,
29 | };
30 |
31 | enum ScaleType {
32 | kScaleTypeFitXY = 0,
33 | kScaleTypeCenterCrop = 1,
34 | kScaleTypeCenterInside = 2,
35 | };
36 |
37 | static constexpr int32_t kCoordsScale = 10000;
38 |
39 | struct Rect {
40 | int32_t x;
41 | int32_t y;
42 | int32_t w;
43 | int32_t h;
44 |
45 | Rect(int32_t x, int32_t y, int32_t w, int32_t h);
46 |
47 | friend bool operator==(const Rect& lhs, const Rect& rhs);
48 |
49 | friend bool operator!=(const Rect& lhs, const Rect& rhs);
50 | };
51 |
52 | struct Size {
53 | int32_t w;
54 | int32_t h;
55 |
56 | Size(int32_t w, int32_t h);
57 |
58 | friend bool operator==(const Size& lhs, const Size& rhs);
59 |
60 | friend bool operator!=(const Size& lhs, const Size& rhs);
61 | };
62 |
63 | Transformation(Size input, Size output);
64 |
65 | void UpdateInput(Size input);
66 |
67 | void UpdateOutput(Size output);
68 |
69 | void UpdateCrop(Rect crop);
70 |
71 | void UpdateFlip(Flip flip);
72 |
73 | void UpdateRotation(Rotation rotation);
74 |
75 | void UpdateScaleType(ScaleType scale_type);
76 |
77 | void Resolve(GLfloat vertex_attributes[16]);
78 |
79 | const char* Describe();
80 |
81 | int32_t input_width();
82 |
83 | int32_t input_height();
84 |
85 | int32_t output_width();
86 |
87 | int32_t output_height();
88 |
89 | Rotation rotation();
90 |
91 | Flip flip();
92 |
93 | friend bool operator==(const Transformation& lhs, const Transformation& rhs);
94 |
95 | friend bool operator!=(const Transformation& lhs, const Transformation& rhs);
96 |
97 | private:
98 | void reset();
99 |
100 | void resolveCrop();
101 |
102 | void resolveFlip();
103 |
104 | void resolveRotate();
105 |
106 | void resolveScale();
107 |
108 | void swap(GLfloat coords[16], int index1, int index2);
109 |
110 | const char* flipName();
111 |
112 | const char* scale_type();
113 |
114 | Rect crop_;
115 | Size input_;
116 | Size output_;
117 | Rotation rotation_;
118 | Flip flip_;
119 | ScaleType scale_type_;
120 |
121 | GLfloat vertex_coords_[8];
122 | GLfloat texture_coords_[8];
123 | };
124 |
125 | }
126 |
127 | #endif //ULTRAGPUIMAGE_UGI_TRANSFORMATION_H
128 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 |
5 | repositories {
6 | google()
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:3.2.1'
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | google()
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
25 | ext {
26 | androidMinSdkVersion = 19
27 | androidTargetSdkVersion = 28
28 | androidCompileSdkVersion = 28
29 |
30 | releaseVersionCode = 1
31 | releaseVersionName = "1.0.0"
32 | }
33 |
--------------------------------------------------------------------------------
/collect_src.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | REPO=/Users/piasy/src/media/webrtc_repo/webrtc_ios/src
4 |
5 | cp ${REPO}/sdk/android/src/java/org/webrtc/EglBase10.java \
6 | ${REPO}/sdk/android/src/java/org/webrtc/EglBase14.java \
7 | UltraGpuImage-Android/src/main/java/com/piasy/ugi/egl/ && \
8 | cp ${REPO}/sdk/android/api/org/webrtc/EglBase.java \
9 | UltraGpuImage-Android/src/main/java/com/piasy/ugi/egl/ && \
10 | cp ${REPO}/rtc_base/java/src/org/webrtc/ThreadUtils.java \
11 | UltraGpuImage-Android/src/main/java/com/piasy/ugi/utils/
12 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | android.useAndroidX=true
2 | android.enableJetifier=true
3 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/iOSExample/Podfile:
--------------------------------------------------------------------------------
1 | post_install do |installer|
2 | installer.pods_project.targets.each do |target|
3 | target.build_configurations.each do |configuration|
4 | configuration.build_settings['SWIFT_VERSION'] = "4"
5 | end
6 | end
7 | end
8 |
9 | # Uncomment the next line to define a global platform for your project
10 | platform :ios, '9.0'
11 |
12 | target 'iOSExample' do
13 | # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
14 | use_frameworks!
15 |
16 | pod 'SDAutoLayout', '~> 2.1.3'
17 | end
18 |
--------------------------------------------------------------------------------
/iOSExample/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SDAutoLayout (2.1.9)
3 |
4 | DEPENDENCIES:
5 | - SDAutoLayout (~> 2.1.3)
6 |
7 | SPEC REPOS:
8 | https://github.com/cocoapods/specs.git:
9 | - SDAutoLayout
10 |
11 | SPEC CHECKSUMS:
12 | SDAutoLayout: 6b6f4db0d009dfc46cef14ef710dbb164e86616c
13 |
14 | PODFILE CHECKSUM: 60d54eac161cb8d67bc604c4514557d9985e9bba
15 |
16 | COCOAPODS: 1.5.3
17 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/AppDelegate.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | @interface AppDelegate : UIResponder
31 |
32 | @property (strong, nonatomic) UIWindow *window;
33 |
34 |
35 | @end
36 |
37 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/AppDelegate.m:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "AppDelegate.h"
29 |
30 | @interface AppDelegate ()
31 |
32 | @end
33 |
34 | @implementation AppDelegate
35 |
36 |
37 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
38 | // Override point for customization after application launch.
39 | return YES;
40 | }
41 |
42 |
43 | - (void)applicationWillResignActive:(UIApplication *)application {
44 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
45 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
46 | }
47 |
48 |
49 | - (void)applicationDidEnterBackground:(UIApplication *)application {
50 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
51 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
52 | }
53 |
54 |
55 | - (void)applicationWillEnterForeground:(UIApplication *)application {
56 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
57 | }
58 |
59 |
60 | - (void)applicationDidBecomeActive:(UIApplication *)application {
61 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
62 | }
63 |
64 |
65 | - (void)applicationWillTerminate:(UIApplication *)application {
66 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
67 | }
68 |
69 |
70 | @end
71 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Assets.xcassets/awesomeface.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "awesomeface.png",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Assets.xcassets/awesomeface.imageset/awesomeface.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Piasy/UltraGpuImage/c402307b4bf6682c5476d87de8e07b3616e6547c/iOSExample/iOSExample/Assets.xcassets/awesomeface.imageset/awesomeface.png
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | UltraGpuImage
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | com.piasy.ugi.example
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 1.0
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/ViewController.h:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 |
30 | @interface ViewController : UIViewController
31 |
32 |
33 | @end
34 |
35 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/ViewController.m:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import "ViewController.h"
29 |
30 | #import
31 | #import
32 |
33 | @implementation ViewController {
34 | UgiRendererView* _rendererView;
35 | UgiTransformation* _transformation;
36 | }
37 |
38 | - (void)viewDidLoad {
39 | [super viewDidLoad];
40 | // Do any additional setup after loading the view, typically from a nib.
41 |
42 | _rendererView = [[UgiRendererView alloc] init];
43 | [self.view addSubview:_rendererView];
44 | _rendererView.sd_layout.widthRatioToView(self.view, 1)
45 | .heightRatioToView(self.view, 1);
46 |
47 | [_rendererView initialize:@"test" renderMode:kUgiRenderModePicture];
48 | _transformation = [_rendererView transformation];
49 |
50 | UgiFilterGroup* filterGroup = [[UgiFilterGroup alloc] init];
51 | [filterGroup addFilter:[[UgiPreprocessFilter alloc] init]];
52 | [_rendererView setFilter:filterGroup];
53 |
54 | [_rendererView renderPicture:[UIImage imageNamed:@"awesomeface"]];
55 | }
56 |
57 |
58 | @end
59 |
--------------------------------------------------------------------------------
/iOSExample/iOSExample/main.m:
--------------------------------------------------------------------------------
1 | //
2 | /*
3 | * The MIT License (MIT)
4 | *
5 | * Copyright (c) 2018 Piasy
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 | * SOFTWARE.
24 | */
25 | //
26 |
27 |
28 | #import
29 | #import "AppDelegate.h"
30 |
31 | int main(int argc, char * argv[]) {
32 | @autoreleasepool {
33 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/iOSExample/project.yml:
--------------------------------------------------------------------------------
1 | name: iOSExample
2 | targets:
3 | iOSExample:
4 | type: application
5 | platform: iOS
6 | deploymentTarget: "9.0"
7 | sources:
8 | - path: iOSExample
9 | dependencies:
10 | - framework: "$(PROJECT_DIR)/../libs/UltraGpuImage_iOS.framework"
11 | implicit: true
12 | settings:
13 | LIBRARY_SEARCH_PATHS: "$(inherited)"
14 | OTHER_LDFLAGS: "$(inherited)"
15 | FRAMEWORK_SEARCH_PATHS: "$(inherited) $(PROJECT_DIR)/../libs/"
16 | CLANG_WARN_DOCUMENTATION_COMMENTS: "NO"
17 | TARGETED_DEVICE_FAMILY: "1,2"
18 | ENABLE_BITCODE: "NO"
19 | ONLY_ACTIVE_ARCH: "NO"
20 | VALID_ARCHS: "arm64"
21 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':AndroidExample', ':UltraGpuImage-Android'
2 |
--------------------------------------------------------------------------------
/setup_xcode_project.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -rf UltraGpuImage/UltraGpuImage.xcodeproj \
4 | UltraGpuImage-iOS/UltraGpuImage-iOS.xcodeproj \
5 | iOSExample/iOSExample.xcodeproj \
6 | iOSExample/iOSExample.xcworkspace && \
7 | cd UltraGpuImage && xcodegen && cd .. && \
8 | cd UltraGpuImage-iOS && xcodegen && cd .. && \
9 | cd iOSExample && xcodegen && pod install && cd .. && \
10 | rm -rf iOSExample/iOSExample.xcworkspace
11 |
--------------------------------------------------------------------------------