~oem-solutions-group/unity-2d/clutter-1.0

« back to all changes in this revision

Viewing changes to clutter/eglx/clutter-stage-egl.c

  • Committer: Bazaar Package Importer
  • Author(s): Emilio Pozuelo Monfort
  • Date: 2010-03-21 13:27:56 UTC
  • mto: (2.1.3 experimental)
  • 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:
19
19
#include "../clutter-stage.h"
20
20
#include "../clutter-stage-window.h"
21
21
 
 
22
static ClutterStageWindowIface *clutter_stage_egl_parent_iface = NULL;
 
23
 
22
24
static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
23
25
 
24
26
G_DEFINE_TYPE_WITH_CODE (ClutterStageEGL,
28
30
                                                clutter_stage_window_iface_init));
29
31
 
30
32
static void
31
 
clutter_stage_egl_unrealize (ClutterActor *actor)
 
33
clutter_stage_egl_unrealize (ClutterStageWindow *stage_window)
32
34
{
33
 
  ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (actor);
34
 
  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
35
 
  gboolean was_offscreen;
36
 
 
37
 
  CLUTTER_MARK();
38
 
 
39
 
  g_object_get (stage_x11->wrapper, "offscreen", &was_offscreen, NULL);
40
 
 
41
 
  if (CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize != NULL)
42
 
    CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->unrealize (actor);
 
35
  ClutterBackend *backend = clutter_get_default_backend ();
 
36
  ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
 
37
  ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (stage_window);
 
38
  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
 
39
 
 
40
  CLUTTER_NOTE (BACKEND, "Unrealizing stage");
43
41
 
44
42
  clutter_x11_trap_x_errors ();
45
43
 
46
 
  if (G_UNLIKELY (was_offscreen))
 
44
  if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
47
45
    {
48
 
      /* No support as yet for this */
 
46
      XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
 
47
      stage_x11->xwin = None;
49
48
    }
50
49
  else
51
 
    {
52
 
      if (!stage_x11->is_foreign_xwin && stage_x11->xwin != None)
53
 
        {
54
 
          XDestroyWindow (stage_x11->xdpy, stage_x11->xwin);
55
 
          stage_x11->xwin = None;
56
 
        }
57
 
      else
58
 
        stage_x11->xwin = None;
59
 
    }
 
50
    stage_x11->xwin = None;
60
51
 
61
52
  if (stage_egl->egl_surface)
62
53
    {
64
55
      stage_egl->egl_surface = EGL_NO_SURFACE;
65
56
    }
66
57
 
67
 
  XSync (stage_x11->xdpy, False);
 
58
  XSync (backend_x11->xdpy, False);
68
59
 
69
60
  clutter_x11_untrap_x_errors ();
70
 
 
71
 
  CLUTTER_MARK ();
72
61
}
73
62
 
74
 
static void
75
 
clutter_stage_egl_realize (ClutterActor *actor)
 
63
static gboolean
 
64
_clutter_stage_egl_try_realize (ClutterStageWindow *stage_window, int *retry_cookie)
76
65
{
77
 
  ClutterStageEGL   *stage_egl = CLUTTER_STAGE_EGL (actor);
78
 
  ClutterStageX11   *stage_x11 = CLUTTER_STAGE_X11 (actor);
 
66
  ClutterStageEGL   *stage_egl = CLUTTER_STAGE_EGL (stage_window);
 
67
  ClutterStageX11   *stage_x11 = CLUTTER_STAGE_X11 (stage_window);
 
68
  ClutterBackend    *backend;
79
69
  ClutterBackendEGL *backend_egl;
80
70
  ClutterBackendX11 *backend_x11;
81
 
  EGLConfig          configs[2];
 
71
  EGLConfig          config;
82
72
  EGLint             config_count;
83
73
  EGLBoolean         status;
84
 
  gboolean           is_offscreen = FALSE;
85
 
 
86
 
  CLUTTER_NOTE (BACKEND, "Realizing main stage");
87
 
 
88
 
  g_object_get (stage_x11->wrapper, "offscreen", &is_offscreen, NULL);
89
 
 
90
 
  backend_egl = CLUTTER_BACKEND_EGL (clutter_get_default_backend ());
91
 
  backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ());
92
 
 
93
 
  if (G_LIKELY (!is_offscreen))
