~ubuntu-branches/ubuntu/quantal/libcm/quantal

« back to all changes in this revision

Viewing changes to src/drawable-node.c

  • Committer: Bazaar Package Importer
  • Author(s): Loic Minier, Josselin Mouette, Loic Minier
  • Date: 2008-05-26 14:43:19 UTC
  • mfrom: (3.1.4 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080526144319-ddwovigo7i925ewr
Tags: 0.1.1-4
[ Josselin Mouette ]
* Allow libgl-dev and libglu-dev as alternative dependencies for
  libcm-dev. Closes: #478887.

[ Loic Minier ]
* Don't copy config.guess/.sub after unpatch in clean; should avoid having
  them in the .diff.gz -- not needed as we always update them after patching
  anyway -- and should fix conversion to source format 3.0; closes: #482728.
* Stop shipping *.la files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* libcm - A library with a xlib wrapper and a gl based scene graph
 
2
 * Copyright (C) 2005, 2006  Red Hat, Inc.
 
3
 *
 
4
 * This library is free software; you can redistribute it and/or
 
5
 * modify it under the terms of the GNU Library General Public
 
6
 * License as published by the Free Software Foundation; either
 
7
 * version 2 of the License, or (at your option) any later version.
 
8
 *
 
9
 * This library is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
 * Library General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU Library General Public
 
15
 * License along with this library; if not, write to the 
 
16
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
17
 * Boston, MA  02111-1307, USA.
 
18
 *
 
19
 * Author: Soren Sandmann (sandmann@redhat.com)
 
20
 */
1
21
#include "drawable-node.h"
2
22
#include <string.h>
3
23
#include "wsint.h"
 
24
#include "state.h"
4
25
#include <math.h>
 
26
#include "stacker.h"
5
27
 
6
28
#include <X11/Xlib.h>
7
29
#include <X11/extensions/Xfixes.h>
12
34
#   define PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8
13
35
#endif
14
36
 
15
 
typedef struct Tile
16
 
{
17
 
    gint x;
18
 
    gint y;
19
 
    gint width;
20
 
    gint height;
21
 
    
22
 
    GLuint texture;
23
 
} Tile;
24
 
 
25
37
G_DEFINE_TYPE (CmDrawableNode, cm_drawable_node, CM_TYPE_NODE);
26
38
 
27
 
static void drawable_node_render (CmNode *node);
 
39
static void drawable_node_render (CmNode *node,
 
40
                                  CmState *state);
28
41
static void drawable_node_compute_extents (CmNode  *node,
29
42
                                           Extents *extents);
 
43
static WsRegion *drawable_node_get_covered_region (CmNode *node);
30
44
 
31
45
static void
32
46
cm_drawable_node_finalize (GObject *object)
34
48
    CmDrawableNode *node = CM_DRAWABLE_NODE (object);
35
49
    WsDisplay *display = WS_RESOURCE (node->drawable)->display;
36
50
    
37
 
#if 0
38
 
    g_print ("finalizing drawable node %p containing %lx\n",
39
 
             object, WS_RESOURCE_XID (node->drawable));
40
 
#endif
41
 
    
42
51
    ws_display_begin_error_trap (display);
43
 
    
44
 
    if (node->pixmap)
45
 
        g_object_unref (node->pixmap);
46
 
    
47
 
    ws_display_end_error_trap (display);
48
 
    
49
 
    /* FIXME: remove this when Ws* has been gobjectified */
50
 
    ws_window_set_configure_callback (
51
 
        (WsWindow *)node->drawable, NULL, NULL);
 
52
 
 
53
    if (node->pix_texture)
 
54
        g_object_unref (node->pix_texture);
 
55
    if (node->grid)
 
56
        g_object_unref (node->grid);
 
57
    if (node->explosion)
 
58
        g_object_unref (node->explosion);
 
59
    if (node->pix_texture)
 
60
        g_object_unref (node->pix_texture);
 
61
    if (node->tex_env)
 
62
        g_object_unref (node->tex_env);
 
63
    if (node->stacker)
 
64
        g_object_unref (node->stacker);
 
65
    if (node->shadow)
 
66
        g_object_unref (node->shadow);
 
67
 
 
68
    cm_node_disown_child (CM_NODE (node), (CmNode **)&node->deform);
52
69
    
53
70
    G_OBJECT_CLASS (cm_drawable_node_parent_class)->finalize (object);
54
71
}
63
80
    
64
81
    node_class->render = drawable_node_render;
65
82
    node_class->compute_extents = drawable_node_compute_extents;
 
83
    node_class->get_covered_region = drawable_node_get_covered_region;
66
84
}
67
85
 
68
86
static void
69
87
cm_drawable_node_init (CmDrawableNode *drawable_node)
70
88
{
71
 
    
72
 
}
 
89
    CmDeform *deform;
73
90
 
74
 
void
75
 
cm_drawable_node_set_damage_func (CmDrawableNode *node,
76
 
                                  DrawableDamageFunc damage_func,
77
 
                                  gpointer data)
78
 
