Ver código fonte

Added shader support

Dalton Nell 9 anos atrás
pai
commit
437eccc73b

+ 10
- 0
CMakeLists.txt Ver arquivo

@@ -79,6 +79,8 @@ set( source
79 79
      src/cmdline.c
80 80
      src/selectrectangle.cpp
81 81
      src/glselectrectangle.cpp
82
+     src/shader.cpp
83
+     src/framebuffer.cpp
82 84
      src/resource.cpp
83 85
      src/xselectrectangle.cpp
84 86
      src/x.cpp
@@ -93,6 +95,7 @@ find_package( GLX       REQUIRED )
93 95
 find_package( XRender   REQUIRED )
94 96
 find_package( XRandr    REQUIRED )
95 97
 find_package( DevIL     REQUIRED )
98
+find_package( GLEW      REQUIRED )
96 99
 # This library is needed only for Ubuntu it seems, some platforms don't even
97 100
 # ship with it. I couldn't find a way to do a test compile to check if librt
98 101
 # was needed, so instead I just didn't mark it as REQUIRED.
@@ -109,12 +112,14 @@ if ( RT_INCLUDE_DIR )
109 112
                          ${OPENGL_INCLUDE_DIR}
110 113
                          ${IL_INCLUDE_DIR}
111 114
                          ${GLX_INCLUDE_DIR}
115
+                         ${GLEW_INCLUDE_DIRS}
112 116
                          ${XRENDER_INCLUDE_DIRS}
113 117
                          ${RT_INCLUDE_DIR} )
114 118
 else()
115 119
     include_directories( ${X11_INCLUDE_DIR}
116 120
                          ${OPENGL_INCLUDE_DIR}
117 121
                          ${IL_INCLUDE_DIR}
122
+                         ${GLEW_INCLUDE_DIRS}
118 123
                          ${GLX_INCLUDE_DIR}
119 124
                          ${XEXT_INCLUDE_DIR} )
120 125
 endif()
@@ -130,6 +135,7 @@ if ( RT_LIBRARY )
130 135
                            ${IL_LIBRARIES}
131 136
                            ${ILUT_LIBRARIES}
132 137
                            ${GLX_LIBRARIES}
138
+                           ${GLEW_LIBRARIES}
133 139
                            ${XRENDER_LIBRARIES}
134 140
                            "${XEXT_LIBRARY}"
135 141
                            "${XRANDR_LIBRARY}"
@@ -139,6 +145,7 @@ else()
139 145
                            ${OPENGL_LIBRARIES}
140 146
                            ${IL_LIBRARIES}
141 147
                            ${ILUT_LIBRARIES}
148
+                           ${GLEW_LIBRARIES}
142 149
                            ${GLX_LIBRARIES}
143 150
                            ${X11_LIBRARIES}
144 151
                            "${XEXT_LIBRARY}" )
@@ -147,4 +154,7 @@ endif()
147 154
 install( TARGETS ${BIN_TARGET}
148 155
          DESTINATION "${CMAKE_INSTALL_PREFIX}/bin" )
149 156
 
157
+install( DIRECTORY "${CMAKE_SOURCE_DIR}/share"
158
+         DESTINATION "${CMAKE_INSTALL_PREFIX}" )
159
+
150 160
 add_definitions(-DINSTALL_PREFIX="${CMAKE_INSTALL_PREFIX}")

+ 1
- 0
share/slop/gothic/corner_bl.png Ver arquivo

@@ -0,0 +1 @@
1
+corner_tl.png

+ 1
- 0
share/slop/gothic/corner_br.png Ver arquivo

@@ -0,0 +1 @@
1
+corner_tl.png

BIN
share/slop/gothic/corner_tl.png Ver arquivo


+ 1
- 0
share/slop/gothic/corner_tr.png Ver arquivo

@@ -0,0 +1 @@
1
+corner_tl.png

BIN
share/slop/gothic/straight.png Ver arquivo


+ 89
- 0
share/slop/refract.frag Ver arquivo

@@ -0,0 +1,89 @@
1
+#version 120
2
+
3
+uniform sampler2D texture;
4
+uniform sampler2D desktop;
5
+uniform int desktopWidth;
6
+uniform int desktopHeight;
7
+uniform float time;
8
+
9
+varying vec2 uvCoord;
10
+
11
+vec2 getDesktopUV( vec2 uv ) {
12
+    // Desktop image is upside-down, blame X11 lmao
13
+    uv.y = -uv.y;
14
+    return uv;
15
+}
16
+
17
+const float pi = 3.14159265f;
18
+
19
+void main() {
20
+    float sigma = 5;
21
+    float numBlurPixelsPerSide = 2.0f;
22
+    float blurMultiplier = 2.0f;
23
+
24
+    // Don't change anything below.
25
+    float blurSize = 1.f/desktopHeight*blurMultiplier;
26
+    vec2  blurMultiplyVec      = vec2(0.0f, 1.0f);
27
+    // Higher strength means bigger wobble
28
+    float strength = 8;
29
+    // Higher speed means faster wobble
30
+    float speed = 1;
31
+    float x = (sin( time*speed + uvCoord.y * desktopHeight/strength ) + 0.5)/desktopWidth*strength;
32
+    float y = (cos( time*speed + uvCoord.x * desktopWidth/strength ) + 0.5)/desktopHeight*strength;
33
+    x = x - (sin( time*speed*0.5 + uvCoord.y * desktopHeight/strength ) + 0.5)/desktopWidth*strength/2;
34
+    y = y - (cos( time*speed*0.5 + uvCoord.x * desktopWidth/strength ) + 0.5)/desktopHeight*strength/2;
35
+    vec2 offset = vec2(x,y);
36
+
37
+    // Incremental Gaussian Coefficent Calculation (See GPU Gems 3 pp. 877 - 889)
38
+    vec3 incrementalGaussian;
39
+    incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);
40
+    incrementalGaussian.y = exp(-0.5f / (sigma * sigma));
41
+    incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
42
+
43
+    vec4 avgValue = vec4(0.0f, 0.0f, 0.0f, 0.0f);
44
+    float coefficientSum = 0.0f;
45
+
46
+    // Take the central sample first...
47
+    vec4 color = texture2D( desktop, getDesktopUV( uvCoord.xy ) + offset );
48
+    color.a = texture2D( texture, uvCoord.xy ).a;
49
+    avgValue += color * incrementalGaussian.x;
50
+    coefficientSum += incrementalGaussian.x;
51
+    incrementalGaussian.xy *= incrementalGaussian.yz;
52
+
53
+    // Go through the remaining 8 vertical samples (4 on each side of the center)
54
+    for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) {
55
+        vec2 uv = (uvCoord.xy - i * blurSize * blurMultiplyVec);
56
+        color = texture2D( desktop, getDesktopUV( uv ) + offset );
57
+        color.a = texture2D( texture, uv ).a;
58
+        avgValue += color * incrementalGaussian.x;
59
+        uv = (uvCoord.xy + i * blurSize * blurMultiplyVec);
60
+        color = texture2D( desktop, getDesktopUV( uv ) + offset );
61
+        color.a = texture2D( texture, uv ).a;
62
+        avgValue += color * incrementalGaussian.x;
63
+        coefficientSum += 2 * incrementalGaussian.x;
64
+        incrementalGaussian.xy *= incrementalGaussian.yz;
65
+    }
66
+
67
+    //Reset
68
+    blurSize = 1.f/desktopWidth*blurMultiplier;
69
+    blurMultiplyVec      = vec2(1.0f, 0.0f);
70
+    incrementalGaussian.x = 1.0f / (sqrt(2.0f * pi) * sigma);
71
+    incrementalGaussian.y = exp(-0.5f / (sigma * sigma));
72
+    incrementalGaussian.z = incrementalGaussian.y * incrementalGaussian.y;
73
+
74
+    // Go through the remaining 8 horizontal samples (4 on each side of the center)
75
+    for (float i = 1.0f; i <= numBlurPixelsPerSide; i++) {
76
+        vec2 uv = (uvCoord.xy - i * blurSize * blurMultiplyVec);
77
+        vec4 color = texture2D( desktop, getDesktopUV( uv ) + offset );
78
+        color.a = texture2D( texture, uv ).a;
79
+        avgValue += color * incrementalGaussian.x;
80
+        uv = (uvCoord.xy + i * blurSize * blurMultiplyVec);
81
+        color = texture2D( desktop, getDesktopUV( uv ) + offset );
82
+        color.a = texture2D( texture, uv ).a;
83
+        avgValue += color * incrementalGaussian.x;
84
+        coefficientSum += 2 * incrementalGaussian.x;
85
+        incrementalGaussian.xy *= incrementalGaussian.yz;
86
+    }
87
+
88
+    gl_FragColor = avgValue / coefficientSum;
89
+}

