static void
resize_handler (CoglOnscreen *onscreen,
                int width,
                int height,
                void *user_data)
{
  CoglFramebuffer *fb = user_data;
  cogl_framebuffer_set_viewport (fb, width / 4, height / 4, width / 2, height / 2);
}
Beispiel #2
0
static void
cogland_compositor_create_output (CoglandCompositor *compositor,
                                  int x,
                                  int y,
                                  int width_mm,
                                  int height_mm)
{
  CoglandOutput *output = g_slice_new0 (CoglandOutput);
  CoglFramebuffer *fb;
  CoglError *error = NULL;
  CoglandMode *mode;

  output->x = x;
  output->y = y;
  output->width_mm = width_mm;
  output->height_mm = height_mm;

  output->wayland_output.interface = &wl_output_interface;

  wl_display_add_global (compositor->wayland_display,
                         &wl_output_interface,
                         output,
                         bind_output);

  output->onscreen = cogl_onscreen_new (compositor->cogl_context,
                                        width_mm, height_mm);
  /* Eventually there will be an implicit allocate on first use so this
   * will become optional... */
  fb = output->onscreen;
  if (!cogl_framebuffer_allocate (fb, &error))
    g_error ("Failed to allocate framebuffer: %s\n", error->message);

  cogl_onscreen_add_dirty_callback (output->onscreen,
                                    dirty_cb,
                                    compositor,
                                    NULL /* destroy */);

  cogl_onscreen_show (output->onscreen);
  cogl_framebuffer_set_viewport (fb,
                                 -x, -y,
                                 compositor->virtual_width,
                                 compositor->virtual_height);

  mode = g_slice_new0 (CoglandMode);
  mode->flags = 0;
  mode->width = width_mm;
  mode->height = height_mm;
  mode->refresh = 60;

  output->modes = g_list_prepend (output->modes, mode);

  compositor->outputs = g_list_prepend (compositor->outputs, output);
}
Beispiel #3
0
static void
_rut_camera_flush_transforms (RutCamera *camera)
{
  const CoglMatrix *projection;
  CoglFramebuffer *fb = camera->fb;
  CameraFlushState *state;

  /* While a camera is in a suspended state then we don't expect to
   * _flush() and use that camera before it is restored. */
  g_return_if_fail (camera->suspended == FALSE);

  state = cogl_object_get_user_data (COGL_OBJECT (fb), &fb_camera_key);
  if (!state)
    {
      state = g_slice_new (CameraFlushState);
      cogl_object_set_user_data (COGL_OBJECT (fb),
                                 &fb_camera_key,
                                 state,
                                 free_camera_flush_state);
    }
  else if (state->current_camera == camera &&
           camera->transform_age == state->transform_age)
    goto done;

  if (camera->in_frame)
    {
      g_warning ("Un-balanced rut_camera_flush/_end calls: "
                 "repeat _flush() calls before _end()");
    }

  cogl_framebuffer_set_viewport (fb,
                                 camera->viewport[0],
                                 camera->viewport[1],
                                 camera->viewport[2],
                                 camera->viewport[3]);

  projection = rut_camera_get_projection (camera);
  cogl_framebuffer_set_projection_matrix (fb, projection);

  cogl_framebuffer_set_modelview_matrix (fb, &camera->view);

  state->current_camera = camera;
  state->transform_age = camera->transform_age;

done:
  camera->in_frame = TRUE;
}
Beispiel #4
0
void
cogl_set_viewport (int x,
                   int y,
                   int width,
                   int height)
{
  CoglFramebuffer *framebuffer;

  _COGL_GET_CONTEXT (ctx, NO_RETVAL);

  framebuffer = cogl_get_draw_framebuffer ();

  cogl_framebuffer_set_viewport (framebuffer,
                                 x,
                                 y,
                                 width,
                                 height);
}
Beispiel #5
0
void
rut_camera_resume (RutCamera *camera)
{
  CameraFlushState *state;
  CoglFramebuffer *fb = camera->fb;

  g_return_if_fail (camera->in_frame == FALSE);
  g_return_if_fail (camera->suspended == TRUE);

  /* While a camera is in a suspended state we don't expect the camera
   * to be touched so its transforms shouldn't have changed... */
  g_return_if_fail (camera->at_suspend_transform_age == camera->transform_age);

  state = cogl_object_get_user_data (COGL_OBJECT (fb), &fb_camera_key);

  /* We only expect to be restoring a camera that has been flushed
   * before */
  g_return_if_fail (state != NULL);

  cogl_framebuffer_pop_matrix (fb);

  /* If the save turned out to be redundant then we have nothing
   * else to restore... */
  if (state->current_camera == camera)
    goto done;

  cogl_framebuffer_set_viewport (fb,
                                 camera->viewport[0],
                                 camera->viewport[1],
                                 camera->viewport[2],
                                 camera->viewport[3]);

  cogl_framebuffer_set_projection_matrix (fb, &camera->projection);

  state->current_camera = camera;
  state->transform_age = camera->transform_age;

done:
  camera->in_frame = TRUE;
  camera->suspended = FALSE;
}
Beispiel #6
0
static void
cogland_compositor_create_output (CoglandCompositor *compositor,
                                  int x,
                                  int y,
                                  int width,
                                  int height)
{
  CoglandOutput *output = g_slice_new0 (CoglandOutput);
  CoglFramebuffer *fb;
  GError *error = NULL;

  output->wayland_output.interface = &wl_output_interface;

  wl_display_add_object (compositor->wayland_display, &output->wayland_output);
  wl_display_add_global (compositor->wayland_display, &output->wayland_output,
                         cogland_output_post_geometry);

  output->onscreen = cogl_onscreen_new (compositor->cogl_context,
                                        width, height);
  /* Eventually there will be an implicit allocate on first use so this
   * will become optional... */
  fb = COGL_FRAMEBUFFER (output->onscreen);
  if (!cogl_framebuffer_allocate (fb, &error))
    g_error ("Failed to allocate framebuffer: %s\n", error->message);

  cogl_onscreen_show (output->onscreen);
#if 0
  cogl_framebuffer_set_viewport (fb, x, y, width, height);
#else
  cogl_push_framebuffer (fb);
  cogl_set_viewport (-x, -y,
                     compositor->virtual_width,
                     compositor->virtual_height);
  cogl_pop_framebuffer ();
#endif

  compositor->outputs = g_list_prepend (compositor->outputs, output);
}
Beispiel #7
0
int
main (int argc, char **argv)
{
  CoglContext *ctx;
  CoglOnscreen *onscreen;
  CoglFramebuffer *fb;
  GError *error = NULL;
  Data data;
  PangoRectangle hello_label_size;
  float fovy, aspect, z_near, z_2d, z_far;
  CoglDepthState depth_state;
  CoglBool has_swap_notify;

  ctx = cogl_context_new (NULL, &error);
  if (!ctx) {
      fprintf (stderr, "Failed to create context: %s\n", error->message);
      return 1;
  }

  onscreen = cogl_onscreen_new (ctx, 640, 480);
  fb = COGL_FRAMEBUFFER (onscreen);
  data.fb = fb;
  data.framebuffer_width = cogl_framebuffer_get_width (fb);
  data.framebuffer_height = cogl_framebuffer_get_height (fb);

  data.timer = g_timer_new ();

  cogl_onscreen_show (onscreen);

  cogl_framebuffer_set_viewport (fb,
                                 0, 0,
                                 data.framebuffer_width,
                                 data.framebuffer_height);

  fovy = 60; /* y-axis field of view */
  aspect = (float)data.framebuffer_width/(float)data.framebuffer_height;
  z_near = 0.1; /* distance to near clipping plane */
  z_2d = 1000; /* position to 2d plane */
  z_far = 2000; /* distance to far clipping plane */

  cogl_framebuffer_perspective (fb, fovy, aspect, z_near, z_far);

  /* Since the pango renderer emits geometry in pixel/device coordinates
   * and the anti aliasing is implemented with the assumption that the
   * geometry *really* does end up pixel aligned, we setup a modelview
   * matrix so that for geometry in the plane z = 0 we exactly map x
   * coordinates in the range [0,stage_width] and y coordinates in the
   * range [0,stage_height] to the framebuffer extents with (0,0) being
   * the top left.
   *
   * This is roughly what Clutter does for a ClutterStage, but this
   * demonstrates how it is done manually using Cogl.
   */
  cogl_matrix_init_identity (&data.view);
  cogl_matrix_view_2d_in_perspective (&data.view, fovy, aspect, z_near, z_2d,
                                      data.framebuffer_width,
                                      data.framebuffer_height);
  cogl_framebuffer_set_modelview_matrix (fb, &data.view);

  /* Initialize some convenient constants */
  cogl_matrix_init_identity (&identity);
  cogl_color_set_from_4ub (&white, 0xff, 0xff, 0xff, 0xff);

  /* rectangle indices allow the GPU to interpret a list of quads (the
   * faces of our cube) as a list of triangles.
   *
   * Since this is a very common thing to do
   * cogl_get_rectangle_indices() is a convenience function for
   * accessing internal index buffers that can be shared.
   */
  data.indices = cogl_get_rectangle_indices (ctx, 6 /* n_rectangles */);
  data.prim = cogl_primitive_new_p3t2 (ctx, COGL_VERTICES_MODE_TRIANGLES,
                                       G_N_ELEMENTS (vertices),
                                       vertices);
  /* Each face will have 6 indices so we have 6 * 6 indices in total... */
  cogl_primitive_set_indices (data.prim,
                              data.indices,
                              6 * 6);

  /* Load a jpeg crate texture from a file */
  printf ("crate.jpg (CC by-nc-nd http://bit.ly/9kP45T) ShadowRunner27 http://bit.ly/m1YXLh\n");
  data.texture = cogl_texture_new_from_file (COGL_EXAMPLES_DATA "crate.jpg",
                                             COGL_TEXTURE_NO_SLICING,
                                             COGL_PIXEL_FORMAT_ANY,
                                             &error);
  if (!data.texture)
    g_error ("Failed to load texture: %s", error->message);

  /* a CoglPipeline conceptually describes all the state for vertex
   * processing, fragment processing and blending geometry. When
   * drawing the geometry for the crate this pipeline says to sample a
   * single texture during fragment processing... */
  data.crate_pipeline = cogl_pipeline_new (ctx);
  cogl_pipeline_set_layer_texture (data.crate_pipeline, 0, data.texture);

  /* Since the box is made of multiple triangles that will overlap
   * when drawn and we don't control the order they are drawn in, we
   * enable depth testing to make sure that triangles that shouldn't
   * be visible get culled by the GPU. */
  cogl_depth_state_init (&depth_state);
  cogl_depth_state_set_test_enabled (&depth_state, TRUE);

  cogl_pipeline_set_depth_state (data.crate_pipeline, &depth_state, NULL);

  /* Setup a Pango font map and context */

  data.pango_font_map = COGL_PANGO_FONT_MAP (cogl_pango_font_map_new (ctx));

  cogl_pango_font_map_set_use_mipmapping (data.pango_font_map, TRUE);

  data.pango_context =
    pango_font_map_create_context (PANGO_FONT_MAP (data.pango_font_map));

  data.pango_font_desc = pango_font_description_new ();
  pango_font_description_set_family (data.pango_font_desc, "Sans");
  pango_font_description_set_size (data.pango_font_desc, 30 * PANGO_SCALE);

  /* Setup the "Hello Cogl" text */

  data.hello_label = pango_layout_new (data.pango_context);
  pango_layout_set_font_description (data.hello_label, data.pango_font_desc);
  pango_layout_set_text (data.hello_label, "Hello Cogl", -1);

  pango_layout_get_extents (data.hello_label, NULL, &hello_label_size);
  data.hello_label_width = PANGO_PIXELS (hello_label_size.width);
  data.hello_label_height = PANGO_PIXELS (hello_label_size.height);

  data.swap_ready = TRUE;

  has_swap_notify =
    cogl_has_feature (ctx, COGL_FEATURE_ID_SWAP_BUFFERS_EVENT);

  if (has_swap_notify)
    cogl_onscreen_add_swap_buffers_callback (COGL_ONSCREEN (fb),
                                             swap_notify_cb,
                                             &data);

  while (1)
    {
      CoglPollFD *poll_fds;
      int n_poll_fds;
      int64_t timeout;

      if (data.swap_ready)
        {
          paint (&data);
          cogl_onscreen_swap_buffers (COGL_ONSCREEN (fb));
        }

      cogl_poll_get_info (ctx, &poll_fds, &n_poll_fds, &timeout);

      if (!has_swap_notify)
        {
          /* If the winsys doesn't support swap event notification
             then we'll just redraw constantly */
          data.swap_ready = TRUE;
          timeout = 0;
        }

      g_poll ((GPollFD *) poll_fds, n_poll_fds,
              timeout == -1 ? -1 : timeout / 1000);

      cogl_poll_dispatch (ctx, poll_fds, n_poll_fds);
    }

  return 0;
}