{
79
 
    node->damage_func = damage_func;
80
 
    node->damage_data = data;
 
91
    drawable_node->grid =
 
92
        cm_grid_new (0, 0, 20, 20, 32, 32);
 
93
    drawable_node->explosion =
 
94
        cm_explosion_new (20, 20, 20, 20);
 
95
    drawable_node->pix_texture =
 
96
        cm_pix_texture_new (NULL,
 
97
                            CM_NODE (drawable_node->grid));
 
98
    drawable_node->tex_env =
 
99
        cm_tex_env_new (CM_NODE (drawable_node->pix_texture));
 
100
    drawable_node->stacker = cm_stacker_new ();
 
101
    drawable_node->shadow = cm_shadow_new (20, 20, 32, 32);
 
102
    cm_stacker_add_child (drawable_node->stacker, CM_NODE (drawable_node->shadow));
 
103
    cm_stacker_add_child (drawable_node->stacker, CM_NODE (drawable_node->tex_env));
 
104
    deform =
 
105
        cm_deform_new (CM_NODE (drawable_node->stacker), 0, 0, 32, 32);
 
106
    cm_node_own_child (CM_NODE (drawable_node), &drawable_node->deform, deform);
 
107
    g_object_unref (deform);
 
108
    drawable_node->explosion_level = 0.0;
81
109
}
82
110
 
83
111
static void
84
112
queue_paint (CmDrawableNode *node)
85
113
{
86
 
#if 0
87
 
    g_print ("calling into metacity\n");
88
 
#endif
89
 
    
90
 
    if (node->damage_func)
91
 
        node->damage_func (node, node->damage_data);
92
 
}
93
 
 
94
 
#define SHADOW_WIDTH 64
95
 
 
96
 
static void
97
 
bind_shadow_texture(void)
98
 
{
99
 
    static unsigned char texture[4 * SHADOW_WIDTH * SHADOW_WIDTH];
100
 
    static gboolean initialized;
101
 
    static GLuint texture_name;
102
 
    int i, j, dx, dy;
103
 
    double d, alpha;
104
 
    const int xofs = 4, yofs = 4;
105
 
    const int fuzz = 2 * SHADOW_WIDTH / 3;
106
 
    
107
 
    if (!initialized)
108
 
    {
109
 
        initialized = TRUE;
110
 
        glGenTextures (1, &texture_name);
111
 
        for (i = 0; i < SHADOW_WIDTH * 2; i++)
112
 
        {
113
 
            for (j = 0; j < SHADOW_WIDTH * 2; j++)
114
 
            {
115
 
                if (i < (xofs + fuzz))
116
 
                    dx = (xofs + fuzz) - i;
117
 
                else if (i < (xofs + 2 * SHADOW_WIDTH - fuzz))
118
 
                    dx = 1;
119
 
                else
120
 
                    dx = i - (xofs + 2 * SHADOW_WIDTH - fuzz + 1);
121
 
                
122
 
                if (j < (yofs + fuzz))
123
 
                    dy = (yofs + fuzz) - j;
124
 
                else if (j < (yofs + 2 * SHADOW_WIDTH - fuzz))
125
 
                    dy = 1;
126
 
                else
127
 
                    dy = j - (yofs + 2 * SHADOW_WIDTH - fuzz + 1);
128
 
                
129
 
                d = sqrt(dx * dx + dy * dy);
130
 
                alpha = pow(0.8, d * 0.7) * 90;
131
 
                
132
 
                texture[i + j * SHADOW_WIDTH * 2] = alpha;
133
 
            }     
134
 
        }
135
 
        
136
 
        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_name);
137
 
        glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_ALPHA,
138
 
                     SHADOW_WIDTH * 2, SHADOW_WIDTH * 2, 0,
139
 
                     GL_ALPHA, GL_BYTE, texture);
140
 
    }
141
 
    
142
 
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_name);
143
 
}
144
 
 
145
 
static void
146
 
emit_quad(int u0, int v0, int u1, int v1,
147
 
          int x0, int y0, int x1, int y1,
148
 
          CmDrawableNode *node)
149
 
{
150
 
    int dx, dy;
151
 
    
152
 
    glTexCoord2i (u0, v0);
153
 
    node->deform_func(x0, y0, node->real_x, node->real_y,
154
 
                      node->real_width, node->real_height,
155
 
                      &dx, &dy, node->deform_data);
156
 
    glVertex3i (dx, dy, 0);
157
 
    glTexCoord2i (u1, v0);
158
 
    node->deform_func(x1, y0, node->real_x, node->real_y,
159
 
                      node->real_width, node->real_height,
160
 
                      &dx, &dy, node->deform_data);
161
 
    glVertex3i (dx, dy, 0);
162
 
    glTexCoord2i (u1, v1);
163
 
    node->deform_func(x1, y1, node->real_x, node->real_y,
164
 
                      node->real_width, node->real_height,
165
 
                      &dx, &dy, node->deform_data);
166
 
    glVertex3i (dx, dy, 0);
167
 
    glTexCoord2i (u0, v1);
168
 
    node->deform_func(x0, y1, node->real_x, node->real_y,
169
 
                      node->real_width, node->real_height,
170
 
                      &dx, &dy, node->deform_data);
171
 
    glVertex3f (dx, dy, 0);
172
 
}
173
 
 
174
 
static void
175
 
draw_window (CmDrawableNode *node)
176
 
