From 7041c420e91ce2c661b96aec89b2c001469a505a Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Wed, 10 Aug 2011 00:25:52 +0300 Subject: links, loads (try glxinfo) but breaks since the init isn't implemented, first message (screen_complete sends a screen_connect). Need to create a socket and allocate some buffers. Xen VGallium used a number of rings. For a socket it's probably overkill, later I'll want to abstract this for ring/no ring, right now probably just do the minimum. --- configs/default | 4 +- configure.ac | 18 ++ src/gallium/drivers/remote/remote_context.c | 14 +- src/gallium/drivers/remote/remote_messages.h | 40 +++- src/gallium/drivers/remote/remote_screen.c | 26 ++- src/gallium/drivers/remote/remote_util.h | 2 +- .../targets/libgl-xlib-remote/xlib_remote.c | 136 ++++++++++++++ .../winsys/sw/remote_xlib/remote_xlib_sw_winsys.c | 208 +++++++++++++++++++-- 8 files changed, 404 insertions(+), 44 deletions(-) create mode 100644 src/gallium/targets/libgl-xlib-remote/xlib_remote.c diff --git a/configs/default b/configs/default index 078c85e8b4..b1d09c37f9 100644 --- a/configs/default +++ b/configs/default @@ -20,8 +20,8 @@ DRM_SOURCE_PATH=$(TOP)/../drm CC = cc CXX = CC HOST_CC = $(CC) -CFLAGS = -O -CXXFLAGS = -O +CFLAGS = -O0 -ggdb3 +CXXFLAGS = -O0 -ggdb3 LDFLAGS = HOST_CFLAGS = $(CFLAGS) GLU_CFLAGS = diff --git a/configure.ac b/configure.ac index ea58dae659..336429ae99 100644 --- a/configure.ac +++ b/configure.ac @@ -621,6 +621,11 @@ AC_ARG_ENABLE([gallium_gbm], @<:@default=auto@:>@])], [enable_gallium_gbm="$enableval"], [enable_gallium_gbm=auto]) +AC_ARG_ENABLE([remote], + [AS_HELP_STRING([--enable-remote], + [enable remoting libGL @<:@default=auto@:>@])], + [enable_remote="$enableval"], + [enable_remote=no]) # Option for Gallium drivers GALLIUM_DRIVERS_DEFAULT="r300,r600,swrast" @@ -801,6 +806,19 @@ x*yes*) ;; esac +case "x$enable_remote$enable_glx$enable_xlib_glx" in +xyesnono|xyesnoyes|xyesyesyes) + echo "--enable-remote requires --enable-glx and no --enable-xlib-glx" + exit 1 + ;; +xyesyesno) + GALLIUM_WINSYS_DIRS="$GALLIUM_WINSYS_DIRS sw/remote-xlib" + GALLIUM_TARGET_DIRS="$GALLIUM_TARGET_DIRS libgl-xlib-remote" + GALLIUM_STATE_TRACKERS_DIRS="glx $GALLIUM_STATE_TRACKERS_DIRS" + HAVE_WINSYS_XLIB="yes" + ;; +esac + case "x$enable_glx$enable_xlib_glx" in xyesyes) DRIVER_DIRS="$DRIVER_DIRS x11" diff --git a/src/gallium/drivers/remote/remote_context.c b/src/gallium/drivers/remote/remote_context.c index 4df3bd1e65..a781d84804 100644 --- a/src/gallium/drivers/remote/remote_context.c +++ b/src/gallium/drivers/remote/remote_context.c @@ -141,7 +141,7 @@ remote_context_draw_elements(struct pipe_context *_pipe, { - DBG("Draw elements: using index buffer %u, size %u, mode %u, start %u, count %u\n", BUFFER_HANDLE(indexBuffer), indexSize, mode, start, count); + DBG("Draw elements: using index buffer %u, size %u, mode %u, start %u, count %u\n", RESOURCE_HANDLE(indexBuffer), indexSize, mode, start, count); mark_framebuffer_dirty(_pipe); @@ -149,7 +149,7 @@ remote_context_draw_elements(struct pipe_context *_pipe, message->base.opcode = REMREQ_DRAW_ELEMENTS; message->pipe = PIPE_HANDLE(_pipe); - message->buffer = BUFFER_HANDLE(indexBuffer); + message->buffer = RESOURCE_HANDLE(indexBuffer); message->indexSize = indexSize; message->mode = mode; message->start = start; @@ -183,7 +183,7 @@ remote_context_draw_range_elements(struct pipe_context *_pipe, unsigned count) { - DBG("Draw range elements: using index buffer %u, size %u, mode %u, start %u, count %u, limits %u/%u\n", BUFFER_HANDLE(indexBuffer), indexSize, mode, start, count, minIndex, maxIndex); + DBG("Draw range elements: using index buffer %u, size %u, mode %u, start %u, count %u, limits %u/%u\n", RESOURCE_HANDLE(indexBuffer), indexSize, mode, start, count, minIndex, maxIndex); mark_framebuffer_dirty(_pipe); @@ -191,7 +191,7 @@ remote_context_draw_range_elements(struct pipe_context *_pipe, message->base.opcode = REMREQ_DRAW_RANGE_ELEMENTS; message->pipe = PIPE_HANDLE(_pipe); - message->buffer = BUFFER_HANDLE(indexBuffer); + message->buffer = RESOURCE_HANDLE(indexBuffer); message->indexSize = indexSize; message->minIndex = minIndex; message->maxIndex = maxIndex; @@ -797,7 +797,7 @@ remote_context_set_constant_buffer(struct pipe_context *_pipe, message->pipe = PIPE_HANDLE(_pipe); message->shader = shader; message->index = index; - message->buffer = BUFFER_HANDLE(buffer); + message->buffer = RESOURCE_HANDLE(buffer); /* char* mapped = (char*)pipe_buffer_map(_pipe->screen, buffer->buffer, PIPE_BUFFER_USAGE_CPU_READ); @@ -977,8 +977,8 @@ remote_context_set_vertex_buffers(struct pipe_context *_pipe, for(i = 0; i < num_buffers; i++) { data[i].stride = buffers[i].stride; data[i].buffer_offset = buffers[i].buffer_offset; - data[i].buffer = buffers[i].buffer ? BUFFER_HANDLE(buffers[i].buffer) : 0; - DBG("Buffer slot %d assigned buffer handle %u\n", i, data[i].buffer); + data[i].resource = buffers[i].buffer ? RESOURCE_HANDLE(buffers[i].buffer) : 0; + DBG("Buffer slot %d assigned resource handle %u\n", i, data[i].resource); } enqueue_message(header); diff --git a/src/gallium/drivers/remote/remote_messages.h b/src/gallium/drivers/remote/remote_messages.h index 8ae1e790c2..f06c3c6024 100644 --- a/src/gallium/drivers/remote/remote_messages.h +++ b/src/gallium/drivers/remote/remote_messages.h @@ -426,7 +426,7 @@ struct remreq_set_sampler_textures { struct opaque_pipe_vertex_element { unsigned stride, buffer_offset; - uint32_t buffer; + uint32_t resource; }; @@ -767,22 +767,24 @@ struct remreq_flush_frontbuffer { struct message_header base; uint32_t screen; uint32_t surface; + uint32_t level; // | flush_frontbuffer: these are unsigned (i.e. 32/64/wtf bits) + uint32_t layer; // | }; -#define REMREQ_FLUSH_FRONTBUFFER 66 +/* added a SCREEN_FLUSH_FRONTBUFFER at the end */ +#define REMREQ_WINSYS_FLUSH_FRONTBUFFER 66 -struct remreq_resource_create { +struct remreq_buffer_create { - struct message_header base; - uint32_t screen; - uint32_t handle; - uint32_t templat_screen; - uint32_t templat_handle; + struct message_header base; + uint32_t screen; + unsigned alignment, size, usage; + uint32_t handle; }; -#define REMREQ_RESOURCE_CREATE 67 +#define REMREQ_BUFFER_CREATE 69 struct remreq_user_buffer_create { @@ -860,6 +862,26 @@ struct remreq_swap_buffers { #define REMREQ_SWAP_BUFFERS 76 +/* Added during porting to newer mesa. Comment below + * still applies - this needs to be either autogenerated or + * at least ordered and use an enum and not defines. */ + +// use remreq_flush_frontbuffer, same for REMREQ_WINSYS_FLUSH_FRONTBUFFER + +#define REMREQ_SCREEN_FLUSH_FRONTBUFFER 80 + +struct remreq_resource_create { + + struct message_header base; + uint32_t screen; + uint32_t handle; + uint32_t templat_screen; + uint32_t templat_handle; + +}; + +#define REMREQ_RESOURCE_CREATE 68 + // Adding new messages for vGallium porting. // All of this should be autogenerated. // Currently for learning purposes doing this on a required basis - not diff --git a/src/gallium/drivers/remote/remote_screen.c b/src/gallium/drivers/remote/remote_screen.c index 5afef8ff95..dbeb0da9f2 100644 --- a/src/gallium/drivers/remote/remote_screen.c +++ b/src/gallium/drivers/remote/remote_screen.c @@ -224,15 +224,31 @@ remote_screen_context_create(struct pipe_screen *_screen, void *priv) } static void -remote_screen_flush_frontbuffer(struct pipe_screen *_screen, - struct pipe_resource *_resource, - unsigned level, unsigned layer, - void *context_private) +remote_screen_flush_frontbuffer( struct pipe_screen *screen, + struct pipe_resource *resource, + unsigned level, unsigned layer, + void *winsys_drawable_handle ) { - DBG("%s: unimplemented\n", __FUNCTION__); + // Original comment from xen vgallium: + // Ignore the context_private pointer, as I can't know where this came from# + // or how to serialise it correctly. + + DBG("Flush frontbuffer\n"); + + ALLOC_OUT_MESSAGE(flush_frontbuffer, message); + + message->base.opcode = REMREQ_SCREEN_FLUSH_FRONTBUFFER; + message->screen = SCREEN_HANDLE(screen); + message->surface = RESOURCE_HANDLE(resource); + message->level = level; + message->layer = layer; + + enqueue_message(message); + } + /******************************************************************** * texture */ diff --git a/src/gallium/drivers/remote/remote_util.h b/src/gallium/drivers/remote/remote_util.h index 68d7c30dfa..4208119b74 100644 --- a/src/gallium/drivers/remote/remote_util.h +++ b/src/gallium/drivers/remote/remote_util.h @@ -27,4 +27,4 @@ #define SURFACE_HANDLE(s) (s ? ((struct remote_surface*)s)->handle : 0) -#define BUFFER_HANDLE(res) (res ? ((struct remote_resource*)res)->handle : 0) +#define RESOURCE_HANDLE(res) (res ? ((struct remote_resource*)res)->handle : 0) diff --git a/src/gallium/targets/libgl-xlib-remote/xlib_remote.c b/src/gallium/targets/libgl-xlib-remote/xlib_remote.c new file mode 100644 index 0000000000..5b31325fc4 --- /dev/null +++ b/src/gallium/targets/libgl-xlib-remote/xlib_remote.c @@ -0,0 +1,136 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/* + * Authors: + * Keith Whitwell + */ +#include "pipe/p_compiler.h" +#include "util/u_debug.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "xm_public.h" + +#include "state_tracker/st_gl_api.h" +#include "target-helpers/inline_sw_helper.h" +#include "target-helpers/inline_debug_helper.h" + + + +/* Helper function to build a subset of a driver stack consisting of + * one the remote rasteriser and the remote_xlib winsys. + */ +static struct pipe_screen * +remote_xlib_create_screen( Display *display ) +{ + struct sw_winsys *winsys; + struct pipe_screen *screen = NULL; + + /* Create the underlying winsys, which performs presents to Xlib + * drawables: + */ + winsys = xlib_remote_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; + + /* Create a software rasterizer on top of that winsys: + */ + screen = remote_screen_create( winsys ); + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return debug_screen_wrap( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; +} + +static struct xm_driver xlib_driver = +{ + .create_pipe_screen = remote_xlib_create_screen, + .create_st_api = st_gl_api_create, +}; + + +/* Build the rendering stack. + */ +static void _init( void ) __attribute__((constructor)); +static void _init( void ) +{ + /* Initialize the xlib libgl code, pass in the winsys: + */ + xmesa_set_driver( &xlib_driver ); +} + + +/*********************************************************************** + * + * Butt-ugly hack to convince the linker not to throw away public GL + * symbols (they are all referenced from getprocaddress, I guess). + */ +extern void (*linker_foo(const unsigned char *procName))(); +extern void (*glXGetProcAddress(const unsigned char *procName))(); + +extern void (*linker_foo(const unsigned char *procName))() +{ + return glXGetProcAddress(procName); +} + + +/** + * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in + * libglapi.a. We need to define them here. + */ +#ifdef GLX_INDIRECT_RENDERING + +#define GL_GLEXT_PROTOTYPES +#include "GL/gl.h" +#include "glapi/glapi.h" +#include "glapi/glapitable.h" + +#if defined(USE_MGL_NAMESPACE) +#define NAME(func) mgl##func +#else +#define NAME(func) gl##func +#endif + +#define DISPATCH(FUNC, ARGS, MESSAGE) \ + GET_DISPATCH()->FUNC ARGS + +#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \ + return GET_DISPATCH()->FUNC ARGS + +/* skip normal ones */ +#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS +#include "glapi/glapitemp.h" + +#endif /* GLX_INDIRECT_RENDERING */ diff --git a/src/gallium/winsys/sw/remote_xlib/remote_xlib_sw_winsys.c b/src/gallium/winsys/sw/remote_xlib/remote_xlib_sw_winsys.c index 978b9db8ad..bdb367af49 100644 --- a/src/gallium/winsys/sw/remote_xlib/remote_xlib_sw_winsys.c +++ b/src/gallium/winsys/sw/remote_xlib/remote_xlib_sw_winsys.c @@ -29,6 +29,8 @@ #include "util/u_memory.h" #include "util/u_hash_table.h" +#include "util/u_format.h" +#include "util/u_math.h" #include "remote_screen.h" #include "remote_state.h" @@ -46,14 +48,14 @@ extern int analyse_waits; struct remote_winsys* singleton_winsys = 0; struct remote_screen* singleton_screen = 0; -struct pipe_winsys * remote_winsys_create(); +struct pipe_winsys * remote_winsys_create(Display *display); static void -remote_create_singletons(void) +remote_create_singletons(Display *display) { if(!singleton_winsys) { DBG("Found no winsys; creating\n"); - singleton_winsys = (struct remote_winsys*)remote_winsys_create(); + singleton_winsys = (struct remote_winsys*)remote_winsys_create(display); } if(!singleton_screen) { @@ -73,6 +75,16 @@ remote_create_singletons(void) } } +struct sw_winsys * +xlib_remote_create_sw_winsys(Display *display) +{ + // TODO - actually use display. Also - do I still need the kludge of the extension + // xen vgallium used to get the changes to the window if I have this Display reference + // here? can't I query it directly for my window's (do I get that reference?) on screen + // location? + remote_create_singletons(display); + return &singleton_winsys->base; +} static const char * winsys_get_name(struct pipe_winsys *_winsys) @@ -82,6 +94,7 @@ winsys_get_name(struct pipe_winsys *_winsys) } +#ifndef REMOTE_USES_SW_WINSYS static void winsys_flush_frontbuffer(struct pipe_winsys *_winsys, @@ -92,11 +105,11 @@ winsys_flush_frontbuffer(struct pipe_winsys *_winsys, // Ignore the context_private pointer, as I can't know where this came from# // or how to serialise it correctly. - DBG("Flush frontbuffer\n"); + DBG("Winsys Flush frontbuffer\n"); ALLOC_OUT_MESSAGE(flush_frontbuffer, message); - message->base.opcode = REMREQ_FLUSH_FRONTBUFFER; + message->base.opcode = REMREQ_WINSYS_FLUSH_FRONTBUFFER; message->screen = WINSYS_HANDLE(_winsys); message->surface = SURFACE_HANDLE(surface); @@ -172,18 +185,18 @@ winsys_buffer_create(struct pipe_winsys *_winsys, enqueue_message(message); - struct remote_buffer* rembuf = CALLOC_STRUCT(remote_buffer); + struct remote_resource* remres = CALLOC_STRUCT(remote_resource); - rembuf->base.alignment = alignment; - rembuf->base.usage = usage; - rembuf->base.size = size; - rembuf->base.refcount = 1; - rembuf->handle = handle; - rembuf->nmaps = 0; - rembuf->is_user = 0; - rembuf->map = malloc(size); - rembuf->remote_dirty = 0; - rembuf->local_dirty = 0; + remres->base.alignment = alignment; + remres->base.usage = usage; + remres->base.size = size; + remres->base.refcount = 1; + remres->handle = handle; + remres->nmaps = 0; + remres->is_user = 0; + remres->map = malloc(size); + remres->remote_dirty = 0; + remres->local_dirty = 0; return (struct pipe_buffer*)rembuf; @@ -433,10 +446,44 @@ winsys_fence_finish(struct pipe_winsys *_winsys, return 0; } +static void +winsys_destroy(struct pipe_winsys *_winsys) +{ + struct remote_winsys *tr_ws = (struct remote_winsys*)_winsys; + + DBG("Destroy winsys for screen %u\n", WINSYS_HANDLE(_winsys)); + + FREE(tr_ws); +} + +#endif // REMOTE_USES_SW_WINSYS + +/** + * Display target for Remote xlib winsys. + * Low-level OS/window system memory buffer + */ +struct remote_displaytarget +{ + struct remote_screen *screen; + enum pipe_format format; + unsigned width; + unsigned height; + unsigned stride; + + void *data; + void *mapped; +}; + +/** Cast wrapper */ +static INLINE struct remote_displaytarget * +remote_displaytarget(struct sw_displaytarget *dt) +{ + return (struct remote_displaytarget *) dt; +} static void -winsys_destroy(struct pipe_winsys *_winsys) +winsys_destroy(struct sw_winsys *_winsys) { struct remote_winsys *tr_ws = (struct remote_winsys*)_winsys; @@ -445,8 +492,125 @@ winsys_destroy(struct pipe_winsys *_winsys) FREE(tr_ws); } +/* these functions taken mostly as is from xlib/xlib_sw_winsys.c, including + * the comments */ +static boolean +remote_is_displaytarget_format_supported(struct sw_winsys *ws, + unsigned tex_usage, + enum pipe_format format) +{ + /* TODO: check visuals or other sensible thing here */ + return TRUE; +} -struct pipe_winsys * remote_winsys_create() +static struct sw_displaytarget * +remote_displaytarget_create(struct sw_winsys *winsys, + unsigned tex_usage, + enum pipe_format format, + unsigned width, unsigned height, + unsigned alignment, + unsigned *stride) +{ + struct remote_displaytarget *remote_dt; + unsigned nblocksy, size; + + remote_dt = CALLOC_STRUCT(remote_displaytarget); + if (!remote_dt) + goto no_remote_dt; + + remote_dt->screen = ((struct remote_winsys *)winsys)->screen; + remote_dt->format = format; + remote_dt->width = width; + remote_dt->height = height; + + nblocksy = util_format_get_nblocksy(format, height); + remote_dt->stride = align(util_format_get_stride(format, width), alignment); + size = remote_dt->stride * nblocksy; + + remote_dt->data = align_malloc(size, alignment); + if (!remote_dt->data) { + goto no_data; + } + + *stride = remote_dt->stride; + return (struct sw_displaytarget *)remote_dt; + +no_data: + FREE(remote_dt); +no_remote_dt: + return NULL; +} + + +static struct sw_displaytarget * +remote_displaytarget_from_handle(struct sw_winsys *winsys, + const struct pipe_resource *templet, + struct winsys_handle *whandle, + unsigned *stride) +{ + assert(0); + return NULL; +} + + +static boolean +remote_displaytarget_get_handle(struct sw_winsys *winsys, + struct sw_displaytarget *dt, + struct winsys_handle *whandle) +{ + assert(0); + return FALSE; +} + +static void * +remote_displaytarget_map(struct sw_winsys *ws, + struct sw_displaytarget *dt, + unsigned flags) +{ + struct remote_displaytarget *remote_dt = remote_displaytarget(dt); + remote_dt->mapped = remote_dt->data; + return remote_dt->mapped; +} + + +static void +remote_displaytarget_unmap(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct remote_displaytarget *remote_dt = remote_displaytarget(dt); + remote_dt->mapped = NULL; +} + +static void +remote_displaytarget_destroy(struct sw_winsys *ws, + struct sw_displaytarget *dt) +{ + struct remote_displaytarget *remote_dt = remote_displaytarget(dt); + + if (remote_dt->data) { + FREE(remote_dt->data); + remote_dt->data = NULL; + } + + FREE(remote_dt); +} + +/** + * Display/copy the image in the surface into the X window specified + * by the display target. + */ +static void +remote_displaytarget_display(struct sw_winsys *ws, + struct sw_displaytarget *dt, + void *context_private) +{ + //struct remote_drawable *remote_drawable = (struct remote_drawable *)context_private; + DBG("%s\n", __FUNCTION__); + //remote_sw_display(remote_drawable, dt); +} + + +struct pipe_winsys * remote_winsys_create(Display *display) { struct remote_winsys *rem_ws; @@ -457,6 +621,8 @@ struct pipe_winsys * remote_winsys_create() goto error1; rem_ws->base.destroy = winsys_destroy; + +#ifndef REMOTE_USES_SW_WINSYS rem_ws->base.get_name = winsys_get_name; rem_ws->base.flush_frontbuffer = winsys_flush_frontbuffer; rem_ws->base.surface_alloc = winsys_surface_alloc; @@ -470,8 +636,10 @@ struct pipe_winsys * remote_winsys_create() rem_ws->base.fence_reference = winsys_fence_reference; rem_ws->base.fence_signalled = winsys_fence_signalled; rem_ws->base.fence_finish = winsys_fence_finish; +#endif - rem_ws->base.is_displaytarget_format_supported = remote_is_displaytarget_format_supported; + rem_ws->base.is_displaytarget_format_supported = + remote_is_displaytarget_format_supported; rem_ws->base.displaytarget_create = remote_displaytarget_create; rem_ws->base.displaytarget_from_handle = remote_displaytarget_from_handle; @@ -481,7 +649,7 @@ struct pipe_winsys * remote_winsys_create() rem_ws->base.displaytarget_destroy = remote_displaytarget_destroy; rem_ws->base.displaytarget_display = remote_displaytarget_display; - + rem_ws->display = display; return &rem_ws->base; -- cgit v1.2.3