예제 #1
0
/*
 * This function will effectively set the pointer (mouse) cursor
 * depending on the GLUT_CURSOR_* choice.
 */
void fghPointerSetCursor( SFG_Window* window,
                          struct wl_pointer* pointer,
                          uint32_t serial )
{
    struct wl_cursor_image* image;
    struct wl_buffer* buffer;

    image = window->Window.pContext.cursor->images[0];
    buffer = wl_cursor_image_get_buffer( image );

    wl_surface_attach( window->Window.pContext.cursor_surface, buffer,
                       0, 0 );
    wl_surface_damage( window->Window.pContext.cursor_surface, 0, 0,
                       image->width, image->height );
    wl_surface_commit( window->Window.pContext.cursor_surface );

    wl_pointer_set_cursor( pointer, serial,
                           window->Window.pContext.cursor_surface,
                           image->hotspot_x, image->hotspot_y );
}
예제 #2
0
static void
window_attach_surface(struct window *window)
{
	struct display *display = window->display;
	struct wl_buffer *buffer;
	int32_t x, y;

	if (window->pending_surface != NULL)
		return;

	window->pending_surface = window->cairo_surface;
	window->cairo_surface = NULL;

	buffer = display_get_buffer_for_surface(display,
						window->pending_surface);
	if (window->resize_edges & WINDOW_RESIZING_LEFT)
		x = window->server_allocation.width -
			window->allocation.width;
	else
		x = 0;

	if (window->resize_edges & WINDOW_RESIZING_TOP)
		y = window->server_allocation.height -
			window->allocation.height;
	else
		y = 0;

	window->server_allocation = window->allocation;
	window->resize_edges = 0;
	wl_surface_attach(window->surface, buffer, x, y);
	wl_display_sync_callback(display->display, free_surface, window);

	if (!window->mapped) {
		wl_surface_map_toplevel(window->surface);
		window->mapped = 1;
	}

	wl_surface_damage(window->surface, 0, 0,
			  window->allocation.width,
			  window->allocation.height);
}
예제 #3
0
static Eina_Bool
_ecore_wl_input_cursor_update(void *data)
{
   struct wl_cursor_image *cursor_image;
   struct wl_buffer *buffer;
   Ecore_Wl_Input *input = data;
   unsigned int delay;

   cursor_image = input->cursor->images[input->cursor_current_index];
   if (!cursor_image) return ECORE_CALLBACK_RENEW;

   if ((buffer = wl_cursor_image_get_buffer(cursor_image)))
     {
        ecore_wl_input_pointer_set(input, input->cursor_surface,
                                   cursor_image->hotspot_x,
                                   cursor_image->hotspot_y);
        wl_surface_attach(input->cursor_surface, buffer, 0, 0);
        wl_surface_damage(input->cursor_surface, 0, 0,
                          cursor_image->width, cursor_image->height);
        wl_surface_commit(input->cursor_surface);

        if ((input->cursor->image_count > 1) && (!input->cursor_frame_cb))
          _ecore_wl_input_cb_pointer_frame(input, NULL, 0);
     }

   if (input->cursor->image_count <= 1)
     return ECORE_CALLBACK_CANCEL;

   delay = cursor_image->delay;
   input->cursor_current_index =
      (input->cursor_current_index + 1) % input->cursor->image_count;

   if (!input->cursor_timer)
     input->cursor_timer =
        ecore_timer_loop_add(delay / 1000.0,
                             _ecore_wl_input_cursor_update, input);
   else
     ecore_timer_interval_set(input->cursor_timer, delay / 1000.0);

   return ECORE_CALLBACK_RENEW;
}
static void
pointer_handle_enter (void *data, struct wl_pointer *pointer, uint32_t serial,
    struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
  GstGLWindowWaylandEGL *window_egl = data;
  struct wl_buffer *buffer;
  struct wl_cursor_image *image = NULL;

  window_egl->display.serial = serial;

  if (window_egl->display.default_cursor) {
    image = window_egl->display.default_cursor->images[0];
    buffer = wl_cursor_image_get_buffer (image);
    wl_pointer_set_cursor (pointer, serial,
        window_egl->display.cursor_surface, image->hotspot_x, image->hotspot_y);
    wl_surface_attach (window_egl->display.cursor_surface, buffer, 0, 0);
    wl_surface_damage (window_egl->display.cursor_surface, 0, 0,
        image->width, image->height);
    wl_surface_commit (window_egl->display.cursor_surface);
  }
}
예제 #5
0
int
main(int argc, char **argv)
{
	struct sigaction sigint;
	struct display *display;
	struct window *window;
	int ret = 0;

	display = create_display();
	window = create_window(display, 250, 250);
	if (!window)
		return 1;

	sigint.sa_handler = signal_int;
	sigemptyset(&sigint.sa_mask);
	sigint.sa_flags = SA_RESETHAND;
	sigaction(SIGINT, &sigint, NULL);

	/* Initialise damage to full surface, so the padding gets painted */
	wl_surface_damage(window->surface, 0, 0,
			  window->width, window->height);

	redraw(window, NULL, 0);

	while (running && ret != -1)
		ret = wl_display_dispatch(display->display);

	fprintf(stderr, "simple-shm exiting\n");

	if (window->display->ivi_application)
	{
		ivi_surface_destroy(window->ivi_surface);
		ivi_application_destroy(window->display->ivi_application);
	}

	destroy_window(window);
	destroy_display(display);

	return 0;
}
예제 #6
0
static void
gst_wl_window_resize_video_surface (GstWlWindow * window, gboolean commit)
{
  GstVideoRectangle src = { 0, };
  GstVideoRectangle dst = { 0, };
  GstVideoRectangle res;

  /* center the video_subsurface inside area_subsurface */
  src.w = window->video_width;
  src.h = window->video_height;
  dst.w = window->render_rectangle.w;
  dst.h = window->render_rectangle.h;

  if (window->video_viewport) {
    gst_video_sink_center_rect (src, dst, &res, TRUE);
    wp_viewport_set_destination (window->video_viewport, res.w, res.h);
  } else {
    gst_video_sink_center_rect (src, dst, &res, FALSE);
  }

  wl_subsurface_set_position (window->video_subsurface, res.x, res.y);

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

  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->video_rectangle = res;
}
예제 #7
0
void
move_client(struct client *client, int x, int y)
{
	struct surface *surface = client->surface;
	int done;

	client->surface->x = x;
	client->surface->y = y;
	wl_test_move_surface(client->test->wl_test, surface->wl_surface,
			     surface->x, surface->y);
	/* The attach here is necessary because commit() will call congfigure
	 * only on surfaces newly attached, and the one that sets the surface
	 * position is the configure. */
	wl_surface_attach(surface->wl_surface, surface->wl_buffer, 0, 0);
	wl_surface_damage(surface->wl_surface, 0, 0, surface->width,
			  surface->height);

	frame_callback_set(surface->wl_surface, &done);

	wl_surface_commit(surface->wl_surface);

	frame_callback_wait(client, &done);
}
예제 #8
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;
}
예제 #9
0
파일: simple-shm.c 프로젝트: N8Fear/adwc
static void
redraw(void *data, struct wl_callback *callback, uint32_t time)
{
	struct window *window = data;
	uint32_t *p;
	int i, end, offset;

	p = window->shm_data;
	end = window->width * window->height;
	offset = time >> 4;
	for (i = 0; i < end; i++)
		p[i] = (i + offset) * 0x0080401;

	wl_surface_attach(window->surface, window->buffer, 0, 0);
	wl_surface_damage(window->surface,
			  0, 0, window->width, window->height);

	if (callback)
		wl_callback_destroy(callback);

	window->callback = wl_surface_frame(window->surface);
	wl_callback_add_listener(window->callback, &frame_listener, window);
}
static gboolean
gst_vaapi_window_wayland_render (GstVaapiWindow * window,
                                 GstVaapiSurface * surface,
                                 const GstVaapiRectangle * src_rect,
                                 const GstVaapiRectangle * dst_rect, guint flags)
{
    GstVaapiWindowWaylandPrivate *const priv =
        GST_VAAPI_WINDOW_WAYLAND_GET_PRIVATE (window);
    GstVaapiDisplay *const display = GST_VAAPI_OBJECT_DISPLAY (window);
    struct wl_display *const wl_display =
        GST_VAAPI_OBJECT_NATIVE_DISPLAY (window);
    struct wl_buffer *buffer;
    FrameState *frame;
    guint width, height, va_flags;
    VAStatus status;
    gboolean need_vpp = FALSE;

    /* Check that we don't need to crop source VA surface */
    gst_vaapi_surface_get_size (surface, &width, &height);
    if (src_rect->x != 0 || src_rect->y != 0)
        need_vpp = TRUE;
    if (src_rect->width != width || src_rect->height != height)
        need_vpp = TRUE;

    /* Check that we don't render to a subregion of this window */
    if (dst_rect->x != 0 || dst_rect->y != 0)
        need_vpp = TRUE;
    if (dst_rect->width != window->width || dst_rect->height != window->height)
        need_vpp = TRUE;

    /* Try to construct a Wayland buffer from VA surface as is (without VPP) */
    if (!need_vpp) {
        GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
        va_flags = from_GstVaapiSurfaceRenderFlags (flags);
        status = vaGetSurfaceBufferWl (GST_VAAPI_DISPLAY_VADISPLAY (display),
                                       GST_VAAPI_OBJECT_ID (surface),
                                       va_flags & (VA_TOP_FIELD | VA_BOTTOM_FIELD), &buffer);
        GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
        if (status == VA_STATUS_ERROR_FLAG_NOT_SUPPORTED)
            need_vpp = TRUE;
        else if (!vaapi_check_status (status, "vaGetSurfaceBufferWl()"))
            return FALSE;
    }

    /* Try to construct a Wayland buffer with VPP */
    if (need_vpp) {
        if (priv->use_vpp) {
            GstVaapiSurface *const vpp_surface =
                vpp_convert (window, surface, src_rect, dst_rect, flags);
            if (G_UNLIKELY (!vpp_surface))
                need_vpp = FALSE;
            else {
                surface = vpp_surface;
                width = window->width;
                height = window->height;
            }
        }

        GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
        status = vaGetSurfaceBufferWl (GST_VAAPI_DISPLAY_VADISPLAY (display),
                                       GST_VAAPI_OBJECT_ID (surface), VA_FRAME_PICTURE, &buffer);
        GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
        if (!vaapi_check_status (status, "vaGetSurfaceBufferWl()"))
            return FALSE;
    }

    /* Wait for the previous frame to complete redraw */
    if (!gst_vaapi_window_wayland_sync (window)) {
        wl_buffer_destroy (buffer);
        return !priv->sync_failed;
    }

    frame = frame_state_new (window);
    if (!frame)
        return FALSE;
    g_atomic_pointer_set (&priv->last_frame, frame);
    g_atomic_int_inc (&priv->num_frames_pending);

    if (need_vpp && priv->use_vpp) {
        frame->surface = surface;
        frame->surface_pool = gst_vaapi_video_pool_ref (priv->surface_pool);
    }

    /* XXX: attach to the specified target rectangle */
    GST_VAAPI_OBJECT_LOCK_DISPLAY (window);
    wl_surface_attach (priv->surface, buffer, 0, 0);
    wl_surface_damage (priv->surface, 0, 0, width, 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 (wl_display);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY (window);
    return TRUE;
}
static GstFlowReturn
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
{
  GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
  gboolean mem_cpy = TRUE;
  GstVideoRectangle src, dst, res;

  GST_LOG_OBJECT (sink,
      "render buffer %p, data = %p, timestamp = %" GST_TIME_FORMAT, buffer,
      GST_BUFFER_DATA (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));

  if (!sink->window)
    create_window (sink, sink->display, sink->video_width, sink->video_height);

  if (sink->render_finish) {
    if (GST_IS_WLBUFFER (buffer)) {
      GstWlBuffer *tmp_buffer = (GstWlBuffer *) buffer;

      /* Does it have a waylandbuffer ? */
      if (tmp_buffer->wbuffer) {
        mem_cpy = FALSE;
        GST_DEBUG_OBJECT (sink, "we have a buffer (%p) we allocated "
            "ourselves and it has a wayland buffer, no memcpy then", buffer);
        sink->window->buffer = tmp_buffer->wbuffer;
      } else {
        /* No wayland buffer, that's a malloc */
        GST_DEBUG_OBJECT (sink, "we have a buffer (%p) we allocated "
            "ourselves but it does not hold a wayland buffer", buffer);
      }
    } else {
      /* Not our baby! */
      GST_DEBUG_OBJECT (sink, "we have a buffer (%p) we did not allocate",
          buffer);
    }

    if (mem_cpy) {

      GstWlBuffer *wlbuf = wayland_buffer_create (sink);

      memcpy (GST_BUFFER_DATA (wlbuf), GST_BUFFER_DATA (buffer),
          GST_BUFFER_SIZE (buffer));
      sink->window->buffer = wlbuf->wbuffer;
    }

    src.w = sink->video_width;
    src.h = sink->video_height;
    dst.w = sink->window->width;
    dst.h = sink->window->height;

    gst_video_sink_center_rect (src, dst, &res, FALSE);

    sink->render_finish = FALSE;

    wl_surface_attach (sink->window->surface, sink->window->buffer, 0, 0);
    wl_surface_damage (sink->window->surface, 0, 0, res.w, res.h);

    if (sink->callback)
      wl_callback_destroy (sink->callback);

    sink->callback = wl_surface_frame (sink->window->surface);
    wl_callback_add_listener (sink->callback, &frame_listener, sink);
    wl_surface_commit (sink->window->surface);

  } else
    GST_LOG_OBJECT (sink,
        "Waiting to get the signal from compositor to render the next frame..");

  wl_display_dispatch (sink->display->display);

  return GST_FLOW_OK;
}
예제 #12
0
static GstStateChangeReturn
gst_wayland_sink_change_state (GstElement * element, GstStateChange transition)
{
  GstWaylandSink *sink = GST_WAYLAND_SINK (element);
  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      if (!gst_wayland_sink_find_display (sink))
        return GST_STATE_CHANGE_FAILURE;
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
  if (ret == GST_STATE_CHANGE_FAILURE)
    return ret;

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      gst_buffer_replace (&sink->last_buffer, NULL);
      if (sink->window) {
        if (gst_wl_window_is_toplevel (sink->window)) {
          g_clear_object (&sink->window);
        } else {
          /* remove buffer from surface, show nothing */
          wl_surface_attach (sink->window->surface, NULL, 0, 0);
          wl_surface_damage (sink->window->surface, 0, 0,
              sink->window->surface_width, sink->window->surface_height);
          wl_surface_commit (sink->window->surface);
          wl_display_flush (sink->display->display);
        }
      }
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      g_mutex_lock (&sink->display_lock);
      /* If we had a toplevel window, we most likely have our own connection
       * to the display too, and it is a good idea to disconnect and allow
       * potentially the application to embed us with GstVideoOverlay
       * (which requires to re-use the same display connection as the parent
       * surface). If we didn't have a toplevel window, then the display
       * connection that we have is definitely shared with the application
       * and it's better to keep it around (together with the window handle)
       * to avoid requesting them again from the application if/when we are
       * restarted (GstVideoOverlay behaves like that in other sinks)
       */
      if (sink->display && !sink->window) {     /* -> the window was toplevel */
        /* Force all buffers to return to the pool, regardless of
         * whether the compositor has released them or not. We are
         * going to kill the display, so we need to return all buffers
         * to be destroyed before this happens.
         * Note that this is done here instead of the pool destructor
         * because the buffers hold a reference to the pool. Also,
         * the buffers can only be unref'ed from the display's event loop
         * and the pool holds a reference to the display. If we drop
         * our references here, when the compositor releases the buffers,
         * they will be unref'ed from the event loop thread, which will
         * unref the pool and therefore the display, which will try to
         * stop the thread from within itself and cause a deadlock.
         */
        if (sink->pool) {
          gst_wayland_compositor_release_all_buffers (GST_WAYLAND_BUFFER_POOL
              (sink->pool));
        }
        g_clear_object (&sink->display);
        g_clear_object (&sink->pool);
      }
      g_mutex_unlock (&sink->display_lock);
      break;
    default:
      break;
  }

  return ret;
}
예제 #13
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;
}
예제 #14
0
static GstFlowReturn
gst_wayland_sink_render (GstBaseSink * bsink, GstBuffer * buffer)
{
  GstWaylandSink *sink = GST_WAYLAND_SINK (bsink);
  GstVideoRectangle src, dst, res;
  GstBuffer *to_render;
  GstWlMeta *meta;
  GstFlowReturn ret;
  struct window *window;
  struct display *display;

  GST_LOG_OBJECT (sink, "render buffer %p", buffer);
  if (!sink->window)
    create_window (sink, sink->display, sink->video_width, sink->video_height);

  window = sink->window;
  display = sink->display;

  meta = gst_buffer_get_wl_meta (buffer);

  if (window->redraw_pending) {
    wl_display_dispatch (display->display);
  }

  if (meta && meta->sink == sink) {
    GST_LOG_OBJECT (sink, "buffer %p from our pool, writing directly", buffer);
    to_render = buffer;
  } else {
    GstMapInfo src;
    GST_LOG_OBJECT (sink, "buffer %p not from our pool, copying", buffer);

    if (!sink->pool)
      goto no_pool;

    if (!gst_buffer_pool_set_active (sink->pool, TRUE))
      goto activate_failed;

    ret = gst_buffer_pool_acquire_buffer (sink->pool, &to_render, NULL);
    if (ret != GST_FLOW_OK)
      goto no_buffer;

    gst_buffer_map (buffer, &src, GST_MAP_READ);
    gst_buffer_fill (to_render, 0, src.data, src.size);
    gst_buffer_unmap (buffer, &src);

    meta = gst_buffer_get_wl_meta (to_render);
  }

  src.w = sink->video_width;
  src.h = sink->video_height;
  dst.w = sink->window->width;
  dst.h = sink->window->height;

  gst_video_sink_center_rect (src, dst, &res, FALSE);

  wl_surface_attach (sink->window->surface, meta->wbuffer, 0, 0);
  wl_surface_damage (sink->window->surface, 0, 0, res.w, res.h);
  window->redraw_pending = TRUE;
  window->callback = wl_surface_frame (window->surface);
  wl_callback_add_listener (window->callback, &frame_callback_listener, window);
  wl_surface_commit (window->surface);
  wl_display_dispatch (display->display);

  if (buffer != to_render)
    gst_buffer_unref (to_render);
  return GST_FLOW_OK;

no_buffer:
  {
    GST_WARNING_OBJECT (sink, "could not create image");
    return ret;
  }
no_pool:
  {
    GST_ELEMENT_ERROR (sink, RESOURCE, WRITE,
        ("Internal error: can't allocate images"),
        ("We don't have a bufferpool negotiated"));
    return GST_FLOW_ERROR;
  }
activate_failed:
  {
    GST_ERROR_OBJECT (sink, "failed to activate bufferpool.");
    ret = GST_FLOW_ERROR;
    return ret;
  }
}
예제 #15
0
int WaylandNativeWindow::queueBuffer(BaseNativeWindowBuffer* buffer, int fenceFd)
{
    WaylandNativeWindowBuffer *wnb = (WaylandNativeWindowBuffer*) buffer;
    int ret = 0;

    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer", "-%p", wnb);
    lock();
    wnb->busy = 1;
    unlock();
    /* XXX locking/something is a bit fishy here */
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);

    while (this->frame_callback && ret != -1) {
        ret = wl_display_dispatch_queue(m_display, this->wl_queue);
    }


    if (ret < 0) {
        TRACE("wl_display_dispatch_queue returned an error");
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);
        check_fatal_error(m_display);
        return ret;
    }

    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_frame_callback", "-%p", wnb);


    lock();

    if (debugenvchecked == 0)
    {
        if (getenv("HYBRIS_WAYLAND_DUMP_BUFFERS") != NULL)
            debugenvchecked = 2;
        else
            debugenvchecked = 1;
    }
    if (debugenvchecked == 2)
    {
        HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb);
        hybris_dump_buffer_to_file(wnb->getNativeBuffer());
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_dumping_buffer", "-%p", wnb);

    }

