summaryrefslogtreecommitdiff
path: root/tests/conform/test-just-vertex-shader.c
blob: 886f354ea7bc40253404701ba3d148f2ea253369 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <clutter/clutter.h>
#include <string.h>

#include "test-conform-common.h"

static const ClutterColor stage_color = { 0x00, 0x00, 0xff, 0xff };

static void
draw_frame (void)
{
  CoglHandle material = cogl_material_new ();
  CoglColor color;
  GError *error = NULL;
  CoglHandle shader, program;

  /* Set the primary vertex color as red */
  cogl_color_set_from_4ub (&color, 0xff, 0x00, 0x00, 0xff);
  cogl_material_set_color (material, &color);

  /* Override the vertex color in the texture environment with a
     constant green color */
  cogl_color_set_from_4ub (&color, 0x00, 0xff, 0x00, 0xff);
  cogl_material_set_layer_combine_constant (material, 0, &color);
  if (!cogl_material_set_layer_combine (material, 0,
                                        "RGBA=REPLACE(CONSTANT)",
                                        &error))
    {
      g_warning ("Error setting blend constant: %s", error->message);
      g_assert_not_reached ();
    }

  /* Set up a dummy vertex shader that does nothing but the usual
     fixed function transform */
  shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
  cogl_shader_source (shader,
                      "void\n"
                      "main ()\n"
                      "{\n"
                      "  cogl_position_out = "
                      "cogl_modelview_projection_matrix * "
                      "cogl_position_in;\n"
                      "  cogl_color_out = cogl_color_in;\n"
                      "}\n");
  cogl_shader_compile (shader);
  if (!cogl_shader_is_compiled (shader))
    {
      char *log = cogl_shader_get_info_log (shader);
      g_warning ("Shader compilation failed:\n%s", log);
      g_free (log);
      g_assert_not_reached ();
    }

  program = cogl_create_program ();
  cogl_program_attach_shader (program, shader);
  cogl_program_link (program);

  cogl_handle_unref (shader);

  /* Draw something using the material */
  cogl_set_source (material);
  cogl_rectangle (0, 0, 50, 50);

  /* Draw it again using the program. It should look exactly the same */
  cogl_program_use (program);
  cogl_rectangle (50, 0, 100, 50);
  cogl_program_use (COGL_INVALID_HANDLE);

  cogl_handle_unref (material);
  cogl_handle_unref (program);
}

static void
validate_pixel (int x, int y)
{
  guint8 pixels[4];

  cogl_read_pixels (x, y, 1, 1, COGL_READ_PIXELS_COLOR_BUFFER,
                    COGL_PIXEL_FORMAT_RGBA_8888_PRE, pixels);

  /* The final color should be green. If it's blue then the layer
     state is being ignored. If it's green then the stage is showing
     through */
  g_assert_cmpint (pixels[0], ==, 0x00);
  g_assert_cmpint (pixels[1], ==, 0xff);
  g_assert_cmpint (pixels[2], ==, 0x00);
}

static void
validate_result (void)
{
  /* Non-shader version */
  validate_pixel (25, 25);
  /* Shader version */
  validate_pixel (75, 25);
}

static void
on_paint (void)
{
  draw_frame ();

  validate_result ();

  /* Comment this out to see what the test paints */
  clutter_main_quit ();
}

void
test_cogl_just_vertex_shader (TestUtilsGTestFixture *fixture,
                              void *data)
{
  ClutterActor *stage;
  unsigned int paint_handler;

  stage = clutter_stage_get_default ();

  /* If shaders aren't supported then we can't run the test */
  if (cogl_features_available (COGL_FEATURE_SHADERS_GLSL))
    {
      clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);

      paint_handler = g_signal_connect_after (stage, "paint",
                                              G_CALLBACK (on_paint), NULL);

      clutter_actor_show (stage);

      clutter_main ();

      g_signal_handler_disconnect (stage, paint_handler);

      if (g_test_verbose ())
        g_print ("OK\n");
    }
  else if (g_test_verbose ())
    g_print ("Skipping\n");
}