{
177
 
    const int tile_size = 32;
178
 
    int u0, v0, u1, v1;
179
 
    int w, h;
180
 
    
181
 
    w = node->real_width;
182
 
    h = node->real_height;
183
 
    
184
 
    glBegin (GL_QUADS);
185
 
    
186
 
    for (u0 = 0; u0 < w; u0 += tile_size)
187
 
    {
188
 
        for (v0 = 0; v0 < h; v0 += tile_size)
189
 
        {
190
 
            u1 = MIN(u0 + tile_size, w);
191
 
            v1 = MIN(v0 + tile_size, h);
192
 
            
193
 
            emit_quad(u0, v0, u1, v1, u0, v0, u1, v1, node);
194
 
        }
195
 
    }
196
 
    
197
 
    glEnd ();
198
 
    
199
 
    glColor4f (0.0, 0.0, 0.0, node->alpha);
200
 
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
201
 
    bind_shadow_texture();
202
 
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
203
 
    glEnable (GL_BLEND);
204
 
    
205
 
    glBegin (GL_QUADS);
206
 
    
207
 
    emit_quad(0, 0, tile_size, tile_size,
208
 
              -tile_size, -tile_size, 0, 0, node);
209
 
    emit_quad(tile_size, 0, 2 * tile_size, tile_size,
210
 
              0, -tile_size, tile_size, 0, node);
211
 
    
212
 
    emit_quad(2 * tile_size, 0, 3 * tile_size, tile_size,
213
 
              w - tile_size, -tile_size, w, 0, node);
214
 
    emit_quad(3 * tile_size, 0, 4 * tile_size, tile_size,
215
 
              w, -tile_size, w + tile_size, 0, node);
216
 
    
217
 
    emit_quad(0, tile_size, tile_size, 2 * tile_size,
218
 
              -tile_size, 0, 0, tile_size, node);
219
 
    emit_quad(3 * tile_size, tile_size, 4 * tile_size, 2 * tile_size,
220
 
              w, 0, w + tile_size, tile_size, node);
221
 
    
222
 
    for (u0 = tile_size; u0 < w - tile_size; u0 += tile_size)
223
 
    {
224
 
        v0 = -tile_size;
225
 
        v1 = 0;
226
 
        u1 = MIN(u0 + tile_size, w - tile_size);
227
 
        
228
 
        emit_quad(2 * tile_size, 0, 2 * tile_size, tile_size,
229
 
                  u0, v0, u1, v1, node);
230
 
        
231
 
        v0 = h;
232
 
        v1 = h + tile_size;
233
 
        emit_quad(2 * tile_size, 3 * tile_size, 2 * tile_size, 4 * tile_size,
234
 
                  u0, v0, u1, v1, node);
235
 
    }
236
 
    
237
 
    
238
 
    for (v0 = tile_size; v0 < h - tile_size; v0 += tile_size)
239
 
    {
240
 
        u0 = -tile_size;
241
 
        u1 = 0;
242
 
        v1 = MIN(v0 + tile_size, h - tile_size);
243
 
        
244
 
        emit_quad(0, 2 * tile_size, tile_size, 2 * tile_size,
245
 
                  u0, v0, u1, v1, node);
246
 
        
247
 
        u0 = w;
248
 
        u1 = w + tile_size;
249
 
        
250
 
        emit_quad(3 * tile_size, 2 * tile_size, 4 * tile_size, 2 * tile_size,
251
 
                  u0, v0, u1, v1, node);
252
 
    }
253
 
    
254
 
    emit_quad(0, 2 * tile_size, tile_size, 3 * tile_size,
255
 
              -tile_size, h - tile_size, 0, h, node);
256
 
    emit_quad(3 * tile_size, 2 * tile_size, 4 * tile_size, 3 * tile_size,
257
 
              w, h - tile_size, w + tile_size, h, node);
258
 
    
259
 
    emit_quad(tile_size, 3 * tile_size, 2 * tile_size, 4 * tile_size,
260
 
              0, h, tile_size, h + tile_size, node);
261
 
    emit_quad(2 * tile_size, 3 * tile_size, 3 * tile_size, 4 * tile_size,
262
 
              w - tile_size, h, w, h + tile_size, node);
263
 
    
264
 
    emit_quad(0, 3 * tile_size, tile_size, 4 * tile_size,
265
 
              -tile_size, h, 0, h + tile_size, node);
266
 
    emit_quad(3 * tile_size, 3 * tile_size, 4 * tile_size, 4 * tile_size,
267
 
              w, h, w + tile_size, h + tile_size, node);
268
 
    
269
 
    glEnd ();
 
114
    cm_node_queue_repaint (CM_NODE (node));
270
115
}
271
116
 
272
117
static void
274
119
{
275
120
    int i, j;
276
121
    
277
 
    printf ("%s:\n", header);
 
122
    g_print ("%s:\n", header);
278
123
    
279
124
    for (i = 0; i < 16; ++i)
280
125
    {
281
 
        printf ("%f ", m[i]);
 
126
        g_print ("%f ", m[i]);
282
127
        
283
128
        if (++j == 4)
284
129
        {
285
 
            printf ("\n");
 
130
            g_print ("\n");
286
131
            j = 0;
287
132
        }
288
133
    }
 
134
}
 
135
 
 
136
static void
 
137
print_rectangle (const char *header, WsRectangle *rect)
 
138
{
 
139
    g_print ("%s\n", header);
289
140
    
 
141
    g_print ("%d %d %d %d\n", rect->x, rect->y, rect->width, rect->height);
290
142
}
291
143
 
292
144
static void
310
162
    print_matrix ("proj",  proj);
311
163
    g_print ("viewport: %d %d %d %d\n", view[0], view[1], view[2], view[3]);
312
164
    
313
 
    printf ("projected: %d %d %d  =>   %f %f %f\n", x, y, z, wx, wy, wz);
 