#if ANDROID_VERSION_MAJOR>=4 && ANDROID_VERSION_MINOR>=2
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb);
    sync_wait(fenceFd, -1);
    close(fenceFd);
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_waiting_for_fence", "-%p", wnb);
#endif

    this->frame_callback = wl_surface_frame(m_window->surface);
    wl_callback_add_listener(this->frame_callback, &frame_listener, this);
    wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
    }
    TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height);
    HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer));

    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    wl_display_flush(m_display);
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer_attachdamagecommit", "-resource@%i", wl_proxy_get_id((struct wl_proxy *) wnb->wlbuffer));

    //--m_freeBufs;
    //pthread_cond_signal(&cond);
    fronted.push_back(wnb);
    HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size());

    if (fronted.size() == m_bufList.size())
    {
        HYBRIS_TRACE_BEGIN("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb);

        /* We have fronted all our buffers, let's wait for one of them to be free */
        do {
            unlock();
            ret = wl_display_dispatch_queue(m_display, this->wl_queue);
            lock();
            if (ret == -1)
            {
                check_fatal_error(m_display);
                break;
            }
            HYBRIS_TRACE_COUNTER("wayland-platform", "fronted.size", "%i", fronted.size());

            if (fronted.size() != m_bufList.size())
                break;
        } while (1);
        HYBRIS_TRACE_END("wayland-platform", "queueBuffer_wait_for_nonfronted_buffer", "-%p", wnb);
    }
    HYBRIS_TRACE_END("wayland-platform", "queueBuffer", "-%p", wnb);
    unlock();

    return NO_ERROR;
}
예제 #16
0
int WaylandNativeWindow::postBuffer(ANativeWindowBuffer* buffer)
{
    TRACE("");
    WaylandNativeWindowBuffer *wnb = NULL;

    lock();
    std::list<WaylandNativeWindowBuffer *>::iterator it = post_registered.begin();
    for (; it != post_registered.end(); it++)
    {
        if ((*it)->other == buffer)
        {
            wnb = (*it);
            break;
        }
    }
    unlock();
    if (!wnb)
    {
        wnb = new WaylandNativeWindowBuffer(buffer);

        wnb->common.incRef(&wnb->common);
        buffer->common.incRef(&buffer->common);
    }

    int ret = 0;

    lock();
    wnb->busy = 1;
    unlock();
    /* XXX locking/something is a bit fishy here */
    while (this->frame_callback && ret != -1) {
        ret = wl_display_dispatch_queue(m_display, this->wl_queue);
    }

    if (ret < 0) {
        TRACE("wl_display_dispatch_queue returned an error:%i", ret);
        check_fatal_error(m_display);
        return ret;
    }

    lock();
    this->frame_callback = wl_surface_frame(m_window->surface);
    wl_callback_add_listener(this->frame_callback, &frame_listener, this);
    wl_proxy_set_queue((struct wl_proxy *) this->frame_callback, this->wl_queue);

    if (wnb->wlbuffer == NULL)
    {
        wnb->wlbuffer_from_native_handle(m_android_wlegl);
        TRACE("%p add listener with %p inside", wnb, wnb->wlbuffer);
        wl_buffer_add_listener(wnb->wlbuffer, &wl_buffer_listener, this);
        wl_proxy_set_queue((struct wl_proxy *) wnb->wlbuffer, this->wl_queue);
        post_registered.push_back(wnb);
    }
    TRACE("%p DAMAGE AREA: %dx%d", wnb, wnb->width, wnb->height);
    wl_surface_attach(m_window->surface, wnb->wlbuffer, 0, 0);
    wl_surface_damage(m_window->surface, 0, 0, wnb->width, wnb->height);
    wl_surface_commit(m_window->surface);
    //--m_freeBufs;
    //pthread_cond_signal(&cond);
    posted.push_back(wnb);
    unlock();

    return NO_ERROR;
}
예제 #17
0
/**
 * Called via eglSwapBuffers(), drv->API.SwapBuffers().
 */