+ 12
- 0
share/slop/refract.vert Ver arquivo

@@ -0,0 +1,12 @@
1
+#version 120
2
+
3
+attribute vec2 vertex;
4
+attribute vec2 uv;
5
+
6
+varying vec2 uvCoord;
7
+
8
+void main()
9
+{
10
+    uvCoord = uv;
11
+	gl_Position = vec4(vertex,0,1);
12
+}

+ 12
- 0
share/slop/simple.frag Ver arquivo

@@ -0,0 +1,12 @@
1
+#version 120
2
+
3
+uniform sampler2D texture;
4
+uniform sampler2D desktop;
5
+uniform float time;
6
+
7
+varying vec2 uvCoord;
8
+
9
+void main()
10
+{
11
+    gl_FragColor = texture2D( texture, uvCoord );
12
+}

+ 12
- 0
share/slop/simple.vert Ver arquivo

@@ -0,0 +1,12 @@
1
+#version 120
2
+
3
+attribute vec2 vertex;
4
+attribute vec2 uv;
5
+
6
+varying vec2 uvCoord;
7
+
8
+void main()
9
+{
10
+    uvCoord = uv;
11
+	gl_Position = vec4(vertex,0,1);
12
+}

+ 20
- 0
share/slop/wiggle.frag Ver arquivo

@@ -0,0 +1,20 @@
1
+#version 120
2
+
3
+uniform sampler2D texture;
4
+uniform sampler2D desktop;
5
+uniform int desktopWidth;
6
+uniform int desktopHeight;
7
+uniform float time;
8
+
9
+varying vec2 uvCoord;
10
+
11
+void main()
12
+{
13
+    // Higher strength means bigger wobble
14
+    float strength = 8;
15
+    // Higher speed means faster wobble
16
+    float speed = 2;
17
+    float x = uvCoord.x + (sin( time*speed + uvCoord.y * desktopHeight/strength ) + 0.5)/desktopWidth*strength;
18
+    float y = uvCoord.y + (cos( time*speed + uvCoord.x * desktopWidth/strength ) + 0.5)/desktopHeight*strength;
19
+    gl_FragColor = texture2D( texture, vec2( x, y ) );
20
+}

+ 12
- 0
share/slop/wiggle.vert Ver arquivo

@@ -0,0 +1,12 @@
1
+#version 120
2
+
3
+attribute vec2 vertex;
4
+attribute vec2 uv;
5
+
6
+varying vec2 uvCoord;
7
+
8
+void main()
9
+{
10
+    uvCoord = uv;
11
+	gl_Position = vec4(vertex,0,1);
12
+}

+ 50
- 2
src/cmdline.c Ver arquivo

@@ -52,8 +52,10 @@ const char *gengetopt_args_info_help[] = {
52 52
   "      --magnify                 Display a magnifying glass when --opengl is\n                                  also enabled.  (default=off)",
53 53
   "      --magstrength=FLOAT       Sets how many times the magnification window\n                                  size is multiplied.  (default=`4')",
54 54
   "      --magpixels=INT           Sets how many pixels are displayed in the\n                                  magnification. The less pixels the bigger the\n                                  magnification.  (default=`64')",
55
+  "      --theme=STRING            Sets the theme of the selection, using textures\n                                  from ~/.config/slop/ or /usr/share/.\n                                  (default=`none')",
56
+  "      --shader=STRING           Sets the shader to load and use from\n                                  ~/.config/slop/ or /usr/share/.\n                                  (default=`simple')",
55 57
   "  -f, --format=STRING           Set the output format string. Format specifiers\n                                  are %x, %y, %w, %h, %i, %g, and %c.\n                                  (default=`X=%x\\nY=%y\\nW=%w\\nH=%h\\nG=%g\\nID=%i\\nCancel=%c\\n')",
56
-  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n\nTips\n    * You can use the arrow keys to move the starting point of a\ndrag-selection, just in case you missed it by a few pixels.\n    * If you don't like a selection: you can cancel it by right-clicking\nregardless of which options are enabled or disabled for slop.\n    * If slop doesn't seem to select a window accurately, the problem could be\nbecause of decorations getting in the way. Try enabling the --nodecorations\nflag.\n",
58
+  "\nExamples\n    $ # Gray, thick, transparent border for maximum visiblity.\n    $ slop -b 20 -c 0.5,0.5,0.5,0.8\n\n    $ # Remove window decorations.\n    $ slop --nodecorations\n\n    $ # Disable window selections. Useful for selecting individual pixels.\n    $ slop -t 0\n\n    $ # Classic Windows XP selection.\n    $ slop -l -c 0.3,0.4,0.6,0.4\n\n    $ # Wiggle wiggle!\n    $ slop --opengl --shader wiggle\n\n    $ # Edgy textures or something.\n    $ slop --opengl --theme gothic\n\n    $ # Change output format to use safer parsing\n    $ slopoutput=$(slop -f \"%x %y %w %h\")\n    $ X=$(echo $slopoutput | awk '{print $1}')\n    $ Y=$(echo $slopoutput | awk '{print $2}')\n    $ W=$(echo $slopoutput | awk '{print $3}')\n    $ H=$(echo $slopoutput | awk '{print $4}')\n\nTips\n    * You can use the arrow keys to move the starting point of a\ndrag-selection, just in case you missed it by a few pixels.\n    * If you don't like a selection: you can cancel it by right-clicking\nregardless of which options are enabled or disabled for slop.\n    * If slop doesn't seem to select a window accurately, the problem could be\nbecause of decorations getting in the way. Try enabling the --nodecorations\nflag.\n",
57 59
     0
58 60
 };
59 61
 
@@ -97,6 +99,8 @@ void clear_given (struct gengetopt_args_info *args_info)
97 99
   args_info->magnify_given = 0 ;
98 100
   args_info->magstrength_given = 0 ;
99 101
   args_info->magpixels_given = 0 ;
102
+  args_info->theme_given = 0 ;
103
+  args_info->shader_given = 0 ;
100 104
   args_info->format_given = 0 ;
101 105
 }
102 106
 
@@ -129,6 +133,10 @@ void clear_args (struct gengetopt_args_info *args_info)
129 133
   args_info->magstrength_orig = NULL;
130 134
   args_info->magpixels_arg = 64;
131 135
   args_info->magpixels_orig = NULL;
136
+  args_info->theme_arg = gengetopt_strdup ("none");
137
+  args_info->theme_orig = NULL;
138
+  args_info->shader_arg = gengetopt_strdup ("simple");
139
+  args_info->shader_orig = NULL;
132 140
   args_info->format_arg = gengetopt_strdup ("X=%x\nY=%y\nW=%w\nH=%h\nG=%g\nID=%i\nCancel=%c\n");
133 141
   args_info->format_orig = NULL;
134 142
   
