~ubuntu-branches/ubuntu/hardy/libcm/hardy

« back to all changes in this revision

Viewing changes to src/wspixmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthew Garrett
  • Date: 2006-02-17 14:28:18 UTC
  • Revision ID: james.westby@ubuntu.com-20060217142818-1ho3qr7jbh2m400r
Tags: upstream-0.0.16
ImportĀ upstreamĀ versionĀ 0.0.16

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "wsint.h"
 
2
 
 
3
G_DEFINE_TYPE (WsPixmap, ws_pixmap, WS_TYPE_DRAWABLE);
 
4
 
 
5
static WsFormat ws_pixmap_get_format (WsDrawable             *drawable);
 
6
static GObject *ws_pixmap_constructor (GType                  type,
 
7
                                       guint                  n_construct_properties,
 
8
                                       GObjectConstructParam *construct_params);
 
9
 
 
10
static void
 
11
ws_pixmap_finalize (GObject *object)
 
12
{
 
13
    WsPixmap *pixmap = WS_PIXMAP (object);
 
14
    
 
15
    /* FIXME: Deal with foreign objects correctly */
 
16
#if 0
 
17
    g_print ("finalizing %p\n", object);
 
18
#endif
 
19
 
 
20
    if (pixmap->texture)
 
21
    {
 
22
        glXReleaseTexImageEXT (WS_RESOURCE_XDISPLAY (pixmap),
 
23
                               pixmap->glx_pixmap,
 
24
                               GLX_FRONT_LEFT_EXT);
 
25
        
 
26
        glXDestroyGLXPixmap (WS_RESOURCE_XDISPLAY (pixmap),
 
27
                             pixmap->glx_pixmap);
 
28
 
 
29
#if 0
 
30
        g_print ("deleting texture %d\n", pixmap->texture);
 
31
#endif
 
32
        
 
33
        glDeleteTextures (1, &pixmap->texture);
 
34
    }
 
35
 
 
36
    g_assert (pixmap->damage);
 
37
    
 
38
    XDamageDestroy (WS_RESOURCE_XDISPLAY (pixmap), pixmap->damage);
 
39
    _ws_display_unregister_damage (WS_RESOURCE (pixmap)->display,
 
40
                                   pixmap->damage);
 
41
    
 
42
    XFreePixmap (WS_RESOURCE_XDISPLAY (object),
 
43
                 WS_RESOURCE_XID (object));
 
44
    
 
45
    G_OBJECT_CLASS (ws_pixmap_parent_class)->finalize (object);
 
46
}
 
47
 
 
48
static void
 
49
ws_pixmap_class_init (WsPixmapClass *class)
 
50
{
 
51
    GObjectClass *object_class = G_OBJECT_CLASS (class);
 
52
    WsDrawableClass *drawable_class = WS_DRAWABLE_CLASS (class);
 
53
    
 
54
    object_class->finalize = ws_pixmap_finalize;
 
55
    object_class->constructor = ws_pixmap_constructor;
 
56
    drawable_class->get_format = ws_pixmap_get_format;
 
57
}
 
58
 
 
59
static void
 
60
repair_pixmap (WsPixmap *pixmap)
 
61
{
 
62
    /* Note that it is important to clear the damage _before_
 
63
     * updating the texture. Otherwise, we will miss any damage
 
64
     * that arrives after updating, but before clearing.
 
65
     */
 
66
 
 
67
  XDamageSubtract (WS_RESOURCE_XDISPLAY (pixmap),
 
68
                     pixmap->damage,
 
69
                     None, None);
 
70
    
 
71
    if (pixmap->texture)
 
72
    {
 
73
        WsRectangle geometry;
 
74
        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, pixmap->texture);
 
75
 
 
76
        ws_drawable_query_geometry (WS_DRAWABLE (pixmap), &geometry);
 
77
        
 
78
#if 0
 
79
        g_print ("bind size; %d %d (%d bytes)\n", geometry.width, geometry.height, geometry.width * geometry.height * 4);
 
80
#endif
 
81
 
 
82
        glXBindTexImageEXT (WS_RESOURCE_XDISPLAY (pixmap),
 
83
                            pixmap->glx_pixmap,
 
84
                            GLX_FRONT_LEFT_EXT, NULL);
 
85
    }
 
86
    
 
87
    if (pixmap->damage_callback)
 
88
        pixmap->damage_callback (pixmap, pixmap->damage_data);
 
89
}              
 
90
 
 
91
static void
 
92
on_damage (WsDisplay *display,
 
93
           Damage     damage,
 
94
           gpointer   data)
 
