summaryrefslogtreecommitdiff
path: root/tests/conform/test-texture-get-set-data.c
blob: 78e302c6e999ad3109ca1801e7623cda881aa49a (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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <clutter/clutter.h>
#include <glib.h>
#include <string.h>

#include "test-conform-common.h"

static void
check_texture (int width, int height, CoglTextureFlags flags)
{
  CoglHandle tex;
  guint8 *data, *p;
  int y, x;

  p = data = g_malloc (width * height * 4);
  for (y = 0; y < height; y++)
    for (x = 0; x < width; x++)
      {
        *(p++) = x;
        *(p++) = y;
        *(p++) = 128;
        *(p++) = (x ^ y);
      }

  tex = cogl_texture_new_from_data (width, height,
                                    flags,
                                    COGL_PIXEL_FORMAT_RGBA_8888,
                                    COGL_PIXEL_FORMAT_RGBA_8888,
                                    width * 4,
                                    data);

  /* Replace the bottom right quarter of the data with negated data to
     test set_region */
  p = data + (height + 1) * width * 2;
  for (y = 0; y < height / 2; y++)
    {
      for (x = 0; x < width / 2; x++)
        {
          p[0] = ~p[0];
          p[1] = ~p[1];
          p[2] = ~p[2];
          p[3] = ~p[3];
          p += 4;
        }
      p += width * 2;
    }
  cogl_texture_set_region (tex,
                           width / 2, /* src_x */
                           height / 2, /* src_y */
                           width / 2, /* dst_x */
                           height / 2, /* dst_y */
                           width / 2, /* dst_width */
                           height / 2, /* dst_height */
                           width,
                           height,
                           COGL_PIXEL_FORMAT_RGBA_8888,
                           width * 4, /* rowstride */
                           data);

  /* Check passing a NULL pointer and a zero rowstride. The texture
     should calculate the needed data size and return it */
  g_assert_cmpint (cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_ANY, 0, NULL),
                   ==,
                   width * height * 4);

  /* Try first receiving the data as RGB. This should cause a
   * conversion */
  memset (data, 0, width * height * 4);

  cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_RGB_888,
                         width * 3, data);

  p = data;

  for (y = 0; y < height; y++)
    for (x = 0; x < width; x++)
      {
        if (x >= width / 2 && y >= height / 2)
          {
            g_assert_cmpint (p[0], ==, ~x & 0xff);
            g_assert_cmpint (p[1], ==, ~y & 0xff);
            g_assert_cmpint (p[2], ==, ~128 & 0xff);
          }
        else
          {
            g_assert_cmpint (p[0], ==, x & 0xff);
            g_assert_cmpint (p[1], ==, y & 0xff);
            g_assert_cmpint (p[2], ==, 128);
          }
        p += 3;
      }

  /* Now try receiving the data as RGBA. This should not cause a
   * conversion and no unpremultiplication because we explicitly set
   * the internal format when we created the texture */
  memset (data, 0, width * height * 4);

  cogl_texture_get_data (tex, COGL_PIXEL_FORMAT_RGBA_8888,
                         width * 4, data);

  p = data;

  for (y = 0; y < height; y++)
    for (x = 0; x < width; x++)
      {
        if (x >= width / 2 && y >= height / 2)
          {
            g_assert_cmpint (p[0], ==, ~x & 0xff);
            g_assert_cmpint (p[1], ==, ~y & 0xff);
            g_assert_cmpint (p[2], ==, ~128 & 0xff);
            g_assert_cmpint (p[3], ==, ~(x ^ y) & 0xff);
          }
        else
          {
            g_assert_cmpint (p[0], ==, x & 0xff);
            g_assert_cmpint (p[1], ==, y & 0xff);
            g_assert_cmpint (p[2], ==, 128);
            g_assert_cmpint (p[3], ==, (x ^ y) & 0xff);
          }
        p += 4;
      }

  cogl_handle_unref (tex);
  g_free (data);
}

static void
paint_cb (void)
{
  /* First try without atlasing */
  check_texture (256, 256, COGL_TEXTURE_NO_ATLAS);
  /* Try again with atlasing. This should end up testing the atlas
     backend and the sub texture backend */
  check_texture (256, 256, 0);
  /* Try with a really big texture in the hope that it will end up
     sliced. */
  check_texture (4, 5128, COGL_TEXTURE_NO_ATLAS);
  /* And in the other direction. */
  check_texture (5128, 4, COGL_TEXTURE_NO_ATLAS);

  clutter_main_quit ();
}

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

  /* We create a stage even though we don't usually need it so that if
     the draw-and-read texture fallback is needed then it will have
     something to draw to */
  stage = clutter_stage_get_default ();

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

  clutter_actor_show (stage);

  clutter_main ();

  g_signal_handler_disconnect (stage, paint_handler);

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