165
    g_print ("projected: %d %d %d  =>   %f %f %f\n", x, y, z, wx, wy, wz);
314
166
#endif
315
167
}
316
168
 
317
169
static void
318
 
update_geometry (CmDrawableNode *node)
319
 
{
320
 
    WsRectangle geometry;
321
 
    
322
 
    if (!ws_drawable_query_geometry (WS_DRAWABLE (node->drawable), &geometry))
323
 
    {
324
 
        return;
325
 
    }
326
 
    
327
 
    node->real_x = geometry.x;
328
 
    node->real_y = geometry.y;
329
 
    node->real_width = geometry.width;
330
 
    node->real_height = geometry.height;
331
 
}
332
 
 
333
 
static void
334
 
drawable_node_render (CmNode *node)
335
 
{
336
 
    CmDrawableNode *drawable_node = CM_DRAWABLE_NODE (node);
337
 
    GLuint texture;
 
170
drawable_node_vertex (gdouble *x,
 
171
                      gdouble *y,
 
172
                      gdouble *z,
 
173
                      gdouble  u,
 
174
                      gdouble  v,
 
175
                      gpointer data)
 
176
    
 
177
{
 
178
    CmDrawableNode *dnode = data;
 
179
    WsRectangle clipbox;
 
180
 
 
181
    cm_drawable_node_get_clipbox (dnode, &clipbox);
 
182
    
 
183
    glTexCoord2f (u * clipbox.width,
 
184
                  v * clipbox.height);
 
185
}
 
186
 
 
187
static WsRegion *
 
188
get_shape (CmDrawableNode *dnode)
 
189
{
 
190
    WsRectangle clipbox;
 
191
    WsRegion *reg;
 
192
 
 
193
    cm_drawable_node_get_clipbox (dnode, &clipbox);
 
194
 
 
195
    if (dnode->shape)
 
196
    {
 
197
        reg = ws_region_copy (dnode->shape);
 
198
        ws_region_offset (reg, clipbox.x, clipbox.y);
 
199
    }
 
200
    else
 
201
    {
 
202
        reg = ws_region_rectangle (&clipbox);
 
203
    }
 
204
 
 
205
    return reg;
 
206
}
 
207
 
 
208
static void
 
209
print_region (const char *header, WsRegion *region)
 
210
{
 
211
    int i;
 
212
    int n_rects;
 
213
    WsRectangle *rects = NULL;
 
214
 
 
215
    ws_region_get_rectangles (region, &rects, &n_rects);
 
216
 
 
217
    g_print ("%s: \n", header);
 
218
    for (i = 0; i < n_rects; ++i)
 
219
    {
 
220
        WsRectangle *r = &(rects[i]);
 
221
 
 
222
        g_print ("   %d %d %d %d\n", r->x, r->y, r->width, r->height);
 
223
    }
 
224
    
 
225
    if (rects)
 
226
        g_free (rects);
 
227
    
 
228
}
 
229
 
 
230
static WsRegion *
 
231
drawable_node_get_covered_region (CmNode *node)
 
232
{
 
233
    CmDrawableNode *dnode = CM_DRAWABLE_NODE (node);
 
234
    WsRegion *result;
 
235
 
 
236
    ws_display_begin_error_trap (WS_RESOURCE (dnode->drawable)->display);
 
237
    
 
238
    if (ws_window_query_input_only (WS_WINDOW (dnode->drawable)))
 
239
    {
 
240
        result = NULL;
 
241
        goto out;
 
242
    }
 
243
    else if (!dnode->viewable)
 
244
    {
 
245
        result = NULL;
 
246
        goto out;
 
247
    }
 
248
    else if (dnode->alpha != 1.0)
 
249
    {
 
250
        result = NULL;
 
251
        goto out;
 
252
    }
 
253
    else if (cm_pix_texture_has_alpha (dnode->pix_texture))
 
254
    {
 
255
        result = NULL;
 
256
        goto out;
 
257
    }
 
258
    else if (dnode->explosion_level > DBL_EPSILON)
 
259
    {
 
260
        result = NULL;
 
261
        goto out;
 
262
    }
 
263
    else if (dnode->deformed)
 
264
    {
 
265
        result = NULL;
 
266
        goto out;
 
267
    }
 
268
    else
 
269
    {
 
270
        result = get_shape (dnode);
 
271
        goto out;
 
272
    }
 
273
 
 
274
out:
 
275
    ws_display_end_error_trap (WS_RESOURCE (dnode->drawable)->display);
 
276
    
 
277
    return result;
 
278
}
 
279
 
 
280
static void
 
281
set_geometries (CmDrawableNode *dnode)
 
282
{
 
283
    WsRegion *reg = NULL;
 
284
    WsRectangle clipbox;
 
285
 
 
286
    reg = get_shape (dnode);
 
287
 
 
288
    ws_region_get_clipbox (reg, &clipbox);
 
289
    
 
290
    cm_grid_set_region (dnode->grid, reg);
 
291
    cm_explosion_set_region (dnode->explosion, reg);
 
292
    
 
293
    cm_deform_set_geometry (dnode->deform,
 
294
                            clipbox.x,
 
295
                            clipbox.y,
 
296
                            clipbox.width,
 
297
                            clipbox.height);
 
298
    cm_shadow_set_geometry (dnode->shadow,
 
299
                            clipbox.x,
 
300
                            clipbox.y,
 
301
                            clipbox.width,
 
302
                            clipbox.height);
 
303
    
 
304
    ws_region_destroy (reg);    
 
305
}
 
306
 
 
307
static void
 
308
drawable_node_render (CmNode *node,
 
309
                      CmState *state)
 
310
{
338
311
    WsScreen *screen;
339
 
    int scr_w, scr_h;
340
 
#if 0
341
 
    double vw, vh;
342
 
    double vx, vy;
343
 
#endif
344
 
    
345
 
    if (!drawable_node->viewable)
346
 
        return;
347
 
    
348
 
    if (!drawable_node->pixmap)
349
 
        return;
350
 
    
351
 
    screen = ws_drawable_query_screen (WS_DRAWABLE (drawable_node->pixmap));
352
 
    texture = ws_pixmap_get_texture (drawable_node->pixmap);
353
 
    
354
 
    if (drawable_node->real_width == -1)
355
 
        update_geometry (drawable_node);
356
 
    
357
 
    scr_w = ws_screen_get_width (screen);
358
 
    scr_h = ws_screen_get_height (screen);
359
 
    
360
 
#if 0
361
 
    vw = drawable_node->width / scr_w;
362
 
    vh = drawable_node->height / scr_h;
363
 
    vx = drawable_node->x / scr_w;
364
 
    vy = drawable_node->y / scr_h;
365
 
#endif
366
 
    
367
 
#if 0
368
 
    g_print ("binding texture: %d\n", texture);
369
 
#endif
370
 
    
371
 
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
372
 
    
373
 
#if 0
374
 
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
375
 
    glEnable (GL_BLEND);
376
 
    glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
377
 
#endif
378
 
    
379
 
#if 0
380
 
    glBegin (GL_QUADS);
381
 
    glTexCoord2f (0, 0);
382
 
    glVertex3f (vx, 1 - vy, 0.0);
383
 
    glTexCoord2f (drawable_node->width, 0);
384
 
    glVertex3f (vx + vw, 1 - vy, 0.0);
385
 
    glTexCoord2f (drawable_node->width, drawable_node->height);
386
 
    glVertex3f (vx + vw, 1 - (vy + vh), 0.0);
387
 
    glTexCoord2f (0, drawable_node->height);
388
 
    glVertex3f (vx, 1 - (vy + vh), 0.0);
389
 
    glEnd ();
390
 
#endif
391
 
    
392
 
    glMatrixMode (GL_PROJECTION);
393
 
    glLoadIdentity ();
394
 
    
395
 
    gluOrtho2D (0, scr_w, scr_h, 0);
396
 
    
397
 
    glDisable (GL_TEXTURE_RECTANGLE_ARB);
398
 
    glColor4f (0.0, 0.0, 0.1, 0.3);
399
 
    
400
 
    glMatrixMode (GL_MODELVIEW);
401
 
    glLoadIdentity ();
402
 
    
403
 
    /* Emperically determined constant that gets rid of some fuzzyness
 
312
    CmDrawableNode *dnode = CM_DRAWABLE_NODE (node);
 
313
 
 
314
#if 0
 
315
    g_print ("are we going to render %lx (%p)?\n",
 
316
             WS_RESOURCE_XID (dnode->drawable), dnode);
 
317
#endif
 
318
    
 
319
    if (!dnode->viewable)
 
320
    {
 
321
#if 0
 
322
        g_print ("not rendering %lx since it is not viewable\n",
 
323
                 WS_RESOURCE_XID (dnode->drawable));
 
324
#endif
 
325
        return;
 
326
    }
 
327
    
 
328
    if (!dnode->pix_texture)
 
329
    {
 
330
#if 0
 
331
        g_print ("not rendering %lx since it doesn't have a pix_texture\n",
 
332
                 WS_RESOURCE_XID (dnode->drawable));
 
333
#endif
 
334
        return;
 
335
    }
 
336
    
 
337
    if (!dnode->pix_texture->pixmap)
 
338
    {
 
339
#if 0
 
340
        g_print ("not rendering %lx since it doesn't have a pixmap\n",
 
341
                 WS_RESOURCE_XID (dnode->drawable));
 
342
#endif
 
343
        return;
 
344
    }
 
345
    
 
346
#if 0
 
347
    g_print ("rendering %lx\n", WS_RESOURCE_XID (dnode->drawable));
 
348
#endif
 
349
 
 
350
    WsPixmap *pixmap = dnode->pix_texture->pixmap;
 
351
    WsDisplay *display = WS_RESOURCE (pixmap)->display;
 
352
    
 
353
    ws_display_begin_error_trap (display);
 
354
 
 
355
    if (ws_window_query_input_only (
 
356
            WS_WINDOW (dnode->drawable)))
 
357
    {
 
358
        ws_display_end_error_trap (display);
 
359
        return;
 
360
    }
 
361
 
 
362
    screen = ws_drawable_query_screen (
 
363
        WS_DRAWABLE (dnode->pix_texture->pixmap));
 
364
 
 
365
    if (!screen)
 
366
    {
 
367
        /* The pixmap was bad or something */
 
368
        ws_display_end_error_trap (display);
 
369
        return;
 
370
    }
 
371
    
 
372
    glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
 
373
    
 
374
    glPushMatrix();
 
375
 
 
376
    cm_state_set_screen_coords (state);
 
377
#if 0
 
378
    gluOrtho2D (0,
 
379
                ws_screen_get_width (screen),
 
380
                ws_screen_get_height (screen), 0);
 
381
#endif
 
382
    
 
383
    /* Empirically determined constant that gets rid of some fuzzyness
404
384
     */
405
 
    glTranslatef (-0.04, -0.04, 0);
406
 
    
407
 
    glShadeModel (GL_SMOOTH);
408
 
#if 0
409
 
    glEnable (GL_LIGHTING);
410
 
#endif
411
 
    glEnable (GL_BLEND);
412
 
    
413
 
    glColor4f (1.0, 1.0, 1.0, drawable_node->alpha);
 
385
#if 0
 
386
    glTranslatef (-0.125, -0.125, 0);
 
387
#endif
 
388
    
 
389
#if 0
 
390
    g_print ("setting geometry: %d %d %d %d\n",
 
391
             dnode->real_x, dnode->real_y,
 
392
             dnode->real_width, dnode->real_height);
 
393
#endif
 
394
    
 
395
    set_geometries (dnode);
 
396
    
 
397
#if 0
 
398
    glColor4f (1.0, 1.0, 1.0, dnode->alpha);
414
399
    glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
415
 
    glEnable (GL_TEXTURE_RECTANGLE_ARB);
416
 
#if 0
417
 
    glColor4f (1.0, 0.9 + 0.1 * g_random_double(), 0.0, 1.0);
418
 
#endif
419
 
    
420
 
    glBlendFunc (drawable_node->alpha < 0.99 ? GL_SRC_ALPHA : GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
421
 
    glDisable (GL_LIGHTING);
422
 
    
423
 
    draw_window(drawable_node);
424
 
    
425
 
#if 0
426
 
    glPopMatrix ();
427
 
#endif
428
 
    
429
 
#if 0
430
 
    g_print ("done painting\n");
431
 
#endif
 
400
    glEnable (GL_BLEND);
 
401
    glBlendFunc (dnode->alpha < 0.99 ? GL_SRC_ALPHA :
 
402
                 GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 
403
    
 
404
#endif
 
405
#if 0
 
406
    cm_node_render (CM_NODE (dnode->pix_texture), state);
 
407
#endif
 
408
    
 
409
#if 0
 
410
    glTranslatef (20 * g_random_double(), 20 * g_random_double(), 0.0);
 
411
#endif
 
412
    
 
413
    cm_node_render (CM_NODE (dnode->deform), state);
 
414
    
 
415
    glPopMatrix();
 
416
    
 
417
    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
 
418
    ws_display_end_error_trap (display);
 
419
    
432
420
}
433
421
 
434
422
static void
447
435
on_damage (WsPixmap *pixmap, gpointer data)
448
436
{
449
437
    CmDrawableNode *node = data;
450
 
    
451
 
#if 0
452
 
    g_print ("queueing paint\n");
453
 
#endif
454
 
    
 
438
 
455
439
    queue_paint (node);
456
440
}
457
441
 
460
444
{
461
445
    WsWindow *window;
462
446
    WsDisplay *display = WS_RESOURCE (node->drawable)->display;
463
 
    WsRectangle geometry;
464
 
    
 
447
    WsPixmap *pixmap;
 
448
 
 
449
    if (node->pix_texture->pixmap && !node->pix_texture->pixmap->do_updates)
 
450
    {
465
451
#if 0
466
 
    g_print ("refreshing pixmap\n");
 
452
        g_print ("not refreshing\n");
467
453
#endif
468
 
    
469
 
    if (node->pixmap && !ws_pixmap_get_updates (node->pixmap))
470
454
        return;
471
 
    
 
455
    }
 
456
 
472
457
    window = WS_WINDOW (node->drawable);
473
458
    
474
 
    if (node->pixmap)
475
 
    {
476
 
#if 0
477
 
        g_print ("unreffing %p\n", node->pixmap);
478
 
#endif
479
 
        g_object_unref (node->pixmap);
480
 
    }
481
 
    
482
459
    ws_display_begin_error_trap (display);
483
460
    
484
 
    node->pixmap = NULL;
 
461
    pixmap = NULL;
485
462
    
486
463
    if (ws_window_query_mapped (window)         &&
487
464
        !ws_window_query_input_only (window))
488
465
    {
489
 
        node->pixmap = ws_window_name_pixmap (window);
 
466
        pixmap = ws_window_name_pixmap (window);
 
467
#if 0
 
468
        g_print ("name pixmap on %lx  %p\n", WS_RESOURCE_XID (window), pixmap);
 
469
#endif
490
470
    }
491
471
    
492
472
    if (ws_display_end_error_trap_with_return (display))
493
473
    {
494
 
        ws_display_begin_error_trap (display);
495
 
        
496
 
        if (node->pixmap)
497
 
        {
498
 
            g_object_unref (node->pixmap);
499
 
            
500
 
            node->pixmap = NULL;
501
 
        }
502
 
        
503
 
        ws_display_end_error_trap (display);
504
 
    }
505
 
    else
506
 
    {
507
 
        if (node->pixmap)
508
 
        {
509
 
            ws_drawable_query_geometry (WS_DRAWABLE (window), &geometry);
510
 
            
511
 
#if 0
512
 
            g_print ("naming pixmap %lx on window %lx (%d x %d)\n", WS_RESOURCE_XID (node->pixmap), WS_RESOURCE_XID (window), geometry.width, geometry.height);
513
 
#endif
514
 
            
515
 
            ws_drawable_query_geometry (WS_DRAWABLE (node->pixmap), &geometry);
516
 
            
517
 
#if 0
518
 
            g_print ("pixmap size (%d x %d)\n", geometry.width, geometry.height);
519
 
#endif
520
 
            ws_pixmap_set_damage_callback (node->pixmap, on_damage, node);
521
 
        }
522
 
    }
523
 
}
524
 
 
525
 
static void
526
 
on_configure (WsWindow *window,
527
 
              int x,
528
 
              int y,
529
 
              int width,
530
 
              int height,
531
 
              int bw,
532
 
              WsWindow *above,
533
 
              gboolean override_redirect,
534
 
              gpointer data)
535
 
{
536
 
    CmDrawableNode *node = data;
537
 
    
538
 
    if (node->pixmap && !ws_pixmap_get_updates (node->pixmap))
539
 
        return;
540
 
    
541
 
    // g_print ("configure\n");
542
 
    if (width != node->real_width ||
543
 
        height != node->real_height)
544
 
    {
545
 
        refresh_pixmap (node);
546
 
    }
547
 
    
548
 
    node->real_x = x;
549
 
    node->real_y = y;
550
 
    node->real_width = width;
551
 
    node->real_height = height;
552
 
    
553
 
    queue_paint (node);
 
474
        if (pixmap)
 
475
        {
 
476
            ws_display_begin_error_trap (display);
 
477
        
 
478
            g_object_unref (pixmap);
 
479
 
 
480
            ws_display_end_error_trap (display);
 
481
            
 
482
            pixmap = NULL;
 
483
        }
 
484
    }
 
485
 
 
486
    ws_display_begin_error_trap (display);
 
487
    
 
488
    cm_pix_texture_set_pixmap (node->pix_texture, pixmap);
 
489
    
 
490
    if (pixmap)
 
491
    {
 
492
        g_signal_connect (pixmap, "damage_notify_event", G_CALLBACK (on_damage), node);
 
493
 
 
494
        g_object_unref (pixmap);
 
495
    }
 
496
        
 
497
    ws_display_end_error_trap (display);
554
498
}
555
499
 
556
500
CmDrawableNode *
557
 
cm_drawable_node_new (WsDrawable *drawable)
 
501
cm_drawable_node_new (WsDrawable *drawable,
 
502
                      WsRectangle *geometry)
558
503
{
559
504
    CmDrawableNode *node;
560
505
    WsDisplay *display;
 
506
    WsRectangle dummy;
561
507
    
562
508
    g_return_val_if_fail (drawable != NULL, NULL);
 
509
 
 
510
    if (!geometry)
 
511
    {
 
512
        /* FIXME: possibly just assertion fail if this happens? */
 
513
        dummy.x = 0;
 
514
        dummy.y = 0;
 
515
        dummy.width = 100;
 
516
        dummy.height = 100;
 
517
 
 
518
        geometry = &dummy;
 
519
    }
563
520
    
564
521
    display = WS_RESOURCE (drawable)->display;
565
522
    
566
523
    node = g_object_new (CM_TYPE_DRAWABLE_NODE, NULL);
567
524
    
568
 
    g_print ("creating drawable node %p containing %lx\n",
569
 
             node, WS_RESOURCE_XID (drawable));
570
 
    
571
525
    node->drawable = drawable;
572
526
    
573
 
    ws_window_set_configure_callback (
574
 
        WS_WINDOW (drawable), on_configure, node);
575
527
    node->viewable = TRUE;
576
528
    
577
 
    node->deform_func = cm_identity_deform;
578
 
    node->deform_data = NULL;
579
 
    
580
 
    node->damage_func = NULL;
581
 
    node->damage_data = NULL;
582
 
    
583
529
    node->timer = g_timer_new ();
584
 
    
585
 
    node->real_x = -1;
586
 
    node->real_y = -1;
587
 
    node->real_width = -1;
588
 
    node->real_height = -1;
 
530
 
 
531
    node->geometry = *geometry;
 
532
    node->shape = NULL;
589
533
    
590
534
    ws_display_init_composite (ws_drawable_get_display (drawable));
591
535
    ws_display_init_damage (ws_drawable_get_display (drawable));
596
540
    {
597
541
        refresh_pixmap (node);
598
542
    }
599
 
    else
600
 
    {
601
 
        g_print ("this should not happen \n");
602
 
        node->pixmap = WS_PIXMAP (drawable);
603
 
    }
604
 
    
 
543
 
605
544
    return node;
606
545
}
607
546
 
614
553
    cm_node_queue_repaint ((CmNode *)node);
615
554
}
616
555
 
