Commit 8b63f9b4 authored by Jakob Bornecrantz's avatar Jakob Bornecrantz

winsys/sw: Add a software winsys layered on a pipe

parent eaee22ac
......@@ -142,8 +142,10 @@ cell_is_format_supported( struct pipe_screen *screen,
format == PIPE_FORMAT_A8B8G8R8_SRGB)
return FALSE;
if (tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if (!winsys->is_displaytarget_format_supported(winsys, format))
if (tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if (!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}
......
......@@ -105,6 +105,7 @@ cell_displaytarget_layout(struct pipe_screen *screen,
/* Round up the surface size to a multiple of the tile size?
*/
ct->dt = winsys->displaytarget_create(winsys,
ct->base->tex_usage,
ct->base.format,
ct->base.width0,
ct->base.height0,
......
......@@ -204,8 +204,10 @@ llvmpipe_is_format_supported( struct pipe_screen *_screen,
return FALSE;
}
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if(!winsys->is_displaytarget_format_supported(winsys, format))
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}
......
......@@ -103,6 +103,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
unsigned height = align(lpt->base.height0, TILE_SIZE);
lpt->dt = winsys->displaytarget_create(winsys,
lpt->base.tex_usage,
lpt->base.format,
width, height,
16,
......@@ -250,6 +251,55 @@ llvmpipe_texture_unmap(struct pipe_texture *texture,
}
static struct pipe_texture *
llvmpipe_texture_from_handle(struct pipe_screen *screen,
const struct pipe_texture *template,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture);
if (!lpt)
return NULL;
lpt->base = *template;
pipe_reference_init(&lpt->base.reference, 1);
lpt->base.screen = screen;
lpt->pot = (util_is_power_of_two(template->width0) &&
util_is_power_of_two(template->height0) &&
util_is_power_of_two(template->depth0));
lpt->dt = winsys->displaytarget_from_handle(winsys,
template,
whandle,
&lpt->stride[0]);
if (!lpt->dt)
goto fail;
return &lpt->base;
fail:
FREE(lpt);
return NULL;
}
static boolean
llvmpipe_texture_get_handle(struct pipe_screen *screen,
struct pipe_texture *pt,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
struct llvmpipe_texture *lpt = llvmpipe_texture(pt);
assert(lpt->dt);
if (!lpt->dt)
return FALSE;
return winsys->displaytarget_get_handle(winsys, lpt->dt, whandle);
}
static struct pipe_surface *
llvmpipe_get_tex_surface(struct pipe_screen *screen,
struct pipe_texture *pt,
......@@ -418,6 +468,7 @@ llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = llvmpipe_texture_create;
screen->texture_destroy = llvmpipe_texture_destroy;
screen->texture_get_handle = llvmpipe_texture_get_handle;
screen->get_tex_surface = llvmpipe_get_tex_surface;
screen->tex_surface_destroy = llvmpipe_tex_surface_destroy;
......
......@@ -173,8 +173,10 @@ softpipe_is_format_supported( struct pipe_screen *screen,
break;
}
if(tex_usage & PIPE_TEXTURE_USAGE_DISPLAY_TARGET) {
if(!winsys->is_displaytarget_format_supported(winsys, format))
if(tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
PIPE_TEXTURE_USAGE_SCANOUT |
PIPE_TEXTURE_USAGE_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format))
return FALSE;
}
......
......@@ -91,6 +91,7 @@ softpipe_displaytarget_layout(struct pipe_screen *screen,
/* Round up the surface size to a multiple of the tile size?
*/
spt->dt = winsys->displaytarget_create(winsys,
spt->base.tex_usage,
spt->base.format,
spt->base.width0,
spt->base.height0,
......@@ -139,8 +140,6 @@ softpipe_texture_create(struct pipe_screen *screen,
}
static void
softpipe_texture_destroy(struct pipe_texture *pt)
{
......@@ -161,6 +160,55 @@ softpipe_texture_destroy(struct pipe_texture *pt)
}
static struct pipe_texture *
softpipe_texture_from_handle(struct pipe_screen *screen,
const struct pipe_texture *template,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_texture *spt = CALLOC_STRUCT(softpipe_texture);
if (!spt)
return NULL;
spt->base = *template;
pipe_reference_init(&spt->base.reference, 1);
spt->base.screen = screen;
spt->pot = (util_is_power_of_two(template->width0) &&
util_is_power_of_two(template->height0) &&
util_is_power_of_two(template->depth0));
spt->dt = winsys->displaytarget_from_handle(winsys,
template,
whandle,
&spt->stride[0]);
if (!spt->dt)
goto fail;
return &spt->base;
fail:
FREE(spt);
return NULL;
}
static boolean
softpipe_texture_get_handle(struct pipe_screen *screen,
struct pipe_texture *pt,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_texture *spt = softpipe_texture(pt);
assert(spt->dt);
if (!spt->dt)
return FALSE;
return winsys->displaytarget_get_handle(winsys, spt->dt, whandle);
}
/**
* Get a pipe_surface "view" into a texture.
*/
......@@ -461,6 +509,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->texture_create = softpipe_texture_create;
screen->texture_destroy = softpipe_texture_destroy;
screen->texture_from_handle = softpipe_texture_from_handle;
screen->texture_get_handle = softpipe_texture_get_handle;
screen->get_tex_surface = softpipe_get_tex_surface;
screen->tex_surface_destroy = softpipe_tex_surface_destroy;
......
......@@ -44,6 +44,7 @@ extern "C" {
#endif
struct winsys_handle;
struct pipe_screen;
struct pipe_context;
......@@ -68,6 +69,7 @@ struct sw_winsys
boolean
(*is_displaytarget_format_supported)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format );
/**
......@@ -83,11 +85,29 @@ struct sw_winsys
*/
struct sw_displaytarget *
(*displaytarget_create)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
unsigned alignment,
unsigned *stride );
/**
* Used to implement texture_from_handle.
*/
struct sw_displaytarget *
(*displaytarget_from_handle)( struct sw_winsys *ws,
const struct pipe_texture *templat,
struct winsys_handle *whandle,
unsigned *stride );
/**
* Used to implement texture_get_handle.
*/
boolean
(*displaytarget_get_handle)( struct sw_winsys *ws,
struct sw_displaytarget *dt,
struct winsys_handle *whandle );
/**
* \param flags bitmask of PIPE_BUFFER_USAGE_x flags
*/
......
......@@ -2,7 +2,7 @@
TOP = ../../../..
include $(TOP)/configs/current
SUBDIRS = $(GALLIUM_WINSYS_DRM_DIRS)
SUBDIRS = sw $(GALLIUM_WINSYS_DRM_DIRS)
default install clean:
@for dir in $(SUBDIRS) ; do \
......
......@@ -7,6 +7,7 @@ PIPE_DRIVERS = \
$(TOP)/src/gallium/state_trackers/dri/libdridrm.a \
$(TOP)/src/gallium/winsys/drm/i965/gem/libi965drm.a \
$(TOP)/src/gallium/drivers/trace/libtrace.a \
$(TOP)/src/gallium/winsys/drm/sw/libswdrm.a \
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
$(TOP)/src/gallium/drivers/identity/libidentity.a \
$(TOP)/src/gallium/drivers/i965/libi965.a
......
......@@ -10,6 +10,8 @@
#include "trace/tr_drm.h"
#include "../../sw/sw_drm_api.h"
/*
* Helper functions
*/
......@@ -108,5 +110,13 @@ struct drm_api i965_libdrm_api =
struct drm_api *
drm_api_create()
{
return trace_drm_create(&i965_libdrm_api);
struct drm_api *api;
if (api == NULL && debug_get_bool_option("BRW_SOFTPIPE", FALSE))
api = sw_drm_api_create(&i965_libdrm_api);
if (api == NULL)
api = &i965_libdrm_api;
return trace_drm_create(api);
}
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = swdrm
C_SOURCES = \
wrapper_sw_winsys.c \
sw_drm_api.c
LIBRARY_INCLUDES =
LIBRARY_DEFINES =
include ../../../Makefile.template
/**********************************************************
* Copyright 2010 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"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#include "util/u_memory.h"
#include "softpipe/sp_public.h"
#include "state_tracker/drm_api.h"
#include "wrapper_sw_winsys.h"
#include "sw_drm_api.h"
/*
* Defines
*/
struct sw_drm_api
{
struct drm_api base;
struct drm_api *api;
struct sw_winsys *sw;
};
static INLINE struct sw_drm_api *
sw_drm_api(struct drm_api *api)
{
return (struct sw_drm_api *)api;
}
/*
* Exported functions
*/
static struct pipe_screen *
sw_drm_create_screen(struct drm_api *_api, int drmFD,
struct drm_create_screen_arg *arg)
{
struct sw_drm_api *swapi = sw_drm_api(_api);
struct drm_api *api = swapi->api;
struct sw_winsys *sww;
struct pipe_screen *screen;
screen = api->create_screen(api, drmFD, arg);
sww = wrapper_sw_winsys_warp_pipe_screen(screen);
return softpipe_create_screen(sww);
}
static void
sw_drm_destroy(struct drm_api *api)
{
struct sw_drm_api *swapi = sw_drm_api(api);
if (swapi->api->destroy)
swapi->api->destroy(swapi->api);
FREE(swapi);
}
struct drm_api *
sw_drm_api_create(struct drm_api *api)
{
struct sw_drm_api *swapi = CALLOC_STRUCT(sw_drm_api);
swapi->base.name = "sw";
swapi->base.driver_name = api->driver_name;
swapi->base.create_screen = sw_drm_create_screen;
swapi->base.destroy = sw_drm_destroy;
swapi->api = api;
return &swapi->base;
}
/**********************************************************
* Copyright 2010 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"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#ifndef SW_DRM_API_H
#define SW_DRM_API_H
struct drm_api;
struct drm_api * sw_drm_api_create(struct drm_api *api);
#endif
/**********************************************************
* Copyright 2010 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"), to deal in the Software without
* restriction, including without limitation the rights to use, copy,
* modify, merge, publish, distribute, sublicense, and/or sell copies
* of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**********************************************************/
#include "wrapper_sw_winsys.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "state_tracker/sw_winsys.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
/*
* This code wraps a pipe_screen and exposes a sw_winsys interface for use
* with software resterizers. This code is used by the DRM based winsys to
* allow access to the drm driver.
*
* We must borrow the whole stack because only the pipe screen knows how
* to decode the content of a buffer. Or how to create a buffer that
* can still be used by drivers using real hardware (as the case is
* with software st/xorg but hw st/dri).
*
* We also need a pipe context for the transfers.
*/
struct wrapper_sw_winsys
{
struct sw_winsys base;
struct pipe_screen *screen;
struct pipe_context *pipe;
};
struct wrapper_sw_displaytarget
{
struct wrapper_sw_winsys *winsys;
struct pipe_texture *tex;
struct pipe_transfer *transfer;
unsigned width;
unsigned height;
unsigned map_count;
unsigned stride; /**< because we give stride at create */
void *ptr;
};
static INLINE struct wrapper_sw_winsys *
wrapper_sw_winsys(struct sw_winsys *ws)
{
return (struct wrapper_sw_winsys *)ws;
}
static INLINE struct wrapper_sw_displaytarget *
wrapper_sw_displaytarget(struct sw_displaytarget *dt)
{
return (struct wrapper_sw_displaytarget *)dt;
}
/*
* Functions
*/
static boolean
wsw_dt_get_stride(struct wrapper_sw_displaytarget *wdt, unsigned *stride)
{
struct pipe_context *pipe = wdt->winsys->pipe;
struct pipe_texture *tex = wdt->tex;
struct pipe_transfer *tr;
tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0,
PIPE_TRANSFER_READ_WRITE,
0, 0, wdt->width, wdt->height);
if (!tr)
return FALSE;
*stride = tr->stride;
wdt->stride = tr->stride;
pipe->tex_transfer_destroy(pipe, tr);
return TRUE;
}
static struct sw_displaytarget *
wsw_dt_wrap_texture(struct wrapper_sw_winsys *wsw,
struct pipe_texture *tex, unsigned *stride)
{
struct wrapper_sw_displaytarget *wdt = CALLOC_STRUCT(wrapper_sw_displaytarget);
if (!wdt)
goto err_unref;
wdt->tex = tex;
wdt->winsys = wsw;
if (!wsw_dt_get_stride(wdt, stride))
goto err_free;
return (struct sw_displaytarget *)wdt;
err_free:
FREE(wdt);
err_unref:
pipe_texture_reference(&tex, NULL);
return NULL;
}
static struct sw_displaytarget *
wsw_dt_create(struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
unsigned alignment,
unsigned *stride)
{
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
struct pipe_texture templ;
struct pipe_texture *tex;
/*
* XXX Why don't we just get the template.
*/
memset(&templ, 0, sizeof(templ));
templ.width0 = width;
templ.height0 = height;
templ.format = format;
templ.tex_usage = tex_usage;
/* XXX alignment: we can't do anything about this */
tex = wsw->screen->texture_create(wsw->screen, &templ);
if (!tex)
return NULL;
return wsw_dt_wrap_texture(wsw, tex, stride);
}
static struct sw_displaytarget *
wsw_dt_from_handle(struct sw_winsys *ws,
const struct pipe_texture *templ,
struct winsys_handle *whandle,
unsigned *stride)
{
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
struct pipe_texture *tex;
tex = wsw->screen->texture_from_handle(wsw->screen, templ, whandle);
if (!tex)
return NULL;
return wsw_dt_wrap_texture(wsw, tex, stride);
}
static void *
wsw_dt_map(struct sw_winsys *ws,
struct sw_displaytarget *dt,
unsigned flags)
{
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
struct pipe_context *pipe = wdt->winsys->pipe;
struct pipe_texture *tex = wdt->tex;
struct pipe_transfer *tr;
void *ptr;
if (!wdt->map_count) {
assert(!wdt->transfer);
tr = pipe->get_tex_transfer(pipe, tex, 0, 0, 0,
PIPE_TRANSFER_READ_WRITE,
0, 0, wdt->width, wdt->height);
if (!tr)
return NULL;
ptr = pipe->transfer_map(pipe, tr);
if (!ptr)
goto err;
wdt->transfer = tr;
wdt->ptr = ptr;
/* XXX Handle this case */
assert(tr->stride == wdt->stride);
}
wdt->map_count++;
return wdt->ptr;
err:
pipe->tex_transfer_destroy(pipe, tr);
return NULL;
}
static void
wsw_dt_unmap(struct sw_winsys *ws,
struct sw_displaytarget *dt)
{
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
struct pipe_context *pipe = wdt->winsys->pipe;
assert(wdt->transfer);
wdt->map_count--;
if (wdt->map_count)
return;
pipe->transfer_unmap(pipe, wdt->transfer);
pipe->tex_transfer_destroy(pipe, wdt->transfer);
wdt->transfer = NULL;
}
static void
wsw_dt_destroy(struct sw_winsys *ws,
struct sw_displaytarget *dt)
{
struct wrapper_sw_displaytarget *wdt = wrapper_sw_displaytarget(dt);
pipe_texture_reference(&wdt->tex, NULL);
FREE(wdt);
}
static void
wsw_destroy(struct sw_winsys *ws)
{
struct wrapper_sw_winsys *wsw = wrapper_sw_winsys(ws);
wsw->pipe->destroy(wsw->pipe);
wsw->screen->destroy(wsw->screen);
FREE(wsw);
}
struct sw_winsys *
wrapper_sw_winsys_warp_pipe_screen(struct pipe_screen *screen)
{
struct wrapper_sw_winsys *wsw = CALLOC_STRUCT(wrapper_sw_winsys);
wsw->base.displaytarget_create = wsw_dt_create;
wsw->base.displaytarget_from_handle = wsw_dt_from_handle;
wsw->base.displaytarget_map = wsw_dt_map;
wsw->base.displaytarget_unmap = wsw_dt_unmap;
wsw->base.displaytarget_destroy = wsw_dt_destroy;
wsw->base.destroy = wsw_destroy;
wsw->screen = screen;
wsw->pipe = screen->context_create(screen, NULL);
if (!wsw->pipe)
goto err;
return &wsw->base;
err:
FREE(wsw);
return NULL;
}
/**********************************************************
* Copyright 2010 VMware, Inc. All rights reserved.
*