~darkxst/ubuntu/saucy/gnome-shell/upstart_log

« back to all changes in this revision

Viewing changes to src/shell-screen-grabber.c

  • Committer: Package Import Robot
  • Author(s): Jeremy Bicha
  • Date: 2013-05-31 12:01:12 UTC
  • mfrom: (1.1.49) (19.1.36 experimental)
  • Revision ID: package-import@ubuntu.com-20130531120112-ew91khxf051x9i2r
Tags: 3.8.2-1ubuntu1
* Merge with Debian (LP: #1185869, #1185721). Remaining changes:
  - debian/control.in:
    + Build-depend on libsystemd-login-dev & libsystemd-daemon-dev
    + Depend on gdm instead of gdm3
    + Don't recommend gnome-session-fallback
  - debian/patches/40_change-pam-name-to-match-gdm.patch:
  - debian/patches/revert-suspend-break.patch:
    + Disabled, not needed on Ubuntu
  - debian/patches/ubuntu-lightdm-user-switching.patch:
    + Allow user switching when using LightDM. Thanks Gerhard Stein
      for rebasing against gnome-shell 3.8!
  - debian/patches/ubuntu_lock_on_suspend.patch
    + Respect Ubuntu's lock-on-suspend setting.
      Disabled until it can be rewritten.
  - debian/patches/git_relock_screen_after_crash.patch:
    + Add Upstream fix for unlocked session after crash (LP: #1064584)
* Note that the new GNOME Classic mode (which requires installing
  gnome-shell-extensions) won't work until gnome-session 3.8 is
  available in Ubuntu

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
 
 
3
 
#include "config.h"
4
 
 
5
 
#include <string.h>
6
 
 
7
 
#include <clutter/clutter.h>
8
 
#include <cogl/cogl.h>
9
 
#ifdef HAVE_GLX
10
 
#include <GL/gl.h>
11
 
#include <GL/glx.h>
12
 
#include <GL/glext.h>
13
 
#endif
14
 
 
15
 
#include "shell-screen-grabber.h"
16
 
 
17
 
#ifdef HAVE_GLX
18
 
PFNGLBINDBUFFERARBPROC pf_glBindBufferARB;
19
 
PFNGLBUFFERDATAARBPROC pf_glBufferDataARB;
20
 
PFNGLDELETEBUFFERSARBPROC pf_glDeleteBuffersARB;
21
 
PFNGLGENBUFFERSARBPROC pf_glGenBuffersARB;
22
 
PFNGLMAPBUFFERARBPROC pf_glMapBufferARB;
23
 
PFNGLUNMAPBUFFERARBPROC pf_glUnmapBufferARB;
24
 
#endif
25
 
 
26
 
struct _ShellScreenGrabberClass
27
 
{
28
 
  GObjectClass parent_class;
29
 
};
30
 
 
31
 
struct _ShellScreenGrabber
32
 
{
33
 
  GObject parent_instance;
34
 
 
35
 
  int have_pixel_buffers;
36
 
  int have_pack_invert;
37
 
  int width, height;
38
 
  GLuint pixel_buffer;
39
 
};
40
 
 
41
 
G_DEFINE_TYPE(ShellScreenGrabber, shell_screen_grabber, G_TYPE_OBJECT);
42
 
 
43
 
static void
44
 
shell_screen_grabber_finalize (GObject *gobject)
45
 
{
46
 
  ShellScreenGrabber *grabber = SHELL_SCREEN_GRABBER (gobject);
47
 
 
48
 
#ifdef HAVE_GLX
49
 
  if (grabber->pixel_buffer != 0)
50
 
    pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
51
 
#endif
52
 
}
53
 
 
54
 
static void
55
 
shell_screen_grabber_class_init (ShellScreenGrabberClass *grabber_class)
56
 
{
57
 
  GObjectClass *gobject_class = G_OBJECT_CLASS (grabber_class);
58
 
 
59
 
  gobject_class->finalize = shell_screen_grabber_finalize;
60
 
}
61
 
 
62
 
static void
63
 
shell_screen_grabber_init (ShellScreenGrabber *grabber)
64
 
{
65
 
  grabber->have_pixel_buffers = -1;
66
 
  grabber->width = -1;
67
 
  grabber->height= -1;
68
 
  grabber->pixel_buffer = 0;
69
 
}
70
 
 
71
 
ShellScreenGrabber *
72
 
shell_screen_grabber_new  (void)
73
 
{
74
 
  return g_object_new (SHELL_TYPE_SCREEN_GRABBER, NULL);
75
 
}
76
 
 
77
 
/**
78
 
 * shell_screen_grabber_grab:
79
 
 * x: X coordinate of the rectangle to grab
80
 
 * y: Y coordinate of the rectangle to grab
81
 
 * width: width of the rectangle to grab
82
 
 * height: heigth of the rectangle to grab
83
 
 *
84
 
 * Grabs pixel data from a portion of the screen.
85
 
 *
86
 
 * Return value: buffer holding the grabbed data. The data is stored as 32-bit
87
 
 *  words with native-endian xRGB pixels (i.e., the same as CAIRO_FORMAT_RGB24)
88
 
 *  with no padding on the rows. So, the size of the buffer is width * height * 4
89
 
 *  bytes. Free with g_free().
90
 
 **/
91
 
guchar *
92
 
shell_screen_grabber_grab (ShellScreenGrabber *grabber,
93
 
                           int                 x,
94
 
                           int                 y,
95
 
                           int                 width,
96
 
                           int                 height)
97
 
{
98
 
  guchar *data;
99
 
  gsize row_bytes;
100
 
  gsize data_size;
101
 
 
102
 
  row_bytes = width * 4;
103
 
  data_size = row_bytes * height;
104
 
  data = g_malloc (data_size);
105
 
 
106
 
#ifdef HAVE_GLX
107
 
  if (grabber->have_pixel_buffers == -1)
108
 
    {
109
 
      const GLubyte* extensions = glGetString (GL_EXTENSIONS);
110
 
      grabber->have_pixel_buffers = strstr ((const char *)extensions, "GL_EXT_pixel_buffer_object") != NULL;
111
 
      grabber->have_pack_invert = strstr ((const char *)extensions, "GL_MESA_pack_invert") != NULL;
112
 
    }
113
 
 
114
 
  if (grabber->have_pixel_buffers)
115
 
    {
116
 
      GLubyte *mapped_data;
117
 
      GLint old_swap_bytes, old_lsb_first, old_row_length, old_skip_pixels, old_skip_rows, old_alignment;
118
 
      GLint old_pack_invert = GL_FALSE;
119
 
      GLint vp_size[4];
120
 
      guchar *src_row, *dest_row;
121
 
      int i;
122
 
 
123
 
      cogl_flush ();
124
 
 
125
 
      if (pf_glBindBufferARB == NULL)
126
 
        {
127
 
          pf_glBindBufferARB = (PFNGLBINDBUFFERARBPROC) cogl_get_proc_address ("glBindBufferARB");
128
 
          pf_glBufferDataARB = (PFNGLBUFFERDATAARBPROC) cogl_get_proc_address ("glBufferDataARB");
129
 
          pf_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC) cogl_get_proc_address ("glDeleteBuffersARB");
130
 
          pf_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC) cogl_get_proc_address ("glGenBuffersARB");
131
 
          pf_glMapBufferARB = (PFNGLMAPBUFFERARBPROC) cogl_get_proc_address ("glMapBufferARB");
132
 
          pf_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC) cogl_get_proc_address ("glUnmapBufferARB");
133
 
        }
134
 
 
135
 
      glGetIntegerv (GL_PACK_SWAP_BYTES, &old_swap_bytes);
136
 
      glGetIntegerv (GL_PACK_LSB_FIRST, &old_lsb_first);
137
 
      glGetIntegerv (GL_PACK_ROW_LENGTH, &old_row_length);
138
 
      glGetIntegerv (GL_PACK_SKIP_PIXELS, &old_skip_pixels);
139
 
      glGetIntegerv (GL_PACK_SKIP_ROWS, &old_skip_rows);
140
 
      glGetIntegerv (GL_PACK_ALIGNMENT, &old_alignment);
141
 
 
142
 
      glPixelStorei (GL_PACK_SWAP_BYTES, GL_FALSE);
143
 
      glPixelStorei (GL_PACK_LSB_FIRST, GL_FALSE);
144
 
      glPixelStorei (GL_PACK_ROW_LENGTH, 0);
145
 
      glPixelStorei (GL_PACK_SKIP_PIXELS, 0);
146
 
      glPixelStorei (GL_PACK_SKIP_ROWS, 0);
147
 
      glPixelStorei (GL_PACK_ALIGNMENT, 1);
148
 
 
149
 
      if (grabber->have_pack_invert)
150
 
        {
151
 
          glGetIntegerv (GL_PACK_INVERT_MESA, &old_pack_invert);
152
 
          glPixelStorei (GL_PACK_INVERT_MESA, GL_FALSE);
153
 
        }
154
 
 
155
 
      if (grabber->pixel_buffer != 0 &&
156
 
          (grabber->width != width ||
157
 
           grabber->height != height))
158
 
        {
159
 
          pf_glDeleteBuffersARB (1, &grabber->pixel_buffer);
160
 
          grabber->pixel_buffer = 0;
161
 
        }
162
 
 
163
 
      if (grabber->pixel_buffer == 0)
164
 
        {
165
 
          pf_glGenBuffersARB (1, &grabber->pixel_buffer);
166
 
 
167
 
          pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
168
 
          pf_glBufferDataARB (GL_PIXEL_PACK_BUFFER_ARB, data_size, 0, GL_STREAM_READ_ARB);
169
 
 
170
 
          grabber->width = width;
171
 
          grabber->height = height;
172
 
        }
173
 
      else
174
 
        {
175
 
          pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, grabber->pixel_buffer);
176
 
        }
