Пример #1
0
/* XXX:
 * Operations like scale, translate, rotate etc need to have an
 * initialized state->matrix to work with, so they will pass
 * initialize = TRUE.
 *
 * _cogl_matrix_stack_load_identity and _cogl_matrix_stack_set on the
 * other hand don't so they will pass initialize = FALSE
 *
 * NB: Identity matrices are represented by setting
 * state->is_identity=TRUE in which case state->matrix will be
 * uninitialized.
 */
static CoglMatrixState *
_cogl_matrix_stack_top_mutable (CoglMatrixStack *stack,
                                gboolean initialize)
{
  CoglMatrixState *state;
  CoglMatrixState *new_top;

  state = _cogl_matrix_stack_top (stack);

  if (state->push_count == 0)
    {
      if (state->is_identity && initialize)
        cogl_matrix_init_identity (&state->matrix);
      return state;
    }

  state->push_count -= 1;

  g_array_set_size (stack->stack, stack->stack->len + 1);
  new_top = &g_array_index (stack->stack, CoglMatrixState,
                            stack->stack->len - 1);
  _cogl_matrix_state_init (new_top);

  if (initialize)
    {
      if (state->is_identity)
        cogl_matrix_init_identity (&new_top->matrix);
      else
        new_top->matrix = state->matrix;
    }

  return new_top;
}
Пример #2
0
RutCamera *
rut_camera_new (RutContext *ctx, CoglFramebuffer *framebuffer)
{
  RutCamera *camera = g_slice_new0 (RutCamera);

  camera->ctx = rut_refable_ref (ctx);

  rut_object_init (&camera->_parent, &rut_camera_type);

  camera->ref_count = 1;

  camera->component.type = RUT_COMPONENT_TYPE_CAMERA;

  rut_camera_set_background_color4f (camera, 0, 0, 0, 1);
  camera->clear_fb = TRUE;

  //rut_graphable_init (RUT_OBJECT (camera));

  camera->orthographic = TRUE;
  camera->x1 = 0;
  camera->y1 = 0;
  camera->x2 = 100;
  camera->y2 = 100;

  camera->near = -1;
  camera->far = 100;

  camera->zoom = 1;

  camera->focal_distance = 30;
  camera->depth_of_field = 3;

  camera->projection_cache_age = -1;
  camera->inverse_projection_age = -1;

  cogl_matrix_init_identity (&camera->view);
  camera->inverse_view_age = -1;

  camera->transform_age = 0;

  cogl_matrix_init_identity (&camera->input_transform);

  if (framebuffer)
    {
      int width = cogl_framebuffer_get_width (framebuffer);
      int height = cogl_framebuffer_get_height (framebuffer);
      camera->fb = cogl_object_ref (framebuffer);
      camera->viewport[2] = width;
      camera->viewport[3] = height;
      camera->x2 = width;
      camera->y2 = height;
    }

  rut_simple_introspectable_init (camera,
                                  _rut_camera_prop_specs,
                                  camera->properties);

  return camera;
}
Пример #3
0
static void
mx_fade_effect_post_paint (ClutterEffect *effect)
{
  MxFadeEffectPrivate *priv = MX_FADE_EFFECT (effect)->priv;

  if (!priv->freeze_update)
    CLUTTER_EFFECT_CLASS (mx_fade_effect_parent_class)->post_paint (effect);
  else
    {
      CoglMatrix modelview;
      ClutterActor *actor, *stage;

      actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
      stage = clutter_actor_get_stage (actor);

      /* Set up the draw matrix so we draw the offscreen texture at the
       * absolute coordinates of the actor-box. We need to do this to
       * avoid transforming by the actor matrix twice, as when it's drawn
       * into the offscreen surface, it'll already be transformed.
       */
      cogl_push_matrix ();

      cogl_matrix_init_identity (&modelview);
      CLUTTER_ACTOR_CLASS (G_OBJECT_GET_CLASS (stage))->
        apply_transform (stage, &modelview);
      cogl_matrix_translate (&modelview, priv->x_offset, priv->y_offset, 0.f);
      cogl_set_modelview_matrix (&modelview);

      clutter_offscreen_effect_paint_target (CLUTTER_OFFSCREEN_EFFECT (effect));

      cogl_pop_matrix ();
    }
}
Пример #4
0
static void
mx_deform_bow_tie_dispose (GObject *object)
{
  MxDeformBowTiePrivate *priv = MX_DEFORM_BOW_TIE (object)->priv;

  if (priv->back_id && priv->back)
    {
      g_signal_handler_disconnect (priv->back, priv->back_id);
      priv->back_id = 0;
    }

  if (priv->back)
    {
      CoglHandle material;

      /* Reset layer matrix */
      material = clutter_texture_get_cogl_material (priv->back);

      if (material)
        {
          CoglMatrix matrix;
          cogl_matrix_init_identity (&matrix);
          cogl_material_set_layer_matrix (material, 0, &matrix);
        }

      g_object_remove_weak_pointer (G_OBJECT (priv->back),
                                    (gpointer *)&priv->back);
      priv->back = NULL;
    }

  G_OBJECT_CLASS (mx_deform_bow_tie_parent_class)->dispose (object);
}
Пример #5
0
void
rut_graphable_get_transform (RutObject *graphable,
                             CoglMatrix *transform)
{
  cogl_matrix_init_identity (transform);
  rut_graphable_apply_transform (graphable, transform);
}
Пример #6
0
/**
 * clutter_matrix_init_identity:
 * @matrix: a #ClutterMatrix
 *
 * Initializes @matrix with the identity matrix, i.e.:
 *
 * |[
 *   .xx = 1.0, .xy = 0.0, .xz = 0.0, .xw = 0.0
 *   .yx = 0.0, .yy = 1.0, .yz = 0.0, .yw = 0.0
 *   .zx = 0.0, .zy = 0.0, .zz = 1.0, .zw = 0.0
 *   .wx = 0.0, .wy = 0.0, .wz = 0.0, .ww = 1.0
 * ]|
 *
 * Return value: (transfer none): the initialized #ClutterMatrix
 *
 * Since: 1.12
 */