@@ -156,7 +164,9 @@ void init_args_info(struct gengetopt_args_info *args_info)
156 164
   args_info->magnify_help = gengetopt_args_info_help[15] ;
157 165
   args_info->magstrength_help = gengetopt_args_info_help[16] ;
158 166
   args_info->magpixels_help = gengetopt_args_info_help[17] ;
159
-  args_info->format_help = gengetopt_args_info_help[18] ;
167
+  args_info->theme_help = gengetopt_args_info_help[18] ;
168
+  args_info->shader_help = gengetopt_args_info_help[19] ;
169
+  args_info->format_help = gengetopt_args_info_help[20] ;
160 170
   
161 171
 }
162 172
 
@@ -253,6 +263,10 @@ cmdline_parser_release (struct gengetopt_args_info *args_info)
253 263
   free_string_field (&(args_info->max_orig));
254 264
   free_string_field (&(args_info->magstrength_orig));
255 265
   free_string_field (&(args_info->magpixels_orig));
266
+  free_string_field (&(args_info->theme_arg));
267
+  free_string_field (&(args_info->theme_orig));
268
+  free_string_field (&(args_info->shader_arg));
269
+  free_string_field (&(args_info->shader_orig));
256 270
   free_string_field (&(args_info->format_arg));
257 271
   free_string_field (&(args_info->format_orig));
258 272
   
@@ -319,6 +333,10 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
319 333
     write_into_file(outfile, "magstrength", args_info->magstrength_orig, 0);
320 334
   if (args_info->magpixels_given)
321 335
     write_into_file(outfile, "magpixels", args_info->magpixels_orig, 0);
336
+  if (args_info->theme_given)
337
+    write_into_file(outfile, "theme", args_info->theme_orig, 0);
338
+  if (args_info->shader_given)
339
+    write_into_file(outfile, "shader", args_info->shader_orig, 0);
322 340
   if (args_info->format_given)
323 341
     write_into_file(outfile, "format", args_info->format_orig, 0);
324 342
   
@@ -596,6 +614,8 @@ cmdline_parser_internal (
596 614
         { "magnify",	0, NULL, 0 },
597 615
         { "magstrength",	1, NULL, 0 },
598 616
         { "magpixels",	1, NULL, 0 },
617
+        { "theme",	1, NULL, 0 },
618
+        { "shader",	1, NULL, 0 },
599 619
         { "format",	1, NULL, 'f' },
600 620
         { 0,  0, 0, 0 }
601 621
       };
@@ -815,6 +835,34 @@ cmdline_parser_internal (
815 835
                 additional_error))
816 836
               goto failure;
817 837
           
838
+          }
839
+          /* Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/..  */
840
+          else if (strcmp (long_options[option_index].name, "theme") == 0)
841
+          {
842
+          
843
+          
844
+            if (update_arg( (void *)&(args_info->theme_arg), 
845
+                 &(args_info->theme_orig), &(args_info->theme_given),
846
+                &(local_args_info.theme_given), optarg, 0, "none", ARG_STRING,
847
+                check_ambiguity, override, 0, 0,
848
+                "theme", '-',
849
+                additional_error))
850
+              goto failure;
851
+          
852
+          }
853
+          /* Sets the shader to load and use from ~/.config/slop/ or /usr/share/..  */
854
+          else if (strcmp (long_options[option_index].name, "shader") == 0)
855
+          {
856
+          
857
+          
858
+            if (update_arg( (void *)&(args_info->shader_arg), 
859
+                 &(args_info->shader_orig), &(args_info->shader_given),
860
+                &(local_args_info.shader_given), optarg, 0, "simple", ARG_STRING,
861
+                check_ambiguity, override, 0, 0,
862
+                "shader", '-',
863
+                additional_error))
864
+              goto failure;
865
+          
818 866
           }
819 867
           
820 868
           break;

+ 8
- 0
src/cmdline.in Ver arquivo

@@ -79,6 +79,12 @@ struct gengetopt_args_info
79 79
   int magpixels_arg;	/**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. (default='64').  */
80 80
   char * magpixels_orig;	/**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. original value given at command line.  */
81 81
   const char *magpixels_help; /**< @brief Sets how many pixels are displayed in the magnification. The less pixels the bigger the magnification. help description.  */
82
+  char * theme_arg;	/**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. (default='none').  */
83
+  char * theme_orig;	/**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. original value given at command line.  */
84
+  const char *theme_help; /**< @brief Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/. help description.  */
85
+  char * shader_arg;	/**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. (default='simple').  */
86
+  char * shader_orig;	/**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. original value given at command line.  */
87
+  const char *shader_help; /**< @brief Sets the shader to load and use from ~/.config/slop/ or /usr/share/. help description.  */
82 88
   char * format_arg;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. (default='REPLACEME').  */
83 89
   char * format_orig;	/**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. original value given at command line.  */
84 90
   const char *format_help; /**< @brief Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c. help description.  */
@@ -100,6 +106,8 @@ struct gengetopt_args_info
100 106
   unsigned int magnify_given ;	/**< @brief Whether magnify was given.  */
101 107
   unsigned int magstrength_given ;	/**< @brief Whether magstrength was given.  */
102 108
   unsigned int magpixels_given ;	/**< @brief Whether magpixels was given.  */
109
+  unsigned int theme_given ;	/**< @brief Whether theme was given.  */
110
+  unsigned int shader_given ;	/**< @brief Whether shader was given.  */
103 111
   unsigned int format_given ;	/**< @brief Whether format was given.  */
104 112
 
105 113
 } ;

+ 444
- 0
src/framebuffer.cpp Ver arquivo

