diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 000000000..e9f3a3a21
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,6 @@
+{
+ "files.associations": {
+ "chrono": "cpp",
+ "ios": "cpp"
+ }
+}
\ No newline at end of file
diff --git a/mediapipe/modules/render_queue/BUILD b/mediapipe/modules/render_queue/BUILD
new file mode 100644
index 000000000..bff9a9b79
--- /dev/null
+++ b/mediapipe/modules/render_queue/BUILD
@@ -0,0 +1,86 @@
+load("@build_bazel_rules_apple//apple:ios.bzl", "ios_framework")
+
+cc_library(
+ name = "ios_olarender",
+ srcs = [
+ "util.cpp",
+ "image_queue.cpp",
+ "image.cpp",
+ "OlaRender.cpp",
+ "OlaRenderIMP.cpp",
+ ],
+ hdrs = [
+ "util.h",
+ "macros.h",
+ "image_queue.h",
+ "image.h",
+ "LockFreeQueue.h",
+ "OlaRender.h",
+ "OlaRenderIMP.h",
+ ],
+ # Use -Dverbose=-1 to turn off zlib's trace logging. (#3280)
+ linkstatic = True,
+ includes = ["."],
+ visibility = ["//visibility:public"],
+ deps = [
+ "//mediapipe/modules/render_queue/math:math",
+ ],
+ copts = select({
+ "//mediapipe:apple": [
+ "-x objective-c++",
+ "-fobjc-arc", # enable reference-counting
+ ],
+ "//conditions:default": [],
+ }),
+ alwayslink = True,
+)
+
+
+
+objc_library(
+ name = "OlaRenderLibrary",
+ visibility = ["//visibility:public"],
+ deps = [
+ "//mediapipe/modules/render_queue:ios_olarender",
+ ],
+ copts = select({
+ "//mediapipe:apple": [
+ "-x objective-c++",
+ "-fobjc-arc", # enable reference-counting
+ ],
+ "//conditions:default": [],
+ }),
+ sdk_frameworks = [
+ "AVFoundation",
+ "CoreGraphics",
+ "CoreMedia",
+ "OpenGLES",
+ "CoreVideo",
+ "IOSurface",
+ "Foundation",
+ "UIKit",
+ ],
+ alwayslink = True,
+)
+
+
+ios_framework(
+ name = "OlaRenderFramework",
+ hdrs = [
+ "image.h",
+ "image_queue.h",
+ "LockFreeQueue.h",
+ "util.h",
+ "macros.h",
+ "OlaRender.h",
+ "OlaRenderIMP.h",
+ ],
+ # alwayslink=True,
+ infoplists = ["Info.plist"],
+ bundle_id = "com.ola.dartrenderplugin",
+ families = ["iphone", "ipad"],
+ minimum_os_version = "10.0",
+ deps = [
+ "//mediapipe/modules/render_queue:OlaRenderLibrary",
+ ],
+)
diff --git a/mediapipe/modules/render_queue/Info.plist b/mediapipe/modules/render_queue/Info.plist
new file mode 100644
index 000000000..8208eaf0f
--- /dev/null
+++ b/mediapipe/modules/render_queue/Info.plist
@@ -0,0 +1,22 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1.0
+
+
diff --git a/mediapipe/modules/render_queue/LockFreeQueue.h b/mediapipe/modules/render_queue/LockFreeQueue.h
new file mode 100644
index 000000000..ef30eeba8
--- /dev/null
+++ b/mediapipe/modules/render_queue/LockFreeQueue.h
@@ -0,0 +1,122 @@
+//
+// Created by Felix Wang on 2022/7/7.
+//
+
+
+#pragma once
+
+#include
+
+#ifdef ANDROID
+
+#include
+
+#define TAG "LockFreeQueue" // 这个是自定义的LOG的标识
+#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__) // 定义LOGI类型
+#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__) // 定义LOGE类型
+#else
+#define LOGI(...) fprintf(stdout, __VA_ARGS__)
+#define LOGE(...) fprintf(stderr, __VA_ARGS__)
+#endif
+
+template
+class LockFreeQueue {
+public:
+ LockFreeQueue(size_t capacity) {
+ _capacityMask = capacity - 1;
+ for (size_t i = 1; i <= sizeof(void *) * 4; i <<= 1)
+ _capacityMask |= _capacityMask >> i;
+ _capacity = _capacityMask + 1;
+
+ _queue = (Node * )
+ new char[sizeof(Node) * _capacity];
+ for (size_t i = 0; i < _capacity; ++i) {
+ _queue[i].tail.store(i, std::memory_order_relaxed);
+ _queue[i].head.store(-1, std::memory_order_relaxed);
+ }
+
+ _tail.store(0, std::memory_order_relaxed);
+ _head.store(0, std::memory_order_relaxed);
+ }
+
+ ~LockFreeQueue() {
+ rawRelease();
+ }
+
+ void releaseNode(T &data) {
+ LOGE("~~~~~~~~~~releaseNode data: %ld", reinterpret_cast(data.data));
+ if (data.data)
+ free(data.data);
+ }
+
+ void rawRelease() {
+ size_t head = _head.load(std::memory_order_acquire);
+ for (size_t i = head; i != _tail; ++i)
+ (&_queue[i & _capacityMask].data)->~T();
+
+ delete[] (char *) _queue;
+ }
+
+ size_t rawCapacity() const { return _capacity; }
+
+ size_t rawSize() const {
+ size_t head = _head.load(std::memory_order_acquire);
+ return _tail.load(std::memory_order_relaxed) - head;
+ }
+
+ bool rawPush(const T &data) {
+ Node *node;
+ size_t tail = _tail.load(std::memory_order_relaxed);
+ for (;;) {
+ node = &_queue[tail & _capacityMask];
+ if (node->tail.load(std::memory_order_relaxed) != tail)
+ return false;
+ if ((_tail.compare_exchange_weak(tail, tail + 1, std::memory_order_relaxed)))
+ break;
+ }
+ new(&node->data)T(data);
+ LOGE("~~~~~~~~~~rawPush data: %ld", reinterpret_cast(node->data.data));
+ node->head.store(tail, std::memory_order_release);
+ return true;
+ }
+
+ bool rawPop(T &result, bool exportFlag) {
+ LOGE("~~~~~~~~~~33");
+ Node *node;
+ size_t head = _head.load(std::memory_order_acquire);
+ for (;;) {
+ node = &_queue[head & _capacityMask];
+ if (node->data.len == 0) {
+ LOGE("~~~~~~~~~~33 len == 0 ");
+ continue;
+ } else {
+ LOGE("~~~~~~~~~~33 node->data.len == %d ", node->data.len);
+ }
+ if (node->head.load(std::memory_order_relaxed) != head) {
+ LOGE("~~~~~~~~~~33 return false ");
+ return false;
+ }
+ if (_head.compare_exchange_weak(head, head + 1, std::memory_order_relaxed))
+ break;
+ }
+ result = node->data;
+// if (() > 1)
+// (&node->data)->~T();
+ node->tail.store(head + _capacity, std::memory_order_release);
+ return true;
+ }
+
+private:
+ struct Node {
+ T data;
+ std::atomic tail;
+ std::atomic head;
+ };
+
+private:
+ size_t _capacityMask;
+ Node *_queue;
+ size_t _capacity;
+ std::atomic _tail;
+ std::atomic _head;
+};
diff --git a/mediapipe/modules/render_queue/OlaRender.cpp b/mediapipe/modules/render_queue/OlaRender.cpp
new file mode 100644
index 000000000..843a74839
--- /dev/null
+++ b/mediapipe/modules/render_queue/OlaRender.cpp
@@ -0,0 +1,39 @@
+//
+// OlaRender.cpp
+// OlaRender
+//
+// Created by 王韧竹 on 2022/6/17.
+//
+
+#include "OlaRender.h"
+#if USE_OLARENDER
+#include
+#include
+#endif
+#include "OlaRenderIMP.h"
+
+
+
+NS_OLA_BEGIN
+
+ OlaRender::~OlaRender() {
+
+ }
+
+ OlaRender::OlaRender() {
+
+ }
+
+#if USE_OLARENDER
+ OlaRender* OlaRender::create(void *env, void *context) {
+ return nullptr;
+}
+#endif
+
+ OlaRender* OlaRender::create() {
+ OLARenderIMP *instance = new OLARenderIMP();
+ return instance;
+ }
+
+
+NS_OLA_END
diff --git a/mediapipe/modules/render_queue/OlaRender.h b/mediapipe/modules/render_queue/OlaRender.h
new file mode 100644
index 000000000..f3adb8fe9
--- /dev/null
+++ b/mediapipe/modules/render_queue/OlaRender.h
@@ -0,0 +1,94 @@
+//
+// OlaRender.hpp
+// OlaRender
+//
+// Created by 王韧竹 on 2022/6/17.
+//
+
+#ifndef OlaRender_hpp
+#define OlaRender_hpp
+
+#define USE_OLARENDER 0
+// 是否开启多上下文渲染
+#define USE_MULTICONTEXT 0
+// 是否直接覆盖srcTexture
+#define USE_TEXImage2D 0
+// 是否要直接渲染到srcTexture上
+#define USE_RENDER_TO_SRCTEXTURE 0
+// 结束后是否需要还原fbo
+#define USE_RESTORE_FBO 0
+// 每次渲染结束之后重新创建
+#define USE_NEED_RECREATE 0
+
+#include
+#include "macros.h"
+
+#if USE_OLARENDER
+#include
+#if PLATFORM == PLATFORM_IOS
+#include "OLARenderView.h"
+#endif
+#endif
+
+#if PLATFORM == PLATFORM_IOS
+
+#import
+#import
+#elif PLATFORM == PLATFORM_ANDROID
+
+#include
+#include
+
+#endif
+
+
+NS_OLA_BEGIN
+
+ typedef struct {
+ int width;
+ int height;
+ int textureId;
+ int ioSurfaceId; // iOS 专属
+ int64_t frameTime;
+ } TextureInfo;
+
+ class Source;
+
+ class OlaRender {
+
+ public:
+ ~OlaRender();
+
+ OlaRender();
+
+#if USE_OLARENDER
+ // Android
+ static OlaRender* create(void *env, void *context);
+#endif
+
+ static OlaRender *create();
+
+
+ /// 加载测试图 初次使用或者release后需要重新Load
+ virtual int loadGraph() = 0;
+
+ virtual int release() = 0;
+
+ virtual TextureInfo render(TextureInfo inputTexture, bool exportFlag) = 0;
+
+#if USE_OLARENDER
+
+#if PLATFORM == PLATFORM_IOS
+ virtual void setDisplayView(OLARenderView *target) = 0;
+#else
+ virtual void setDisplayView(TargetView *target) = 0;
+#endif
+
+ virtual void removeRenderTarget() = 0;
+
+ virtual Source* getTerminalSource() = 0;
+#endif
+ };
+NS_OLA_END
+
+#endif /* OlaRender_hpp */
diff --git a/mediapipe/modules/render_queue/OlaRenderIMP.cpp b/mediapipe/modules/render_queue/OlaRenderIMP.cpp
new file mode 100644
index 000000000..b46dafd33
--- /dev/null
+++ b/mediapipe/modules/render_queue/OlaRenderIMP.cpp
@@ -0,0 +1,603 @@
+//
+// OlaRenderIMP.cpp
+// OlaRender
+//
+// Created by 王韧竹 on 2022/6/20.
+//
+
+
+#include "OlaRenderIMP.h"
+#include "image_queue.h"
+
+#if USE_OLARENDER
+#include
+#endif
+
+#if USE_OLARENDER
+#else
+const std::string TransformFragmentShaderString = SHADER_STRING
+ (
+ uniform
+sampler2D colorMap;
+varying highp
+vec2 vTexCoord;
+
+void main() {
+ highp
+ vec4 textureColor;
+ highp
+ vec2 uv = vTexCoord;
+ textureColor = texture2D(colorMap, uv);
+
+ gl_FragColor = vec4(textureColor.rgb, textureColor.a);
+// gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+
+);
+
+const std::string TransformVertexShaderString = SHADER_STRING
+ (
+ attribute
+vec4 position;
+attribute vec4
+texCoord;
+
+uniform mat4
+mvp;
+varying vec2
+vTexCoord;
+
+void main() {
+ gl_Position = mvp * position;
+ vTexCoord = texCoord.xy;
+}
+
+);
+
+const std::string VertexShaderString = SHADER_STRING
+ (
+ attribute
+vec4 position;
+attribute vec4
+texCoord;
+attribute vec4
+texCoord1;
+
+varying vec2
+vTexCoord;
+varying vec2
+vTexCoord1;
+
+void main() {
+ gl_Position = position;
+ vTexCoord = texCoord.xy;
+ vTexCoord1 = texCoord1.xy;
+}
+
+);
+
+const std::string FragmentShaderString = SHADER_STRING
+ (
+
+ varying
+highp vec2
+vTexCoord;
+varying highp
+vec2 vTexCoord1;
+uniform sampler2D
+colorMap;
+uniform sampler2D
+colorMap1;
+
+void main() {
+ lowp
+ vec4 textureColor = texture2D(colorMap, vTexCoord);
+ lowp
+ vec4 textureColor2 = texture2D(colorMap1, vTexCoord1);
+ gl_FragColor = vec4(textureColor2 + textureColor * (1.0 - textureColor2.a));
+}
+
+);
+#endif
+
+NS_OLA_BEGIN
+
+static GLfloat
+positionCoords[] = {
+-1.0f, -1.0f, 0.0f,
+1.0f, -1.0f, 0.0f,
+-1.0f, 1.0f, 0.0f,
+1.0f, 1.0f, 0.0f,
+};
+
+static GLfloat textureCoords[] = {
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+};
+
+static GLfloat textureCoords1[] = {
+ 0.0f, 1.0f,
+ 1.0f, 1.0f,
+ 0.0f, 0.0f,
+ 1.0f, 0.0f,
+};
+
+OLARenderIMP::OLARenderIMP() {
+
+}
+
+OLARenderIMP::~OLARenderIMP() {
+// imageData = nil;
+ ImageQueue::getInstance()->dispose();
+ _mvp_matrix.set_identity();
+}
+
+int OLARenderIMP::release() {
+#if USE_OLARENDER
+ if (_sobelFilter) {
+ _sobelFilter->removeAllTargets();
+ _sobelFilter->release();
+ _sobelFilter = nullptr;
+ }
+
+ if (_brightFilter) {
+ _brightFilter->removeAllTargets();
+ _brightFilter->release();
+ _brightFilter = nullptr;
+ }
+
+
+ if (_inputFramebuffer) {
+ _inputFramebuffer->setExternalTexture(-1);
+ _inputFramebuffer->release(false);
+ _inputFramebuffer = nullptr;
+ }
+ if (_bridgeFilter) {
+ _bridgeFilter->release();
+ _bridgeFilter = nullptr;
+ }
+
+ _terminalFilter = nullptr;
+ Filter::releaseVBOBuffers();
+ Context::getInstance()->getFramebufferCache()->purge();
+ Context::destroy();
+#else
+ if (_outputTexture > 0) {
+ glDeleteTextures(1, &_outputTexture);
+ _outputTexture = -1;
+ }
+
+ if (_outputFramebuffer > 0) {
+ glDeleteFramebuffers(1, &_outputFramebuffer);
+ _outputFramebuffer = -1;
+ }
+ if (_blendProgram > 0) {
+ glDeleteProgram(_blendProgram);
+ _blendProgram = -1;
+ }
+
+ if (_blendTexture > 0) {
+ glDeleteTextures(1, &_blendTexture);
+ _blendTexture = -1;
+ }
+
+ if (_blendFbo) {
+ glDeleteFramebuffers(1, &_blendFbo);
+ _blendFbo = -1;
+ }
+
+ if (_transformProgram) {
+ glDeleteProgram(_transformProgram);
+ _transformProgram = -1;
+ }
+
+ if (_transformTexture > 0) {
+ glDeleteTextures(1, &_transformTexture);
+ _transformTexture = -1;
+ }
+#endif
+ _isInit = false;
+ return 1;
+}
+
+int OLARenderIMP::loadGraph() {
+ if (!_isInit) {
+#if USE_OLARENDER
+#if USE_MULTICONTEXT
+ OlaDispatch::getSharedInstance()->runSync([&] {
+#endif
+ _brightFilter = BrightnessFilter::create();
+ _bridgeFilter = OlaBridgeTextureFilter::create(-1, -1, -1);
+ _sobelFilter = SobelEdgeDetectionFilter::create();
+ _sobelFilter->addTarget(_brightFilter)->addTarget(_bridgeFilter);
+
+ _terminalFilter = _bridgeFilter;
+
+#if USE_MULTICONTEXT
+ }, Context::ContextType::IOContext);
+#endif
+#else
+
+#endif
+ _isInit = true;
+
+ }
+ return 1;
+}
+
+TextureInfo OLARenderIMP::render(TextureInfo inputTexture, bool exportFlag) {
+#if USE_NEED_RECREATE
+ release();
+#endif
+ _renderWidth = inputTexture.width;
+ _renderHeight = inputTexture.height;
+ loadGraph();
+ TextureInfo outputTexture;
+ outputTexture.textureId = inputTexture.textureId;
+#if USE_OLARENDER
+#if USE_RESTORE_FBO
+ GLint curFbo;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &curFbo);
+#endif
+#if USE_MULTICONTEXT
+ GLsync sync;
+
+ OlaDispatch::getSharedInstance()->runSync([&] {
+#endif
+
+ if (_terminalFilter) {
+ if (_inputFramebuffer == nullptr || _inputFramebuffer->getTexture() != inputTexture.textureId) {
+ if (_inputFramebuffer) {
+ _inputFramebuffer->release(false);
+ _inputFramebuffer = nullptr;
+ }
+ _inputFramebuffer = new Framebuffer(inputTexture.width, inputTexture.height,
+ (GLuint)inputTexture.textureId, false);
+ _inputFramebuffer->setNoCacheFramebuffer();
+
+ }
+
+ _inputFramebuffer->setExternalTexture(inputTexture.textureId);
+ if (_bridgeFilter) {
+ //这是我们内部创建一个纹理id
+#if USE_RENDER_TO_SRCTEXTURE
+ _bridgeFilter->updateTargetTexture(inputTexture.textureId, inputTexture.width,
+ inputTexture.height, -1);
+#else
+ _bridgeFilter->updateTargetTexture(-1, inputTexture.width,
+ inputTexture.height, -1);
+#endif
+ }
+ /**
+ 下面这一段是测试代码验证引擎用
+ */
+ if (_brightFilter && _sobelFilter) {
+ _sobelFilter->unPrepear();
+ _sobelFilter->setInputFramebuffer(_inputFramebuffer);
+
+ _brightFilter->setBrightness(0.5);
+ if (_tempFactor > 1.0) {
+ _tempFactor = 0.0;
+ } else {
+ _tempFactor += 1.0 / 120.0;
+ }
+ _sobelFilter->setProperty("edgeStrength", _tempFactor);
+ _sobelFilter->update(inputTexture.frameTime); //测试渲染
+ }
+
+ auto *framebuffer = _terminalFilter->getFramebuffer();
+ if (framebuffer) {
+ outputTexture.textureId = framebuffer->getTexture();
+ outputTexture.width = framebuffer->getWidth();
+ outputTexture.height = framebuffer->getHeight();
+ outputTexture.ioSurfaceId = framebuffer->getSurfaceID();
+ }
+ }
+#if USE_MULTICONTEXT
+ sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ }, Context::ContextType::IOContext);
+ glWaitSync(sync, 0, GL_TIMEOUT_IGNORED);
+ glDeleteSync(sync);
+#endif
+
+#if USE_TEXImage2D
+ IOSurfaceRef surface = IOSurfaceLookup(outputTexture.ioSurfaceId);
+ IOSurfaceLock(surface, kIOSurfaceLockReadOnly, 0);
+ void *pixels = IOSurfaceGetBaseAddress(surface);
+
+ glBindTexture(GL_TEXTURE_2D, inputTexture.textureId);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, outputTexture.width, outputTexture.height, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
+ IOSurfaceUnlock(surface, kIOSurfaceLockReadOnly, 0);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ outputTexture.textureId = inputTexture.textureId;
+#endif
+
+#if USE_RESTORE_FBO
+ glBindFramebuffer(GL_FRAMEBUFFER, curFbo);
+#endif
+#else
+
+ _loadProgram();
+ _loadOutputTexture(inputTexture.width, inputTexture.height);
+
+ ImageInfo rs;
+
+ ImageQueue::getInstance()->pop(rs, exportFlag);
+ Log("OlaRender", "aaa");
+// while (exportFlag && rs.len == 0);
+ if (rs.len > 0) {
+ int width = rs.width;
+ int height = rs.height;
+
+ setCanvasPixels(width, height, rs.data, inputTexture.frameTime,
+ Vec4(rs.startX, rs.startY, rs.normalWidth, rs.normalHeight));
+ Log("OlaRender", "bbb");
+ }
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ glUseProgram(_blendProgram);
+ glBindFramebuffer(GL_FRAMEBUFFER, _outputFramebuffer);
+ glViewport(0, 0, inputTexture.width, inputTexture.height);
+ glClearColor(0, 0, 0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, inputTexture.textureId);
+ glUniform1i(_inputTextureSlot, 0);
+ glActiveTexture(GL_TEXTURE1);
+
+
+ CHECK_GL(glBindTexture(GL_TEXTURE_2D, _blendTexture));
+ CHECK_GL(glUniform1i(_inputTextureSlot1, 1));
+
+
+ glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, 0, 0, textureCoords);
+ glEnableVertexAttribArray(_texCoordSlot);
+
+ glVertexAttribPointer(_texCoordSlot1, 2, GL_FLOAT, 0, 0, textureCoords1);
+ glEnableVertexAttribArray(_texCoordSlot1);
+
+ glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, 0, 0, positionCoords);
+ glEnableVertexAttribArray(_positionSlot);
+
+ CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
+ outputTexture.textureId = _outputTexture;
+ if (rs.len > 0) {
+ ImageQueue::getInstance()->releaseNode(rs);
+ }
+#endif
+
+ return outputTexture;
+}
+
+void OLARenderIMP::setCanvasPixels(int width, int height, const void *pixels, int64_t frameTime,
+ Vec4 roi) {
+ if (_blendTexture != -1) {
+ if (_lastTransformSize != Vec2(width, height)) {
+ glDeleteTextures(1, &_transformTexture);
+ _transformTexture = -1;
+ }
+
+ if (_transformTexture == -1) {
+ glGenTextures(1, &_transformTexture);
+ glBindTexture(GL_TEXTURE_2D, _transformTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ CHECK_GL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ }
+
+ if (_transformTexture != -1 && _blendFbo != -1) {
+ // test
+ _setROI(roi);
+
+ glUseProgram(_transformProgram);
+ glBindFramebuffer(GL_FRAMEBUFFER, _blendFbo);
+ glViewport(0, 0, _renderWidth, _renderHeight);
+
+
+ glClearColor(0, 0, 0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_2D, _transformTexture);
+ Log("OLARender", "transformTexture :%d", _transformTexture);
+ glUniform1i(_transformTextureSlot, 0);
+ glUniformMatrix4fv(_transform_mvp, 1, GL_FALSE, (GLfloat * ) & _mvp_matrix);
+
+ glVertexAttribPointer(_transformTexCoordSlot, 2, GL_FLOAT, 0, 0, textureCoords);
+ glEnableVertexAttribArray(_transformTexCoordSlot);
+ glVertexAttribPointer(_transformPositionSlot, 3, GL_FLOAT, 0, 0, positionCoords);
+ glEnableVertexAttribArray(_transformPositionSlot);
+
+ CHECK_GL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
+ }
+ }
+}
+
+#if USE_OLARENDER
+#if PLATFORM == PLATFORM_IOS
+void OLARenderIMP::setDisplayView(OLARenderView *target) {
+
+#else
+void OLARenderIMP::setDisplayView(TargetView *target) {
+#endif
+ _targetView = target;
+ if (_terminalFilter) {
+ _terminalFilter->addTarget(target);
+ }
+}
+
+
+void OLARenderIMP::removeRenderTarget() {
+ _terminalFilter->removeAllTargets();
+}
+
+Source* OLARenderIMP::getTerminalSource() {
+ return _terminalFilter;
+}
+#else
+
+void OLARenderIMP::_loadProgram() {
+ if (_blendProgram == -1) {
+ GLuint vertexShader = _loadShader(GL_VERTEX_SHADER, VertexShaderString);
+ GLuint fragmentShader = _loadShader(GL_FRAGMENT_SHADER, FragmentShaderString);
+
+ _blendProgram = glCreateProgram();
+ if (!_blendProgram) {
+ assert(0);
+ return;
+ }
+
+ glAttachShader(_blendProgram, vertexShader);
+ glAttachShader(_blendProgram, fragmentShader);
+
+ glLinkProgram(_blendProgram);
+
+ // 检查错误
+ GLint linked;
+ glGetProgramiv(_blendProgram, GL_LINK_STATUS, &linked);
+ if (!linked) {
+ glDeleteProgram(_blendProgram);
+ _blendProgram = 0;
+ return;
+ }
+
+ glUseProgram(_blendProgram);
+
+ _positionSlot = glGetAttribLocation(_blendProgram, "position");
+ _texCoordSlot = glGetAttribLocation(_blendProgram, "texCoord");
+ _texCoordSlot1 = glGetAttribLocation(_blendProgram, "texCoord1");
+ _inputTextureSlot = glGetUniformLocation(_blendProgram, "colorMap");
+ _inputTextureSlot1 = glGetUniformLocation(_blendProgram, "colorMap1");
+ }
+
+ if (_transformProgram == -1) {
+ GLuint vertexShader = _loadShader(GL_VERTEX_SHADER, TransformVertexShaderString);
+ GLuint fragmentShader = _loadShader(GL_FRAGMENT_SHADER, TransformFragmentShaderString);
+
+ _transformProgram = glCreateProgram();
+ if (!_transformProgram) {
+ assert(0);
+ return;
+ }
+
+ glAttachShader(_transformProgram, vertexShader);
+ glAttachShader(_transformProgram, fragmentShader);
+
+ glLinkProgram(_transformProgram);
+
+ // 检查错误
+ GLint linked;
+ glGetProgramiv(_transformProgram, GL_LINK_STATUS, &linked);
+ if (!linked) {
+ glDeleteProgram(_transformProgram);
+ _transformProgram = 0;
+ return;
+ }
+
+ glUseProgram(_transformProgram);
+ _transformPositionSlot = glGetAttribLocation(_transformProgram, "position");
+ _transformTexCoordSlot = glGetAttribLocation(_transformProgram, "texCoord");
+ _transformTextureSlot = glGetUniformLocation(_transformProgram, "colorMap");
+ _transform_mvp = glGetUniformLocation(_transformProgram, "mvp");
+ }
+}
+
+void OLARenderIMP::_loadOutputTexture(int width, int height) {
+ if (_outputTexture == -1 || _outputFramebuffer == -1) {
+ glGenFramebuffers(1, &_outputFramebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, _outputFramebuffer);
+
+ glGenTextures(1, &_outputTexture);
+ glBindTexture(GL_TEXTURE_2D, _outputTexture);
+
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _outputTexture, 0);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ assert(status == GL_FRAMEBUFFER_COMPLETE);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glGenFramebuffers(1, &_blendFbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, _blendFbo);
+ glGenTextures(1, &_blendTexture);
+ glBindTexture(GL_TEXTURE_2D, _blendTexture);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, _blendTexture, 0);
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ assert(status == GL_FRAMEBUFFER_COMPLETE);
+
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBindTexture(GL_TEXTURE_2D, 0);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ }
+}
+
+void OLARenderIMP::_setROI(Vec4 roi) {
+ _mvp_matrix.set_identity();
+ _roi.x = roi.x;
+ _roi.y = roi.y;
+ _roi.z = roi.z;
+ _roi.w = roi.w;
+ //transform OK
+ float realXOffset = 1.0 / _roi.z * (1.0 - _roi.z);
+ float realYOffset = 1.0 / _roi.w * (1.0 - _roi.w);
+
+ auto roiAdjusted = Vec4(1.0 / _roi.z * _roi.x * 2.0,
+ 1.0 / _roi.w * _roi.y * 2.0, 1.0, 1.0);
+ _mvp_matrix.scale(_roi.z, _roi.w, 1.0);
+
+
+// #if defined(__ANDROID__) || defined(ANDROID)
+ _mvp_matrix.translate(-realXOffset, realYOffset, 0.0);
+ _mvp_matrix.translate(roiAdjusted.x, -roiAdjusted.y, 0.0);
+// #else
+// _mvp_matrix.translate(-realXOffset, -realYOffset, 0.0);
+// _mvp_matrix.translate(roiAdjusted.x, roiAdjusted.y, 0.0);
+// #endif
+}
+
+GLuint OLARenderIMP::_loadShader(GLenum shaderType, const std::string &shaderString) {
+ GLuint shader = glCreateShader(shaderType);
+ if (shader == 0) {
+ return 0;
+ }
+
+ // Load the shader source
+ const char *shaderStringUTF8 = shaderString.c_str();
+ glShaderSource(shader, 1, &shaderStringUTF8, NULL);
+
+ // Compile the shader
+ glCompileShader(shader);
+
+ // Check the compile status
+ GLint compiled = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
+
+ if (!compiled) {
+ assert(0);
+ glDeleteShader(shader);
+ return 0;
+ }
+
+ return shader;
+}
+
+#endif
+NS_OLA_END
diff --git a/mediapipe/modules/render_queue/OlaRenderIMP.h b/mediapipe/modules/render_queue/OlaRenderIMP.h
new file mode 100644
index 000000000..189075dff
--- /dev/null
+++ b/mediapipe/modules/render_queue/OlaRenderIMP.h
@@ -0,0 +1,122 @@
+//
+// OlaRenderIMP.hpp
+// OlaRender
+//
+// Created by 王韧竹 on 2022/6/20.
+//
+
+#ifndef OlaRenderIMP_hpp
+#define OlaRenderIMP_hpp
+
+#include
+#include "macros.h"
+#include "OlaRender.h"
+#include