95
{
 
96
    WsPixmap *pixmap = data;
 
97
 
 
98
#if 0
 
99
    g_print ("processing damage on %lx\n", WS_RESOURCE_XID (pixmap));
 
100
#endif
 
101
 
 
102
    if (pixmap->do_updates)
 
103
        repair_pixmap (pixmap);
 
104
}
 
105
 
 
106
static WsFormat
 
107
ws_pixmap_get_format (WsDrawable *drawable)
 
108
{
 
109
    WsPixmap *pixmap = WS_PIXMAP (drawable);
 
110
 
 
111
    return pixmap->format;
 
112
}
 
113
 
 
114
static GObject *
 
115
ws_pixmap_constructor (GType                    type,
 
116
                       guint                    n_construct_properties,
 
117
                       GObjectConstructParam *construct_params)
 
118
{
 
119
    GObject *object;
 
120
    WsPixmap *pixmap;
 
121
    
 
122
    object = G_OBJECT_CLASS (ws_pixmap_parent_class)->constructor (
 
123
        type, n_construct_properties, construct_params);
 
124
    
 
125
    pixmap = WS_PIXMAP (object);
 
126
    
 
127
    pixmap->damage = XDamageCreate (WS_RESOURCE_XDISPLAY (pixmap),
 
128
                                    WS_RESOURCE_XID (pixmap),
 
129
                                    XDamageReportNonEmpty);
 
130
 
 
131
    XDamageSubtract (WS_RESOURCE_XDISPLAY (pixmap),
 
132
                     pixmap->damage,
 
133
                     None, None);
 
134
 
 
135
    g_assert (pixmap->damage);
 
136
    
 
137
    _ws_display_register_damage (WS_RESOURCE (pixmap)->display,
 
138
                                 pixmap->damage,
 
139
                                 on_damage, pixmap);
 
140
    
 
141
    return object;
 
142
}
 
143
 
 
144
static void
 
145
ws_pixmap_init (WsPixmap *pixmap)
 
146
{
 
147
    pixmap->damage_callback = NULL;
 
148
    pixmap->damage_data = NULL;
 
149
    pixmap->do_updates = TRUE;
 
150
}
 
151
 
 
152
static WsPixmap *
 
153
pixmap_new (WsDisplay *display,
 
154
            XID        xid,
 
155
            WsFormat   format)
 
156
{
 
157
    WsPixmap *pixmap = g_object_new (WS_TYPE_PIXMAP,
 
158
                                     "display", display,
 
159
                                     "xid", xid,
 
160
                                     NULL);
 
161
 
 
162
#if 0
 
163
    g_print ("allocating pixmap %lx\n", WS_RESOURCE_XID (pixmap));
 
164
#endif
 
165
    
 
166
    pixmap->format = format;
 
167
    
 
168
    g_assert (xid == WS_RESOURCE_XID (pixmap));
 
169
    
 
170
    return pixmap;
 
171
}
 
172
 
 
173
WsPixmap *
 
174
ws_pixmap_new (WsDrawable *drawable,
 
175
               int         width,
 
176
               int         height)
 
177
{
 
178
    Pixmap pixmap;
 
179
    Display *xdisplay;
 
180
    WsFormat format;
 
181
 
 
182
    g_return_val_if_fail (WS_IS_DRAWABLE (drawable), NULL);
 
183
    g_return_val_if_fail (
 
184
        ws_format_is_viewable (ws_drawable_get_format (drawable)), NULL);
 
185
    
 
186
    format = ws_drawable_get_format (drawable);
 
187
    
 
188
    xdisplay = WS_RESOURCE_XDISPLAY (drawable);
 
189
 
 
190
    pixmap = XCreatePixmap (xdisplay,
 
191
                            WS_RESOURCE_XID (drawable),
 
192
                            width, height, ws_format_get_depth (format));
 
193
    
 
194
    return pixmap_new (WS_RESOURCE (drawable)->display,
 
195
                       pixmap, format);
 
196
}
 
197
 
 
198
WsPixmap *
 
199
_ws_pixmap_ensure (WsDisplay *display,
 
200
                   XID        xid,
 
201
                   WsFormat   format)
 
202
{
 
203
    WsPixmap *pixmap =
 
204
        g_hash_table_lookup (display->xresources, (gpointer)xid);
 
205
    
 
206
    if (!pixmap)
 
207
        pixmap = pixmap_new (display, xid, format);
 
208
    
 
209
    return pixmap;
 
210
}
 
211
 
 
212
static GLXPixmap
 
213
create_glx_pixmap (WsPixmap *pixmap)
 