@@ -0,0 +1,444 @@
1
+#include "framebuffer.hpp"
2
+
3
+slop::Framebuffer::Framebuffer() {
4
+    m_shader = new slop::Shader( "simple", resource->getRealPath( "simple.vert" ), resource->getRealPath( "simple.frag" ) );
5
+    generatedBuffers = false;
6
+    m_width = 0;
7
+    m_height = 0;
8
+    m_flags = (slop::Framebuffer::buffers)0;
9
+    m_depth = 0;
10
+    m_stencil = 0;
11
+    m_frame = 0;
12
+    m_buffers[0] = 0;
13
+    m_buffers[1] = 0;
14
+    m_texture = 0;
15
+}
16
+
17
+void slop::Framebuffer::setShader( std::string shader ) {
18
+    delete m_shader;
19
+    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
20
+}
21
+
22
+slop::Framebuffer::Framebuffer( unsigned int width, unsigned int height, unsigned char flags, std::string shader ) {
23
+    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
24
+    generatedBuffers = false;
25
+    m_width = width;
26
+    m_height = height;
27
+    m_flags = flags;
28
+    if ( m_flags & stencil && m_flags & depth ) {
29
+        fprintf( stderr, "Most hardware doesn't support using a FBO with a depth and stencil attached! Condensing them to one render buffer..." );
30
+    }
31
+    if ( GLEW_VERSION_3_0 ) {
32
+        glGenFramebuffers( 1, &m_frame );
33
+        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
34
+        if ( m_flags & color ) {
35
+            glGenTextures( 1, &m_texture );
36
+            glBindTexture( GL_TEXTURE_2D, m_texture );
37
+            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
38
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
39
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
40
+            glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
41
+        }
42
+
43
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
44
+            glGenRenderbuffers( 1, &m_depth );
45
+            glBindRenderbuffer( GL_RENDERBUFFER, m_depth );
46
+            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height );
47
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth );
48
+        }
49
+
50
+        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
51
+        if ( m_flags & stencil ) {
52
+            glGenRenderbuffers( 1, &m_stencil );
53
+            glBindRenderbuffer( GL_RENDERBUFFER, m_stencil );
54
+            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_width, m_height );
55
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
56
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
57
+        }
58
+        check();
59
+        //Make sure we unbind when we're done.
60
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
61
+    } else if ( GLEW_EXT_framebuffer_object ) {
62
+        glGenFramebuffersEXT( 1, &m_frame );
63
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
64
+
65
+        if ( m_flags & color ) {
66
+            glGenTextures( 1, &m_texture );
67
+            glBindTexture( GL_TEXTURE_2D, m_texture );
68
+            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0 );
69
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
70
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
71
+            glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
72
+        }
73
+
74
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
75
+            glGenRenderbuffersEXT( 1, &m_depth );
76
+            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depth );
77
+            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height );
78
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth );
79
+        }
80
+
81
+        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
82
+        if ( m_flags & stencil ) {
83
+            glGenRenderbuffersEXT( 1, &m_stencil );
84
+            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_stencil );
85
+            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_width, m_height );
86
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
87
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
88
+        }
89
+        check();
90
+        //Make sure we unbind when we're done.
91
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
92
+    } else {
93
+        fprintf( stderr, "Error: Failed to create framebuffer! You need OpenGL 3.0 or the GL_EXT_framebuffer_object extension!\n" );
94
+    }
95
+}
96
+
97
+slop::Framebuffer::~Framebuffer() {
98
+    if ( GLEW_VERSION_3_0 ) {
99
+        glDeleteFramebuffers( 1, &m_frame );
100
+        if ( m_flags & color ) {
101
+            glDeleteTextures( 1, &m_texture );
102
+        }
103
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
104
+            glDeleteRenderbuffers( 1, &m_depth );
105
+        }
106
+        if ( m_flags & stencil ) {
107
+            glDeleteRenderbuffers( 1, &m_stencil );
108
+        }
109
+    } else if ( GLEW_EXT_framebuffer_object ) {
110
+        glDeleteFramebuffersEXT( 1, &m_frame );
111
+        if ( m_flags & color ) {
112
+            glDeleteTextures( 1, &m_texture );
113
+        }
114
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
115
+            glDeleteRenderbuffersEXT( 1, &m_depth );
116
+        }
117
+        if ( m_flags & stencil ) {
118
+            glDeleteRenderbuffersEXT( 1, &m_stencil );
119
+        }
120
+    }
121
+    if ( generatedBuffers ) {
122
+        glDeleteBuffers( 2, m_buffers );
123
+    }
124
+    delete m_shader;
125
+}
126
+
127
+void slop::Framebuffer::bind() {
128
+    if ( GLEW_VERSION_3_0 ) {
129
+        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
130
+    } else if ( GLEW_EXT_framebuffer_object ) {
131
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
132
+    }
133
+}
134
+
135
+void slop::Framebuffer::unbind() {
136
+    if ( GLEW_VERSION_3_0 ) {
137
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
138
+    } else if ( GLEW_EXT_framebuffer_object ) {
139
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
140
+    }
141
+}
142
+
143
+void slop::Framebuffer::createFromTexture( unsigned int texture, std::string shader ) {
144
+    // First make sure we're empty.
145
+    if ( GLEW_VERSION_3_0 ) {
146
+        glDeleteFramebuffers( 1, &m_frame );
147
+        if ( m_flags & color ) {
148
+            glDeleteTextures( 1, &m_texture );
149
+        }
150
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
151
+            glDeleteRenderbuffers( 1, &m_depth );
152
+        }
153
+        if ( m_flags & stencil ) {
154
+            glDeleteRenderbuffers( 1, &m_stencil );
155
+        }
156
+    } else if ( GLEW_EXT_framebuffer_object ) {
157
+        glDeleteFramebuffersEXT( 1, &m_frame );
158
+        if ( m_flags & color ) {
159
+            glDeleteTextures( 1, &m_texture );
160
+        }
161
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
162
+            glDeleteRenderbuffersEXT( 1, &m_depth );
163
+        }
164
+        if ( m_flags & stencil ) {
165
+            glDeleteRenderbuffersEXT( 1, &m_stencil );
166
+        }
167
+    }
168
+    delete m_shader;
169
+    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
170
+    // Set flags to 0 so we don't delete the texture on deconstruction.
171
+    m_flags = 0;
172
+    m_texture = texture;
173
+    if ( GLEW_VERSION_3_0 ) {
174
+        glGenFramebuffers( 1, &m_frame );
175
+        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
176
+        glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
177
+    } else if ( GLEW_EXT_framebuffer_object ) {
178
+        glGenFramebuffersEXT( 1, &m_frame );
179
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
180
+        glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
181
+    }
182
+    check();
183
+    glBindFramebuffer( GL_FRAMEBUFFER, 0 );
184
+}
185
+
186
+void slop::Framebuffer::create( unsigned int width, unsigned int height, unsigned char flags, std::string shader ) {
187
+    if ( m_width == width && m_height == height && m_flags == flags ) {
188
+        return;
189
+    }
190
+    delete m_shader;
191
+    m_shader = new slop::Shader( shader, resource->getRealPath( shader + ".vert" ), resource->getRealPath( shader + ".frag" ) );
192
+    if ( GLEW_VERSION_3_0 ) {
193
+        glDeleteFramebuffers( 1, &m_frame );
194
+        if ( m_flags & color ) {
195
+            glDeleteTextures( 1, &m_texture );
196
+        }
197
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
198
+            glDeleteRenderbuffers( 1, &m_depth );
199
+        }
200
+        if ( m_flags & stencil ) {
201
+            glDeleteRenderbuffers( 1, &m_stencil );
202
+        }
203
+    } else if ( GLEW_EXT_framebuffer_object ) {
204
+        glDeleteFramebuffersEXT( 1, &m_frame );
205
+        if ( m_flags & color ) {
206
+            glDeleteTextures( 1, &m_texture );
207
+        }
208
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
209
+            glDeleteRenderbuffersEXT( 1, &m_depth );
210
+        }
211
+        if ( m_flags & stencil ) {
212
+            glDeleteRenderbuffersEXT( 1, &m_stencil );
213
+        }
214
+    }
215
+    m_flags = flags;
216
+    m_width = width;
217
+    m_height = height;
218
+    if ( GLEW_VERSION_3_0 ) {
219
+        glGenFramebuffers( 1, &m_frame );
220
+        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
221
+
222
+        if ( m_flags & color ) {
223
+            glGenTextures( 1, &m_texture );
224
+            glBindTexture( GL_TEXTURE_2D, m_texture );
225
+            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
226
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
227
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
228
+            glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0 );
229
+        }
230
+
231
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
232
+            glGenRenderbuffers( 1, &m_depth );
233
+            glBindRenderbuffer( GL_RENDERBUFFER, m_depth );
234
+            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT, m_width, m_height );
235
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depth );
236
+        }
237
+
238
+        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
239
+        if ( m_flags & stencil ) {
240
+            glGenRenderbuffers( 1, &m_stencil );
241
+            glBindRenderbuffer( GL_RENDERBUFFER, m_stencil );
242
+            glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_STENCIL, m_width, m_height );
243
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
244
+            glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil );
245
+        }
246
+        //Make sure we unbind when we're done.
247
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
248
+    } else if ( GLEW_EXT_framebuffer_object ) {
249
+        glGenFramebuffersEXT( 1, &m_frame );
250
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
251
+
252
+        if ( m_flags & color ) {
253
+            glGenTextures( 1, &m_texture );
254
+            glBindTexture( GL_TEXTURE_2D, m_texture );
255
+            glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_RGB, GL_UNSIGNED_BYTE, 0 );
256
+           glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
257
+            glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
258
+            glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0 );
259
+        }
260
+
261
+        if ( m_flags & depth && !( m_flags & stencil ) ) {
262
+            glGenRenderbuffersEXT( 1, &m_depth );
263
+            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_depth );
264
+            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_width, m_height );
265
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depth );
266
+        }
267
+
268
+        //This is the only way I could get a proper stencil buffer, by making a GL_DEPTH_STENCIL attachment to both points.
269
+        if ( m_flags & stencil ) {
270
+            glGenRenderbuffersEXT( 1, &m_stencil );
271
+            glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, m_stencil );
272
+            glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_STENCIL_EXT, m_width, m_height );
273
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
274
+            glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_stencil );
275
+        }
276
+        //Make sure we unbind when we're done.
277
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
278
+    }
279
+}
280
+
281
+void slop::Framebuffer::check()
282
+{
283
+    if ( GLEW_VERSION_3_0 ) {
284
+        glBindFramebuffer( GL_FRAMEBUFFER, m_frame );
285
+        unsigned int err = glCheckFramebufferStatus( GL_FRAMEBUFFER );
286
+        if ( err == GL_FRAMEBUFFER_COMPLETE ) {
287
+            return;
288
+        }
289
+        fprintf( stderr, "Error: Framebuffer failed a check procedure for reason: " );
290
+        switch ( err ) {
291
+            case GL_FRAMEBUFFER_UNDEFINED: {
292
+                fprintf( stderr, "GL_FRAMEBUFFER_UNDEFINED\n" );
293
+                break;
294
+            }
295
+            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: {
296
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT\n" );
297
+                break;
298
+            }
299
+            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: {
300
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT\n" );
301
+                break;
302
+            }
303
+            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: {
304
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER\n" );
305
+                break;
306
+            }
307
+            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: {
308
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER\n" );
309
+                break;
310
+            }
311
+            case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: {
312
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS\n" );
313
+                break;
314
+            }
315
+            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: {
316
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE\n" );
317
+                break;
318
+            }
319
+            case GL_FRAMEBUFFER_UNSUPPORTED: {
320
+                fprintf( stderr, "GL_FRAMEBUFFER_UNSUPPORTED\n" );
321
+                break;
322
+            }
323
+            default: {
324
+                fprintf( stderr, "UNKNOWN\n" );
325
+                break;
326
+            }
327
+        }
328
+        glBindFramebuffer( GL_FRAMEBUFFER, 0 );
329
+    } else if ( GLEW_EXT_framebuffer_object ) {
330
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, m_frame );
331
+        unsigned int err = glCheckFramebufferStatusEXT( GL_FRAMEBUFFER_EXT );
332
+        if ( err == GL_FRAMEBUFFER_COMPLETE_EXT ) {
333
+            return;
334
+        }
335
+        switch ( err ) {
336
+            /* Apparently doesn't exist as an extension.
337
+               case GL_FRAMEBUFFER_UNDEFINED_EXT: {
338
+                fprintf( stderr, "GL_FRAMEBUFFER_UNDEFINED_EXT\n" );
339
+                break;
340
+            }*/
341
+            case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: {
342
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT\n" );
343
+                break;
344
+            }
345
+            case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: {
346
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT\n" );
347
+                break;
348
+            }
349
+            case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: {
350
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT\n" );
351
+                break;
352
+            }
353
+            case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: {
354
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT\n" );
355
+                break;
356
+            }
357
+            case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT: {
358
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT\n" );
359
+                break;
360
+            }
361
+            case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT: {
362
+                fprintf( stderr, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT\n" );
363
+                break;
364
+            }
365
+            case GL_FRAMEBUFFER_UNSUPPORTED_EXT: {
366
+                fprintf( stderr, "GL_FRAMEBUFFER_UNSUPPORTED_EXT\n" );
367
+                break;
368
+            }
369
+            default: {
370
+                fprintf( stderr, "Unknown framebuffer error!\n" );
371
+                break;
372
+            }
373
+        }
374
+        glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
375
+    }
376
+}
377
+
378
+void slop::Framebuffer::generateBuffers() {
379
+    if ( generatedBuffers ) {
380
+        return;
381
+    }
382
+    std::vector<glm::vec2> verts;
383
+    std::vector<glm::vec2> uvs;
384
+    verts.push_back( glm::vec2( -1, -1 ) );
385
+    verts.push_back( glm::vec2( 1, -1 ) );
386
+    verts.push_back( glm::vec2( 1, 1 ) );
387
+    verts.push_back( glm::vec2( -1, 1 ) );
388
+    uvs.push_back( glm::vec2( 0, 0 ) );
389
+    uvs.push_back( glm::vec2( 1, 0 ) );
390
+    uvs.push_back( glm::vec2( 1, 1 ) );
391
+    uvs.push_back( glm::vec2( 0, 1 ) );
392
+
393
+    glGenBuffers( 2, m_buffers );
394
+    glBindBuffer( GL_ARRAY_BUFFER, m_buffers[0] );
395
+    glBufferData( GL_ARRAY_BUFFER, verts.size() * sizeof( glm::vec2 ), &verts[0], GL_STATIC_DRAW );
396
+    glBindBuffer( GL_ARRAY_BUFFER, m_buffers[1] );
397
+    glBufferData( GL_ARRAY_BUFFER, uvs.size() * sizeof( glm::vec2 ), &uvs[0], GL_STATIC_DRAW );
398
+    generatedBuffers = true;
399
+}
400
+
401
+void slop::Framebuffer::clear( glm::vec4 clearcolor, unsigned char flags ) {
402
+    // FIXME: This should auto-bind and unbind, but I was too lazy to find out how to push and pop gl states.
403
+    unsigned int colorbit = 0;
404
+    if ( flags & color ) {
405
+        colorbit = colorbit | GL_COLOR_BUFFER_BIT;
406
+    }
407
+    if ( m_flags & depth && flags & depth ) {
408
+        colorbit = colorbit | GL_DEPTH_BUFFER_BIT;
409
+    }
410
+    if ( m_flags & stencil && flags & stencil) {
411
+        colorbit = colorbit | GL_STENCIL_BUFFER_BIT;
412
+    }
413
+    glClearColor( clearcolor.x, clearcolor.y, clearcolor.z, clearcolor.w );
414
+    glClear( colorbit );
415
+}
416
+
417
+void slop::Framebuffer::draw( float time, unsigned int desktop ) {
418
+    if ( !( m_flags & color ) ) {
419
+        return;
420
+    }
421
+
422
+    generateBuffers();
423
+
424
+    //slop::Shader* shader = shaders->get( "simple" );
425
+    m_shader->bind();
426
+    m_shader->setParameter( "texture", 0 );
427
+    m_shader->setParameter( "desktop", 1 );
428
+    m_shader->setParameter( "time", time );
429
+    m_shader->setParameter( "desktopWidth", (int)xengine->getWidth() );
430
+    m_shader->setParameter( "desktopHeight", (int)xengine->getHeight() );
431
+    m_shader->setAttribute( "vertex", m_buffers[0], 2 );
432
+    m_shader->setAttribute( "uv", m_buffers[1], 2 );
433
+
434
+    glActiveTexture(GL_TEXTURE0 + 0);
435
+    glBindTexture( GL_TEXTURE_2D, m_texture );
436
+    glActiveTexture(GL_TEXTURE0 + 1);
437
+    glBindTexture( GL_TEXTURE_2D, desktop );
438
+    glActiveTexture(GL_TEXTURE0 + 0);
439
+    glEnable( GL_TEXTURE_2D );
440
+    glDrawArrays( GL_QUADS, 0, 4 );
441
+    glDisable( GL_TEXTURE_2D );
442
+
443
+    m_shader->unbind();
444
+}

