Sweeping Media Layer Changes (GL ES 2.0 Support)
This commit is contained in:
parent
4ed11b67e7
commit
1743626113
2
.gitignore
vendored
2
.gitignore
vendored
@ -9,3 +9,5 @@ appimage-builder-cache
|
||||
appimage-build
|
||||
AppDir
|
||||
*.zsync
|
||||
core*
|
||||
qemu_*
|
||||
|
@ -2,15 +2,15 @@ cmake_minimum_required(VERSION 3.13.0)
|
||||
|
||||
# Specify Options
|
||||
option(MCPI_IS_MIXED_BUILD "Whether The Architecture-Independent And ARM Code Are Different Architecture" FALSE)
|
||||
if(MCPI_IS_MIXED_BUILD)
|
||||
option(MCPI_BUNDLE_ARMHF_SYSROOT "Whether To Include An ARMHF Sysroot" TRUE)
|
||||
endif()
|
||||
option(MCPI_BUNDLE_ARMHF_SYSROOT "Whether To Include An ARMHF Sysroot" ${MCPI_IS_MIXED_BUILD})
|
||||
option(MCPI_SERVER_MODE "Server Mode" FALSE)
|
||||
option(MCPI_HEADLESS_MODE "Headless Mode" ${MCPI_SERVER_MODE})
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
option(MCPI_USE_MEDIA_LAYER_PROXY "Whether To Enable The Media Layer Proxy" ${MCPI_IS_MIXED_BUILD})
|
||||
option(MCPI_USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE)
|
||||
else()
|
||||
set(MCPI_USE_MEDIA_LAYER_PROXY FALSE)
|
||||
set(MCPI_USE_GLES1_COMPATIBILITY_LAYER FALSE)
|
||||
endif()
|
||||
set(MCPI_BUILD_MODE "both" CACHE STRING "\"arm\" = Build Only Code That Must Be ARM; \"native\" = Build Architecture-Independent Code; \"both\" = Build All Code As ARM")
|
||||
set_property(CACHE MCPI_BUILD_MODE PROPERTY STRINGS "both" "arm" "native")
|
||||
@ -118,6 +118,9 @@ endif()
|
||||
if(MCPI_BUNDLE_ARMHF_SYSROOT)
|
||||
add_definitions(-DMCPI_BUNDLE_ARMHF_SYSROOT)
|
||||
endif()
|
||||
if(MCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||
add_definitions(-DMCPI_USE_GLES1_COMPATIBILITY_LAYER)
|
||||
endif()
|
||||
|
||||
# Version
|
||||
set_property(
|
||||
|
7
dependencies/minecraft-pi/CMakeLists.txt
vendored
7
dependencies/minecraft-pi/CMakeLists.txt
vendored
@ -12,4 +12,9 @@ FetchContent_Declare(
|
||||
FetchContent_Populate(minecraft-pi)
|
||||
|
||||
# Install
|
||||
install(DIRECTORY "${minecraft-pi_SOURCE_DIR}/" DESTINATION "${MCPI_INSTALL_DIR}" USE_SOURCE_PERMISSIONS)
|
||||
install(
|
||||
DIRECTORY "${minecraft-pi_SOURCE_DIR}/"
|
||||
DESTINATION "${MCPI_INSTALL_DIR}"
|
||||
USE_SOURCE_PERMISSIONS
|
||||
REGEX "api" EXCLUDE
|
||||
)
|
||||
|
@ -2,8 +2,11 @@
|
||||
|
||||
## Command Line Arguments
|
||||
|
||||
### ``--version`` (Or ``-v``)
|
||||
If you run MCPI-Reborn with ``--version`` it will print its version to ``stdout``.
|
||||
|
||||
### ``--print-available-feature-flags`` (Client Mode Only)
|
||||
If you run MCPI-Reborn with ``--print-available-feature-flags``, it will print the available feature flags and then immediately exit.
|
||||
If you run MCPI-Reborn with ``--print-available-feature-flags``, it will print the available feature flags to ``stdout`` and then immediately exit.
|
||||
|
||||
The feature flags are printed in the following format:
|
||||
```
|
||||
|
@ -149,7 +149,17 @@ static void exit_handler(__attribute__((unused)) int signal_id) {
|
||||
}
|
||||
|
||||
// Pre-Bootstrap
|
||||
void pre_bootstrap() {
|
||||
void pre_bootstrap(int argc, char *argv[]) {
|
||||
// Print Version
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-v") == 0) {
|
||||
// Print
|
||||
printf("Reborn v%s\n", VERSION);
|
||||
fflush(stdout);
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
// GTK Dark Mode
|
||||
#ifndef MCPI_SERVER_MODE
|
||||
set_and_print_env("GTK_THEME", "Adwaita:dark");
|
||||
|
@ -6,7 +6,7 @@ extern "C" {
|
||||
|
||||
void set_and_print_env(const char *name, char *value);
|
||||
|
||||
void pre_bootstrap();
|
||||
void pre_bootstrap(int argc, char *argv[]);
|
||||
void bootstrap(int argc, char *argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -127,7 +127,7 @@ static void run_zenity_and_set_env(const char *env_name, std::vector<std::string
|
||||
#define LIST_DIALOG_SIZE "400"
|
||||
int main(int argc, char *argv[]) {
|
||||
// Pre-Bootstrap
|
||||
pre_bootstrap();
|
||||
pre_bootstrap(argc, argv);
|
||||
|
||||
// Print Features
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <stdint.h>
|
||||
#include <signal.h>
|
||||
#include <poll.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
@ -41,14 +42,16 @@ static void exit_handler(__attribute__((unused)) int signal) {
|
||||
}
|
||||
|
||||
// Setup
|
||||
#define PIPE_READ 0
|
||||
#define PIPE_WRITE 1
|
||||
void setup_crash_report() {
|
||||
// Store Output
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
int output_pipe[2];
|
||||
safe_pipe2(output_pipe, 0);
|
||||
int error_pipe[2];
|
||||
safe_pipe2(error_pipe, 0);
|
||||
#endif
|
||||
int input_pipe[2];
|
||||
safe_pipe2(input_pipe, 0);
|
||||
|
||||
// Fork
|
||||
pid_t ret = fork();
|
||||
@ -58,14 +61,15 @@ void setup_crash_report() {
|
||||
// Child Process
|
||||
|
||||
// Pipe stdio
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
dup2(output_pipe[1], STDOUT_FILENO);
|
||||
close(output_pipe[0]);
|
||||
close(output_pipe[1]);
|
||||
dup2(error_pipe[1], STDERR_FILENO);
|
||||
close(error_pipe[0]);
|
||||
close(error_pipe[1]);
|
||||
#endif
|
||||
dup2(output_pipe[PIPE_WRITE], STDOUT_FILENO);
|
||||
close(output_pipe[PIPE_READ]);
|
||||
close(output_pipe[PIPE_WRITE]);
|
||||
dup2(error_pipe[PIPE_WRITE], STDERR_FILENO);
|
||||
close(error_pipe[PIPE_READ]);
|
||||
close(error_pipe[PIPE_WRITE]);
|
||||
dup2(input_pipe[PIPE_READ], STDIN_FILENO);
|
||||
close(input_pipe[PIPE_READ]);
|
||||
close(input_pipe[PIPE_WRITE]);
|
||||
|
||||
// Create New Process Group
|
||||
setpgid(0, 0);
|
||||
@ -87,13 +91,12 @@ void setup_crash_report() {
|
||||
act_sigterm.sa_handler = &exit_handler;
|
||||
sigaction(SIGTERM, &act_sigterm, NULL);
|
||||
|
||||
// Capture stdio
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Close Unneeded File Descriptors
|
||||
close(output_pipe[1]);
|
||||
close(error_pipe[1]);
|
||||
close(output_pipe[PIPE_WRITE]);
|
||||
close(error_pipe[PIPE_WRITE]);
|
||||
close(input_pipe[PIPE_READ]);
|
||||
|
||||
// Create A Buffer
|
||||
// Setup Logging
|
||||
#define BUFFER_SIZE 1024
|
||||
char buf[BUFFER_SIZE];
|
||||
|
||||
@ -105,10 +108,11 @@ void setup_crash_report() {
|
||||
}
|
||||
|
||||
// Setup Polling
|
||||
int number_fds = 2;
|
||||
int number_fds = 3;
|
||||
struct pollfd poll_fds[number_fds];
|
||||
poll_fds[0].fd = output_pipe[0];
|
||||
poll_fds[1].fd = error_pipe[0];
|
||||
poll_fds[0].fd = output_pipe[PIPE_READ];
|
||||
poll_fds[1].fd = error_pipe[PIPE_READ];
|
||||
poll_fds[2].fd = STDIN_FILENO;
|
||||
for (int i = 0; i < number_fds; i++) {
|
||||
poll_fds[i].events = POLLIN;
|
||||
}
|
||||
@ -129,31 +133,51 @@ void setup_crash_report() {
|
||||
for (int i = 0; i < number_fds; i++) {
|
||||
if (poll_fds[i].revents != 0) {
|
||||
if (poll_fds[i].revents & POLLIN) {
|
||||
// Data Available
|
||||
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
|
||||
if (bytes_read == -1) {
|
||||
ERR("Unable To Read Log Data: %s", strerror(errno));
|
||||
}
|
||||
if (poll_fds[i].fd == STDIN_FILENO) {
|
||||
// Data Available From stdin
|
||||
int bytes_available;
|
||||
if (ioctl(fileno(stdin), FIONREAD, &bytes_available) == -1) {
|
||||
bytes_available = 0;
|
||||
}
|
||||
// Read
|
||||
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE);
|
||||
if (bytes_read == -1) {
|
||||
ERR("Unable To Read Log Data: %s", strerror(errno));
|
||||
}
|
||||
// Write To Child
|
||||
if (write(input_pipe[PIPE_WRITE], (void *) buf, bytes_read) == -1) {
|
||||
ERR("Unable To Write Input To Child: %s", strerror(errno));
|
||||
}
|
||||
} else {
|
||||
// Data Available From Child's stdout/stderr
|
||||
ssize_t bytes_read = read(poll_fds[i].fd, (void *) buf, BUFFER_SIZE - 1 /* Account For NULL-Terminator */);
|
||||
if (bytes_read == -1) {
|
||||
ERR("Unable To Read Log Data: %s", strerror(errno));
|
||||
}
|
||||
|
||||
// Print To Terminal
|
||||
buf[bytes_read] = '\0';
|
||||
fprintf(i == 0 ? stdout : stderr, "%s", buf);
|
||||
// Print To Terminal
|
||||
buf[bytes_read] = '\0';
|
||||
fprintf(i == 0 ? stdout : stderr, "%s", buf);
|
||||
|
||||
// Write To log
|
||||
if (write(log_file_fd, (void *) buf, bytes_read) == -1) {
|
||||
ERR("Unable To Write Log Data: %s", strerror(errno));
|
||||
// Write To log
|
||||
if (write(log_file_fd, (void *) buf, bytes_read) == -1) {
|
||||
ERR("Unable To Write Log Data: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// File Descriptor No Longer Accessible
|
||||
if (close(poll_fds[i].fd) == -1) {
|
||||
if (poll_fds[i].events != 0 && close(poll_fds[i].fd) == -1) {
|
||||
ERR("Unable To Close File Descriptor: %s", strerror(errno));
|
||||
}
|
||||
poll_fds[i].events = 0;
|
||||
number_open_fds--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Close Input Pipe
|
||||
close(input_pipe[PIPE_WRITE]);
|
||||
|
||||
// Get Return Code
|
||||
int status;
|
||||
@ -176,33 +200,30 @@ void setup_crash_report() {
|
||||
fprintf(stderr, "%s", exit_code_line);
|
||||
|
||||
// Write Exit Code Log Line
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
if (write(log_file_fd, (void *) exit_code_line, strlen(exit_code_line)) == -1) {
|
||||
ERR("Unable To Write Exit Code To Log: %s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Free Exit Code Log Line
|
||||
free(exit_code_line);
|
||||
}
|
||||
|
||||
// Show Crash Log
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
// Close Log File FD
|
||||
if (close(log_file_fd) == -1) {
|
||||
ERR("Unable To Close Log File Descriptor: %s", strerror(errno));
|
||||
}
|
||||
|
||||
// Show Report
|
||||
// Show Crash Log
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
if (is_crash) {
|
||||
show_report(log_filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Delete Log File
|
||||
if (unlink(log_filename) == -1) {
|
||||
ERR("Unable To Delete Log File: %s", strerror(errno));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Exit
|
||||
exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Pre-Bootstrap
|
||||
pre_bootstrap();
|
||||
pre_bootstrap(argc, argv);
|
||||
|
||||
// Set Home To Current Directory, So World Data Is Stored There
|
||||
char *launch_directory = getcwd(NULL, 0);
|
||||
|
@ -25,7 +25,7 @@
|
||||
dlerror(); \
|
||||
real_##name = (name##_t) dlsym(RTLD_NEXT, #name); \
|
||||
if (!real_##name) { \
|
||||
ERR("Error Resolving Symbol: "#name": %s", dlerror()); \
|
||||
ERR("Error Resolving Symbol: " #name ": %s", dlerror()); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
@ -49,6 +49,8 @@ extern "C" {
|
||||
|
||||
// Safe Version Of pipe()
|
||||
void safe_pipe2(int pipefd[2], int flags);
|
||||
// Check If Two Percentages Are Different Enough To Be Logged
|
||||
int is_progress_difference_significant(int32_t new_val, int32_t old_val);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -6,3 +6,19 @@ void safe_pipe2(int pipefd[2], int flags) {
|
||||
ERR("Unable To Create Pipe: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
||||
// Check If Two Percentages Are Different Enough To Be Logged
|
||||
#define SIGNIFICANT_PROGRESS 5
|
||||
int is_progress_difference_significant(int32_t new_val, int32_t old_val) {
|
||||
if (new_val != old_val) {
|
||||
if (new_val == -1 || old_val == -1) {
|
||||
return 1;
|
||||
} else if (new_val == 0 || new_val == 100) {
|
||||
return 1;
|
||||
} else {
|
||||
return new_val - old_val >= SIGNIFICANT_PROGRESS;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,16 @@
|
||||
project(media-layer)
|
||||
|
||||
# Check Options
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY AND MCPI_BUILD_MODE STREQUAL "both")
|
||||
message(FATAL_ERROR "Media Layer Proxy Is Redundant When Building ARM And Native Components In The Same Build")
|
||||
endif()
|
||||
# Target Notes:
|
||||
# media-layer-core-real: Fully Built Media Layer Core
|
||||
# media-layer-core: Alias Target That Points To The Library MCPI Should Link To
|
||||
|
||||
# Add Headers
|
||||
add_library(media-layer-headers INTERFACE)
|
||||
target_include_directories(media-layer-headers INTERFACE include)
|
||||
|
||||
# Add GLESv1_CM Stubs Or Compatibility Layer
|
||||
add_subdirectory(gles)
|
||||
|
||||
# Add Core
|
||||
add_subdirectory(core)
|
||||
|
||||
@ -17,8 +19,5 @@ if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
add_subdirectory(proxy)
|
||||
endif()
|
||||
|
||||
# Add Stubs
|
||||
add_subdirectory(stubs)
|
||||
|
||||
# Add Extras
|
||||
add_subdirectory(extras)
|
||||
|
@ -8,26 +8,30 @@ endif()
|
||||
|
||||
# Build
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY AND BUILD_NATIVE_COMPONENTS)
|
||||
# Building Native Components
|
||||
add_library(media-layer-core OBJECT ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
elseif(NOT MCPI_USE_MEDIA_LAYER_PROXY AND BUILD_ARM_COMPONENTS)
|
||||
# Building ARM Components
|
||||
add_library(media-layer-core SHARED ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
# Build Media Layer Core Natively And Use Proxy
|
||||
add_library(media-layer-core-real OBJECT ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
endif()
|
||||
if(NOT MCPI_USE_MEDIA_LAYER_PROXY AND BUILD_ARM_COMPONENTS)
|
||||
# Directly Link Media Layer Core To MCPI
|
||||
add_library(media-layer-core-real SHARED ${CORE_SRC}) # Dependencies Are Setup Later
|
||||
set_target_properties(media-layer-core-real PROPERTIES OUTPUT_NAME "media-layer-core")
|
||||
# Install
|
||||
install(TARGETS media-layer-core DESTINATION "${MCPI_LIB_DIR}")
|
||||
install(TARGETS media-layer-core-real DESTINATION "${MCPI_LIB_DIR}")
|
||||
# Create Alias Target For Linking
|
||||
add_library(media-layer-core ALIAS media-layer-core-real)
|
||||
endif()
|
||||
|
||||
# Configure Media Layer Core If Built
|
||||
if(TARGET media-layer-core)
|
||||
if(TARGET media-layer-core-real)
|
||||
# Link
|
||||
target_link_libraries(media-layer-core media-layer-headers reborn-util pthread dl)
|
||||
target_link_libraries(media-layer-core-real media-layer-headers reborn-util pthread dl)
|
||||
if(NOT MCPI_HEADLESS_MODE)
|
||||
# Find FreeImage
|
||||
find_library(FREEIMAGE_LIBRARY NAMES freeimage libfreeimage.so.3 REQUIRED)
|
||||
# OpenAL
|
||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||
# Link
|
||||
target_link_libraries(media-layer-core "${FREEIMAGE_LIBRARY}" "${OPENAL_LIBRARY}" m GLESv1_CM glfw)
|
||||
target_link_libraries(media-layer-core-real "${FREEIMAGE_LIBRARY}" "${OPENAL_LIBRARY}" m GLESv1_CM glfw)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
@ -15,6 +15,7 @@ static std::vector<ALuint> &get_sources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
// Error Checking
|
||||
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
|
||||
#define AL_ERROR_CHECK_MANUAL(val) \
|
||||
{ \
|
||||
@ -73,6 +74,7 @@ void media_audio_update(float volume, float x, float y, float z, float yaw) {
|
||||
}
|
||||
}
|
||||
|
||||
// Play
|
||||
void media_audio_play(const char *source, const char *name, float x, float y, float z, float pitch, float volume, int is_ui) {
|
||||
// Check
|
||||
if (_media_audio_is_loaded()) {
|
||||
|
@ -207,21 +207,18 @@ static ALuint load_sound(const char *source, const char *name) {
|
||||
}
|
||||
|
||||
// Store Buffers
|
||||
static std::unordered_map<std::string, ALuint> &get_buffers() {
|
||||
static std::unordered_map<std::string, ALuint> buffers;
|
||||
return buffers;
|
||||
}
|
||||
static std::unordered_map<std::string, ALuint> buffers;
|
||||
|
||||
// Get Buffer For Sound
|
||||
ALuint _media_audio_get_buffer(const char *source, const char *name) {
|
||||
// Check
|
||||
if (_media_audio_is_loaded()) {
|
||||
if (get_buffers().count(name) > 0) {
|
||||
if (buffers.count(name) > 0) {
|
||||
// Return
|
||||
return get_buffers()[name];
|
||||
return buffers[name];
|
||||
} else {
|
||||
// Load And Return
|
||||
get_buffers()[name] = load_sound(source, name);
|
||||
buffers[name] = load_sound(source, name);
|
||||
return _media_audio_get_buffer(source, name);
|
||||
}
|
||||
} else {
|
||||
@ -232,11 +229,11 @@ ALuint _media_audio_get_buffer(const char *source, const char *name) {
|
||||
// Delete Buffers
|
||||
void _media_audio_delete_buffers() {
|
||||
if (_media_audio_is_loaded()) {
|
||||
for (auto it : get_buffers()) {
|
||||
for (auto it : buffers) {
|
||||
if (it.second && alIsBuffer(it.second)) {
|
||||
alDeleteBuffers(1, &it.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
get_buffers().clear();
|
||||
buffers.clear();
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#include <SDL/SDL.h>
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
#define GLFW_INCLUDE_NONE
|
||||
@ -225,7 +224,7 @@ static void glfw_scroll(__attribute__((unused)) GLFWwindow *window, __attribute_
|
||||
#endif
|
||||
|
||||
// Track Media Layer State
|
||||
static int is_running = 0;
|
||||
static volatile int is_running = 0;
|
||||
|
||||
// Track If Raw Mouse Motion Is Enabled
|
||||
static int raw_mouse_motion_enabled = 1;
|
||||
@ -253,6 +252,8 @@ void media_disable_vsync() {
|
||||
}
|
||||
|
||||
// Init Media Layer
|
||||
#define GL_VERSION 0x1f02
|
||||
typedef const unsigned char *(*glGetString_t)(unsigned int name);
|
||||
void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *icon) {
|
||||
// Don't Enable GLFW In Headless Mode
|
||||
#ifndef MCPI_HEADLESS_MODE
|
||||
@ -263,10 +264,15 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
ERR("Unable To Initialize GLFW");
|
||||
}
|
||||
|
||||
// Create OpenGL ES 1.1 Context
|
||||
// Create OpenGL ES Context
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
|
||||
#ifdef MCPI_USE_GLES1_COMPATIBILITY_LAYER
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
#else
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 1);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
|
||||
#endif
|
||||
// Use EGL
|
||||
glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API);
|
||||
// Extra Settings
|
||||
@ -289,6 +295,10 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
// Make Window Context Current
|
||||
glfwMakeContextCurrent(glfw_window);
|
||||
|
||||
// Debug
|
||||
glGetString_t glGetString = (glGetString_t) glfwGetProcAddress("glGetString");
|
||||
DEBUG("Using %s", (*glGetString)(GL_VERSION));
|
||||
|
||||
// Init OpenAL
|
||||
_media_audio_init();
|
||||
#else
|
||||
@ -303,6 +313,9 @@ void SDL_WM_SetCaption(const char *title, __attribute__((unused)) const char *ic
|
||||
if (disable_vsync) {
|
||||
media_disable_vsync();
|
||||
}
|
||||
|
||||
// Always Cleanup Media Layer
|
||||
atexit(media_cleanup);
|
||||
}
|
||||
|
||||
void media_swap_buffers() {
|
||||
@ -384,10 +397,6 @@ void media_cleanup() {
|
||||
is_running = 0;
|
||||
}
|
||||
}
|
||||
// Always Cleanup Media Layer
|
||||
__attribute__((destructor)) static void always_cleanup() {
|
||||
media_cleanup();
|
||||
}
|
||||
|
||||
// Store Cursor State
|
||||
static int cursor_grabbed = 0;
|
||||
|
@ -70,7 +70,7 @@ void media_take_screenshot(char *home) {
|
||||
int height = viewport[3];
|
||||
|
||||
// Get Line Size
|
||||
int line_size = width * 3;
|
||||
int line_size = width * 4;
|
||||
{
|
||||
// Handle Alignment
|
||||
int alignment;
|
||||
@ -85,14 +85,14 @@ void media_take_screenshot(char *home) {
|
||||
|
||||
// Read Pixels
|
||||
unsigned char pixels[size];
|
||||
glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, pixels);
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
|
||||
// Handle Little Endian Systems
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
// Swap Red And Blue
|
||||
for (int j = 0; j < width; j++) {
|
||||
for (int k = 0; k < height; k++) {
|
||||
int pixel = (k * line_size) + (j * 3);
|
||||
int pixel = (k * line_size) + (j * 4);
|
||||
// Swap
|
||||
int red = pixels[pixel];
|
||||
int blue = pixels[pixel + 2];
|
||||
@ -103,7 +103,7 @@ void media_take_screenshot(char *home) {
|
||||
#endif
|
||||
|
||||
// Save Image
|
||||
FIBITMAP *image = FreeImage_ConvertFromRawBits(pixels, width, height, line_size, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0);
|
||||
FIBITMAP *image = FreeImage_ConvertFromRawBits(pixels, width, height, line_size, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK, 0);
|
||||
if (!FreeImage_Save(FIF_PNG, image, file, 0)) {
|
||||
INFO("Screenshot Failed: %s", file);
|
||||
} else {
|
||||
|
@ -2,5 +2,10 @@ project(media-layer-extras)
|
||||
|
||||
if(BUILD_ARM_COMPONENTS)
|
||||
# Add Source To Media Core
|
||||
target_sources(media-layer-core PRIVATE src/SDL.c)
|
||||
if(TARGET media-layer-core-real)
|
||||
set(TARGET media-layer-core-real)
|
||||
elseif(TARGET media-layer-proxy-server)
|
||||
set(TARGET media-layer-proxy-server)
|
||||
endif()
|
||||
target_sources("${TARGET}" PRIVATE src/SDL.c)
|
||||
endif()
|
||||
|
29
media-layer/gles/CMakeLists.txt
Normal file
29
media-layer/gles/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
project(media-layer-stubs)
|
||||
|
||||
# Stubs Only Needed For ARM
|
||||
if(MCPI_USE_GLES1_COMPATIBILITY_LAYER AND BUILD_NATIVE_COMPONENTS AND NOT MCPI_HEADLESS_MODE)
|
||||
# GLESv1_CM Compatibility Layer
|
||||
set(GLES1_LINK_MODE "SHARED")
|
||||
if(MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
# Link To Media Layer Proxy Client Statically
|
||||
# (This is so it doesn't interfere with the Media Layer Proxy Server's libGLESv1_CM.so.1 symlink.)
|
||||
set(GLES1_LINK_MODE "OBJECT")
|
||||
endif()
|
||||
add_library(GLESv1_CM "${GLES1_LINK_MODE}" src/compatibility-layer/state.c src/compatibility-layer/passthrough.c src/compatibility-layer/matrix.c src/compatibility-layer/draw.c)
|
||||
target_link_libraries(GLESv1_CM glfw reborn-util dl m)
|
||||
# Install
|
||||
if(NOT MCPI_USE_MEDIA_LAYER_PROXY)
|
||||
install(TARGETS GLESv1_CM DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
else()
|
||||
# Add GLESv1_CM Stubs For Linking
|
||||
add_library(GLESv1_CM SHARED src/stubs.c)
|
||||
# Install Fake GLESv1_CM Stubs In Server Mode
|
||||
if(MCPI_HEADLESS_MODE AND BUILD_ARM_COMPONENTS)
|
||||
install(TARGETS GLESv1_CM DESTINATION "${MCPI_LIB_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Common
|
||||
target_link_libraries(GLESv1_CM media-layer-headers)
|
||||
set_target_properties(GLESv1_CM PROPERTIES SOVERSION "1")
|
255
media-layer/gles/src/compatibility-layer/draw.c
Normal file
255
media-layer/gles/src/compatibility-layer/draw.c
Normal file
@ -0,0 +1,255 @@
|
||||
#include "state.h"
|
||||
#include "passthrough.h"
|
||||
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
// Shaders
|
||||
#define REAL_GL_FRAGMENT_SHADER 0x8b30
|
||||
#define REAL_GL_VERTEX_SHADER 0x8b31
|
||||
#define REAL_GL_INFO_LOG_LENGTH 0x8b84
|
||||
#define REAL_GL_COMPILE_STATUS 0x8b81
|
||||
GL_FUNC(glUseProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetUniformLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glUniformMatrix4fv, void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
|
||||
GL_FUNC(glUniform1i, void, (GLint location, GLint v0));
|
||||
GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0));
|
||||
GL_FUNC(glUniform4f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glGetAttribLocation, GLint, (GLuint program, const GLchar *name));
|
||||
GL_FUNC(glEnableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glDisableVertexAttribArray, void, (GLuint index));
|
||||
GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
|
||||
GL_FUNC(glVertexAttrib3f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2));
|
||||
GL_FUNC(glVertexAttrib4f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
|
||||
GL_FUNC(glCreateShader, GLuint, (GLenum type));
|
||||
GL_FUNC(glShaderSource, void, (GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length));
|
||||
GL_FUNC(glCompileShader, void, (GLuint shader));
|
||||
GL_FUNC(glCreateProgram, GLuint, ());
|
||||
GL_FUNC(glAttachShader, void, (GLuint program, GLuint shader));
|
||||
GL_FUNC(glLinkProgram, void, (GLuint program));
|
||||
GL_FUNC(glGetShaderiv, void, (GLuint shader, GLenum pname, GLint *params));
|
||||
GL_FUNC(glGetShaderInfoLog, void, (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
|
||||
|
||||
// Compile Shader
|
||||
static void log_shader(GLuint shader, const char *name) {
|
||||
// Log
|
||||
GLint log_length = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_INFO_LOG_LENGTH, &log_length);
|
||||
GLchar *log = malloc(log_length * sizeof (GLchar));
|
||||
ALLOC_CHECK(log);
|
||||
real_glGetShaderInfoLog()(shader, log_length, &log_length, log);
|
||||
if (log_length > 0) {
|
||||
if (log_length > 1 && log[log_length - 1] == '\n') {
|
||||
log[log_length - 1] = '\0';
|
||||
}
|
||||
DEBUG("%s Shader Compile Log: %s", name, log);
|
||||
}
|
||||
free(log);
|
||||
|
||||
// Check Status
|
||||
GLint is_compiled = 0;
|
||||
real_glGetShaderiv()(shader, REAL_GL_COMPILE_STATUS, &is_compiled);
|
||||
if (!is_compiled) {
|
||||
ERR("Failed To Compile %s Shader", name);
|
||||
}
|
||||
}
|
||||
static GLuint compile_shader(const char *vertex_shader_text, const char *fragment_shader_text) {
|
||||
// Vertex Shader
|
||||
const GLuint vertex_shader = real_glCreateShader()(REAL_GL_VERTEX_SHADER);
|
||||
real_glShaderSource()(vertex_shader, 1, &vertex_shader_text, NULL);
|
||||
real_glCompileShader()(vertex_shader);
|
||||
log_shader(vertex_shader, "Vertex");
|
||||
|
||||
// Fragment Shader
|
||||
const GLuint fragment_shader = real_glCreateShader()(REAL_GL_FRAGMENT_SHADER);
|
||||
real_glShaderSource()(fragment_shader, 1, &fragment_shader_text, NULL);
|
||||
real_glCompileShader()(fragment_shader);
|
||||
log_shader(fragment_shader, "Fragment");
|
||||
|
||||
// Link
|
||||
GLuint program = real_glCreateProgram()();
|
||||
real_glAttachShader()(program, vertex_shader);
|
||||
real_glAttachShader()(program, fragment_shader);
|
||||
real_glLinkProgram()(program);
|
||||
|
||||
// Return
|
||||
return program;
|
||||
}
|
||||
|
||||
// Shader
|
||||
static GLuint get_shader() {
|
||||
static GLuint program = 0;
|
||||
if (program == 0) {
|
||||
static const char *vertex_shader_text =
|
||||
"#version 100\n"
|
||||
"precision mediump float;\n"
|
||||
// Matrices
|
||||
"uniform mat4 u_projection;\n"
|
||||
"uniform mat4 u_model_view;\n"
|
||||
"uniform mat4 u_texture;\n"
|
||||
// Texture
|
||||
"attribute vec3 a_vertex_coords;\n"
|
||||
"attribute vec2 a_texture_coords;\n"
|
||||
"varying vec4 v_texture_pos;\n"
|
||||
// Color
|
||||
"attribute vec4 a_color;\n"
|
||||
"varying vec4 v_color;\n"
|
||||
// Fog
|
||||
"varying vec4 v_fog_eye_position;\n"
|
||||
// Main
|
||||
"void main() {\n"
|
||||
" v_texture_pos = u_texture * vec4(a_texture_coords.xy, 0.0, 1.0);\n"
|
||||
" gl_Position = u_projection * u_model_view * vec4(a_vertex_coords.xyz, 1.0);\n"
|
||||
" v_color = a_color;\n"
|
||||
" v_fog_eye_position = u_model_view * vec4(a_vertex_coords.xyz, 1.0);\n"
|
||||
"}";
|
||||
static const char *fragment_shader_text =
|
||||
"#version 100\n"
|
||||
"precision mediump float;\n"
|
||||
// Texture
|
||||
"uniform bool u_has_texture;"
|
||||
"uniform sampler2D u_texture_unit;\n"
|
||||
// Color
|
||||
"varying vec4 v_color;\n"
|
||||
"varying vec4 v_texture_pos;\n"
|
||||
// Alpha Test
|
||||
"uniform bool u_alpha_test;\n"
|
||||
// Fog
|
||||
"uniform bool u_fog;\n"
|
||||
"uniform vec4 u_fog_color;\n"
|
||||
"uniform bool u_fog_is_linear;\n"
|
||||
"uniform float u_fog_start;\n"
|
||||
"uniform float u_fog_end;\n"
|
||||
"varying vec4 v_fog_eye_position;\n"
|
||||
// Main
|
||||
"void main(void) {\n"
|
||||
" gl_FragColor = v_color;\n"
|
||||
" if (u_has_texture) {\n"
|
||||
" gl_FragColor *= texture2D(u_texture_unit, v_texture_pos.xy);\n"
|
||||
" }\n"
|
||||
" if (u_alpha_test && gl_FragColor.a <= 0.1) {\n"
|
||||
" discard;\n"
|
||||
" }\n"
|
||||
" if (u_fog) {\n"
|
||||
" float fog_factor;\n"
|
||||
" if (u_fog_is_linear) {\n"
|
||||
" fog_factor = (u_fog_end - length(v_fog_eye_position)) / (u_fog_end - u_fog_start);\n"
|
||||
" } else {\n"
|
||||
" fog_factor = exp(-u_fog_start * length(v_fog_eye_position));\n"
|
||||
" }\n"
|
||||
" gl_FragColor = mix(gl_FragColor, u_fog_color, 1.0 - clamp(fog_factor, 0.0, 1.0));\n"
|
||||
" }\n"
|
||||
"}";
|
||||
program = compile_shader(vertex_shader_text, fragment_shader_text);
|
||||
}
|
||||
return program;
|
||||
}
|
||||
|
||||
// Shader Switching
|
||||
static void use_shader(GLuint program) {
|
||||
static GLuint current_program = 0;
|
||||
if (current_program != program) {
|
||||
real_glUseProgram()(program);
|
||||
current_program = program;
|
||||
}
|
||||
}
|
||||
|
||||
// Array Pointer Drawing
|
||||
GL_FUNC(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count));
|
||||
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
|
||||
// Verify
|
||||
if (gl_state.array_pointers.vertex.size != 3 || !gl_state.array_pointers.vertex.enabled || gl_state.array_pointers.vertex.type != GL_FLOAT) {
|
||||
ERR("Unsupported Vertex Conifguration");
|
||||
}
|
||||
|
||||
// Check Mode
|
||||
int use_color_pointer = gl_state.array_pointers.color.enabled;
|
||||
if (use_color_pointer && (gl_state.array_pointers.color.size != 4 || gl_state.array_pointers.color.type != GL_UNSIGNED_BYTE)) {
|
||||
ERR("Unsupported Color Conifguration");
|
||||
}
|
||||
int use_texture = gl_state.texture_2d && gl_state.array_pointers.tex_coord.enabled;
|
||||
if (use_texture && (gl_state.array_pointers.tex_coord.size != 2 || gl_state.array_pointers.tex_coord.type != GL_FLOAT)) {
|
||||
ERR("Unsupported Texture Conifguration");
|
||||
}
|
||||
|
||||
// Load Shader
|
||||
GLuint program = get_shader();
|
||||
use_shader(program);
|
||||
|
||||
// Projection Matrix
|
||||
GLint u_projection_handle = real_glGetUniformLocation()(program, "u_projection");
|
||||
matrix_t *p = &gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i];
|
||||
real_glUniformMatrix4fv()(u_projection_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Model View Matrix
|
||||
GLint u_model_view_handle = real_glGetUniformLocation()(program, "u_model_view");
|
||||
p = &gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
|
||||
real_glUniformMatrix4fv()(u_model_view_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Has Texture
|
||||
GLint u_has_texture_handle = real_glGetUniformLocation()(program, "u_has_texture"); \
|
||||
real_glUniform1i()(u_has_texture_handle, use_texture); \
|
||||
|
||||
// Texture Matrix
|
||||
GLint u_texture_handle = real_glGetUniformLocation()(program, "u_texture");
|
||||
p = &gl_state.matrix_stacks.texture.stack[gl_state.matrix_stacks.texture.i];
|
||||
real_glUniformMatrix4fv()(u_texture_handle, 1, 0, (GLfloat *) &p->data[0][0]);
|
||||
|
||||
// Texture Unit
|
||||
GLint u_texture_unit_handle = real_glGetUniformLocation()(program, "u_texture_unit");
|
||||
real_glUniform1i()(u_texture_unit_handle, 0);
|
||||
|
||||
// Alpha Test
|
||||
GLint u_alpha_test_handle = real_glGetUniformLocation()(program, "u_alpha_test");
|
||||
real_glUniform1i()(u_alpha_test_handle, gl_state.alpha_test);
|
||||
|
||||
// Color
|
||||
GLint a_color_handle = real_glGetAttribLocation()(program, "a_color");
|
||||
if (use_color_pointer) {
|
||||
real_glVertexAttribPointer()(a_color_handle, gl_state.array_pointers.color.size, gl_state.array_pointers.color.type, 1, gl_state.array_pointers.color.stride, gl_state.array_pointers.color.pointer);
|
||||
real_glEnableVertexAttribArray()(a_color_handle);
|
||||
} else {
|
||||
real_glVertexAttrib4f()(a_color_handle, gl_state.color.red, gl_state.color.green, gl_state.color.blue, gl_state.color.alpha);
|
||||
}
|
||||
|
||||
// Fog
|
||||
GLint u_fog_handle = real_glGetUniformLocation()(program, "u_fog");
|
||||
real_glUniform1i()(u_fog_handle, gl_state.fog.enabled);
|
||||
if (gl_state.fog.enabled) {
|
||||
GLint u_fog_color_handle = real_glGetUniformLocation()(program, "u_fog_color");
|
||||
real_glUniform4f()(u_fog_color_handle, gl_state.fog.color[0], gl_state.fog.color[1], gl_state.fog.color[2], gl_state.fog.color[3]);
|
||||
GLint u_fog_is_linear_handle = real_glGetUniformLocation()(program, "u_fog_is_linear");
|
||||
real_glUniform1i()(u_fog_is_linear_handle, gl_state.fog.mode == GL_LINEAR);
|
||||
GLint u_fog_start_handle = real_glGetUniformLocation()(program, "u_fog_start");
|
||||
real_glUniform1f()(u_fog_start_handle, gl_state.fog.start);
|
||||
GLint u_fog_end_handle = real_glGetUniformLocation()(program, "u_fog_end");
|
||||
real_glUniform1f()(u_fog_end_handle, gl_state.fog.end);
|
||||
}
|
||||
|
||||
// Vertices
|
||||
GLint a_vertex_coords_handle = real_glGetAttribLocation()(program, "a_vertex_coords");
|
||||
real_glVertexAttribPointer()(a_vertex_coords_handle, gl_state.array_pointers.vertex.size, gl_state.array_pointers.vertex.type, 0, gl_state.array_pointers.vertex.stride, gl_state.array_pointers.vertex.pointer);
|
||||
real_glEnableVertexAttribArray()(a_vertex_coords_handle);
|
||||
|
||||
// Texture Coordinates
|
||||
GLint a_texture_coords_handle = real_glGetAttribLocation()(program, "a_texture_coords");
|
||||
if (use_texture) {
|
||||
real_glVertexAttribPointer()(a_texture_coords_handle, gl_state.array_pointers.tex_coord.size, gl_state.array_pointers.tex_coord.type, 0, gl_state.array_pointers.tex_coord.stride, gl_state.array_pointers.tex_coord.pointer);
|
||||
real_glEnableVertexAttribArray()(a_texture_coords_handle);
|
||||
} else {
|
||||
real_glVertexAttrib3f()(a_texture_coords_handle, 0, 0, 0);
|
||||
}
|
||||
|
||||
// Draw
|
||||
real_glDrawArrays()(mode, first, count);
|
||||
|
||||
// Cleanup
|
||||
if (use_color_pointer) {
|
||||
real_glDisableVertexAttribArray()(a_color_handle);
|
||||
}
|
||||
real_glDisableVertexAttribArray()(a_vertex_coords_handle);
|
||||
if (use_texture) {
|
||||
real_glDisableVertexAttribArray()(a_texture_coords_handle);
|
||||
}
|
||||
}
|
132
media-layer/gles/src/compatibility-layer/matrix.c
Normal file
132
media-layer/gles/src/compatibility-layer/matrix.c
Normal file
@ -0,0 +1,132 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "state.h"
|
||||
#include "passthrough.h"
|
||||
|
||||
// Matrix Common
|
||||
static void matrix_copy(matrix_t *src, matrix_t *dst) {
|
||||
memcpy((void *) dst->data, (void *) src->data, MATRIX_DATA_SIZE);
|
||||
}
|
||||
|
||||
// Identity Matrix
|
||||
static matrix_t identity_matrix = {
|
||||
.data = {
|
||||
{1, 0, 0, 0},
|
||||
{0, 1, 0, 0},
|
||||
{0, 0, 1, 0},
|
||||
{0, 0, 0, 1}
|
||||
}
|
||||
};
|
||||
static void init_matrix_stack(matrix_stack_t *stack) {
|
||||
matrix_copy(&identity_matrix, &stack->stack[0]);
|
||||
}
|
||||
__attribute__((constructor)) static void init_matrix_stacks() {
|
||||
init_matrix_stack(&gl_state.matrix_stacks.model_view);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.projection);
|
||||
init_matrix_stack(&gl_state.matrix_stacks.texture);
|
||||
}
|
||||
|
||||
// Matrix Mode
|
||||
static matrix_stack_t *get_matrix_stack() {
|
||||
switch (gl_state.matrix_stacks.mode) {
|
||||
case GL_MODELVIEW: {
|
||||
return &gl_state.matrix_stacks.model_view;
|
||||
}
|
||||
case GL_PROJECTION: {
|
||||
return &gl_state.matrix_stacks.projection;
|
||||
}
|
||||
case GL_TEXTURE: {
|
||||
return &gl_state.matrix_stacks.texture;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Matrix Mode: %i", gl_state.matrix_stacks.mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Matrix Functions
|
||||
void glMatrixMode(GLenum mode) {
|
||||
gl_state.matrix_stacks.mode = mode;
|
||||
}
|
||||
void glPopMatrix() {
|
||||
get_matrix_stack()->i--;
|
||||
}
|
||||
void glLoadIdentity() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&identity_matrix, &stack->stack[stack->i]);
|
||||
}
|
||||
void glPushMatrix() {
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_copy(&stack->stack[stack->i], &stack->stack[stack->i + 1]);
|
||||
stack->i++;
|
||||
}
|
||||
void glMultMatrixf(const GLfloat *m) {
|
||||
matrix_t new_matrix;
|
||||
matrix_stack_t *stack = get_matrix_stack();
|
||||
matrix_t *current_matrix = &stack->stack[stack->i];
|
||||
for (int x = 0; x < MATRIX_SIZE; x++) {
|
||||
for (int y = 0; y < MATRIX_SIZE; y++) {
|
||||
GLfloat result = 0;
|
||||
for (int i = 0; i < MATRIX_SIZE; i++) {
|
||||
result += (current_matrix->data[i][y] * m[(x * MATRIX_SIZE) + i]);
|
||||
}
|
||||
new_matrix.data[x][y] = result;
|
||||
}
|
||||
}
|
||||
matrix_copy(&new_matrix, current_matrix);
|
||||
}
|
||||
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
x, 0, 0, 0,
|
||||
0, y, 0, 0,
|
||||
0, 0, z, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
|
||||
GLfloat m[] = {
|
||||
1, 0, 0, 0,
|
||||
0, 1, 0, 0,
|
||||
0, 0, 1, 0,
|
||||
x, y, z, 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) {
|
||||
GLfloat m[] = {
|
||||
(2.f / (right - left)), 0, 0, 0,
|
||||
0, (2.f / (top - bottom)), 0, 0,
|
||||
0, 0, (-2.f / (far - near)), 0,
|
||||
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), 1
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
||||
#define DEG2RAD (M_PI / 180.f)
|
||||
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
|
||||
// Normalize
|
||||
GLfloat length = sqrtf((x * x) + (y * y) + (z * z));
|
||||
x /= length;
|
||||
y /= length;
|
||||
z /= length;
|
||||
|
||||
// Values
|
||||
GLfloat angle_radians = angle * DEG2RAD;
|
||||
GLfloat c = cosf(angle_radians);
|
||||
GLfloat s = sinf(angle_radians);
|
||||
GLfloat x2 = x * x;
|
||||
GLfloat y2 = y * y;
|
||||
GLfloat z2 = z * z;
|
||||
|
||||
// Multiply
|
||||
GLfloat m[] = {
|
||||
x2 * (1.f - c) + c, (x * y) * (1.f - c) + (z * s), (x * z) * (1.f - c) - (y * s), 0,
|
||||
(x * y) * (1.f - c) - (z * s), y2 * (1.f - c) + c, (y * z) * (1.f - c) + (x * s), 0,
|
||||
(x * z) * (1.f - c) + (y * s), (y * z) * (1.f - c) - (x * s), z2 * (1.f - c) + c, 0,
|
||||
0, 0, 0, 1.f
|
||||
};
|
||||
glMultMatrixf(m);
|
||||
}
|
9
media-layer/gles/src/compatibility-layer/matrix.h
Normal file
9
media-layer/gles/src/compatibility-layer/matrix.h
Normal file
@ -0,0 +1,9 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
// Matrix Common
|
||||
#define MATRIX_SIZE 4
|
||||
#define MATRIX_DATA_SIZE (sizeof (float) * MATRIX_SIZE * MATRIX_SIZE)
|
||||
// OpenGL Matricies Are Column-Major
|
||||
typedef struct {
|
||||
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
|
||||
} matrix_t;
|
113
media-layer/gles/src/compatibility-layer/passthrough.c
Normal file
113
media-layer/gles/src/compatibility-layer/passthrough.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include <GLES/gl.h>
|
||||
|
||||
#include "passthrough.h"
|
||||
|
||||
// Simple v1.1 -> v2.0 Passthrough Functions
|
||||
GL_FUNC(glLineWidth, void, (GLfloat width));
|
||||
void glLineWidth(GLfloat width) {
|
||||
real_glLineWidth()(width);
|
||||
}
|
||||
GL_FUNC(glBlendFunc, void, (GLenum sfactor, GLenum dfactor));
|
||||
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
|
||||
real_glBlendFunc()(sfactor, dfactor);
|
||||
}
|
||||
GL_FUNC(glClear, void, (GLbitfield mask));
|
||||
void glClear(GLbitfield mask) {
|
||||
real_glClear()(mask);
|
||||
}
|
||||
GL_FUNC(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage));
|
||||
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
|
||||
real_glBufferData()(target, size, data, usage);
|
||||
}
|
||||
GL_FUNC(glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glScissor()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glTexParameteri, void, (GLenum target, GLenum pname, GLint param));
|
||||
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
real_glTexParameteri()(target, pname, param);
|
||||
}
|
||||
GL_FUNC(glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexImage2D()(target, level, internalformat, width, height, border, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glPolygonOffset, void, (GLfloat factor, GLfloat units));
|
||||
void glPolygonOffset(GLfloat factor, GLfloat units) {
|
||||
real_glPolygonOffset()(factor, units);
|
||||
}
|
||||
GL_FUNC(glDepthRangef, void, (GLclampf near, GLclampf far));
|
||||
void glDepthRangef(GLclampf near, GLclampf far) {
|
||||
real_glDepthRangef()(near, far);
|
||||
}
|
||||
GL_FUNC(glDepthFunc, void, (GLenum func));
|
||||
void glDepthFunc(GLenum func) {
|
||||
real_glDepthFunc()(func);
|
||||
}
|
||||
GL_FUNC(glBindBuffer, void, (GLenum target, GLuint buffer));
|
||||
void glBindBuffer(GLenum target, GLuint buffer) {
|
||||
real_glBindBuffer()(target, buffer);
|
||||
}
|
||||
GL_FUNC(glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
|
||||
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
|
||||
real_glClearColor()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glDepthMask, void, (GLboolean flag));
|
||||
void glDepthMask(GLboolean flag) {
|
||||
real_glDepthMask()(flag);
|
||||
}
|
||||
GL_FUNC(glHint, void, (GLenum target, GLenum mode));
|
||||
void glHint(GLenum target, GLenum mode) {
|
||||
if (target != GL_PERSPECTIVE_CORRECTION_HINT) {
|
||||
real_glHint()(target, mode);
|
||||
}
|
||||
}
|
||||
GL_FUNC(glDeleteBuffers, void, (GLsizei n, const GLuint *buffers));
|
||||
void glDeleteBuffers(GLsizei n, const GLuint *buffers) {
|
||||
real_glDeleteBuffers()(n, buffers);
|
||||
}
|
||||
GL_FUNC(glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha));
|
||||
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
|
||||
real_glColorMask()(red, green, blue, alpha);
|
||||
}
|
||||
GL_FUNC(glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels));
|
||||
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
|
||||
real_glTexSubImage2D()(target, level, xoffset, yoffset, width, height, format, type, pixels);
|
||||
}
|
||||
GL_FUNC(glGenTextures, void, (GLsizei n, GLuint *textures));
|
||||
void glGenTextures(GLsizei n, GLuint *textures) {
|
||||
real_glGenTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glDeleteTextures, void, (GLsizei n, const GLuint *textures));
|
||||
void glDeleteTextures(GLsizei n, const GLuint *textures) {
|
||||
real_glDeleteTextures()(n, textures);
|
||||
}
|
||||
GL_FUNC(glBindTexture, void, (GLenum target, GLuint texture));
|
||||
void glBindTexture(GLenum target, GLuint texture) {
|
||||
real_glBindTexture()(target, texture);
|
||||
}
|
||||
GL_FUNC(glCullFace, void, (GLenum mode));
|
||||
void glCullFace(GLenum mode) {
|
||||
real_glCullFace()(mode);
|
||||
}
|
||||
GL_FUNC(glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height));
|
||||
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
real_glViewport()(x, y, width, height);
|
||||
}
|
||||
GL_FUNC(glIsEnabled, GLboolean, (GLenum cap));
|
||||
GLboolean glIsEnabled(GLenum cap) {
|
||||
return real_glIsEnabled()(cap);
|
||||
}
|
||||
GL_FUNC(glGetIntegerv, void, (GLenum pname, GLint *data));
|
||||
void glGetIntegerv(GLenum pname, GLint *data) {
|
||||
real_glGetIntegerv()(pname, data);
|
||||
}
|
||||
GL_FUNC(glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data));
|
||||
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data) {
|
||||
real_glReadPixels()(x, y, width, height, format, type, data);
|
||||
}
|
||||
void glShadeModel(__attribute__((unused)) GLenum mode) {
|
||||
// Do Nothing
|
||||
}
|
||||
void glNormal3f(__attribute__((unused)) GLfloat nx, __attribute__((unused)) GLfloat ny, __attribute__((unused)) GLfloat nz) {
|
||||
// Do Nothing
|
||||
}
|
19
media-layer/gles/src/compatibility-layer/passthrough.h
Normal file
19
media-layer/gles/src/compatibility-layer/passthrough.h
Normal file
@ -0,0 +1,19 @@
|
||||
#define GLFW_INCLUDE_NONE
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
// Load GL Function
|
||||
#define GL_FUNC(name, return_type, args) \
|
||||
typedef return_type (*real_##name##_t)args; \
|
||||
\
|
||||
__attribute__((__unused__)) static real_##name##_t real_##name() { \
|
||||
static real_##name##_t func = NULL; \
|
||||
if (!func) { \
|
||||
func = (real_##name##_t) glfwGetProcAddress(#name); \
|
||||
if (!func) { \
|
||||
ERR("Error Resolving GL Symbol: " #name ": %s", dlerror()); \
|
||||
} \
|
||||
} \
|
||||
return func; \
|
||||
}
|
178
media-layer/gles/src/compatibility-layer/state.c
Normal file
178
media-layer/gles/src/compatibility-layer/state.c
Normal file
@ -0,0 +1,178 @@
|
||||
#include <libreborn/libreborn.h>
|
||||
|
||||
#include "state.h"
|
||||
#include "passthrough.h"
|
||||
|
||||
// GL State
|
||||
gl_state_t gl_state = {
|
||||
.color = {
|
||||
.red = 1,
|
||||
.green = 1,
|
||||
.blue = 1,
|
||||
.alpha = 1
|
||||
},
|
||||
.matrix_stacks = {
|
||||
.mode = GL_MODELVIEW
|
||||
},
|
||||
.alpha_test = 0,
|
||||
.texture_2d = 0,
|
||||
.fog = {
|
||||
.enabled = 0,
|
||||
.mode = GL_LINEAR,
|
||||
.color = {0, 0, 0, 0},
|
||||
.start = 0,
|
||||
.end = 1
|
||||
}
|
||||
};
|
||||
|
||||
// Change Color
|
||||
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
||||
gl_state.color.red = red;
|
||||
gl_state.color.green = green;
|
||||
gl_state.color.blue = blue;
|
||||
gl_state.color.alpha = alpha;
|
||||
}
|
||||
|
||||
// Array Pointer Storage
|
||||
#define ARRAY_POINTER_FUNC(func, name) \
|
||||
void func(GLint size, GLenum type, GLsizei stride, const void *pointer) { \
|
||||
gl_state.array_pointers.name.size = size; \
|
||||
gl_state.array_pointers.name.type = type; \
|
||||
gl_state.array_pointers.name.stride = stride; \
|
||||
gl_state.array_pointers.name.pointer = pointer; \
|
||||
}
|
||||
ARRAY_POINTER_FUNC(glVertexPointer, vertex)
|
||||
ARRAY_POINTER_FUNC(glColorPointer, color)
|
||||
ARRAY_POINTER_FUNC(glTexCoordPointer, tex_coord)
|
||||
static array_pointer_t *get_array_pointer(GLenum array) {
|
||||
switch (array) {
|
||||
case GL_VERTEX_ARRAY: {
|
||||
return &gl_state.array_pointers.vertex;
|
||||
}
|
||||
case GL_COLOR_ARRAY: {
|
||||
return &gl_state.array_pointers.color;
|
||||
}
|
||||
case GL_TEXTURE_COORD_ARRAY: {
|
||||
return &gl_state.array_pointers.tex_coord;
|
||||
}
|
||||
default: {
|
||||
ERR("Unsupported Array Pointer: %i", array);
|
||||
}
|
||||
}
|
||||
}
|
||||
void glEnableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 1;
|
||||
}
|
||||
void glDisableClientState(GLenum array) {
|
||||
get_array_pointer(array)->enabled = 0;
|
||||
}
|
||||
|
||||
// Enable/Disable State
|
||||
GL_FUNC(glEnable, void, (GLenum cap));
|
||||
void glEnable(GLenum cap) {
|
||||
switch (cap) {
|
||||
case GL_ALPHA_TEST: {
|
||||
gl_state.alpha_test = 1;
|
||||
break;
|
||||
}
|
||||
case GL_TEXTURE_2D: {
|
||||
gl_state.texture_2d = 1;
|
||||
break;
|
||||