Exemplo n.º 1
0
/**
 * _st_create_texture_material:
 * @src_texture: The CoglTexture for the material
 *
 * Creates a simple material which contains the given texture as a
 * single layer.
 */
CoglHandle
_st_create_texture_material (CoglHandle src_texture)
{
  static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
  CoglHandle material;

  g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
                        COGL_INVALID_HANDLE);

  /* We use a material that has a dummy texture as a base for all
     texture materials. The idea is that only the Cogl texture object
     would be different in the children so it is likely that Cogl will
     be able to share GL programs between all the textures. */
  if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
    {
      static const guint8 white_pixel[] = { 0xff, 0xff, 0xff, 0xff };
      CoglHandle dummy_texture;

      dummy_texture = st_cogl_texture_new_from_data_wrapper (1, 1,
                                                             COGL_TEXTURE_NONE,
                                                             COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                                             COGL_PIXEL_FORMAT_ANY,
                                                             4, white_pixel);

      texture_material_template = cogl_material_new ();
      cogl_material_set_layer (texture_material_template, 0, dummy_texture);
      cogl_handle_unref (dummy_texture);
    }

  material = cogl_material_copy (texture_material_template);

  cogl_material_set_layer (material, 0, src_texture);

  return material;
}
CoglHandle
_st_create_shadow_material (StShadow   *shadow_spec,
                            CoglHandle  src_texture)
{
  static CoglHandle shadow_material_template = COGL_INVALID_HANDLE;

  CoglHandle  material;
  CoglHandle  texture;
  guchar     *pixels_in, *pixels_out;
  gint        width_in, height_in, rowstride_in;
  gint        width_out, height_out, rowstride_out;

  g_return_val_if_fail (shadow_spec != NULL, COGL_INVALID_HANDLE);
  g_return_val_if_fail (src_texture != COGL_INVALID_HANDLE,
                        COGL_INVALID_HANDLE);

  width_in  = cogl_texture_get_width  (src_texture);
  height_in = cogl_texture_get_height (src_texture);
  rowstride_in = (width_in + 3) & ~3;

  pixels_in  = g_malloc0 (rowstride_in * height_in);

  cogl_texture_get_data (src_texture, COGL_PIXEL_FORMAT_A_8,
                         rowstride_in, pixels_in);

  pixels_out = blur_pixels (pixels_in, width_in, height_in, rowstride_in,
                            shadow_spec->blur,
                            &width_out, &height_out, &rowstride_out);
  g_free (pixels_in);

  texture = cogl_texture_new_from_data (width_out,
                                        height_out,
                                        COGL_TEXTURE_NONE,
                                        COGL_PIXEL_FORMAT_A_8,
                                        COGL_PIXEL_FORMAT_A_8,
                                        rowstride_out,
                                        pixels_out);

  g_free (pixels_out);

  if (G_UNLIKELY (shadow_material_template == COGL_INVALID_HANDLE))
    {
      shadow_material_template = cogl_material_new ();

      /* We set up the material to blend the shadow texture with the combine
       * constant, but defer setting the latter until painting, so that we can
       * take the actor's overall opacity into account. */
      cogl_material_set_layer_combine (shadow_material_template, 0,
                                       "RGBA = MODULATE (CONSTANT, TEXTURE[A])",
                                       NULL);
    }

  material = cogl_material_copy (shadow_material_template);

  cogl_material_set_layer (material, 0, texture);

  cogl_handle_unref (texture);

  return material;
}
Exemplo n.º 3
0
/**
 * meta_create_texture_material:
 * @src_texture: (allow-none): texture to use initially for the layer
 *
 * Creates a material with a single layer. Using a common template
 * allows sharing a shader for different uses in Muffin. To share the same
 * shader with all other materials that are just texture plus opacity
 * would require Cogl fixes.
 * (See http://bugzilla.clutter-project.org/show_bug.cgi?id=2425)
 *
 * Return value: (transfer full): a newly created Cogl material
 */
CoglHandle
meta_create_texture_material (CoglHandle src_texture)
{
  static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
  CoglHandle material;

  /* We use a material that has a dummy texture as a base for all
     texture materials. The idea is that only the Cogl texture object
     would be different in the children so it is likely that Cogl will
     be able to share GL programs between all the textures. */
  if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
    {
      CoglHandle dummy_texture;

      dummy_texture = meta_create_color_texture_4ub (0xff, 0xff, 0xff, 0xff,
                                                     COGL_TEXTURE_NONE);

      texture_material_template = cogl_material_new ();
      cogl_material_set_layer (texture_material_template, 0, dummy_texture);
      cogl_handle_unref (dummy_texture);
    }

  material = cogl_material_copy (texture_material_template);

  if (src_texture != COGL_INVALID_HANDLE)
    cogl_material_set_layer (material, 0, src_texture);

  return material;
}
Exemplo n.º 4
0
void
mx_texture_frame_paint_texture (CoglHandle  texture,
                                guint8      opacity,
                                gfloat      top,
                                gfloat      right,
                                gfloat      bottom,
                                gfloat      left,
                                gfloat      width,
                                gfloat      height)
{
  CoglHandle material;

  /* setup the template material */
  if (!template_material)
    template_material = cogl_material_new ();

  /* create the material and apply opacity */
  material = cogl_material_copy (template_material);

  mx_texture_frame_paint_texture_internal (material, texture,
                                           opacity,
                                           top, right,
                                           bottom, left,
                                           width, height);

  cogl_handle_unref (material);
}
Exemplo n.º 5
0
static void
mex_tile_init (MexTile *self)
{
  MexTilePrivate *priv = self->priv = TILE_PRIVATE (self);
  const ClutterColor opaque = { 0x00, 0x00, 0x00, 0x00 };
  ClutterEffect *fade;

  /* create a template material for the header background from which cheap
   * copies can be made for each instance */
  if (G_UNLIKELY (!template_material))
    template_material = cogl_material_new ();

  priv->material = cogl_material_copy (template_material);


  /* layout for primary and secondary labels */
  priv->box_layout = mx_box_layout_new ();
  mx_box_layout_set_spacing (MX_BOX_LAYOUT (priv->box_layout), 12);

  /* add fade effect to the box layout */
  fade = (ClutterEffect*) mx_fade_effect_new ();
  mx_fade_effect_set_border (MX_FADE_EFFECT (fade), 0, 50, 0, 0);
  mx_fade_effect_set_color (MX_FADE_EFFECT (fade), &opaque);
  clutter_actor_add_effect_with_name (priv->box_layout, "fade", fade);
  clutter_actor_meta_set_enabled (CLUTTER_ACTOR_META (fade), TRUE);

  clutter_actor_push_internal (CLUTTER_ACTOR (self));
  clutter_actor_set_parent (priv->box_layout, CLUTTER_ACTOR (self));
  clutter_actor_pop_internal (CLUTTER_ACTOR (self));


  priv->label = clutter_text_new ();
  priv->secondary_label = clutter_text_new ();
  clutter_actor_set_opacity (priv->secondary_label, 128);

  clutter_container_add (CLUTTER_CONTAINER (priv->box_layout), priv->label,
                         priv->secondary_label, NULL);

  priv->header_visible = TRUE;

  priv->timeline = clutter_timeline_new (DURATION);
  priv->important_alpha =
    clutter_alpha_new_full (priv->timeline, CLUTTER_EASE_OUT_QUAD);
  g_signal_connect_object (priv->timeline, "new-frame",
                           G_CALLBACK (mex_tile_important_new_frame_cb), self,
                           0);
  g_signal_connect_object (priv->timeline, "completed",
                           G_CALLBACK (mex_tile_timeline_completed_cb), self,
                           0);

  g_signal_connect (self, "style-changed",
                    G_CALLBACK (mex_tile_style_changed_cb), NULL);

  g_signal_connect (self, "actor-added",
                    G_CALLBACK (mex_tile_actor_added), NULL);
  g_signal_connect (self, "actor-removed",
                    G_CALLBACK (mex_tile_actor_removed), NULL);
}
Exemplo n.º 6
0
static void
glide_image_init (GlideImage *self)
{
  self->priv = GLIDE_IMAGE_GET_PRIVATE (self);
  
  self->priv->material = cogl_material_new ();
  
  cogl_material_set_layer_filters (self->priv->material, 0,
				   COGL_MATERIAL_FILTER_LINEAR_MIPMAP_LINEAR,
				   COGL_MATERIAL_FILTER_LINEAR);
}
Exemplo n.º 7
0
/* XXX: not sure how to keep the frame data on screen during
 * fade out, so just have a solid idle material for now. */
