Beispiel #1
0
static void
set_my_viewport(struct box *box)
{
	wl_fixed_t src_x, src_y, src_width, src_height;
	int32_t dst_width = SURFACE_WIDTH;
	int32_t dst_height = SURFACE_HEIGHT;

	if (box->mode == MODE_NO_VIEWPORT)
		return;

	/* Cut the green border in half, take white border fully in,
	 * and black border fully out. The borders are 1px wide in buffer.
	 *
	 * The gl-renderer uses linear texture sampling, this means the
	 * top and left edges go to 100% green, bottom goes to 50% blue/black,
	 * right edge has thick white sliding to 50% red.
	 */
	src_x = wl_fixed_from_double((RECT_X + 0.5) / BUFFER_SCALE);
	src_y = wl_fixed_from_double((RECT_Y + 0.5) / BUFFER_SCALE);
	src_width = wl_fixed_from_double((RECT_W - 0.5) / BUFFER_SCALE);
	src_height = wl_fixed_from_double((RECT_H - 0.5) / BUFFER_SCALE);

	if (box->scaler_version < 2 && box->mode != MODE_SRC_DST) {
		fprintf(stderr, "Error: server's wl_scaler interface version "
			"%d does not support this mode.\n",
			box->scaler_version);
		exit(1);
	}

	switch (box->mode){
	case MODE_SRC_ONLY:
		wl_viewport_set_source(box->viewport, src_x, src_y,
				       src_width, src_height);
		break;
	case MODE_DST_ONLY:
		wl_viewport_set_destination(box->viewport,
					    dst_width, dst_height);
		break;
	case MODE_SRC_DST:
		if (box->scaler_version < 2) {
			wl_viewport_set(box->viewport,
					src_x, src_y, src_width, src_height,
					dst_width, dst_height);
		} else {
			wl_viewport_set_source(box->viewport, src_x, src_y,
					       src_width, src_height);
			wl_viewport_set_destination(box->viewport,
						    dst_width, dst_height);
		}
		break;
	default:
		assert(!"not reached");
	}
}
static gboolean
gst_mfx_window_wayland_resize (GstMfxWindow * window, guint width, guint height)
{
  GstMfxWindowWaylandPrivate *const priv =
      GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window);
  GstMfxDisplayWaylandPrivate *const priv_display =
      GST_MFX_DISPLAY_WAYLAND_GET_PRIVATE (GST_MFX_WINDOW_DISPLAY (window));

  GST_DEBUG ("resize window, new size %ux%u", width, height);

  GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window));

#ifdef USE_WESTON_4_0
  if (priv->wp_viewport)
    wp_viewport_set_destination (priv->wp_viewport, width, height);
#else
  if (priv->viewport)
    wl_viewport_set_destination (priv->viewport, width, height);
