예제 #1
0
파일: rut-rectangle.c 프로젝트: cee1/rig
RutRectangle *
rut_rectangle_new4f (RutContext *ctx,
                     float width,
                     float height,
                     float red,
                     float green,
                     float blue,
                     float alpha)
{
  RutRectangle *rectangle = g_slice_new0 (RutRectangle);
  static CoglBool initialized = FALSE;

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

  rut_object_init (&rectangle->_parent, &rut_rectangle_type);

  rectangle->ref_count = 1;

  rut_graphable_init (rectangle);
  rut_paintable_init (rectangle);

  rectangle->width = width;
  rectangle->height = height;

  rectangle->pipeline = cogl_pipeline_new (ctx->cogl_context);
  cogl_pipeline_set_color4f (rectangle->pipeline,
                             red, green, blue, alpha);

  return rectangle;
}
예제 #2
0
static void
paint_scene (RigPaintContext *paint_ctx)
{
  RutPaintContext *rut_paint_ctx = &paint_ctx->_parent;
  RigEngine *engine = paint_ctx->engine;
  CoglContext *ctx = engine->ctx->cogl_context;
  CoglFramebuffer *fb = rut_camera_get_framebuffer (rut_paint_ctx->camera);

  if (paint_ctx->pass == RIG_PASS_COLOR_UNBLENDED)
    {
      CoglPipeline *pipeline = cogl_pipeline_new (ctx);
      cogl_pipeline_set_color4f (pipeline,
                                 engine->background_color.red,
                                 engine->background_color.green,
                                 engine->background_color.blue,
                                 engine->background_color.alpha);
      cogl_framebuffer_draw_rectangle (fb,
                                       pipeline,
                                       0, 0,
                                       engine->device_width, engine->device_height);
                                       //0, 0, engine->pane_width, engine->pane_height);
      cogl_object_unref (pipeline);
    }

  rut_graphable_traverse (engine->scene,
                          RUT_TRAVERSE_DEPTH_FIRST,
                          entitygraph_pre_paint_cb,
                          entitygraph_post_paint_cb,
                          paint_ctx);

  rig_journal_flush (engine->journal, paint_ctx);
}
예제 #3
0
static void
paint (TestState *state)
{
  CoglPipeline *white = cogl_pipeline_new (test_ctx);
  int i;

  cogl_pipeline_set_color4f (white, 1, 1, 1, 1);


  cogl_framebuffer_draw_rectangle (state->fbo[0],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_framebuffer_draw_rectangle (state->fbo[1],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_framebuffer_draw_rectangle (state->fbo[2],
                                   white,
                                   -1.0, -1.0, 1.0, 1.0);

  cogl_object_unref (white);

  cogl_framebuffer_clear4f (test_fb,
                            COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH,
                            0.5, 0.5, 0.5, 1.0);

  /* Render all of the textures to the screen */
  for (i = 0; i < NUM_FBOS; i++)
    {
      CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
      cogl_pipeline_set_layer_texture (pipeline, 0, state->tex[i]);
      cogl_framebuffer_draw_rectangle (test_fb, pipeline,
                                       2.0f / NUM_FBOS * i - 1.0f, -1.0f,
                                       2.0f / NUM_FBOS * (i + 1) - 1.0f, 1.0f);
      cogl_object_unref (pipeline);
    }

  /* Verify all of the fbos drew the right color */
  for (i = 0; i < NUM_FBOS; i++)
    {
      uint8_t expected_colors[NUM_FBOS][4] =
        { { 0xff, 0x00, 0x00, 0xff },
          { 0x00, 0xff, 0x00, 0xff },
          { 0x00, 0x00, 0xff, 0xff } };

      test_utils_check_pixel_rgb (test_fb,
                                  state->width * (i + 0.5f) / NUM_FBOS,
                                  state->height / 2,
                                  expected_colors[i][0],
                                  expected_colors[i][1],
                                  expected_colors[i][2]);
    }
}
예제 #4
0
static void
paint (TestState *state)
{
  CoglPipeline *pipeline = cogl_pipeline_new (test_ctx);
  CoglTexture *tex;
  CoglError *error = NULL;
  CoglSnippet *snippet;

  cogl_framebuffer_clear4f (test_fb, COGL_BUFFER_BIT_COLOR, 0, 0, 0, 1);

  /* Set the primary vertex color as red */
  cogl_pipeline_set_color4f (pipeline, 1, 0, 0, 1);

  /* Override the vertex color in the texture environment with a
     constant green color provided by a texture */
  tex = create_dummy_texture ();
  cogl_pipeline_set_layer_texture (pipeline, 0, tex);
  cogl_object_unref (tex);
  if (!cogl_pipeline_set_layer_combine (pipeline, 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
     modelview-projection transform */
  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
                              NULL, /* no declarations */
                              NULL); /* no "post" code */
  cogl_snippet_set_replace (snippet,
                            "  cogl_position_out = "
                            "cogl_modelview_projection_matrix * "
                            "cogl_position_in;\n"
                            "  cogl_color_out = cogl_color_in;\n"
                            "  cogl_tex_coord0_out = cogl_tex_coord_in;\n");

  /* Draw something without the snippet */
  cogl_framebuffer_draw_rectangle (test_fb, pipeline, 0, 0, 50, 50);

  /* Draw it again using the snippet. It should look exactly the same */
  cogl_pipeline_add_snippet (pipeline, snippet);
  cogl_object_unref (snippet);

  cogl_framebuffer_draw_rectangle (test_fb, pipeline, 50, 0, 100, 50);

  cogl_object_unref (pipeline);
}
예제 #5
0
static void
clutter_deform_effect_paint_target (ClutterOffscreenEffect *effect)
{
  ClutterDeformEffect *self= CLUTTER_DEFORM_EFFECT (effect);
  ClutterDeformEffectPrivate *priv = self->priv;
  CoglHandle material;
  CoglPipeline *pipeline;
  CoglDepthState depth_state;
  CoglFramebuffer *fb = cogl_get_draw_framebuffer ();

  if (priv->is_dirty)
    {
      ClutterRect rect;
      gboolean mapped_buffer;
      CoglVertexP3T2C4 *verts;
      ClutterActor *actor;
      gfloat width, height;
      guint opacity;
      gint i, j;

      actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (effect));
      opacity = clutter_actor_get_paint_opacity (actor);

      /* if we don't have a target size, fall back to the actor's
       * allocation, though wrong it might be
       */
      if (clutter_offscreen_effect_get_target_rect (effect, &rect))
        {
          width = clutter_rect_get_width (&rect);
          height = clutter_rect_get_height (&rect);
        }
      else
        clutter_actor_get_size (actor, &width, &height);

      /* XXX ideally, the sub-classes should tell us what they
       * changed in the texture vertices; we then would be able to
       * avoid resubmitting the same data, if it did not change. for
       * the time being, we resubmit everything
       */
      verts = cogl_buffer_map (COGL_BUFFER (priv->buffer),
                               COGL_BUFFER_ACCESS_WRITE,
                               COGL_BUFFER_MAP_HINT_DISCARD);

      /* If the map failed then we'll resort to allocating a temporary
         buffer */
      if (verts == NULL)
        {
          mapped_buffer = FALSE;
          verts = g_malloc (sizeof (*verts) * priv->n_vertices);
        }
      else
        mapped_buffer = TRUE;

      for (i = 0; i < priv->y_tiles + 1; i++)
        {
          for (j = 0; j < priv->x_tiles + 1; j++)
            {
              CoglVertexP3T2C4 *vertex_out;
              CoglTextureVertex vertex;

              /* CoglTextureVertex isn't an ideal structure to use for
                 this because it contains a CoglColor. The internal
                 layout of CoglColor is mean to be private so Clutter
                 can not pass a pointer to it as a vertex
                 attribute. Also it contains padding so we end up
                 storing more data in the vertex buffer than we need
                 to. Instead we let the application modify a dummy
                 vertex and then copy the details back out to a more
                 well-defined struct */

              vertex.tx = (float) j / priv->x_tiles;
              vertex.ty = (float) i / priv->y_tiles;

              vertex.x = width * vertex.tx;
              vertex.y = height * vertex.ty;
              vertex.z = 0.0f;

              cogl_color_init_from_4ub (&vertex.color, 255, 255, 255, opacity);

              clutter_deform_effect_deform_vertex (self,
                                                   width, height,
                                                   &vertex);

              vertex_out = verts + i * (priv->x_tiles + 1) + j;

              vertex_out->x = vertex.x;
              vertex_out->y = vertex.y;
              vertex_out->z = vertex.z;
              vertex_out->s = vertex.tx;
              vertex_out->t = vertex.ty;
              vertex_out->r = cogl_color_get_red_byte (&vertex.color);
              vertex_out->g = cogl_color_get_green_byte (&vertex.color);
              vertex_out->b = cogl_color_get_blue_byte (&vertex.color);
              vertex_out->a = cogl_color_get_alpha_byte (&vertex.color);
            }
        }

      if (mapped_buffer)
        cogl_buffer_unmap (COGL_BUFFER (priv->buffer));
      else
        {
          cogl_buffer_set_data (COGL_BUFFER (priv->buffer),
                                0, /* offset */
                                verts,
                                sizeof (*verts) * priv->n_vertices);
          g_free (verts);
        }

      priv->is_dirty = FALSE;
    }

  material = clutter_offscreen_effect_get_target (effect);
  pipeline = COGL_PIPELINE (material);

  /* enable depth testing */
  cogl_depth_state_init (&depth_state);
  cogl_depth_state_set_test_enabled (&depth_state, TRUE);
  cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL);

  /* enable backface culling if we have a back material */
  if (priv->back_pipeline != NULL)
    cogl_pipeline_set_cull_face_mode (pipeline,
                                      COGL_PIPELINE_CULL_FACE_MODE_BACK);

  /* draw the front */
  if (material != NULL)
    cogl_framebuffer_draw_primitive (fb, pipeline, priv->primitive);

  /* draw the back */
  if (priv->back_pipeline != NULL)
    {
      CoglPipeline *back_pipeline;

      /* We probably shouldn't be modifying the user's material so
         instead we make a temporary copy */
      back_pipeline = cogl_pipeline_copy (priv->back_pipeline);
      cogl_pipeline_set_depth_state (back_pipeline, &depth_state, NULL);
      cogl_pipeline_set_cull_face_mode (back_pipeline,
                                        COGL_PIPELINE_CULL_FACE_MODE_FRONT);

      cogl_framebuffer_draw_primitive (fb, back_pipeline, priv->primitive);

      cogl_object_unref (back_pipeline);
    }

  if (G_UNLIKELY (priv->lines_primitive != NULL))
    {
      CoglContext *ctx =
        clutter_backend_get_cogl_context (clutter_get_default_backend ());
      CoglPipeline *lines_pipeline = cogl_pipeline_new (ctx);
      cogl_pipeline_set_color4f (lines_pipeline, 1.0, 0, 0, 1.0);
      cogl_framebuffer_draw_primitive (fb, lines_pipeline,
                                       priv->lines_primitive);
      cogl_object_unref (lines_pipeline);
    }
}
예제 #6
0
int
main (int argc,
      char **argv)
{
  Data data;
  CoglContext *ctx;
  CoglOnscreen *onscreen;
  GstElement *pipeline;
  GSource *cogl_source;
  GstBus *bus;
  char *uri;
  GError *error = NULL;

  memset (&data, 0, sizeof (Data));

  /* Set the necessary cogl elements */

  ctx = cogl_context_new (NULL, NULL);

  onscreen = cogl_onscreen_new (ctx, 640, 480);
  cogl_onscreen_set_resizable (onscreen, TRUE);
  cogl_onscreen_add_resize_callback (onscreen, _resize_callback, &data, NULL);
  cogl_onscreen_show (onscreen);

  data.fb = onscreen;
  cogl_framebuffer_orthographic (data.fb, 0, 0, 640, 480, -1, 100);

  data.border_pipeline = cogl_pipeline_new (ctx);
  cogl_pipeline_set_color4f (data.border_pipeline, 0, 0, 0, 1);
  /* disable blending */
  cogl_pipeline_set_blend (data.border_pipeline,
                           "RGBA = ADD (SRC_COLOR, 0)", NULL);

  /* Intialize GStreamer */

  gst_init (&argc, &argv);

  /*
     Create the cogl-gst video sink by calling the cogl_gst_video_sink_new
     function and passing it a CoglContext (this is used to create the
     CoglPipeline and the texures for each frame). Alternatively you can use
     gst_element_factory_make ("coglsink", "some_name") and then set the
     context with cogl_gst_video_sink_set_context.
  */

  if (argc < 2)
    uri = "http://docs.gstreamer.com/media/sintel_trailer-480p.webm";
  else
    uri = argv[1];

  if (!make_pipeline_for_uri (ctx, uri, &pipeline, &data.sink, &error))
    {
      g_print ("Error creating pipeline: %s\n", error->message);
      g_clear_error (&error);
      return EXIT_FAILURE;
    }

  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  gst_bus_add_watch (bus, _bus_watch, &data);

  data.main_loop = g_main_loop_new (NULL, FALSE);

  cogl_source = cogl_glib_source_new (ctx, G_PRIORITY_DEFAULT);
  g_source_attach (cogl_source, NULL);

  /*
    The cogl-pipeline-ready signal tells you when the cogl pipeline is
    initialized i.e. when cogl-gst has figured out the video format and
    is prepared to retrieve and attach the first frame of the video.
  */

  g_signal_connect (data.sink, "pipeline-ready",
                    G_CALLBACK (_set_up_pipeline), &data);

  data.draw_ready = TRUE;
  data.frame_ready = FALSE;

  g_main_loop_run (data.main_loop);

  g_source_destroy (cogl_source);
  g_source_unref (cogl_source);

  g_main_loop_unref (data.main_loop);

  return 0;
}
예제 #7
0
static CoglPipeline *
get_entity_color_pipeline (RigEngine *engine,
                           RutEntity *entity,
                           RutComponent *geometry,
                           CoglBool blended)
{
  CoglSnippet *snippet;
  CoglDepthState depth_state;
  RutMaterial *material;
  CoglTexture *texture = NULL;
  CoglTexture *normal_map = NULL;
  CoglTexture *alpha_mask = NULL;
  CoglPipeline *pipeline;
  CoglFramebuffer *shadow_fb;

  if (blended)
    pipeline = rut_entity_get_pipeline_cache (entity,
                                              CACHE_SLOT_COLOR_BLENDED);
  else
    pipeline = rut_entity_get_pipeline_cache (entity,
                                              CACHE_SLOT_COLOR_UNBLENDED);
  if (pipeline)
    {
      cogl_object_ref (pipeline);
      goto FOUND;
    }

  pipeline = cogl_pipeline_new (engine->ctx->cogl_context);

  material = rut_entity_get_component (entity, RUT_COMPONENT_TYPE_MATERIAL);
  if (material)
    {
      RutAsset *texture_asset = rut_material_get_texture_asset (material);
      RutAsset *normal_map_asset =
        rut_material_get_normal_map_asset (material);
      RutAsset *alpha_mask_asset =
        rut_material_get_alpha_mask_asset (material);

      if (texture_asset)
        texture = rut_asset_get_texture (texture_asset);
      if (texture)
        cogl_pipeline_set_layer_texture (pipeline, 1, texture);

      if (normal_map_asset)
        normal_map = rut_asset_get_texture (normal_map_asset);

      if (alpha_mask_asset)
        alpha_mask = rut_asset_get_texture (alpha_mask_asset);
    }

#if 0
  /* NB: Our texture colours aren't premultiplied */
  cogl_pipeline_set_blend (pipeline,
                           "RGB = ADD(SRC_COLOR*(SRC_COLOR[A]), DST_COLOR*(1-SRC_COLOR[A]))"
                           "A   = ADD(SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))",
                           NULL);
#endif

#if 0
  if (rut_object_get_type (geometry) == &rut_shape_type)
    rut_geometry_component_update_pipeline (geometry, pipeline);

  pipeline = cogl_pipeline_new (rut_cogl_context);
#endif

  cogl_pipeline_set_color4f (pipeline, 0.8f, 0.8f, 0.8f, 1.f);

  /* enable depth testing */
  cogl_depth_state_init (&depth_state);
  cogl_depth_state_set_test_enabled (&depth_state, TRUE);

  if (blended)
    cogl_depth_state_set_write_enabled (&depth_state, FALSE);

  cogl_pipeline_set_depth_state (pipeline, &depth_state, NULL);

  /* Vertex shader setup for lighting */
  cogl_pipeline_add_snippet (pipeline, engine->lighting_vertex_snippet);

  if (normal_map)
    cogl_pipeline_add_snippet (pipeline, engine->normal_map_vertex_snippet);

  if (rut_entity_get_receive_shadow (entity))
    cogl_pipeline_add_snippet (pipeline, engine->shadow_mapping_vertex_snippet);

  /* and fragment shader */

  /* XXX: ideally we wouldn't have to rely on conditionals + discards
   * in the fragment shader to differentiate blended and unblended
   * regions and instead we should let users mark out opaque regions
   * in geometry.
   */
  cogl_pipeline_add_snippet (pipeline,
                             blended ?
                             engine->blended_discard_snippet :
                             engine->unblended_discard_snippet);

  cogl_pipeline_add_snippet (pipeline, engine->unpremultiply_snippet);

  if (material)
    {
      if (alpha_mask)
        {
          /* We don't want this layer to be automatically modulated with the
           * previous layers so we set its combine mode to "REPLACE" so it
           * will be skipped past and we can sample its texture manually */
          cogl_pipeline_set_layer_combine (pipeline, 2, "RGBA=REPLACE(PREVIOUS)", NULL);
          cogl_pipeline_set_layer_texture (pipeline, 2, alpha_mask);

          cogl_pipeline_add_snippet (pipeline, engine->alpha_mask_snippet);
        }

      if (normal_map)
        {
          /* We don't want this layer to be automatically modulated with the
           * previous layers so we set its combine mode to "REPLACE" so it
           * will be skipped past and we can sample its texture manually */
          cogl_pipeline_set_layer_combine (pipeline, 5, "RGBA=REPLACE(PREVIOUS)", NULL);
          cogl_pipeline_set_layer_texture (pipeline, 5, normal_map);

          snippet = engine->normal_map_fragment_snippet;
        }
      else
        {
          snippet = engine->material_lighting_snippet;
        }
    }
  else
    {
      snippet = engine->simple_lighting_snippet;
    }

  cogl_pipeline_add_snippet (pipeline, snippet);

  if (rut_entity_get_receive_shadow (entity))
    {
      /* Hook the shadow map sampling */

      cogl_pipeline_set_layer_texture (pipeline, 7, engine->shadow_map);
      /* For debugging the shadow mapping... */
      //cogl_pipeline_set_layer_texture (pipeline, 7, engine->shadow_color);
      //cogl_pipeline_set_layer_texture (pipeline, 7, engine->gradient);

      /* We don't want this layer to be automatically modulated with the
       * previous layers so we set its combine mode to "REPLACE" so it
       * will be skipped past and we can sample its texture manually */
      cogl_pipeline_set_layer_combine (pipeline, 7, "RGBA=REPLACE(PREVIOUS)", NULL);

      /* Handle shadow mapping */
      cogl_pipeline_add_snippet (pipeline,
                                 engine->shadow_mapping_fragment_snippet);
    }

  cogl_pipeline_add_snippet (pipeline, engine->premultiply_snippet);

  if (rut_object_get_type (geometry) == &rut_shape_type)
    {
      CoglTexture *shape_texture;

      if (rut_shape_get_shaped (RUT_SHAPE (geometry)))
        {
          shape_texture =
            rut_shape_get_shape_texture (RUT_SHAPE (geometry));
          cogl_pipeline_set_layer_texture (pipeline, 0, shape_texture);
        }

      rut_shape_add_reshaped_callback (RUT_SHAPE (geometry),
                                       reshape_cb,
                                       NULL,
                                       NULL);
    }
  else if (rut_object_get_type (geometry) == &rut_diamond_type)
    rut_diamond_apply_mask (RUT_DIAMOND (geometry), pipeline);

  if (!blended)
    {
      cogl_pipeline_set_blend (pipeline, "RGBA = ADD (SRC_COLOR, 0)", NULL);
      rut_entity_set_pipeline_cache (entity,
                                     CACHE_SLOT_COLOR_UNBLENDED, pipeline);
    }
  else
    {
      rut_entity_set_pipeline_cache (entity,
                                     CACHE_SLOT_COLOR_BLENDED, pipeline);
    }

FOUND:

  /* FIXME: there's lots to optimize about this! */
  shadow_fb = COGL_FRAMEBUFFER (engine->shadow_fb);

  /* update uniforms in pipelines */
  {
    CoglMatrix light_shadow_matrix, light_projection;
    CoglMatrix model_transform;
    const float *light_matrix;
    int location;

    cogl_framebuffer_get_projection_matrix (shadow_fb, &light_projection);

    /* XXX: This is pretty bad that we are having to do this. It would
     * be nicer if cogl exposed matrix-stacks publicly so we could
     * maintain the entity model_matrix incrementally as we traverse
     * the scenegraph. */
    rut_graphable_get_transform (entity, &model_transform);

    get_light_modelviewprojection (&model_transform,
                                   engine->light,
                                   &light_projection,
                                   &light_shadow_matrix);

    light_matrix = cogl_matrix_get_array (&light_shadow_matrix);

    location = cogl_pipeline_get_uniform_location (pipeline,
                                                   "light_shadow_matrix");
    cogl_pipeline_set_uniform_matrix (pipeline,
                                      location,
                                      4, 1,
                                      FALSE,
                                      light_matrix);
  }

  return pipeline;
}