static void
set_idle_material (ClutterGstVideoTexture *video_texture)
{
  CoglColor transparent;
  CoglHandle material;

  cogl_color_init_from_4ub (&transparent, 0, 0, 0, 0);
  material = cogl_material_new ();
  cogl_material_set_color (material, &transparent);
  clutter_gst_video_texture_set_idle_material (video_texture, material);
  cogl_handle_unref (material);
}
Exemplo n.º 8
0
G_MODULE_EXPORT int
test_cogl_shader_arbfp_main (int argc, char *argv[])
{
  ClutterActor *stage;
  char *file;
  GError *error;
  ClutterColor stage_color = { 0x61, 0x64, 0x8c, 0xff };

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

  stage = clutter_stage_new ();

  clutter_stage_set_title (CLUTTER_STAGE (stage), "Assembly Shader Test");
  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);

  file = g_build_filename (TESTS_DATADIR, "redhand.png", NULL);
  error = NULL;
  redhand = cogl_texture_new_from_file (file, 0, COGL_PIXEL_FORMAT_ANY,
                                        &error);
  if (redhand == COGL_INVALID_HANDLE)
    g_error ("image load failed: %s", error->message);

  material = cogl_material_new ();
  cogl_material_set_layer (material, 0, redhand);

  set_shader_num (0);
  g_signal_connect_after (stage, "paint", G_CALLBACK (paint_cb), NULL);

  clutter_actor_set_reactive (stage, TRUE);
  g_signal_connect (stage, "button-release-event",
                    G_CALLBACK (button_release_cb), NULL);
  g_signal_connect (stage, "key-release-event",
                    G_CALLBACK (key_release_cb), NULL);

  g_signal_connect (stage, "delete-event",
                    G_CALLBACK (destroy_window_cb), NULL);

  timeout_id = clutter_threads_add_timeout (1000, timeout_cb, NULL);

  clutter_threads_add_idle (idle_cb, stage);

  clutter_actor_show (stage);

  clutter_main ();

  return EXIT_SUCCESS;
}
Exemplo n.º 9
0
static void
aisleriot_slot_renderer_set_material_for_card (AisleriotSlotRenderer *srend,
                                               CoglHandle tex,
                                               gboolean show_highlight)
{
  AisleriotSlotRendererPrivate *priv = srend->priv;
  guint8 opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (srend));

  if (priv->material == COGL_INVALID_HANDLE)
    priv->material = cogl_material_new ();

  if (show_highlight)
    {
      CoglColor color;

      /* The previous code for drawing the highlight rendered the
         normal card texture and then rendered the card again
         multiplied by the highlight color but with 50%
         transparency. The blend function is alpha*src+(1-alpha*dst)
         where src is effectively the tex times the highlight color
         and the dst is the original tex. Therefore the final color is
         0.5*tex+0.5*tex*highlight which is the same as
         (0.5+highlight/2)*tex. We can precompute that value to avoid
         having to draw the card twice */
      cogl_color_set_from_4ub (&color,
                               MIN (priv->highlight_color.red
                                    / 2 + 128, 0xff),
                               MIN (priv->highlight_color.green
                                    / 2 + 128, 0xff),
                               MIN (priv->highlight_color.blue
                                    / 2 + 128, 0xff),
                               opacity);
      cogl_color_premultiply (&color);
      cogl_material_set_color (priv->material, &color);
    }
  else
    cogl_material_set_color4ub (priv->material,
                                opacity, opacity, opacity, opacity);

  cogl_material_set_layer (priv->material, 0, tex);
  cogl_set_source (priv->material);
}
Exemplo n.º 10
0
int
main (int argc, char **argv)
{
  ClutterActor *stage = stage;
  ClutterActor *side_box;
  ClutterActor *button_box;
  ClutterActor *box;
  ClutterAnimation *anim;
  MashLightSet *light_set;
  MxStyle *style;
  GError *error = NULL;
  Data data;
  int i;

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

  style = mx_style_get_default ();
  if (!mx_style_load_from_file (style, "lights.css",
                                &error))
    {
      g_warning ("Error setting style: %s", error->message);
      g_clear_error (&error);
    }

  stage = clutter_stage_get_default ();
  clutter_actor_set_size (stage, 800, 600);

  side_box = mx_table_new ();
  clutter_actor_set_name (side_box, "side-box");
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), side_box);
  clutter_actor_set_size (side_box, 300,
                          clutter_actor_get_height (stage));
  clutter_actor_set_x (side_box,
                       clutter_actor_get_width (stage)
                       - clutter_actor_get_width (side_box));

  button_box = mx_table_new ();
  mx_table_add_actor (MX_TABLE (side_box), button_box, 0, 0);

  data.notebook = mx_notebook_new ();

  mx_table_add_actor (MX_TABLE (side_box), data.notebook, 1, 0);

  data.model = mash_model_new_from_file (MASH_DATA_NONE,
                                         argc > 1
                                         ? argv[1]
                                         : "suzanne.ply",
                                         &error);
  if (data.model == NULL)
    {
      g_warning ("Error loading model: %s", error->message);
      g_clear_error (&error);
      return 1;
    }

  light_set = mash_light_set_new ();

  box = clutter_box_new (clutter_fixed_layout_new ());

  clutter_actor_set_size (data.model, 400, 400);
  clutter_actor_set_position (data.model, 50.0, 100.0);
  clutter_container_add_actor (CLUTTER_CONTAINER (box), data.model);

  clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);

  g_signal_connect_swapped (box, "paint",
                            G_CALLBACK (cogl_set_depth_test_enabled),
                            GINT_TO_POINTER (TRUE));
  g_signal_connect_data (box, "paint",
                         G_CALLBACK (cogl_set_depth_test_enabled),
                         GINT_TO_POINTER (FALSE), NULL,
                         G_CONNECT_AFTER | G_CONNECT_SWAPPED);

  data.light_marker_material = cogl_material_new ();
  {
    CoglColor color;
    cogl_color_set_from_4ub (&color, 255, 0, 0, 255);
    /* Use the layer state to ignore the vertex color from the shader so
       that the light marker won't itself be lit */
    cogl_material_set_layer_combine_constant (data.light_marker_material, 0,
                                              &color);
    cogl_material_set_layer_combine (data.light_marker_material, 0,
                                     "RGBA = REPLACE(CONSTANT)",
                                     NULL);
  }

  clutter_actor_set_rotation (data.model, CLUTTER_Y_AXIS,
                              0.0f,
                              clutter_actor_get_width (data.model) / 2.0f,
                              0.0f,
                              0.0f);

  anim = clutter_actor_animate (data.model, CLUTTER_LINEAR, 3000,
                                "rotation-angle-y", 360.0f,
                                NULL);
  clutter_animation_set_loop (anim, TRUE);

  for (i = 0; i < N_LIGHTS; i++)
    {
      ClutterActor *table = mx_table_new ();
      ClutterActor *button;
      static ClutterActor *(* constructors[N_LIGHTS]) (void) =
        { mash_directional_light_new,
          mash_point_light_new,
          mash_spot_light_new };
      static const ClutterColor black = { 0, 0, 0, 255 };

      data.lights[i] = constructors[i] ();

      button = mx_button_new_with_label (G_OBJECT_TYPE_NAME (data.lights[i]));
      mx_table_add_actor (MX_TABLE (button_box), button, i, 0);

      /* Default to disable all of the lights */
      g_object_set (data.lights[i],
                    "ambient", &black,
                    "diffuse", &black,
                    "specular", &black,
                    NULL);

      data.notebook_buttons[i] = button;

      clutter_container_add_actor (CLUTTER_CONTAINER (box), data.lights[i]);
      mash_light_set_add_light (light_set, MASH_LIGHT (data.lights[i]));

      add_color_prop (table, "ambient light",
                      G_OBJECT (data.lights[i]), "ambient");
      add_color_prop (table, "diffuse light",
                      G_OBJECT (data.lights[i]), "diffuse");
      add_color_prop (table, "specular light",
                      G_OBJECT (data.lights[i]), "specular");

      if (MASH_IS_POINT_LIGHT (data.lights[i]))
        {
          add_float_prop (table, "constant attenuation",
                          G_OBJECT (data.lights[i]), "constant-attenuation",
                          0.0f, 10.0f);
          add_float_prop (table, "linear attenuation",
                          G_OBJECT (data.lights[i]), "linear-attenuation",
                          0.0f, 10.0f);
          add_float_prop (table, "quadratic attenuation",
                          G_OBJECT (data.lights[i]), "quadratic-attenuation",
                          0.0f, 10.0f);
        }

      if (MASH_IS_SPOT_LIGHT (data.lights[i]))
        {
          clutter_actor_set_x (data.lights[i], 250);

          add_float_prop (table, "spot cutoff",
                          G_OBJECT (data.lights[i]), "spot-cutoff",
                          0.0f, 90.0f);
          add_float_prop (table, "spot exponent",
                          G_OBJECT (data.lights[i]), "spot-exponent",
                          0.0f, 128.0f);
        }

      clutter_container_add_actor (CLUTTER_CONTAINER (data.notebook), table);

      data.notebook_pages[i] = table;
    }

  {
    ClutterActor *button;
    ClutterActor *table;
    CoglHandle material;
    float maximum_shininess;

    material = mash_model_get_pipeline (MASH_MODEL (data.model));

    /* Before version 1.3.10 on the 1.3 branch and 1.2.14 on the 1.2
       branch Cogl would remap the shininess property to the range
       [0,1]. After this it is just a value greater or equal to zero
       (but GL imposes a limit of 128.0) */
    if (clutter_check_version (1, 3, 9)
        || (clutter_major_version == 1
            && clutter_minor_version == 2
            && clutter_micro_version >= 13))
      maximum_shininess = 128.0f;
    else
      maximum_shininess = 1.0f;

    cogl_material_set_shininess (material, maximum_shininess);

    button = mx_button_new_with_label ("Material");
    data.notebook_buttons[i] = button;
    mx_table_add_actor (MX_TABLE (button_box), button, i, 0);
    table = mx_table_new ();
    data.notebook_pages[i] = table;
    clutter_container_add_actor (CLUTTER_CONTAINER (data.notebook), table);

    add_material_color_prop (table, "emission", material,
                             cogl_material_set_emission,
                             cogl_material_get_emission);
    add_material_color_prop (table, "diffuse", material,
                             cogl_material_set_diffuse,
                             cogl_material_get_diffuse);
    add_material_color_prop (table, "ambient", material,
                             cogl_material_set_ambient,
                             cogl_material_get_ambient);
    add_material_color_prop (table, "specular", material,
                             cogl_material_set_specular,
                             cogl_material_get_specular);
    add_material_float_prop (table, "shininess", material,
                             0.0f, maximum_shininess,
                             cogl_material_set_shininess,
                             cogl_material_get_shininess);
  }

  mash_model_set_light_set (MASH_MODEL (data.model), light_set);
  g_object_unref (light_set);

  for (i = 0; i < N_PAGES; i++)
    {
      g_signal_connect (data.notebook_buttons[i], "notify::toggled",
                        G_CALLBACK (notebook_button_cb), &data);
      mx_button_set_is_toggle (MX_BUTTON (data.notebook_buttons[i]), TRUE);
    }

  mx_button_set_toggled (MX_BUTTON (data.notebook_buttons[0]), TRUE);

  g_signal_connect (stage, "motion-event",
                    G_CALLBACK (motion_event_cb),
                    &data);

  clutter_actor_show (stage);

  clutter_main ();

  cogl_handle_unref (data.light_marker_material);

  return 0;
}
Exemplo n.º 11
0
static gboolean
cogl_create_context (void)
{
  GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
  unsigned long  enable_flags = 0;
  CoglHandle window_buffer;

  if (_context != NULL)
    return FALSE;

  /* Allocate context memory */
  _context = (CoglContext*) g_malloc (sizeof (CoglContext));

  /* Init default values */
  _context->feature_flags = 0;
  _context->features_cached = FALSE;

  /* Initialise the driver specific state */
  /* TODO: combine these two into one function */
  _cogl_create_context_driver (_context);
  _cogl_features_init ();

  _cogl_material_init_default_material ();

  _context->enable_flags = 0;
  _context->color_alpha = 0;

  _context->enable_backface_culling = FALSE;
  _context->flushed_front_winding = COGL_FRONT_WINDING_COUNTER_CLOCKWISE;

  _context->indirect = gl_is_indirect;

  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 = NULL;

  _context->simple_material = cogl_material_new ();
  _context->source_material = NULL;

  _context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
  _context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;

  _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
  _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));

  _context->current_material = NULL;
  _context->current_material_flags = 0;
  memset (&_context->current_material_flush_options,
          0, sizeof (CoglMaterialFlushOptions));
  _context->current_layers = g_array_new (FALSE, FALSE,
                                          sizeof (CoglLayerInfo));
  _context->n_texcoord_arrays_enabled = 0;

  _context->framebuffer_stack = _cogl_create_framebuffer_stack ();
  window_buffer = _cogl_onscreen_new ();
  cogl_set_framebuffer (window_buffer);
  /* XXX: the deprecated _cogl_set_draw_buffer API expects to
   * find the window buffer here... */
  _context->window_buffer = window_buffer;

  _context->dirty_bound_framebuffer = TRUE;
  _context->dirty_gl_viewport = TRUE;

  _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
  _context->last_path = 0;
  _context->stencil_material = cogl_material_new ();

  _context->in_begin_gl_block = FALSE;

  _context->quad_indices_byte = COGL_INVALID_HANDLE;
  _context->quad_indices_short = COGL_INVALID_HANDLE;
  _context->quad_indices_short_len = 0;

  _context->texture_download_material = COGL_INVALID_HANDLE;

  /* Create default textures used for fall backs */
  _context->default_gl_texture_2d_tex =
    cogl_texture_new_from_data (1, /* width */
                                1, /* height */
                                COGL_TEXTURE_NO_SLICING,
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
                                /* internal format */
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                0, /* auto calc row stride */
                                default_texture_data);
  _context->default_gl_texture_rect_tex =
    cogl_texture_new_from_data (1, /* width */
                                1, /* height */
                                COGL_TEXTURE_NO_SLICING,
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
                                /* internal format */
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                0, /* auto calc row stride */
                                default_texture_data);

  cogl_set_source (_context->simple_material);
  _cogl_material_flush_gl_state (_context->source_material, NULL);
  enable_flags =
    _cogl_material_get_cogl_enable_flags (_context->source_material);
  cogl_enable (enable_flags);
  _cogl_flush_face_winding ();

  _context->atlas = NULL;
  _context->atlas_texture = COGL_INVALID_HANDLE;

  _context->current_pbo = NULL;

  _context->max_texture_units = -1;

  return TRUE;
}
Exemplo n.º 12
0
void
test_cogl_vertex_buffer_contiguous (TestUtilsGTestFixture *fixture,
		                    void *data)
{
  TestState state;
  ClutterActor *stage;
  ClutterColor stage_clr = {0x0, 0x0, 0x0, 0xff};
  ClutterActor *group;
  unsigned int idle_source;
  guchar tex_data[] = {
    0xff, 0x00, 0x00, 0xff,
    0xff, 0x00, 0x00, 0xff,
    0x00, 0xff, 0x00, 0xff,
    0x00, 0xff, 0x00, 0xff
  };

  stage = clutter_stage_get_default ();

  clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_clr);
  clutter_actor_get_geometry (stage, &state.stage_geom);

  group = clutter_group_new ();
  clutter_actor_set_size (group,
			  state.stage_geom.width,
			  state.stage_geom.height);
  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);

  /* We force continuous redrawing incase someone comments out the
   * clutter_main_quit and wants visual feedback for the test since we
   * wont be doing anything else that will trigger redrawing. */
  idle_source = g_idle_add (queue_redraw, stage);

  g_signal_connect (group, "paint", G_CALLBACK (on_paint), &state);

  state.texture = cogl_texture_new_from_data (2, 2,
                                              COGL_TEXTURE_NO_SLICING,
                                              COGL_PIXEL_FORMAT_RGBA_8888,
                                              COGL_PIXEL_FORMAT_ANY,
                                              0, /* auto calc row stride */
                                              tex_data);

  state.material = cogl_material_new ();
  cogl_material_set_color4ub (state.material, 0x00, 0xff, 0x00, 0xff);
  cogl_material_set_layer (state.material, 0, state.texture);

  {
    GLfloat triangle_verts[3][2] =
      {
	{0.0,	0.0},
	{100.0, 100.0},
	{0.0,	100.0}
      };
    GLbyte triangle_colors[3][4] =
      {
	{0x00, 0x00, 0xff, 0xff}, /* blue */
	{0x00, 0x00, 0xff, 0x00}, /* transparent blue */
	{0x00, 0x00, 0xff, 0x00}  /* transparent blue */
      };
    GLfloat triangle_tex_coords[3][2] =
      {
        {0.0, 0.0},
        {1.0, 1.0},
        {0.0, 1.0}
      };
    state.buffer = cogl_vertex_buffer_new (3 /* n vertices */);
    cogl_vertex_buffer_add (state.buffer,
			    "gl_Vertex",
			    2, /* n components */
			    GL_FLOAT,
			    FALSE, /* normalized */
			    0, /* stride */
			    triangle_verts);
    cogl_vertex_buffer_add (state.buffer,
			    "gl_Color::blue",
			    4, /* n components */
			    GL_UNSIGNED_BYTE,
			    FALSE, /* normalized */
			    0, /* stride */
			    triangle_colors);
    cogl_vertex_buffer_add (state.buffer,
			    "gl_MultiTexCoord0",
			    2, /* n components */
			    GL_FLOAT,
			    FALSE, /* normalized */
			    0, /* stride */
			    triangle_tex_coords);

    cogl_vertex_buffer_submit (state.buffer);
  }

  clutter_actor_show_all (stage);

  clutter_main ();

  cogl_handle_unref (state.buffer);
  cogl_handle_unref (state.material);
  cogl_handle_unref (state.texture);

  g_source_remove (idle_source);

  if (g_test_verbose ())
    g_print ("OK\n");
}
Exemplo n.º 13
0
static void
on_paint (ClutterActor *actor, TestState *state)
{
  CoglHandle tex0, tex1;
  CoglHandle material;
  gboolean status;
  GError *error = NULL;
  float tex_coords[] = {
    0, 0, 0.5, 0.5, /* tex0 */
    0.5, 0.5, 1, 1 /* tex1 */
  };

  /* XXX:
   * We haven't always had good luck with GL drivers implementing glReadPixels
   * reliably and skipping the first two frames improves our chances... */
  if (state->frame++ <= 2)
    {
      g_usleep (G_USEC_PER_SEC);
      return;
    }

  tex0 = make_texture (0x00);
  tex1 = make_texture (0x11);

  material = cogl_material_new ();

  /* An arbitrary color which should be replaced by the first texture layer */
  cogl_material_set_color4ub (material, 0x80, 0x80, 0x80, 0x80);
  cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL);

  cogl_material_set_layer (material, 0, tex0);
  cogl_material_set_layer_combine (material, 0,
                                   "RGBA = REPLACE (TEXTURE)", NULL);

  cogl_material_set_layer (material, 1, tex1);
  status = cogl_material_set_layer_combine (material, 1,
                                            "RGBA = ADD (PREVIOUS, TEXTURE)",
                                            &error);
  if (!status)
    {
      /* It's not strictly a test failure; you need a more capable GPU or
       * driver to test this texture combine string. */
      g_debug ("Failed to setup texture combine string "
               "RGBA = ADD (PREVIOUS, TEXTURE): %s",
               error->message);
    }

  cogl_set_source (material);
  cogl_rectangle_with_multitexture_coords (0, 0, QUAD_WIDTH, QUAD_WIDTH,
                                           tex_coords, 8);

  cogl_handle_unref (material);
  cogl_handle_unref (tex0);
  cogl_handle_unref (tex1);

  /* See what we got... */

  assert_region_color (0, 0, QUAD_WIDTH, QUAD_WIDTH,
                       0x55, 0x55, 0x55, 0x55);

  /* Comment this out if you want visual feedback for what this test paints */