617
 
void
618
 
cm_drawable_node_update_pixmap (CmDrawableNode *node)
 
556
gboolean
 
557
cm_drawable_node_get_viewable (CmDrawableNode *node)
619
558
{
620
 
    g_print ("refreshing pixmap because app told us to\n");
621
 
    refresh_pixmap (node);
 
559
    return node->viewable;
622
560
}
623
561
 
624
562
void
625
563
cm_drawable_node_set_geometry (CmDrawableNode *node,
626
 
                               double x,
627
 
                               double y,
628
 
                               double width,
629
 
                               double height)
 
564
                               WsRectangle    *geometry)
630
565
{
631
 
    node->deform_func = cm_user_geometry_deform;
632
 
    node->deform_data = node;
633
 
    
634
 
    node->user_x = x;
635
 
    node->user_y = y;
636
 
    node->user_width = width;
637
 
    node->user_height = height;
 
566
    g_return_if_fail (geometry != NULL);
 
567
 
 
568
    node->geometry = *geometry;
638
569
    
639
570
    queue_paint (node);
640
571
}
643
574
cm_drawable_node_set_patch (CmDrawableNode *node,
644
575
                            CmPoint points[][4])
645
576
{
646
 
    node->deform_func = cm_patch_deform;
647
 
    node->deform_data = node;
648
 
    
649
 
    memcpy (node->patch_points, points, sizeof node->patch_points);
650
 
    
651
 
    queue_paint (node);
 
577
    g_return_if_fail (CM_IS_DRAWABLE_NODE (node));
 
578
 
 
579
    node->deformed = TRUE;
 
580
    
 
581
    cm_deform_set_patch (node->deform, points);
652
582
}
653
583
 
