gl_shader.cc (5367B)
1 /* 2 * Copyright 2012 Google, Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * Google Author(s): Behdad Esfahbod 17 */ 18 #include <assert.h> 19 20 #include "gl_shader.h" 21 #include "gl_atlas_glsl.h" 22 #include "gl_vshader_glsl.h" 23 #include "gl_fshader_glsl.h" 24 25 26 citrun::gl_shader::gl_shader() 27 { 28 } 29 30 static unsigned int 31 glyph_encode (unsigned int atlas_x , /* 7 bits */ 32 unsigned int atlas_y, /* 7 bits */ 33 unsigned int corner_x, /* 1 bit */ 34 unsigned int corner_y, /* 1 bit */ 35 unsigned int nominal_w, /* 6 bits */ 36 unsigned int nominal_h /* 6 bits */) 37 { 38 assert (0 == (atlas_x & ~0x7F)); 39 assert (0 == (atlas_y & ~0x7F)); 40 assert (0 == (corner_x & ~1)); 41 assert (0 == (corner_y & ~1)); 42 assert (0 == (nominal_w & ~0x3F)); 43 assert (0 == (nominal_h & ~0x3F)); 44 45 unsigned int x = (((atlas_x << 6) | nominal_w) << 1) | corner_x; 46 unsigned int y = (((atlas_y << 6) | nominal_h) << 1) | corner_y; 47 48 return (x << 16) | y; 49 } 50 51 static void 52 glyph_vertex_encode (double x, double y, 53 unsigned int corner_x, unsigned int corner_y, 54 const citrun::glyph_info_t *gi, 55 citrun::glyph_vertex_t *v) 56 { 57 unsigned int encoded = glyph_encode (gi->atlas_x, gi->atlas_y, 58 corner_x, corner_y, 59 gi->nominal_w, gi->nominal_h); 60 v->x = x; 61 v->y = y; 62 v->g16hi = encoded >> 16; 63 v->g16lo = encoded & 0xFFFF; 64 } 65 66 void 67 citrun::gl_shader::add_glyph_vertices(const glyphy_point_t &p, double font_size, 68 citrun::glyph_info_t *gi, std::vector<glyph_vertex_t> *vertices, 69 glyphy_extents_t *extents) 70 { 71 if (gi->is_empty) 72 return; 73 74 glyph_vertex_t v[4]; 75 76 #define ENCODE_CORNER(_cx, _cy) \ 77 do { \ 78 double _vx = p.x + font_size * ((1-_cx) * gi->extents.min_x + _cx * gi->extents.max_x); \ 79 double _vy = p.y - font_size * ((1-_cy) * gi->extents.min_y + _cy * gi->extents.max_y); \ 80 glyph_vertex_encode (_vx, _vy, _cx, _cy, gi, &v[_cx * 2 + _cy]); \ 81 } while (0) 82 ENCODE_CORNER (0, 0); 83 ENCODE_CORNER (0, 1); 84 ENCODE_CORNER (1, 0); 85 ENCODE_CORNER (1, 1); 86 #undef ENCODE_CORNER 87 88 vertices->push_back (v[0]); 89 vertices->push_back (v[1]); 90 vertices->push_back (v[2]); 91 92 vertices->push_back (v[1]); 93 vertices->push_back (v[2]); 94 vertices->push_back (v[3]); 95 96 if (extents) { 97 glyphy_extents_clear (extents); 98 for (unsigned int i = 0; i < 4; i++) { 99 glyphy_point_t p = {v[i].x, v[i].y}; 100 glyphy_extents_add (extents, &p); 101 } 102 } 103 } 104 105 106 107 108 static GLuint 109 compile_shader (GLenum type, 110 GLsizei count, 111 const GLchar** sources) 112 { 113 TRACE(); 114 115 GLuint shader; 116 GLint compiled; 117 118 if (!(shader = glCreateShader (type))) 119 return shader; 120 121 glShaderSource (shader, count, sources, 0); 122 glCompileShader (shader); 123 124 glGetShaderiv (shader, GL_COMPILE_STATUS, &compiled); 125 if (!compiled) { 126 GLint info_len = 0; 127 LOGW ("%s shader failed to compile\n", 128 type == GL_VERTEX_SHADER ? "Vertex" : "Fragment"); 129 glGetShaderiv (shader, GL_INFO_LOG_LENGTH, &info_len); 130 131 if (info_len > 0) { 132 char *info_log = (char*) malloc (info_len); 133 glGetShaderInfoLog (shader, info_len, NULL, info_log); 134 135 LOGW ("%s\n", info_log); 136 free (info_log); 137 } 138 139 abort (); 140 } 141 142 return shader; 143 } 144 145 static GLuint 146 link_program (GLuint vshader, 147 GLuint fshader) 148 { 149 TRACE(); 150 151 GLuint program; 152 GLint linked; 153 154 program = glCreateProgram (); 155 glAttachShader (program, vshader); 156 glAttachShader (program, fshader); 157 glLinkProgram (program); 158 glDeleteShader (vshader); 159 glDeleteShader (fshader); 160 161 glGetProgramiv (program, GL_LINK_STATUS, &linked); 162 if (!linked) { 163 GLint info_len = 0; 164 LOGW ("Program failed to link\n"); 165 glGetProgramiv (program, GL_INFO_LOG_LENGTH, &info_len); 166 167 if (info_len > 0) { 168 char *info_log = (char*) malloc (info_len); 169 glGetProgramInfoLog (program, info_len, NULL, info_log); 170 171 LOGW ("%s\n", info_log); 172 free (info_log); 173 } 174 175 abort (); 176 } 177 178 return program; 179 } 180 181 #ifdef GL_ES_VERSION_2_0 182 # define GLSL_HEADER_STRING \ 183 "#extension GL_OES_standard_derivatives : enable\n" \ 184 "precision highp float;\n" \ 185 "precision highp int;\n" 186 #else 187 # define GLSL_HEADER_STRING \ 188 "#version 110\n" 189 #endif 190 191 GLuint 192 citrun::gl_shader::create_program() 193 { 194 TRACE(); 195 196 GLuint vshader, fshader, program; 197 const GLchar *vshader_sources[] = {GLSL_HEADER_STRING, 198 gl_vshader_glsl}; 199 vshader = compile_shader (GL_VERTEX_SHADER, ARRAY_LEN (vshader_sources), vshader_sources); 200 const GLchar *fshader_sources[] = {GLSL_HEADER_STRING, 201 gl_atlas_glsl, 202 glyphy_common_shader_source (), 203 "#define GLYPHY_SDF_PSEUDO_DISTANCE 1\n", 204 glyphy_sdf_shader_source (), 205 gl_fshader_glsl}; 206 fshader = compile_shader (GL_FRAGMENT_SHADER, ARRAY_LEN (fshader_sources), fshader_sources); 207 208 program = link_program (vshader, fshader); 209 return program; 210 }