94
 
    {
95
 
      int c;
96
 
      int num_configs;
97
 
      EGLConfig *all_configs;
98
 
 
99
 
      EGLint cfg_attribs[] = {
100
 
        EGL_BUFFER_SIZE,    EGL_DONT_CARE,
101
 
        EGL_RED_SIZE,       5,
102
 
        EGL_GREEN_SIZE,     6,
103
 
        EGL_BLUE_SIZE,      5,
104
 
       EGL_STENCIL_SIZE, 8,
 
74
  int                i;
 
75
  int                num_configs;
 
76
  EGLConfig         *all_configs;
 
77
  EGLint             cfg_attribs[] = {
 
78
    /* NB: This must be the first attribute, since we may
 
79
     * try and fallback to no stencil buffer */
 
80
    EGL_STENCIL_SIZE,   8,
 
81
 
 
82
    EGL_RED_SIZE,       5,
 
83
    EGL_GREEN_SIZE,     6,
 
84
    EGL_BLUE_SIZE,      5,
 
85
 
 
86
    EGL_BUFFER_SIZE,    EGL_DONT_CARE,
 
87
 
105
88
#ifdef HAVE_COGL_GLES2
106
 
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 
89
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
107
90
#else /* HAVE_COGL_GLES2 */
108
 
        EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
 
91
    EGL_SURFACE_TYPE,    EGL_WINDOW_BIT,
109
92
#endif /* HAVE_COGL_GLES2 */
110
93
 
111
 
        EGL_NONE
112
 
      };
113
 
 
114
 
      status = eglGetConfigs (backend_egl->edpy,
115
 
                              configs,
116
 
                              2,
117
 
                              &config_count);
118
 
 
119
 
      eglGetConfigs (clutter_eglx_display (), NULL, 0, &num_configs);
120
 
 
121
 
      all_configs = g_malloc (num_configs * sizeof (EGLConfig));
122
 
      eglGetConfigs (clutter_eglx_display (),
123
 
                     all_configs,
124
 
                     num_configs,
125
 
                     &num_configs);
126
 
 
127
 
      for (c = 0; c < num_configs; ++c)
128
 
        {
129
 
          EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
130
 
 
131
 
          eglGetConfigAttrib (clutter_eglx_display (),
132
 
                              all_configs[c],
133
 
                              EGL_RED_SIZE, &red);
134
 
          eglGetConfigAttrib (clutter_eglx_display (),
135
 
                              all_configs[c],
136
 
                              EGL_GREEN_SIZE, &green);
137
 
          eglGetConfigAttrib (clutter_eglx_display (),
138
 
                              all_configs[c],
139
 
                              EGL_BLUE_SIZE, &blue);
140
 
          eglGetConfigAttrib (clutter_eglx_display (),
141
 
                              all_configs[c],
142
 
                              EGL_ALPHA_SIZE, &alpha);
143
 
          eglGetConfigAttrib (clutter_eglx_display (),
144
 
                              all_configs[c],
145
 
                              EGL_STENCIL_SIZE, &stencil);
146
 
          CLUTTER_NOTE (BACKEND, "EGLConfig == R:%d G:%d B:%d A:%d S:%d \n",
147
 
                        red, green, blue, alpha, stencil);
148
 
        }
149
 
 
150
 
      g_free (all_configs);
151
 
 
152
 
      if (status != EGL_TRUE)
153
 
        {
154
 
          g_critical ("eglGetConfigs failed");
155
 
          goto fail;
156
 
        }
157
 
 
158
 
      status = eglChooseConfig (backend_egl->edpy,
159
 
                                cfg_attribs,
160
 
                                configs,
161
 
                                G_N_ELEMENTS (configs),
162
 
                                &config_count);
163
 
 
164
 
      if (status != EGL_TRUE)
165
 
        {
166
 
          g_critical ("eglChooseConfig failed");
167
 
          goto fail;
168
 
        }
169
 
 
170
 
      if (stage_x11->xwin == None)
171
 
        stage_x11->xwin =
172
 
          XCreateSimpleWindow (stage_x11->xdpy,
173
 
                               stage_x11->xwin_root,
174
 
                               0, 0,
175
 
                               stage_x11->xwin_width,
176
 
                               stage_x11->xwin_height,
177
 
                               0, 0,
178
 
                               WhitePixel (stage_x11->xdpy,
179
 
                                           stage_x11->xscreen));
180
 
 
181
 
      if (clutter_x11_has_event_retrieval ())
182
 
        {
183
 
          if (clutter_x11_has_xinput ())
184
 
            {
185
 
              XSelectInput (stage_x11->xdpy, stage_x11->xwin,
186
 
                            StructureNotifyMask |
187
 
                            FocusChangeMask |
188
 
                            ExposureMask |
189
 
                            EnterWindowMask | LeaveWindowMask |
190
 
                            PropertyChangeMask);
191
 
#ifdef USE_XINPUT          
192
 
              _clutter_x11_select_events (stage_x11->xwin);
 
94
    EGL_NONE
 
95
  };
 
96
  EGLDisplay edpy;
 
97
 
 
98
  /* Here we can change the attributes depending on the fallback count... */
 
99
 
 
100
  /* Some GLES hardware can't support a stencil buffer: */
 
101
  if (*retry_cookie == 1)
 
102
    {
 
103
      g_warning ("Trying with stencil buffer disabled...");
 
104
      cfg_attribs[1 /* EGL_STENCIL_SIZE */] = 0;
 
105
    }
 
106
 
 
107
  /* XXX: at this point we only have one fallback */
 
108
 
 
109
  backend     = clutter_get_default_backend ();
 
110
  backend_egl = CLUTTER_BACKEND_EGL (backend);
 
111
  backend_x11 = CLUTTER_BACKEND_X11 (backend);
 
112
 
 
113
  edpy = clutter_eglx_display ();
 
114
 
 
115
  eglGetConfigs (edpy, NULL, 0, &num_configs);
 
116
 
 
117
  all_configs = g_malloc (num_configs * sizeof (EGLConfig));
 
118
  eglGetConfigs (clutter_eglx_display (),
 
119
                 all_configs,
 
120
                 num_configs,
 
121
                 &num_configs);
 
122
 
 
123
  for (i = 0; i < num_configs; ++i)
 
124
    {
 
125
      EGLint red = -1, green = -1, blue = -1, alpha = -1, stencil = -1;
 
126
 
 
127
      eglGetConfigAttrib (edpy,
 
128
                          all_configs[i],
 
129
                          EGL_RED_SIZE, &red);
 
130
      eglGetConfigAttrib (edpy,
 
131
                          all_configs[i],
 
132
                          EGL_GREEN_SIZE, &green);
 
133
      eglGetConfigAttrib (edpy,
 
134
                          all_configs[i],
 
135
                          EGL_BLUE_SIZE, &blue);
 
136
      eglGetConfigAttrib (edpy,
 
137
                          all_configs[i],
 
138
                          EGL_ALPHA_SIZE, &alpha);
 
139
      eglGetConfigAttrib (edpy,
 
140
                          all_configs[i],
 
141
                          EGL_STENCIL_SIZE, &stencil);
 
142
      CLUTTER_NOTE (BACKEND, "EGLConfig == R:%d G:%d B:%d A:%d S:%d \n",
 
143
                    red, green, blue, alpha, stencil);
 
144
    }
 
145
 
 
146
  g_free (all_configs);
 
147
 
 
148
  status = eglChooseConfig (edpy,
 
149
                            cfg_attribs,
 
150
                            &config, 1,
 
151
                            &config_count);
 
152
  if (status != EGL_TRUE)
 
153
    {
 
154
      g_warning ("eglChooseConfig failed");
 
155
      goto fail;
 
156
    }
 
157
 
 
158
  if (stage_x11->xwin == None)
 
159
    stage_x11->xwin =
 
160
      XCreateSimpleWindow (backend_x11->xdpy,
 
161
                           backend_x11->xwin_root,
 
162
                           0, 0,
 
163
                           stage_x11->xwin_width,
 
164
                           stage_x11->xwin_height,
 
165
                           0, 0,
 
166
                           WhitePixel (backend_x11->xdpy,
 
167
                                       backend_x11->xscreen_num));
 
168
 
 
169
  if (clutter_x11_has_event_retrieval ())
 
170
    {
 
171
      if (clutter_x11_has_xinput ())
 
172
        {
 
173
          XSelectInput (backend_x11->xdpy, stage_x11->xwin,
 
174
                        StructureNotifyMask |
 
175
                        FocusChangeMask |
 
176
                        ExposureMask |
 
177
                        EnterWindowMask | LeaveWindowMask |
 
178
                        PropertyChangeMask);
 
179
#ifdef USE_XINPUT
 
180
          _clutter_x11_select_events (stage_x11->xwin);
193
181
#endif
194
 
            }
195
 
          else
196
 
            XSelectInput (stage_x11->xdpy, stage_x11->xwin,
197
 
                          StructureNotifyMask |
198
 
                          FocusChangeMask |
199
 
                          ExposureMask |
200
 
                          PointerMotionMask |
201
 
                          KeyPressMask | KeyReleaseMask |
202
 
                          ButtonPressMask | ButtonReleaseMask |
203
 
                          EnterWindowMask | LeaveWindowMask |
204
 
                          PropertyChangeMask);
205
 
        }
206
 
 
207
 
      /* FIXME, do these in a clutterstage_x11_realise? */
208
 
      clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
209
 
      clutter_stage_x11_set_wm_protocols (stage_x11);
210
 
 
211
 
      if (stage_egl->egl_surface != EGL_NO_SURFACE)
212
 
        {
213
 
          eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
214
 
          stage_egl->egl_surface = EGL_NO_SURFACE;
215
 
        }
216
 
 
217
 
      stage_egl->egl_surface =
218
 
        eglCreateWindowSurface (backend_egl->edpy,
219
 
                                configs[0],
220
 
                                (NativeWindowType) stage_x11->xwin,
221
 
                                NULL);
222
 
 
223
 
      if (stage_egl->egl_surface == EGL_NO_SURFACE)
224
 
        {
225
 
          g_critical ("Unable to create an EGL surface");
226
 
          goto fail;
227
 
        }
228
 
 
229
 
      if (G_UNLIKELY (backend_egl->egl_context == None))
230
 
        {
 
182
        }
 
183
      else
 
184
        XSelectInput (backend_x11->xdpy, stage_x11->xwin,
 
185
                      StructureNotifyMask |
 
186
                      FocusChangeMask |
 
187
                      ExposureMask |
 
188
                      PointerMotionMask |
 
189
                      KeyPressMask | KeyReleaseMask |
 
190
                      ButtonPressMask | ButtonReleaseMask |
 
191
                      EnterWindowMask | LeaveWindowMask |
 
192
                      PropertyChangeMask);
 
193
    }
 
194
 
 
195
  clutter_stage_x11_fix_window_size (stage_x11, -1, -1);
 
196
  clutter_stage_x11_set_wm_protocols (stage_x11);
 
197
 
 
198
  if (stage_egl->egl_surface != EGL_NO_SURFACE)
 
199
    {
 
200
      eglDestroySurface (edpy, stage_egl->egl_surface);
 
201
      stage_egl->egl_surface = EGL_NO_SURFACE;
 
202
    }
 
203
 
 
204
  stage_egl->egl_surface =
 
205
    eglCreateWindowSurface (edpy,
 
206
                            config,
 
207
                            (NativeWindowType) stage_x11->xwin,
 
208
                            NULL);
 
209
 
 
210
  if (stage_egl->egl_surface == EGL_NO_SURFACE)
 
211
    {
 
212
      g_warning ("Unable to create an EGL surface");
 
213
      goto fail;
 
214
    }
 
215
 
 
216
  if (G_UNLIKELY (backend_egl->egl_context == None))
 
217
    {
231
218
#ifdef HAVE_COGL_GLES2
232
 
          static const EGLint attribs[3]
233
 
            = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
219
      static const EGLint attribs[3]
 
220
        = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
234
221
 
235
 
          backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
236
 
                                                       configs[0],
237
 
                                                       EGL_NO_CONTEXT,
238
 
                                                       attribs);
 
222
      backend_egl->egl_context = eglCreateContext (edpy,
 
223
                                                   config,
 
224
                                                   EGL_NO_CONTEXT,
 
225
                                                   attribs);
239
226
#else
240
 
          /* Seems some GLES implementations 1.x do not like attribs... */
241
 
          backend_egl->egl_context = eglCreateContext (backend_egl->edpy,
242
 
                                                       configs[0],
243
 
                                                       EGL_NO_CONTEXT,
244
 
                                                       NULL);
 
227
      /* Seems some GLES implementations 1.x do not like attribs... */
 
228
      backend_egl->egl_context = eglCreateContext (edpy,
 
229
                                                   config,
 
230
                                                   EGL_NO_CONTEXT,
 
231
                                                   NULL);
245
232
#endif
246
 
          if (backend_egl->egl_context == EGL_NO_CONTEXT)
247
 
            {
248
 
              g_critical ("Unable to create a suitable EGL context");
249
 
              goto fail;
250
 
            }
251
 
          backend_egl->egl_config = configs[0];
252
 
          CLUTTER_NOTE (GL, "Created EGL Context");
 
233
      if (backend_egl->egl_context == EGL_NO_CONTEXT)
 
234
        {
 
235
          g_warning ("Unable to create a suitable EGL context");
 
236
          goto fail;
253
237
        }
254
 
    }
255
 
  else
256
 
    {
257
 
      g_critical ("EGLX Backend does not support offscreen rendering");
258
 
      goto fail;
259
 
    }
260
 
 
261
 
  /* we need to chain up to the X11 stage implementation in order to
262
 
   * set the window state in case we set it before realizing the stage
263
 
   */
264
 
  CLUTTER_ACTOR_CLASS (clutter_stage_egl_parent_class)->realize (actor);
265
 
  return;
 
238
 
 
239
      backend_egl->egl_config = config;
 
240
      CLUTTER_NOTE (GL, "Created EGL Context");
 
241
    }
 