#if 1
  clutter_main_quit ();
#endif
}
Exemplo n.º 14
0
static gboolean
cogl_create_context ()
{
  GLubyte default_texture_data[] = { 0xff, 0xff, 0xff, 0x0 };
  gulong  enable_flags = 0;
  CoglDrawBufferState *draw_buffer;

  if (_context != NULL)
    return FALSE;

  /* Allocate context memory */
  _context = (CoglContext*) g_malloc (sizeof (CoglContext));

  /* Init default values */
  _context->feature_flags = 0;
  _context->features_cached = FALSE;

  _context->enable_flags = 0;
  _context->color_alpha = 0;

  _context->enable_backface_culling = FALSE;

  _context->indirect = gl_is_indirect;

  _context->default_material = cogl_material_new ();
  _context->source_material = NULL;

  _context->default_gl_texture_2d_tex = COGL_INVALID_HANDLE;
  _context->default_gl_texture_rect_tex = COGL_INVALID_HANDLE;

  _context->journal = g_array_new (FALSE, FALSE, sizeof (CoglJournalEntry));
  _context->logged_vertices = g_array_new (FALSE, FALSE, sizeof (GLfloat));
  _context->journal_vbo = 0;
  _context->journal_vbo_len = 0;

  _context->current_material = NULL;
  _context->current_material_flags = 0;
  memset (&_context->current_material_flush_options,
          0, sizeof (CoglMaterialFlushOptions));
  _context->current_layers = g_array_new (FALSE, FALSE,
                                          sizeof (CoglLayerInfo));
  _context->n_texcoord_arrays_enabled = 0;

  draw_buffer = g_slice_new0 (CoglDrawBufferState);
  draw_buffer->target = COGL_WINDOW_BUFFER;
  draw_buffer->offscreen = COGL_INVALID_HANDLE;
  _context->draw_buffer_stack =
    g_slist_prepend (NULL, draw_buffer);

  _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
  _context->last_path = 0;
  _context->stencil_material = cogl_material_new ();

  _context->in_begin_gl_block = FALSE;

  _context->viewport_width = 0;
  _context->viewport_height = 0;

  _context->pf_glGenRenderbuffersEXT = NULL;
  _context->pf_glBindRenderbufferEXT = NULL;
  _context->pf_glRenderbufferStorageEXT = NULL;
  _context->pf_glGenFramebuffersEXT = NULL;
  _context->pf_glBindFramebufferEXT = NULL;
  _context->pf_glFramebufferTexture2DEXT = NULL;
  _context->pf_glFramebufferRenderbufferEXT = NULL;
  _context->pf_glCheckFramebufferStatusEXT = NULL;
  _context->pf_glDeleteFramebuffersEXT = NULL;
  _context->pf_glBlitFramebufferEXT = NULL;
  _context->pf_glRenderbufferStorageMultisampleEXT = NULL;

  _context->pf_glCreateProgramObjectARB = NULL;
  _context->pf_glCreateShaderObjectARB = NULL;
  _context->pf_glShaderSourceARB = NULL;
  _context->pf_glCompileShaderARB = NULL;
  _context->pf_glAttachObjectARB = NULL;
  _context->pf_glLinkProgramARB = NULL;
  _context->pf_glUseProgramObjectARB = NULL;
  _context->pf_glGetUniformLocationARB = NULL;
  _context->pf_glDeleteObjectARB = NULL;
  _context->pf_glGetInfoLogARB = NULL;
  _context->pf_glGetObjectParameterivARB = NULL;
  _context->pf_glUniform1fARB = NULL;
  _context->pf_glUniform2fARB = NULL;
  _context->pf_glUniform3fARB = NULL;
  _context->pf_glUniform4fARB = NULL;
  _context->pf_glUniform1fvARB = NULL;
  _context->pf_glUniform2fvARB = NULL;
  _context->pf_glUniform3fvARB = NULL;
  _context->pf_glUniform4fvARB = NULL;
  _context->pf_glUniform1iARB = NULL;
  _context->pf_glUniform2iARB = NULL;
  _context->pf_glUniform3iARB = NULL;
  _context->pf_glUniform4iARB = NULL;
  _context->pf_glUniform1ivARB = NULL;
  _context->pf_glUniform2ivARB = NULL;
  _context->pf_glUniform3ivARB = NULL;
  _context->pf_glUniform4ivARB = NULL;
  _context->pf_glUniformMatrix2fvARB = NULL;
  _context->pf_glUniformMatrix3fvARB = NULL;
  _context->pf_glUniformMatrix4fvARB = NULL;

  _context->pf_glDrawRangeElements = NULL;
  _context->pf_glActiveTexture = NULL;
  _context->pf_glClientActiveTexture = NULL;

  _context->pf_glBlendFuncSeparate = NULL;
  _context->pf_glBlendEquationSeparate = NULL;

  /* Initialise the clip stack */
  _cogl_clip_stack_state_init ();

  /* Initialise matrix stack */
  _cogl_current_matrix_state_init ();

  /* Create default textures used for fall backs */
  _context->default_gl_texture_2d_tex =
    cogl_texture_new_from_data (1, /* width */
                                1, /* height */
                                COGL_TEXTURE_NO_SLICING,
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
                                /* internal format */
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                0, /* auto calc row stride */
                                default_texture_data);
  _context->default_gl_texture_rect_tex =
    cogl_texture_new_from_data (1, /* width */
                                1, /* height */
                                COGL_TEXTURE_NO_SLICING,
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE, /* data format */
                                /* internal format */
                                COGL_PIXEL_FORMAT_RGBA_8888_PRE,
                                0, /* auto calc row stride */
                                default_texture_data);

  cogl_set_source (_context->default_material);
  _cogl_material_flush_gl_state (_context->source_material, NULL);
  enable_flags =
    _cogl_material_get_cogl_enable_flags (_context->source_material);
  cogl_enable (enable_flags);

  _context->quad_indices_byte = COGL_INVALID_HANDLE;
  _context->quad_indices_short = COGL_INVALID_HANDLE;
  _context->quad_indices_short_len = 0;

  return TRUE;
}
Exemplo n.º 15
0
static gboolean
setup_framebuffers (StThemeNodeTransition *transition,
                    const ClutterActorBox *allocation)
{
  StThemeNodeTransitionPrivate *priv = transition->priv;
  CoglColor clear_color = { 0, 0, 0, 0 };
  guint width, height;

  /* template material to avoid unnecessary shader compilation */
  static CoglHandle material_template = COGL_INVALID_HANDLE;

  width  = priv->offscreen_box.x2 - priv->offscreen_box.x1;
  height = priv->offscreen_box.y2 - priv->offscreen_box.y1;

  g_return_val_if_fail (width  > 0, FALSE);
  g_return_val_if_fail (height > 0, FALSE);

  if (priv->old_texture)
    cogl_handle_unref (priv->old_texture);
  priv->old_texture = cogl_texture_new_with_size (width, height,
                                                  COGL_TEXTURE_NO_SLICING,
                                                  COGL_PIXEL_FORMAT_ANY);

  if (priv->new_texture)
    cogl_handle_unref (priv->new_texture);
  priv->new_texture = cogl_texture_new_with_size (width, height,
                                                  COGL_TEXTURE_NO_SLICING,
                                                  COGL_PIXEL_FORMAT_ANY);

  g_return_val_if_fail (priv->old_texture != COGL_INVALID_HANDLE, FALSE);
  g_return_val_if_fail (priv->new_texture != COGL_INVALID_HANDLE, FALSE);

  if (priv->old_offscreen)
    cogl_handle_unref (priv->old_offscreen);
  priv->old_offscreen = cogl_offscreen_new_to_texture (priv->old_texture);

  if (priv->new_offscreen)
    cogl_handle_unref (priv->new_offscreen);
  priv->new_offscreen = cogl_offscreen_new_to_texture (priv->new_texture);

  g_return_val_if_fail (priv->old_offscreen != COGL_INVALID_HANDLE, FALSE);
  g_return_val_if_fail (priv->new_offscreen != COGL_INVALID_HANDLE, FALSE);

  if (priv->material == NULL)
    {
      if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
        {
          material_template = cogl_material_new ();

          cogl_material_set_layer_combine (material_template, 0,
                                           "RGBA = REPLACE (TEXTURE)",
                                           NULL);
          cogl_material_set_layer_combine (material_template, 1,
                                           "RGBA = INTERPOLATE (PREVIOUS, "
                                                               "TEXTURE, "
                                                               "CONSTANT[A])",
                                           NULL);
          cogl_material_set_layer_combine (material_template, 2,
                                           "RGBA = MODULATE (PREVIOUS, "
                                                            "PRIMARY)",
                                           NULL);
        }
      priv->material = cogl_material_copy (material_template);
    }

  cogl_material_set_layer (priv->material, 0, priv->new_texture);
  cogl_material_set_layer (priv->material, 1, priv->old_texture);

  cogl_push_framebuffer (priv->old_offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
              priv->offscreen_box.y2, priv->offscreen_box.y1,
              0.0, 1.0);
  st_theme_node_paint (priv->old_theme_node, allocation, 255);
  cogl_pop_framebuffer ();

  cogl_push_framebuffer (priv->new_offscreen);
  cogl_clear (&clear_color, COGL_BUFFER_BIT_COLOR);
  cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
              priv->offscreen_box.y2, priv->offscreen_box.y1,
              0.0, 1.0);
  st_theme_node_paint (priv->new_theme_node, allocation, 255);
  cogl_pop_framebuffer ();

  return TRUE;
}
Exemplo n.º 16
0
static void
on_paint (ClutterActor *actor, TestState *state)
{
  CoglHandle tex0, tex1;
  CoglHandle material;
  gboolean status;
  GError *error = NULL;
  float tex_coords[] = {
    0, 0, 0.5, 0.5, /* tex0 */
    0.5, 0.5, 1, 1 /* tex1 */
  };

  tex0 = make_texture (0x00);
  tex1 = make_texture (0x11);

  material = cogl_material_new ();

  /* An arbitrary color which should be replaced by the first texture layer */
  cogl_material_set_color4ub (material, 0x80, 0x80, 0x80, 0x80);
  cogl_material_set_blend (material, "RGBA = ADD (SRC_COLOR, 0)", NULL);

  cogl_material_set_layer (material, 0, tex0);
  cogl_material_set_layer_combine (material, 0,
                                   "RGBA = REPLACE (TEXTURE)", NULL);
  /* We'll use nearest filtering mode on the textures, otherwise the
     edge of the quad can pull in texels from the neighbouring
     quarters of the texture due to imprecision */
  cogl_material_set_layer_filters (material, 0,
                                   COGL_MATERIAL_FILTER_NEAREST,
                                   COGL_MATERIAL_FILTER_NEAREST);

  cogl_material_set_layer (material, 1, tex1);
  cogl_material_set_layer_filters (material, 1,
                                   COGL_MATERIAL_FILTER_NEAREST,
                                   COGL_MATERIAL_FILTER_NEAREST);
  status = cogl_material_set_layer_combine (material, 1,
                                            "RGBA = ADD (PREVIOUS, TEXTURE)",
                                            &error);
  if (!status)
    {
      /* It's not strictly a test failure; you need a more capable GPU or
       * driver to test this texture combine string. */
      g_debug ("Failed to setup texture combine string "
               "RGBA = ADD (PREVIOUS, TEXTURE): %s",
               error->message);
    }

  cogl_set_source (material);
  cogl_rectangle_with_multitexture_coords (0, 0, QUAD_WIDTH, QUAD_WIDTH,
                                           tex_coords, 8);

  cogl_handle_unref (material);
  cogl_handle_unref (tex0);
  cogl_handle_unref (tex1);

  /* See what we got... */

  assert_region_color (0, 0, QUAD_WIDTH, QUAD_WIDTH,
                       0x55, 0x55, 0x55, 0x55);

  /* Comment this out if you want visual feedback for what this test paints */
#if 1
  clutter_main_quit ();
#endif
}
Exemplo n.º 17
0
static void
paint_legacy (TestState *state)
{
  CoglHandle material = cogl_material_new ();
  CoglTexture *tex;
  CoglColor color;
  CoglError *error = NULL;
  CoglHandle shader, program;

  cogl_color_init_from_4ub (&color, 0, 0, 0, 255);
  cogl_clear (&color, COGL_BUFFER_BIT_COLOR);

  /* Set the primary vertex color as red */
  cogl_color_set_from_4ub (&color, 0xff, 0x00, 0x00, 0xff);
  cogl_material_set_color (material, &color);

  /* Override the vertex color in the texture environment with a
     constant green color provided by a texture */
  tex = create_dummy_texture ();
  cogl_material_set_layer (material, 0, tex);
  cogl_object_unref (tex);
  if (!cogl_material_set_layer_combine (material, 0,
                                        "RGBA=REPLACE(TEXTURE)",
                                        &error))
    {
      g_warning ("Error setting layer combine: %s", error->message);
      g_assert_not_reached ();
    }

  /* Set up a dummy vertex shader that does nothing but the usual
     fixed function transform */
  shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
  cogl_shader_source (shader,
                      "void\n"
                      "main ()\n"
                      "{\n"
                      "  cogl_position_out = "
                      "cogl_modelview_projection_matrix * "
                      "cogl_position_in;\n"
                      "  cogl_color_out = cogl_color_in;\n"
                      "  cogl_tex_coord_out[0] = cogl_tex_coord_in;\n"
                      "}\n");
  cogl_shader_compile (shader);
  if (!cogl_shader_is_compiled (shader))
    {
      char *log = cogl_shader_get_info_log (shader);
      g_warning ("Shader compilation failed:\n%s", log);
      g_free (log);
      g_assert_not_reached ();
    }

  program = cogl_create_program ();
  cogl_program_attach_shader (program, shader);
  cogl_program_link (program);

  cogl_handle_unref (shader);

  /* Draw something using the material */
  cogl_set_source (material);
  cogl_rectangle (0, 0, 50, 50);

  /* Draw it again using the program. It should look exactly the same */
  cogl_program_use (program);
  cogl_rectangle (50, 0, 100, 50);
  cogl_program_use (COGL_INVALID_HANDLE);

  cogl_handle_unref (material);
  cogl_handle_unref (program);
}
Exemplo n.º 18
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;
}
static void
st_drawing_area_paint (ClutterActor *self)
{
  StDrawingArea *area = ST_DRAWING_AREA (self);
  StDrawingAreaPrivate *priv = area->priv;
  StThemeNode *theme_node = st_widget_get_theme_node (ST_WIDGET (self));
  ClutterActorBox allocation_box;
  ClutterActorBox content_box;
  int width, height;
  CoglColor color;
  guint8 paint_opacity;

  (CLUTTER_ACTOR_CLASS (st_drawing_area_parent_class))->paint (self);

  clutter_actor_get_allocation_box (self, &allocation_box);
  st_theme_node_get_content_box (theme_node, &allocation_box, &content_box);

  width = (int)(0.5 + content_box.x2 - content_box.x1);
  height = (int)(0.5 + content_box.y2 - content_box.y1);

  if (priv->material == COGL_INVALID_HANDLE)
    priv->material = cogl_material_new ();

  if (priv->texture != COGL_INVALID_HANDLE &&
      (width != cogl_texture_get_width (priv->texture) ||
       height != cogl_texture_get_height (priv->texture)))
    {
      cogl_handle_unref (priv->texture);
      priv->texture = COGL_INVALID_HANDLE;
    }

  if (width > 0 && height > 0)
    {
      if (priv->texture == COGL_INVALID_HANDLE)
        {
          priv->texture = cogl_texture_new_with_size (width, height,
                                                      COGL_TEXTURE_NONE,
                                                      CLUTTER_CAIRO_FORMAT_ARGB32);
          priv->needs_repaint = TRUE;
        }

      if (priv->needs_repaint)
        {
          cairo_surface_t *surface;

          surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
          priv->context = cairo_create (surface);
          priv->in_repaint = TRUE;
          priv->needs_repaint = FALSE;

          g_signal_emit ((GObject*)area, st_drawing_area_signals[REPAINT], 0);

          priv->in_repaint = FALSE;
          cairo_destroy (priv->context);
          priv->context = NULL;

          cogl_texture_set_region (priv->texture, 0, 0, 0, 0, width, height, width, height,
                                   CLUTTER_CAIRO_FORMAT_ARGB32,
                                   cairo_image_surface_get_stride (surface),
                                   cairo_image_surface_get_data (surface));

          cairo_surface_destroy (surface);
        }
    }

  cogl_material_set_layer (priv->material, 0, priv->texture);

  if (priv->texture)
    {
      paint_opacity = clutter_actor_get_paint_opacity (self);
      cogl_color_set_from_4ub (&color,
                               paint_opacity, paint_opacity, paint_opacity, paint_opacity);
      cogl_material_set_color (priv->material, &color);

      cogl_set_source (priv->material);
      cogl_rectangle_with_texture_coords (content_box.x1, content_box.y1,
                                          width, height,
                                          0.0f, 0.0f, 1.0f, 1.0f);
    }
}
Exemplo n.º 20
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);
}
Exemplo n.º 21
0
static void
clutter_stage_glx_redraw (ClutterStageWindow *stage_window)
{
  ClutterBackendX11 *backend_x11;
  ClutterBackendGLX *backend_glx;
  ClutterStageX11 *stage_x11;
  ClutterStageGLX *stage_glx;
  GLXDrawable drawable;
  unsigned int video_sync_count;
  gboolean may_use_clipped_redraw;
  gboolean use_clipped_redraw;

  CLUTTER_STATIC_TIMER (painting_timer,
                        "Redrawing", /* parent */
                        "Painting actors",
                        "The time spent painting actors",
                        0 /* no application private data */);
  CLUTTER_STATIC_TIMER (swapbuffers_timer,
                        "Redrawing", /* parent */
                        "glXSwapBuffers",
                        "The time spent blocked by glXSwapBuffers",
                        0 /* no application private data */);
  CLUTTER_STATIC_TIMER (blit_sub_buffer_timer,
                        "Redrawing", /* parent */
                        "glx_blit_sub_buffer",
                        "The time spent in _glx_blit_sub_buffer",
                        0 /* no application private data */);

  stage_x11 = CLUTTER_STAGE_X11 (stage_window);
  if (stage_x11->xwin == None)
    return;

  stage_glx = CLUTTER_STAGE_GLX (stage_window);

  backend_x11 = stage_x11->backend;
  backend_glx = CLUTTER_BACKEND_GLX (backend_x11);

  CLUTTER_TIMER_START (_clutter_uprof_context, painting_timer);

  if (G_LIKELY (backend_glx->can_blit_sub_buffer) &&
      /* NB: a zero width redraw clip == full stage redraw */
      stage_glx->bounding_redraw_clip.width != 0 &&
      /* some drivers struggle to get going and produce some junk
       * frames when starting up... */
      G_LIKELY (stage_glx->frame_count > 3) &&
      /* While resizing a window clipped redraws are disabled to avoid
       * artefacts. See clutter-event-x11.c:event_translate for a
       * detailed explanation */
      G_LIKELY (stage_x11->clipped_redraws_cool_off == 0))
    {
      may_use_clipped_redraw = TRUE;
    }
  else
    may_use_clipped_redraw = FALSE;

  if (may_use_clipped_redraw &&
      G_LIKELY (!(clutter_paint_debug_flags &
                  CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
    use_clipped_redraw = TRUE;
  else
    use_clipped_redraw = FALSE;

  if (use_clipped_redraw)
    {
      CLUTTER_NOTE (CLIPPING,
                    "Stage clip pushed: x=%d, y=%d, width=%d, height=%d\n",
                    stage_glx->bounding_redraw_clip.x,
                    stage_glx->bounding_redraw_clip.y,
                    stage_glx->bounding_redraw_clip.width,
                    stage_glx->bounding_redraw_clip.height);
      cogl_clip_push_window_rectangle (stage_glx->bounding_redraw_clip.x,
                                       stage_glx->bounding_redraw_clip.y,
                                       stage_glx->bounding_redraw_clip.width,
                                       stage_glx->bounding_redraw_clip.height);
      _clutter_stage_do_paint (stage_x11->wrapper,
                               &stage_glx->bounding_redraw_clip);
      cogl_clip_pop ();
    }
  else
    {
      CLUTTER_NOTE (CLIPPING, "Unclipped stage paint\n");
      _clutter_stage_do_paint (stage_x11->wrapper, NULL);
    }

  if (may_use_clipped_redraw &&
      G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_REDRAWS)))
    {
      static CoglMaterial *outline = NULL;
      ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
      ClutterActor *actor = CLUTTER_ACTOR (stage_x11->wrapper);
      CoglHandle vbo;
      float x_1 = clip->x;
      float x_2 = clip->x + clip->width;
      float y_1 = clip->y;
      float y_2 = clip->y + clip->height;
      float quad[8] = {
        x_1, y_1,
        x_2, y_1,
        x_2, y_2,
        x_1, y_2
      };
      CoglMatrix modelview;

      if (outline == NULL)
        {
          outline = cogl_material_new ();
          cogl_material_set_color4ub (outline, 0xff, 0x00, 0x00, 0xff);
        }

      vbo = cogl_vertex_buffer_new (4);
      cogl_vertex_buffer_add (vbo,
                              "gl_Vertex",
                              2, /* n_components */
                              COGL_ATTRIBUTE_TYPE_FLOAT,
                              FALSE, /* normalized */
                              0, /* stride */
                              quad);
      cogl_vertex_buffer_submit (vbo);

      cogl_push_matrix ();
      cogl_matrix_init_identity (&modelview);
      _clutter_actor_apply_modelview_transform (actor, &modelview);
      cogl_set_modelview_matrix (&modelview);
      cogl_set_source (outline);
      cogl_vertex_buffer_draw (vbo, COGL_VERTICES_MODE_LINE_LOOP,
                               0 , 4);
      cogl_pop_matrix ();
      cogl_object_unref (vbo);
    }

  cogl_flush ();
  CLUTTER_TIMER_STOP (_clutter_uprof_context, painting_timer);

  drawable = stage_glx->glxwin
           ? stage_glx->glxwin
           : stage_x11->xwin;

  /* If we might ever use _clutter_backend_glx_blit_sub_buffer then we
   * always need to keep track of the video_sync_count so that we can
   * throttle blits.
   *
   * Note: we get the count *before* we issue any glXCopySubBuffer or
   * blit_sub_buffer request in case the count would go up before
   * returning control to us.
   */
  if (backend_glx->can_blit_sub_buffer && backend_glx->get_video_sync)
    backend_glx->get_video_sync (&video_sync_count);

  /* push on the screen */
  if (use_clipped_redraw)
    {
      ClutterGeometry *clip = &stage_glx->bounding_redraw_clip;
      ClutterGeometry copy_area;
      ClutterActor *actor;

      CLUTTER_NOTE (BACKEND,
                    "_glx_blit_sub_buffer (window: 0x%lx, "
                                          "x: %d, y: %d, "
                                          "width: %d, height: %d)",
                    (unsigned long) drawable,
                    stage_glx->bounding_redraw_clip.x,
                    stage_glx->bounding_redraw_clip.y,
                    stage_glx->bounding_redraw_clip.width,
                    stage_glx->bounding_redraw_clip.height);

      /* XXX: It seems there will be a race here in that the stage
       * window may be resized before glXCopySubBufferMESA is handled
       * and so we may copy the wrong region. I can't really see how
       * we can handle this with the current state of X but at least
       * in this case a full redraw should be queued by the resize
       * anyway so it should only exhibit temporary artefacts.
       */
      actor = CLUTTER_ACTOR (stage_x11->wrapper);
      copy_area.y = clutter_actor_get_height (actor)
                  - clip->y
                  - clip->height;
      copy_area.x = clip->x;
      copy_area.width = clip->width;
      copy_area.height = clip->height;

      /* glXCopySubBufferMESA and glBlitFramebuffer are not integrated
       * with the glXSwapIntervalSGI mechanism which we usually use to
       * throttle the Clutter framerate to the vertical refresh and so
       * we have to manually wait for the vblank period...
       */

      /* Here 'is_synchronized' only means that the blit won't cause a
       * tear, ie it won't prevent multiple blits per retrace if they
       * can all be performed in the blanking period. If that's the
       * case then we still want to use the vblank sync menchanism but
       * we only need it to throttle redraws.
       */
      if (!backend_glx->blit_sub_buffer_is_synchronized)
        {
          /* XXX: note that glXCopySubBuffer, at least for Intel, is
           * synchronized with the vblank but glBlitFramebuffer may
           * not be so we use the same scheme we do when calling
           * glXSwapBuffers without the swap_control extension and
           * call glFinish () before waiting for the vblank period.
           *
           * See where we call glXSwapBuffers for more details.
           */
          glFinish ();
          wait_for_vblank (backend_glx);
        }
      else if (backend_glx->get_video_sync)
        {
          /* If we have the GLX_SGI_video_sync extension then we can
           * be a bit smarter about how we throttle blits by avoiding
           * any waits if we can see that the video sync count has
           * already progressed. */
          if (backend_glx->last_video_sync_count == video_sync_count)
            wait_for_vblank (backend_glx);
        }
      else
        wait_for_vblank (backend_glx);

      CLUTTER_TIMER_START (_clutter_uprof_context, blit_sub_buffer_timer);
      _clutter_backend_glx_blit_sub_buffer (backend_glx,
                                            drawable,
                                            copy_area.x,
                                            copy_area.y,
                                            copy_area.width,
                                            copy_area.height);
      CLUTTER_TIMER_STOP (_clutter_uprof_context, blit_sub_buffer_timer);
    }
  else
    {
      CLUTTER_NOTE (BACKEND, "glXSwapBuffers (display: %p, window: 0x%lx)",
                    backend_x11->xdpy,
                    (unsigned long) drawable);

      /* If we have GLX swap buffer events then glXSwapBuffers will return
       * immediately and we need to track that there is a swap in
       * progress... */
      if (clutter_feature_available (CLUTTER_FEATURE_SWAP_EVENTS))
        stage_glx->pending_swaps++;

      if (backend_glx->vblank_type != CLUTTER_VBLANK_GLX_SWAP &&
          backend_glx->vblank_type != CLUTTER_VBLANK_NONE)
        {
          /* If we are going to wait for VBLANK manually, we not only
           * need to flush out pending drawing to the GPU before we
           * sleep, we need to wait for it to finish. Otherwise, we
           * may end up with the situation:
           *
           *        - We finish drawing      - GPU drawing continues
           *        - We go to sleep         - GPU drawing continues
           * VBLANK - We call glXSwapBuffers - GPU drawing continues
           *                                 - GPU drawing continues
           *                                 - Swap buffers happens
           *
           * Producing a tear. Calling glFinish() first will cause us
           * to properly wait for the next VBLANK before we swap. This
           * obviously does not happen when we use _GLX_SWAP and let
           * the driver do the right thing
           */
          glFinish ();

          wait_for_vblank (backend_glx);
        }

      CLUTTER_TIMER_START (_clutter_uprof_context, swapbuffers_timer);
      glXSwapBuffers (backend_x11->xdpy, drawable);
      CLUTTER_TIMER_STOP (_clutter_uprof_context, swapbuffers_timer);

      _cogl_swap_buffers_notify ();
    }

  backend_glx->last_video_sync_count = video_sync_count;

  /* reset the redraw clipping for the next paint... */
  stage_glx->initialized_redraw_clip = FALSE;

  stage_glx->frame_count++;
}