214
{
 
215
    Display *xdisplay = WS_RESOURCE_XDISPLAY (pixmap);
 
216
    int screen_no = WS_DRAWABLE_XSCREEN_NO (pixmap);
 
217
    WsFormat format = ws_drawable_get_format (WS_DRAWABLE (pixmap));
 
218
    XVisualInfo *vis_infos;
 
219
    int n_infos;
 
220
    XVisualInfo template;
 
221
    
 
222
    template.screen = screen_no;
 
223
    template.depth = ws_format_get_depth (format);
 
224
    template.class = TrueColor;
 
225
    
 
226
    ws_format_get_masks (format,
 
227
                         &template.red_mask,
 
228
                         &template.green_mask,
 
229
                         &template.blue_mask);
 
230
    
 
231
    vis_infos = XGetVisualInfo (xdisplay,
 
232
                                VisualScreenMask        |
 
233
                                VisualDepthMask         |
 
234
                                VisualClassMask         |
 
235
                                VisualRedMaskMask       |
 
236
                                VisualGreenMaskMask     |
 
237
                                VisualBlueMaskMask,
 
238
                                &template, &n_infos);
 
239
    
 
240
    if (!vis_infos)
 
241
    {
 
242
        g_warning ("No XVisualInfos found - will likely crash");
 
243
        return None;
 
244
    }
 
245
    
 
246
    /* All of the XVisualInfos returned should be ok, so just pick
 
247
     * the first one.
 
248
     */
 
249
    
 
250
    return glXCreateGLXPixmap (
 
251
        xdisplay, vis_infos, WS_RESOURCE_XID (pixmap));
 
252
}
 
253
 
 
254
GLuint
 
255
ws_pixmap_get_texture (WsPixmap  *pixmap)
 
256
{
 
257
    g_return_val_if_fail (WS_IS_PIXMAP (pixmap), 0);
 
258
    
 
259
    if (!pixmap->texture)
 
260
    {
 
261
        WsRectangle geometry;
 
262
        pixmap->glx_pixmap = create_glx_pixmap (pixmap);
 
263
        
 
264
        if (!pixmap->glx_pixmap)
 
265
        {
 
266
            g_warning ("Could not create a GLXpixmap for %lx\n",
 
267
                       WS_RESOURCE_XID (pixmap));
 
268
            
 
269
            return 0;
 
270
        }
 
271
 
 
272
        /* FIXME: at this point we are just assuming that texture from
 
273
         * drawable is available. At some point we should reinstate the
 
274
         * XGetImage() code. At that point configure.ac needs to be
 
275
         * changed to not report an error.
 
276
         */
 
277
        glGenTextures (1, &pixmap->texture);
 
278
 
 
279
        ws_drawable_query_geometry (WS_DRAWABLE (pixmap), &geometry);
 
280
        
 
281
#if 0
 
282
        g_print ("creating texture %d\n", pixmap->texture);
 
283
        g_print ("size; %d %d (%d bytes)\n", geometry.width, geometry.height, geometry.width * geometry.height * 4);
 
284
#endif
 
285
 
 
286
        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, pixmap->texture);
 
287
        
 
288
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 
289
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
290
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
 
291
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
 
292
        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_R, GL_CLAMP);
 
293
 
 
294
#if 0
 
295
        /* XXX JX experimental stuffs */
 
296
        glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
 
297
        glTexEnvi (GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE);
 
298
        glTexEnvi (GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_CONSTANT_ARB);
 
299
        /* and then need to set a glColor somewhere... */
 
300
#endif
 
301
        
 
302
        glXBindTexImageEXT (WS_RESOURCE_XDISPLAY (pixmap),
 
303
                            pixmap->glx_pixmap,
 
304
                            GLX_FRONT_LEFT_EXT, NULL);
 
305
        
 
306
#if 0
 
307
        g_print ("creating damage: %lx on %lx\n", pixmap->damage,
 
308
                 WS_RESOURCE_XID (pixmap));
 
309
#endif
 
310
    }
 
311
    
 
312
    return pixmap->texture;
 
313
}
 
314
 
 
315
void
 
316
ws_pixmap_set_damage_callback (WsPixmap *pixmap,
 
317
                               WsDamageCallback cb,
 
318
                               gpointer  data)
 
319
{
 
320
    pixmap->damage_callback = cb;
 
321
    pixmap->damage_data = data;
 
322
}
 
323
 
 
324
void
 
325
ws_pixmap_set_updates (WsPixmap *pixmap, gboolean updates)
 
326
{
 
327
  pixmap->do_updates = !!updates;
 
328
 
 
329
  if (pixmap->do_updates)
 
330
    repair_pixmap (pixmap);
 
331
}
 
332
 
 
333
gboolean
 
334
ws_pixmap_get_updates (WsPixmap *pixmap)
 
335
{
 
336
  return pixmap->do_updates;
 
337
}