154 lines
5.0 KiB
C++
Raw Normal View History

//
// Created by Marc Rousavy on 29.08.23.
//
#include "OpenGLContext.h"
#include <EGL/egl.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <android/native_window.h>
#include <android/log.h>
#include "OpenGLError.h"
namespace vision {
feat: Skia for Android (#1731) * feat: Call Skia Renderer * Use default NativePreviewView for Skia * Render to separate FBO * It appears once * Refactor a lot lol * Pass width/height * Read width/heights * Update SkiaRenderer.cpp * Read stencil/samples * Use switch for target * Clear full red * Update VideoPipeline.cpp * fix: Use `BorrowTextureFrom` instead of `AdoptTextureFrom` * Get it to work * Draw Camera Frame again (only works for first frame) * glDisable(GL_BLEND) * Use Frame Buffer again * Simplify Skia offscreen surface creation * fix: Get it to kinda work? * fix: Remove `sampler2D` shader Only the EXTERNAL_OES one kinda works * Revert "fix: Remove `sampler2D` shader" This reverts commit bf241a82f440f5a442f23a2b10329b813e7cdb3e. * Revert "fix: Get it to kinda work?" This reverts commit ea6a8784ad8dc7d05e8076591874f021b51dd84a. * fix: Use Skia for rendering * Simplify drawing code a lot * Clean up drawing loop a bit more * Some docs * Update SkiaRenderer.cpp * Surface * try to use Matrix * Use BottomLeft as a surface origin again * Get actual surface dimensions * Use 1x1 pbuffer instead * Update SkiaRenderer.cpp * Update SkiaRenderer.cpp * feat: Implement Skia Frame Processor (#1735) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * feat: Custom `Frame` implementation that uses CPU `ByteBuffer` (#1736) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * try: Try to just create a CPU based ByteBuffer * fix: Fix Java Type * fix remaining errors * try fixing FrameFactory * Use `free` * fix: Fix scene mode crash on some emulators * fix: Fix scene mode crash on some emulators * Fix getting pixels * fix: Fix buffer not being freed * Add some docs to `Frame` * Test Skia again * Use `getCurrentPresentationTime()` * Remove `FrameFactory.cpp` * Update VideoPipeline.h * Update VideoPipeline.cpp
2023-09-01 10:43:19 +02:00
std::shared_ptr<OpenGLContext> OpenGLContext::CreateWithOffscreenSurface() {
return std::unique_ptr<OpenGLContext>(new OpenGLContext());
}
OpenGLContext::~OpenGLContext() {
destroy();
}
void OpenGLContext::destroy() {
if (display != EGL_NO_DISPLAY) {
eglMakeCurrent(display, offscreenSurface, offscreenSurface, context);
if (offscreenSurface != EGL_NO_SURFACE) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Destroying OpenGL Surface...");
eglDestroySurface(display, offscreenSurface);
offscreenSurface = EGL_NO_SURFACE;
}
if (context != EGL_NO_CONTEXT) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Destroying OpenGL Context...");
eglDestroyContext(display, context);
context = EGL_NO_CONTEXT;
}
__android_log_print(ANDROID_LOG_INFO, TAG, "Destroying OpenGL Display...");
eglTerminate(display);
display = EGL_NO_DISPLAY;
config = nullptr;
}
}
void OpenGLContext::ensureOpenGL() {
bool successful;
// EGLDisplay
if (display == EGL_NO_DISPLAY) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLDisplay..");
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY) throw OpenGLError("Failed to get default OpenGL Display!");
EGLint major;
EGLint minor;
successful = eglInitialize(display, &major, &minor);
if (!successful) throw OpenGLError("Failed to initialize OpenGL!");
}
// EGLConfig
if (config == nullptr) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLConfig..");
EGLint attributes[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
feat: Skia for Android (#1731) * feat: Call Skia Renderer * Use default NativePreviewView for Skia * Render to separate FBO * It appears once * Refactor a lot lol * Pass width/height * Read width/heights * Update SkiaRenderer.cpp * Read stencil/samples * Use switch for target * Clear full red * Update VideoPipeline.cpp * fix: Use `BorrowTextureFrom` instead of `AdoptTextureFrom` * Get it to work * Draw Camera Frame again (only works for first frame) * glDisable(GL_BLEND) * Use Frame Buffer again * Simplify Skia offscreen surface creation * fix: Get it to kinda work? * fix: Remove `sampler2D` shader Only the EXTERNAL_OES one kinda works * Revert "fix: Remove `sampler2D` shader" This reverts commit bf241a82f440f5a442f23a2b10329b813e7cdb3e. * Revert "fix: Get it to kinda work?" This reverts commit ea6a8784ad8dc7d05e8076591874f021b51dd84a. * fix: Use Skia for rendering * Simplify drawing code a lot * Clean up drawing loop a bit more * Some docs * Update SkiaRenderer.cpp * Surface * try to use Matrix * Use BottomLeft as a surface origin again * Get actual surface dimensions * Use 1x1 pbuffer instead * Update SkiaRenderer.cpp * Update SkiaRenderer.cpp * feat: Implement Skia Frame Processor (#1735) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * feat: Custom `Frame` implementation that uses CPU `ByteBuffer` (#1736) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * try: Try to just create a CPU based ByteBuffer * fix: Fix Java Type * fix remaining errors * try fixing FrameFactory * Use `free` * fix: Fix scene mode crash on some emulators * fix: Fix scene mode crash on some emulators * Fix getting pixels * fix: Fix buffer not being freed * Add some docs to `Frame` * Test Skia again * Use `getCurrentPresentationTime()` * Remove `FrameFactory.cpp` * Update VideoPipeline.h * Update VideoPipeline.cpp
2023-09-01 10:43:19 +02:00
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0,
EGL_STENCIL_SIZE, 0,
EGL_NONE};
EGLint numConfigs;
successful = eglChooseConfig(display, attributes, &config, 1, &numConfigs);
if (!successful || numConfigs == 0) throw OpenGLError("Failed to choose OpenGL config!");
}
// EGLContext
if (context == EGL_NO_CONTEXT) {
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing EGLContext..");
EGLint contextAttributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
context = eglCreateContext(display, config, nullptr, contextAttributes);
if (context == EGL_NO_CONTEXT) throw OpenGLError("Failed to create OpenGL context!");
}
// EGLSurface
if (offscreenSurface == EGL_NO_SURFACE) {
// If we don't have a surface at all
feat: Skia for Android (#1731) * feat: Call Skia Renderer * Use default NativePreviewView for Skia * Render to separate FBO * It appears once * Refactor a lot lol * Pass width/height * Read width/heights * Update SkiaRenderer.cpp * Read stencil/samples * Use switch for target * Clear full red * Update VideoPipeline.cpp * fix: Use `BorrowTextureFrom` instead of `AdoptTextureFrom` * Get it to work * Draw Camera Frame again (only works for first frame) * glDisable(GL_BLEND) * Use Frame Buffer again * Simplify Skia offscreen surface creation * fix: Get it to kinda work? * fix: Remove `sampler2D` shader Only the EXTERNAL_OES one kinda works * Revert "fix: Remove `sampler2D` shader" This reverts commit bf241a82f440f5a442f23a2b10329b813e7cdb3e. * Revert "fix: Get it to kinda work?" This reverts commit ea6a8784ad8dc7d05e8076591874f021b51dd84a. * fix: Use Skia for rendering * Simplify drawing code a lot * Clean up drawing loop a bit more * Some docs * Update SkiaRenderer.cpp * Surface * try to use Matrix * Use BottomLeft as a surface origin again * Get actual surface dimensions * Use 1x1 pbuffer instead * Update SkiaRenderer.cpp * Update SkiaRenderer.cpp * feat: Implement Skia Frame Processor (#1735) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * feat: Custom `Frame` implementation that uses CPU `ByteBuffer` (#1736) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * try: Try to just create a CPU based ByteBuffer * fix: Fix Java Type * fix remaining errors * try fixing FrameFactory * Use `free` * fix: Fix scene mode crash on some emulators * fix: Fix scene mode crash on some emulators * Fix getting pixels * fix: Fix buffer not being freed * Add some docs to `Frame` * Test Skia again * Use `getCurrentPresentationTime()` * Remove `FrameFactory.cpp` * Update VideoPipeline.h * Update VideoPipeline.cpp
2023-09-01 10:43:19 +02:00
__android_log_print(ANDROID_LOG_INFO, TAG, "Initializing 1x1 offscreen pbuffer EGLSurface..");
EGLint attributes[] = {EGL_WIDTH, 1,
EGL_HEIGHT, 1,
EGL_NONE};
offscreenSurface = eglCreatePbufferSurface(display, config, attributes);
if (offscreenSurface == EGL_NO_SURFACE) throw OpenGLError("Failed to create OpenGL Surface!");
}
}
void OpenGLContext::use() {
this->use(offscreenSurface);
}
void OpenGLContext::use(EGLSurface surface) {
if (surface == EGL_NO_SURFACE) throw OpenGLError("Cannot render to a null Surface!");
// 1. Make sure the OpenGL context is initialized
this->ensureOpenGL();
// 2. Make the OpenGL context current
bool successful = eglMakeCurrent(display, surface, surface, context);
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to use current OpenGL context!");
// 3. Caller can now render to this surface
}
feat: Skia for Android (#1731) * feat: Call Skia Renderer * Use default NativePreviewView for Skia * Render to separate FBO * It appears once * Refactor a lot lol * Pass width/height * Read width/heights * Update SkiaRenderer.cpp * Read stencil/samples * Use switch for target * Clear full red * Update VideoPipeline.cpp * fix: Use `BorrowTextureFrom` instead of `AdoptTextureFrom` * Get it to work * Draw Camera Frame again (only works for first frame) * glDisable(GL_BLEND) * Use Frame Buffer again * Simplify Skia offscreen surface creation * fix: Get it to kinda work? * fix: Remove `sampler2D` shader Only the EXTERNAL_OES one kinda works * Revert "fix: Remove `sampler2D` shader" This reverts commit bf241a82f440f5a442f23a2b10329b813e7cdb3e. * Revert "fix: Get it to kinda work?" This reverts commit ea6a8784ad8dc7d05e8076591874f021b51dd84a. * fix: Use Skia for rendering * Simplify drawing code a lot * Clean up drawing loop a bit more * Some docs * Update SkiaRenderer.cpp * Surface * try to use Matrix * Use BottomLeft as a surface origin again * Get actual surface dimensions * Use 1x1 pbuffer instead * Update SkiaRenderer.cpp * Update SkiaRenderer.cpp * feat: Implement Skia Frame Processor (#1735) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * feat: Custom `Frame` implementation that uses CPU `ByteBuffer` (#1736) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * try: Try to just create a CPU based ByteBuffer * fix: Fix Java Type * fix remaining errors * try fixing FrameFactory * Use `free` * fix: Fix scene mode crash on some emulators * fix: Fix scene mode crash on some emulators * Fix getting pixels * fix: Fix buffer not being freed * Add some docs to `Frame` * Test Skia again * Use `getCurrentPresentationTime()` * Remove `FrameFactory.cpp` * Update VideoPipeline.h * Update VideoPipeline.cpp
2023-09-01 10:43:19 +02:00
void OpenGLContext::flush() const {
bool successful = eglSwapBuffers(display, eglGetCurrentSurface(EGL_DRAW));
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to swap OpenGL buffers!");
}
OpenGLTexture OpenGLContext::createTexture(OpenGLTexture::Type type, int width, int height) {
// 1. Make sure the OpenGL context is initialized
this->ensureOpenGL();
// 2. Make the OpenGL context current
bool successful = eglMakeCurrent(display, offscreenSurface, offscreenSurface, context);
if (!successful || eglGetError() != EGL_SUCCESS) throw OpenGLError("Failed to use current OpenGL context!");
GLuint textureId;
glGenTextures(1, &textureId);
feat: Skia for Android (#1731) * feat: Call Skia Renderer * Use default NativePreviewView for Skia * Render to separate FBO * It appears once * Refactor a lot lol * Pass width/height * Read width/heights * Update SkiaRenderer.cpp * Read stencil/samples * Use switch for target * Clear full red * Update VideoPipeline.cpp * fix: Use `BorrowTextureFrom` instead of `AdoptTextureFrom` * Get it to work * Draw Camera Frame again (only works for first frame) * glDisable(GL_BLEND) * Use Frame Buffer again * Simplify Skia offscreen surface creation * fix: Get it to kinda work? * fix: Remove `sampler2D` shader Only the EXTERNAL_OES one kinda works * Revert "fix: Remove `sampler2D` shader" This reverts commit bf241a82f440f5a442f23a2b10329b813e7cdb3e. * Revert "fix: Get it to kinda work?" This reverts commit ea6a8784ad8dc7d05e8076591874f021b51dd84a. * fix: Use Skia for rendering * Simplify drawing code a lot * Clean up drawing loop a bit more * Some docs * Update SkiaRenderer.cpp * Surface * try to use Matrix * Use BottomLeft as a surface origin again * Get actual surface dimensions * Use 1x1 pbuffer instead * Update SkiaRenderer.cpp * Update SkiaRenderer.cpp * feat: Implement Skia Frame Processor (#1735) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * feat: Custom `Frame` implementation that uses CPU `ByteBuffer` (#1736) * feat: Implement JS Skia Frame Processor * Update SkiaRenderer.cpp * push * Create Frame from C++ * compile * Compile * Update VideoPipeline.cpp * Fix JNI local ref * Use `HardwareBuffer` for implementation * try: Try to just create a CPU based ByteBuffer * fix: Fix Java Type * fix remaining errors * try fixing FrameFactory * Use `free` * fix: Fix scene mode crash on some emulators * fix: Fix scene mode crash on some emulators * Fix getting pixels * fix: Fix buffer not being freed * Add some docs to `Frame` * Test Skia again * Use `getCurrentPresentationTime()` * Remove `FrameFactory.cpp` * Update VideoPipeline.h * Update VideoPipeline.cpp
2023-09-01 10:43:19 +02:00
GLenum target;
switch (type) {
case OpenGLTexture::Type::ExternalOES:
target = GL_TEXTURE_EXTERNAL_OES;
break;
case OpenGLTexture::Type::Texture2D:
target = GL_TEXTURE_2D;
break;
default:
throw std::runtime_error("Invalid OpenGL Texture Type!");
}
glBindTexture(target, textureId);
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
return {
.id = textureId,
.target = target,
.width = width,
.height = height
};
}
} // namespace vision