#endif

  wl_surface_damage (priv->surface, 0, 0, width, height);
  wl_surface_commit (priv->surface);

  if (priv->opaque_region)
    wl_region_destroy (priv->opaque_region);

  priv->opaque_region = wl_compositor_create_region (priv_display->compositor);
  wl_region_add (priv->opaque_region, 0, 0, width, height);

  GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window));

  return TRUE;
}
Beispiel #3
0
void
gst_wl_window_set_render_rectangle (GstWlWindow * window, gint x, gint y,
    gint w, gint h)
{
  g_return_if_fail (window != NULL);

  window->render_rectangle.x = x;
  window->render_rectangle.y = y;
  window->render_rectangle.w = w;
  window->render_rectangle.h = h;

  /* position the area inside the parent - needs a parent commit to apply */
  if (window->area_subsurface)
    wl_subsurface_set_position (window->area_subsurface, x, y);

  /* change the size of the area */
  wl_viewport_set_destination (window->area_viewport, w, h);

  if (window->video_width != 0) {
    wl_subsurface_set_sync (window->video_subsurface);
    gst_wl_window_resize_video_surface (window, TRUE);
  }

  wl_surface_damage (window->area_surface, 0, 0, w, h);
  wl_surface_commit (window->area_surface);

  if (window->video_width != 0)
    wl_subsurface_set_desync (window->video_subsurface);
}
Beispiel #4
0
static void
gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit)
{
  GstVideoRectangle src, res;

  /* center the video_subsurface inside area_subsurface */
  src.w = window->video_width;
  src.h = window->video_height;
  gst_video_sink_center_rect (src, window->render_rectangle, &res, TRUE);

  wl_subsurface_set_position (window->video_subsurface, res.x, res.y);
  wl_viewport_set_destination (window->video_viewport, res.w, res.h);

  if (commit) {
    wl_surface_damage (window->video_surface, 0, 0, res.w, res.h);
    wl_surface_commit (window->video_surface);
  }

  if (gst_wl_window_is_toplevel (window)) {
    struct wl_region *region;

    region = wl_compositor_create_region (window->display->compositor);
    wl_region_add(region, 0, 0, window->render_rectangle.w, window->render_rectangle.h);
    wl_surface_set_input_region (window->area_surface, region);
    wl_region_destroy (region);
  }

  /* this is saved for use in wl_surface_damage */
  window->surface_width = res.w;
  window->surface_height = res.h;
}
Beispiel #5
0
static void
gst_wl_window_resize_internal (GstWlWindow * window, gboolean commit)
{
  GstVideoRectangle src, res;

  src.w = window->video_width;
  src.h = window->video_height;
  gst_video_sink_center_rect (src, window->render_rectangle, &res, TRUE);

  if (window->subsurface)
    wl_subsurface_set_position (window->subsurface,
        window->render_rectangle.x + res.x, window->render_rectangle.y + res.y);
  wl_viewport_set_destination (window->viewport, res.w, res.h);

  if (commit) {
    wl_surface_damage (window->surface, 0, 0, res.w, res.h);
    wl_surface_commit (window->surface);
  }

  /* this is saved for use in wl_surface_damage */
  window->surface_width = res.w;
  window->surface_height = res.h;
}
static gboolean
gst_mfx_window_wayland_render (GstMfxWindow * window,
    GstMfxSurface * surface,
    const GstMfxRectangle * src_rect, const GstMfxRectangle * dst_rect)
{
  GstMfxWindowWaylandPrivate *const priv =
      GST_MFX_WINDOW_WAYLAND_GET_PRIVATE (window);
  GstMfxDisplayWaylandPrivate *const display_priv =
      GST_MFX_DISPLAY_WAYLAND_GET_PRIVATE (GST_MFX_WINDOW_DISPLAY (window));
  struct wl_display *const display =
      GST_MFX_DISPLAY_HANDLE (GST_MFX_WINDOW_DISPLAY (window));
  GstMfxPrimeBufferProxy *buffer_proxy;
  struct wl_buffer *buffer;
  FrameState *frame;
  guintptr fd = 0;
  guint32 drm_format = 0;
  gint offsets[3] = { 0 }, pitches[3] = { 0 }, num_planes = 0, i = 0;
  VaapiImage *vaapi_image;

  buffer_proxy = gst_mfx_prime_buffer_proxy_new_from_surface (surface);
  if (!buffer_proxy)
    return FALSE;

  fd = GST_MFX_PRIME_BUFFER_PROXY_HANDLE (buffer_proxy);
  vaapi_image = gst_mfx_prime_buffer_proxy_get_vaapi_image (buffer_proxy);
  num_planes = vaapi_image_get_plane_count (vaapi_image);

  if ((dst_rect->height != src_rect->height)
      || (dst_rect->width != src_rect->width)) {
#ifdef USE_WESTON_4_0
    if (priv->wp_viewport) {
      wp_viewport_set_destination (priv->wp_viewport,
          dst_rect->width, dst_rect->height);
    }
#else
    if (priv->viewport) {
      wl_viewport_set_destination (priv->viewport,
          dst_rect->width, dst_rect->height);
    }
#endif
  }

  for (i = 0; i < num_planes; i++) {
    offsets[i] = vaapi_image_get_offset (vaapi_image, i);
    pitches[i] = vaapi_image_get_pitch (vaapi_image, i);
  }

  if (GST_VIDEO_FORMAT_NV12 == vaapi_image_get_format (vaapi_image)) {
    drm_format = WL_DRM_FORMAT_NV12;
  } else if (GST_VIDEO_FORMAT_BGRA == vaapi_image_get_format (vaapi_image)) {
    drm_format = WL_DRM_FORMAT_ARGB8888;
  }

  if (!drm_format)
    goto error;

  if (!display_priv->drm)
    goto error;

  GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window));
  buffer =
      wl_drm_create_prime_buffer (display_priv->drm, fd,
          src_rect->width, src_rect->height, drm_format,
          offsets[0], pitches[0],
          offsets[1], pitches[1],
          offsets[2], pitches[2]);
  GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window));
  if (!buffer) {
    GST_ERROR ("No wl_buffer created\n");
    goto error;
  }

  frame = frame_state_new (window);
  if (!frame)
    goto error;

  g_atomic_pointer_set (&priv->last_frame, frame);
  g_atomic_int_inc (&priv->num_frames_pending);

  GST_MFX_DISPLAY_LOCK (GST_MFX_WINDOW_DISPLAY (window));
  wl_surface_attach (priv->surface, buffer, 0, 0);

  wl_surface_damage (priv->surface, 0, 0, dst_rect->width, dst_rect->height);

  if (priv->opaque_region) {
    wl_surface_set_opaque_region (priv->surface, priv->opaque_region);
    wl_region_destroy (priv->opaque_region);
    priv->opaque_region = NULL;
  }
  wl_proxy_set_queue ((struct wl_proxy *) buffer, priv->event_queue);
  wl_buffer_add_listener (buffer, &frame_buffer_listener, frame);

  frame->callback = wl_surface_frame (priv->surface);
  wl_callback_add_listener (frame->callback, &frame_callback_listener, frame);

  wl_surface_commit (priv->surface);
  wl_display_flush (display);

  GST_MFX_DISPLAY_UNLOCK (GST_MFX_WINDOW_DISPLAY (window));

  vaapi_image_unref (vaapi_image);
  gst_mfx_prime_buffer_proxy_unref (buffer_proxy);

  return TRUE;