+ 50
- 0
src/framebuffer.hpp Ver arquivo

@@ -0,0 +1,50 @@
1
+#ifndef IS_FRAMEBUFFER_H_
2
+#define IS_FRAMEBUFFER_H_
3
+
4
+#include <GL/glew.h>
5
+#include <GL/gl.h>
6
+#include <glm/glm.hpp>
7
+
8
+#include "x.hpp"
9
+#include "shader.hpp"
10
+#include "resource.hpp"
11
+
12
+namespace slop {
13
+
14
+class Framebuffer
15
+{
16
+public:
17
+    enum buffers
18
+    {
19
+        color = 0x01,
20
+        depth = 0x02,
21
+        stencil = 0x04
22
+    };
23
+    Framebuffer();
24
+    Framebuffer( unsigned int width, unsigned int height, unsigned char flags = color, std::string shader = "simple" );
25
+    ~Framebuffer();
26
+    void create( unsigned int width, unsigned int height, unsigned char flags = color, std::string shader = "simple" );
27
+    void createFromTexture( unsigned int texture, std::string shader = "simple" );
28
+    void setShader( std::string shader = "simple" );
29
+    void clear( glm::vec4 color = glm::vec4( 0, 0, 0, 1 ), unsigned char flags = color | depth | stencil );
30
+    void bind();
31
+    void unbind();
32
+    void draw( float time, unsigned int image );
33
+    unsigned int m_texture;
34
+    unsigned int m_depth;
35
+    unsigned int m_stencil;
36
+    slop::Shader* m_shader;
37
+private:
38
+    unsigned int m_width;
39
+    unsigned int m_height;
40
+    void check();
41
+    void generateBuffers();
42
+    unsigned char m_flags;
43
+    bool generatedBuffers;
44
+    unsigned int m_frame;
45
+    unsigned int m_buffers[2];
46
+};
47
+
48
+}
49
+
50
+#endif //IS_FRAMEBUFFER_H_