static EGLBoolean
dri2_swap_buffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
{
   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
   struct dri2_egl_surface *dri2_surf = dri2_egl_surface(draw);
   struct dri2_egl_driver *dri2_drv = dri2_egl_driver(drv);
   struct wl_callback *callback;

   if (dri2_surf->block_swap_buffers) {
      wl_display_flush(dri2_dpy->wl_dpy);
      while (dri2_surf->block_swap_buffers)
         wl_display_iterate(dri2_dpy->wl_dpy, WL_DISPLAY_READABLE);
   }

   dri2_surf->block_swap_buffers = EGL_TRUE;
   callback = wl_surface_frame(dri2_surf->wl_win->surface);
   wl_callback_add_listener(callback, &frame_listener, dri2_surf);

   if (dri2_surf->base.Type == EGL_WINDOW_BIT) {
      pointer_swap(
	    (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT],
	    (const void **) &dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]);

      dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]->attachment = 
	 __DRI_BUFFER_FRONT_LEFT;
      dri2_surf->dri_buffers[__DRI_BUFFER_BACK_LEFT]->attachment = 
	 __DRI_BUFFER_BACK_LEFT;

      swap_wl_buffers(dri2_surf, WL_BUFFER_FRONT, WL_BUFFER_BACK);

      if (!dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT])
	 dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT] =
	    wayland_create_buffer(dri2_surf,
		  dri2_surf->dri_buffers[__DRI_BUFFER_FRONT_LEFT]);

      wl_buffer_damage(dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT], 0, 0,
		       dri2_surf->base.Width, dri2_surf->base.Height);
      wl_surface_attach(dri2_surf->wl_win->surface,
	    dri2_surf->wl_drm_buffer[WL_BUFFER_FRONT],
	    dri2_surf->dx, dri2_surf->dy);
      dri2_surf->wl_buffer_lock[WL_BUFFER_FRONT] = 1;

      dri2_surf->wl_win->attached_width  = dri2_surf->base.Width;
      dri2_surf->wl_win->attached_height = dri2_surf->base.Height;
      /* reset resize growing parameters */
      dri2_surf->dx = 0;
      dri2_surf->dy = 0;

      wl_surface_damage(dri2_surf->wl_win->surface, 0, 0,
	    dri2_surf->base.Width, dri2_surf->base.Height);
   }

   _EGLContext *ctx;
   if (dri2_drv->glFlush) {
      ctx = _eglGetCurrentContext();
      if (ctx && ctx->DrawSurface == &dri2_surf->base)
         dri2_drv->glFlush();
   }

   (*dri2_dpy->flush->flush)(dri2_surf->dri_drawable);
   (*dri2_dpy->flush->invalidate)(dri2_surf->dri_drawable);

   return EGL_TRUE;
}
static gboolean
gst_vaapi_window_wayland_render(
    GstVaapiWindow          *window,
    GstVaapiSurface         *surface,
    const GstVaapiRectangle *src_rect,
    const GstVaapiRectangle *dst_rect,
    guint                    flags
)
{
    GstVaapiWindowWaylandPrivate * const priv =
        GST_VAAPI_WINDOW_WAYLAND(window)->priv;
    GstVaapiDisplay * const display = GST_VAAPI_OBJECT_DISPLAY(window);
    struct wl_display * const wl_display = GST_VAAPI_OBJECT_WL_DISPLAY(window);
    struct wl_buffer *buffer;
    struct wl_callback *callback;
    guint width, height, va_flags;
    VASurfaceID surface_id;
    VAStatus status;

    /* XXX: use VPP to support unusual source and destination rectangles */
    gst_vaapi_surface_get_size(surface, &width, &height);
    if (src_rect->x      != 0     ||
            src_rect->y      != 0     ||
            src_rect->width  != width ||
            src_rect->height != height) {
        GST_ERROR("unsupported source rectangle for rendering");
        return FALSE;
    }

    if (0 && (dst_rect->width != width || dst_rect->height != height)) {
        GST_ERROR("unsupported target rectangle for rendering");
        return FALSE;
    }

    surface_id = GST_VAAPI_OBJECT_ID(surface);
    if (surface_id == VA_INVALID_ID)
        return FALSE;

    GST_VAAPI_OBJECT_LOCK_DISPLAY(window);

    /* Wait for the previous frame to complete redraw */
    if (priv->redraw_pending)
        wl_display_iterate(wl_display, WL_DISPLAY_READABLE);

    /* XXX: use VA/VPP for other filters */
    va_flags = from_GstVaapiSurfaceRenderFlags(flags);
    status = vaGetSurfaceBufferWl(
                 GST_VAAPI_DISPLAY_VADISPLAY(display),
                 surface_id,
                 va_flags & (VA_TOP_FIELD|VA_BOTTOM_FIELD),
                 &buffer
             );
    if (status == VA_STATUS_ERROR_FLAG_NOT_SUPPORTED) {
        /* XXX: de-interlacing flags not supported, try with VPP? */
        status = vaGetSurfaceBufferWl(
                     GST_VAAPI_DISPLAY_VADISPLAY(display),
                     surface_id,
                     VA_FRAME_PICTURE,
                     &buffer
                 );
    }
    if (!vaapi_check_status(status, "vaGetSurfaceBufferWl()"))
        return FALSE;

    /* XXX: attach to the specified target rectangle */
    wl_surface_attach(priv->surface, buffer, 0, 0);
    wl_surface_damage(priv->surface, 0, 0, width, height);

    wl_display_iterate(wl_display, WL_DISPLAY_WRITABLE);
    priv->redraw_pending = TRUE;
    priv->buffer = buffer;

    callback = wl_surface_frame(priv->surface);
    wl_callback_add_listener(callback, &frame_callback_listener, priv);
    GST_VAAPI_OBJECT_UNLOCK_DISPLAY(window);
    return TRUE;
}
예제 #19
0
static struct window *
create_window(struct display *display, int width, int height,
	      enum wl_output_transform transform, int scale,
	      enum window_flags flags)
{
	struct window *window;