177
 
 
178
 
      /* In OpenGL, (x,y) specifies the bottom-left corner rather than the
179
 
       * top-left */
180
 
      glGetIntegerv (GL_VIEWPORT, vp_size);
181
 
      y = vp_size[3] - (y + height);
182
 
 
183
 
      /* the "big-endian" version actually works for both, but the litle-endian
184
 
       * version has been better tested with a range of drivers, so we'll
185
 
       * keep on using it on little-endian.
186
 
       */
187
 
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
188
 
      glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, 0);
189
 
#else
190
 
      glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
191
 
#endif
192
 
 
193
 
      mapped_data = pf_glMapBufferARB (GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
194
 
 
195
 
      src_row = mapped_data + (height - 1) * row_bytes;
196
 
      dest_row = data;
197
 
 
198
 
      for (i = 0; i < height; i++)
199
 
        {
200
 
          memcpy (dest_row, src_row, row_bytes);
201
 
          src_row -= row_bytes;
202
 
          dest_row += row_bytes;
203
 
        }
204
 
 
205
 
      pf_glUnmapBufferARB (GL_PIXEL_PACK_BUFFER_ARB);
206
 
      pf_glBindBufferARB (GL_PIXEL_PACK_BUFFER_ARB, 0);
207
 
 
208
 
      glPixelStorei (GL_PACK_SWAP_BYTES, old_swap_bytes);
209
 
      glPixelStorei (GL_PACK_LSB_FIRST, old_lsb_first);
210
 
      glPixelStorei (GL_PACK_ROW_LENGTH, old_row_length);
211
 
      glPixelStorei (GL_PACK_SKIP_PIXELS, old_skip_pixels);
212
 
      glPixelStorei (GL_PACK_SKIP_ROWS, old_skip_rows);
213
 
      glPixelStorei (GL_PACK_ALIGNMENT, old_alignment);
214
 
 
215
 
      if (grabber->have_pack_invert)
216
 
        glPixelStorei (GL_PACK_INVERT_MESA, old_pack_invert);
217
 
    }
218
 
  else
219
 
#endif /* HAVE_GLX */
220
 
    {
221
 
      cogl_read_pixels (x, y,
222
 
                        width, height,
223
 
                        COGL_READ_PIXELS_COLOR_BUFFER,
224
 
                        CLUTTER_CAIRO_FORMAT_ARGB32,
225
 
                        data);
226
 
    }
227
 
 
228
 
  return data;
229
 
}