"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / winsys / cogl-texture-pixmap-x11.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2010 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
20  *
21  *
22  *
23  * Authors:
24  *  Neil Roberts   <neil@linux.intel.com>
25  *  Johan Bilien   <johan.bilien@nokia.com>
26  *  Robert Bragg   <robert@linux.intel.com>
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "cogl-debug.h"
34 #include "cogl-internal.h"
35 #include "cogl-util.h"
36 #include "cogl-texture-pixmap-x11.h"
37 #include "cogl-texture-pixmap-x11-private.h"
38 #include "cogl-bitmap-private.h"
39 #include "cogl-texture-private.h"
40 #include "cogl-texture-driver.h"
41 #include "cogl-texture-2d-private.h"
42 #include "cogl-texture-rectangle-private.h"
43 #include "cogl-context-private.h"
44 #include "cogl-display-private.h"
45 #include "cogl-renderer-private.h"
46 #include "cogl-handle.h"
47 #include "cogl-winsys-private.h"
48 #include "cogl-pipeline-opengl-private.h"
49 #include "cogl-xlib.h"
50
51 #include <X11/Xlib.h>
52 #include <X11/Xutil.h>
53
54 #include <sys/ipc.h>
55 #include <sys/shm.h>
56 #include <X11/extensions/XShm.h>
57
58 #include <string.h>
59 #include <math.h>
60
61 static void _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap);
62
63 COGL_TEXTURE_DEFINE (TexturePixmapX11, texture_pixmap_x11);
64
65 static const CoglTextureVtable cogl_texture_pixmap_x11_vtable;
66
67 GQuark
68 cogl_texture_pixmap_x11_error_quark (void)
69 {
70   return g_quark_from_static_string ("cogl-texture-pixmap-error-quark");
71 }
72
73 static void
74 cogl_damage_rectangle_union (CoglDamageRectangle *damage_rect,
75                              int x,
76                              int y,
77                              int width,
78                              int height)
79 {
80   /* If the damage region is empty then we'll just copy the new
81      rectangle directly */
82   if (damage_rect->x1 == damage_rect->x2 ||
83       damage_rect->y1 == damage_rect->y2)
84     {
85       damage_rect->x1 = x;
86       damage_rect->y1 = y;
87       damage_rect->x2 = x + width;
88       damage_rect->y2 = y + height;
89     }
90   else
91     {
92       if (damage_rect->x1 > x)
93         damage_rect->x1 = x;
94       if (damage_rect->y1 > y)
95         damage_rect->y1 = y;
96       if (damage_rect->x2 < x + width)
97         damage_rect->x2 = x + width;
98       if (damage_rect->y2 < y + height)
99         damage_rect->y2 = y + height;
100     }
101 }
102
103 static gboolean
104 cogl_damage_rectangle_is_whole (const CoglDamageRectangle *damage_rect,
105                                 unsigned int width,
106                                 unsigned int height)
107 {
108   return (damage_rect->x1 == 0 && damage_rect->y1 == 0
109           && damage_rect->x2 == width && damage_rect->y2 == height);
110 }
111
112 static const CoglWinsysVtable *
113 _cogl_texture_pixmap_x11_get_winsys (CoglTexturePixmapX11 *tex_pixmap)
114 {
115   /* FIXME: A CoglContext should be reachable from a CoglTexture
116    * pointer */
117   _COGL_GET_CONTEXT (ctx, NULL);
118
119   return ctx->display->renderer->winsys_vtable;
120 }
121
122 static void
123 process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
124                       XDamageNotifyEvent *damage_event)
125 {
126   Display *display;
127   enum { DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
128   const CoglWinsysVtable *winsys;
129
130   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
131
132   display = cogl_xlib_get_display ();
133
134   COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);
135
136   switch (tex_pixmap->damage_report_level)
137     {
138     case COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES:
139       /* For raw rectangles we don't need do look at the damage region
140          at all because the damage area is directly given in the event
141          struct and the reporting of events is not affected by
142          clearing the damage region */
143       handle_mode = DO_NOTHING;
144       break;
145
146     case COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES:
147     case COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY:
148       /* For delta rectangles and non empty we'll query the damage
149          region for the bounding box */
150       handle_mode = NEED_BOUNDING_BOX;
151       break;
152
153     case COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX:
154       /* For bounding box we need to clear the damage region but we
155          don't actually care what it was because the damage event
156          itself contains the bounding box of the region */
157       handle_mode = NEEDS_SUBTRACT;
158       break;
159
160     default:
161       g_assert_not_reached ();
162     }
163
164   /* If the damage already covers the whole rectangle then we don't
165      need to request the bounding box of the region because we're
166      going to update the whole texture anyway. */
167   if (cogl_damage_rectangle_is_whole (&tex_pixmap->damage_rect,
168                                       tex_pixmap->width,
169                                       tex_pixmap->height))
170     {
171       if (handle_mode != DO_NOTHING)
172         XDamageSubtract (display, tex_pixmap->damage, None, None);
173     }
174   else if (handle_mode == NEED_BOUNDING_BOX)
175     {
176       XserverRegion parts;
177       int r_count;
178       XRectangle r_bounds;
179       XRectangle *r_damage;
180
181       /* We need to extract the damage region so we can get the
182          bounding box */
183
184       parts = XFixesCreateRegion (display, 0, 0);
185       XDamageSubtract (display, tex_pixmap->damage, None, parts);
186       r_damage = XFixesFetchRegionAndBounds (display,
187                                              parts,
188                                              &r_count,
189                                              &r_bounds);
190       cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
191                                    r_bounds.x,
192                                    r_bounds.y,
193                                    r_bounds.width,
194                                    r_bounds.height);
195       if (r_damage)
196         XFree (r_damage);
197
198       XFixesDestroyRegion (display, parts);
199     }
200   else
201     {
202       if (handle_mode == NEEDS_SUBTRACT)
203         /* We still need to subtract from the damage region but we
204            don't care what the region actually was */
205         XDamageSubtract (display, tex_pixmap->damage, None, None);
206
207       cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
208                                    damage_event->area.x,
209                                    damage_event->area.y,
210                                    damage_event->area.width,
211                                    damage_event->area.height);
212     }
213
214   if (tex_pixmap->winsys)
215     {
216       /* If we're using the texture from pixmap extension then there's no
217          point in getting the region and we can just mark that the texture
218          needs updating */
219       winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
220       winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
221     }
222 }
223
224 static CoglFilterReturn
225 _cogl_texture_pixmap_x11_filter (XEvent *event, void *data)
226 {
227   CoglTexturePixmapX11 *tex_pixmap = data;
228   int damage_base;
229
230   _COGL_GET_CONTEXT (ctxt, COGL_FILTER_CONTINUE);
231
232   damage_base = _cogl_xlib_get_damage_base ();
233   if (event->type == damage_base + XDamageNotify)
234     {
235       XDamageNotifyEvent *damage_event = (XDamageNotifyEvent *) event;
236
237       if (damage_event->damage == tex_pixmap->damage)
238         process_damage_event (tex_pixmap, damage_event);
239     }
240
241   return COGL_FILTER_CONTINUE;
242 }
243
244 static void
245 set_damage_object_internal (CoglContext *ctx,
246                             CoglTexturePixmapX11 *tex_pixmap,
247                             Damage damage,
248                             CoglTexturePixmapX11ReportLevel report_level)
249 {
250   if (tex_pixmap->damage)
251     {
252       cogl_xlib_renderer_remove_filter (ctx->display->renderer,
253                                         _cogl_texture_pixmap_x11_filter,
254                                         tex_pixmap);
255
256       if (tex_pixmap->damage_owned)
257         {
258           XDamageDestroy (cogl_xlib_get_display (), tex_pixmap->damage);
259           tex_pixmap->damage_owned = FALSE;
260         }
261     }
262
263   tex_pixmap->damage = damage;
264   tex_pixmap->damage_report_level = report_level;
265
266   if (damage)
267     cogl_xlib_renderer_add_filter (ctx->display->renderer,
268                                    _cogl_texture_pixmap_x11_filter,
269                                    tex_pixmap);
270 }
271
272 CoglTexturePixmapX11 *
273 cogl_texture_pixmap_x11_new (CoglContext *ctxt,
274                              guint32 pixmap,
275                              gboolean automatic_updates,
276                              GError **error)
277 {
278   CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
279   Display *display = cogl_xlib_get_display ();
280   Window pixmap_root_window;
281   int pixmap_x, pixmap_y;
282   unsigned int pixmap_border_width;
283   CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
284   XWindowAttributes window_attributes;
285   int damage_base;
286   const CoglWinsysVtable *winsys;
287
288   _cogl_texture_init (tex, &cogl_texture_pixmap_x11_vtable);
289
290   tex_pixmap->pixmap = pixmap;
291   tex_pixmap->image = NULL;
292   tex_pixmap->shm_info.shmid = -1;
293   tex_pixmap->tex = COGL_INVALID_HANDLE;
294   tex_pixmap->damage_owned = FALSE;
295   tex_pixmap->damage = 0;
296
297   if (!XGetGeometry (display, pixmap, &pixmap_root_window,
298                      &pixmap_x, &pixmap_y,
299                      &tex_pixmap->width, &tex_pixmap->height,
300                      &pixmap_border_width, &tex_pixmap->depth))
301     {
302       g_free (tex_pixmap);
303       g_set_error (error,
304                    COGL_TEXTURE_PIXMAP_X11_ERROR,
305                    COGL_TEXTURE_PIXMAP_X11_ERROR_X11,
306                    "Unable to query pixmap size");
307       return NULL;
308     }
309
310   /* We need a visual to use for shared memory images so we'll query
311      it from the pixmap's root window */
312   if (!XGetWindowAttributes (display, pixmap_root_window, &window_attributes))
313     {
314       g_free (tex_pixmap);
315       g_set_error (error,
316                    COGL_TEXTURE_PIXMAP_X11_ERROR,
317                    COGL_TEXTURE_PIXMAP_X11_ERROR_X11,
318                    "Unable to query root window attributes");
319       return NULL;
320     }
321   tex_pixmap->visual = window_attributes.visual;
322
323   /* If automatic updates are requested and the Xlib connection
324      supports damage events then we'll register a damage object on the
325      pixmap */
326   damage_base = _cogl_xlib_get_damage_base ();
327   if (automatic_updates && damage_base >= 0)
328     {
329       Damage damage = XDamageCreate (display,
330                                      pixmap,
331                                      XDamageReportBoundingBox);
332       set_damage_object_internal (ctxt,
333                                   tex_pixmap,
334                                   damage,
335                                   COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX);
336       tex_pixmap->damage_owned = TRUE;
337     }
338
339   /* Assume the entire pixmap is damaged to begin with */
340   tex_pixmap->damage_rect.x1 = 0;
341   tex_pixmap->damage_rect.x2 = tex_pixmap->width;
342   tex_pixmap->damage_rect.y1 = 0;
343   tex_pixmap->damage_rect.y2 = tex_pixmap->height;
344
345   winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
346   if (winsys->texture_pixmap_x11_create)
347     {
348       tex_pixmap->use_winsys_texture =
349         winsys->texture_pixmap_x11_create (tex_pixmap);
350     }
351   else
352     tex_pixmap->use_winsys_texture = FALSE;
353
354   if (!tex_pixmap->use_winsys_texture)
355     tex_pixmap->winsys = NULL;
356
357   return _cogl_texture_pixmap_x11_handle_new (tex_pixmap);
358 }
359
360 /* Tries to allocate enough shared mem to handle a full size
361  * update size of the X Pixmap. */
362 static void
363 try_alloc_shm (CoglTexturePixmapX11 *tex_pixmap)
364 {
365   XImage *dummy_image;
366   Display *display;
367
368   display = cogl_xlib_get_display ();
369
370   if (!XShmQueryExtension (display))
371     return;
372
373   /* We are creating a dummy_image so we can have Xlib calculate
374    * image->bytes_per_line - including any magic padding it may
375    * want - for the largest possible ximage we might need to use
376    * when handling updates to the texture.
377    *
378    * Note: we pass a NULL shminfo here, but that has no bearing
379    * on the setup of the XImage, except that ximage->obdata will
380    * == NULL.
381    */
382   dummy_image =
383     XShmCreateImage (display,
384                      tex_pixmap->visual,
385                      tex_pixmap->depth,
386                      ZPixmap,
387                      NULL,
388                      NULL, /* shminfo, */
389                      tex_pixmap->width,
390                      tex_pixmap->height);
391   if (!dummy_image)
392     goto failed_image_create;
393
394   tex_pixmap->shm_info.shmid = shmget (IPC_PRIVATE,
395                                        dummy_image->bytes_per_line
396                                        * dummy_image->height,
397                                        IPC_CREAT | 0777);
398   if (tex_pixmap->shm_info.shmid == -1)
399     goto failed_shmget;
400
401   tex_pixmap->shm_info.shmaddr = shmat (tex_pixmap->shm_info.shmid, 0, 0);
402   if (tex_pixmap->shm_info.shmaddr == (void *) -1)
403     goto failed_shmat;
404
405   tex_pixmap->shm_info.readOnly = False;
406
407   if (XShmAttach (display, &tex_pixmap->shm_info) == 0)
408     goto failed_xshmattach;
409
410   XDestroyImage (dummy_image);
411
412   return;
413
414  failed_xshmattach:
415   g_warning ("XShmAttach failed");
416   shmdt (tex_pixmap->shm_info.shmaddr);
417
418  failed_shmat:
419   g_warning ("shmat failed");
420   shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
421
422  failed_shmget:
423   g_warning ("shmget failed");
424   XDestroyImage (dummy_image);
425
426  failed_image_create:
427   tex_pixmap->shm_info.shmid = -1;
428 }
429
430 void
431 cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *tex_pixmap,
432                                      int x,
433                                      int y,
434                                      int width,
435                                      int height)
436 {
437   /* We'll queue the update for both the GLX texture and the regular
438      texture because we can't determine which will be needed until we
439      actually render something */
440
441   if (tex_pixmap->winsys)
442     {
443       const CoglWinsysVtable *winsys;
444       winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
445       winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
446     }
447
448   cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
449                                x, y, width, height);
450 }
451
452 gboolean
453 cogl_texture_pixmap_x11_is_using_tfp_extension (CoglTexturePixmapX11 *tex_pixmap)
454 {
455   return !!tex_pixmap->winsys;
456 }
457
458 void
459 cogl_texture_pixmap_x11_set_damage_object (CoglTexturePixmapX11 *tex_pixmap,
460                                            guint32 damage,
461                                            CoglTexturePixmapX11ReportLevel
462                                                                   report_level)
463 {
464   int damage_base;
465
466   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
467
468   damage_base = _cogl_xlib_get_damage_base ();
469   if (damage_base >= 0)
470     set_damage_object_internal (ctxt, tex_pixmap, damage, report_level);
471 }
472
473 static void
474 _cogl_texture_pixmap_x11_update_image_texture (CoglTexturePixmapX11 *tex_pixmap)
475 {
476   Display *display;
477   Visual *visual;
478   CoglPixelFormat image_format;
479   XImage *image;
480   int src_x, src_y;
481   int x, y, width, height;
482
483   display = cogl_xlib_get_display ();
484   visual = tex_pixmap->visual;
485
486   /* If the damage region is empty then there's nothing to do */
487   if (tex_pixmap->damage_rect.x2 == tex_pixmap->damage_rect.x1)
488     return;
489
490   x = tex_pixmap->damage_rect.x1;
491   y = tex_pixmap->damage_rect.y1;
492   width = tex_pixmap->damage_rect.x2 - x;
493   height = tex_pixmap->damage_rect.y2 - y;
494
495   /* We lazily create the texture the first time it is needed in case
496      this texture can be entirely handled using the GLX texture
497      instead */
498   if (tex_pixmap->tex == COGL_INVALID_HANDLE)
499     {
500       CoglPixelFormat texture_format;
501
502       texture_format = (tex_pixmap->depth >= 32
503                         ? COGL_PIXEL_FORMAT_RGBA_8888_PRE
504                         : COGL_PIXEL_FORMAT_RGB_888);
505
506       tex_pixmap->tex = cogl_texture_new_with_size (tex_pixmap->width,
507                                                     tex_pixmap->height,
508                                                     COGL_TEXTURE_NONE,
509                                                     texture_format);
510     }
511
512   if (tex_pixmap->image == NULL)
513     {
514       /* If we also haven't got a shm segment then this must be the
515          first time we've tried to update, so lets try allocating shm
516          first */
517       if (tex_pixmap->shm_info.shmid == -1)
518         try_alloc_shm (tex_pixmap);
519
520       if (tex_pixmap->shm_info.shmid == -1)
521         {
522           COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetImage", tex_pixmap);
523
524           /* We'll fallback to using a regular XImage. We'll download
525              the entire area instead of a sub region because presumably
526              if this is the first update then the entire pixmap is
527              needed anyway and it saves trying to manually allocate an
528              XImage at the right size */
529           tex_pixmap->image = XGetImage (display,
530                                          tex_pixmap->pixmap,
531                                          0, 0,
532                                          tex_pixmap->width, tex_pixmap->height,
533                                          AllPlanes, ZPixmap);
534           image = tex_pixmap->image;
535           src_x = x;
536           src_y = y;
537         }
538       else
539         {
540           COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XShmGetImage",
541                      tex_pixmap);
542
543           /* Create a temporary image using the beginning of the
544              shared memory segment and the right size for the region
545              we want to update. We need to reallocate the XImage every
546              time because there is no XShmGetSubImage. */
547           image = XShmCreateImage (display,
548                                    tex_pixmap->visual,
549                                    tex_pixmap->depth,
550                                    ZPixmap,
551                                    NULL,
552                                    &tex_pixmap->shm_info,
553                                    width,
554                                    height);
555           image->data = tex_pixmap->shm_info.shmaddr;
556           src_x = 0;
557           src_y = 0;
558
559           XShmGetImage (display, tex_pixmap->pixmap, image, x, y, AllPlanes);
560         }
561     }
562   else
563     {
564       COGL_NOTE (TEXTURE_PIXMAP, "Updating %p using XGetSubImage", tex_pixmap);
565
566       image = tex_pixmap->image;
567       src_x = x;
568       src_y = y;
569
570       XGetSubImage (display,
571                     tex_pixmap->pixmap,
572                     x, y, width, height,
573                     AllPlanes, ZPixmap,
574                     image,
575                     x, y);
576     }
577
578   image_format =
579     _cogl_util_pixel_format_from_masks (visual->red_mask,
580                                         visual->green_mask,
581                                         visual->blue_mask,
582                                         image->depth,
583                                         image->bits_per_pixel,
584                                         image->byte_order == LSBFirst);
585
586   cogl_texture_set_region (tex_pixmap->tex,
587                            src_x, src_y,
588                            x, y, width, height,
589                            image->width,
590                            image->height,
591                            image_format,
592                            image->bytes_per_line,
593                            (const guint8 *) image->data);
594
595   /* If we have a shared memory segment then the XImage would be a
596      temporary one with no data allocated so we can just XFree it */
597   if (tex_pixmap->shm_info.shmid != -1)
598     XFree (image);
599
600   memset (&tex_pixmap->damage_rect, 0, sizeof (CoglDamageRectangle));
601 }
602
603 static void
604 _cogl_texture_pixmap_x11_set_use_winsys_texture (CoglTexturePixmapX11 *tex_pixmap,
605                                                  gboolean new_value)
606 {
607   if (tex_pixmap->use_winsys_texture != new_value)
608     {
609       /* Notify cogl-pipeline.c that the texture's underlying GL texture
610        * storage is changing so it knows it may need to bind a new texture
611        * if the CoglTexture is reused with the same texture unit. */
612       _cogl_pipeline_texture_storage_change_notify (COGL_TEXTURE (tex_pixmap));
613
614       tex_pixmap->use_winsys_texture = new_value;
615     }
616 }
617
618 static void
619 _cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
620                                  gboolean needs_mipmap)
621 {
622   if (tex_pixmap->winsys)
623     {
624       const CoglWinsysVtable *winsys =
625         _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
626
627       if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
628         {
629           _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
630           return;
631         }
632     }
633
634   /* If it didn't work then fallback to using XGetImage. This may be
635      temporary */
636   _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, FALSE);
637
638   _cogl_texture_pixmap_x11_update_image_texture (tex_pixmap);
639 }
640
641 static CoglHandle
642 _cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
643 {
644   CoglHandle tex;
645   int i;
646
647   /* We try getting the texture twice, once without flushing the
648      updates and once with. If pre_paint has been called already then
649      we should have a good idea of which texture to use so we don't
650      want to mess with that by ensuring the updates. However, if we
651      couldn't find a texture then we'll just make a best guess by
652      flushing without expecting mipmap support and try again. This
653      would happen for example if an application calls
654      get_gl_texture before the first paint */
655
656   for (i = 0; i < 2; i++)
657     {
658       if (tex_pixmap->use_winsys_texture)
659         {
660           const CoglWinsysVtable *winsys =
661             _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
662           tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap);
663         }
664       else
665         tex = tex_pixmap->tex;
666
667       if (tex)
668         return tex;
669
670       _cogl_texture_pixmap_x11_update (tex_pixmap, FALSE);
671     }
672
673   g_assert_not_reached ();
674
675   return COGL_INVALID_HANDLE;
676 }
677
678 static gboolean
679 _cogl_texture_pixmap_x11_set_region (CoglTexture     *tex,
680                                      int              src_x,
681                                      int              src_y,
682                                      int              dst_x,
683                                      int              dst_y,
684                                      unsigned int     dst_width,
685                                      unsigned int     dst_height,
686                                      CoglBitmap      *bmp)
687 {
688   /* This doesn't make much sense for texture from pixmap so it's not
689      supported */
690   return FALSE;
691 }
692
693 static gboolean
694 _cogl_texture_pixmap_x11_get_data (CoglTexture     *tex,
695                                    CoglPixelFormat  format,
696                                    unsigned int     rowstride,
697                                    guint8          *data)
698 {
699   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
700   CoglHandle child_tex;
701
702   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
703
704   /* Forward on to the child texture */
705   return cogl_texture_get_data (child_tex, format, rowstride, data);
706 }
707
708 typedef struct _NormalizeCoordsWrapperData
709 {
710   int width;
711   int height;
712   CoglMetaTextureCallback callback;
713   void *user_data;
714 } NormalizeCoordsWrapperData;
715
716 static void
717 normalize_coords_wrapper_cb (CoglTexture *child_texture,
718                              const float *child_texture_coords,
719                              const float *meta_coords,
720                              void *user_data)
721 {
722   NormalizeCoordsWrapperData *data = user_data;
723   float normalized_coords[4];
724
725   normalized_coords[0] = meta_coords[0] / data->width;
726   normalized_coords[1] = meta_coords[1] / data->height;
727   normalized_coords[2] = meta_coords[2] / data->width;
728   normalized_coords[3] = meta_coords[3] / data->height;
729
730   data->callback (child_texture,
731                   child_texture_coords, normalized_coords,
732                   data->user_data);
733 }
734
735 static void
736 _cogl_texture_pixmap_x11_foreach_sub_texture_in_region
737                                   (CoglTexture              *tex,
738                                    float                     virtual_tx_1,
739                                    float                     virtual_ty_1,
740                                    float                     virtual_tx_2,
741                                    float                     virtual_ty_2,
742                                    CoglMetaTextureCallback   callback,
743                                    void                     *user_data)
744 {
745   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
746   CoglHandle child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
747
748   /* Forward on to the child texture */
749
750   /* tfp textures may be implemented in terms of a
751    * CoglTextureRectangle texture which uses un-normalized texture
752    * coordinates but we want to consistently deal with normalized
753    * texture coordinates with CoglTexturePixmapX11... */
754   if (cogl_is_texture_rectangle (child_tex))
755     {
756       NormalizeCoordsWrapperData data;
757       int width = tex_pixmap->width;
758       int height = tex_pixmap->height;
759
760       virtual_tx_1 *= width;
761       virtual_ty_1 *= height;
762       virtual_tx_2 *= width;
763       virtual_ty_2 *= height;
764
765       data.width = width;
766       data.height = height;
767       data.callback = callback;
768       data.user_data = user_data;
769
770       cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex),
771                                            virtual_tx_1,
772                                            virtual_ty_1,
773                                            virtual_tx_2,
774                                            virtual_ty_2,
775                                            COGL_PIPELINE_WRAP_MODE_REPEAT,
776                                            COGL_PIPELINE_WRAP_MODE_REPEAT,
777                                            normalize_coords_wrapper_cb,
778                                            &data);
779     }
780   else
781     cogl_meta_texture_foreach_in_region (COGL_META_TEXTURE (child_tex),
782                                          virtual_tx_1,
783                                          virtual_ty_1,
784                                          virtual_tx_2,
785                                          virtual_ty_2,
786                                          COGL_PIPELINE_WRAP_MODE_REPEAT,
787                                          COGL_PIPELINE_WRAP_MODE_REPEAT,
788                                          callback,
789                                          user_data);
790 }
791
792 static int
793 _cogl_texture_pixmap_x11_get_max_waste (CoglTexture *tex)
794 {
795   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
796   CoglHandle child_tex;
797
798   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
799
800   return cogl_texture_get_max_waste (child_tex);
801 }
802
803 static gboolean
804 _cogl_texture_pixmap_x11_is_sliced (CoglTexture *tex)
805 {
806   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
807   CoglHandle child_tex;
808
809   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
810
811   return cogl_texture_is_sliced (child_tex);
812 }
813
814 static gboolean
815 _cogl_texture_pixmap_x11_can_hardware_repeat (CoglTexture *tex)
816 {
817   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
818   CoglHandle child_tex;
819
820   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
821
822   return _cogl_texture_can_hardware_repeat (child_tex);
823 }
824
825 static void
826 _cogl_texture_pixmap_x11_transform_coords_to_gl (CoglTexture *tex,
827                                                  float       *s,
828                                                  float       *t)
829 {
830   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
831   CoglHandle child_tex;
832
833   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
834
835   /* Forward on to the child texture */
836   _cogl_texture_transform_coords_to_gl (child_tex, s, t);
837 }
838
839 static CoglTransformResult
840 _cogl_texture_pixmap_x11_transform_quad_coords_to_gl (CoglTexture *tex,
841                                                       float       *coords)
842 {
843   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
844   CoglHandle child_tex;
845
846   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
847
848   /* Forward on to the child texture */
849   return _cogl_texture_transform_quad_coords_to_gl (child_tex, coords);
850 }
851
852 static gboolean
853 _cogl_texture_pixmap_x11_get_gl_texture (CoglTexture *tex,
854                                          GLuint      *out_gl_handle,
855                                          GLenum      *out_gl_target)
856 {
857   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
858   CoglHandle child_tex;
859
860   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
861
862   /* Forward on to the child texture */
863   return cogl_texture_get_gl_texture (child_tex,
864                                       out_gl_handle,
865                                       out_gl_target);
866 }
867
868 static void
869 _cogl_texture_pixmap_x11_set_filters (CoglTexture *tex,
870                                       GLenum       min_filter,
871                                       GLenum       mag_filter)
872 {
873   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
874   CoglHandle child_tex;
875
876   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
877
878   /* Forward on to the child texture */
879   _cogl_texture_set_filters (child_tex, min_filter, mag_filter);
880 }
881
882 static void
883 _cogl_texture_pixmap_x11_pre_paint (CoglTexture *tex,
884                                     CoglTexturePrePaintFlags flags)
885 {
886   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
887   CoglHandle child_tex;
888
889   _cogl_texture_pixmap_x11_update (tex_pixmap,
890                                    !!(flags & COGL_TEXTURE_NEEDS_MIPMAP));
891
892   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
893
894   _cogl_texture_pre_paint (child_tex, flags);
895 }
896
897 static void
898 _cogl_texture_pixmap_x11_ensure_non_quad_rendering (CoglTexture *tex)
899 {
900   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
901   CoglHandle child_tex;
902
903   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
904
905   /* Forward on to the child texture */
906   _cogl_texture_ensure_non_quad_rendering (child_tex);
907 }
908
909 static void
910 _cogl_texture_pixmap_x11_set_wrap_mode_parameters (CoglTexture *tex,
911                                                    GLenum       wrap_mode_s,
912                                                    GLenum       wrap_mode_t,
913                                                    GLenum       wrap_mode_p)
914 {
915   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
916   CoglHandle child_tex;
917
918   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
919
920   /* Forward on to the child texture */
921   _cogl_texture_set_wrap_mode_parameters (child_tex,
922                                           wrap_mode_s,
923                                           wrap_mode_t,
924                                           wrap_mode_p);
925 }
926
927 static CoglPixelFormat
928 _cogl_texture_pixmap_x11_get_format (CoglTexture *tex)
929 {
930   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
931   CoglHandle child_tex;
932
933   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
934
935   /* Forward on to the child texture */
936   return cogl_texture_get_format (child_tex);
937 }
938
939 static GLenum
940 _cogl_texture_pixmap_x11_get_gl_format (CoglTexture *tex)
941 {
942   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
943   CoglHandle child_tex;
944
945   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
946
947   return _cogl_texture_get_gl_format (child_tex);
948 }
949
950 static int
951 _cogl_texture_pixmap_x11_get_width (CoglTexture *tex)
952 {
953   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
954
955   return tex_pixmap->width;
956 }
957
958 static int
959 _cogl_texture_pixmap_x11_get_height (CoglTexture *tex)
960 {
961   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
962
963   return tex_pixmap->height;
964 }
965
966 static CoglTextureType
967 _cogl_texture_pixmap_x11_get_type (CoglTexture *tex)
968 {
969   CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (tex);
970   CoglTexture *child_tex;
971
972   child_tex = _cogl_texture_pixmap_x11_get_texture (tex_pixmap);
973
974   /* Forward on to the child texture */
975   return _cogl_texture_get_type (child_tex);
976 }
977
978 static void
979 _cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
980 {
981   _COGL_GET_CONTEXT (ctxt, NO_RETVAL);
982
983   set_damage_object_internal (ctxt, tex_pixmap, 0, 0);
984
985   if (tex_pixmap->image)
986     XDestroyImage (tex_pixmap->image);
987
988   if (tex_pixmap->shm_info.shmid != -1)
989     {
990       XShmDetach (cogl_xlib_get_display (), &tex_pixmap->shm_info);
991       shmdt (tex_pixmap->shm_info.shmaddr);
992       shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
993     }
994
995   if (tex_pixmap->tex)
996     cogl_handle_unref (tex_pixmap->tex);
997
998   if (tex_pixmap->winsys)
999     {
1000       const CoglWinsysVtable *winsys =
1001         _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
1002       winsys->texture_pixmap_x11_free (tex_pixmap);
1003     }
1004
1005   /* Chain up */
1006   _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
1007 }
1008
1009 static const CoglTextureVtable
1010 cogl_texture_pixmap_x11_vtable =
1011   {
1012     _cogl_texture_pixmap_x11_set_region,
1013     _cogl_texture_pixmap_x11_get_data,
1014     _cogl_texture_pixmap_x11_foreach_sub_texture_in_region,
1015     _cogl_texture_pixmap_x11_get_max_waste,
1016     _cogl_texture_pixmap_x11_is_sliced,
1017     _cogl_texture_pixmap_x11_can_hardware_repeat,
1018     _cogl_texture_pixmap_x11_transform_coords_to_gl,
1019     _cogl_texture_pixmap_x11_transform_quad_coords_to_gl,
1020     _cogl_texture_pixmap_x11_get_gl_texture,
1021     _cogl_texture_pixmap_x11_set_filters,
1022     _cogl_texture_pixmap_x11_pre_paint,
1023     _cogl_texture_pixmap_x11_ensure_non_quad_rendering,
1024     _cogl_texture_pixmap_x11_set_wrap_mode_parameters,
1025     _cogl_texture_pixmap_x11_get_format,
1026     _cogl_texture_pixmap_x11_get_gl_format,
1027     _cogl_texture_pixmap_x11_get_width,
1028     _cogl_texture_pixmap_x11_get_height,
1029     _cogl_texture_pixmap_x11_get_type,
1030     NULL /* is_foreign */
1031   };