i965g: Conversion to winsys handle

This commit is contained in:
Jakob Bornecrantz 2010-02-17 21:45:41 +00:00
parent 0e1eb1b876
commit 45089784e3
4 changed files with 200 additions and 241 deletions

View File

@ -303,6 +303,119 @@ fail:
return NULL;
}
static struct pipe_texture *
brw_texture_from_handle(struct pipe_screen *screen,
const struct pipe_texture *templ,
struct winsys_handle *whandle)
{
struct brw_screen *bscreen = brw_screen(screen);
struct brw_texture *tex;
struct brw_winsys_buffer *buffer;
unsigned tiling;
unsigned pitch;
if (templ->target != PIPE_TEXTURE_2D ||
templ->last_level != 0 ||
templ->depth0 != 1)
return NULL;
if (util_format_is_compressed(templ->format))
return NULL;
tex = CALLOC_STRUCT(brw_texture);
if (!tex)
return NULL;
if (bscreen->sws->bo_from_handle(bscreen->sws, whandle, &pitch, &tiling, &buffer) != PIPE_OK)
goto fail;
memcpy(&tex->base, templ, sizeof *templ);
pipe_reference_init(&tex->base.reference, 1);
tex->base.screen = screen;
/* XXX: cpp vs. blocksize
*/
tex->cpp = util_format_get_blocksize(tex->base.format);
tex->tiling = tiling;
make_empty_list(&tex->views[0]);
make_empty_list(&tex->views[1]);
if (!brw_texture_layout(bscreen, tex))
goto fail;
/* XXX Maybe some more checks? */
if ((pitch / tex->cpp) < tex->pitch)
goto fail;
tex->pitch = pitch / tex->cpp;
tex->bo = buffer;
/* fix this warning */
#if 0
if (tex->size > buffer->size)
goto fail;
#endif
tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
tex->ss.ss0.surface_format = translate_tex_format(tex->base.format);
assert(tex->ss.ss0.surface_format != BRW_SURFACEFORMAT_INVALID);
/* This is ok for all textures with channel width 8bit or less:
*/
/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
/* XXX: what happens when tex->bo->offset changes???
*/
tex->ss.ss1.base_addr = 0; /* reloc */
tex->ss.ss2.mip_count = tex->base.last_level;
tex->ss.ss2.width = tex->base.width0 - 1;
tex->ss.ss2.height = tex->base.height0 - 1;
switch (tex->tiling) {
case BRW_TILING_NONE:
tex->ss.ss3.tiled_surface = 0;
tex->ss.ss3.tile_walk = 0;
break;
case BRW_TILING_X:
tex->ss.ss3.tiled_surface = 1;
tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
break;
case BRW_TILING_Y:
tex->ss.ss3.tiled_surface = 1;
tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
break;
}
tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
tex->ss.ss3.depth = tex->base.depth0 - 1;
tex->ss.ss4.min_lod = 0;
return &tex->base;
fail:
FREE(tex);
return NULL;
}
static boolean
brw_texture_get_handle(struct pipe_screen *screen,
struct pipe_texture *texture,
struct winsys_handle *whandle)
{
struct brw_screen *bscreen = brw_screen(screen);
struct brw_texture *tex = brw_texture(texture);
unsigned stride;
stride = tex->pitch * tex->cpp;
return bscreen->sws->bo_get_handle(tex->bo, whandle, stride);
}
static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen,
const struct pipe_texture *templ,
const unsigned *stride,
@ -451,125 +564,12 @@ brw_tex_transfer_destroy(struct pipe_transfer *trans)
}
/*
* Functions exported to the winsys
*/
boolean brw_texture_get_winsys_buffer(struct pipe_texture *texture,
struct brw_winsys_buffer **buffer,
unsigned *stride)
{
struct brw_texture *tex = brw_texture(texture);
*buffer = tex->bo;
if (stride)
*stride = tex->pitch * tex->cpp;
return TRUE;
}
struct pipe_texture *
brw_texture_blanket_winsys_buffer(struct pipe_screen *screen,
const struct pipe_texture *templ,
unsigned pitch,
unsigned tiling,
struct brw_winsys_buffer *buffer)
{
struct brw_screen *bscreen = brw_screen(screen);
struct brw_texture *tex;
GLuint format;
if (templ->target != PIPE_TEXTURE_2D ||
templ->last_level != 0 ||
templ->depth0 != 1)
return NULL;
if (util_format_is_compressed(templ->format))
return NULL;
tex = CALLOC_STRUCT(brw_texture);
if (!tex)
return NULL;
memcpy(&tex->base, templ, sizeof *templ);
pipe_reference_init(&tex->base.reference, 1);
tex->base.screen = screen;
/* XXX: cpp vs. blocksize
*/
tex->cpp = util_format_get_blocksize(tex->base.format);
tex->tiling = tiling;
make_empty_list(&tex->views[0]);
make_empty_list(&tex->views[1]);
if (!brw_texture_layout(bscreen, tex))
goto fail;
/* XXX Maybe some more checks? */
if ((pitch / tex->cpp) < tex->pitch)
goto fail;
tex->pitch = pitch / tex->cpp;
tex->bo = buffer;
/* fix this warning */
#if 0
if (tex->size > buffer->size)
goto fail;
#endif
tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
format = translate_tex_format(tex->base.format);
assert(format != BRW_SURFACEFORMAT_INVALID);
tex->ss.ss0.surface_format = format;
/* This is ok for all textures with channel width 8bit or less:
*/
/* tex->ss.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
/* XXX: what happens when tex->bo->offset changes???
*/
tex->ss.ss1.base_addr = 0; /* reloc */
tex->ss.ss2.mip_count = tex->base.last_level;
tex->ss.ss2.width = tex->base.width0 - 1;
tex->ss.ss2.height = tex->base.height0 - 1;
switch (tex->tiling) {
case BRW_TILING_NONE:
tex->ss.ss3.tiled_surface = 0;
tex->ss.ss3.tile_walk = 0;
break;
case BRW_TILING_X:
tex->ss.ss3.tiled_surface = 1;
tex->ss.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
break;
case BRW_TILING_Y:
tex->ss.ss3.tiled_surface = 1;
tex->ss.ss3.tile_walk = BRW_TILEWALK_YMAJOR;
break;
}
tex->ss.ss3.pitch = (tex->pitch * tex->cpp) - 1;
tex->ss.ss3.depth = tex->base.depth0 - 1;
tex->ss.ss4.min_lod = 0;
return &tex->base;
fail:
FREE(tex);
return NULL;
}
void brw_screen_tex_init( struct brw_screen *brw_screen )
{
brw_screen->base.is_format_supported = brw_is_format_supported;
brw_screen->base.texture_create = brw_texture_create;
brw_screen->base.texture_from_handle = brw_texture_from_handle;
brw_screen->base.texture_get_handle = brw_texture_get_handle;
brw_screen->base.texture_destroy = brw_texture_destroy;
brw_screen->base.texture_blanket = brw_texture_blanket;
brw_screen->base.get_tex_transfer = brw_get_tex_transfer;

View File

@ -162,6 +162,16 @@ struct brw_winsys_screen {
unsigned alignment,
struct brw_winsys_buffer **bo_out);
enum pipe_error (*bo_from_handle)(struct brw_winsys_screen *sws,
struct winsys_handle *whandle,
unsigned *stride,
unsigned *tiling,
struct brw_winsys_buffer **bo_out);
enum pipe_error (*bo_get_handle)(struct brw_winsys_buffer *buffer,
struct winsys_handle *whandle,
unsigned stride);
/* Destroy a buffer when our refcount goes to zero:
*/
void (*bo_destroy)(struct brw_winsys_buffer *buffer);

View File

@ -37,129 +37,6 @@ i965_libdrm_get_device_id(unsigned int *device_id)
fclose(file);
}
static struct i965_libdrm_buffer *
i965_libdrm_buffer_from_handle(struct i965_libdrm_winsys *idws,
const char* name, unsigned handle)
{
struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer);
uint32_t swizzle = 0;
if (BRW_DUMP)
debug_printf("%s\n", __FUNCTION__);
if (!buf)
return NULL;
pipe_reference_init(&buf->base.reference, 1);
buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, name, handle);
buf->base.size = buf->bo->size;
buf->base.sws = &idws->base;
buf->flinked = TRUE;
buf->flink = handle;
if (!buf->bo)
goto err;
drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle);
if (buf->tiling != 0)
buf->map_gtt = TRUE;
return buf;
err:
FREE(buf);
return NULL;
}
/*
* Exported functions
*/
static struct pipe_texture *
i965_libdrm_texture_from_shared_handle(struct drm_api *api,
struct pipe_screen *screen,
struct pipe_texture *template,
const char* name,
unsigned pitch,
unsigned handle)
{
/* XXX: this is silly -- there should be a way to get directly from
* the "drm_api" struct to ourselves, without peering into
* unrelated code:
*/
struct i965_libdrm_winsys *idws = i965_libdrm_winsys(brw_screen(screen)->sws);
struct i965_libdrm_buffer *buffer;
if (BRW_DUMP)
debug_printf("%s %s pitch %d handle 0x%x\n", __FUNCTION__,
name, pitch, handle);
buffer = i965_libdrm_buffer_from_handle(idws, name, handle);
if (!buffer)
return NULL;
return brw_texture_blanket_winsys_buffer(screen, template, pitch,
buffer->tiling,
&buffer->base);
}
static boolean
i965_libdrm_shared_handle_from_texture(struct drm_api *api,
struct pipe_screen *screen,
struct pipe_texture *texture,
unsigned *pitch,
unsigned *handle)
{
struct i965_libdrm_buffer *buf = NULL;
struct brw_winsys_buffer *buffer = NULL;
if (BRW_DUMP)
debug_printf("%s\n", __FUNCTION__);
if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch))
return FALSE;
buf = i965_libdrm_buffer(buffer);
if (!buf->flinked) {
if (drm_intel_bo_flink(buf->bo, &buf->flink))
return FALSE;
buf->flinked = TRUE;
}
*handle = buf->flink;
if (BRW_DUMP)
debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle);
return TRUE;
}
static boolean
i965_libdrm_local_handle_from_texture(struct drm_api *api,
struct pipe_screen *screen,
struct pipe_texture *texture,
unsigned *pitch,
unsigned *handle)
{
struct brw_winsys_buffer *buffer = NULL;
if (BRW_DUMP)
debug_printf("%s\n", __FUNCTION__);
if (!brw_texture_get_winsys_buffer(texture, &buffer, pitch))
return FALSE;
*handle = i965_libdrm_buffer(buffer)->bo->handle;
if (BRW_DUMP)
debug_printf(" -> pitch %d handle 0x%x\n", *pitch, *handle);
return TRUE;
}
static void
i965_libdrm_winsys_destroy(struct brw_winsys_screen *iws)
{
@ -225,9 +102,6 @@ struct drm_api i965_libdrm_api =
{
.name = "i965",
.create_screen = i965_libdrm_create_screen,
.texture_from_shared_handle = i965_libdrm_texture_from_shared_handle,
.shared_handle_from_texture = i965_libdrm_shared_handle_from_texture,
.local_handle_from_texture = i965_libdrm_local_handle_from_texture,
.destroy = destroy,
};

View File

@ -1,4 +1,5 @@
#include "state_tracker/drm_api.h"
#include "i965_drm_winsys.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
@ -122,6 +123,78 @@ err:
return PIPE_ERROR_OUT_OF_MEMORY;
}
static enum pipe_error
i965_libdrm_bo_from_handle(struct brw_winsys_screen *sws,
struct winsys_handle *whandle,
unsigned *stride,
unsigned *tile,
struct brw_winsys_buffer **bo_out)
{
struct i965_libdrm_winsys *idws = i965_libdrm_winsys(sws);
struct i965_libdrm_buffer *buf = CALLOC_STRUCT(i965_libdrm_buffer);
uint32_t swizzle = 0;
if (BRW_DUMP)
debug_printf("%s\n", __FUNCTION__);
if (!buf)
return PIPE_ERROR_OUT_OF_MEMORY;
pipe_reference_init(&buf->base.reference, 1);
buf->bo = drm_intel_bo_gem_create_from_name(idws->gem, "FROM_HANDLE", whandle->handle);
buf->base.size = buf->bo->size;
buf->base.sws = &idws->base;
buf->flinked = TRUE;
buf->flink = whandle->handle;
if (!buf->bo)
goto err;
drm_intel_bo_get_tiling(buf->bo, &buf->tiling, &swizzle);
if (buf->tiling != 0)
buf->map_gtt = TRUE;
*tile = buf->tiling;
*stride = whandle->stride;
*bo_out = &buf->base;
return PIPE_OK;
err:
FREE(buf);
return PIPE_ERROR_OUT_OF_MEMORY;
}
static enum pipe_error
i965_libdrm_bo_get_handle(struct brw_winsys_buffer *buffer,
struct winsys_handle *whandle,
unsigned stride)
{
struct i965_libdrm_buffer *buf = i965_libdrm_buffer(buffer);
if (BRW_DUMP)
debug_printf("%s\n", __FUNCTION__);
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
if (!buf->flinked) {
if (drm_intel_bo_flink(buf->bo, &buf->flink))
return PIPE_ERROR_BAD_INPUT;
buf->flinked = TRUE;
}
whandle->handle = buf->flink;
} else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
whandle->handle = buf->bo->handle;
} else {
assert(!"unknown usage");
return PIPE_ERROR_BAD_INPUT;
}
whandle->stride = stride;
return PIPE_OK;
}
static void
i965_libdrm_bo_destroy(struct brw_winsys_buffer *buffer)
{
@ -415,6 +488,8 @@ void
i965_libdrm_winsys_init_buffer_functions(struct i965_libdrm_winsys *idws)
{
idws->base.bo_alloc = i965_libdrm_bo_alloc;
idws->base.bo_from_handle = i965_libdrm_bo_from_handle;
idws->base.bo_get_handle = i965_libdrm_bo_get_handle;
idws->base.bo_destroy = i965_libdrm_bo_destroy;
idws->base.bo_emit_reloc = i965_libdrm_bo_emit_reloc;
idws->base.bo_exec = i965_libdrm_bo_exec;