Exemplo n.º 1
0
void SoModelWire::init(const GlProgram& prog, int part)
{
	if (part == 0) {
		m.load("armmodel/rhand.m");
	}
	else if (part == 1) {
		m.load("armmodel/rlowerarm.m");
	}
	else if (part == 2) {
		m.load("armmodel/rupperarm.m");
	}


	// Define buffers needed:
	set_program(prog);
	gen_vertex_arrays(1); // will use 1 vertex array
	gen_buffers(2);       // will use 2 buffers: one for coordinates and one for colors
	uniform_locations(10); // will send 2 variables: the 2 matrices below
	uniform_location(0, "vTransf");
	uniform_location(1, "vProj");
	uniform_location(2, "lPos");
	uniform_location(3, "la");
	uniform_location(4, "ld");
	uniform_location(5, "ls");
	uniform_location(6, "ka");
	uniform_location(7, "kd");
	uniform_location(8, "ks");
	uniform_location(9, "sh");

}
Exemplo n.º 2
0
void SoCapsule::init(const GlProgram& prog) {
	// Define buffers needed:
	set_program(prog);
	gen_vertex_arrays(1); // will use 1 vertex array
	gen_buffers(2);       // will use 2 buffers: one for coordinates and one for colors
	uniform_locations(2); // will send 2 variables: the 2 matrices below
	uniform_location(0, "vTransf");
	uniform_location(1, "vProj");
}
Exemplo n.º 3
0
Program * Object::get_program(GLuint program_position) {
  if(programs.size() > program_position && programs[program_position] != 0) {
    return programs[program_position]; //success!
  } else {
    if(parent != 0) {
      Program * prog = parent->get_program(program_position);
      set_program(prog);
      return prog;
    } else {
      return 0;
    }
  }
}
Exemplo n.º 4
0
void Channel::event(uint8_t a, uint8_t b, uint8_t c)
{
	switch(a & 0xF0)
	{
		case 0x80: note_off(b); break;
		case 0x90: note_on(b,c); break;
		case 0xA0: break; //IMPLEMENTME: polyphonic aftertouch (note, dynamic)
		case 0xB0: set_controller(b,c); break;
		case 0xC0: set_program(b); break;
		case 0xD0: break; //IMPLEMENTME: monotonic aftertouch (dynamic)
		case 0xE0: set_pitch_bend( ( (((b&0x7F) + ((c&0x7F)<<7)) - 8192) / 8192.0 ) * max_pitchbend ); break;
		case 0xF0: break; //own controls/sysex (to be implemented) IMPLEMENTME
		default: output_verbose("NOTE: got unknown command "+ IntToStrHex(a&0xF0) +", ignoring it\n");
		;
	}
}
Exemplo n.º 5
0
static void
texture_paint(struct ctx *context, GLuint *textures, GLuint nmemb, const struct wlc_geometry *geometry, struct paint *settings)
{
   const GLfloat vertices[8] = {
      geometry->origin.x + geometry->size.w, geometry->origin.y,
      geometry->origin.x, geometry->origin.y,
      geometry->origin.x + geometry->size.w, geometry->origin.y + geometry->size.h,
      geometry->origin.x, geometry->origin.y + geometry->size.h,
   };

   const GLfloat coords[8] = {
      1, 0,
      0, 0,
      1, 1,
      0, 1
   };

   set_program(context, settings->program);

   if (settings->dim > 0.0f) {
      GL_CALL(glUniform1fv(context->program->uniforms[UNIFORM_DIM], 1, &settings->dim));
   }

   for (GLuint i = 0; i < nmemb; ++i) {
      if (!textures[i])
         break;

      GL_CALL(glActiveTexture(GL_TEXTURE0 + i));
      GL_CALL(glBindTexture(GL_TEXTURE_2D, textures[i]));

      if (settings->filter || !wlc_size_equals(&context->resolution, &context->mode)) {
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
      } else {
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
         GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
      }
   }

   GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertices));
   GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, coords));
   GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
}
Exemplo n.º 6
0
Channel::Channel()
{
	volume=ONE;
	set_program(0);
	curr_prg.controller[NO_CONT]=1;
	quick_release=0;
	portamento_frames2=portamento_frames=0;
	do_portamento=false;
	pitchbend=ONE;
	n_voices=0;
	
	max_pitchbend=1.0;
	
	set_balance(64);
	
	pressed_keys.clear();
	held_keys.clear();
	sostenuto_keys.clear();
	hold_pedal_pressed=false;
	legato_pedal_pressed=false;
	curr_vol_factor=1.0;
}
Exemplo n.º 7
0
static void
resolution(struct ctx *context, const struct wlc_size *mode, const struct wlc_size *resolution)
{
   assert(context && resolution);

   if (!wlc_size_equals(&context->resolution, resolution)) {
      for (GLuint i = 0; i < PROGRAM_LAST; ++i) {
         set_program(context, i);
         GL_CALL(glUniform2fv(context->program->uniforms[UNIFORM_RESOLUTION], 1, (GLfloat[]){ resolution->w, resolution->h }));
      }

      GL_CALL(glBindTexture(GL_TEXTURE_2D, context->textures[TEXTURE_FAKEFB]));
      GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, resolution->w, resolution->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL));
      clear_fakefb(context);
      context->resolution = *resolution;
   }

   if (!wlc_size_equals(&context->mode, mode)) {
      GL_CALL(glViewport(0, 0, mode->w, mode->h));
      context->mode = *mode;
   }
}
Exemplo n.º 8
0
Arquivo: gles2.c Projeto: UIKit0/wlc
static struct ctx*
create_context(void)
{
   const char *vert_shader =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform vec2 resolution;\n"
      "mat4 ortho = mat4("
      "  2.0/resolution.x,         0,          0, 0,"
      "          0,        -2.0/resolution.y,  0, 0,"
      "          0,                0,         -1, 0,"
      "         -1,                1,          0, 1"
      ");\n"
      "attribute vec4 pos;\n"
      "attribute vec2 uv;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  gl_Position = ortho * pos;\n"
      "  v_uv = uv;\n"
      "}\n";

   const char *frag_shader_dummy =
      "#version 100\n"
      "precision mediump float;\n"
      "void main() {\n"
      "  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
      "}\n";

   const char *frag_shader_cursor =
      "#version 100\n"
      "precision highp float;\n"
      "uniform sampler2D texture0;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  vec4 palette[3];\n"
      "  palette[0] = vec4(0.0, 0.0, 0.0, 1.0);\n"
      "  palette[1] = vec4(1.0, 1.0, 1.0, 1.0);\n"
      "  palette[2] = vec4(0.0, 0.0, 0.0, 0.0);\n"
      "  gl_FragColor = palette[int(texture2D(texture0, v_uv).r * 256.0)];\n"
      "}\n";

   const char *frag_shader_bg =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform float time;\n"
      "uniform vec2 resolution;\n"
      "varying vec2 v_uv;\n"
      "#define M_PI 3.1415926535897932384626433832795\n"
      "float impulse(float x, float k) {\n"
      "  float h = k * x;\n"
      "  return h * exp(1.0 - h);\n"
      "}\n"
      "void main() {\n"
      "  vec3 color = vec3(0.0);\n"
      "  vec2 pos = (v_uv * 4.0 - 2.0);\n"
      "  float frame = time * M_PI * 10.0;\n"
      "  float f = impulse(0.01, sin(frame) + 1.0) + 0.25;\n"
      "  color += vec3(0.15, 0.3, 0.35) * (1.0 / distance(vec2(1.0, 0.0), pos) * f);\n"
      "  for (int i = 0; i < 3; ++i) {\n"
      "     float t = frame + (float(i) * 1.8);\n"
      "     color += vec3(0.15, 0.18, 0.15) * float(i + 1) * (1.0 / distance(vec2(sin(t * 0.8) * 0.5 + 1.0, cos(t) * 0.5), pos) * 0.09);\n"
      "  }\n"
      "  gl_FragColor = vec4(color, 1.0);\n"
      "}\n";

   const char *frag_shader_rgb =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  gl_FragColor = vec4(texture2D(texture0, v_uv).rgb * dim, 1.0);\n"
      "}\n";

   const char *frag_shader_rgba =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  vec4 col = texture2D(texture0, v_uv);\n"
      "  gl_FragColor = vec4(col.rgb * dim, col.a);\n"
      "}\n";

   const char *frag_shader_egl =
      "#version 100\n"
      "#extension GL_OES_EGL_image_external : require\n"
      "precision mediump float;\n"
      "uniform samplerExternalOES texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main()\n"
      "{\n"
      "  vec4 col = texture2D(texture0, v_uv);\n"
      "  gl_FragColor = vec4(col.rgb * dim, col.a)\n;"
      "}\n";

#define FRAGMENT_CONVERT_YUV                                        \
      "  y *= dim;\n"                                               \
      "  u *= dim;\n"                                               \
      "  v *= dim;\n"                                               \
      "  gl_FragColor.r = y + 1.59602678 * v;\n"                    \
      "  gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n"   \
      "  gl_FragColor.b = y + 2.01723214 * u;\n"                    \
      "  gl_FragColor.a = 1.0;\n"

   const char *frag_shader_y_uv =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).r - 0.5;\n"
      "  float v = texture2D(texture1, v_uv).g - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   const char *frag_shader_y_u_v =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform sampler2D texture2;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).x - 0.5;\n"
      "  float v = texture2D(texture2, v_uv).x - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   const char *frag_shader_y_xuxv =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).g - 0.5;\n"
      "  float v = texture2D(texture1, v_uv).a - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   struct ctx *context;
   if (!(context = calloc(1, sizeof(struct ctx))))
      return NULL;

   const char *str;
   str = (const char*)GL_CALL(gl.api.glGetString(GL_VERSION));
   wlc_log(WLC_LOG_INFO, "GL version: %s", str ? str : "(null)");
   str = (const char*)GL_CALL(gl.api.glGetString(GL_VENDOR));
   wlc_log(WLC_LOG_INFO, "GL vendor: %s", str ? str : "(null)");

   context->extensions = (const char*)GL_CALL(gl.api.glGetString(GL_EXTENSIONS));

   if (has_extension(context, "GL_OES_EGL_image_external")) {
      context->api.glEGLImageTargetTexture2DOES = gl.api.glEGLImageTargetTexture2DOES;
   } else {
      wlc_log(WLC_LOG_WARN, "gles2: GL_OES_EGL_image_external not available");
      frag_shader_egl = frag_shader_dummy;
   }

   const struct {
      const char *vert;
      const char *frag;
   } map[PROGRAM_LAST] = {
      { vert_shader, frag_shader_rgb }, // PROGRAM_RGB
      { vert_shader, frag_shader_rgba }, // PROGRAM_RGBA
      { vert_shader, frag_shader_egl }, // PROGRAM_EGL
      { vert_shader, frag_shader_y_uv }, // PROGRAM_Y_UV
      { vert_shader, frag_shader_y_u_v }, // PROGRAM_Y_U_V
      { vert_shader, frag_shader_y_xuxv }, // PROGRAM_Y_XUXV
      { vert_shader, frag_shader_cursor }, // PROGRAM_CURSOR
      { vert_shader, frag_shader_bg }, // PROGRAM_BG
   };

   for (GLuint i = 0; i < PROGRAM_LAST; ++i) {
      GLuint vert = create_shader(map[i].vert, GL_VERTEX_SHADER);
      GLuint frag = create_shader(map[i].frag, GL_FRAGMENT_SHADER);
      context->programs[i].obj = gl.api.glCreateProgram();
      GL_CALL(gl.api.glAttachShader(context->programs[i].obj, vert));
      GL_CALL(gl.api.glAttachShader(context->programs[i].obj, frag));
      GL_CALL(gl.api.glLinkProgram(context->programs[i].obj));
      GL_CALL(gl.api.glDeleteShader(vert));
      GL_CALL(gl.api.glDeleteShader(frag));

      GLint status;
      GL_CALL(gl.api.glGetProgramiv(context->programs[i].obj, GL_LINK_STATUS, &status));
      if (!status) {
         GLsizei len;
         char log[1024];
         GL_CALL(gl.api.glGetProgramInfoLog(context->programs[i].obj, sizeof(log), &len, log));
         wlc_log(WLC_LOG_ERROR, "Linking:\n%*s\n", len, log);
         abort();
      }

      set_program(context, i);
      GL_CALL(gl.api.glBindAttribLocation(context->programs[i].obj, 0, "pos"));
      GL_CALL(gl.api.glBindAttribLocation(context->programs[i].obj, 1, "uv"));

      for (int u = 0; u < UNIFORM_LAST; ++u) {
         context->programs[i].uniforms[u] = GL_CALL(gl.api.glGetUniformLocation(context->programs[i].obj, uniform_names[u]));
      }

      GL_CALL(gl.api.glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE0], 0));
      GL_CALL(gl.api.glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE1], 1));
      GL_CALL(gl.api.glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE2], 2));
   }

   struct {
      GLenum format;
      GLuint w, h;
      GLenum type;
      const void *data;
   } images[TEXTURE_LAST] = {
      { GL_LUMINANCE, 1, 1, GL_UNSIGNED_BYTE, (GLubyte[]){ 0 } }, // TEXTURE_BLACK
Exemplo n.º 9
0
int do_track_event(unsigned char *data, int *pos)
{
	char channel;
	unsigned char buf[5];
	
	buf[0]=data[*pos];
	*pos +=1;
	channel = buf[0] & 0xf;
#ifdef WANT_MPU401
	if (card_info.synth_type==SYNTH_TYPE_MIDI) {
		switch((buf[0]&0xf0)) {
		 case 0x80:
		 case 0x90:
		 case 0xa0:
		 case 0xb0:
		 case 0xe0:
			buf[1]=data[*pos]; *pos+=1;
			buf[2]=data[*pos]; *pos+=1;
			MIDI_MESSAGE3(buf[0],buf[1],buf[2]);
			break;
		 case 0xc0:
		 case 0xd0:
			buf[1]=data[*pos]; *pos+=1;
			MIDI_MESSAGE3(buf[0],0,buf[1]);
			break;
		 case 0xf0:
			return 1;
		 default:
			return 3;
		}
		seqbuf_dump();
		return 0;
	}
#endif
	
	switch((buf[0] & 0xf0))
	{
	 case 0x80:
		buf[1]=data[*pos];
		*pos +=1;
		buf[2]=data[*pos];
		*pos +=1;
		stop_note((int) channel, (int) buf[1], (int) buf[2]);
		break;
	 case 0x90:
		buf[1]=data[*pos];
		*pos +=1;
		buf[2]=data[*pos];
		*pos +=1;
		if(buf[2] == 0)
		{
			stop_note((int) channel, (int) buf[1], (int) buf[2]);
		}
		else
		{
			start_note((int) channel, (int) buf[1], (int) buf[2]);
		}
		break;
	 case 0xa0:
		buf[1]=data[*pos];
		*pos +=1;
		buf[2]=data[*pos];
		*pos +=1;
		set_key_pressure((int) channel, (int) buf[1], (int) buf[2]);
		break;
	 case 0xb0:
		buf[1]=data[*pos];
		*pos +=1;
		buf[2]=data[*pos];
		*pos +=1;
		set_control((int) channel, (int) buf[1], (int) buf[2]);
		break;
	 case 0xe0:
		buf[1]=data[*pos];
		*pos +=1;
		buf[2]=data[*pos];
		*pos +=1;
		set_pitchbend((int) channel, (int) ((buf[2] << 7) + buf[1]);
		break;
	 case 0xc0:
		buf[1]=data[*pos];
		*pos +=1;
		set_program((int) channel, (int) buf[1] );
		break;
	 case 0xd0:
		buf[1]=data[*pos];
		*pos +=1;
		set_chn_pressure((int) channel, (int) buf[1]);
		break;
	 case 0xf0:
		return 1;
	 default:
		return 3;
	}
	seqbuf_dump();
	return 0;
}
Exemplo n.º 10
0
gint
main (gint argc, gchar ** argv)
{
  GstElement *bin;
  GstElement *src, *fmt, *enc, *sink;
  GstCaps *caps;
  GstStructure *prog;

  /* init gstreamer */
  gst_init (&argc, &argv);

  /* create a new bin to hold the elements */
  bin = gst_pipeline_new ("camera");

  /* create elements */
  if (!(sink = gst_element_factory_make ("multifilesink", NULL))) {
    GST_WARNING ("Can't create element \"multifilesink\"");
    return -1;
  }
  g_object_set (sink, "location", "image%02d.jpg", NULL);

  if (!(enc = gst_element_factory_make ("jpegenc", NULL))) {
    GST_WARNING ("Can't create element \"jpegenc\"");
    return -1;
  }

  if (!(fmt = gst_element_factory_make ("capsfilter", NULL))) {
    GST_WARNING ("Can't create element \"capsfilter\"");
    return -1;
  }
  caps =
      gst_caps_from_string
      ("video/x-raw, width=640, height=480, framerate=(fraction)15/1");
  g_object_set (fmt, "caps", caps, NULL);

  if (!(src = gst_element_factory_make ("v4l2src", NULL))) {
    GST_WARNING ("Can't create element \"v4l2src\"");
    return -1;
  }
  g_object_set (src, "queue-size", 1, NULL);

  /* add objects to the main bin */
  gst_bin_add_many (GST_BIN (bin), src, fmt, enc, sink, NULL);

  /* link elements */
  if (!gst_element_link_many (src, fmt, enc, sink, NULL)) {
    GST_WARNING ("Can't link elements");
    return -1;
  }

  /* programm a pattern of events */
#if 0
  prog = gst_structure_from_string ("program"
      ", image00=(structure)\"image\\,contrast\\=0.0\\;\""
      ", image01=(structure)\"image\\,contrast\\=0.3\\;\""
      ", image02=(structure)\"image\\,contrast\\=1.0\\;\""
      ", image03=(structure)\"image\\,contrast\\=0.05\\;\";", NULL);
#endif
#if 1
  prog = gst_structure_from_string ("program"
      ", image00=(structure)\"image\\,brightness\\=1.0\\,contrast\\=0.0\\;\""
      ", image01=(structure)\"image\\,brightness\\=0.5\\,contrast\\=0.3\\;\""
      ", image02=(structure)\"image\\,brightness\\=0.25\\,contrast\\=1.0\\;\""
      ", image03=(structure)\"image\\,brightness\\=0.0\\,contrast\\=0.05\\;\";",
      NULL);
#endif
  set_program (GST_OBJECT (src), prog);
  g_object_set (src, "num-buffers", gst_structure_n_fields (prog), NULL);

  /* prepare playback */
  gst_element_set_state (bin, GST_STATE_PAUSED);

  /* play and wait */
  gst_element_set_state (bin, GST_STATE_PLAYING);

  /* mainloop and wait for eos */
  event_loop (bin);

  /* stop and cleanup */
  gst_element_set_state (bin, GST_STATE_NULL);
  gst_object_unref (GST_OBJECT (bin));
  return 0;
}
Exemplo n.º 11
0
static struct ctx*
create_context(void)
{
   const char *vert_shader =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform vec2 resolution;\n"
      "attribute vec4 pos;\n"
      "attribute vec2 uv;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  mat4 ortho = mat4("
      "    2.0/resolution.x,         0,          0, 0,"
      "            0,        -2.0/resolution.y,  0, 0,"
      "            0,                0,         -1, 0,"
      "           -1,                1,          0, 1"
      "  );\n"
      "  gl_Position = ortho * pos;\n"
      "  v_uv = uv;\n"
      "}\n";

   const char *frag_shader_dummy =
      "#version 100\n"
      "precision mediump float;\n"
      "void main() {\n"
      "  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
      "}\n";

   const char *frag_shader_cursor =
      "#version 100\n"
      "precision highp float;\n"
      "uniform sampler2D texture0;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  vec4 palette[3];\n"
      "  palette[0] = vec4(0.0, 0.0, 0.0, 1.0);\n"
      "  palette[1] = vec4(1.0, 1.0, 1.0, 1.0);\n"
      "  palette[2] = vec4(0.0, 0.0, 0.0, 0.0);\n"
      "  gl_FragColor = palette[int(texture2D(texture0, v_uv).r * 256.0)];\n"
      "}\n";

   const char *frag_shader_rgb =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  gl_FragColor = vec4(texture2D(texture0, v_uv).rgb * dim, 1.0);\n"
      "}\n";

   const char *frag_shader_rgba =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  vec4 col = texture2D(texture0, v_uv);\n"
      "  gl_FragColor = vec4(col.rgb * dim, col.a);\n"
      "}\n";

   const char *frag_shader_egl =
      "#version 100\n"
      "#extension GL_OES_EGL_image_external : require\n"
      "precision mediump float;\n"
      "uniform samplerExternalOES texture0;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main()\n"
      "{\n"
      "  vec4 col = texture2D(texture0, v_uv);\n"
      "  gl_FragColor = vec4(col.rgb * dim, col.a)\n;"
      "}\n";

#define FRAGMENT_CONVERT_YUV                                        \
   "  y *= dim;\n"                                               \
   "  u *= dim;\n"                                               \
   "  v *= dim;\n"                                               \
   "  gl_FragColor.r = y + 1.59602678 * v;\n"                    \
   "  gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n"   \
   "  gl_FragColor.b = y + 2.01723214 * u;\n"                    \
   "  gl_FragColor.a = 1.0;\n"

   const char *frag_shader_y_uv =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).r - 0.5;\n"
      "  float v = texture2D(texture1, v_uv).g - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   const char *frag_shader_y_u_v =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform sampler2D texture2;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).x - 0.5;\n"
      "  float v = texture2D(texture2, v_uv).x - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   const char *frag_shader_y_xuxv =
      "#version 100\n"
      "precision mediump float;\n"
      "uniform sampler2D texture0;\n"
      "uniform sampler2D texture1;\n"
      "uniform float dim;\n"
      "varying vec2 v_uv;\n"
      "void main() {\n"
      "  float y = 1.16438356 * (texture2D(texture0, v_uv).x - 0.0625);\n"
      "  float u = texture2D(texture1, v_uv).g - 0.5;\n"
      "  float v = texture2D(texture1, v_uv).a - 0.5;\n"
      FRAGMENT_CONVERT_YUV
      "}\n";

   struct ctx *context;
   if (!(context = calloc(1, sizeof(struct ctx))))
      return NULL;

   const char *str;
   str = (const char*)GL_CALL(glGetString(GL_VERSION));
   wlc_log(WLC_LOG_INFO, "GL version: %s", str ? str : "(null)");
   str = (const char*)GL_CALL(glGetString(GL_VENDOR));
   wlc_log(WLC_LOG_INFO, "GL vendor: %s", str ? str : "(null)");

   /** TODO: Should be available in GLES3 */
#if 0
   GL_CALL(glGetInternalFormativ(GL_TEXTURE_2D, GL_RGBA, GL_TEXTURE_IMAGE_FORMAT, 1, &context->preferred_format));
   GL_CALL(glGetInternalFormativ(GL_TEXTURE_2D, GL_RGBA, GL_TEXTURE_IMAGE_TYPE, 1, &context->preferred_type));
   wlc_log(WLC_LOG_INFO, "Preferred texture format: %d", context->preferred_format);
   wlc_log(WLC_LOG_INFO, "Preferred texture type: %d", context->preferred_type);
#endif

   context->extensions = (const char*)GL_CALL(glGetString(GL_EXTENSIONS));

   if (!has_extension(context, "GL_OES_EGL_image_external")) {
      wlc_log(WLC_LOG_WARN, "gles2: GL_OES_EGL_image_external not available");
      frag_shader_egl = frag_shader_dummy;
   }

   const struct {
      const char *vert;
      const char *frag;
   } map[PROGRAM_LAST] = {
      { vert_shader, frag_shader_rgb }, // PROGRAM_RGB
      { vert_shader, frag_shader_rgba }, // PROGRAM_RGBA
      { vert_shader, frag_shader_egl }, // PROGRAM_EGL
      { vert_shader, frag_shader_y_uv }, // PROGRAM_Y_UV
      { vert_shader, frag_shader_y_u_v }, // PROGRAM_Y_U_V
      { vert_shader, frag_shader_y_xuxv }, // PROGRAM_Y_XUXV
      { vert_shader, frag_shader_cursor }, // PROGRAM_CURSOR
   };

   for (GLuint i = 0; i < PROGRAM_LAST; ++i) {
      GLuint vert = create_shader(map[i].vert, GL_VERTEX_SHADER);
      GLuint frag = create_shader(map[i].frag, GL_FRAGMENT_SHADER);
      context->programs[i].obj = glCreateProgram();
      GL_CALL(glAttachShader(context->programs[i].obj, vert));
      GL_CALL(glAttachShader(context->programs[i].obj, frag));
      GL_CALL(glLinkProgram(context->programs[i].obj));
      GL_CALL(glDeleteShader(vert));
      GL_CALL(glDeleteShader(frag));

      GLint status;
      GL_CALL(glGetProgramiv(context->programs[i].obj, GL_LINK_STATUS, &status));
      if (!status) {
         GLsizei len;
         char log[1024];
         GL_CALL(glGetProgramInfoLog(context->programs[i].obj, sizeof(log), &len, log));
         wlc_log(WLC_LOG_ERROR, "Linking:\n%*s\n", len, log);
         abort();
      }

      set_program(context, i);
      GL_CALL(glBindAttribLocation(context->programs[i].obj, 0, "pos"));
      GL_CALL(glBindAttribLocation(context->programs[i].obj, 1, "uv"));

      for (int u = 0; u < UNIFORM_LAST; ++u) {
         context->programs[i].uniforms[u] = GL_CALL(glGetUniformLocation(context->programs[i].obj, uniform_names[u]));
      }

      GL_CALL(glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE0], 0));
      GL_CALL(glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE1], 1));
      GL_CALL(glUniform1i(context->programs[i].uniforms[UNIFORM_TEXTURE2], 2));
   }

   struct {
      GLenum format;
      GLuint w, h;
      GLenum type;
      const void *data;
   } images[TEXTURE_LAST] = {
      { GL_LUMINANCE, 1, 1, GL_UNSIGNED_BYTE, NULL }, // TEXTURE_BLACK
      { GL_LUMINANCE, 14, 14, GL_UNSIGNED_BYTE, cursor_palette }, // TEXTURE_CURSOR
      { GL_RGBA, 0, 0, GL_UNSIGNED_BYTE, NULL }, // TEXTURE_FAKEFB
   };

   GL_CALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 1));
   GL_CALL(glGenTextures(TEXTURE_LAST, context->textures));

   for (GLuint i = 0; i < TEXTURE_LAST; ++i) {
      GL_CALL(glBindTexture(GL_TEXTURE_2D, context->textures[i]));
      GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
      GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
      GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, images[i].format, images[i].w, images[i].h, 0, images[i].format, images[i].type, images[i].data));
   }

   GL_CALL(glEnableVertexAttribArray(0));
   GL_CALL(glEnableVertexAttribArray(1));

   GL_CALL(glGenFramebuffers(1, &context->clear_fbo));
   GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, context->clear_fbo));
   GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, context->textures[TEXTURE_FAKEFB], 0));
   GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, 0));

   GL_CALL(glEnable(GL_BLEND));
   GL_CALL(glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA));
   GL_CALL(glClearColor(0.0, 0.0, 0.0, 0.0));
   return context;
}