some renderer improvements

This commit is contained in:
Twaik Yont 2019-06-28 18:16:40 +03:00
parent 3b6336f54b
commit 3c5fee04da
7 changed files with 293 additions and 153 deletions

View File

@ -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
View 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
View File

@ -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;
} }

View File

@ -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']
) )

View File

@ -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"); //LOGD("Creating %dx%d texture", width, height);
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;
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);
glDrawTex(); texture->width = width;
//glDrawTexCoords(-1.0, -1.0, 1.0, 1.0); texture->height = height;
glBindTexture(GL_TEXTURE_2D, 0); return texture;
}
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
View 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);

View File

@ -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