some renderer improvements
This commit is contained in:
parent
3b6336f54b
commit
3c5fee04da
@ -1,18 +0,0 @@
|
|||||||
Xwayland depends on these Wayland interfaces:
|
|
||||||
1. wl_display (libwayland builtin)
|
|
||||||
2. wl_registry (libwayland builtin)
|
|
||||||
3. wl_shm (libwayland builtin)
|
|
||||||
4. wl_shm_pool (libwayland builtin)
|
|
||||||
5. wl_compositor
|
|
||||||
6. wl_shell
|
|
||||||
7. wl_region
|
|
||||||
8. wl_surface
|
|
||||||
9. wl_shell_surface
|
|
||||||
10. wl_seat
|
|
||||||
11. wl_pointer
|
|
||||||
12. wl_keyboard
|
|
||||||
13. wl_drm (glamor only)
|
|
||||||
14. xdg_surface
|
|
||||||
15. xdg_shell
|
|
||||||
16. zwp_relative_pointer_manager_v1
|
|
||||||
17. zwp_pointer_constraints_v1
|
|
34
log.h
Normal file
34
log.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifdef __ANDROID__
|
||||||
|
#include <android/log.h>
|
||||||
|
|
||||||
|
#ifndef LOG_TAG
|
||||||
|
#define LOG_TAG "XLorie"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LOG(prio, ...) __android_log_print(prio, LOG_TAG, __VA_ARGS__)
|
||||||
|
|
||||||
|
#define LOGI(...) LOG(ANDROID_LOG_INFO, __VA_ARGS__)
|
||||||
|
#define LOGW(...) LOG(ANDROID_LOG_WARN, __VA_ARGS__)
|
||||||
|
#define LOGD(...) LOG(ANDROID_LOG_DEBUG, __VA_ARGS__)
|
||||||
|
#define LOGV(...) LOG(ANDROID_LOG_VERBOSE, __VA_ARGS__)
|
||||||
|
#define LOGE(...) LOG(ANDROID_LOG_ERROR, __VA_ARGS__)
|
||||||
|
#define LOGF(...) LOG(ANDROID_LOG_FATAL, __VA_ARGS__)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define LOG(prio, ...) { printf(prio __VA_ARGS__); printf("\n"); }
|
||||||
|
|
||||||
|
#define LOGI(...) LOG("I: " , __VA_ARGS__)
|
||||||
|
#define LOGW(...) LOG("W: " , __VA_ARGS__)
|
||||||
|
#define LOGD(...) LOG("D: " , __VA_ARGS__)
|
||||||
|
#define LOGV(...) LOG("V: " , __VA_ARGS__)
|
||||||
|
#define LOGE(...) LOG("E: " , __VA_ARGS__)
|
||||||
|
#define LOGF(...) LOG("F: " , __VA_ARGS__)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#ifdef DBG
|
||||||
|
#undef DBG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DBG LOGD("Here! %s %d", __FILE__, __LINE__)
|
150
main.c
150
main.c
@ -13,10 +13,31 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <sys/time.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
|
#include "renderer.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
#define static
|
bool trace_funcs = false;
|
||||||
|
|
||||||
|
void __attribute__((no_instrument_function))
|
||||||
|
__cyg_profile_func_enter (void *func, void *caller) {
|
||||||
|
if (!trace_funcs) return;
|
||||||
|
Dl_info info;
|
||||||
|
if (dladdr(func, &info))
|
||||||
|
LOGD ("enter %p [%s] %s\n", func, (info.dli_fname) ? info.dli_fname : "?", info.dli_sname ? info.dli_sname : "?");
|
||||||
|
}
|
||||||
|
void __attribute__((no_instrument_function))
|
||||||
|
__cyg_profile_func_exit (void *func, void *caller) {
|
||||||
|
if (!trace_funcs) return;
|
||||||
|
Dl_info info;
|
||||||
|
if (dladdr(func, &info))
|
||||||
|
LOGD ("leave %p [%s] %s\n", func, (info.dli_fname) ? info.dli_fname : "?", info.dli_sname ? info.dli_sname : "?");
|
||||||
|
}
|
||||||
|
|
||||||
|
#define static // backtrace do not report static function names
|
||||||
|
|
||||||
void handler(int sig) {
|
void handler(int sig) {
|
||||||
void *array[10];
|
void *array[10];
|
||||||
@ -33,7 +54,7 @@ void handler(int sig) {
|
|||||||
|
|
||||||
#define BINDFUNC(interface, version, implementation) \
|
#define BINDFUNC(interface, version, implementation) \
|
||||||
static void interface##_bind (struct wl_client *client, void *data, uint32_t _version, uint32_t id) { \
|
static void interface##_bind (struct wl_client *client, void *data, uint32_t _version, uint32_t id) { \
|
||||||
printf ("bind: " #interface "\n"); \
|
LOGD("bind: " #interface); \
|
||||||
struct wl_resource *resource = wl_resource_create (client, &interface##_interface, version, id); \
|
struct wl_resource *resource = wl_resource_create (client, &interface##_interface, version, id); \
|
||||||
if (resource == NULL) { \
|
if (resource == NULL) { \
|
||||||
wl_client_post_no_memory(client); \
|
wl_client_post_no_memory(client); \
|
||||||
@ -44,6 +65,7 @@ void handler(int sig) {
|
|||||||
|
|
||||||
struct lorie_composiror {
|
struct lorie_composiror {
|
||||||
struct wl_display *display;
|
struct wl_display *display;
|
||||||
|
struct wl_resource *wl_output;
|
||||||
struct wl_list clients;
|
struct wl_list clients;
|
||||||
struct wl_list surfaces;
|
struct wl_list surfaces;
|
||||||
struct wl_list shell_surfaces;
|
struct wl_list shell_surfaces;
|
||||||
@ -56,6 +78,8 @@ struct lorie_composiror {
|
|||||||
bool redraw_needed;
|
bool redraw_needed;
|
||||||
|
|
||||||
uint32_t width, height;
|
uint32_t width, height;
|
||||||
|
|
||||||
|
struct renderer* renderer;
|
||||||
} c = {0};
|
} c = {0};
|
||||||
|
|
||||||
struct client {
|
struct client {
|
||||||
@ -82,10 +106,11 @@ struct surface {
|
|||||||
struct wl_resource *buffer;
|
struct wl_resource *buffer;
|
||||||
struct wl_resource *frame_callback;
|
struct wl_resource *frame_callback;
|
||||||
//int x, y;
|
//int x, y;
|
||||||
//struct texture texture;
|
struct texture *texture;
|
||||||
struct client *client;
|
struct client *client;
|
||||||
struct shell_surface *shell_surface;
|
struct shell_surface *shell_surface;
|
||||||
struct wl_list link;
|
struct wl_list link;
|
||||||
|
uint32_t width, height;
|
||||||
bool entered;
|
bool entered;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -115,11 +140,34 @@ void *null = NULL;
|
|||||||
static void surface_attach (struct wl_client *client, struct wl_resource *resource, struct wl_resource *buffer, int32_t x, int32_t y) {
|
static void surface_attach (struct wl_client *client, struct wl_resource *resource, struct wl_resource *buffer, int32_t x, int32_t y) {
|
||||||
struct surface *surface = wl_resource_get_user_data (resource);
|
struct surface *surface = wl_resource_get_user_data (resource);
|
||||||
surface->buffer = buffer;
|
surface->buffer = buffer;
|
||||||
//c.toplevel = surface;
|
|
||||||
|
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
||||||
|
if (shm_buffer == NULL) {
|
||||||
|
surface->width = surface->height = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
surface->width = wl_shm_buffer_get_width (shm_buffer);
|
||||||
|
surface->height = wl_shm_buffer_get_height (shm_buffer);
|
||||||
|
|
||||||
|
if (!surface->texture ||
|
||||||
|
surface->texture->width != surface->width ||
|
||||||
|
surface->texture->height != surface->height) {
|
||||||
|
texture_destroy(&surface->texture);
|
||||||
|
surface->texture = texture_create(surface->width, surface->height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void surface_damage (struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) {
|
static void surface_damage (struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) {
|
||||||
printf("Surface damage\n");
|
|
||||||
c.redraw_needed = true;
|
c.redraw_needed = true;
|
||||||
|
struct surface *surface = wl_resource_get_user_data (resource);
|
||||||
|
struct texture* texture;
|
||||||
|
if (!surface || !surface->texture) {
|
||||||
|
texture = surface->texture;
|
||||||
|
texture->damage.x = min(texture->damage.x, x);
|
||||||
|
texture->damage.y = min(texture->damage.y, y);
|
||||||
|
texture->damage.width = max(texture->damage.width, width);
|
||||||
|
texture->damage.height = max(texture->damage.height, height);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static void surface_frame (struct wl_client *client, struct wl_resource *resource, uint32_t callback) {
|
static void surface_frame (struct wl_client *client, struct wl_resource *resource, uint32_t callback) {
|
||||||
struct surface *surface = wl_resource_get_user_data (resource);
|
struct surface *surface = wl_resource_get_user_data (resource);
|
||||||
@ -128,7 +176,22 @@ static void surface_frame (struct wl_client *client, struct wl_resource *resourc
|
|||||||
/*No op*/ static void surface_set_opaque_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {}
|
/*No op*/ static void surface_set_opaque_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {}
|
||||||
/*No op*/ static void surface_set_input_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {}
|
/*No op*/ static void surface_set_input_region (struct wl_client *client, struct wl_resource *resource, struct wl_resource *region) {}
|
||||||
static void surface_commit (struct wl_client *client, struct wl_resource *resource) {
|
static void surface_commit (struct wl_client *client, struct wl_resource *resource) {
|
||||||
printf("Surface commit\n");
|
struct surface *surface = wl_resource_get_user_data (resource);
|
||||||
|
if (!surface || !surface->buffer) return;
|
||||||
|
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (surface->buffer);
|
||||||
|
if (surface->texture && shm_buffer) {
|
||||||
|
void *data = wl_shm_buffer_get_data (shm_buffer);
|
||||||
|
if (data) {
|
||||||
|
texture_upload(surface->texture, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wl_buffer_send_release (surface->buffer);
|
||||||
|
|
||||||
|
if (surface->frame_callback) {
|
||||||
|
wl_callback_send_done (surface->frame_callback, backend_get_timestamp());
|
||||||
|
wl_resource_destroy (surface->frame_callback);
|
||||||
|
surface->frame_callback = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*No op*/ static void surface_set_buffer_transform (struct wl_client *client, struct wl_resource *resource, int32_t transform) {}
|
/*No op*/ static void surface_set_buffer_transform (struct wl_client *client, struct wl_resource *resource, int32_t transform) {}
|
||||||
/*No op*/ static void surface_set_buffer_scale (struct wl_client *client, struct wl_resource *resource, int32_t scale) {}
|
/*No op*/ static void surface_set_buffer_scale (struct wl_client *client, struct wl_resource *resource, int32_t scale) {}
|
||||||
@ -136,6 +199,7 @@ static void surface_delete (struct wl_resource *resource) {
|
|||||||
struct surface *surface = wl_resource_get_user_data (resource);
|
struct surface *surface = wl_resource_get_user_data (resource);
|
||||||
if (c.toplevel == surface) c.toplevel = NULL;
|
if (c.toplevel == surface) c.toplevel = NULL;
|
||||||
wl_list_remove (&surface->link);
|
wl_list_remove (&surface->link);
|
||||||
|
texture_destroy(&surface->texture);
|
||||||
free (surface);
|
free (surface);
|
||||||
}
|
}
|
||||||
static struct wl_surface_interface surface_interface = {&surface_destroy, &surface_attach, &surface_damage, &surface_frame, &surface_set_opaque_region, &surface_set_input_region, &surface_commit, &surface_set_buffer_transform, &surface_set_buffer_scale};
|
static struct wl_surface_interface surface_interface = {&surface_destroy, &surface_attach, &surface_damage, &surface_frame, &surface_set_opaque_region, &surface_set_input_region, &surface_commit, &surface_set_buffer_transform, &surface_set_buffer_scale};
|
||||||
@ -215,7 +279,7 @@ static void seat_get_keyboard (struct wl_client *client, struct wl_resource *res
|
|||||||
/*No op*/ static void seat_get_touch (struct wl_client *client, struct wl_resource *resource, uint32_t id) {}
|
/*No op*/ static void seat_get_touch (struct wl_client *client, struct wl_resource *resource, uint32_t id) {}
|
||||||
static struct wl_seat_interface seat_interface = {&seat_get_pointer, &seat_get_keyboard, &seat_get_touch};
|
static struct wl_seat_interface seat_interface = {&seat_get_pointer, &seat_get_keyboard, &seat_get_touch};
|
||||||
static void wl_seat_bind (struct wl_client *client, void *data, uint32_t version, uint32_t id) {
|
static void wl_seat_bind (struct wl_client *client, void *data, uint32_t version, uint32_t id) {
|
||||||
printf ("bind: wl_seat\n");
|
LOGD("bind: wl_seat");
|
||||||
struct wl_resource *seat = wl_resource_create (client, &wl_seat_interface, 7, id);
|
struct wl_resource *seat = wl_resource_create (client, &wl_seat_interface, 7, id);
|
||||||
wl_resource_set_implementation (seat, &seat_interface, NULL, NULL);
|
wl_resource_set_implementation (seat, &seat_interface, NULL, NULL);
|
||||||
wl_seat_send_capabilities (seat, WL_SEAT_CAPABILITY_POINTER|WL_SEAT_CAPABILITY_KEYBOARD);
|
wl_seat_send_capabilities (seat, WL_SEAT_CAPABILITY_POINTER|WL_SEAT_CAPABILITY_KEYBOARD);
|
||||||
@ -230,6 +294,12 @@ static const struct wl_output_interface output_interface = {
|
|||||||
output_release,
|
output_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
wl_output_unbind (struct wl_resource *resource) {
|
||||||
|
if (c.wl_output == resource)
|
||||||
|
c.wl_output = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wl_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
wl_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
|
||||||
{
|
{
|
||||||
@ -240,7 +310,7 @@ wl_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wl_resource_set_implementation(resource, &output_interface, NULL, NULL);
|
wl_resource_set_implementation(resource, &output_interface, NULL, &wl_output_unbind);
|
||||||
|
|
||||||
int mm_width = c.width/DPI*25*2;
|
int mm_width = c.width/DPI*25*2;
|
||||||
int mm_height = c.height/DPI*25*2;
|
int mm_height = c.height/DPI*25*2;
|
||||||
@ -251,10 +321,29 @@ wl_output_bind(struct wl_client *client, void *data, uint32_t version, uint32_t
|
|||||||
|
|
||||||
if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
|
if (version >= WL_OUTPUT_DONE_SINCE_VERSION)
|
||||||
wl_output_send_done(resource);
|
wl_output_send_done(resource);
|
||||||
|
|
||||||
|
c.wl_output = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
// backend callbacks
|
// backend callbacks
|
||||||
/*No op*/ static void handle_resize_event (int width, int height) {}
|
static void handle_resize_event (int width, int height) {
|
||||||
|
//glViewport(0, 0, width, height);
|
||||||
|
c.width = width;
|
||||||
|
c.height = height;
|
||||||
|
if (c.wl_output) {
|
||||||
|
wl_output_send_mode(c.wl_output, 3, width, height, 60000);
|
||||||
|
wl_output_send_done(c.wl_output);
|
||||||
|
if (c.toplevel && c.toplevel->client->pointer) {
|
||||||
|
wl_pointer_send_leave(c.toplevel->client->pointer, 0, c.toplevel->surface);
|
||||||
|
wl_pointer_send_enter (c.toplevel->client->pointer, 0, c.toplevel->surface, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c.toplevel && c.toplevel->shell_surface) {
|
||||||
|
wl_shell_surface_send_configure(c.toplevel->shell_surface->shell_surface, 0, width, height);
|
||||||
|
wl_shell_surface_send_ping(c.toplevel->shell_surface->shell_surface, 33231);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
static void handle_draw_event (void) {
|
static void handle_draw_event (void) {
|
||||||
c.redraw_needed = true;
|
c.redraw_needed = true;
|
||||||
}
|
}
|
||||||
@ -296,46 +385,24 @@ static void handle_terminate() {
|
|||||||
}
|
}
|
||||||
static struct callbacks callbacks = {&handle_resize_event, &handle_draw_event, &handle_mouse_motion_event, &handle_mouse_button_event, &handle_key_event, &handle_modifiers_changed, &handle_terminate};
|
static struct callbacks callbacks = {&handle_resize_event, &handle_draw_event, &handle_mouse_motion_event, &handle_mouse_button_event, &handle_key_event, &handle_modifiers_changed, &handle_terminate};
|
||||||
|
|
||||||
void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data);
|
|
||||||
|
|
||||||
static void draw_surface(struct surface *surface) {
|
|
||||||
if (!surface) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (surface->buffer);
|
|
||||||
if (shm_buffer == NULL) return;
|
|
||||||
uint32_t width = wl_shm_buffer_get_width (shm_buffer);
|
|
||||||
uint32_t height = wl_shm_buffer_get_height (shm_buffer);
|
|
||||||
void *data = wl_shm_buffer_get_data (shm_buffer);
|
|
||||||
if (data) {
|
|
||||||
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
||||||
wl_buffer_send_release (surface->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (surface->frame_callback) {
|
|
||||||
wl_callback_send_done (surface->frame_callback, backend_get_timestamp());
|
|
||||||
wl_resource_destroy (surface->frame_callback);
|
|
||||||
surface->frame_callback = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw (void) {
|
static void draw (void) {
|
||||||
glClearColor (1, 1, 0, 1);
|
glClearColor (0, 0, 0, 0);
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
//glLoadIdentity();
|
|
||||||
|
|
||||||
draw_surface(c.toplevel);
|
if (c.renderer && c.toplevel && c.toplevel->texture)
|
||||||
|
texture_draw(c.renderer, c.toplevel->texture, -1.0, -1.0, 1.0, 1.0);
|
||||||
|
|
||||||
glFlush ();
|
glFlush ();
|
||||||
backend_swap_buffers ();
|
backend_swap_buffers ();
|
||||||
c.redraw_needed = false;
|
c.redraw_needed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(void) {
|
int main(int argc, char *argv[]) {
|
||||||
printf("Starting lorie server\n");
|
if (argc == 2 && !strcmp("-f", argv[1])) trace_funcs = true;
|
||||||
|
LOGV("Starting lorie server");
|
||||||
signal(SIGSEGV, handler);
|
signal(SIGSEGV, handler);
|
||||||
backend_init (&callbacks);
|
backend_init (&callbacks);
|
||||||
setenv("WAYLAND_DEBUG", "1", 1);
|
//setenv("WAYLAND_DEBUG", "1", 1);
|
||||||
memset(&c, 0, sizeof(c));
|
memset(&c, 0, sizeof(c));
|
||||||
wl_list_init (&c.clients);
|
wl_list_init (&c.clients);
|
||||||
wl_list_init (&c.surfaces);
|
wl_list_init (&c.surfaces);
|
||||||
@ -352,19 +419,22 @@ int main(void) {
|
|||||||
wl_global_create (c.display, &wl_output_interface, 3, NULL, &wl_output_bind);
|
wl_global_create (c.display, &wl_output_interface, 3, NULL, &wl_output_bind);
|
||||||
wl_display_init_shm (c.display);
|
wl_display_init_shm (c.display);
|
||||||
|
|
||||||
|
c.renderer = renderer_create();
|
||||||
|
|
||||||
struct wl_event_loop *event_loop = wl_display_get_event_loop (c.display);
|
struct wl_event_loop *event_loop = wl_display_get_event_loop (c.display);
|
||||||
int wayland_fd = wl_event_loop_get_fd (event_loop);
|
int wayland_fd = wl_event_loop_get_fd (event_loop);
|
||||||
while (c.running) {
|
while (c.running) {
|
||||||
wl_event_loop_dispatch (event_loop, 0);
|
wl_event_loop_dispatch (event_loop, 0);
|
||||||
backend_dispatch_nonblocking ();
|
backend_dispatch_nonblocking ();
|
||||||
wl_display_flush_clients (c.display);
|
wl_display_flush_clients (c.display);
|
||||||
if (c.redraw_needed)
|
if (c.redraw_needed) {
|
||||||
draw ();
|
draw ();
|
||||||
|
}
|
||||||
// usleep(50000);
|
// usleep(50000);
|
||||||
|
|
||||||
backend_wait_for_events (wayland_fd);
|
backend_wait_for_events (wayland_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wl_display_destroy (c.display);
|
wl_display_destroy (c.display);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -30,10 +30,12 @@ proxy_srcs = [
|
|||||||
'renderer.c'
|
'renderer.c'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
add_global_arguments('-finstrument-functions', language : 'c')
|
||||||
|
|
||||||
proxy = executable(
|
proxy = executable(
|
||||||
'proxy',
|
'proxy',
|
||||||
sources: proxy_srcs,
|
sources: proxy_srcs,
|
||||||
include_directories: incdirs,
|
include_directories: incdirs,
|
||||||
dependencies: [egl, glesv2, libx11, libx11_xcb, wayland_server, libxkbcommon, libxkbcommon_x11],
|
dependencies: [egl, glesv2, libx11, libx11_xcb, wayland_server, libxkbcommon, libxkbcommon_x11],
|
||||||
link_args: ['-lm', '-g', '-rdynamic']
|
link_args: ['-O0', '-lm', '-ldl', '-g', '-rdynamic', '-finstrument-functions']
|
||||||
)
|
)
|
||||||
|
197
renderer.c
197
renderer.c
@ -1,17 +1,6 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <EGL/egl.h>
|
#include "renderer.h"
|
||||||
#include <GLES2/gl2.h>
|
#include "log.h"
|
||||||
|
|
||||||
#define LOGI(...) (printf("(I): " __VA_ARGS__))
|
|
||||||
#define LOGW(...) (printf("(W): " __VA_ARGS__))
|
|
||||||
#define LOGE(...) (printf("(E): " __VA_ARGS__))
|
|
||||||
|
|
||||||
static GLuint gTextureProgram;
|
|
||||||
static GLuint gvTexturePositionHandle;
|
|
||||||
static GLuint gvTextureTexCoordsHandle;
|
|
||||||
static GLuint gvTextureSamplerHandle;
|
|
||||||
|
|
||||||
static const char gSimpleVS[] =
|
static const char gSimpleVS[] =
|
||||||
"attribute vec4 position;\n"
|
"attribute vec4 position;\n"
|
||||||
@ -31,12 +20,27 @@ static const char gSimpleFS[] =
|
|||||||
//" gl_FragColor = vec4(outTexCoords.x/outTexCoords.y,outTexCoords.y/outTexCoords.x, 0.0, 0.0);\n"
|
//" gl_FragColor = vec4(outTexCoords.x/outTexCoords.y,outTexCoords.y/outTexCoords.x, 0.0, 0.0);\n"
|
||||||
"}\n\n";
|
"}\n\n";
|
||||||
|
|
||||||
static void checkGlError(const char* op) {
|
static void checkGlError(const char* op, int line) {
|
||||||
GLint error;
|
GLint error;
|
||||||
|
char *desc = NULL;
|
||||||
for (error = glGetError(); error; error = glGetError()) {
|
for (error = glGetError(); error; error = glGetError()) {
|
||||||
LOGE("after %s() glError (0x%x)\n", op, error);
|
switch (error) {
|
||||||
|
#define E(code) case code: desc = #code; break;
|
||||||
|
E(GL_INVALID_ENUM);
|
||||||
|
E(GL_INVALID_VALUE);
|
||||||
|
E(GL_INVALID_OPERATION);
|
||||||
|
E(GL_STACK_OVERFLOW_KHR);
|
||||||
|
E(GL_STACK_UNDERFLOW_KHR);
|
||||||
|
E(GL_OUT_OF_MEMORY);
|
||||||
|
E(GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||||
|
E(GL_CONTEXT_LOST_KHR);
|
||||||
|
#undef E
|
||||||
|
}
|
||||||
|
LOGE("GL: %s after %s() (line %d)", desc, op, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define checkGlError(op) checkGlError(op, __LINE__)
|
||||||
static GLuint loadShader(GLenum shaderType, const char* pSource) {
|
static GLuint loadShader(GLenum shaderType, const char* pSource) {
|
||||||
GLuint shader = glCreateShader(shaderType);
|
GLuint shader = glCreateShader(shaderType);
|
||||||
if (shader) {
|
if (shader) {
|
||||||
@ -51,8 +55,7 @@ static GLuint loadShader(GLenum shaderType, const char* pSource) {
|
|||||||
char* buf = (char*) malloc(infoLen);
|
char* buf = (char*) malloc(infoLen);
|
||||||
if (buf) {
|
if (buf) {
|
||||||
glGetShaderInfoLog(shader, infoLen, NULL, buf);
|
glGetShaderInfoLog(shader, infoLen, NULL, buf);
|
||||||
LOGE("Could not compile shader %d:\n%s\n",
|
LOGE("Could not compile shader %d:\n%s\n", shaderType, buf);
|
||||||
shaderType, buf);
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
glDeleteShader(shader);
|
glDeleteShader(shader);
|
||||||
@ -63,7 +66,7 @@ static GLuint loadShader(GLenum shaderType, const char* pSource) {
|
|||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
|
static GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
|
||||||
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
|
GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
|
||||||
if (!vertexShader) {
|
if (!vertexShader) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -101,88 +104,108 @@ GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) {
|
|||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setupGraphics(void) {
|
struct renderer *renderer_create(void) {
|
||||||
|
struct renderer* r = calloc(1, sizeof(struct renderer));
|
||||||
gTextureProgram = createProgram(gSimpleVS, gSimpleFS);
|
if (r == NULL) {
|
||||||
if (!gTextureProgram) {
|
LOGE("Failed to allocate renderer\n");
|
||||||
return false;
|
return NULL;
|
||||||
}
|
}
|
||||||
gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position"); checkGlError("glGetAttribLocation");
|
r->gTextureProgram = createProgram(gSimpleVS, gSimpleFS); checkGlError("glCreateProgram");
|
||||||
gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords"); checkGlError("glGetAttribLocation");
|
if (!r->gTextureProgram) {
|
||||||
gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture"); checkGlError("glGetAttribLocation");
|
LOGE("GLESv2: Unable to create shader program");
|
||||||
|
renderer_destroy(&r);
|
||||||
return true;
|
return NULL;
|
||||||
|
}
|
||||||
|
r->gvPos = (GLuint) glGetAttribLocation(r->gTextureProgram, "position"); checkGlError("glGetAttribLocation");
|
||||||
|
r->gvCoords = (GLuint) glGetAttribLocation(r->gTextureProgram, "texCoords"); checkGlError("glGetAttribLocation");
|
||||||
|
r->gvTextureSamplerHandle = (GLuint) glGetUniformLocation(r->gTextureProgram, "texture"); checkGlError("glGetAttribLocation");
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
const GLfloat gTriangleVertices[] = { 0.0f, 0.5f, -0.5f, -0.5f,
|
void renderer_destroy(struct renderer** renderer) {
|
||||||
0.5f, -0.5f };
|
if (!renderer || !(*renderer)) return;
|
||||||
|
|
||||||
#define FLOAT_SIZE_BYTES 4;
|
glUseProgram(0);
|
||||||
const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES;
|
glDeleteProgram((*renderer)->gTextureProgram);
|
||||||
const GLfloat gTriangleVerticesData[] = {
|
free(*renderer);
|
||||||
// X, Y, Z, U, V
|
*renderer = NULL;
|
||||||
-1.0f, 1.0f, 0, 0.f, 0.f,
|
|
||||||
1.0f, 1.0f, 0, 1.f, 0.f,
|
|
||||||
-1.0f, -1.0f, 0, 0.f, 1.f,
|
|
||||||
1.0f, -1.0f, 0, 1.f, 1.f,
|
|
||||||
};
|
|
||||||
|
|
||||||
void glDrawTex(void) {
|
|
||||||
if (!gTextureProgram) {
|
|
||||||
if(!setupGraphics()) {
|
|
||||||
LOGE("Could not set up graphics.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
glUseProgram(gTextureProgram); checkGlError("glUseProgram");
|
|
||||||
|
|
||||||
glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE,
|
|
||||||
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, gTriangleVerticesData);
|
|
||||||
checkGlError("glVertexAttribPointer");
|
|
||||||
glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE,
|
|
||||||
TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &gTriangleVerticesData[3]);
|
|
||||||
checkGlError("glVertexAttribPointer");
|
|
||||||
glEnableVertexAttribArray(gvTexturePositionHandle);
|
|
||||||
glEnableVertexAttribArray(gvTextureTexCoordsHandle);
|
|
||||||
checkGlError("glEnableVertexAttribArray");
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
|
||||||
checkGlError("glDrawArrays");
|
|
||||||
|
|
||||||
glUseProgram(0); checkGlError("glUseProgram");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void glDrawTexCoords(float x0, float y0, float x1, float y1) {
|
struct texture *texture_create(int width, int height) {
|
||||||
float coords[20] = {
|
if (width <= 0 || height <= 0) return NULL;
|
||||||
x0, -y0, 0.f, 0.f, 0.f,
|
struct texture* texture = calloc(1, sizeof(struct texture));
|
||||||
x1, -y0, 0.f, 1.f, 0.f,
|
if (texture == NULL) {
|
||||||
x0, -y1, 0.f, 0.f, 1.f,
|
LOGE("Failed to allocate renderer\n");
|
||||||
x1, -y1, 0.f, 1.f, 1.f
|
return NULL;
|
||||||
};
|
|
||||||
|
|
||||||
glUseProgram(gTextureProgram); checkGlError("glUseProgram");
|
|
||||||
|
|
||||||
glVertexAttribPointer(gvTexturePositionHandle, 3, GL_FLOAT, GL_FALSE, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, coords); checkGlError("glVertexAttribPointer");
|
|
||||||
glVertexAttribPointer(gvTextureTexCoordsHandle, 2, GL_FLOAT, GL_FALSE, TRIANGLE_VERTICES_DATA_STRIDE_BYTES, &coords[3]); checkGlError("glVertexAttribPointer");
|
|
||||||
glEnableVertexAttribArray(gvTexturePositionHandle); checkGlError("glEnableVertexAttribArray");
|
|
||||||
glEnableVertexAttribArray(gvTextureTexCoordsHandle); checkGlError("glEnableVertexAttribArray");
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); checkGlError("glDrawArrays");
|
|
||||||
|
|
||||||
glUseProgram(0); checkGlError("glUseProgram");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint gPixelsTexture;
|
//LOGD("Creating %dx%d texture", width, height);
|
||||||
|
|
||||||
void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data){
|
|
||||||
if(!gPixelsTexture) glGenTextures(1, &gPixelsTexture);
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, gPixelsTexture);
|
glGenTextures(1, &texture->id);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 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, NULL);
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, type, data);
|
texture->width = width;
|
||||||
glDrawTex();
|
texture->height = height;
|
||||||
//glDrawTexCoords(-1.0, -1.0, 1.0, 1.0);
|
return texture;
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
}
|
||||||
|
|
||||||
|
void texture_upload(struct texture *texture, void *data) {
|
||||||
|
if (!texture || !data) return;
|
||||||
|
|
||||||
|
//LOGD("Texture uploading");
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, texture->width, texture->height, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
|
#else
|
||||||
|
int h;
|
||||||
|
for (h=texture->damage.y; h<(texture->damage.y+texture->damage.height); h++) {
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, texture->damage.y, texture->width, texture->damage.height, GL_RGBA, GL_UNSIGNED_BYTE, &data[texture->damage.y * texture->width * 4]);
|
||||||
|
texture->damage.x =
|
||||||
|
texture->damage.y =
|
||||||
|
texture->damage.width =
|
||||||
|
texture->damage.height = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void texture_draw(struct renderer* renderer, struct texture *texture, float x0, float y0, float x1, float y1) {
|
||||||
|
if (!renderer || !texture) return;
|
||||||
|
//LOGD("Texture drawing");
|
||||||
|
float coords[20] = {
|
||||||
|
x0, -y0, 0.f, 0.f, 0.f,
|
||||||
|
x1, -y0, 0.f, 1.f, 0.f,
|
||||||
|
x0, -y1, 0.f, 0.f, 1.f,
|
||||||
|
x1, -y1, 0.f, 1.f, 1.f,
|
||||||
|
};
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glUseProgram(renderer->gTextureProgram); checkGlError("glUseProgram");
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture->id);
|
||||||
|
|
||||||
|
glVertexAttribPointer(renderer->gvPos, 3, GL_FLOAT, GL_FALSE, 20, coords); checkGlError("glVertexAttribPointer");
|
||||||
|
glVertexAttribPointer(renderer->gvCoords, 2, GL_FLOAT, GL_FALSE, 20, &coords[3]); checkGlError("glVertexAttribPointer");
|
||||||
|
glEnableVertexAttribArray(renderer->gvPos); checkGlError("glEnableVertexAttribArray");
|
||||||
|
glEnableVertexAttribArray(renderer->gvCoords); checkGlError("glEnableVertexAttribArray");
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); checkGlError("glDrawArrays");
|
||||||
|
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glUseProgram(0); checkGlError("glUseProgram");
|
||||||
|
}
|
||||||
|
|
||||||
|
void texture_destroy(struct texture** texture) {
|
||||||
|
if (!texture || !(*texture)) return;
|
||||||
|
//LOGD("Texture destroying");
|
||||||
|
|
||||||
|
glDeleteTextures(1, &(*texture)->id);
|
||||||
|
|
||||||
|
free(*texture);
|
||||||
|
*texture = NULL;
|
||||||
}
|
}
|
||||||
|
29
renderer.h
Normal file
29
renderer.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include <GLES2/gl2.h>
|
||||||
|
#include <GLES2/gl2ext.h> // GLES error descriotions
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define min(x, y) (((x) < (y)) ? (x) : (y))
|
||||||
|
#define max(x, y) (((x) > (y)) ? (x) : (y))
|
||||||
|
|
||||||
|
struct renderer {
|
||||||
|
GLuint gTextureProgram;
|
||||||
|
GLuint gvPos;
|
||||||
|
GLuint gvCoords;
|
||||||
|
GLuint gvTextureSamplerHandle;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct texture {
|
||||||
|
GLuint id;
|
||||||
|
int width, height;
|
||||||
|
struct {
|
||||||
|
int32_t x, y, width, height;
|
||||||
|
} damage;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct renderer *renderer_create(void);
|
||||||
|
void renderer_destroy(struct renderer** renderer);
|
||||||
|
|
||||||
|
struct texture *texture_create(int width, int height);
|
||||||
|
void texture_upload(struct texture *texture, void *data);
|
||||||
|
void texture_draw(struct renderer* renderer, struct texture *texture, float x0, float y0, float x1, float y1);
|
||||||
|
void texture_destroy(struct texture** texture);
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
export WAYLAND_DEBUG=1
|
export WAYLAND_DEBUG=1
|
||||||
export DISPLAY=:1
|
export DISPLAY=:1
|
||||||
Xwayland $DISPLAY &
|
Xwayland $DISPLAY -shm &
|
||||||
sleep 0.3
|
sleep 0.3
|
||||||
openbox &
|
openbox &
|
||||||
sleep 0.3
|
sleep 0.3
|
||||||
|
Loading…
Reference in New Issue
Block a user