X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fegl%2Fcommon%2Fnative_helper.c;h=ebe5144b36799819fab79c5b712f05c37c38ee76;hb=d7522ed13052a3d30bc4faedce04685263f57933;hp=0f2d02032b575707d08ce7f587c503fa44030640;hpb=9032d2a13ecd019206a48767d9205c0aafa7cca2;p=mesa.git diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index 0f2d02032b5..ebe5144b367 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 + * Thomas Hellstrom */ #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; @@ -143,6 +167,14 @@ resource_surface_add_resources(struct resource_surface *rsurf, return ((rsurf->resource_mask & resource_mask) == resource_mask); } +void +resource_surface_import_resource(struct resource_surface *rsurf, + enum native_attachment which, + struct pipe_resource *pres) +{ + pipe_resource_reference(&rsurf->resources[which], pres); + rsurf->resource_mask |= 1 << which; +} void resource_surface_get_resources(struct resource_surface *rsurf, @@ -217,3 +249,238 @@ resource_surface_present(struct resource_surface *rsurf, return TRUE; } + +/** + * Schedule a copy swap from the back to the front buffer using the + * native display's copy context. + */ +boolean +resource_surface_copy_swap(struct resource_surface *rsurf, + struct native_display *ndpy) +{ + struct pipe_resource *ftex; + struct pipe_resource *btex; + struct pipe_context *pipe; + struct pipe_box src_box; + boolean ret = FALSE; + + pipe = ndpy_get_copy_context(ndpy); + if (!pipe) + return FALSE; + + ftex = resource_surface_get_single_resource(rsurf, + NATIVE_ATTACHMENT_FRONT_LEFT); + if (!ftex) + goto out_no_ftex; + btex = resource_surface_get_single_resource(rsurf, + NATIVE_ATTACHMENT_BACK_LEFT); + if (!btex) + goto out_no_btex; + + u_box_origin_2d(ftex->width0, ftex->height0, &src_box); + pipe->resource_copy_region(pipe, ftex, 0, 0, 0, 0, + btex, 0, &src_box); + ret = TRUE; + + 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); + 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); + + 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.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; +}