예제 #1
0
static boolean
dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
{
    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    struct native_display *ndpy = &dri2dpy->base;
    struct pipe_context *pipe = ndpy_get_copy_context(ndpy);

    /* flush buffer */
    pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_FRONT_LEFT]);
    pipe->flush(pipe, NULL, 0);

    /* copy to real front buffer */
    if (dri2surf->have_fake)
        x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
                                  0, 0, dri2surf->width, dri2surf->height,
                                  DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);

    /* force buffers to be updated in next validation call */
    if (!dri2_surface_receive_events(&dri2surf->base)) {
        dri2surf->server_stamp++;
        dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
                                                &dri2surf->base, dri2surf->server_stamp);
    }

    return TRUE;
}
예제 #2
0
static boolean
dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask,
                      unsigned int *seq_num, struct pipe_resource **textures,
                      int *width, int *height)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);

   if (dri2surf->server_stamp != dri2surf->client_stamp ||
       (dri2surf->valid_mask & attachment_mask) != attachment_mask) {
      if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask))
         return FALSE;
   }

   if (seq_num)
      *seq_num = dri2surf->client_stamp;

   if (textures) {
      int att;
      for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
         if (native_attachment_mask_test(attachment_mask, att)) {
            struct pipe_resource *ptex = dri2surf->textures[att];

            textures[att] = NULL;
            pipe_resource_reference(&textures[att], ptex);
         }
      }
   }

   if (width)
      *width = dri2surf->width;
   if (height)
      *height = dri2surf->height;

   return TRUE;
}
예제 #3
0
/**
 * Update the buffers of the surface.  This is a slow function due to the
 * round-trip to the server.
 */
static boolean
dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);

   dri2_surface_get_buffers(&dri2surf->base, buffer_mask);

   return ((dri2surf->valid_mask & buffer_mask) == buffer_mask);
}
예제 #4
0
static void
dri2_surface_wait(struct native_surface *nsurf)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;

   if (dri2surf->have_fake) {
      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
            0, 0, dri2surf->width, dri2surf->height,
            DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
   }
}
예제 #5
0
static boolean
dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects,
                          const int *rects)
{
    struct dri2_surface *dri2surf = dri2_surface(nsurf);
    struct dri2_display *dri2dpy = dri2surf->dri2dpy;
    struct native_display *ndpy = &dri2dpy->base;
    struct pipe_context *pipe = ndpy_get_copy_context(ndpy);

    /* copy to front buffer */
    if (dri2surf->have_back) {
        pipe->flush_resource(pipe, dri2surf->textures[NATIVE_ATTACHMENT_BACK_LEFT]);
        pipe->flush(pipe, NULL, 0);

        if (num_rects > 0)
            x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
                                             num_rects, rects,
                                             DRI2BufferBackLeft, DRI2BufferFrontLeft);
        else
            x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
                                      0, 0, dri2surf->width, dri2surf->height,
                                      DRI2BufferBackLeft, DRI2BufferFrontLeft);
    }

    /* and update fake front buffer */
    if (dri2surf->have_fake) {
        if (num_rects > 0)
            x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
                                             num_rects, rects,
                                             DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
        else
            x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
                                      0, 0, dri2surf->width, dri2surf->height,
                                      DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
    }

    /* force buffers to be updated in next validation call */
    if (!dri2_surface_receive_events(&dri2surf->base)) {
        dri2surf->server_stamp++;
        dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
                                                &dri2surf->base, dri2surf->server_stamp);
    }

    return TRUE;
}
예제 #6
0
static void
dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable,
                                void *user_data)
{
   struct native_display *ndpy = (struct native_display* ) user_data;
   struct dri2_display *dri2dpy = dri2_display(ndpy);
   struct native_surface *nsurf;
   struct dri2_surface *dri2surf;

   nsurf = (struct native_surface *)
      util_hash_table_get(dri2dpy->surfaces, (void *) drawable);
   if (!nsurf)
      return;

   dri2surf = dri2_surface(nsurf);

   dri2surf->server_stamp++;
   dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
         &dri2surf->base, dri2surf->server_stamp);
}
예제 #7
0
static boolean
dri2_surface_flush_frontbuffer(struct native_surface *nsurf)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;

   /* copy to real front buffer */
   if (dri2surf->have_fake)
      x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
            0, 0, dri2surf->width, dri2surf->height,
            DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft);

   /* force buffers to be updated in next validation call */
   if (!dri2_surface_receive_events(&dri2surf->base)) {
      dri2surf->server_stamp++;
      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
            &dri2surf->base, dri2surf->server_stamp);
   }

   return TRUE;
}
예제 #8
0
static boolean
dri2_surface_swap_buffers(struct native_surface *nsurf, int num_rects,
                          const int *rects)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;

   /* copy to front buffer */
   if (dri2surf->have_back) {
      if (num_rects > 0)
         x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
               num_rects, rects,
               DRI2BufferBackLeft, DRI2BufferFrontLeft);
      else
         x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
               0, 0, dri2surf->width, dri2surf->height,
               DRI2BufferBackLeft, DRI2BufferFrontLeft);
   }

   /* and update fake front buffer */
   if (dri2surf->have_fake) {
      if (num_rects > 0)
         x11_drawable_copy_buffers_region(dri2dpy->xscr, dri2surf->drawable,
               num_rects, rects,
               DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
      else
         x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable,
               0, 0, dri2surf->width, dri2surf->height,
               DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft);
   }

   /* force buffers to be updated in next validation call */
   if (!dri2_surface_receive_events(&dri2surf->base)) {
      dri2surf->server_stamp++;
      dri2dpy->event_handler->invalid_surface(&dri2dpy->base,
            &dri2surf->base, dri2surf->server_stamp);
   }

   return TRUE;
}
예제 #9
0
static void
dri2_surface_destroy(struct native_surface *nsurf)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   int i;

   FREE(dri2surf->last_xbufs);

   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) {
      struct pipe_resource *ptex = dri2surf->textures[i];
      pipe_resource_reference(&ptex, NULL);
   }

   if (dri2surf->drawable) {
      x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr,
            dri2surf->drawable, FALSE);

      util_hash_table_remove(dri2surf->dri2dpy->surfaces,
            (void *) dri2surf->drawable);
   }
   FREE(dri2surf);
}
예제 #10
0
/**
 * Return TRUE if the surface receives DRI2_InvalidateBuffers events.
 */
