This repository was archived by the owner on Sep 23, 2025. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Expand file tree
/
Copy pathosm_bridge.c
More file actions
148 lines (131 loc) · 5.44 KB
/
Copy pathosm_bridge.c
File metadata and controls
148 lines (131 loc) · 5.44 KB
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//
// Created by maks on 18.10.2023.
//
#include <malloc.h>
#include <string.h>
#include <environ/environ.h>
#include <android/log.h>
#include "osm_bridge.h"
static const char* g_LogTag = "GLBridge";
static __thread osm_render_window_t* currentBundle;
// a tiny buffer for rendering when there's nowhere t render
static char no_render_buffer[4];
static bool hasSetNoRendererBuffer = false;
// Its not in a .h file because it is not supposed to be used outsife of this file.
void setNativeWindowSwapInterval(struct ANativeWindow* nativeWindow, int swapInterval);
bool osm_init() {
dlsym_OSMesa();
return true; // no more specific initialization required
}
osm_render_window_t* osm_get_current() {
return currentBundle;
}
osm_render_window_t* osm_init_context(osm_render_window_t* share) {
osm_render_window_t* render_window = malloc(sizeof(osm_render_window_t));
if(render_window == NULL) return NULL;
memset(render_window, 0, sizeof(osm_render_window_t));
OSMesaContext osmesa_share = NULL;
if(share != NULL) osmesa_share = share->context;
OSMesaContext context = OSMesaCreateContext_p(GL_RGBA, osmesa_share);
if(context == NULL) {
free(render_window);
return NULL;
}
render_window->context = context;
return render_window;
}
void osm_set_no_render_buffer(ANativeWindow_Buffer* buffer) {
buffer->bits = &no_render_buffer;
buffer->width = 1;
buffer->height = 1;
buffer->stride = 0;
}
void osm_swap_surfaces(osm_render_window_t* bundle) {
if(bundle->nativeSurface != NULL && bundle->newNativeSurface != bundle->nativeSurface) {
if(!bundle->disable_rendering) {
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Unlocking for cleanup...");
ANativeWindow_unlockAndPost(bundle->nativeSurface);
}
ANativeWindow_release(bundle->nativeSurface);
}
if(bundle->newNativeSurface != NULL) {
__android_log_print(ANDROID_LOG_ERROR, g_LogTag, "Switching to new native surface");
bundle->nativeSurface = bundle->newNativeSurface;
bundle->newNativeSurface = NULL;
ANativeWindow_acquire(bundle->nativeSurface);
ANativeWindow_setBuffersGeometry(bundle->nativeSurface, 0, 0, WINDOW_FORMAT_RGBX_8888);
bundle->disable_rendering = false;
return;
}else {
__android_log_print(ANDROID_LOG_ERROR, g_LogTag,
"No new native surface, switching to dummy framebuffer");
bundle->nativeSurface = NULL;
osm_set_no_render_buffer(&bundle->buffer);
bundle->disable_rendering = true;
}
}
void osm_release_window() {
currentBundle->newNativeSurface = NULL;
osm_swap_surfaces(currentBundle);
}
void osm_apply_current_ll() {
ANativeWindow_Buffer* buffer = ¤tBundle->buffer;
OSMesaMakeCurrent_p(currentBundle->context, buffer->bits, GL_UNSIGNED_BYTE, buffer->width, buffer->height);
if(buffer->stride != currentBundle->last_stride)
OSMesaPixelStore_p(OSMESA_ROW_LENGTH, buffer->stride);
currentBundle->last_stride = buffer->stride;
}
void osm_make_current(osm_render_window_t* bundle) {
if(bundle == NULL) {
//technically this does nothing as its not possible to unbind a context in OSMesa
OSMesaMakeCurrent_p(NULL, NULL, 0, 0, 0);
currentBundle = NULL;
return;
}
bool hasSetMainWindow = false;
currentBundle = bundle;
if(pojav_environ->mainWindowBundle == NULL) {
pojav_environ->mainWindowBundle = (basic_render_window_t*) bundle;
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is now %p", pojav_environ->mainWindowBundle);
pojav_environ->mainWindowBundle->newNativeSurface = pojav_environ->pojavWindow;
hasSetMainWindow = true;
}
if(bundle->nativeSurface == NULL) {
//prepare the buffer for our first render!
osm_swap_surfaces(bundle);
if(hasSetMainWindow) pojav_environ->mainWindowBundle->state = STATE_RENDERER_ALIVE;
}
if (!hasSetNoRendererBuffer)
{
osm_set_no_render_buffer(&bundle->buffer);
hasSetNoRendererBuffer = true;
}
osm_apply_current_ll();
OSMesaPixelStore_p(OSMESA_Y_UP,0);
}
void osm_swap_buffers() {
if(currentBundle->state == STATE_RENDERER_NEW_WINDOW) {
osm_swap_surfaces(currentBundle);
currentBundle->state = STATE_RENDERER_ALIVE;
}
if(currentBundle->nativeSurface != NULL && !currentBundle->disable_rendering)
if(ANativeWindow_lock(currentBundle->nativeSurface, ¤tBundle->buffer, NULL) != 0)
osm_release_window();
osm_apply_current_ll();
glFinish_p(); // this will force osmesa to write the last rendered image into the buffer
if(currentBundle->nativeSurface != NULL && !currentBundle->disable_rendering)
if(ANativeWindow_unlockAndPost(currentBundle->nativeSurface) != 0)
osm_release_window();
}
void osm_setup_window() {
if(pojav_environ->mainWindowBundle != NULL) {
__android_log_print(ANDROID_LOG_INFO, g_LogTag, "Main window bundle is not NULL, changing state");
pojav_environ->mainWindowBundle->state = STATE_RENDERER_NEW_WINDOW;
pojav_environ->mainWindowBundle->newNativeSurface = pojav_environ->pojavWindow;
}
}
void osm_swap_interval(int swapInterval) {
if(pojav_environ->mainWindowBundle != NULL && pojav_environ->mainWindowBundle->nativeSurface != NULL) {
setNativeWindowSwapInterval(pojav_environ->mainWindowBundle->nativeSurface, swapInterval);
}
}