+#include"abc.h"
+
+static const char* vert_shader =
+ "#version 330 core\n"
+ "layout(location = 0) in vec4 position; \n"
+ "layout(location = 1) in vec2 a_texCoord; \n"
+ "out vec2 v_texCoord; \n"
+ "uniform mat4 mvp; \n"
+ "void main() { \n"
+ "gl_Position = mvp * position; \n"
+ "v_texCoord = a_texCoord; \n"
+ "} \n";
+
+static const char* frag_shader =
+ "#version 330 core\n"
+ "in vec2 v_texCoord; \n"
+ "out vec4 outputColor; \n"
+ "uniform float opacity; \n"
+ "uniform sampler2D tex_rgba; \n"
+ "void main() { \n"
+ " vec2 xy = v_texCoord; \n"
+ " vec4 v = texture2D(tex_rgba, xy).rgba; \n"
+ " v *= opacity;\n"
+ " outputColor = vec4(v.b, v.g, v.r, v.a); \n"
+ "} \n";
+
+
+static GLuint program = 0;
+
+static GLuint vao = 0;
+static GLuint buffers[2] = {0};
+static GLuint texture_rgba = 0;
+
+static GLuint uniform_mvp;
+static GLuint uniform_rgba;
+static GLuint uniform_opacity;
+
+
+int __render_text_gl(abc_obj_t* obj, const char* bgra, int w_text, int h_text, int width, int height,
+ int x,
+ int y,
+ int w,
+ int h,
+ int view_x, int view_y, int view_w, int view_h, float mvp[16])
+{
+ if (0 == program)
+ __init_program(&program, vert_shader, frag_shader);
+
+ if (0 == vao)
+ __init_buffers(&vao, buffers);
+
+ if (0 == texture_rgba)
+ __init_texture(&texture_rgba, GL_RGBA, w_text, h_text, NULL);
+
+ GLfloat opacity = 1.0;
+
+ abc_attr_t* attr = abc_obj_get_attr(obj, ABC_CSS_OPACITY);
+ if (attr && attr->value->len > 0)
+ opacity = atof(attr->value->data);
+
+ GLfloat vert_update[] =
+ {
+ 2.0 * view_x / (float)width - 1.0,
+ -2.0 * (view_y + view_h) / (float)height + 1.0,
+
+ 2.0 * (view_x + view_w) / (float)width - 1.0,
+ -2.0 * (view_y + view_h) / (float)height + 1.0,
+
+ 2.0 * view_x / (float)width - 1.0,
+ -2.0 * view_y / (float)height + 1.0,
+
+ 2.0 * (view_x + view_w) / (float)width - 1.0,
+ -2.0 * view_y / (float)height + 1.0,
+ };
+
+ GLfloat texture_update[] =
+ {
+ (view_x - x) / (float)w,
+ (view_y + view_h - y) / (float)h,
+
+ (view_x + view_w - x) / (float)w,
+ (view_y + view_h - y) / (float)h,
+
+ (view_x - x) / (float)w,
+ (view_y - y) / (float)h,
+
+ (view_x + view_w - x) / (float)w,
+ (view_y - y) / (float)h,
+ };
+
+ glUseProgram(program);
+ uniform_mvp = glGetUniformLocation(program, "mvp");
+ uniform_rgba = glGetUniformLocation(program, "tex_rgba");
+ uniform_opacity = glGetUniformLocation(program, "opacity");
+
+ glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, mvp);
+
+ // board
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_2D, texture_rgba);
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w_text, h_text, 0, GL_RGBA, GL_UNSIGNED_BYTE, bgra);
+ glUniform1i(uniform_rgba, 0);
+
+ glUniform1f(uniform_opacity, opacity);
+
+ // draw
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[0]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vert_update), vert_update);
+
+ glBindBuffer (GL_ARRAY_BUFFER, buffers[1]);
+ glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(texture_update), texture_update);
+
+ glBindVertexArray(vao);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisable(GL_BLEND);
+
+ glBindVertexArray(0);
+ glUseProgram(0);
+ return 0;
+}