/*
* Mesa 3-D graphics library
- * Version: 7.9
*
* Copyright (C) 2010 LunarG Inc.
+ * Copyright (C) 2011 VMware Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
+ * Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "util/u_inlines.h"
#include "native_helper.h"
+/**
+ * Number of swap fences and mask
+ */
+
+#define EGL_SWAP_FENCES_MAX 4
+#define EGL_SWAP_FENCES_MASK 3
+#define EGL_SWAP_FENCES_DEFAULT 1
+
struct resource_surface {
struct pipe_screen *screen;
enum pipe_format format;
struct pipe_resource *resources[NUM_NATIVE_ATTACHMENTS];
uint resource_mask;
uint width, height;
+
+ /**
+ * Swap fences.
+ */
+ struct pipe_fence_handle *swap_fences[EGL_SWAP_FENCES_MAX];
+ unsigned int cur_fences;
+ unsigned int head;
+ unsigned int tail;
+ unsigned int desired_fences;
};
struct resource_surface *
enum pipe_format format, uint bind)
{
struct resource_surface *rsurf = CALLOC_STRUCT(resource_surface);
+ char *swap_fences = getenv("EGL_THROTTLE_FENCES");
if (rsurf) {
rsurf->screen = screen;
rsurf->format = format;
rsurf->bind = bind;
+ rsurf->desired_fences = (swap_fences) ? atoi(swap_fences) :
+ EGL_SWAP_FENCES_DEFAULT;
+ if (rsurf->desired_fences > EGL_SWAP_FENCES_MAX)
+ rsurf->desired_fences = EGL_SWAP_FENCES_MAX;
}
return rsurf;
return TRUE;
rsurf->screen->flush_frontbuffer(rsurf->screen,
- pres, 0, 0, winsys_drawable_handle);
+ pres, 0, 0, winsys_drawable_handle, NULL);
return TRUE;
}
u_box_origin_2d(ftex->width0, ftex->height0, &src_box);
pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0,
btex, 0, &src_box);
- pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
ret = TRUE;
- out_no_ftex:
- pipe_resource_reference(&btex, NULL);
out_no_btex:
+ pipe_resource_reference(&btex, NULL);
+ out_no_ftex:
pipe_resource_reference(&ftex, NULL);
return ret;
}
+
+static struct pipe_fence_handle *
+swap_fences_pop_front(struct resource_surface *rsurf)
+{
+ struct pipe_screen *screen = rsurf->screen;
+ struct pipe_fence_handle *fence = NULL;
+
+ if (rsurf->desired_fences == 0)
+ return NULL;
+
+ if (rsurf->cur_fences >= rsurf->desired_fences) {
+ screen->fence_reference(screen, &fence, rsurf->swap_fences[rsurf->tail]);
+ screen->fence_reference(screen, &rsurf->swap_fences[rsurf->tail++], NULL);
+ rsurf->tail &= EGL_SWAP_FENCES_MASK;
+ --rsurf->cur_fences;
+ }
+ return fence;
+}
+
+static void
+swap_fences_push_back(struct resource_surface *rsurf,
+ struct pipe_fence_handle *fence)
+{
+ struct pipe_screen *screen = rsurf->screen;
+
+ if (!fence || rsurf->desired_fences == 0)
+ return;
+
+ while(rsurf->cur_fences == rsurf->desired_fences)
+ swap_fences_pop_front(rsurf);
+
+ rsurf->cur_fences++;
+ screen->fence_reference(screen, &rsurf->swap_fences[rsurf->head++],
+ fence);
+ rsurf->head &= EGL_SWAP_FENCES_MASK;
+}
+
+boolean
+resource_surface_throttle(struct resource_surface *rsurf)
+{
+ struct pipe_screen *screen = rsurf->screen;
+ struct pipe_fence_handle *fence = swap_fences_pop_front(rsurf);
+
+ if (fence) {
+ (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE);
+ screen->fence_reference(screen, &fence, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+boolean
+resource_surface_flush(struct resource_surface *rsurf,
+ struct native_display *ndpy)
+{
+ struct pipe_fence_handle *fence = NULL;
+ struct pipe_screen *screen = rsurf->screen;
+ struct pipe_context *pipe= ndpy_get_copy_context(ndpy);
+
+ if (!pipe)
+ return FALSE;
+
+ pipe->flush(pipe, &fence, 0);
+ if (fence == NULL)
+ return FALSE;
+
+ swap_fences_push_back(rsurf, fence);
+ screen->fence_reference(screen, &fence, NULL);
+
+ return TRUE;
+}
+
+void
+resource_surface_wait(struct resource_surface *rsurf)
+{
+ while (resource_surface_throttle(rsurf));
+}
+
+boolean
+native_display_copy_to_pixmap(struct native_display *ndpy,
+ EGLNativePixmapType pix,
+ struct pipe_resource *src)
+{
+ struct pipe_context *pipe;
+ struct native_surface *nsurf;
+ struct pipe_resource *dst;
+ struct pipe_resource *tmp[NUM_NATIVE_ATTACHMENTS];
+ const enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT;
+
+ pipe = ndpy_get_copy_context(ndpy);
+ if (!pipe)
+ return FALSE;
+
+ nsurf = ndpy->create_pixmap_surface(ndpy, pix, NULL);
+ if (!nsurf)
+ return FALSE;
+
+ /* get the texutre */
+ tmp[natt] = NULL;
+ nsurf->validate(nsurf, 1 << natt, NULL, tmp, NULL, NULL);
+ dst = tmp[natt];
+
+ if (dst && dst->format == src->format) {
+ struct native_present_control ctrl;
+ struct pipe_box src_box;
+
+ u_box_origin_2d(src->width0, src->height0, &src_box);
+ pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &src_box);
+ pipe->flush(pipe, NULL, 0);
+
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.natt = natt;
+ nsurf->present(nsurf, &ctrl);
+ }
+
+ if (dst)
+ pipe_resource_reference(&dst, NULL);
+
+ nsurf->destroy(nsurf);
+
+ return TRUE;
+}
+
+#include "state_tracker/drm_driver.h"
+struct pipe_resource *
+drm_display_import_native_buffer(struct native_display *ndpy,
+ struct native_buffer *nbuf)
+{
+ struct pipe_screen *screen = ndpy->screen;
+ struct pipe_resource *res = NULL;
+
+ switch (nbuf->type) {
+ case NATIVE_BUFFER_DRM:
+ {
+ struct winsys_handle wsh;
+
+ memset(&wsh, 0, sizeof(wsh));
+ wsh.handle = nbuf->u.drm.name;
+ wsh.type = DRM_API_HANDLE_TYPE_SHARED;
+ wsh.stride = nbuf->u.drm.stride;
+
+ res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return res;
+}
+
+boolean
+drm_display_export_native_buffer(struct native_display *ndpy,
+ struct pipe_resource *res,
+ struct native_buffer *nbuf)
+{
+ struct pipe_screen *screen = ndpy->screen;
+ boolean ret = FALSE;
+
+ switch (nbuf->type) {
+ case NATIVE_BUFFER_DRM:
+ {
+ struct winsys_handle wsh;
+
+ if ((nbuf->u.drm.templ.bind & res->bind) != nbuf->u.drm.templ.bind)
+ break;
+
+ memset(&wsh, 0, sizeof(wsh));
+ wsh.type = DRM_API_HANDLE_TYPE_KMS;
+ if (!screen->resource_get_handle(screen, res, &wsh))
+ break;
+
+ nbuf->u.drm.handle = wsh.handle;
+ nbuf->u.drm.stride = wsh.stride;
+
+ /* get the name of the GEM object */
+ if (nbuf->u.drm.templ.bind & PIPE_BIND_SHARED) {
+ memset(&wsh, 0, sizeof(wsh));
+ wsh.type = DRM_API_HANDLE_TYPE_SHARED;
+ if (!screen->resource_get_handle(screen, res, &wsh))
+ break;
+
+ nbuf->u.drm.name = wsh.handle;
+ }
+
+ nbuf->u.drm.templ = *res;
+ ret = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}