ClutterMatrix *
clutter_matrix_init_identity (ClutterMatrix *matrix)
{
  cogl_matrix_init_identity (matrix);

  return matrix;
}
Пример #7
0
void
rig_camera_update_view (RigEngine *engine, RutEntity *camera, CoglBool shadow_pass)
{
  RutCamera *camera_component =
    rut_entity_get_component (camera, RUT_COMPONENT_TYPE_CAMERA);
  CoglMatrix transform;
  CoglMatrix inverse_transform;
  CoglMatrix view;

  /* translate to z_2d and scale */
  if (!shadow_pass)
    view = engine->main_view;
  else
    view = engine->identity;

  /* apply the camera viewing transform */
  rut_graphable_get_transform (camera, &transform);
  cogl_matrix_get_inverse (&transform, &inverse_transform);
  cogl_matrix_multiply (&view, &view, &inverse_transform);

  if (shadow_pass)
    {
      CoglMatrix flipped_view;
      cogl_matrix_init_identity (&flipped_view);
      cogl_matrix_scale (&flipped_view, 1, -1, 1);
      cogl_matrix_multiply (&flipped_view, &flipped_view, &view);
      rut_camera_set_view_transform (camera_component, &flipped_view);
    }
  else
    rut_camera_set_view_transform (camera_component, &view);
}
Пример #8
0
void
_mai_node_draw_recursive (MaiNode *self, CoglMatrix *acc_mtx)
{
  CoglPrimitive *to_draw;
  to_draw = nx_cogl_primitive_new (self->mesh_verts, self->mesh_indices, self->mesh_uvs);

  CoglMatrix cur_mtx;
  cogl_matrix_init_identity (&cur_mtx);
  cogl_matrix_multiply (&cur_mtx, &cur_mtx, acc_mtx);
  cogl_matrix_multiply (&cur_mtx, &cur_mtx, self->transformation);

  cogl_set_modelview_matrix (&cur_mtx);

  nx_cogl_primitive_draw (to_draw);

  cogl_object_unref (to_draw);

  int tmp1;
  for (tmp1=0; tmp1<self->children->len; ++tmp1)
    {
      MaiNode *child;
      child = g_mai_node_ptr_array_index (self->children, tmp1);
      _mai_node_draw_recursive (child, &cur_mtx);
    }
}
Пример #9
0
gboolean
cogl_matrix_get_inverse (const CoglMatrix *matrix, CoglMatrix *inverse)
{
#ifndef USE_MESA_MATRIX_API
#warning "cogl_matrix_get_inverse not supported without Mesa matrix API"
  cogl_matrix_init_identity (inverse);
  return FALSE;
#else
  if (_math_matrix_update_inverse ((CoglMatrix *)matrix))
    {
      cogl_matrix_init_from_array (inverse, matrix->inv);
      return TRUE;
    }
  else
    {
      cogl_matrix_init_identity (inverse);
      return FALSE;
    }
#endif
}
Пример #10
0
const CoglMatrix *
rut_camera_get_projection (RutCamera *camera)
{
  if (G_UNLIKELY (camera->projection_cache_age != camera->projection_age))
    {
      cogl_matrix_init_identity (&camera->projection);

      if (camera->orthographic)
        {
          float x1, x2, y1, y2;

          if (camera->zoom != 1)
            {
              float center_x = camera->x1 + (camera->x2 - camera->x1) / 2.0;
              float center_y = camera->y1 + (camera->y2 - camera->y1) / 2.0;
              float inverse_scale = 1.0 / camera->zoom;
              float dx = (camera->x2 - center_x) * inverse_scale;
              float dy = (camera->y2 - center_y) * inverse_scale;

              camera->x1 = center_x - dx;
              camera->x2 = center_x + dx;
              camera->y1 = center_y - dy;
              camera->y2 = center_y + dy;
            }
          else
            {
              x1 = camera->x1;
              x2 = camera->x2;
              y1 = camera->y1;
              y2 = camera->y2;
            }

          cogl_matrix_orthographic (&camera->projection,
                                    x1, y1, x2, y2,
                                    camera->near,
                                    camera->far);
        }
      else
        {
          float aspect_ratio = camera->viewport[2] / camera->viewport[3];
          rut_util_matrix_scaled_perspective (&camera->projection,
                                              camera->fov,
                                              aspect_ratio,
                                              camera->near,
                                              camera->far,
                                              camera->zoom);
        }

      camera->projection_cache_age = camera->projection_age;
    }

  return &camera->projection;
}
Пример #11
0
static void
paint_matrix_pipeline (CoglPipeline *pipeline)
{
  CoglMatrix matrices[4];
  float matrix_floats[16 * 4];
  int uniform_location;
  int i;

  for (i = 0; i < 4; i++)
    cogl_matrix_init_identity (matrices + i);

  /* Use the first matrix to make the color red */
  cogl_matrix_translate (matrices + 0, 1.0f, 0.0f, 0.0f);

  /* Rotate the vertex so that it ends up green */
  cogl_matrix_rotate (matrices + 1, 90.0f, 0.0f, 0.0f, 1.0f);

  /* Scale the vertex so it ends up halved */
  cogl_matrix_scale (matrices + 2, 0.5f, 0.5f, 0.5f);

  /* Add a blue component in the final matrix. The final matrix is
     uploaded as transposed so we need to transpose first to cancel
     that out */
  cogl_matrix_translate (matrices + 3, 0.0f, 0.0f, 1.0f);
  cogl_matrix_transpose (matrices + 3);

  for (i = 0; i < 4; i++)
    memcpy (matrix_floats + i * 16,
            cogl_matrix_get_array (matrices + i),
            sizeof (float) * 16);

  /* Set the first three matrices as transposed */
  uniform_location =
    cogl_pipeline_get_uniform_location (pipeline, "matrix_array");
  cogl_pipeline_set_uniform_matrix (pipeline,
                                    uniform_location,
                                    4, /* dimensions */
                                    3, /* count */
                                    FALSE, /* not transposed */
                                    matrix_floats);

  /* Set the last matrix as untransposed */
  uniform_location =
    cogl_pipeline_get_uniform_location (pipeline, "matrix_array[3]");
  cogl_pipeline_set_uniform_matrix (pipeline,
                                    uniform_location,
                                    4, /* dimensions */
                                    1, /* count */
                                    TRUE, /* transposed */
                                    matrix_floats + 16 * 3);

  paint_pipeline (pipeline, 12);
}
Пример #12
0
/**
 * mash_light_get_modelview_matrix:
 * @light: A #MashLight
 * @matrix: The return location for the matrix
 *
 * Gets the modelview matrix for the light including all of the
 * transformations for its parent actors. This should be used for
 * updating uniforms that depend on the actor's transformation or
 * position.
 */
