~ubuntu-branches/ubuntu/precise/clutter-1.0/precise

« back to all changes in this revision

Viewing changes to clutter/glx/clutter-glx-texture-pixmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental) (1.3.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 8.
  • Revision ID: james.westby@ubuntu.com-20100321132756-nf8yd30yxo3zzwcm
Tags: upstream-1.2.2
ImportĀ upstreamĀ versionĀ 1.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 * Lesser General Public License for more details.
21
21
 *
22
22
 * You should have received a copy of the GNU Lesser General Public
23
 
 * License along with this library; if not, write to the
24
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
25
 
 * Boston, MA 02111-1307, USA.
 
23
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 
24
 *
 
25
 *
26
26
 */
27
27
 
28
28
/*  TODO:
64
64
 
65
65
#include "../clutter-util.h"
66
66
#include "../clutter-debug.h"
 
67
#include "../clutter-private.h"
67
68
 
68
69
#include "cogl/cogl.h"
69
70
 
84
85
  CLUTTER_GLX_RECTANGLE_FORCE
85
86
} RectangleState;
86
87
 
 
88
enum
 
89
{
 
90
  PROP_0,
 
91
  PROP_AUTO_REDRAW,
 
92
};
 
93
 
87
94
static BindTexImage      _gl_bind_tex_image = NULL;
88
95
static ReleaseTexImage   _gl_release_tex_image = NULL;
89
96
static GenerateMipmap    _gl_generate_mipmap = NULL;
100
107
 
101
108
  gboolean      bound;
102
109
  gint          can_mipmap;
103
 
  gint          mipmap_generate_queued;
 
110
  gboolean      mipmap_generate_queued;
 
111
 
 
112
  gboolean      bind_tex_image_queued;
104
113
 
105
114
  gboolean      using_rectangle;
106
115
};
121
130
               clutter_glx_texture_pixmap, \
122
131
               CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
123
132
 
124
 
static gboolean
125
 
texture_bind (ClutterGLXTexturePixmap *tex)
 
133
static void
 
134
bind_texture (ClutterGLXTexturePixmap *tex)
126
135
{
127
 
  GLuint     handle = 0;
128
 
  GLenum     target = 0;
129
 
  CoglHandle cogl_tex;
130
 
  cogl_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE(tex));
 
136
  GLuint handle = 0;
 
137
  GLenum target = 0;
 
138
  CoglHandle cogl_tex =
 
139
    clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (tex));
131
140
 
132
141
  if (!cogl_texture_get_gl_texture (cogl_tex, &handle, &target))
133
 
      return FALSE;
 
142
    g_warning ("Failed to pluck out GL handle from cogl texture to bind");
134
143
 
135
 
  /* FIXME: fire off an error here? */
136
144
  glBindTexture (target, handle);
137
 
 
138
 
  return TRUE;
 
145
}
 
146
 
 
147
static void
 
148
release_tex_image (ClutterGLXTexturePixmap *texture)
 
149
{
 
150
  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
 
151
  Display *dpy;
 
152
 
 
153
  if (!priv->glx_pixmap || !priv->bound)
 
154
    return;
 
155
 
 
156
  dpy = clutter_x11_get_default_display ();
 
157
 
 
158
  bind_texture (texture);
 
159
 
 
160
  clutter_x11_trap_x_errors ();
 
161
 
 
162
  (_gl_release_tex_image) (dpy,
 
163
                           priv->glx_pixmap,
 
164
                           GLX_FRONT_LEFT_EXT);
 
165
 
 
166
  XSync (dpy, FALSE);
 
167
 
 
168
  if (clutter_x11_untrap_x_errors ())
 
169
    CLUTTER_NOTE (TEXTURE, "Failed to release?");
 
170
 
 
171
  CLUTTER_NOTE (TEXTURE, "Destroyed pxm: %li", priv->glx_pixmap);
 
172
 
 
173
  priv->bound = FALSE;
139
174
}
140
175
 
141
176
static void
142
177
on_glx_texture_pixmap_pre_paint (ClutterGLXTexturePixmap *texture,
143
178
                                 gpointer                 user_data)
