From 3c5fee04da41cc5254687743a4c0d5daf4200798 Mon Sep 17 00:00:00 2001 From: Twaik Yont Date: Fri, 28 Jun 2019 18:16:40 +0300 Subject: [PATCH] some renderer improvements --- Xwayland.arch | 18 ----- log.h | 34 ++++++++ main.c | 150 ++++++++++++++++++++++++++---------- meson.build | 4 +- renderer.c | 209 ++++++++++++++++++++++++++++---------------------- renderer.h | 29 +++++++ test_xwayland | 2 +- 7 files changed, 293 insertions(+), 153 deletions(-) delete mode 100644 Xwayland.arch create mode 100644 log.h create mode 100644 renderer.h diff --git a/Xwayland.arch b/Xwayland.arch deleted file mode 100644 index 332aad7..0000000 --- a/Xwayland.arch +++ /dev/null @@ -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 diff --git a/log.h b/log.h new file mode 100644 index 0000000..7014c38 --- /dev/null +++ b/log.h @@ -0,0 +1,34 @@ +#ifdef __ANDROID__ +#include + +#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 + +#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__) diff --git a/main.c b/main.c index 5efa6a3..44cd04a 100644 --- a/main.c +++ b/main.c @@ -13,10 +13,31 @@ #include #include #include +#include #include +#include #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 *array[10]; @@ -33,7 +54,7 @@ void handler(int sig) { #define BINDFUNC(interface, version, implementation) \ 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); \ if (resource == NULL) { \ wl_client_post_no_memory(client); \ @@ -44,6 +65,7 @@ void handler(int sig) { struct lorie_composiror { struct wl_display *display; + struct wl_resource *wl_output; struct wl_list clients; struct wl_list surfaces; struct wl_list shell_surfaces; @@ -56,6 +78,8 @@ struct lorie_composiror { bool redraw_needed; uint32_t width, height; + + struct renderer* renderer; } c = {0}; struct client { @@ -82,10 +106,11 @@ struct surface { struct wl_resource *buffer; struct wl_resource *frame_callback; //int x, y; - //struct texture texture; + struct texture *texture; struct client *client; struct shell_surface *shell_surface; struct wl_list link; + uint32_t width, height; 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) { struct surface *surface = wl_resource_get_user_data (resource); 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) { - printf("Surface damage\n"); 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) { 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_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) { - 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_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); if (c.toplevel == surface) c.toplevel = NULL; wl_list_remove (&surface->link); + texture_destroy(&surface->texture); 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}; @@ -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) {} 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) { - printf ("bind: wl_seat\n"); + LOGD("bind: wl_seat"); struct wl_resource *seat = wl_resource_create (client, &wl_seat_interface, 7, id); wl_resource_set_implementation (seat, &seat_interface, NULL, NULL); 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, }; +static void +wl_output_unbind (struct wl_resource *resource) { + if (c.wl_output == resource) + c.wl_output = NULL; +} + static void 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; } - 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_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) wl_output_send_done(resource); + + c.wl_output = resource; } // 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) { 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}; -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) { - glClearColor (1, 1, 0, 1); + glClearColor (0, 0, 0, 0); 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 (); backend_swap_buffers (); c.redraw_needed = false; } -int main(void) { - printf("Starting lorie server\n"); +int main(int argc, char *argv[]) { + if (argc == 2 && !strcmp("-f", argv[1])) trace_funcs = true; + LOGV("Starting lorie server"); signal(SIGSEGV, handler); backend_init (&callbacks); - setenv("WAYLAND_DEBUG", "1", 1); + //setenv("WAYLAND_DEBUG", "1", 1); memset(&c, 0, sizeof(c)); wl_list_init (&c.clients); 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_display_init_shm (c.display); + c.renderer = renderer_create(); + struct wl_event_loop *event_loop = wl_display_get_event_loop (c.display); int wayland_fd = wl_event_loop_get_fd (event_loop); while (c.running) { wl_event_loop_dispatch (event_loop, 0); backend_dispatch_nonblocking (); wl_display_flush_clients (c.display); - if (c.redraw_needed) + if (c.redraw_needed) { draw (); + } // usleep(50000); + backend_wait_for_events (wayland_fd); } - wl_display_destroy (c.display); return 0; } diff --git a/meson.build b/meson.build index 5ef20be..be4845a 100644 --- a/meson.build +++ b/meson.build @@ -30,10 +30,12 @@ proxy_srcs = [ 'renderer.c' ] +add_global_arguments('-finstrument-functions', language : 'c') + proxy = executable( 'proxy', sources: proxy_srcs, include_directories: incdirs, 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'] ) diff --git a/renderer.c b/renderer.c index 36246a8..7305119 100644 --- a/renderer.c +++ b/renderer.c @@ -1,17 +1,6 @@ -#include -#include #include -#include -#include - -#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; +#include "renderer.h" +#include "log.h" static const char gSimpleVS[] = "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" "}\n\n"; -static void checkGlError(const char* op) { +static void checkGlError(const char* op, int line) { GLint error; + char *desc = NULL; 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) { GLuint shader = glCreateShader(shaderType); if (shader) { @@ -51,8 +55,7 @@ static GLuint loadShader(GLenum shaderType, const char* pSource) { char* buf = (char*) malloc(infoLen); if (buf) { glGetShaderInfoLog(shader, infoLen, NULL, buf); - LOGE("Could not compile shader %d:\n%s\n", - shaderType, buf); + LOGE("Could not compile shader %d:\n%s\n", shaderType, buf); free(buf); } glDeleteShader(shader); @@ -63,7 +66,7 @@ static GLuint loadShader(GLenum shaderType, const char* pSource) { 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); if (!vertexShader) { return 0; @@ -101,88 +104,108 @@ GLuint createProgram(const char* pVertexSource, const char* pFragmentSource) { return program; } -bool setupGraphics(void) { - - gTextureProgram = createProgram(gSimpleVS, gSimpleFS); - if (!gTextureProgram) { - return false; - } - gvTexturePositionHandle = glGetAttribLocation(gTextureProgram, "position"); checkGlError("glGetAttribLocation"); - gvTextureTexCoordsHandle = glGetAttribLocation(gTextureProgram, "texCoords"); checkGlError("glGetAttribLocation"); - gvTextureSamplerHandle = glGetUniformLocation(gTextureProgram, "texture"); checkGlError("glGetAttribLocation"); - - return true; +struct renderer *renderer_create(void) { + struct renderer* r = calloc(1, sizeof(struct renderer)); + if (r == NULL) { + LOGE("Failed to allocate renderer\n"); + return NULL; + } + r->gTextureProgram = createProgram(gSimpleVS, gSimpleFS); checkGlError("glCreateProgram"); + if (!r->gTextureProgram) { + LOGE("GLESv2: Unable to create shader program"); + renderer_destroy(&r); + 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, - 0.5f, -0.5f }; - -#define FLOAT_SIZE_BYTES 4; -const GLint TRIANGLE_VERTICES_DATA_STRIDE_BYTES = 5 * FLOAT_SIZE_BYTES; -const GLfloat gTriangleVerticesData[] = { - // X, Y, Z, U, V - -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"); +void renderer_destroy(struct renderer** renderer) { + if (!renderer || !(*renderer)) return; + + glUseProgram(0); + glDeleteProgram((*renderer)->gTextureProgram); + free(*renderer); + *renderer = NULL; } -static void glDrawTexCoords(float x0, float y0, float x1, float y1) { - 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 - }; - - 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; - -void glDrawPixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid * data){ - if(!gPixelsTexture) glGenTextures(1, &gPixelsTexture); +struct texture *texture_create(int width, int height) { + if (width <= 0 || height <= 0) return NULL; + struct texture* texture = calloc(1, sizeof(struct texture)); + if (texture == NULL) { + LOGE("Failed to allocate renderer\n"); + return NULL; + } + + //LOGD("Creating %dx%d texture", width, height); + 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_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_RGBA, type, data); - glDrawTex(); - //glDrawTexCoords(-1.0, -1.0, 1.0, 1.0); - glBindTexture(GL_TEXTURE_2D, 0); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + + texture->width = width; + texture->height = height; + 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; } diff --git a/renderer.h b/renderer.h new file mode 100644 index 0000000..113f160 --- /dev/null +++ b/renderer.h @@ -0,0 +1,29 @@ +#include +#include // GLES error descriotions +#include + +#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); diff --git a/test_xwayland b/test_xwayland index e410d3c..7443920 100755 --- a/test_xwayland +++ b/test_xwayland @@ -1,7 +1,7 @@ #!/bin/bash export WAYLAND_DEBUG=1 export DISPLAY=:1 -Xwayland $DISPLAY & +Xwayland $DISPLAY -shm & sleep 0.3 openbox & sleep 0.3