citrun

watch C/C++ source code execute
Log | Files | Refs | LICENSE

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 }