654
584
void
655
 
cm_drawable_node_unset_geometry (CmDrawableNode *node)
 
585
cm_drawable_node_unset_patch (CmDrawableNode *node)
656
586
{
657
 
    node->deform_func = cm_identity_deform;
658
 
    node->deform_data = NULL;
 
587
    cm_deform_set_deform (node->deform, NULL, NULL);
 
588
 
 
589
    node->deformed = FALSE;
659
590
    
660
591
    queue_paint (node);
661
592
}
664
595
cm_drawable_node_set_updates (CmDrawableNode *node,
665
596
                              gboolean        updates)
666
597
{
667
 
    ws_display_begin_error_trap (ws_drawable_get_display (node->drawable));
668
 
    
669
 
    ws_pixmap_set_updates (node->pixmap, updates);
670
 
    
671
 
    if (node->pixmap && ws_pixmap_get_updates (node->pixmap))
672
 
        update_geometry (node);
673
 
    
674
 
    refresh_pixmap (node);
675
 
    
676
 
    ws_display_end_error_trap (ws_drawable_get_display (node->drawable));
 
598
    updates = !!updates;
 
599
 
 
600
    if (node->pix_texture->pixmap)
 
601
        ws_pixmap_set_updates (node->pix_texture->pixmap, updates);
677
602
}
678
603
 
