nouveau: Conversion to winsys handle

Not the best conversion that could be done.
This commit is contained in:
Jakob Bornecrantz 2010-03-04 14:36:51 +00:00
parent 86e146df97
commit 3bd622d64e
2 changed files with 78 additions and 66 deletions

View file

@ -4,6 +4,7 @@
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include <stdio.h>
#include <errno.h>
@ -12,6 +13,9 @@
#include "nouveau_winsys.h"
#include "nouveau_screen.h"
/* XXX this should go away */
#include "state_tracker/drm_api.h"
static const char *
nouveau_screen_get_name(struct pipe_screen *pscreen)
{
@ -231,6 +235,71 @@ nouveau_screen_fence_finish(struct pipe_screen *screen,
return 0;
}
/*
* Both texture_{from|get}_handle use drm api defines directly which they
* shouldn't do. The problem is that from|get are pipe functions and as
* such they should be defined in the pipe level. If nouveau had a propper
* winsys interface we would have added from|get to that interface using
* the winsys_handle struct as done with other drivers. However this code
* calls directly into the libdrm_nouveau.so functions (nouveau_bo_*). So
* we need to translate the handle into something they understand.
*/
static struct pipe_texture *
nouveau_screen_texture_from_handle(struct pipe_screen *pscreen,
const struct pipe_texture *templ,
struct winsys_handle *whandle)
{
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
struct pipe_texture *pt;
struct pipe_buffer *pb;
int ret;
pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
if (!pb)
return NULL;
ret = nouveau_bo_handle_ref(dev, whandle->handle, (struct nouveau_bo**)(pb+1));
if (ret) {
debug_printf("%s: ref name 0x%08x failed with %d\n",
__func__, whandle->handle, ret);
FREE(pb);
return NULL;
}
pipe_reference_init(&pb->reference, 1);
pb->screen = pscreen;
pb->alignment = 0;
pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
PIPE_BUFFER_USAGE_CPU_READ_WRITE;
pb->size = nouveau_bo(pb)->size;
pt = pscreen->texture_blanket(pscreen, templ, &whandle->stride, pb);
pipe_buffer_reference(&pb, NULL);
return pt;
}
static boolean
nouveau_screen_texture_get_handle(struct pipe_screen *pscreen,
struct pipe_texture *pt,
struct winsys_handle *whandle)
{
struct nouveau_miptree *mt = nouveau_miptree(pt);
if (!mt || !mt->bo)
return false;
whandle->stride = util_format_get_stride(mt->base.format, mt->base.width0);
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
return nouveau_bo_handle_get(mt->bo, &whandle->handle) == 0;
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
whandle->handle = mt->bo->handle;
return TRUE;
} else {
return FALSE;
}
}
int
nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
{
@ -258,6 +327,9 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
pscreen->fence_signalled = nouveau_screen_fence_signalled;
pscreen->fence_finish = nouveau_screen_fence_finish;
pscreen->texture_from_handle = nouveau_screen_texture_from_handle;
pscreen->texture_get_handle = nouveau_screen_texture_get_handle;
return 0;
}

View file

@ -21,6 +21,7 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen,
struct pipe_surface *ps = NULL;
struct pipe_texture *pt = NULL;
struct pipe_texture tmpl;
struct winsys_handle whandle;
memset(&tmpl, 0, sizeof(tmpl));
tmpl.tex_usage = PIPE_TEXTURE_USAGE_SCANOUT;
@ -31,8 +32,11 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_screen *pscreen,
tmpl.width0 = width;
tmpl.height0 = height;
pt = api->texture_from_shared_handle(api, pscreen, &tmpl,
"front buffer", pitch, handle);
memset(&whandle, 0, sizeof(whandle));
whandle.stride = pitch;
whandle.handle = handle;
pt = pscreen->texture_from_handle(pscreen, &tmpl, &whandle);
if (!pt)
return NULL;
@ -142,74 +146,10 @@ nouveau_drm_create_screen(struct drm_api *api, int fd,
return nvws->pscreen;
}
static struct pipe_texture *
nouveau_drm_pt_from_name(struct drm_api *api, struct pipe_screen *pscreen,
struct pipe_texture *templ, const char *name,
unsigned stride, unsigned handle)
{
struct nouveau_device *dev = nouveau_screen(pscreen)->device;
struct pipe_texture *pt;
struct pipe_buffer *pb;
int ret;
pb = CALLOC(1, sizeof(struct pipe_buffer) + sizeof(struct nouveau_bo*));
if (!pb)
return NULL;
ret = nouveau_bo_handle_ref(dev, handle, (struct nouveau_bo**)(pb+1));
if (ret) {
debug_printf("%s: ref name 0x%08x failed with %d\n",
__func__, handle, ret);
FREE(pb);
return NULL;
}
pipe_reference_init(&pb->reference, 1);
pb->screen = pscreen;
pb->alignment = 0;
pb->usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE |
PIPE_BUFFER_USAGE_CPU_READ_WRITE;
pb->size = nouveau_bo(pb)->size;
pt = pscreen->texture_blanket(pscreen, templ, &stride, pb);
pipe_buffer_reference(&pb, NULL);
return pt;
}
static boolean
nouveau_drm_name_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
struct pipe_texture *pt, unsigned *stride,
unsigned *handle)
{
struct nouveau_miptree *mt = nouveau_miptree(pt);
if (!mt || !mt->bo)
return false;
return nouveau_bo_handle_get(mt->bo, handle) == 0;
}
static boolean
nouveau_drm_handle_from_pt(struct drm_api *api, struct pipe_screen *pscreen,
struct pipe_texture *pt, unsigned *stride,
unsigned *handle)
{
struct nouveau_miptree *mt = nouveau_miptree(pt);
if (!mt || !mt->bo)
return false;
*handle = mt->bo->handle;
*stride = util_format_get_stride(mt->base.format, mt->base.width0);
return true;
}
struct drm_api drm_api_hooks = {
.name = "nouveau",
.driver_name = "nouveau",
.create_screen = nouveau_drm_create_screen,
.texture_from_shared_handle = nouveau_drm_pt_from_name,
.shared_handle_from_texture = nouveau_drm_name_from_pt,
.local_handle_from_texture = nouveau_drm_handle_from_pt,
};
struct drm_api *