summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/state_trackers/egl/common/native_helper.c103
-rw-r--r--src/gallium/state_trackers/egl/common/native_helper.h27
-rw-r--r--src/gallium/state_trackers/egl/drm/modeset.c15
3 files changed, 141 insertions, 4 deletions
diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c
index 0f00c4d13e..be6713d03a 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.c
+++ b/src/gallium/state_trackers/egl/common/native_helper.c
@@ -3,6 +3,7 @@
* 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"),
@@ -24,6 +25,7 @@
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
+ * Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "util/u_inlines.h"
@@ -34,6 +36,14 @@
#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;
@@ -42,6 +52,15 @@ struct resource_surface {
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 *
@@ -49,11 +68,16 @@ resource_surface_create(struct pipe_screen *screen,
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;
@@ -256,7 +280,6 @@ resource_surface_copy_swap(struct resource_surface *rsurf,
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:
@@ -266,3 +289,81 @@ resource_surface_copy_swap(struct resource_surface *rsurf,
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, 0);
+ 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, PIPE_FLUSH_RENDER_CACHE, &fence);
+ 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));
+}
diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h
index ad6827336a..39564a0436 100644
--- a/src/gallium/state_trackers/egl/common/native_helper.h
+++ b/src/gallium/state_trackers/egl/common/native_helper.h
@@ -3,6 +3,7 @@
* 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"),
@@ -24,6 +25,7 @@
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
+ * Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "native.h"
@@ -75,6 +77,31 @@ resource_surface_present(struct resource_surface *rsurf,
enum native_attachment which,
void *winsys_drawable_handle);
+/**
+ * Perform a gallium copy blit between the back left and front left
+ * surfaces. Needs to be followed by a call to resource_surface_flush.
+ */
boolean
resource_surface_copy_swap(struct resource_surface *rsurf,
struct native_display *ndpy);
+
+/**
+ * Throttle on outstanding rendering using the copy context. For example
+ * copy swaps.
+ */
+boolean
+resource_surface_throttle(struct resource_surface *rsurf);
+
+/**
+ * Flush pending rendering using the copy context. This function saves a
+ * marker for upcoming throttles.
+ */
+boolean
+resource_surface_flush(struct resource_surface *rsurf,
+ struct native_display *ndpy);
+/**
+ * Wait for all rendering using the copy context to be complete. Frees all
+ * throttle markers saved using resource_surface_flush.
+ */
+void
+resource_surface_wait(struct resource_surface *rsurf);
diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c
index 6eaa42fafb..3fff954090 100644
--- a/src/gallium/state_trackers/egl/drm/modeset.c
+++ b/src/gallium/state_trackers/egl/drm/modeset.c
@@ -3,6 +3,7 @@
* 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"),
@@ -24,6 +25,7 @@
*
* Authors:
* Chia-I Wu <olv@lunarg.com>
+ * Thomas Hellstrom <thellstrom@vmware.com>
*/
#include "util/u_memory.h"
@@ -136,8 +138,12 @@ drm_surface_copy_swap(struct native_surface *nsurf)
struct drm_surface *drmsurf = drm_surface(nsurf);
struct drm_display *drmdpy = drmsurf->drmdpy;
- if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base) ||
- !drm_surface_flush_frontbuffer(nsurf))
+ (void) resource_surface_throttle(drmsurf->rsurf);
+ if (!resource_surface_copy_swap(drmsurf->rsurf, &drmdpy->base))
+ return FALSE;
+
+ (void) resource_surface_flush(drmsurf->rsurf, &drmdpy->base);
+ if (!drm_surface_flush_frontbuffer(nsurf))
return FALSE;
drmsurf->sequence_number++;
@@ -218,7 +224,9 @@ drm_surface_present(struct native_surface *nsurf,
static void
drm_surface_wait(struct native_surface *nsurf)
{
- /* no-op */
+ struct drm_surface *drmsurf = drm_surface(nsurf);
+
+ resource_surface_wait(drmsurf->rsurf);
}
static void
@@ -226,6 +234,7 @@ drm_surface_destroy(struct native_surface *nsurf)
{
struct drm_surface *drmsurf = drm_surface(nsurf);
+ resource_surface_wait(drmsurf->rsurf);
if (drmsurf->current_crtc.crtc)
drmModeFreeCrtc(drmsurf->current_crtc.crtc);