679
604
void
681
606
                            double alpha)
682
607
{
683
608
    node->alpha = alpha;
684
 
    
685
 
    queue_paint (node);
 
609
 
 
610
    if (node->alpha < 0.99)
 
611
    {
 
612
        WsColor alpha = { node->alpha * 0xffff, 0xffff, 0xffff, 0xffff };
 
613
        
 
614
        cm_tex_env_set_modulate (node->tex_env, &alpha);
 
615
    }
 
616
    else
 
617
    {
 
618
        cm_tex_env_set_replace (node->tex_env);
 
619
    }
 
620
    
 
621
    queue_paint (node);
 
622
}
 
623
 
 
624
void
 
625
cm_drawable_node_update_pixmap (CmDrawableNode *node)
 
626
{
 
627
#if 0
 
628
    g_print ("refreshing pixmap because app told us to\n");
 
629
#endif
 
630
    refresh_pixmap (node);
 
631
}
 
632
 
 
633
void
 
634
cm_drawable_node_set_shape (CmDrawableNode *node,
 
635
                            WsRegion *shape)
 
636
{
 
637
    WsRegion *new_shape = shape? ws_region_copy (shape) : NULL;
 
638
 
 
639
    if (node->shape)
 
640
        ws_region_destroy (node->shape);
 
641
 
 
642
    node->shape = new_shape;
 
643
 
 
644
    queue_paint (node);
 
645
}
 