error:
  {
    vaapi_image_unref (vaapi_image);
    gst_mfx_prime_buffer_proxy_unref (buffer_proxy);
    return FALSE;
  }
}
Beispiel #7
0
static void
redraw(void *data, struct wl_callback *callback, uint32_t time)
{
	struct window *window = data;
	struct buffer *buffer;
	int off_x, off_y, bwidth, bheight, bborder, bpitch, bradius;
	uint32_t *buffer_data;
	float bx, by;

	buffer = window_next_buffer(window);
	if (!buffer) {
		fprintf(stderr,
			!callback ? "Failed to create the first buffer.\n" :
			"Both buffers busy at redraw(). Server bug?\n");
		abort();
	}

	/* Rotate the damage, but keep the even/odd parity so the
	 * dimensions of the buffers don't change */
	if (window->flags & WINDOW_FLAG_ROTATING_TRANSFORM)
		window->transform = (window->transform + 2) % 8;

	switch (window->transform) {
	default:
	case WL_OUTPUT_TRANSFORM_NORMAL:
	case WL_OUTPUT_TRANSFORM_180:
	case WL_OUTPUT_TRANSFORM_FLIPPED:
	case WL_OUTPUT_TRANSFORM_FLIPPED_180:
		bwidth = window->width * window->scale;
		bheight = window->height * window->scale;
		break;
	case WL_OUTPUT_TRANSFORM_90:
	case WL_OUTPUT_TRANSFORM_270:
	case WL_OUTPUT_TRANSFORM_FLIPPED_90:
	case WL_OUTPUT_TRANSFORM_FLIPPED_270:
		bwidth = window->height * window->scale;
		bheight = window->width * window->scale;
		break;
	}

	bpitch = bwidth;

	bborder = window->border * window->scale;
	bradius = window->ball.radius * window->scale;

	buffer_data = buffer->shm_data;
	if (window->viewport) {
		/* Fill the whole thing with red to detect viewport errors */
		paint_box(buffer->shm_data, bpitch, 0, 0, bwidth, bheight,
			  0xffff0000);

		/* The buffer is the same size.  However, we crop it
		 * and scale it up by a factor of 2 */
		bborder /= 2;
		bradius /= 2;
		bwidth /= 2;
		bheight /= 2;

		/* Offset the drawing region */
		off_x = (window->width / 3) * window->scale;
		off_y = (window->height / 5) * window->scale;
		switch (window->transform) {
		default:
		case WL_OUTPUT_TRANSFORM_NORMAL:
			buffer_data += off_y * bpitch + off_x;
			break;
		case WL_OUTPUT_TRANSFORM_90:
			buffer_data += off_x * bpitch + (bwidth - off_y);
			break;
		case WL_OUTPUT_TRANSFORM_180:
			buffer_data += (bheight - off_y) * bpitch +
				       (bwidth - off_x);
			break;
		case WL_OUTPUT_TRANSFORM_270:
			buffer_data += (bheight - off_x) * bpitch + off_y;
			break;
		case WL_OUTPUT_TRANSFORM_FLIPPED:
			buffer_data += off_y * bpitch + (bwidth - off_x);
			break;
		case WL_OUTPUT_TRANSFORM_FLIPPED_90:
			buffer_data += (bheight - off_x) * bpitch +
				       (bwidth - off_y);
			break;
		case WL_OUTPUT_TRANSFORM_FLIPPED_180:
			buffer_data += (bheight - off_y) * bpitch + off_x;
			break;
		case WL_OUTPUT_TRANSFORM_FLIPPED_270:
			buffer_data += off_x * bpitch + off_y;
			break;
		}
		wl_viewport_set_source(window->viewport,
				       wl_fixed_from_int(window->width / 3),
				       wl_fixed_from_int(window->height / 5),
				       wl_fixed_from_int(window->width / 2),
				       wl_fixed_from_int(window->height / 2));
	}

	/* Paint the border */
	paint_box(buffer_data, bpitch, 0, 0, bwidth, bborder, 0xffffffff);
	paint_box(buffer_data, bpitch, 0, 0, bborder, bheight, 0xffffffff);
	paint_box(buffer_data, bpitch,
		  bwidth - bborder, 0, bborder, bheight, 0xffffffff);
	paint_box(buffer_data, bpitch,
		  0, bheight - bborder, bwidth, bborder, 0xffffffff);

	/* fill with translucent */
	paint_box(buffer_data, bpitch, bborder, bborder,
		  bwidth - 2 * bborder, bheight - 2 * bborder, 0x80000000);

	/* Damage where the ball was */
	wl_surface_damage(window->surface,
			  window->ball.x - window->ball.radius,
			  window->ball.y - window->ball.radius,
			  window->ball.radius * 2 + 1,
			  window->ball.radius * 2 + 1);

	window_advance_game(window, time);

	window_get_transformed_ball(window, &bx, &by);

	/* Paint the ball */
	paint_circle(buffer_data, bpitch, bx, by, bradius, 0xff00ff00);

	if (print_debug) {
		printf("Ball now located at (%f, %f)\n",
		       window->ball.x, window->ball.y);

		printf("Circle painted at (%f, %f), radius %d\n", bx, by,
		       bradius);

		printf("Buffer damage rectangle: (%d, %d) @ %dx%d\n",
		       (int)(bx - bradius), (int)(by - bradius),
		       bradius * 2 + 1, bradius * 2 + 1);
	}

	/* Damage where the ball is now */
	wl_surface_damage(window->surface,
			  window->ball.x - window->ball.radius,
			  window->ball.y - window->ball.radius,
			  window->ball.radius * 2 + 1,
			  window->ball.radius * 2 + 1);

	wl_surface_attach(window->surface, buffer->buffer, 0, 0);

	if (window->display->compositor_version >= 2 &&
	    (window->transform != WL_OUTPUT_TRANSFORM_NORMAL ||
	     window->flags & WINDOW_FLAG_ROTATING_TRANSFORM))
		wl_surface_set_buffer_transform(window->surface,
						window->transform);

	if (window->viewport)
		wl_viewport_set_destination(window->viewport,
					    window->width,
					    window->height);

	if (window->scale != 1)
		wl_surface_set_buffer_scale(window->surface,
					    window->scale);

	if (callback)
		wl_callback_destroy(callback);

	window->callback = wl_surface_frame(window->surface);
	wl_callback_add_listener(window->callback, &frame_listener, window);
	wl_surface_commit(window->surface);
	buffer->busy = 1;
}