144
179
{
145
 
  if (texture->priv->mipmap_generate_queued)
 
180
  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
 
181
  gboolean tex_bound = FALSE;
 
182
  Display *dpy = clutter_x11_get_default_display();
 
183
 
 
184
  if (priv->bind_tex_image_queued)
 
185
    {
 
186
      CLUTTER_NOTE (TEXTURE, "Really updating via GLX");
 
187
 
 
188
      bind_texture (CLUTTER_GLX_TEXTURE_PIXMAP (texture));
 
189
      tex_bound = TRUE;
 
190
 
 
191
      clutter_x11_trap_x_errors ();
 
192
 
 
193
      (_gl_bind_tex_image) (dpy,
 
194
                            priv->glx_pixmap,
 
195
                            GLX_FRONT_LEFT_EXT,
 
196
                            NULL);
 
197
 
 
198
      XSync (dpy, FALSE);
 
199
 
 
200
      /* Note above fires X error for non name pixmaps - but
 
201
       * things still seem to work - i.e pixmap updated
 
202
       */
 
203
      if (clutter_x11_untrap_x_errors ())
 
204
        CLUTTER_NOTE (TEXTURE, "Update bind_tex_image failed");
 
205
 
 
206
      priv->bound = TRUE;
 
207
 
 
208
      if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
 
209
          == CLUTTER_TEXTURE_QUALITY_HIGH)
 
210
        {
 
211
          priv->mipmap_generate_queued++;
 
212
        }
 
213
 
 
214
      priv->bind_tex_image_queued = FALSE;
 
215
    }
 
216
 
 
217
  if (_gl_generate_mipmap &&
 
218
      priv->can_mipmap &&
 
219
      priv->mipmap_generate_queued)
146
220
    {
147
221
      GLuint     handle = 0;
148
222
      GLenum     target = 0;
150
224
      cogl_tex = clutter_texture_get_cogl_texture
151
225
        (CLUTTER_TEXTURE(texture));
152
226
 
153
 
      texture_bind (texture);
 
227
      bind_texture (texture);
 
228
      tex_bound = TRUE;
154
229
 
155
230
      cogl_texture_get_gl_texture (cogl_tex, &handle, &target);
156
231
 
157
232
      _gl_generate_mipmap (target);
158
 
 
159
 
      texture->priv->mipmap_generate_queued = 0;
160
233
    }
 
234
  priv->mipmap_generate_queued = FALSE;
161
235
 
162
236
  /* Disable mipmaps if we can't support them */
163
237
  if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
164
238
      == CLUTTER_TEXTURE_QUALITY_HIGH
165
 
      && !texture->priv->can_mipmap)
 
239
      && !priv->can_mipmap)
166
240
    {
167
241
      CoglHandle material
168
242
        = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture));
198
272
                                  clutter_x11_get_default_screen ());
199
273
 
200
274
      /* Check for the texture from pixmap extension */
201
 
      if (cogl_check_extension ("GLX_EXT_texture_from_pixmap", glx_extensions))
 
275
      if (_cogl_check_extension ("GLX_EXT_texture_from_pixmap",
 
276
                                 glx_extensions))