static INLINE boolean
dri2_surface_receive_events(struct native_surface *nsurf)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   return (dri2surf->dri2dpy->dri_minor >= 3);
}
예제 #11
0
/**
 * Get the buffers from the server.
 */
static void
dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
   unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2];
   int num_ins, num_outs, att;
   struct x11_drawable_buffer *xbufs;
   uint bpp = util_format_get_blocksizebits(dri2surf->color_format);
   boolean with_format = FALSE; /* never ask for depth/stencil */

   /* We must get the front on servers which doesn't support with format
    * due to a silly bug in core dri2. You can't copy to/from a buffer
    * that you haven't requested and you recive BadValue errors */
   if (dri2surf->dri2dpy->dri_minor < 1) {
      with_format = FALSE;
      buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT);
   }

   /* prepare the attachments */
   num_ins = 0;
   for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) {
      if (native_attachment_mask_test(buffer_mask, att)) {
         unsigned int dri2att;

         switch (att) {
         case NATIVE_ATTACHMENT_FRONT_LEFT:
            dri2att = DRI2BufferFrontLeft;
            break;
         case NATIVE_ATTACHMENT_BACK_LEFT:
            dri2att = DRI2BufferBackLeft;
            break;
         case NATIVE_ATTACHMENT_FRONT_RIGHT:
            dri2att = DRI2BufferFrontRight;
            break;
         case NATIVE_ATTACHMENT_BACK_RIGHT:
            dri2att = DRI2BufferBackRight;
            break;
         default:
            assert(0);
            dri2att = 0;
            break;
         }

         dri2atts[num_ins++] = dri2att;
         if (with_format)
            dri2atts[num_ins++] = bpp;
      }
   }
   if (with_format)
      num_ins /= 2;

   xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable,
                                    &dri2surf->width, &dri2surf->height,
                                    dri2atts, with_format, num_ins, &num_outs);

   /* we should be able to do better... */
   if (xbufs && dri2surf->last_num_xbufs == num_outs &&
       memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) {
      FREE(xbufs);
      dri2surf->client_stamp = dri2surf->server_stamp;
      return;
   }

   dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs);

   dri2surf->server_stamp++;
   dri2surf->client_stamp = dri2surf->server_stamp;

   FREE(dri2surf->last_xbufs);
   dri2surf->last_xbufs = xbufs;
   dri2surf->last_num_xbufs = num_outs;
}
예제 #12
0
/**
 * Process the buffers returned by the server.
 */
static void
dri2_surface_process_drawable_buffers(struct native_surface *nsurf,
                                      struct x11_drawable_buffer *xbufs,
                                      int num_xbufs)
{
   struct dri2_surface *dri2surf = dri2_surface(nsurf);
   struct dri2_display *dri2dpy = dri2surf->dri2dpy;
   struct pipe_resource templ;
   struct winsys_handle whandle;
   uint valid_mask;
   int i;

   /* free the old textures */
   for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++)
      pipe_resource_reference(&dri2surf->textures[i], NULL);
   dri2surf->valid_mask = 0x0;

   dri2surf->have_back = FALSE;
   dri2surf->have_fake = FALSE;

   if (!xbufs)
      return;

   memset(&templ, 0, sizeof(templ));
   templ.target = PIPE_TEXTURE_2D;
   templ.last_level = 0;
   templ.width0 = dri2surf->width;
   templ.height0 = dri2surf->height;
   templ.depth0 = 1;
   templ.array_size = 1;
   templ.format = dri2surf->color_format;
   templ.bind = PIPE_BIND_RENDER_TARGET;

   valid_mask = 0x0;
   for (i = 0; i < num_xbufs; i++) {
      struct x11_drawable_buffer *xbuf = &xbufs[i];
      const char *desc;
      enum native_attachment natt;

      switch (xbuf->attachment) {
      case DRI2BufferFrontLeft:
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
         desc = "DRI2 Front Buffer";
         break;
      case DRI2BufferFakeFrontLeft:
         natt = NATIVE_ATTACHMENT_FRONT_LEFT;
         desc = "DRI2 Fake Front Buffer";
         dri2surf->have_fake = TRUE;
         break;
      case DRI2BufferBackLeft:
         natt = NATIVE_ATTACHMENT_BACK_LEFT;
         desc = "DRI2 Back Buffer";
         dri2surf->have_back = TRUE;
         break;
      default:
         desc = NULL;
         break;
      }

      if (!desc || dri2surf->textures[natt]) {
         if (!desc)
            _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment);
         else
            _eglLog(_EGL_WARNING, "both real and fake front buffers are listed");
         continue;
      }

      memset(&whandle, 0, sizeof(whandle));
      whandle.stride = xbuf->pitch;
      whandle.handle = xbuf->name;
      dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle(
         dri2dpy->base.screen, &templ, &whandle);
      if (dri2surf->textures[natt])
         valid_mask |= 1 << natt;
   }

   dri2surf->valid_mask = valid_mask;
}