	if (display->compositor_version < 2 &&
	    (transform != WL_OUTPUT_TRANSFORM_NORMAL ||
	     flags & WINDOW_FLAG_ROTATING_TRANSFORM)) {
		fprintf(stderr, "wl_surface.buffer_transform unsupported in "
				"wl_surface version %d\n",
			display->compositor_version);
		exit(1);
	}

	if (display->compositor_version < 3 &&
	    (! (flags & WINDOW_FLAG_USE_VIEWPORT)) && scale != 1) {
		fprintf(stderr, "wl_surface.buffer_scale unsupported in "
				"wl_surface version %d\n",
			display->compositor_version);
		exit(1);
	}

	if (display->scaler == NULL && (flags & WINDOW_FLAG_USE_VIEWPORT)) {
		fprintf(stderr, "Compositor does not support wl_viewport");
		exit(1);
	}

	window = calloc(1, sizeof *window);
	if (!window)
		return NULL;

	window->callback = NULL;
	window->display = display;
	window->width = width;
	window->height = height;
	window->border = 10;
	window->flags = flags;
	window->transform = transform;
	window->scale = scale;

	window_init_game(window);

	window->surface = wl_compositor_create_surface(display->compositor);

	if (window->flags & WINDOW_FLAG_USE_VIEWPORT)
		window->viewport = wl_scaler_get_viewport(display->scaler,
							  window->surface);