242
 
 
243
  *retry_cookie = 0;
 
244
  return TRUE;
266
245
 
267
246
fail:
268
 
  CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
 
247
 
 
248
  if (stage_egl->egl_surface != EGL_NO_SURFACE)
 
249
    {
 
250
      eglDestroySurface (backend_egl->edpy, stage_egl->egl_surface);
 
251
      stage_egl->egl_surface = EGL_NO_SURFACE;
 
252
    }
 
253
  if (stage_x11->xwin != None)
 
254
    {
 
255
      XDestroyWindow (backend_x11->xdpy, stage_x11->xwin);
 
256
      stage_x11->xwin = None;
 
257
    }
 
258
 
 
259
  /* NB: We currently only support a single fallback option */
 
260
  if (*retry_cookie == 0)
 
261
    *retry_cookie = 1; /* tell the caller to try again */
 
262
  else
 
263
    *retry_cookie = 0; /* tell caller not to try again! */
 
264
 
 
265
  return FALSE;
 
266
}
 
267
 
 
268
static gboolean
 
269
clutter_stage_egl_realize (ClutterStageWindow *stage_window)
 
270
{
 
271
  int retry_cookie = 0;
 
272
 
 
273
  CLUTTER_NOTE (BACKEND, "Realizing main stage");
 
274
 
 
275
  while (1)
 
276
    {
 
277
      /* _clutter_stage_egl_try_realize supports fallbacks, and the number of
 
278
       * fallbacks already tried is tracked in the retry_cookie, so what we are
 
279
       * doing here is re-trying until we get told there are no more fallback
 
280
       * options... */
 
281
      if (_clutter_stage_egl_try_realize (stage_window, &retry_cookie))
 
282
        {
 
283
          gboolean ret = clutter_stage_egl_parent_iface->realize (stage_window);
 
284
          if (G_LIKELY (ret))
 
285
            CLUTTER_NOTE (BACKEND, "Successfully realized stage");
 
286
 
 
287
          return ret;
 
288
        }
 
289
      if (retry_cookie == 0)
 
290
        return FALSE; /* we've been told not to try again! */
 
291
 
 
292
      g_warning ("%s: Trying fallback", G_STRFUNC);
 
293
    }
 
294
 
 
295
  g_return_val_if_reached (FALSE);
269
296
}
270
297
 
271
298
static void
272
299
clutter_stage_egl_dispose (GObject *gobject)
273
300
{
274
 
  ClutterStageEGL *stage_egl = CLUTTER_STAGE_EGL (gobject);
275
 
  ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (gobject);
276
 
 
277
301
  G_OBJECT_CLASS (clutter_stage_egl_parent_class)->dispose (gobject);
278
302
}
279
303
 
280
304
static void
281
305
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
282
306
{
 
307
  clutter_stage_egl_parent_iface = g_type_interface_peek_parent (iface);
 
308
 
 
309
  iface->realize = clutter_stage_egl_realize;
 
310
  iface->unrealize = clutter_stage_egl_unrealize;
 
311
 
283
312
  /* the rest is inherited from ClutterStageX11 */
284
313
}
285
314
 
287
316
clutter_stage_egl_class_init (ClutterStageEGLClass *klass)
288
317
{
289
318
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
290
 
  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
291
319
 
292
320
  gobject_class->dispose = clutter_stage_egl_dispose;
293
 
 
294
 
  actor_class->realize = clutter_stage_egl_realize;
295
 
  actor_class->unrealize = clutter_stage_egl_unrealize;
296
321
}
297
322
 
298
323
static void