|
|
@@ -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)); |
|
|
|
} |