diff --git a/bin64/liboverlay.so.0 b/bin64/liboverlay.so.0 index 5468d7a..cc059a8 100755 Binary files a/bin64/liboverlay.so.0 and b/bin64/liboverlay.so.0 differ diff --git a/include/drawglx_internal.h b/include/drawglx_internal.h index 6f78458..fb9b0ac 100644 --- a/include/drawglx_internal.h +++ b/include/drawglx_internal.h @@ -10,6 +10,7 @@ #include "drawglx.h" #include "fontapi_internal.h" #include "programs.h" +#include "textureapi_internal.h" #include "vector.h" #include "vec234.h" @@ -26,6 +27,7 @@ enum DI_PUSH_INDICES, DI_PROGRAM_SWITCH_TEXTURE, DI_PROGRAM_SWITCH_FONT, + DI_TEXTUREAPI_BIND_TEXTURE, DI_TERMINATE }; @@ -42,6 +44,8 @@ struct draw_instruction_t GLuint texture; /* DI_PROGRAM_SWITCH_FONT */ xoverlay_font_handle_t font; + /* */ + xoverlay_texture_handle thandle; }; }; @@ -96,6 +100,9 @@ dis_push_indices(size_t count, GLuint *index_data); void dis_program_switch_texture(GLuint texture); +void +dis_textureapi_switch_texture(xoverlay_texture_handle texture); + void dis_program_switch_font(xoverlay_font_handle_t font); @@ -114,6 +121,7 @@ struct draw_state GLuint texture; xoverlay_font_handle_t font; + xoverlay_texture_handle thandle; GLuint shader; }; @@ -146,6 +154,9 @@ ds_render_next_frame(); /* To be called by draw functions */ +void +ds_prepare_texture_handle(xoverlay_texture_handle handle); + void ds_prepare_texture(GLuint texture); @@ -175,7 +186,7 @@ void draw_rect_outline(vec2 xy, vec2 hw, vec4 color, float thickness); void -draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st); +draw_rect_textured(vec2 xy, vec2 hw, vec4 color, xoverlay_texture_handle texture, vec2 t_xy, vec2 t_hw); void draw_string_internal(vec2 xy, const char *string, xoverlay_font_handle_t font, vec4 color, int *out_x, int *out_y); diff --git a/include/overlay.h b/include/overlay.h index 634e063..eaf9a8c 100644 --- a/include/overlay.h +++ b/include/overlay.h @@ -8,6 +8,7 @@ #pragma once #include "fontapi.h" +#include "textureapi.h" #include #include @@ -16,7 +17,6 @@ typedef void(*xoverlay_callback_keypress)(unsigned int keycode, int action); typedef void(*xoverlay_callback_click)(unsigned int buttoncode, int action); typedef void(*xoverlay_callback_scroll)(int value); typedef void(*xoverlay_callback_mousemove)(int dx, int dy, int x, int y); -/* typedef void(*xoverlay_callback_draw)(); */ struct xoverlay_library { @@ -24,7 +24,6 @@ struct xoverlay_library xoverlay_callback_click cb_click; xoverlay_callback_scroll cb_scroll; xoverlay_callback_mousemove cb_mousemove; - /* xoverlay_callback_draw cb_draw; */ Display *display; Window window; @@ -43,18 +42,6 @@ struct xoverlay_library int y; } mouse; - /*struct - { - int x; - int y; - char buttons[5]; - } mouse; - - struct - { - char keymap[32]; - } keyboard;*/ - char init; char drawing; }; @@ -108,6 +95,9 @@ xoverlay_draw_rect(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color void xoverlay_draw_rect_outline(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, float thickness); +void +xoverlay_draw_rect_textured(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, xoverlay_texture_handle texture, xoverlay_vec2_t t_xy, xoverlay_vec2_t t_hw); + void xoverlay_draw_string(xoverlay_vec2_t xy, const char *string, xoverlay_font_handle_t font, xoverlay_vec4_t color, int *out_x, int *out_y); diff --git a/include/textureapi.h b/include/textureapi.h new file mode 100644 index 0000000..b21e0d3 --- /dev/null +++ b/include/textureapi.h @@ -0,0 +1,19 @@ +/* + * textureapi.h + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#pragma once + +typedef unsigned xoverlay_texture_handle; + +xoverlay_texture_handle +xoverlay_texture_load_png_rgba(const char *path); + +void +xoverlay_texture_unload(xoverlay_texture_handle handle); + +void +xoverlay_texture_get_size(xoverlay_texture_handle handle, int *width, int *height); diff --git a/include/textureapi_internal.h b/include/textureapi_internal.h new file mode 100644 index 0000000..b8878f6 --- /dev/null +++ b/include/textureapi_internal.h @@ -0,0 +1,51 @@ +/* + * textureapi_internal.h + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#pragma once + +#include "textureapi.h" + +#include +#include + +#define XOVERLAY_TEXTURE_COUNT 64 + +struct textureapi_texture_t +{ + char bound; + char init; + + int width; + int height; + + GLuint texture_id; + char filename[256]; + GLubyte *data; +}; + + +struct textureapi_texture_t loaded_textures[XOVERLAY_TEXTURE_COUNT]; + +int +textureapi_load_png_rgba(const char *name, struct textureapi_texture_t *out); + +struct textureapi_texture_t * +textureapi_get(xoverlay_texture_handle handle); + +void +textureapi_bind(xoverlay_texture_handle handle); + +int +textureapi_init(); + +void +textureapi_destroy(); + +xoverlay_texture_handle +textureapi_add_texture(struct textureapi_texture_t font); + + diff --git a/src/drawglx.o b/src/drawglx.o index d54eea0..d68a706 100644 Binary files a/src/drawglx.o and b/src/drawglx.o differ diff --git a/src/drawglx_internal.c b/src/drawglx_internal.c index cabaeb7..d0193d4 100644 --- a/src/drawglx_internal.c +++ b/src/drawglx_internal.c @@ -238,6 +238,26 @@ dis_fetch_instruction() return result; } +void +dis_textureapi_switch_texture(xoverlay_texture_handle texture) +{ + struct draw_instruction_t *last = dis_last_pushed_instruction(); + + if (last && last->type == DI_TEXTUREAPI_BIND_TEXTURE) + { + last->thandle = texture; + return; + } + else + { + struct draw_instruction_t instr; + + instr.type = DI_TEXTUREAPI_BIND_TEXTURE; + instr.thandle = texture; + dis_push_instruction(instr); + } +} + void ds_init() @@ -317,6 +337,7 @@ ds_render_next_frame() ds_pre_render(); dis_finish(); ds.program = -1; + ds.thandle = 0; ds.font = 0; ds.texture = 0; ds.shader = 0; @@ -356,6 +377,9 @@ ds_render_next_frame() case DI_PROGRAM_SWITCH_FONT: program_freetype_switch_font(instr->font); break; + case DI_TEXTUREAPI_BIND_TEXTURE: + textureapi_bind(instr->thandle); + break; case DI_INVALID_INSTRUCTION: case DI_TERMINATE: default: @@ -404,6 +428,16 @@ ds_use_font(xoverlay_font_handle_t font) } } +void +ds_prepare_texture_handle(xoverlay_texture_handle handle) +{ + if (handle != ds.thandle) + { + dis_textureapi_switch_texture(handle); + ds.thandle = handle; + } +} + void ds_prepare_program(int program) { @@ -527,36 +561,48 @@ draw_rect_outline(vec2 xy, vec2 hw, vec4 color, float thickness) draw_line(point, delta, color, thickness); } + void -draw_rect_textured(vec2 xy, vec2 hw, vec4 color, int texture, vec2 uv, vec2 st) +draw_rect_textured(vec2 xy, vec2 hw, vec4 color, xoverlay_texture_handle texture, vec2 t_xy, vec2 t_hw) { + struct textureapi_texture_t *tx = textureapi_get(texture); + if (tx == NULL) + return; + ds_prepare_program(PROGRAM_TRIANGLES_TEXTURED); + ds_prepare_texture_handle(texture); + GLuint idx = dstream.next_index; struct vertex_v2ft2fc4f vertices[4]; /* A C => ABC, CDB * B D */ - GLuint indices[6] = { idx, idx + 1, idx + 2, idx + 2, idx + 3, idx + 1 }; + GLuint indices[6] = { idx, idx + 1, idx + 2, idx + 2, idx + 3, idx }; + + float s0 = t_xy.x / tx->width; + float s1 = (t_xy.x + t_hw.x) / tx->width; + float t0 = t_xy.y / tx->height; + float t1 = (t_xy.y + t_hw.y) / tx->height; vertices[0].pos.x = xy.x; vertices[0].pos.y = xy.y; - vertices[0].uv = uv; + vertices[0].uv = (vec2){ s0, t1 }; vertices[0].color = color; vertices[1].pos.x = xy.x; vertices[1].pos.y = xy.y + hw.y; - vertices[1].uv = (vec2){ uv.x, uv.y + st.y }; + vertices[1].uv = (vec2){ s0, t0 }; vertices[1].color = color; vertices[2].pos.x = xy.x + hw.x; vertices[2].pos.y = xy.y + hw.y; - vertices[1].uv = (vec2){ uv.x + st.x, uv.y + st.y }; + vertices[2].uv = (vec2){ s1, t0 }; vertices[2].color = color; vertices[3].pos.x = xy.x + hw.x; vertices[3].pos.y = xy.y; - vertices[1].uv = (vec2){ uv.x + st.x, uv.y }; + vertices[3].uv = (vec2){ s1, t1 }; vertices[3].color = color; dis_push_vertices(4, sizeof(struct vertex_v2ft2fc4f), vertices); diff --git a/src/drawglx_internal.o b/src/drawglx_internal.o index d02a500..56cff53 100644 Binary files a/src/drawglx_internal.o and b/src/drawglx_internal.o differ diff --git a/src/overlay.c b/src/overlay.c index 19f1e71..e9448fa 100644 --- a/src/overlay.c +++ b/src/overlay.c @@ -45,6 +45,9 @@ int xoverlay_init() if (xoverlay_glx_create_window() < 0) return -1; + textureapi_init(); + fontapi_init(); + xoverlay_library.init = 1; return 0; } @@ -53,6 +56,9 @@ void xoverlay_destroy() { XDestroyWindow(xoverlay_library.display, xoverlay_library.window); XCloseDisplay(xoverlay_library.display); + xoverlay_glx_destroy(); + fontapi_destroy(); + textureapi_destroy(); xoverlay_library.init = 0; } @@ -263,6 +269,11 @@ xoverlay_draw_string_with_outline(xoverlay_vec2_t xy, const char *string, xoverl draw_string_with_outline(*(vec2*)&xy, string, font, *(vec4*)&color, *(vec4*)&outline_color, outline_width, adjust_outline_alpha, out_x, out_y); } +void +xoverlay_draw_rect_textured(xoverlay_vec2_t xy, xoverlay_vec2_t hw, xoverlay_rgba_t color, xoverlay_texture_handle texture, xoverlay_vec2_t t_xy, xoverlay_vec2_t t_hw) +{ + draw_rect_textured(*(vec2*)&xy, *(vec2*)&hw, *(vec4*)&color, texture, *(vec2*)&t_xy, *(vec2*)&t_hw); +} void xoverlay_draw_begin() { diff --git a/src/overlay.o b/src/overlay.o index 2000bc9..fd96fd8 100644 Binary files a/src/overlay.o and b/src/overlay.o differ diff --git a/src/program_freetype.o b/src/program_freetype.o index 3d99f64..7a0b554 100644 Binary files a/src/program_freetype.o and b/src/program_freetype.o differ diff --git a/src/program_triangles_plain.o b/src/program_triangles_plain.o index 4afd7cc..bcdc436 100644 Binary files a/src/program_triangles_plain.o and b/src/program_triangles_plain.o differ diff --git a/src/program_triangles_textured.c b/src/program_triangles_textured.c index b2911a8..6096123 100644 --- a/src/program_triangles_textured.c +++ b/src/program_triangles_textured.c @@ -8,6 +8,7 @@ #include #include "programs.h" +#include "drawglx_internal.h" DECL_PROGRAM_INIT(triangles_textured) { @@ -16,6 +17,7 @@ DECL_PROGRAM_INIT(triangles_textured) DECL_PROGRAM_LOAD(triangles_textured) { + ds_use_shader(programs[PROGRAM_TRIANGLES_TEXTURED].shader); vertex_buffer_clear(programs[PROGRAM_TRIANGLES_TEXTURED].vertex); } diff --git a/src/program_triangles_textured.o b/src/program_triangles_textured.o index 4e08454..e720989 100644 Binary files a/src/program_triangles_textured.o and b/src/program_triangles_textured.o differ diff --git a/src/programs.c b/src/programs.c index 85b9724..8c42c21 100644 --- a/src/programs.c +++ b/src/programs.c @@ -107,8 +107,14 @@ const char *shader_v2ft2fc4f_frag = "uniform sampler2D texture;\n" "void main()\n" "{\n" - " float a = texture2D(texture, gl_TexCoord[0].xy).r;\n" - "gl_FragColor = vec4(gl_Color.rgb, gl_Color.a*a);\n" + " vec4 tex = texture2D(texture, gl_TexCoord[0].xy);\n" + " gl_FragColor = vec4(gl_Color.rgb * tex.rgb, gl_Color.a*tex.a);\n" + "}"; +const char *shader_v2ft2fc4f_freetype_frag = + "uniform sampler2D texture;\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(gl_Color.rgb, gl_Color.a * texture2D(texture, gl_TexCoord[0].xy).r);\n" "}"; void @@ -119,6 +125,6 @@ program_init_everything() setup_matrices(programs[PROGRAM_TRIANGLES_PLAIN].shader, 0); PROGRAM_INIT_INPLACE(&programs[PROGRAM_TRIANGLES_TEXTURED], "vertex:2f,tex_coord:2f,color:4f", shader_v2ft2fc4f_frag, shader_v2ft2fc4f_vert, triangles_textured); setup_matrices(programs[PROGRAM_TRIANGLES_TEXTURED].shader, 1); - PROGRAM_INIT_INPLACE(&programs[PROGRAM_FREETYPE], "vertex:2f,tex_coord:2f,color:4f", shader_v2ft2fc4f_frag, shader_v2ft2fc4f_vert, freetype); + PROGRAM_INIT_INPLACE(&programs[PROGRAM_FREETYPE], "vertex:2f,tex_coord:2f,color:4f", shader_v2ft2fc4f_freetype_frag, shader_v2ft2fc4f_vert, freetype); setup_matrices(programs[PROGRAM_FREETYPE].shader, 1); } diff --git a/src/programs.o b/src/programs.o index 5efafd1..c624a33 100644 Binary files a/src/programs.o and b/src/programs.o differ diff --git a/src/textureapi.c b/src/textureapi.c new file mode 100644 index 0000000..24993de --- /dev/null +++ b/src/textureapi.c @@ -0,0 +1,188 @@ +/* + * textureapi_internal.c + * + * Created on: Nov 11, 2017 + * Author: nullifiedcat + */ + +#include "drawglx_internal.h" +#include "textureapi_internal.h" + +#include +#include +#include + +int +textureapi_load_png_rgba(const char *name, struct textureapi_texture_t *out) +{ + memset(out, 0, sizeof(struct textureapi_texture_t)); + + FILE *file; + file = fopen(name, "r"); + if (file == NULL) + { + perror("textureapi: could not open file: "); + return -1; + } + png_byte header[8]; + fread(header, 1, 8, file); + if (png_sig_cmp(header, 0, 8)) + { + printf("textureapi: not a PNG file\n"); + fclose(file); + return -1; + } + png_structp pngstr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (pngstr == NULL) + { + printf("textureapi: png creation error\n"); + return -1; + } + png_infop pnginfo = png_create_info_struct(pngstr); + png_infop pngend = png_create_info_struct(pngstr); + if (setjmp(png_jmpbuf(pngstr))) + { + png_destroy_read_struct(pngstr, pnginfo, pngend); + return -1; + } + png_init_io(pngstr, file); + png_set_sig_bytes(pngstr, 8); + png_read_info(pngstr, pnginfo); + int width, height, depth, colortype; + png_get_IHDR(pngstr, pnginfo, &width, &height, &depth, &colortype, NULL, NULL, NULL); + png_read_update_info(pngstr, pnginfo); + int row_bytes; + if (PNG_COLOR_TYPE_RGBA != png_get_color_type(pngstr, pnginfo)) + { + printf("textureapi: not RGBA PNG\n"); + png_destroy_read_struct(pngstr, pnginfo, pngend); + fclose(file); + return -1; + } + + png_bytepp row_pointers; + row_bytes = png_get_rowbytes(pngstr, pnginfo); + out->data = malloc(row_bytes * height * sizeof(png_byte)); + if (out->data == NULL) + { + printf("malloc error\n"); + png_destroy_read_struct(pngstr, pnginfo, pngend); + fclose(file); + return -1; + } + row_pointers = malloc(height * sizeof(png_bytep)); + if (row_pointers == NULL) + { + printf("malloc error\n"); + png_destroy_read_struct(pngstr, pnginfo, pngend); + free(out->data); + fclose(file); + return -1; + } + for (int i = 0; i < height; ++i) + { + row_pointers[height - 1 - i] = out->data + i * row_bytes; + } + png_read_image(pngstr, row_pointers); + + // png_destroy_read_struct(pngstr, pnginfo, pngend); + free(row_pointers); + fclose(file); + out->width = width; + out->height = height; + out->init = 1; + return 0; +} + + +void +textureapi_bind(xoverlay_texture_handle handle) +{ + struct textureapi_texture_t *texture = textureapi_get(handle); + if (texture == NULL || texture->init == 0) + return; + if (!texture->bound) + { + printf("generating texture\n"); + glGenTextures(1, &texture->texture_id); + glBindTexture(GL_TEXTURE_2D, texture->texture_id); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture->data); + 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_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + texture->bound = 1; + } + ds_bind_texture(texture->texture_id); +} + +xoverlay_texture_handle +xoverlay_texture_load_png_rgba(const char *path) +{ + struct textureapi_texture_t result; + result.bound = 0; + strncpy(result.filename, path, 255); + if (textureapi_load_png_rgba(path, &result) != 0) + { + printf("textureapi: could not load texture file %s\n", path); + } + return textureapi_add_texture(result); +} + + +void +xoverlay_texture_get_size(xoverlay_texture_handle handle, int *width, int *height) +{ + struct textureapi_texture_t *tx = textureapi_get(handle); + if (tx == NULL) + return; + if (width) + *width = tx->width; + if (height) + *height = tx->height; +} + +struct textureapi_texture_t * +textureapi_get(xoverlay_texture_handle handle) +{ + if (handle == 0 || handle >= XOVERLAY_TEXTURE_COUNT) + return NULL; + if (loaded_textures[handle - 1].init == 0) + return NULL; + return &loaded_textures[handle - 1]; +} + +int +textureapi_init() +{ + memset(loaded_textures, 0, sizeof(loaded_textures)); + return 0; +} + +void +textureapi_destroy() +{ + +} + +xoverlay_texture_handle +textureapi_add_texture(struct textureapi_texture_t texture) +{ + for (xoverlay_texture_handle i = 0; i < XOVERLAY_TEXTURE_COUNT; ++i) + { + if (loaded_textures[i].init == 0) + { + memcpy(&loaded_textures[i], &texture, sizeof(texture)); + loaded_textures[i].init = 1; + return i + 1; + } + } + return 0; +} + +void +xoverlay_texture_unload(xoverlay_texture_handle handle) +{ + // TODO +} diff --git a/src/textureapi_internal.o b/src/textureapi_internal.o new file mode 100644 index 0000000..b3edaf6 Binary files /dev/null and b/src/textureapi_internal.o differ