void
mash_light_get_modelview_matrix (MashLight *light,
                                 CoglMatrix *matrix)
{
  MashLightPrivate *priv = light->priv;

  if (priv->modelview_matrix_dirty)
    {
      ClutterActor *actor;
      GSList *parents = NULL, *l;

      cogl_matrix_init_identity (&priv->modelview_matrix);

      /* Get the complete modelview matrix for light by applying all of
         its parent transformations as well as its own in reverse */
      for (actor = CLUTTER_ACTOR (light);
           actor;
           actor = clutter_actor_get_parent (actor))
        parents = g_slist_prepend (parents, actor);

      for (l = parents; l; l = l->next)
        {
          CoglMatrix actor_matrix;

          cogl_matrix_init_identity (&actor_matrix);
          clutter_actor_get_transformation_matrix (CLUTTER_ACTOR (l->data),
                                                   &actor_matrix);

          cogl_matrix_multiply (&priv->modelview_matrix,
                                &priv->modelview_matrix,
                                &actor_matrix);
        }

      g_slist_free (parents);

      priv->modelview_matrix_dirty = FALSE;
    }

  *matrix = priv->modelview_matrix;
}
Пример #13
0
void
_example_draw_at (int x, int y)
{
    cogl_set_source_color4ub ('\xFF', '1', '1', 255);
    cogl_ortho (0, 64, 0, 64, -5, 5);

    CoglMatrix idmtx;
    cogl_matrix_init_identity (&idmtx);
    cogl_set_modelview_matrix (&idmtx);

    cogl_rectangle (x+1, y+1, x-1, y-1);

    cogl_flush ();
}
Пример #14
0
static void
mx_deform_bow_tie_texture_reset (ClutterTexture *texture)
{
  CoglHandle material;

  material = clutter_texture_get_cogl_material (texture);

  if (material)
    {
      CoglMatrix matrix;
      cogl_matrix_init_identity (&matrix);
      cogl_material_set_layer_matrix (material, 0, &matrix);
    }
}
Пример #15
0
void
test_euler_quaternion (void)
{
  CoglEuler euler;
  CoglQuaternion quaternion;
  CoglMatrix matrix_a, matrix_b;

  /* Try doing the rotation with three separate rotations */
  cogl_matrix_init_identity (&matrix_a);
  cogl_matrix_rotate (&matrix_a, -30.0f, 0.0f, 1.0f, 0.0f);
  cogl_matrix_rotate (&matrix_a, 40.0f, 1.0f, 0.0f, 0.0f);
  cogl_matrix_rotate (&matrix_a, 50.0f, 0.0f, 0.0f, 1.0f);

  /* And try the same rotation with a euler */
  cogl_euler_init (&euler, -30, 40, 50);
  cogl_matrix_init_from_euler (&matrix_b, &euler);

  /* Verify that the matrices are approximately the same */
  COMPARE_MATRICES (&matrix_a, &matrix_b);

  /* Try converting the euler to a matrix via a quaternion */
  cogl_quaternion_init_from_euler (&quaternion, &euler);
  memset (&matrix_b, 0, sizeof (matrix_b));
  cogl_matrix_init_from_quaternion (&matrix_b, &quaternion);
  COMPARE_MATRICES (&matrix_a, &matrix_b);

  /* Try applying the rotation from a euler to a framebuffer */
  cogl_framebuffer_identity_matrix (test_fb);
  cogl_framebuffer_rotate_euler (test_fb, &euler);
  memset (&matrix_b, 0, sizeof (matrix_b));
  cogl_framebuffer_get_modelview_matrix (test_fb, &matrix_b);
  COMPARE_MATRICES (&matrix_a, &matrix_b);

  /* And again with a quaternion */
  cogl_framebuffer_identity_matrix (test_fb);
  cogl_framebuffer_rotate_quaternion (test_fb, &quaternion);
  memset (&matrix_b, 0, sizeof (matrix_b));
  cogl_framebuffer_get_modelview_matrix (test_fb, &matrix_b);
  COMPARE_MATRICES (&matrix_a, &matrix_b);

  /* FIXME: This needs a lot more tests! */

  if (cogl_test_verbose ())
    g_print ("OK\n");
}
Пример #16
0
void
mai_node_draw_recursive (MaiNode *self)
{
  CoglMatrix initial_mtx;
  cogl_matrix_init_identity (&initial_mtx);
  cogl_set_modelview_matrix (&initial_mtx);

  cogl_set_source_color4ub ('\x1', '\x1', '\xFF', 255);
  cogl_set_source_texture (g_testtex);
  cogl_ortho (0, 64, 0, 64, -1, 1);

  cogl_matrix_translate (&initial_mtx, 20.0f, 20.0f, 0.0f);
  cogl_matrix_scale (&initial_mtx, 5.0f, 5.0f, 1.0f);
  cogl_matrix_rotate(&initial_mtx, -90.0f, 1.0f, 0.0f, 0.0f);

  _mai_node_draw_recursive (self, &initial_mtx);

  cogl_flush ();
}
Пример #17
0
static void
mx_deform_bow_tie_texture_vflip (ClutterTexture *texture)
{
  CoglHandle material;

  material = clutter_texture_get_cogl_material (texture);

  if (material)
    {
      CoglMatrix matrix;
      cogl_matrix_init_identity (&matrix);

      /* Vflip */
      cogl_matrix_scale (&matrix, 1.f, -1.f, 1.f);
      cogl_matrix_translate (&matrix, 0.f, 1.f, 0.f);

      cogl_material_set_layer_matrix (material, 0, &matrix);
    }
}
Пример #18
0
/* Update view depending on scrollbar values */
static void _xfdashboard_viewpad_update_view_viewport(XfdashboardViewpad *self)
{
	XfdashboardViewpadPrivate	*priv;
	ClutterMatrix				transform;
	gfloat						x, y, w, h;

	g_return_if_fail(XFDASHBOARD_IS_VIEWPAD(self));

	priv=self->priv;

	/* Check for active view */
	if(priv->activeView==NULL)
	{
		g_warning(_("Cannot update viewport of view because no one is active"));
		return;
	}

	/* Get offset from scrollbars and view size from clipping */
	if(clutter_actor_has_clip(CLUTTER_ACTOR(priv->activeView)))
	{
		clutter_actor_get_clip(CLUTTER_ACTOR(priv->activeView), &x, &y, &w, &h);
	}
		else
		{
 			x=y=0.0f;
			clutter_actor_get_size(CLUTTER_ACTOR(priv->activeView), &w, &h);
		}

	/* To avoid blur convert float to ints (virtually) */
	x=ceil(x);
	y=ceil(y);
	w=ceil(w);
	h=ceil(h);

	/* Set transformation (offset) */
	cogl_matrix_init_identity(&transform);
	cogl_matrix_translate(&transform, -x, -y, 0.0f);
	clutter_actor_set_transform(CLUTTER_ACTOR(priv->activeView), &transform);

	/* Set new clipping */
	clutter_actor_set_clip(CLUTTER_ACTOR(priv->activeView), x, y, w, h);
}
Пример #19
0
void
_cogl_matrix_stack_get (CoglMatrixStack *stack,
                        CoglMatrix      *matrix)
{
  CoglMatrixState *state;

  state = _cogl_matrix_stack_top (stack);

  /* NB: identity matrices are lazily initialized because we can often avoid
   * initializing them at all if nothing is pushed on top of them since we
   * load them using glLoadIdentity()
   *
   * The Cogl journal typically loads an identiy matrix because it performs
   * software transformations, which is why we have optimized this case.
   */
  if (state->is_identity)
    cogl_matrix_init_identity (matrix);
  else
    *matrix = state->matrix;
}
Пример #20
0
void
_clutter_paint_volume_transform_relative (ClutterPaintVolume *pv,
                                          ClutterActor *relative_to_ancestor)
{
  CoglMatrix matrix;
  ClutterActor *actor;

  actor = pv->actor;

  g_return_if_fail (actor != NULL);

  _clutter_paint_volume_set_reference_actor (pv, relative_to_ancestor);

  cogl_matrix_init_identity (&matrix);
  _clutter_actor_apply_relative_transformation_matrix (actor,
                                                       relative_to_ancestor,
                                                      &matrix);

  _clutter_paint_volume_transform (pv, &matrix);
}
Пример #21
0
void
cogl_matrix_stack_perspective (CoglMatrixStack *stack,
                                float fov_y,
                                float aspect,
                                float z_near,
                                float z_far)
{
  CoglMatrixEntryLoad *entry;

  entry =
    _cogl_matrix_stack_push_replacement_entry (stack,
                                               COGL_MATRIX_OP_LOAD);

  entry->matrix =
    _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);

  cogl_matrix_init_identity (entry->matrix);
  cogl_matrix_perspective (entry->matrix,
                           fov_y, aspect, z_near, z_far);
}
Пример #22
0
RutTransform *
rut_transform_new (RutContext *ctx)
{
    RutTransform *transform = g_slice_new (RutTransform);
    static CoglBool initialized = FALSE;

    if (initialized == FALSE)
    {
        _rut_transform_init_type ();
        initialized = TRUE;
    }

    rut_object_init (&transform->_parent, &rut_transform_type);

    transform->ref_count = 1;

    rut_graphable_init (transform);

    cogl_matrix_init_identity (&transform->matrix);

    return transform;
}
Пример #23
0
static void
setup_orthographic_modelview (void)
{
  CoglMatrix matrix;
  int fb_width = cogl_framebuffer_get_width (test_fb);
  int fb_height = cogl_framebuffer_get_height (test_fb);

  /* Set up a non-identity modelview matrix. When the journal is
   * flushed it will usually flush the identity matrix. Using the
   * non-default matrix ensures that we test that Cogl restores the
   * matrix we asked for. The matrix sets up an orthographic transform
   * in the modelview matrix */

  cogl_matrix_init_identity (&matrix);
  cogl_matrix_orthographic (&matrix,
                            0.0f, 0.0f, /* x_1 y_1 */
                            fb_width,
                            fb_height,
                            -1.0f, /* nearval */
                            1.0f /* farval */);
  cogl_framebuffer_set_modelview_matrix (test_fb, &matrix);
}
Пример #24
0
void
cogl_matrix_stack_orthographic (CoglMatrixStack *stack,
                                 float x_1,
                                 float y_1,
                                 float x_2,
                                 float y_2,
                                 float near,
                                 float far)
{
  CoglMatrixEntryLoad *entry;

  entry =
    _cogl_matrix_stack_push_replacement_entry (stack,
                                               COGL_MATRIX_OP_LOAD);

  entry->matrix =
    _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);

  cogl_matrix_init_identity (entry->matrix);
  cogl_matrix_orthographic (entry->matrix,
                            x_1, y_1, x_2, y_2, near, far);
}
Пример #25
0
void
cogl_matrix_stack_frustum (CoglMatrixStack *stack,
                            float left,
                            float right,
                            float bottom,
                            float top,
                            float z_near,
                            float z_far)
{
  CoglMatrixEntryLoad *entry;

  entry =
    _cogl_matrix_stack_push_replacement_entry (stack,
                                               COGL_MATRIX_OP_LOAD);

  entry->matrix =
    _cogl_magazine_chunk_alloc (cogl_matrix_stack_matrices_magazine);

  cogl_matrix_init_identity (entry->matrix);
  cogl_matrix_frustum (entry->matrix,
                       left, right, bottom, top,
                       z_near, z_far);
}
Пример #26
0
void
_clutter_paint_volume_get_stage_paint_box (ClutterPaintVolume *pv,
                                           ClutterStage *stage,
                                           ClutterActorBox *box)
{
  ClutterPaintVolume projected_pv;
  CoglMatrix modelview;
  CoglMatrix projection;
  float viewport[4];

  _clutter_paint_volume_copy_static (pv, &projected_pv);

  cogl_matrix_init_identity (&modelview);

  /* If the paint volume isn't already in eye coordinates... */
  if (pv->actor)
    _clutter_actor_apply_relative_transformation_matrix (pv->actor, NULL,
                                                         &modelview);

  _clutter_stage_get_projection_matrix (stage, &projection);
  _clutter_stage_get_viewport (stage,
                               &viewport[0],
                               &viewport[1],
                               &viewport[2],
                               &viewport[3]);

  _clutter_paint_volume_project (&projected_pv,
                                 &modelview,
                                 &projection,
                                 viewport);

  _clutter_paint_volume_get_bounding_box (&projected_pv, box);

  _clutter_actor_box_enlarge_for_effects (box);

  clutter_paint_volume_free (&projected_pv);
}
Пример #27
0
static void
_clutter_stage_wayland_repair_dirty(ClutterStageWayland *stage_wayland,
				       ClutterStage     *stage)
{
  CoglMaterial *outline = NULL;
  CoglHandle vbo;
  float vertices[8], texcoords[8];
  CoglMatrix modelview;
  cairo_region_t *dirty;
  cairo_rectangle_int_t rect;
  int i, count;
  float width, height;

  dirty = stage_wayland->back_buffer->dirty_region;
  stage_wayland->back_buffer->dirty_region = NULL;
  cairo_region_subtract (dirty, stage_wayland->repaint_region);
  width = stage_wayland->allocation.width;
  height = stage_wayland->allocation.height;
  
  /* If this is the first time we render, there is no front buffer to
   * copy back from, but then the dirty region not covered by the
   * repaint should be empty, because we repaint the entire stage.
   *
   * assert(stage_wayland->front_buffer != NULL) ||
   *   cairo_region_is_empty(dirty);
   *
   * FIXME: in test-rotate, the stage never queues a full repaint
   * initially, it's restricted to the paint box of it's rotating
   * children.
   */

  if (!stage_wayland->front_buffer)
    return;

  outline = cogl_material_new ();
  cogl_material_set_layer (outline, 0, stage_wayland->front_buffer->tex);
  count = cairo_region_num_rectangles (dirty);

  for (i = 0; i < count; i++)
    {
      cairo_region_get_rectangle (dirty, i, &rect);
      vbo = cogl_vertex_buffer_new (4);

      vertices[0] = rect.x - 1;
      vertices[1] = rect.y - 1;
      vertices[2] = rect.x + rect.width + 1;
      vertices[3] = rect.y - 1;
      vertices[4] = rect.x + rect.width + 1;
      vertices[5] = rect.y + rect.height + 1;
      vertices[6] = rect.x - 1;
      vertices[7] = rect.y + rect.height + 1;

      cogl_vertex_buffer_add (vbo,
			      "gl_Vertex",
			      2, /* n_components */
			      COGL_ATTRIBUTE_TYPE_FLOAT,
			      FALSE, /* normalized */
			      0, /* stride */
			      vertices);

      texcoords[0] = vertices[0] / width;
      texcoords[1] = vertices[1] / height;
      texcoords[2] = vertices[2] / width;
      texcoords[3] = vertices[3] / height;
      texcoords[4] = vertices[4] / width;
      texcoords[5] = vertices[5] / height;
      texcoords[6] = vertices[6] / width;
      texcoords[7] = vertices[7] / height;

      cogl_vertex_buffer_add (vbo,
			      "gl_MultiTexCoord0",
			      2, /* n_components */
			      COGL_ATTRIBUTE_TYPE_FLOAT,
			      FALSE, /* normalized */
			      0, /* stride */
			      texcoords);

      cogl_vertex_buffer_submit (vbo);

      cogl_push_matrix ();
      cogl_matrix_init_identity (&modelview);
      _clutter_actor_apply_modelview_transform (CLUTTER_ACTOR (stage),
						&modelview);
      cogl_set_modelview_matrix (&modelview);
      cogl_set_source (outline);
      cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_TRIANGLE_FAN,
			       0 , 4);
      cogl_pop_matrix ();
      cogl_object_unref (vbo);
    }

  cairo_region_destroy (dirty);
}
Пример #28
0
G_MODULE_EXPORT int
test_cogl_multitexture_main (int argc, char *argv[])
{
  GError            *error = NULL;
  ClutterActor	    *stage;
  ClutterColor       stage_color = { 0x61, 0x56, 0x56, 0xff };
  TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
  gfloat             stage_w, stage_h;
  gchar            **files;
  gfloat             tex_coords[] =
    {
    /* tx1  ty1  tx2  ty2 */
         0,   0,   1,   1,
         0,   0,   1,   1,
         0,   0,   1,   1
    };

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  stage = clutter_stage_new ();
  clutter_actor_get_size (stage, &stage_w, &stage_h);

  clutter_stage_set_title (CLUTTER_STAGE (stage), "Cogl: Multi-texturing");
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);

  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  /* We create a non-descript actor that we know doesn't have a
   * default paint handler, so that we can easily control
   * painting in a paint signal handler, without having to
   * sub-class anything etc. */
  state->group = clutter_group_new ();
  clutter_actor_set_position (state->group, stage_w / 2, stage_h / 2);
  g_signal_connect (state->group, "paint",
		    G_CALLBACK(material_rectangle_paint), state);

  files = g_new (gchar*, 4);
  files[0] = g_build_filename (TESTS_DATADIR, "redhand_alpha.png", NULL);
  files[1] = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
  files[2] = g_build_filename (TESTS_DATADIR, "light0.png", NULL);
  files[3] = NULL;

  state->alpha_tex =
    cogl_texture_new_from_file (files[0],
                                COGL_TEXTURE_NO_SLICING,
				COGL_PIXEL_FORMAT_ANY,
				&error);
  if (!state->alpha_tex)
    g_critical ("Failed to load redhand_alpha.png: %s", error->message);

  state->redhand_tex =
    cogl_texture_new_from_file (files[1],
                                COGL_TEXTURE_NO_SLICING,
				COGL_PIXEL_FORMAT_ANY,
				&error);
  if (!state->redhand_tex)
    g_critical ("Failed to load redhand.png: %s", error->message);

  state->light_tex0 =
    cogl_texture_new_from_file (files[2],
                                COGL_TEXTURE_NO_SLICING,
				COGL_PIXEL_FORMAT_ANY,
				&error);
  if (!state->light_tex0)
    g_critical ("Failed to load light0.png: %s", error->message);

  state->light_tex1 =
    cogl_texture_new_from_file (files[2],
                                COGL_TEXTURE_NO_SLICING,
				COGL_PIXEL_FORMAT_ANY,
				&error);
  if (!state->light_tex1)
    g_critical ("Failed to load light0.png: %s", error->message);

  g_strfreev (files);

  state->material0 = cogl_material_new ();
  cogl_material_set_layer (state->material0, 0, state->alpha_tex);
  cogl_material_set_layer (state->material0, 1, state->redhand_tex);
  cogl_material_set_layer (state->material0, 2, state->light_tex0);

  state->material1 = cogl_material_new ();
  cogl_material_set_layer (state->material1, 0, state->alpha_tex);
  cogl_material_set_layer (state->material1, 1, state->redhand_tex);
  cogl_material_set_layer (state->material1, 2, state->light_tex1);

  state->tex_coords = tex_coords;

  cogl_matrix_init_identity (&state->tex_matrix0);
  cogl_matrix_init_identity (&state->tex_matrix1);
  cogl_matrix_init_identity (&state->rot_matrix0);
  cogl_matrix_init_identity (&state->rot_matrix1);

  cogl_matrix_translate (&state->rot_matrix0, 0.5, 0.5, 0);
  cogl_matrix_rotate (&state->rot_matrix0, 10.0, 0, 0, 1.0);
  cogl_matrix_translate (&state->rot_matrix0, -0.5, -0.5, 0);

  cogl_matrix_translate (&state->rot_matrix1, 0.5, 0.5, 0);
  cogl_matrix_rotate (&state->rot_matrix1, -10.0, 0, 0, 1.0);
  cogl_matrix_translate (&state->rot_matrix1, -0.5, -0.5, 0);

  clutter_actor_set_anchor_point (state->group, 86, 125);
  clutter_container_add_actor (CLUTTER_CONTAINER(stage),
			       state->group);

  state->timeline = clutter_timeline_new (2812);

  g_signal_connect (state->timeline, "new-frame", G_CALLBACK (frame_cb), state);

  clutter_actor_animate_with_timeline (state->group,
                                       CLUTTER_LINEAR,
                                       state->timeline,
                                       "rotation-angle-y", 30.0,
                                       "signal-after::completed",
                                       animation_completed_cb, state,
                                       NULL);

  /* start the timeline and thus the animations */
  clutter_timeline_start (state->timeline);

  clutter_actor_show_all (stage);

  clutter_main();

  cogl_handle_unref (state->material1);
  cogl_handle_unref (state->material0);
  cogl_handle_unref (state->alpha_tex);
  cogl_handle_unref (state->redhand_tex);
  cogl_handle_unref (state->light_tex0);
  cogl_handle_unref (state->light_tex1);
  g_free (state);

  return 0;
}
Пример #29
0
static RutShapeModel *
shape_model_new (RutContext *ctx,
                 CoglBool shaped,
                 float tex_width,
                 float tex_height)
{
  RutShapeModel *shape_model = g_slice_new (RutShapeModel);
  RutBuffer *buffer = rut_buffer_new (sizeof (CoglVertexP3) * 6);
  RutMesh *pick_mesh = rut_mesh_new_from_buffer_p3 (COGL_VERTICES_MODE_TRIANGLES,
                                                    6,
                                                    buffer);
  CoglVertexP3 *pick_vertices = (CoglVertexP3 *)buffer->data;
  CoglMatrix matrix;
  float tex_aspect;
  float size_x;
  float size_y;
  float half_size_x;
  float half_size_y;
  float geom_size_x;
  float geom_size_y;
  float half_geom_size_x;
  float half_geom_size_y;

  rut_object_init (&shape_model->_parent, &rut_shape_model_type);

  shape_model->ref_count = 1;

  if (shaped)
    {
      /* In this case we are using a shape mask texture which is has a
       * square size and is padded with transparent pixels to provide
       * antialiasing. The shape mask is half the size of the texture
       * itself so we make the geometry twice as large to compensate.
       */
      size_x = MIN (tex_width, tex_height);
      size_y = size_x;
      geom_size_x = size_x * 2.0;
      geom_size_y = geom_size_x;
    }
  else
    {
      size_x = tex_width;
      size_y = tex_height;
      geom_size_x = tex_width;
      geom_size_y = tex_height;
    }

  half_size_x = size_x / 2.0;
  half_size_y = size_y / 2.0;
  half_geom_size_x = geom_size_x / 2.0;
  half_geom_size_y = geom_size_y / 2.0;

    {
      int n_vertices;
      int i;

      VertexP2T2T2 vertices[] =
        {
          { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 },
          { -half_geom_size_x,  half_geom_size_y, 0, 1, 0, 1 },
          {  half_geom_size_x,  half_geom_size_y, 1, 1, 1, 1 },

          { -half_geom_size_x, -half_geom_size_y, 0, 0, 0, 0 },
          {  half_geom_size_x,  half_geom_size_y, 1, 1, 1, 1 },
          {  half_geom_size_x, -half_geom_size_y, 1, 0, 1, 0 },
        };

      cogl_matrix_init_identity (&matrix);
      tex_aspect = (float)tex_width / (float)tex_height;

      if (shaped)
        {
          float s_scale, t_scale;
          float s0, t0;

          /* NB: The circle mask texture has a centered circle that is
           * half the width of the texture itself. We want the primary
           * texture to be mapped to this center circle. */

          s_scale = 2;
          t_scale = 2;

          if (tex_aspect < 1) /* taller than it is wide */
            t_scale *= tex_aspect;
          else /* wider than it is tall */
            {
              float inverse_aspect = 1.0f / tex_aspect;
              s_scale *= inverse_aspect;
            }

          s0 = 0.5 - (s_scale / 2.0);
          t0 = 0.5 - (t_scale / 2.0);

          cogl_matrix_translate (&matrix, s0, t0, 0);
          cogl_matrix_scale (&matrix, s_scale, t_scale, 1);
        }

      n_vertices = sizeof (vertices) / sizeof (VertexP2T2T2);
      for (i = 0; i < n_vertices; i++)
        {
          float z = 0, w = 1;

          cogl_matrix_transform_point (&matrix,
                                       &vertices[i].s1,
                                       &vertices[i].t1,
                                       &z,
                                       &w);
#ifdef MESA_CONST_ATTRIB_BUG_WORKAROUND
          vertices[i].Nx = 0;
          vertices[i].Ny = 0;
          vertices[i].Nz = 1;

          vertices[i].Tx = 1;
          vertices[i].Ty = 0;
          vertices[i].Tz = 0;
#endif
        }

      shape_model->primitive =
        primitive_new_p2t2t2 (ctx->cogl_context,
                              COGL_VERTICES_MODE_TRIANGLES,
                              n_vertices,
                              vertices);
    }

  shape_model->shape_texture = cogl_object_ref (ctx->circle_texture);

  pick_vertices[0].x = -half_size_x;
  pick_vertices[0].y = -half_size_y;
  pick_vertices[1].x = -half_size_x;
  pick_vertices[1].y = half_size_y;
  pick_vertices[2].x = half_size_x;
  pick_vertices[2].y = half_size_y;
  pick_vertices[3] = pick_vertices[0];
  pick_vertices[4] = pick_vertices[2];
  pick_vertices[5].x = half_size_x;
  pick_vertices[5].y = -half_size_y;

  shape_model->pick_mesh = pick_mesh;


  return shape_model;
}
Пример #30
0
/* For reference: There was some deliberation over whether to have a
 * constructor that could throw an exception but looking at standard
 * practices with several high level OO languages including python, C++,
 * C# Java and Ruby they all support exceptions in constructors and the
 * general consensus appears to be that throwing an exception is neater
 * than successfully constructing with an internal error status that
 * would then have to be explicitly checked via some form of ::is_ok()
 * method.
 */