202
277
        {
203
278
          _gl_bind_tex_image =
204
279
            (BindTexImage)cogl_get_proc_address ("glXBindTexImageEXT");
213
288
        (GenerateMipmap)cogl_get_proc_address ("glGenerateMipmapEXT");
214
289
 
215
290
      gl_extensions = (char *) glGetString (GL_EXTENSIONS);
216
 
      _have_tex_rectangle = cogl_check_extension ("GL_ARB_texture_rectangle",
 
291
      _have_tex_rectangle = _cogl_check_extension ("GL_ARB_texture_rectangle",
217
292
                                                  gl_extensions);
218
293
 
219
294
      if ((rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
250
325
 
251
326
          cogl_texture_get_gl_texture (cogl_tex, &gl_handle, &gl_target);
252
327
 
253
 
          if (gl_target == CGL_TEXTURE_RECTANGLE_ARB)
 
328
          if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
254
329
            glDeleteTextures (1, &gl_handle);
255
330
        }
256
331
 
351
426
      using_rectangle = TRUE;
352
427
 
353
428
      glGenTextures (1, &tex);
354
 
      glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
355
 
      glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
 
429
      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
 
430
      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
356
431
                    gl_format, width, height,
357
432
                    0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
358
433
 
359
 
      handle = cogl_texture_new_from_foreign (tex, CGL_TEXTURE_RECTANGLE_ARB,
 
434
      handle = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
360
435
                                              width, height,
361
436
                                              0, 0,
362
437
                                              cogl_format | COGL_BGR_BIT |
379
454
      priv->using_rectangle = using_rectangle;
380
455
 
381
456
      clutter_texture_set_cogl_texture (texture, handle);
382
 
      cogl_texture_unref(handle);
 
457
      cogl_handle_unref(handle);
383
458
 
384
459
      return TRUE;
385
460
    }
411
486
static void
412
487
clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
413
488
{
414
 
  ClutterGLXTexturePixmap        *texture = CLUTTER_GLX_TEXTURE_PIXMAP (actor);
415
 
  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
416
 
  Display                        *dpy;
 
489
  ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (actor);
 
490
  Display                 *dpy;
417
491
 
418
492
  dpy = clutter_x11_get_default_display();
419
493
 
429
503
  if (!CLUTTER_ACTOR_IS_REALIZED (actor))
430
504
    return;
431
505
 
432
 
  if (priv->glx_pixmap && priv->bound)
433
 
    {
434
 
      clutter_x11_trap_x_errors ();
435
 
 
436
 
      (_gl_release_tex_image) (dpy,
437
 
                               priv->glx_pixmap,
438
 
                               GLX_FRONT_LEFT_EXT);
439
 
 
440
 
      XSync (clutter_x11_get_default_display(), FALSE);
441
 
      clutter_x11_untrap_x_errors ();
442
 
 
443
 
      priv->bound = FALSE;
444
 
    }
 
506
  release_tex_image (texture);
445
507
 
446
508
  CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
447
509
}
587
649
 
588
650
  dpy = clutter_x11_get_default_display ();
589
651
 
590
 
  if (priv->glx_pixmap &&
591
 
      priv->bound)
592
 
    {
593
 
      texture_bind (texture);
594
 
 
595
 
      clutter_x11_trap_x_errors ();
596
 
 
597
 
      (_gl_release_tex_image) (dpy,
598
 
                               priv->glx_pixmap,
599
 
                               GLX_FRONT_LEFT_EXT);
600
 
 
601
 
      XSync (clutter_x11_get_default_display(), FALSE);
602
 
 
603
 
      if (clutter_x11_untrap_x_errors ())
604
 
        CLUTTER_NOTE (TEXTURE, "Failed to release?");
605
 
 
606
 
      CLUTTER_NOTE (TEXTURE, "Destroyed pxm: %li", priv->glx_pixmap);
607
 
 
608
 
      priv->bound = FALSE;
609
 
    }
 
652
  release_tex_image (texture);
610
653
 
611
654
  clutter_x11_trap_x_errors ();
612
655
  if (priv->glx_pixmap)
721
764
      goto cleanup;
722
765
    }
723
766
 
724
 
 cleanup:
 
767
cleanup:
725
768
 
726
769
  if (priv->glx_pixmap)
727
770
    clutter_glx_texture_pixmap_free_glx_pixmap (texture);
738
781
                                              pixmap_width, pixmap_height);
739
782
 
740
783
      /* Get ready to queue initial mipmap generation */
741
 
      if (_gl_generate_mipmap
742
 
          && priv->can_mipmap
743
 
          &&  clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
 
784
      if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
744
785
          == CLUTTER_TEXTURE_QUALITY_HIGH)
745
786
        {
746
 
          priv->mipmap_generate_queued++;
 
787
          priv->mipmap_generate_queued = TRUE;
747
788
        }
748
789
 
749
790
      return;
766
807
                                        gint                     height)
767
808
{
768
809
  ClutterGLXTexturePixmap *texture_glx = CLUTTER_GLX_TEXTURE_PIXMAP (texture);
769
 
  ClutterGLXTexturePixmapPrivate       *priv = texture_glx->priv;
770
 
  Display                              *dpy;
 
810
  ClutterGLXTexturePixmapPrivate  *priv = texture_glx->priv;
771
811
 
772
812
  CLUTTER_NOTE (TEXTURE, "Updating texture pixmap");
773
813
 
774
 
  dpy = clutter_x11_get_default_display();
775
 
 
776
814
  if (!CLUTTER_ACTOR_IS_REALIZED (texture))
777
815
    return;
778
816
 
791
829
  if (priv->glx_pixmap == None)
792
830
    return;
793
831
 
794
 
  if (texture_bind (CLUTTER_GLX_TEXTURE_PIXMAP(texture)))
795
 
    {
796
 
      CLUTTER_NOTE (TEXTURE, "Really updating via GLX");
797
 
 
798
 
      clutter_x11_trap_x_errors ();
799
 
 
800
 
      (_gl_bind_tex_image) (dpy,
801
 
                            priv->glx_pixmap,
802
 
                            GLX_FRONT_LEFT_EXT,
803
 
                            NULL);
804
 
 
805
 
      XSync (clutter_x11_get_default_display(), FALSE);
806
 
 
807
 
      /* Note above fires X error for non name pixmaps - but
808
 
       * things still seem to work - i.e pixmap updated
809
 
       */
810
 
      if (clutter_x11_untrap_x_errors ())
811
 
        CLUTTER_NOTE (TEXTURE, "Update bind_tex_image failed");
812
 
 
813
 
      priv->bound = TRUE;
814
 
 
815
 
      if (_gl_generate_mipmap
816
 
          && priv->can_mipmap
817
 
          &&  clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
818
 
              == CLUTTER_TEXTURE_QUALITY_HIGH)
819
 
        {
820
 
          /* FIXME: It may make more sense to set a flag here and only
821
 
           *        generate the mipmap on a pre paint.. compressing need
822
 
           *        to call generate mipmap
823
 
           *        May break clones however..
824
 
          */
825
 
          priv->mipmap_generate_queued++;
826
 
        }
827
 
 
828
 
    }
829
 
  else
830
 
    g_warning ("Failed to bind initial tex");
831
 
 
832
 
  clutter_actor_queue_redraw (CLUTTER_ACTOR(texture));
 
832
  priv->bind_tex_image_queued = TRUE;
833
833
}
834
834
 