646
 
 
647
void
 
648
cm_drawable_node_get_clipbox  (CmDrawableNode *node,
 
649
                               WsRectangle    *clipbox)
 
650
{
 
651
    if (!clipbox)
 
652
        return;
 
653
 
 
654
    *clipbox = node->geometry;
 
655
}
 
656
 
 
657
void
 
658
cm_drawable_node_set_scale_rect (CmDrawableNode *node,
 
659
                                 WsRectangle  *rect)
 
660
{
 
661
    cm_deform_set_rectangle (node->deform, rect);
 
662
 
 
663
    node->deformed = TRUE;
 
664
    
 
665
    queue_paint (node);
 
666
}
 
667
 
 
668
void
 
669
cm_drawable_node_set_explosion_level (CmDrawableNode *node,
 
670
                                      gdouble          explosion_level)
 
671
{
 
672
    if (fabs (explosion_level) < DBL_EPSILON)
 
673
    {
 
674
        cm_pix_texture_set_child (node->pix_texture, node->grid);
 
675
 
 
676
        if (cm_node_is_toplevel (CM_NODE (node->shadow)))
 
677
        {
 
678
            cm_stacker_add_child (node->stacker, CM_NODE (node->shadow));
 
679
            cm_stacker_lower_child (node->stacker, CM_NODE (node->shadow));
 
680
        }
 
681
    }
 
682
    else
 
683
    {
 
684
        cm_pix_texture_set_child (node->pix_texture, node->explosion);
 
685
 
 
686
        if (!cm_node_is_toplevel (CM_NODE (node->shadow)))
 
687
            cm_stacker_remove_child (CM_NODE (node->shadow)->parents->data, CM_NODE (node->shadow));
 
688
    }
 
689
 
 
690
    cm_explosion_set_level (node->explosion, explosion_level);
 
691
    node->explosion_level = explosion_level;
686
692
}