CoglContext *
cogl_context_new (CoglDisplay *display,
                  CoglError **error)
{
  CoglContext *context;
  uint8_t white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
  CoglBitmap *white_pixel_bitmap;
  const CoglWinsysVtable *winsys;
  int i;
  CoglError *internal_error = NULL;

  _cogl_init ();

#ifdef COGL_ENABLE_PROFILE
  /* We need to be absolutely sure that uprof has been initialized
   * before calling _cogl_uprof_init. uprof_init (NULL, NULL)
   * will be a NOP if it has been initialized but it will also
   * mean subsequent parsing of the UProf GOptionGroup will have no
   * affect.
   *
   * Sadly GOptionGroup based library initialization is extremely
   * fragile by design because GOptionGroups have no notion of
   * dependencies and so the order things are initialized isn't
   * currently under tight control.
   */
  uprof_init (NULL, NULL);
  _cogl_uprof_init ();
#endif

  /* Allocate context memory */
  context = g_malloc0 (sizeof (CoglContext));

  /* Convert the context into an object immediately in case any of the
     code below wants to verify that the context pointer is a valid
     object */
  _cogl_context_object_new (context);

  /* XXX: Gross hack!
   * Currently everything in Cogl just assumes there is a default
   * context which it can access via _COGL_GET_CONTEXT() including
   * code used to construct a CoglContext. Until all of that code
   * has been updated to take an explicit context argument we have
   * to immediately make our pointer the default context.
   */
  _cogl_context = context;

  /* Init default values */
  memset (context->features, 0, sizeof (context->features));
  context->feature_flags = 0;
  memset (context->private_features, 0, sizeof (context->private_features));

  context->rectangle_state = COGL_WINSYS_RECTANGLE_STATE_UNKNOWN;

  memset (context->winsys_features, 0, sizeof (context->winsys_features));

  if (!display)
    {
      CoglRenderer *renderer = cogl_renderer_new ();
      if (!cogl_renderer_connect (renderer, error))
        {
          g_free (context);
          return NULL;
        }

      display = cogl_display_new (renderer, NULL);
      cogl_object_unref(renderer);
    }
  else
    cogl_object_ref (display);

  if (!cogl_display_setup (display, error))
    {
      cogl_object_unref (display);
      g_free (context);
      return NULL;
    }

  context->display = display;

  /* This is duplicated data, but it's much more convenient to have
     the driver attached to the context and the value is accessed a
     lot throughout Cogl */
  context->driver = display->renderer->driver;

  /* Again this is duplicated data, but it convenient to be able
   * access these from the context. */
  context->driver_vtable = display->renderer->driver_vtable;
  context->texture_driver = display->renderer->texture_driver;

  for (i = 0; i < G_N_ELEMENTS (context->private_features); i++)
    context->private_features[i] |= display->renderer->private_features[i];

  winsys = _cogl_context_get_winsys (context);
  if (!winsys->context_init (context, error))
    {
      cogl_object_unref (display);
      g_free (context);
      return NULL;
    }

  context->attribute_name_states_hash =
    g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
  context->attribute_name_index_map = NULL;
  context->n_attribute_names = 0;

  /* The "cogl_color_in" attribute needs a deterministic name_index
   * so we make sure it's the first attribute name we register */
  _cogl_attribute_register_attribute_name (context, "cogl_color_in");


  context->uniform_names =
    g_ptr_array_new_with_free_func ((GDestroyNotify) g_free);
  context->uniform_name_hash = g_hash_table_new (g_str_hash, g_str_equal);
  context->n_uniform_names = 0;

  /* Initialise the driver specific state */
  _cogl_init_feature_overrides (context);

  /* XXX: ONGOING BUG: Intel viewport scissor
   *
   * Intel gen6 drivers don't currently correctly handle offset
   * viewports, since primitives aren't clipped within the bounds of
   * the viewport.  To workaround this we push our own clip for the
   * viewport that will use scissoring to ensure we clip as expected.
   *
   * TODO: file a bug upstream!
   */
  if (context->gpu.driver_package == COGL_GPU_INFO_DRIVER_PACKAGE_MESA &&
      context->gpu.architecture == COGL_GPU_INFO_ARCHITECTURE_SANDYBRIDGE &&
      !getenv ("COGL_DISABLE_INTEL_VIEWPORT_SCISSORT_WORKAROUND"))
    context->needs_viewport_scissor_workaround = TRUE;
  else
    context->needs_viewport_scissor_workaround = FALSE;

  context->sampler_cache = _cogl_sampler_cache_new (context);

  _cogl_pipeline_init_default_pipeline ();
  _cogl_pipeline_init_default_layers ();
  _cogl_pipeline_init_state_hash_functions ();
  _cogl_pipeline_init_layer_state_hash_functions ();

  context->current_clip_stack_valid = FALSE;
  context->current_clip_stack = NULL;

  context->legacy_backface_culling_enabled = FALSE;

  cogl_matrix_init_identity (&context->identity_matrix);
  cogl_matrix_init_identity (&context->y_flip_matrix);
  cogl_matrix_scale (&context->y_flip_matrix, 1, -1, 1);

  context->flushed_matrix_mode = COGL_MATRIX_MODELVIEW;

  context->texture_units =
    g_array_new (FALSE, FALSE, sizeof (CoglTextureUnit));

  if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_ANY_GL))
    {
      /* See cogl-pipeline.c for more details about why we leave texture unit 1
       * active by default... */
      context->active_texture_unit = 1;
      GE (context, glActiveTexture (GL_TEXTURE1));
    }

  context->legacy_fog_state.enabled = FALSE;

  context->opaque_color_pipeline = cogl_pipeline_new (context);
  context->blended_color_pipeline = cogl_pipeline_new (context);
  context->texture_pipeline = cogl_pipeline_new (context);
  context->codegen_header_buffer = g_string_new ("");
  context->codegen_source_buffer = g_string_new ("");
  context->codegen_boilerplate_buffer = g_string_new ("");
  context->source_stack = NULL;

  context->legacy_state_set = 0;

  context->default_gl_texture_2d_tex = NULL;
  context->default_gl_texture_3d_tex = NULL;
  context->default_gl_texture_rect_tex = NULL;

  context->framebuffers = NULL;
  context->current_draw_buffer = NULL;
  context->current_read_buffer = NULL;
  context->current_draw_buffer_state_flushed = 0;
  context->current_draw_buffer_changes = COGL_FRAMEBUFFER_STATE_ALL;

  context->swap_callback_closures =
    g_hash_table_new (g_direct_hash, g_direct_equal);

  _cogl_list_init (&context->onscreen_events_queue);
  _cogl_list_init (&context->onscreen_dirty_queue);

  g_queue_init (&context->gles2_context_stack);

  context->journal_flush_attributes_array =
    g_array_new (TRUE, FALSE, sizeof (CoglAttribute *));
  context->journal_clip_bounds = NULL;

  context->polygon_vertices = g_array_new (FALSE, FALSE, sizeof (float));

  context->current_pipeline = NULL;
  context->current_pipeline_changes_since_flush = 0;
  context->current_pipeline_with_color_attrib = FALSE;

  _cogl_bitmask_init (&context->enabled_builtin_attributes);
  _cogl_bitmask_init (&context->enable_builtin_attributes_tmp);
  _cogl_bitmask_init (&context->enabled_texcoord_attributes);
  _cogl_bitmask_init (&context->enable_texcoord_attributes_tmp);
  _cogl_bitmask_init (&context->enabled_custom_attributes);
  _cogl_bitmask_init (&context->enable_custom_attributes_tmp);
  _cogl_bitmask_init (&context->changed_bits_tmp);

  context->max_texture_units = -1;
  context->max_activateable_texture_units = -1;

  context->current_fragment_program_type = COGL_PIPELINE_PROGRAM_TYPE_GLSL;
  context->current_vertex_program_type = COGL_PIPELINE_PROGRAM_TYPE_GLSL;
  context->current_gl_program = 0;

  context->current_gl_dither_enabled = TRUE;
  context->current_gl_color_mask = COGL_COLOR_MASK_ALL;

  context->gl_blend_enable_cache = FALSE;

  context->depth_test_enabled_cache = FALSE;
  context->depth_test_function_cache = COGL_DEPTH_TEST_FUNCTION_LESS;
  context->depth_writing_enabled_cache = TRUE;
  context->depth_range_near_cache = 0;
  context->depth_range_far_cache = 1;

  context->legacy_depth_test_enabled = FALSE;

  context->pipeline_cache = _cogl_pipeline_cache_new ();

  for (i = 0; i < COGL_BUFFER_BIND_TARGET_COUNT; i++)
    context->current_buffer[i] = NULL;

  context->window_buffer = NULL;
  context->framebuffer_stack = _cogl_create_framebuffer_stack ();

  /* XXX: In this case the Clutter backend is still responsible for
   * the OpenGL binding API and for creating onscreen framebuffers and
   * so we have to add a dummy framebuffer to represent the backend
   * owned window... */
  if (_cogl_context_get_winsys (context) == _cogl_winsys_stub_get_vtable ())
    {
      CoglOnscreen *window = _cogl_onscreen_new ();
      cogl_set_framebuffer (COGL_FRAMEBUFFER (window));
      cogl_object_unref (COGL_FRAMEBUFFER (window));
    }

  context->current_path = NULL;
  context->stencil_pipeline = cogl_pipeline_new (context);

  context->in_begin_gl_block = FALSE;

  context->quad_buffer_indices_byte = NULL;
  context->quad_buffer_indices = NULL;
  context->quad_buffer_indices_len = 0;

  context->rectangle_byte_indices = NULL;
  context->rectangle_short_indices = NULL;
  context->rectangle_short_indices_len = 0;

  context->texture_download_pipeline = NULL;
  context->blit_texture_pipeline = NULL;

