diff options
Diffstat (limited to 'src/gallium/state_trackers/egl/common/native_helper.c')
-rw-r--r-- | src/gallium/state_trackers/egl/common/native_helper.c | 103 |
1 files changed, 102 insertions, 1 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)); +} |