+ 38
- 0
src/glselectrectangle.cpp Ver arquivo

@@ -27,6 +27,7 @@ slop::GLSelectRectangle::~GLSelectRectangle() {
27 27
     if ( m_window == None ) {
28 28
         return;
29 29
     }
30
+    delete m_framebuffer;
30 31
     // Try to erase the window before destroying it.
31 32
     glClearColor( 0, 0, 0, 0 );
32 33
     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
@@ -78,6 +79,11 @@ void slop::GLSelectRectangle::constrainWithinMonitor( int* x, int* y, int* w, in
78 79
     m_offseth *= m_glassSize;
79 80
 }
80 81
 
82
+void slop::GLSelectRectangle::setShader( std::string shader ) {
83
+    m_shader = shader;
84
+    m_framebuffer->setShader( shader );
85
+}
86
+
81 87
 void slop::GLSelectRectangle::setMagnifySettings( bool on, float magstrength, unsigned int pixels ) {
82 88
     m_glassSize = magstrength;
83 89
     m_glassPixels = pixels;
@@ -286,6 +292,8 @@ slop::GLSelectRectangle::GLSelectRectangle( int sx, int sy, int ex, int ey, int
286 292
     m_glassBorder = 1;
287 293
     m_monitors = xengine->getCRTCS();
288 294
     m_themed = false;
295
+    m_shader = "simple";
296
+    m_time = 0;
289 297
 
290 298
     // If we don't have a border, we don't exist, so just die.
291 299
     if ( m_border == 0 ) {
@@ -396,11 +404,32 @@ slop::GLSelectRectangle::GLSelectRectangle( int sx, int sy, int ex, int ey, int
396 404
     if ( !glXMakeContextCurrent( xengine->m_display, m_glxWindow, m_glxWindow, m_renderContext ) ) {
397 405
         fprintf( stderr, "Failed to attach GL context to window!\n" );
398 406
     }
407
+    GLenum err = glewInit();
408
+    if ( GLEW_OK != err ) {
409
+        /* Problem: glewInit failed, something is seriously wrong. */
410
+        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
411
+    }
412
+
413
+    // Get an image of the entire desktop for use in shaders.
414
+    XImage* image = XGetImage( xengine->m_display, xengine->m_root, 0, 0, xengine->getWidth(), xengine->getHeight(), 0xffffffff, ZPixmap );
415
+    glEnable(GL_TEXTURE_2D);
416
+    glGenTextures(1, &m_desktop);
417
+    glBindTexture(GL_TEXTURE_2D, m_desktop);
418
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
419
+    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
420
+    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
421
+    glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, xengine->getWidth(), xengine->getHeight(), 0, GL_BGRA, GL_UNSIGNED_BYTE, (void*)(&(image->data[0])));
422
+    XDestroyImage( image );
423
+
424
+    glDisable(GL_TEXTURE_2D);
425
+    m_framebuffer = new slop::Framebuffer( xengine->getWidth(), xengine->getHeight(), slop::Framebuffer::color, m_shader );
426
+    m_framebuffer->bind();
399 427
     glEnable( GL_BLEND );
400 428
     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
401 429
     glClearColor( 0, 0, 0, 0 );
402 430
     glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
403 431
     glXSwapBuffers( xengine->m_display, m_glxWindow );
432
+    m_framebuffer->unbind();
404 433
 }
405 434
 
406 435
 void slop::GLSelectRectangle::setGeo( int sx, int sy, int ex, int ey ) {
@@ -416,6 +445,8 @@ void slop::GLSelectRectangle::setGeo( int sx, int sy, int ex, int ey ) {
416 445
 }
417 446
 
418 447
 void slop::GLSelectRectangle::update( double dt ) {
448
+    m_time += dt;
449
+    m_framebuffer->bind();
419 450
     glViewport( 0, 0, xengine->getWidth(), xengine->getHeight() );
420 451
 
421 452
     glClearColor( 0, 0, 0, 0 );
@@ -498,6 +529,13 @@ void slop::GLSelectRectangle::update( double dt ) {
498 529
         glEnd();
499 530
     }
500 531
 
532
+    m_framebuffer->unbind();
533
+
534
+    glClearColor( 0, 0, 0, 0 );
535
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
536
+
537
+    m_framebuffer->draw( (float) m_time, m_desktop );
538
+
501 539
     if ( m_glassEnabled ) {
502 540
         generateMagnifyingGlass();
503 541
         findOptimalGlassPosition();

+ 7
- 0
src/glselectrectangle.hpp Ver arquivo

@@ -24,11 +24,13 @@
24 24
 #include "x.hpp"
25 25
 #include "selectrectangle.hpp"
26 26
 #include "resource.hpp"
27
+#include "framebuffer.hpp"
27 28
 
28 29
 #include <unistd.h>
29 30
 
30 31
 #include <GL/gl.h>
31 32
 #include <GL/glx.h>
33
+#include <GL/glew.h>
32 34
 #include <GL/glxext.h>
33 35
 #define ILUT_USE_OPENGL
34 36
 #include <IL/il.h>
@@ -59,6 +61,7 @@ public:
59 61
     void                findOptimalGlassPosition();
60 62
     void                constrainWithinMonitor( int* x, int* y, int* w, int* h );
61 63
     void                setTheme( bool on, std::string name );
64
+    void                setShader( std::string name );
62 65
     float               m_r;
63 66
     float               m_g;
64 67
     float               m_b;
@@ -79,6 +82,7 @@ public:
79 82
     int                 m_offsety;
80 83
     int                 m_offsetw;
81 84
     int                 m_offseth;
85
+    unsigned int        m_desktop;
82 86
     unsigned int        m_glassPixels;
83 87
     float               m_glassSize;
84 88
     int                 m_glassBorder;
@@ -87,7 +91,10 @@ public:
87 91
     int                 m_glassx;
88 92
     int                 m_glassy;
89 93
     bool                m_glassEnabled;
94
+    double              m_time;
95
+    std::string         m_shader;
90 96
     std::vector<XRRCrtcInfo*> m_monitors;
97
+    slop::Framebuffer*  m_framebuffer;
91 98
 };
92 99
 
93 100
 }

+ 11
- 5
src/main.cpp Ver arquivo

@@ -21,6 +21,7 @@
21 21
 #include <time.h>
22 22
 #include <cstdio>
23 23
 #include <sstream>
24
+#include <execinfo.h>
24 25
 
25 26
 #ifdef __MACH__
26 27
 #include <mach/clock.h>
@@ -248,6 +249,9 @@ int app( int argc, char** argv ) {
248 249
     bool highlight = options.highlight_flag;
249 250
     bool keyboard = !options.nokeyboard_flag;
250 251
     bool decorations = !options.nodecorations_flag;
252
+    bool themeon = (bool)options.theme_given;
253
+    std::string theme = options.theme_arg;
254
+    std::string shader = options.shader_arg;
251 255
     struct timespec start, time;
252 256
     int xoffset = 0;
253 257
     int yoffset = 0;
@@ -369,7 +373,8 @@ int app( int argc, char** argv ) {
369 373
                                                                      r, g, b, a );
370 374
                             // Haha why is this so hard to cast?
371 375
                             ((slop::GLSelectRectangle*)(selection))->setMagnifySettings( magenabled, magstrength, magpixels );
372
-                            ((slop::GLSelectRectangle*)(selection))->setTheme( true, "gothic" );
376
+                            ((slop::GLSelectRectangle*)(selection))->setTheme( themeon, theme );
377
+                            ((slop::GLSelectRectangle*)(selection))->setShader( shader );
373 378
                         } else {
374 379
                             selection = new slop::XSelectRectangle( t.m_x, t.m_y,
375 380
                                                                     t.m_x + t.m_width,
@@ -427,7 +432,8 @@ int app( int argc, char** argv ) {
427 432
                                                                  r, g, b, a );
428 433
                         // Haha why is this so hard to cast?
429 434
                         ((slop::GLSelectRectangle*)(selection))->setMagnifySettings( magenabled, magstrength, magpixels );
430
-                        ((slop::GLSelectRectangle*)(selection))->setTheme( true, "gothic" );
435
+                        ((slop::GLSelectRectangle*)(selection))->setTheme( themeon, theme );
436
+                        ((slop::GLSelectRectangle*)(selection))->setShader( shader );
431 437
                     } else {
432 438
                         selection = new slop::XSelectRectangle( sx, sy,
433 439
                                                                 ex, ey,
@@ -527,12 +533,12 @@ int main( int argc, char** argv ) {
527 533
         return app( argc, argv );
528 534
     } catch( std::bad_alloc const& exception ) {
529 535
         fprintf( stderr, "Couldn't allocate enough memory! No space left in RAM." );
530
-        return EXIT_FAILURE;
531 536
     } catch( std::exception const& exception ) {
532 537
         fprintf( stderr, "Unhandled Exception Thrown: %s\n", exception.what() );
533
-        return EXIT_FAILURE;
538
+    } catch( std::string err ) {
539
+        fprintf( stderr, "Unhandled Exception Thrown: %s\n", err.c_str() );
534 540
     } catch( ... ) {
535 541
         fprintf( stderr, "Unknown Exception Thrown!\n" );
536
-        return EXIT_FAILURE;
537 542
     }
543
+    return EXIT_FAILURE;
538 544
 }

+ 16
- 0
src/options.ggo Ver arquivo

@@ -78,6 +78,16 @@ option "magpixels" - "Sets how many pixels are displayed in the magnification. T
78 78
     default="64"
79 79
     optional
80 80
 
81
+option "theme" - "Sets the theme of the selection, using textures from ~/.config/slop/ or /usr/share/."
82
+    string
83
+    default="none"
84
+    optional
85
+
86
+option "shader" - "Sets the shader to load and use from ~/.config/slop/ or /usr/share/."
87
+    string
88
+    default="simple"
89
+    optional
90
+
81 91
 option "format" f "Set the output format string. Format specifiers are %x, %y, %w, %h, %i, %g, and %c."
82 92
     string
83 93
     default="REPLACEME"
@@ -96,6 +106,12 @@ text "\n"
96 106
 text "    $ # Classic Windows XP selection.\n"
97 107
 text "    $ slop -l -c 0.3,0.4,0.6,0.4\n"
98 108
 text "\n"
109
+text "    $ # Wiggle wiggle!\n"
110
+text "    $ slop --opengl --shader wiggle\n"
111
+text "\n"
112
+text "    $ # Edgy textures or something.\n"
113
+text "    $ slop --opengl --theme gothic\n"
114
+text "\n"
99 115
 text "    $ # Change output format to use safer parsing\n"
100 116
 text "    $ slopoutput=$(slop -f \"%x %y %w %h\")\n"
101 117
 text "    $ X=$(echo $slopoutput | awk '{print $1}')\n"

+ 10
- 6
src/resource.cpp Ver arquivo

@@ -30,22 +30,26 @@ slop::Resource::Resource() {
30 30
         char* home = getpwuid(getuid())->pw_dir;
31 31
         m_usrconfig += home;
32 32
         m_usrconfig += "/.config/slop/";
33
+        m_sysconfig = INSTALL_PREFIX;
34
+        m_sysconfig += "/share/slop/";
33 35
         return;
34 36
     }
35 37
     m_usrconfig += config;
36 38
     m_usrconfig += "/slop/";
37 39
     m_sysconfig = INSTALL_PREFIX;
38
-    m_sysconfig += "/share/slop";
40
+    m_sysconfig += "/share/slop/";
39 41
 }
40 42
 
41 43
 std::string slop::Resource::getRealPath( std::string localpath ) {
42
-    if ( !validatePath( m_usrconfig + localpath ) ) {
43
-        if ( !validatePath( m_sysconfig + localpath ) ) {
44
-            fprintf( stderr, "Failed to find directory %s in %s or %s...\n", localpath.c_str(), m_usrconfig.c_str(), m_sysconfig.c_str() );
45
-        }
44
+    if ( validatePath( m_usrconfig + localpath ) ) {
45
+        return m_usrconfig + localpath;
46
+    }
47
+    if ( validatePath( m_sysconfig + localpath ) ) {
46 48
         return m_sysconfig + localpath;
47 49
     }
48
-    return m_usrconfig + localpath;
50
+    std::string err = "The file or folder " + localpath + " was not found in either " + m_sysconfig + " or " + m_usrconfig + "\n";
51
+    throw err;
52
+    return localpath;
49 53
 }
50 54
 
51 55
 bool slop::Resource::validatePath( std::string path ) {

+ 1
- 0
src/resource.hpp Ver arquivo

@@ -22,6 +22,7 @@
22 22
 #define IS_RESOURCE_H_
23 23
 
24 24
 #include <stdlib.h>
25
+#include <cassert>
25 26
 #include <cstdio>
26 27
 #include <string>
27 28
 #include <unistd.h>

+ 1
- 0
src/selectrectangle.hpp Ver arquivo

@@ -23,6 +23,7 @@
23 23
 
24 24
 #include "x.hpp"
25 25
 #include "selectrectangle.hpp"
26
+#include "shader.hpp"
26 27
 
27 28
 #include <unistd.h>
28 29
 

+ 172
- 0
src/shader.cpp Ver arquivo

@@ -0,0 +1,172 @@
1
+#include "shader.hpp"
2
+
3
+slop::Shader::Shader( std::string name, std::string vert, std::string frag, std::string type ) {
4
+    m_name = name;
5
+    // Set up the type of the shader, this is read by render to know what kind of matricies it needs.
6
+    if ( type == "perspective" ) {
7
+        m_type = 0;
8
+    } else if ( type == "orthographic" ) {
9
+        m_type = 1;
10
+    } else {
11
+        m_type = -1;
12
+    }
13
+    m_good = false;
14
+    // Create the program to link to.
15
+    m_program = glCreateProgram();
16
+
17
+    std::ifstream v( vert.c_str() );
18
+    std::string vert_contents((std::istreambuf_iterator<char>(v)),
19
+                               std::istreambuf_iterator<char>());
20
+    std::ifstream f( frag.c_str() );
21
+    std::string frag_contents((std::istreambuf_iterator<char>(f)),
22
+                              std::istreambuf_iterator<char>());
23
+
24
+    const char* vertsrc = vert_contents.c_str();
25
+    const char* fragsrc = frag_contents.c_str();
26
+
27
+    // Compile both shaders.
28
+    unsigned int vertShader = glCreateShader( GL_VERTEX_SHADER );
29
+    glShaderSource( vertShader, 1, &vertsrc , NULL );
30
+    int err = compile( vertShader );
31
+
32
+    if ( err ) {
33
+        fprintf( stderr, "Failed to compile shader %s.\n", vert.c_str() );
34
+        glDeleteShader( vertShader );
35
+        return;
36
+    }
37
+
38
+    unsigned int fragShader = glCreateShader( GL_FRAGMENT_SHADER );
39
+    glShaderSource( fragShader, 1, &fragsrc, NULL );
40
+    err = compile( fragShader );
41
+    if ( err ) {
42
+        fprintf( stderr, "Failed to compile shader %s.\n", frag.c_str() );
43
+        glDeleteShader( vertShader );
44
+        glDeleteShader( fragShader );
45
+        return;
46
+    }
47
+
48
+
49
+    // Then attempt to link them to this shader.
50
+    err = link( vertShader, fragShader );
51
+    if ( err ) {
52
+        fprintf( stderr, "Failed to link shader %s.\n", name.c_str() );
53
+        glDeleteShader( vertShader );
54
+        glDeleteShader( fragShader );
55
+        return;
56
+    }
57
+
58
+    // Clean up :)
59
+    glDeleteShader( vertShader );
60
+    glDeleteShader( fragShader );
61
+    m_good = true;
62
+    glUseProgram( 0 );
63
+}
64
+
65
+slop::Shader::~Shader() {
66
+    glDeleteProgram( m_program );
67
+}
68
+
69
+unsigned int slop::Shader::getProgram() {
70
+    return m_program;
71
+}
72
+
73
+void slop::Shader::bind() {
74
+    glUseProgram( m_program );
75
+}
76
+
77
+int slop::Shader::compile( unsigned int shader ) {
78
+    glCompileShader( shader );
79
+
80
+    // Compiling the shader is the easy part, all this junk down here is for printing the error it might generate.
81
+    int result;
82
+    int logLength;
83
+    glGetShaderiv( shader, GL_COMPILE_STATUS, &result );
84
+    glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &logLength );
85
+    if ( result == GL_FALSE ) {
86
+        char* errormsg = new char[ logLength ];
87
+        glGetShaderInfoLog( shader, logLength, NULL, errormsg );
88
+        fprintf( stderr, "%s\n", errormsg );
89
+        delete[] errormsg;
90
+        return 1;
91
+    }
92
+    return 0;
93
+}
94
+
95
+int slop::Shader::link( unsigned int vertshader, unsigned int fragshader ) {
96
+    glAttachShader( m_program, vertshader );
97
+    glAttachShader( m_program, fragshader );
98
+    glLinkProgram( m_program );
99
+
100
+    // Linking the shader is the easy part, all this junk down here is for printing the error it might generate.
101
+    int result;
102
+    int logLength;
103
+    glGetProgramiv( m_program, GL_LINK_STATUS, &result);
104
+    glGetProgramiv( m_program, GL_INFO_LOG_LENGTH, &logLength);
105
+    if ( result == GL_FALSE ) {
106
+        char* errormsg = new char[ logLength ];
107
+        glGetProgramInfoLog( m_program, logLength, NULL, errormsg );
108
+        fprintf( stderr, "%s\n", errormsg );
109
+        delete[] errormsg;
110
+        return 1;
111
+    }
112
+    return 0;
113
+}
114
+
115
+unsigned int slop::Shader::getUniformLocation( std::string name ) {
116
+    if ( !m_good ) {
117
+        return 0;
118
+    }
119
+    glUseProgram( m_program );
120
+    return glGetUniformLocation( m_program, name.c_str() );
121
+}
122
+
123
+void slop::Shader::setParameter( std::string name, int foo ) {
124
+    if ( !m_good ) {
125
+        return;
126
+    }
127
+    glUniform1i( getUniformLocation( name ), foo );
128
+}
129
+
130
+void slop::Shader::setParameter( std::string name, float foo ) {
131
+    if ( !m_good ) {
132
+        return;
133
+    }
134
+    glUniform1f( getUniformLocation( name ), foo );
135
+}
136
+
137
+void slop::Shader::setParameter( std::string name, glm::mat4 foo ) {
138
+    if ( !m_good ) {
139
+        return;
140
+    }
141
+    glUniformMatrix4fv( getUniformLocation( name ), 1, GL_FALSE, glm::value_ptr( foo ) );
142
+}
143
+
144
+void slop::Shader::setParameter( std::string name, glm::vec4 foo ) {
145
+    if ( !m_good ) {
146
+        return;
147
+    }
148
+    glUniform4f( getUniformLocation( name ), foo.x, foo.y, foo.z, foo.w );
149
+}
150
+
151
+void slop::Shader::setParameter( std::string name, glm::vec2 foo ) {
152
+    if ( !m_good ) {
153
+        return;
154
+    }
155
+    glUniform2f( getUniformLocation( name ), foo.x, foo.y );
156
+}
157
+
158
+void slop::Shader::setAttribute( std::string name, unsigned int buffer, unsigned int stepsize ) {
159
+    unsigned int a = glGetAttribLocation( m_program, name.c_str() );
160
+    glEnableVertexAttribArray( a );
161
+    glBindBuffer( GL_ARRAY_BUFFER, buffer );
162
+    glVertexAttribPointer( a, stepsize, GL_FLOAT, GL_FALSE, 0, NULL );
163
+    m_activeattribs.push_back( a );
164
+}
165
+
166
+void slop::Shader::unbind() {
167
+    for ( unsigned int i=0; i<m_activeattribs.size(); i++ ) {
168
+        glDisableVertexAttribArray( m_activeattribs[i] );
169
+    }
170
+    m_activeattribs.clear();
171
+    glUseProgram( 0 );
172
+}

+ 44
- 0
src/shader.hpp Ver arquivo

@@ -0,0 +1,44 @@
1
+// shader.hpp: Loads shaders into opengl
2
+
3
+#ifndef IS_SHADER_H_
4
+#define IS_SHADER_H_
5
+
6
+#include <string>
7
+#include <cstdio>
8
+#include <vector>
9
+#include <glm/glm.hpp>
10
+#include <glm/gtc/type_ptr.hpp>
11
+#include <GL/glew.h>
12
+#include <string>
13
+#include <fstream>
14
+#include <streambuf>
15
+
16
+namespace slop {
17
+
18
+class Shader {
19
+public:
20
+    Shader( std::string name, std::string vert, std::string frag, std::string shadertype = "other" );
21
+    ~Shader();
22
+    unsigned int    getProgram();
23
+    std::string     m_name;
24
+    void            bind();
25
+    void            unbind();
26
+    void            setParameter( std::string name, int foo );
27
+    void            setParameter( std::string name, float foo );
28
+    void            setParameter( std::string name, glm::mat4 foo );
29
+    void            setParameter( std::string name, glm::vec4 foo );
30
+    void            setParameter( std::string name, glm::vec2 foo );
31
+    void            setAttribute( std::string name, unsigned int buffer, unsigned int stepsize );
32
+    int             m_type;
33
+private:
34
+    std::vector<unsigned int>   m_activeattribs;
35
+    bool                        m_good;
36
+    unsigned int                getUniformLocation( std::string );
37
+    int                         compile( unsigned int shader );
38
+    int                         link( unsigned int vert, unsigned int frag );
39
+    unsigned int                m_program;
40
+};
41
+
42
+};
43
+
44
+#endif // IS_SHADER_H_