	if (display->shell) {
		window->xdg_surface =
			xdg_shell_get_xdg_surface(display->shell,
						  window->surface);

		assert(window->xdg_surface);

		xdg_surface_add_listener(window->xdg_surface,
					 &xdg_surface_listener, window);

		xdg_surface_set_title(window->xdg_surface, "simple-damage");
	} else if (display->fshell) {
		_wl_fullscreen_shell_present_surface(display->fshell,
						     window->surface,
						     _WL_FULLSCREEN_SHELL_PRESENT_METHOD_DEFAULT,
						     NULL);
	} else {
		assert(0);
	}

	/* Initialise damage to full surface, so the padding gets painted */
	wl_surface_damage(window->surface, 0, 0, INT32_MAX, INT32_MAX);

	return window;
}
예제 #20
0
static gboolean
_eventd_nd_wl_create_buffer(EventdNdSurface *self)
{
    struct wl_shm_pool *pool;
    struct wl_buffer *buffer;
    gint fd;
    gpointer data;
    gint width, height, stride;
    gsize size;

    width = self->width * self->context->scale;
    height = self->height * self->context->scale;
    stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, width);
    size = stride * height;

    gchar *filename;
    filename = g_build_filename(g_get_user_runtime_dir(), PACKAGE_NAME G_DIR_SEPARATOR_S "wayland-surface", NULL);
    fd = g_open(filename, O_CREAT | O_RDWR | O_CLOEXEC, 0);
    g_unlink(filename);
    g_free(filename);
    if ( fd < 0 )
    {
        g_warning("creating a buffer file for %zu B failed: %s\n", size, g_strerror(errno));
        return FALSE;
    }
    if ( ftruncate(fd, size) < 0 )
    {
        close(fd);
        return FALSE;
    }

    data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ( data == MAP_FAILED )
    {
        g_warning("mmap failed: %s\n", g_strerror(errno));
        close(fd);
        return FALSE;
    }

    cairo_surface_t *cairo_surface;
    cairo_surface = cairo_image_surface_create_for_data(data, CAIRO_FORMAT_ARGB32, width, height, 4 * width);
    cairo_surface_set_device_scale(cairo_surface, self->context->scale, self->context->scale);
    self->context->nd->notification_draw(self->notification, cairo_surface, TRUE);
    cairo_surface_destroy(cairo_surface);

    munmap(data, size);

    pool = wl_shm_create_pool(self->context->shm, fd, size);
    buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride, WL_SHM_FORMAT_ARGB8888);
    wl_shm_pool_destroy(pool);
    close(fd);

    if ( self->buffer != NULL )
        _eventd_nd_wl_buffer_release(self->buffer, self->buffer->buffer);

    self->buffer = g_new0(EventdNdWlBuffer, 1);
    self->buffer->buffer = buffer;
    self->buffer->data = data;
    self->buffer->size = size;

    wl_buffer_add_listener(buffer, &_eventd_nd_wl_buffer_listener, self->buffer);

    wl_surface_damage(self->surface, 0, 0, self->width, self->height);
    wl_surface_attach(self->surface, self->buffer->buffer, 0, 0);
    if ( wl_surface_get_version(self->surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION )
        wl_surface_set_buffer_scale(self->surface, self->context->scale);
    wl_surface_commit(self->surface);

    return TRUE;
}
예제 #21
0
void
window_damage(struct window *window, int32_t x, int32_t y,
	      int32_t width, int32_t height)
{
	wl_surface_damage(window->surface, x, y, width, height);
}
/* Swap the contents of a drawable to the screen */
static WSEGLError wseglSwapDrawable
    (WSEGLDrawableHandle _drawable, unsigned long data)
{
    struct wl_egl_window *drawable = (struct wl_egl_window *) _drawable;
    struct wl_callback *callback;

    if (drawable->numFlipBuffers)
    {
//        wsegl_info("PRESENT FLIP");
        PVR2DPresentFlip(drawable->display->context, drawable->flipChain, drawable->backBuffers[drawable->currentBackBuffer], 0);
    }
    else if (drawable->display->display)
    { 
        //wsegl_info("wseglSwapDrawable for wayland, %d %p", drawable->currentBackBuffer, drawable->drmbuffers[drawable->currentBackBuffer]);

        int ret = 0;
        while (drawable->display->frame_callback && ret != -1)
            ret = wl_display_dispatch_queue(drawable->display->display, drawable->display->queue);

        drawable->display->frame_callback = wl_surface_frame(drawable->surface);
        wl_callback_add_listener(drawable->display->frame_callback, &frame_listener, drawable);
        wl_proxy_set_queue((struct wl_proxy *)drawable->display->frame_callback, drawable->display->queue);

        if (!drawable->drmbuffers[drawable->currentBackBuffer])
        {
            int32_t handle;
            struct wl_resource *wlbuf;

            handle = drawable->exporthandles[drawable->currentBackBuffer];
            wlbuf = sgx_wlegl_create_buffer(drawable->display->sgx_wlegl,
                        drawable->width, drawable->height, drawable->strideBytes,
                        drawable->format, handle);
            drawable->drmbuffers[drawable->currentBackBuffer] = wlbuf;
            wsegl_info("sgx_wlegl_create_buffer for %d", drawable->currentBackBuffer);

            wsegl_info("Add listener for %p with %p (buf %d) inside", drawable, wlbuf, drawable->currentBackBuffer);

            // TODO: listen for release

            wl_proxy_set_queue((struct wl_proxy *)wlbuf, drawable->display->queue);
        }

        struct wl_resource *wlbuf = drawable->drmbuffers[drawable->currentBackBuffer];
        wl_surface_attach(drawable->surface, wlbuf, 0, 0); 
        wl_surface_damage(drawable->surface, 0, 0, drawable->width, drawable->height);
        wl_surface_commit(drawable->surface);
    }
    else
    {
       PVR2DBLTINFO blit;

       memset(&blit, 0, sizeof(blit));
    
       blit.CopyCode = PVR2DROPcopy;
       blit.BlitFlags = PVR2D_BLIT_DISABLE_ALL;
       blit.pSrcMemInfo = drawable->backBuffers[drawable->currentBackBuffer];
       blit.SrcStride = drawable->strideBytes;
       blit.SrcX = 0;
       blit.SrcY = 0;
       blit.SizeX = drawable->width;
       blit.SizeY = drawable->height;
       blit.SrcFormat = wsegl2pvr2dformat(drawable->format);

       blit.pDstMemInfo = drawable->frontBufferPVRMEM;
       blit.DstStride = drawable->strideBytes; 
       blit.DstX = 0;
       blit.DstY = 0;
       blit.DSizeX = drawable->width;
       blit.DSizeY = drawable->height;
       blit.DstFormat = wsegl2pvr2dformat(drawable->format);
       PVR2DBlt(drawable->display->context, &blit); 
       PVR2DQueryBlitsComplete
          (drawable->display->context, drawable->frontBufferPVRMEM, 1);                      
       assert (drawable->display->fd >= 0);


       struct omapfb_update_window update_window;
         
       update_window.x = update_window.out_x = 0;
       update_window.y = update_window.out_y = 0;
       update_window.width = update_window.out_width = drawable->width;
       update_window.height = update_window.out_height = drawable->height;
       update_window.format = 0;

       assert(ioctl(drawable->display->fd, OMAPFB_UPDATE_WINDOW, &update_window) == 0);
    }
    
    drawable->currentBackBuffer   
      = (drawable->currentBackBuffer + 1) % WAYLANDWSEGL_MAX_BACK_BUFFERS;

    return WSEGL_SUCCESS;
}
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;
  }
}
예제 #24
0
static void vertical_blank(void *pointer)
{
	struct wayland *wayland = pointer;

	wl_display_roundtrip(wayland->display);

	struct timespec tv;
	int32_t nsec_diff;
	clock_gettime(CLOCK_MONOTONIC, &tv);
	if (tv_prev.tv_sec == 0 && tv_prev.tv_nsec == 0) {
		nsec_diff = 0;
		tv_prev = tv;
	}
	else {
		nsec_diff = nano_elapsed(&tv_prev, &tv);
		tv_prev = tv;

		// assert(sec_diff == 0);

		cairo_surface_t *cairo_surface =
			cairo_image_surface_create_for_data(
				(unsigned char *)wayland->back_data,
				CAIRO_FORMAT_ARGB32,
				256 * SCALE, 240 * SCALE, 256 * SCALE * 4);
		cairo_t *cairo = cairo_create(cairo_surface);
		char buffer[200];
		double fps = 1000000000.0 / ((double) nsec_diff);
		sprintf(buffer, "FPS %.1f", fps);
		cairo_set_source_rgba(cairo, 255, 255, 255, 0.8);
		cairo_select_font_face(cairo, "Cousine",
			CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
		cairo_set_font_size(cairo, 12 * SCALE);
		cairo_move_to(cairo, 2 * SCALE, 236 * SCALE);
		cairo_show_text(cairo, buffer);
		cairo_destroy(cairo);
		cairo_surface_destroy(cairo_surface);
		// ++frame_count;
	}

	swap_buffers(wayland);

	wayland->frame_callback = wl_surface_frame(wayland->surface);
	wl_callback_add_listener(wayland->frame_callback,
	                         &frame_callback_listener, wayland);

	wl_surface_damage(wayland->surface, 0, 0,
	                  wayland->width, wayland->height);
	wl_surface_attach(wayland->surface, wayland->front_buffer, 0, 0);
	wl_surface_commit(wayland->surface);

	wl_display_flush(wayland->display);

	const int32_t NSEC_PER_60FPS_TICK = 16666666;
	if (nsec_diff != 0) {
		struct timespec req = {
			.tv_sec = 0,
			.tv_nsec = NSEC_PER_60FPS_TICK - nsec_diff,
		};
		struct timespec rem;
		nanosleep(&req, &rem);
	}
}

static uint8_t joypad1_read(void *pointer)
{
	struct wayland *wayland = pointer;

	wl_display_roundtrip(wayland->display);

	uint8_t state = wayland->joypad1_state;
	wayland->joypad1_state = wayland->joypad1_press;

	return state;
}

uint8_t nes_emulator_ppu_backend_wayland_init(
	struct nes_emulator_ppu_backend **ppu_backend)
{
	if (ppu_backend == NULL) {
		return EXIT_CODE_ARG_ERROR_BIT;
	}
	*ppu_backend = NULL;

	struct nes_emulator_ppu_backend *b =
		malloc(sizeof(struct nes_emulator_ppu_backend));
	if (b == NULL) {
		return EXIT_CODE_OS_ERROR_BIT;
	}

	struct wayland *w = malloc(sizeof(struct wayland));
	if (w == NULL) {
		free(b);
		return EXIT_CODE_OS_ERROR_BIT;
	}
	w->joypad1_state = 0;
	w->joypad1_press = 0;

	uint8_t exit_code = init_wayland(w);
	if (exit_code != 0) {
		free(w);
		free(b);
		return exit_code;
	}

	b->pointer = w;
	b->render_pixel = render_pixel;
	b->vertical_blank = vertical_blank;
	b->joypad1_read = joypad1_read;
	*ppu_backend = b;
	return 0;
}

uint8_t nes_emulator_ppu_backend_wayland_fini(
	struct nes_emulator_ppu_backend **ppu_backend)
{
	uint8_t exit_code = 0;
	struct wayland *wayland = (struct wayland *) (*ppu_backend)->pointer;
	exit_code |= fini_wayland(wayland);
	free(wayland);
	free(*ppu_backend);
	*ppu_backend = NULL;
	return exit_code;
}