#ifdef HAVE_COGL_GL
  if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_ALPHA_TEST))
    /* The default for GL_ALPHA_TEST is to always pass which is equivalent to
     * the test being disabled therefore we assume that for all drivers there
     * will be no performance impact if we always leave the test enabled which
     * makes things a bit simpler for us. Under GLES2 the alpha test is
     * implemented in the fragment shader so there is no enable for it
     */
    GE (context, glEnable (GL_ALPHA_TEST));

  if ((context->driver == COGL_DRIVER_GL3))
    {
      GLuint vertex_array;

      /* In a forward compatible context, GL 3 doesn't support rendering
       * using the default vertex array object. Cogl doesn't use vertex
       * array objects yet so for now we just create a dummy array
       * object that we will use as our own default object. Eventually
       * it could be good to attach the vertex array objects to
       * CoglPrimitives */
      context->glGenVertexArrays (1, &vertex_array);
      context->glBindVertexArray (vertex_array);
    }
#endif

  context->current_modelview_entry = NULL;
  context->current_projection_entry = NULL;
  _cogl_matrix_entry_identity_init (&context->identity_entry);
  _cogl_matrix_entry_cache_init (&context->builtin_flushed_projection);
  _cogl_matrix_entry_cache_init (&context->builtin_flushed_modelview);

  /* Create default textures used for fall backs */
  context->default_gl_texture_2d_tex =
    cogl_texture_2d_new_from_data (context,
                                   1, 1,
                                   COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                   0, /* rowstride */
                                   white_pixel,
                                   NULL); /* abort on error */

  /* If 3D or rectangle textures aren't supported then these will
   * return errors that we can simply ignore. */
  internal_error = NULL;
  context->default_gl_texture_3d_tex =
    cogl_texture_3d_new_from_data (context,
                                   1, 1, 1, /* width, height, depth */
                                   COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                   0, /* rowstride */
                                   0, /* image stride */
                                   white_pixel,
                                   &internal_error);
  if (internal_error)
    cogl_error_free (internal_error);

  /* TODO: add cogl_texture_rectangle_new_from_data() */
  white_pixel_bitmap =
    cogl_bitmap_new_for_data (context,
                              1, 1, /* width/height */
                              COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                              4, /* rowstride */
                              white_pixel);

  internal_error = NULL;
  context->default_gl_texture_rect_tex =
    cogl_texture_rectangle_new_from_bitmap (white_pixel_bitmap);

  /* XXX: we need to allocate the texture now because the white_pixel
   * data is on the stack */
  cogl_texture_allocate (COGL_TEXTURE (context->default_gl_texture_rect_tex),
                         &internal_error);
  if (internal_error)
    cogl_error_free (internal_error);

  cogl_object_unref (white_pixel_bitmap);

  cogl_push_source (context->opaque_color_pipeline);

  context->atlases = NULL;
  g_hook_list_init (&context->atlas_reorganize_callbacks, sizeof (GHook));

  context->buffer_map_fallback_array = g_byte_array_new ();
  context->buffer_map_fallback_in_use = FALSE;

  /* As far as I can tell, GL_POINT_SPRITE doesn't have any effect
     unless GL_COORD_REPLACE is enabled for an individual layer.
     Therefore it seems like it should be ok to just leave it enabled
     all the time instead of having to have a set property on each
     pipeline to track whether any layers have point sprite coords
     enabled. We don't need to do this for GL3 or GLES2 because point
     sprites are handled using a builtin varying in the shader. */
  if (_cogl_has_private_feature (context, COGL_PRIVATE_FEATURE_GL_FIXED) &&
      cogl_has_feature (context, COGL_FEATURE_ID_POINT_SPRITE))
    GE (context, glEnable (GL_POINT_SPRITE));

  _cogl_list_init (&context->fences);

  return context;
}