835
835
static void
851
851
  actor_class->unrealize = clutter_glx_texture_pixmap_unrealize;
852
852
 
853
853
  x11_texture_class->update_area = clutter_glx_texture_pixmap_update_area;
854
 
 
855
854
}
856
855
 
857
856
/**
858
857
 * clutter_glx_texture_pixmap_using_extension:
859
858
 * @texture: A #ClutterGLXTexturePixmap
860
859
 *
861
 
 * Return value: A boolean indicating if the texture is using the
862
 
 * GLX_EXT_texture_from_pixmap OpenGL extension or falling back to
863
 
 * slower software mechanism.
 
860
 * Checks whether @texture is using the GLX_EXT_texture_from_pixmap
 
861
 * extension; this extension can be optionally (though it is strongly
 
862
 * encouraged) implemented as a zero-copy between a GLX pixmap and
 
863
 * a GL texture.
 
864
 *
 
865
 * Return value: %TRUE if the texture is using the
 
866
 *   GLX_EXT_texture_from_pixmap OpenGL extension or falling back to the
 
867
 *   slower software mechanism.
864
868
 *
865
869
 * Since: 0.8
866
 
 **/
 
870
 */
867
871
gboolean
868
872
clutter_glx_texture_pixmap_using_extension (ClutterGLXTexturePixmap *texture)
869
873
{
882
886
 * clutter_glx_texture_pixmap_new_with_pixmap:
883
887
 * @pixmap: the X Pixmap to which this texture should be bound
884
888
 *
 
889
 * Creates a new #ClutterGLXTexturePixmap for @pixmap
 
890
 *
885
891
 * Return value: A new #ClutterGLXTexturePixmap bound to the given X Pixmap
886
892
 *
887
893
 * Since: 0.8
888
 
 **/
889
 
ClutterActor*
 
894
 */
 
895
ClutterActor *
890
896
clutter_glx_texture_pixmap_new_with_pixmap (Pixmap pixmap)
891
897
{
892
 
  ClutterActor *actor;
893
 
 
894
 
  actor = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
895
 
                        "pixmap", pixmap,
896
 
                        NULL);
897
 
 
898
 
  return actor;
 
898
  return g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
 
899
                       "pixmap", pixmap,
 
900
                       NULL);
899
901
}
900
902
 
901
903
/**
902
904
 * clutter_glx_texture_pixmap_new_with_window:
903
905
 * @window: the X window to which this texture should be bound
904
906
 *
 
907
 * Creates a new #ClutterGLXTexturePixmap for @window
 
908
 *
905
909
 * Return value: A new #ClutterGLXTexturePixmap bound to the given X window
906
910
 *
907
911
 * Since: 0.8
908
912
 **/
909
 
ClutterActor*
 
913
ClutterActor *
910
914
clutter_glx_texture_pixmap_new_with_window (Window window)
911
915
{
912
 
  ClutterActor *actor;
913
 
 
914
 
  actor = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
915
 
                        "window", window,
916
 
                        NULL);
917
 
 
918
 
  return actor;
 
916
  return g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
 
917
                       "window", window,
 
918
                       NULL);
919
919
}
920
920
 
921
921
/**
922
922
 * clutter_glx_texture_pixmap_new:
923
923
 *
 
924
 * Creates a new, empty #ClutterGLXTexturePixmap
 
925
 *
924
926
 * Return value: A new #ClutterGLXTexturePixmap
925
927
 *
926
928
 * Since: 0.8
927
 
 **/
 
929
 */
928
930
ClutterActor *
929
931
clutter_glx_texture_pixmap_new (void)
930
932
{
931
 
  ClutterActor *actor;
932
 
 
933
 
  actor = g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP, NULL);
934
 
 
935
 
  return actor;
 
933
  return g_object_new (CLUTTER_GLX_TYPE_TEXTURE_PIXMAP, NULL);
936
934
}