diff options
Diffstat (limited to 'src/gallium/state_trackers')
136 files changed, 8231 insertions, 7344 deletions
diff --git a/src/gallium/state_trackers/dri/Makefile b/src/gallium/state_trackers/dri/Makefile index ef8f19709ab..72e70577b3d 100644 --- a/src/gallium/state_trackers/dri/Makefile +++ b/src/gallium/state_trackers/dri/Makefile @@ -1,28 +1,12 @@ +# src/gallium/state_trackers/dri/Makefile TOP = ../../../.. include $(TOP)/configs/current -LIBNAME = dridrm +SUBDIRS = drm sw -LIBRARY_INCLUDES = \ - -I$(TOP)/include \ - -I$(TOP)/src/mesa \ - -I$(TOP)/src/mesa/drivers/dri/common \ - -I$(TOP)/src/mesa/main \ - $(shell pkg-config --cflags-only-I libdrm) - - -C_SOURCES = \ - dri_context.c \ - dri_screen.c \ - dri_drawable.c \ - dri_extensions.c - -# $(TOP)/src/mesa/drivers/dri/common/utils.c \ - $(TOP)/src/mesa/drivers/dri/common/vblank.c \ - $(TOP)/src/mesa/drivers/dri/common/dri_util.c \ - $(TOP)/src/mesa/drivers/dri/common/xmlconfig.c \ - $(TOP)/src/mesa/drivers/common/driverfuncs.c \ - $(TOP)/src/mesa/drivers/dri/common/texmem.c \ - $(TOP)/src/mesa/drivers/dri/common/drirenderbuffer.c - -include ../../Makefile.template +default install clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) $@) || exit 1; \ + fi \ + done diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript index ce2c2735974..aba60fb8c5b 100644 --- a/src/gallium/state_trackers/dri/SConscript +++ b/src/gallium/state_trackers/dri/SConscript @@ -1,23 +1,6 @@ -####################################################################### -# SConscript for dri state_tracker - Import('*') -if env['dri']: - - env = env.Clone() - - env.Append(CPPPATH = [ - '#/src/mesa', - '#/src/mesa/drivers/dri/common', - ]) - - st_dri = env.ConvenienceLibrary( - target = 'st_dri', - source = [ 'dri_context.c', - 'dri_drawable.c', - 'dri_extensions.c', - 'dri_screen.c', - ] - ) - Export('st_dri') +SConscript([ + 'sw/SConscript', + 'drm/SConscript', +]) diff --git a/src/gallium/state_trackers/dri/common/dri1_helper.c b/src/gallium/state_trackers/dri/common/dri1_helper.c new file mode 100644 index 00000000000..f641b41ff8b --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri1_helper.c @@ -0,0 +1,129 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Management of pipe objects (surface / pipe / fences) used by DRI1 and DRISW. + * + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +#include "util/u_inlines.h" +#include "pipe/p_context.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri1_helper.h" + +struct pipe_fence_handle * +dri1_swap_fences_pop_front(struct dri_drawable *draw) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->base.screen; + struct pipe_fence_handle *fence = NULL; + + if (draw->cur_fences >= draw->desired_fences) { + screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); + screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); + --draw->cur_fences; + draw->tail &= DRI_SWAP_FENCES_MASK; + } + return fence; +} + +void +dri1_swap_fences_push_back(struct dri_drawable *draw, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = dri_screen(draw->sPriv)->base.screen; + + if (!fence) + return; + + if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { + draw->cur_fences++; + screen->fence_reference(screen, &draw->swap_fences[draw->head++], + fence); + draw->head &= DRI_SWAP_FENCES_MASK; + } +} + +void +dri1_swap_fences_clear(struct dri_drawable *drawable) +{ + struct pipe_screen *screen = dri_screen(drawable->sPriv)->base.screen; + struct pipe_fence_handle *fence; + + while (drawable->cur_fences) { + fence = dri1_swap_fences_pop_front(drawable); + screen->fence_reference(screen, &fence, NULL); + } +} + +struct pipe_surface * +dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex) +{ + struct pipe_screen *pipe_screen = dri_screen(drawable->sPriv)->base.screen; + struct pipe_surface *psurf = drawable->dri1_surface; + + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&drawable->dri1_surface, NULL); + + drawable->dri1_surface = pipe_screen->get_tex_surface(pipe_screen, + ptex, 0, 0, 0, PIPE_BIND_BLIT_SOURCE); + + psurf = drawable->dri1_surface; + } + + return psurf; +} + +void +dri1_destroy_pipe_surface(struct dri_drawable *drawable) +{ + pipe_surface_reference(&drawable->dri1_surface, NULL); +} + +struct pipe_context * +dri1_get_pipe_context(struct dri_screen *screen) +{ + struct pipe_context *pipe = screen->dri1_pipe; + + if (!pipe) { + screen->dri1_pipe = + screen->base.screen->context_create(screen->base.screen, NULL); + pipe = screen->dri1_pipe; + } + + return pipe; +} + +void +dri1_destroy_pipe_context(struct dri_screen *screen) +{ + if (screen->dri1_pipe) + screen->dri1_pipe->destroy(screen->dri1_pipe); +} diff --git a/src/gallium/state_trackers/dri/common/dri1_helper.h b/src/gallium/state_trackers/dri/common/dri1_helper.h new file mode 100644 index 00000000000..c98adf2df22 --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri1_helper.h @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +#ifndef DRI1_HELPER_H +#define DRI1_HELPER_H + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" + +struct pipe_fence_handle * +dri1_swap_fences_pop_front(struct dri_drawable *draw); + +void +dri1_swap_fences_push_back(struct dri_drawable *draw, + struct pipe_fence_handle *fence); + +void +dri1_swap_fences_clear(struct dri_drawable *drawable); + +struct pipe_surface * +dri1_get_pipe_surface(struct dri_drawable *drawable, struct pipe_resource *ptex); + +void +dri1_destroy_pipe_surface(struct dri_drawable *drawable); + +struct pipe_context * +dri1_get_pipe_context(struct dri_screen *screen); + +void +dri1_destroy_pipe_context(struct dri_screen *screen); + +#endif /* DRI1_HELPER_H */ diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c index 69b55183965..a808d2d9ddf 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/common/dri_context.c @@ -29,18 +29,24 @@ * Author: Jakob Bornecrantz <[email protected]> */ -#include "dri_screen.h" +#include "utils.h" +#include "dri_screen.h" #include "dri_drawable.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" +#include "dri_context.h" + #include "pipe/p_context.h" +#include "state_tracker/st_context.h" -#include "dri_context.h" +static void +dri_init_extensions(struct dri_context *ctx) +{ + struct st_context *st = (struct st_context *) ctx->st; -#include "util/u_memory.h" + /* New extensions should be added in mesa/state_tracker/st_extensions.c + * and not in this file. */ + driInitExtensions(st->ctx, NULL, GL_FALSE); +} GLboolean dri_create_context(const __GLcontextModes * visual, @@ -48,8 +54,10 @@ dri_create_context(const __GLcontextModes * visual, { __DRIscreen *sPriv = cPriv->driScreenPriv; struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; struct dri_context *ctx = NULL; - struct st_context *st_share = NULL; + struct st_context_iface *st_share = NULL; + struct st_visual stvis; if (sharedContextPrivate) { st_share = ((struct dri_context *)sharedContextPrivate)->st; @@ -63,21 +71,15 @@ dri_create_context(const __GLcontextModes * visual, ctx->cPriv = cPriv; ctx->sPriv = sPriv; ctx->lock = screen->drmLock; - ctx->d_stamp = -1; - ctx->r_stamp = -1; driParseConfigFiles(&ctx->optionCache, &screen->optionCache, sPriv->myNum, "dri"); - ctx->pipe = screen->pipe_screen->context_create( screen->pipe_screen, - ctx ); - - if (ctx->pipe == NULL) - goto fail; - - ctx->st = st_create_context(ctx->pipe, visual, st_share); + dri_fill_st_visual(&stvis, screen, visual); + ctx->st = stapi->create_context(stapi, &screen->base, &stvis, st_share); if (ctx->st == NULL) goto fail; + ctx->st->st_manager_private = (void *) ctx; dri_init_extensions(ctx); @@ -85,10 +87,7 @@ dri_create_context(const __GLcontextModes * visual, fail: if (ctx && ctx->st) - st_destroy_context(ctx->st); - - if (ctx && ctx->pipe) - ctx->pipe->destroy(ctx->pipe); + ctx->st->destroy(ctx->st); FREE(ctx); return FALSE; @@ -110,11 +109,8 @@ dri_destroy_context(__DRIcontext * cPriv) * to avoid having to add code elsewhere to cope with flushing a * partially destroyed context. */ - st_flush(ctx->st, 0, NULL); - - /* Also frees ctx->pipe? - */ - st_destroy_context(ctx->st); + ctx->st->flush(ctx->st, 0, NULL); + ctx->st->destroy(ctx->st); FREE(ctx); } @@ -122,14 +118,15 @@ dri_destroy_context(__DRIcontext * cPriv) GLboolean dri_unbind_context(__DRIcontext * cPriv) { - if (cPriv) { - struct dri_context *ctx = dri_context(cPriv); - - if (--ctx->bind_count == 0) { - if (ctx->st && ctx->st == st_get_current()) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - st_make_current(NULL, NULL, NULL); - } + /* dri_util.c ensures cPriv is not null */ + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_context *ctx = dri_context(cPriv); + struct st_api *stapi = screen->st_api; + + if (--ctx->bind_count == 0) { + if (ctx->st == stapi->get_current(stapi)) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + stapi->make_current(stapi, NULL, NULL, NULL); } } @@ -141,77 +138,43 @@ dri_make_current(__DRIcontext * cPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv) { - if (cPriv) { - struct dri_context *ctx = dri_context(cPriv); - struct dri_drawable *draw = dri_drawable(driDrawPriv); - struct dri_drawable *read = dri_drawable(driReadPriv); - struct st_context *old_st = st_get_current(); + /* dri_util.c ensures cPriv is not null */ + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_context *ctx = dri_context(cPriv); + struct st_api *stapi = screen->st_api; + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + struct st_context_iface *old_st = stapi->get_current(stapi); - if (old_st && old_st != ctx->st) - st_flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); + if (old_st && old_st != ctx->st) + old_st->flush(old_st, PIPE_FLUSH_RENDER_CACHE, NULL); - ++ctx->bind_count; + ++ctx->bind_count; - if (ctx->dPriv != driDrawPriv) { - ctx->dPriv = driDrawPriv; - ctx->d_stamp = driDrawPriv->lastStamp - 1; - } - if (ctx->rPriv != driReadPriv) { - ctx->rPriv = driReadPriv; - ctx->r_stamp = driReadPriv->lastStamp - 1; - } - - st_make_current(ctx->st, draw->stfb, read->stfb); - - if (__dri1_api_hooks) { - dri1_update_drawables(ctx, draw, read); - } else { - dri_update_buffer(ctx->pipe->screen, - ctx->pipe->priv); - } - } else { - st_make_current(NULL, NULL, NULL); + if (ctx->dPriv != driDrawPriv) { + ctx->dPriv = driDrawPriv; + draw->texture_stamp = driDrawPriv->lastStamp - 1; + } + if (ctx->rPriv != driReadPriv) { + ctx->rPriv = driReadPriv; + read->texture_stamp = driReadPriv->lastStamp - 1; } - return GL_TRUE; -} - -static void -st_dri_lock(void *pipe_priv) -{ - dri_lock((struct dri_context *)pipe_priv); -} + stapi->make_current(stapi, ctx->st, &draw->base, &read->base); -static void -st_dri_unlock(void *pipe_priv) -{ - dri_unlock((struct dri_context *)pipe_priv); + return GL_TRUE; } -static boolean -st_dri_is_locked(void *pipe_priv) +struct dri_context * +dri_get_current(__DRIscreen *sPriv) { - return ((struct dri_context *)pipe_priv)->isLocked; -} + struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; + struct st_context_iface *st; -static boolean -st_dri_lost_lock(void *pipe_priv) -{ - return ((struct dri_context *)pipe_priv)->wsLostLock; -} + st = stapi->get_current(stapi); -static void -st_dri_clear_lost_lock(void *pipe_priv) -{ - ((struct dri_context *)pipe_priv)->wsLostLock = FALSE; + return (struct dri_context *) (st) ? st->st_manager_private : NULL; } -struct dri1_api_lock_funcs dri1_lf = { - .lock = st_dri_lock, - .unlock = st_dri_unlock, - .is_locked = st_dri_is_locked, - .is_lock_lost = st_dri_lost_lock, - .clear_lost_lock = st_dri_clear_lost_lock -}; - /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/common/dri_context.h index 13f497462f7..9fe6b581016 100644 --- a/src/gallium/state_trackers/dri/dri_context.h +++ b/src/gallium/state_trackers/dri/common/dri_context.h @@ -33,8 +33,7 @@ #define DRI_CONTEXT_H #include "pipe/p_compiler.h" -#include "drm.h" -#include "dri_util.h" +#include "dri_wrapper.h" struct pipe_context; struct pipe_fence; @@ -51,9 +50,6 @@ struct dri_context driOptionCache optionCache; - unsigned int d_stamp; - unsigned int r_stamp; - drmLock *lock; boolean isLocked; boolean stLostLock; @@ -62,8 +58,7 @@ struct dri_context unsigned int bind_count; /* gallium */ - struct st_context *st; - struct pipe_context *pipe; + struct st_context_iface *st; }; static INLINE struct dri_context * @@ -72,33 +67,9 @@ dri_context(__DRIcontext * driContextPriv) return (struct dri_context *)driContextPriv->driverPrivate; } -static INLINE void -dri_lock(struct dri_context *ctx) -{ - drm_context_t hw_context = ctx->cPriv->hHWContext; - char ret = 0; - - DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); - if (ret) { - drmGetLock(ctx->sPriv->fd, hw_context, 0); - ctx->stLostLock = TRUE; - ctx->wsLostLock = TRUE; - } - ctx->isLocked = TRUE; -} - -static INLINE void -dri_unlock(struct dri_context *ctx) -{ - ctx->isLocked = FALSE; - DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); -} - /*********************************************************************** * dri_context.c */ -extern struct dri1_api_lock_funcs dri1_lf; - void dri_destroy_context(__DRIcontext * driContextPriv); boolean dri_unbind_context(__DRIcontext * driContextPriv); @@ -108,16 +79,14 @@ dri_make_current(__DRIcontext * driContextPriv, __DRIdrawable * driDrawPriv, __DRIdrawable * driReadPriv); +struct dri_context * +dri_get_current(__DRIscreen * driScreenPriv); + boolean dri_create_context(const __GLcontextModes * visual, __DRIcontext * driContextPriv, void *sharedContextPrivate); -/*********************************************************************** - * dri_extensions.c - */ -void dri_init_extensions(struct dri_context *ctx); - #endif /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c new file mode 100644 index 00000000000..25892fc7a76 --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri_drawable.c @@ -0,0 +1,224 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri1_helper.h" + +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + + +static boolean +dri_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct dri_screen *screen = dri_screen(drawable->sPriv); + unsigned statt_mask, new_mask; + boolean new_stamp; + int i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= (1 << statts[i]); + + /* record newly allocated textures */ + new_mask = (statt_mask & ~drawable->texture_mask); + + /* + * dPriv->pStamp is the server stamp. It should be accessed with a lock, at + * least for DRI1. dPriv->lastStamp is the client stamp. It has the value + * of the server stamp when last checked. + */ + new_stamp = (drawable->texture_stamp != drawable->dPriv->lastStamp); + + if (new_stamp || new_mask) { + if (new_stamp && screen->update_drawable_info) + screen->update_drawable_info(drawable); + + screen->allocate_textures(drawable, statts, count); + + /* add existing textures */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->textures[i]) + statt_mask |= (1 << i); + } + + drawable->texture_stamp = drawable->dPriv->lastStamp; + drawable->texture_mask = statt_mask; + } + + if (!out) + return TRUE; + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], drawable->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +dri_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct dri_screen *screen = dri_screen(drawable->sPriv); + + /* XXX remove this and just set the correct one on the framebuffer */ + screen->flush_frontbuffer(drawable, statt); + + return TRUE; +} + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +boolean +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const __GLcontextModes * visual, boolean isPixmap) +{ + struct dri_screen *screen = sPriv->private; + struct dri_drawable *drawable = NULL; + + if (isPixmap) + goto fail; /* not implemented */ + + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto fail; + + dri_fill_st_visual(&drawable->stvis, screen, visual); + + /* setup the st_framebuffer_iface */ + drawable->base.visual = &drawable->stvis; + drawable->base.flush_front = dri_st_framebuffer_flush_front; + drawable->base.validate = dri_st_framebuffer_validate; + drawable->base.st_manager_private = (void *) drawable; + + drawable->sPriv = sPriv; + drawable->dPriv = dPriv; + dPriv->driverPrivate = (void *)drawable; + + drawable->desired_fences = 2; + + return GL_TRUE; +fail: + FREE(drawable); + return GL_FALSE; +} + +void +dri_destroy_buffer(__DRIdrawable * dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + int i; + + dri1_swap_fences_clear(drawable); + + dri1_destroy_pipe_surface(drawable); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + + drawable->desired_fences = 0; + + FREE(drawable); +} + +/** + * Validate the texture at an attachment. Allocate the texture if it does not + * exist. + */ +void +dri_drawable_validate_att(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned i, count = 0; + + /* check if buffer already exists */ + if (drawable->texture_mask & (1 << statt)) + return; + + /* make sure DRI2 does not destroy existing buffers */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->texture_mask & (1 << i)) { + statts[count++] = i; + } + } + statts[count++] = statt; + + drawable->texture_stamp = drawable->dPriv->lastStamp - 1; + + /* this calles into the manager */ + drawable->base.validate(&drawable->base, statts, count, NULL); +} + +/** + * Get the format and binding of an attachment. + */ +void +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind) +{ + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + *format = drawable->stvis.color_format; + *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + *format = drawable->stvis.depth_stencil_format; + *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + *format = PIPE_FORMAT_NONE; + *bind = 0; + break; + } +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h index 8bc59cb4c3d..5fd650ac88e 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.h +++ b/src/gallium/state_trackers/dri/common/dri_drawable.h @@ -29,6 +29,8 @@ #define DRI_DRAWABLE_H #include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "state_tracker/st_api.h" struct pipe_surface; struct pipe_fence_handle; @@ -40,30 +42,29 @@ struct dri_context; struct dri_drawable { + struct st_framebuffer_iface base; + struct st_visual stvis; + /* dri */ __DRIdrawable *dPriv; __DRIscreen *sPriv; - unsigned attachments[8]; - unsigned num_attachments; - - boolean is_pixmap; - __DRIbuffer old[8]; unsigned old_num; unsigned old_w; unsigned old_h; - /* gallium */ - struct st_framebuffer *stfb; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + unsigned int texture_mask, texture_stamp; + struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; unsigned int head; unsigned int tail; unsigned int desired_fences; unsigned int cur_fences; - enum pipe_format color_format; - enum pipe_format depth_stencil_format; + /* used only by DRI1 */ + struct pipe_surface *dri1_surface; }; static INLINE struct dri_drawable * @@ -80,35 +81,18 @@ dri_create_buffer(__DRIscreen * sPriv, __DRIdrawable * dPriv, const __GLcontextModes * visual, boolean isPixmap); -void -dri_update_buffer(struct pipe_screen *screen, void *context_private); - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); - -void dri_swap_buffers(__DRIdrawable * dPriv); - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); - -void dri_get_buffers(__DRIdrawable * dPriv); - void dri_destroy_buffer(__DRIdrawable * dPriv); -void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, - GLint glx_texture_format, __DRIdrawable *dPriv); - -void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, - __DRIdrawable *dPriv); - void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read); +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind); void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private); +dri_drawable_validate_att(struct dri_drawable *drawable, + enum st_attachment_type statt); + #endif /* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c new file mode 100644 index 00000000000..064c73f54c2 --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri_screen.c @@ -0,0 +1,410 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +#include "utils.h" +#ifndef __NOT_HAVE_DRM_H +#include "vblank.h" +#endif +#include "xmlpool.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri1_helper.h" +#ifndef __NOT_HAVE_DRM_H +#include "dri1.h" +#include "dri2.h" +#else +#include "drisw.h" +#endif + +#include "util/u_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_format.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ + +#include "util/u_debug.h" + +PUBLIC const char __driConfigOptions[] = + DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY +/* DRI_CONF_FORCE_S3TC_ENABLE(false) */ + DRI_CONF_ALLOW_LARGE_TEXTURES(1) + DRI_CONF_SECTION_END DRI_CONF_END; + +static const uint __driNConfigOptions = 3; + +static const __DRIconfig ** +dri_fill_in_modes(struct dri_screen *screen, + unsigned pixel_bits) +{ + __DRIconfig **configs = NULL; + __DRIconfig **configs_r5g6b5 = NULL; + __DRIconfig **configs_a8r8g8b8 = NULL; + __DRIconfig **configs_x8r8g8b8 = NULL; + unsigned num_modes; + uint8_t depth_bits_array[5]; + uint8_t stencil_bits_array[5]; + uint8_t msaa_samples_array[2]; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + unsigned msaa_samples_factor; + struct pipe_screen *p_screen = screen->base.screen; + boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8; + boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + depth_bits_array[0] = 0; + stencil_bits_array[0] = 0; + depth_buffer_factor = 1; + + pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_RENDER_TARGET, 0); + pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_RENDER_TARGET, 0); + pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_RENDER_TARGET, 0); + + /* We can only get a 16 or 32 bit depth buffer with getBuffersWithFormat */ + if (dri_with_format(screen->sPriv)) { + pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, + PIPE_TEXTURE_2D, + PIPE_BIND_DEPTH_STENCIL, 0); + } else { + pf_z16 = FALSE; + pf_z32 = FALSE; + } + + if (pf_z16) { + depth_bits_array[depth_buffer_factor] = 16; + stencil_bits_array[depth_buffer_factor++] = 0; + } + if (pf_x8z24 || pf_z24x8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 0; + screen->d_depth_bits_last = pf_x8z24; + } + if (pf_s8z24 || pf_z24s8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 8; + screen->sd_depth_bits_last = pf_s8z24; + } + if (pf_z32) { + depth_bits_array[depth_buffer_factor] = 32; + stencil_bits_array[depth_buffer_factor++] = 0; + } + + msaa_samples_array[0] = 0; + msaa_samples_array[1] = 4; + back_buffer_factor = 3; + msaa_samples_factor = 2; + + num_modes = + depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4; + + if (pf_r5g6b5) + configs_r5g6b5 = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + back_buffer_factor, + msaa_samples_array, msaa_samples_factor, + GL_TRUE); + + if (pf_a8r8g8b8) + configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + msaa_samples_array, + msaa_samples_factor, + GL_TRUE); + + if (pf_x8r8g8b8) + configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + msaa_samples_array, + msaa_samples_factor, + GL_TRUE); + + if (pixel_bits == 16) { + configs = configs_r5g6b5; + if (configs_a8r8g8b8) + configs = configs ? driConcatConfigs(configs, configs_a8r8g8b8) : configs_a8r8g8b8; + if (configs_x8r8g8b8) + configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; + } else { + configs = configs_a8r8g8b8; + if (configs_x8r8g8b8) + configs = configs ? driConcatConfigs(configs, configs_x8r8g8b8) : configs_x8r8g8b8; + if (configs_r5g6b5) + configs = configs ? driConcatConfigs(configs, configs_r5g6b5) : configs_r5g6b5; + } + + if (configs == NULL) { + debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); + return NULL; + } + + return (const __DRIconfig **)configs; +} + +/** + * Roughly the converse of dri_fill_in_modes. + */ +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode) +{ + memset(stvis, 0, sizeof(*stvis)); + + stvis->samples = mode->samples; + stvis->render_buffer = ST_ATTACHMENT_INVALID; + + if (mode->redBits == 8) { + if (mode->alphaBits == 8) + stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; + else + stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; + } + + switch (mode->depthBits) { + default: + case 0: + stvis->depth_stencil_format = PIPE_FORMAT_NONE; + break; + case 16: + stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (mode->stencilBits == 0) { + stvis->depth_stencil_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; + } else { + stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_Z24_UNORM_S8_USCALED: + PIPE_FORMAT_S8_USCALED_Z24_UNORM; + } + break; + case 32: + stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; + break; + } + + stvis->accum_format = (mode->haveAccumBuffer) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (mode->stereoMode) { + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + if (mode->haveDepthBuffer || mode->haveStencilBuffer) + stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + /* let the state tracker allocate the accum buffer */ +} + +#ifndef __NOT_HAVE_DRM_H + +/** + * Get information about previous buffer swaps. + */ +static int +dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo) +{ + if (dPriv == NULL || dPriv->driverPrivate == NULL || sInfo == NULL) + return -1; + else + return 0; +} + +#endif + +static boolean +dri_get_egl_image(struct st_manager *smapi, + struct st_egl_image *stimg) +{ + struct dri_context *ctx = + (struct dri_context *)stimg->stctxi->st_manager_private; + struct dri_screen *screen = dri_screen(ctx->sPriv); + __DRIimage *img = NULL; + + if (screen->lookup_egl_image) { + img = screen->lookup_egl_image(ctx, stimg->egl_image); + } + + if (!img) + return FALSE; + + stimg->texture = NULL; + pipe_resource_reference(&stimg->texture, img->texture); + stimg->face = img->face; + stimg->level = img->level; + stimg->zslice = img->zslice; + + return TRUE; +} + +static void +dri_destroy_option_cache(struct dri_screen * screen) +{ + int i; + + if (screen->optionCache.info) { + for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { + FREE(screen->optionCache.info[i].name); + FREE(screen->optionCache.info[i].ranges); + } + FREE(screen->optionCache.info); + } + + FREE(screen->optionCache.values); +} + +void +dri_destroy_screen_helper(struct dri_screen * screen) +{ + dri1_destroy_pipe_context(screen); + + if (screen->st_api && screen->st_api->destroy) + screen->st_api->destroy(screen->st_api); + + if (screen->base.screen) + screen->base.screen->destroy(screen->base.screen); + + dri_destroy_option_cache(screen); +} + +static void +dri_destroy_screen(__DRIscreen * sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + + dri_destroy_screen_helper(screen); + + FREE(screen); + sPriv->private = NULL; + sPriv->extensions = NULL; +} + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen, + unsigned pixel_bits) +{ + screen->base.screen = pscreen; + if (!screen->base.screen) { + debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); + return NULL; + } + + screen->base.get_egl_image = dri_get_egl_image; + screen->st_api = st_gl_api_create(); + + if (!screen->st_api) + return NULL; + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, __driNConfigOptions); + + return dri_fill_in_modes(screen, pixel_bits); +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec driDriverAPI = { + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + +#ifndef __NOT_HAVE_DRM_H + + .GetSwapInfo = dri_get_swap_info, + .GetDrawableMSC = driDrawableGetMSC32, + .WaitForMSC = driWaitForMSC32, + .InitScreen2 = dri2_init_screen, + + .InitScreen = dri1_init_screen, + .SwapBuffers = dri1_swap_buffers, + .CopySubBuffer = dri1_copy_sub_buffer, + +#else + + .InitScreen = drisw_init_screen, + .SwapBuffers = drisw_swap_buffers, + +#endif + +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_screen.h b/src/gallium/state_trackers/dri/common/dri_screen.h new file mode 100644 index 00000000000..1740fa8f426 --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri_screen.h @@ -0,0 +1,136 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +#ifndef DRI_SCREEN_H +#define DRI_SCREEN_H + +#include "dri_wrapper.h" +#include "xmlconfig.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/st_api.h" +#include "state_tracker/drm_api.h" + +struct dri_context; +struct dri_drawable; + +struct dri_screen +{ + /* st_api */ + struct st_manager base; + struct st_api *st_api; + + /* dri */ + __DRIscreen *sPriv; + + /** + * Configuration cache with default values for all contexts + */ + driOptionCache optionCache; + + /* drm */ + int fd; + drmLock *drmLock; + + /* hooks filled in by dri1, dri2 & drisw */ + __DRIimage * (*lookup_egl_image)(struct dri_context *ctx, void *handle); + void (*allocate_textures)(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count); + void (*update_drawable_info)(struct dri_drawable *drawable); + void (*flush_frontbuffer)(struct dri_drawable *drawable, + enum st_attachment_type statt); + + /* gallium */ + struct drm_api *api; + boolean d_depth_bits_last; + boolean sd_depth_bits_last; + boolean auto_fake_front; + + /* used only by DRI1 */ + struct pipe_context *dri1_pipe; +}; + +/** cast wrapper */ +static INLINE struct dri_screen * +dri_screen(__DRIscreen * sPriv) +{ + return (struct dri_screen *)sPriv->private; +} + +struct __DRIimageRec { + struct pipe_resource *texture; + unsigned face; + unsigned level; + unsigned zslice; + + void *loader_private; +}; + +#ifndef __NOT_HAVE_DRM_H + +static INLINE boolean +dri_with_format(__DRIscreen * sPriv) +{ + const __DRIdri2LoaderExtension *loader = sPriv->dri2.loader; + + return loader + && (loader->base.version >= 3) + && (loader->getBuffersWithFormat != NULL); +} + +#else + +static INLINE boolean +dri_with_format(__DRIscreen * sPriv) +{ + return TRUE; +} + +#endif + +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const __GLcontextModes *mode); + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen, + unsigned pixel_bits); + +void +dri_destroy_screen_helper(struct dri_screen * screen); + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_wrapper.h b/src/gallium/state_trackers/dri/common/dri_wrapper.h new file mode 100644 index 00000000000..141ba02706a --- /dev/null +++ b/src/gallium/state_trackers/dri/common/dri_wrapper.h @@ -0,0 +1,10 @@ +#ifndef DRI_WRAPPER_H +#define DRI_WRAPPER_H + +#ifndef __NOT_HAVE_DRM_H +#include "dri_util.h" +#else +#include "drisw_util.h" +#endif + +#endif diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c deleted file mode 100644 index 173f4041c8c..00000000000 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ /dev/null @@ -1,761 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell <[email protected]> - * Author: Jakob Bornecrantz <[email protected]> - */ - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" - -#include "pipe/p_context.h" -#include "pipe/p_screen.h" -#include "main/mtypes.h" -#include "main/renderbuffer.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_cb_fbo.h" - -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_rect.h" -#include "util/u_inlines.h" - -static struct pipe_surface * -dri_surface_from_handle(struct drm_api *api, - struct pipe_screen *screen, - unsigned handle, - enum pipe_format format, - unsigned width, unsigned height, unsigned pitch) -{ - struct pipe_surface *surface = NULL; - struct pipe_texture *texture = NULL; - struct pipe_texture templat; - - memset(&templat, 0, sizeof(templat)); - templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.target = PIPE_TEXTURE_2D; - templat.last_level = 0; - templat.depth0 = 1; - templat.format = format; - templat.width0 = width; - templat.height0 = height; - - texture = api->texture_from_shared_handle(api, screen, &templat, - "dri2 buffer", pitch, handle); - - if (!texture) { - debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__); - return NULL; - } - - surface = screen->get_tex_surface(screen, texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - /* we don't need the texture from this point on */ - pipe_texture_reference(&texture, NULL); - return surface; -} - -/** - * Pixmaps have will have the same name of fake front and front. - */ -static boolean -dri2_check_if_pixmap(__DRIbuffer *buffers, int count) -{ - boolean found = FALSE; - boolean is_pixmap = FALSE; - unsigned name; - int i; - - for (i = 0; i < count; i++) { - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - if (found) { - is_pixmap = buffers[i].name == name; - } else { - name = buffers[i].name; - found = TRUE; - } - default: - continue; - } - } - - return is_pixmap; -} - -/** - * This will be called a drawable is known to have been resized. - */ -void -dri_get_buffers(__DRIdrawable * dPriv) -{ - - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *surface = NULL; - struct dri_screen *st_screen = dri_screen(drawable->sPriv); - struct pipe_screen *screen = st_screen->pipe_screen; - __DRIbuffer *buffers = NULL; - __DRIscreen *dri_screen = drawable->sPriv; - __DRIdrawable *dri_drawable = drawable->dPriv; - struct drm_api *api = st_screen->api; - boolean have_depth = FALSE; - int i, count; - - if ((dri_screen->dri2.loader - && (dri_screen->dri2.loader->base.version > 2) - && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) { - buffers = (*dri_screen->dri2.loader->getBuffersWithFormat) - (dri_drawable, &dri_drawable->w, &dri_drawable->h, - drawable->attachments, drawable->num_attachments, - &count, dri_drawable->loaderPrivate); - } else { - assert(dri_screen->dri2.loader); - buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, - &dri_drawable->w, - &dri_drawable->h, - drawable->attachments, - drawable-> - num_attachments, &count, - dri_drawable-> - loaderPrivate); - } - - if (buffers == NULL) { - return; - } - - /* set one cliprect to cover the whole dri_drawable */ - dri_drawable->x = 0; - dri_drawable->y = 0; - dri_drawable->backX = 0; - dri_drawable->backY = 0; - dri_drawable->numClipRects = 1; - dri_drawable->pClipRects[0].x1 = 0; - dri_drawable->pClipRects[0].y1 = 0; - dri_drawable->pClipRects[0].x2 = dri_drawable->w; - dri_drawable->pClipRects[0].y2 = dri_drawable->h; - dri_drawable->numBackClipRects = 1; - dri_drawable->pBackClipRects[0].x1 = 0; - dri_drawable->pBackClipRects[0].y1 = 0; - dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; - dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; - - if (drawable->old_num == count && - drawable->old_w == dri_drawable->w && - drawable->old_h == dri_drawable->h && - memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) { - return; - } else { - drawable->old_num = count; - drawable->old_w = dri_drawable->w; - drawable->old_h = dri_drawable->h; - memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); - } - - drawable->is_pixmap = dri2_check_if_pixmap(buffers, count); - - for (i = 0; i < count; i++) { - enum pipe_format format = 0; - int index = 0; - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - if (!st_screen->auto_fake_front) - continue; - /* fallthrough */ - case __DRI_BUFFER_FAKE_FRONT_LEFT: - index = ST_SURFACE_FRONT_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_BACK_LEFT: - index = ST_SURFACE_BACK_LEFT; - format = drawable->color_format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - index = ST_SURFACE_DEPTH; - format = drawable->depth_stencil_format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - if (index == ST_SURFACE_DEPTH) { - if (have_depth) - continue; - else - have_depth = TRUE; - } - - surface = dri_surface_from_handle(api, - screen, - buffers[i].name, - format, - dri_drawable->w, - dri_drawable->h, buffers[i].pitch); - - switch (buffers[i].attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - case __DRI_BUFFER_BACK_LEFT: - drawable->color_format = surface->format; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - drawable->depth_stencil_format = surface->format; - break; - case __DRI_BUFFER_ACCUM: - default: - assert(0); - } - - st_set_framebuffer_surface(drawable->stfb, index, surface); - pipe_surface_reference(&surface, NULL); - } - /* this needed, or else the state tracker fails to pick the new buffers */ - st_resize_framebuffer(drawable->stfb, dri_drawable->w, dri_drawable->h); -} - -/** - * These are used for GLX_EXT_texture_from_pixmap - */ -void dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, - GLint format, __DRIdrawable *dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_surface *ps; - - if (!drawable->stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer) { - struct gl_renderbuffer *rb = - st_new_renderbuffer_fb(drawable->color_format, 0 /*XXX*/, FALSE); - _mesa_add_renderbuffer(&drawable->stfb->Base, BUFFER_FRONT_LEFT, rb); - } - - dri_get_buffers(drawable->dPriv); - st_get_framebuffer_surface(drawable->stfb, ST_SURFACE_FRONT_LEFT, &ps); - - if (!ps) - return; - - st_bind_texture_surface(ps, target == GL_TEXTURE_2D ? ST_TEXTURE_2D : - ST_TEXTURE_RECT, 0, drawable->color_format); -} - -void dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, - __DRIdrawable *dPriv) -{ - dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); -} - -void -dri_update_buffer(struct pipe_screen *screen, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - - if (ctx->d_stamp == *ctx->dPriv->pStamp && - ctx->r_stamp == *ctx->rPriv->pStamp) - return; - - ctx->d_stamp = *ctx->dPriv->pStamp; - ctx->r_stamp = *ctx->rPriv->pStamp; - - /* Ask the X server for new renderbuffers. */ - dri_get_buffers(ctx->dPriv); - if (ctx->dPriv != ctx->rPriv) - dri_get_buffers(ctx->rPriv); - -} - -void -dri_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct dri_drawable *drawable = dri_drawable(ctx->dPriv); - __DRIdrawable *dri_drawable = ctx->dPriv; - __DRIscreen *dri_screen = ctx->sPriv; - - /* XXX Does this function get called with DRI1? */ - - if (ctx->dPriv == NULL) { - debug_printf("%s: no drawable bound to context\n", __func__); - return; - } - -#if 0 - /* TODO if rendering to pixmaps is slow enable this code. */ - if (drawable->is_pixmap) - return; -#else - (void)drawable; -#endif - - (*dri_screen->dri2.loader->flushFrontBuffer)(dri_drawable, - dri_drawable->loaderPrivate); -} - -/** - * This is called when we need to set up GL rendering to a new X window. - */ -boolean -dri_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const __GLcontextModes * visual, boolean isPixmap) -{ - struct dri_screen *screen = sPriv->private; - struct dri_drawable *drawable = NULL; - int i; - - if (isPixmap) - goto fail; /* not implemented */ - - drawable = CALLOC_STRUCT(dri_drawable); - if (drawable == NULL) - goto fail; - - if (visual->redBits == 8) { - if (visual->alphaBits == 8) - drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; - else - drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; - } else { - drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM; - } - - switch(visual->depthBits) { - default: - case 0: - drawable->depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - drawable->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (visual->stencilBits == 0) { - drawable->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_Z24X8_UNORM: - PIPE_FORMAT_X8Z24_UNORM; - } else { - drawable->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_Z24S8_UNORM: - PIPE_FORMAT_S8Z24_UNORM; - } - break; - case 32: - drawable->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - drawable->stfb = st_create_framebuffer(visual, - drawable->color_format, - drawable->depth_stencil_format, - drawable->depth_stencil_format, - dPriv->w, - dPriv->h, (void *)drawable); - if (drawable->stfb == NULL) - goto fail; - - drawable->sPriv = sPriv; - drawable->dPriv = dPriv; - dPriv->driverPrivate = (void *)drawable; - - /* setup dri2 buffers information */ - /* TODO incase of double buffer visual, delay fake creation */ - i = 0; - if (sPriv->dri2.loader - && (sPriv->dri2.loader->base.version > 2) - && (sPriv->dri2.loader->getBuffersWithFormat != NULL)) { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - if (!screen->auto_fake_front) { - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->doubleBufferMode) { - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - drawable->attachments[i++] = visual->rgbBits; - } - if (visual->depthBits && visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - drawable->attachments[i++] = visual->depthBits + visual->stencilBits; - } else if (visual->depthBits) { - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - drawable->attachments[i++] = visual->depthBits; - } else if (visual->stencilBits) { - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->attachments[i++] = visual->stencilBits; - } - drawable->num_attachments = i / 2; - } else { - drawable->attachments[i++] = __DRI_BUFFER_FRONT_LEFT; - if (!screen->auto_fake_front) - drawable->attachments[i++] = __DRI_BUFFER_FAKE_FRONT_LEFT; - if (visual->doubleBufferMode) - drawable->attachments[i++] = __DRI_BUFFER_BACK_LEFT; - if (visual->depthBits && visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH_STENCIL; - else if (visual->depthBits) - drawable->attachments[i++] = __DRI_BUFFER_DEPTH; - else if (visual->stencilBits) - drawable->attachments[i++] = __DRI_BUFFER_STENCIL; - drawable->num_attachments = i; - } - - drawable->desired_fences = 2; - - return GL_TRUE; -fail: - FREE(drawable); - return GL_FALSE; -} - -static struct pipe_fence_handle * -dri_swap_fences_pop_front(struct dri_drawable *draw) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence = NULL; - - if (draw->cur_fences >= draw->desired_fences) { - screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); - screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); - --draw->cur_fences; - draw->tail &= DRI_SWAP_FENCES_MASK; - } - return fence; -} - -static void -dri_swap_fences_push_back(struct dri_drawable *draw, - struct pipe_fence_handle *fence) -{ - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - - if (!fence) - return; - - if (draw->cur_fences < DRI_SWAP_FENCES_MAX) { - draw->cur_fences++; - screen->fence_reference(screen, &draw->swap_fences[draw->head++], - fence); - draw->head &= DRI_SWAP_FENCES_MASK; - } -} - -void -dri_destroy_buffer(__DRIdrawable * dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_fence_handle *fence; - struct pipe_screen *screen = dri_screen(drawable->sPriv)->pipe_screen; - - st_unreference_framebuffer(drawable->stfb); - drawable->desired_fences = 0; - while (drawable->cur_fences) { - fence = dri_swap_fences_pop_front(drawable); - screen->fence_reference(screen, &fence, NULL); - } - - FREE(drawable); -} - -static void -dri1_update_drawables_locked(struct dri_context *ctx, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv) -{ - if (ctx->stLostLock) { - ctx->stLostLock = FALSE; - if (driDrawPriv == driReadPriv) - DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); - else - DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, - driReadPriv); - } -} - -/** - * This ensures all contexts which bind to a drawable pick up the - * drawable change and signal new buffer state. - * Calling st_resize_framebuffer for each context may seem like overkill, - * but no new buffers will actually be allocated if the dimensions don't - * change. - */ - -static void -dri1_propagate_drawable_change(struct dri_context *ctx) -{ - __DRIdrawable *dPriv = ctx->dPriv; - __DRIdrawable *rPriv = ctx->rPriv; - boolean flushed = FALSE; - - if (dPriv && ctx->d_stamp != dPriv->lastStamp) { - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - flushed = TRUE; - ctx->d_stamp = dPriv->lastStamp; - st_resize_framebuffer(dri_drawable(dPriv)->stfb, dPriv->w, dPriv->h); - - } - - if (rPriv && dPriv != rPriv && ctx->r_stamp != rPriv->lastStamp) { - - if (!flushed) - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - ctx->r_stamp = rPriv->lastStamp; - st_resize_framebuffer(dri_drawable(rPriv)->stfb, rPriv->w, rPriv->h); - - } else if (rPriv && dPriv == rPriv) { - - ctx->r_stamp = ctx->d_stamp; - - } -} - -void -dri1_update_drawables(struct dri_context *ctx, - struct dri_drawable *draw, struct dri_drawable *read) -{ - dri_lock(ctx); - dri1_update_drawables_locked(ctx, draw->dPriv, read->dPriv); - dri_unlock(ctx); - - dri1_propagate_drawable_change(ctx); -} - -static INLINE boolean -dri1_intersect_src_bbox(struct drm_clip_rect *dst, - int dst_x, - int dst_y, - const struct drm_clip_rect *src, - const struct drm_clip_rect *bbox) -{ - int xy1; - int xy2; - - xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : - (int)bbox->x1 + dst_x; - xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : - (int)bbox->x2 + dst_x; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->x1 = xy1; - dst->x2 = xy2; - - xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : - (int)bbox->y1 + dst_y; - xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : - (int)bbox->y2 + dst_y; - if (xy1 >= xy2 || xy1 < 0) - return FALSE; - - dst->y1 = xy1; - dst->y2 = xy2; - return TRUE; -} - -static void -dri1_swap_copy(struct dri_context *ctx, - struct pipe_surface *dst, - struct pipe_surface *src, - __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) -{ - struct pipe_context *pipe = ctx->pipe; - struct drm_clip_rect clip; - struct drm_clip_rect *cur; - int i; - - cur = dPriv->pClipRects; - - for (i = 0; i < dPriv->numClipRects; ++i) { - if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { - if (pipe->surface_copy) { - pipe->surface_copy(pipe, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } else { - util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, - src, - (int)clip.x1 - dPriv->x, - (int)clip.y1 - dPriv->y, - clip.x2 - clip.x1, clip.y2 - clip.y1); - } - } - } -} - -static void -dri1_copy_to_front(struct dri_context *ctx, - struct pipe_surface *surf, - __DRIdrawable * dPriv, - const struct drm_clip_rect *sub_box, - struct pipe_fence_handle **fence) -{ - struct pipe_context *pipe = ctx->pipe; - boolean save_lost_lock; - uint cur_w; - uint cur_h; - struct drm_clip_rect bbox; - boolean visible = TRUE; - - *fence = NULL; - - dri_lock(ctx); - save_lost_lock = ctx->stLostLock; - dri1_update_drawables_locked(ctx, dPriv, dPriv); - st_get_framebuffer_dimensions(dri_drawable(dPriv)->stfb, &cur_w, &cur_h); - - bbox.x1 = 0; - bbox.x2 = cur_w; - bbox.y1 = 0; - bbox.y2 = cur_h; - - if (sub_box) - visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); - - if (visible && __dri1_api_hooks->present_locked) { - - __dri1_api_hooks->present_locked(pipe, - surf, - dPriv->pClipRects, - dPriv->numClipRects, - dPriv->x, dPriv->y, &bbox, fence); - - } else if (visible && __dri1_api_hooks->front_srf_locked) { - - struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); - - if (front) - dri1_swap_copy(ctx, front, surf, dPriv, &bbox); - - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, fence); - } - - ctx->stLostLock = save_lost_lock; - - /** - * FIXME: Revisit this: Update drawables on copy_sub_buffer ? - */ - - if (!sub_box) - dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); - - dri_unlock(ctx); - dri1_propagate_drawable_change(ctx); -} - -void -dri1_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) -{ - struct dri_context *ctx = (struct dri_context *)context_private; - struct pipe_fence_handle *dummy_fence; - - dri1_copy_to_front(ctx, surf, ctx->dPriv, NULL, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); - - /** - * FIXME: Do we need swap throttling here? - */ -} - -void -dri_swap_buffers(__DRIdrawable * dPriv) -{ - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_screen *screen = dri_screen(draw->sPriv)->pipe_screen; - struct pipe_fence_handle *fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; /* For now */ - - ctx = (struct dri_context *)st->pipe->priv; - - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_notify_swapbuffers(draw->stfb); - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - fence = dri_swap_fences_pop_front(draw); - if (fence) { - (void)screen->fence_finish(screen, fence, 0); - screen->fence_reference(screen, &fence, NULL); - } - dri1_copy_to_front(ctx, back_surf, dPriv, NULL, &fence); - dri_swap_fences_push_back(draw, fence); - screen->fence_reference(screen, &fence, NULL); - } -} - -void -dri_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) -{ - struct pipe_screen *screen = dri_screen(dPriv->driScreenPriv)->pipe_screen; - struct drm_clip_rect sub_bbox; - struct dri_context *ctx; - struct pipe_surface *back_surf; - struct dri_drawable *draw = dri_drawable(dPriv); - struct pipe_fence_handle *dummy_fence; - struct st_context *st = st_get_current(); - - assert(__dri1_api_hooks != NULL); - - if (!st) - return; - - ctx = (struct dri_context *)st->pipe->priv; - - sub_bbox.x1 = x; - sub_bbox.x2 = x + w; - sub_bbox.y1 = y; - sub_bbox.y2 = y + h; - - st_get_framebuffer_surface(draw->stfb, ST_SURFACE_BACK_LEFT, &back_surf); - if (back_surf) { - st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); - dri1_copy_to_front(ctx, back_surf, dPriv, &sub_bbox, &dummy_fence); - screen->fence_reference(screen, &dummy_fence, NULL); - } -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_extensions.c b/src/gallium/state_trackers/dri/dri_extensions.c deleted file mode 100644 index 1259813a412..00000000000 --- a/src/gallium/state_trackers/dri/dri_extensions.c +++ /dev/null @@ -1,142 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell <[email protected]> - * Author: Jakob Bornecrantz <[email protected]> - */ - -#include "dri_screen.h" -#include "dri_context.h" -#include "state_tracker/st_context.h" - -#define need_GL_ARB_map_buffer_range -#define need_GL_ARB_multisample -#define need_GL_ARB_occlusion_query -#define need_GL_ARB_point_parameters -#define need_GL_ARB_provoking_vertex -#define need_GL_ARB_shader_objects -#define need_GL_ARB_texture_compression -#define need_GL_ARB_vertex_array_object -#define need_GL_ARB_vertex_buffer_object -#define need_GL_ARB_vertex_program -#define need_GL_ARB_vertex_shader -#define need_GL_ARB_window_pos -#define need_GL_EXT_blend_color -#define need_GL_EXT_blend_equation_separate -#define need_GL_EXT_blend_func_separate -#define need_GL_EXT_blend_minmax -#define need_GL_EXT_cull_vertex -#define need_GL_EXT_draw_buffers2 -#define need_GL_EXT_fog_coord -#define need_GL_EXT_framebuffer_object -#define need_GL_EXT_multi_draw_arrays -#define need_GL_EXT_provoking_vertex -#define need_GL_EXT_secondary_color -#define need_GL_EXT_stencil_two_side -#define need_GL_APPLE_vertex_array_object -#define need_GL_NV_vertex_program -#define need_GL_VERSION_2_0 -#define need_GL_VERSION_2_1 -#include "main/remap_helper.h" -#include "utils.h" - -/** - * Extension strings exported by the driver. - */ -static const struct dri_extension card_extensions[] = { - {"GL_ARB_fragment_shader", NULL}, - {"GL_ARB_map_buffer_range", GL_ARB_map_buffer_range_functions}, - {"GL_ARB_multisample", GL_ARB_multisample_functions}, - {"GL_ARB_multitexture", NULL}, - {"GL_ARB_occlusion_query", GL_ARB_occlusion_query_functions}, - {"GL_ARB_pixel_buffer_object", NULL}, - {"GL_ARB_provoking_vertex", GL_ARB_provoking_vertex_functions}, - {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, - {"GL_ARB_shading_language_100", GL_VERSION_2_0_functions }, - {"GL_ARB_shading_language_120", GL_VERSION_2_1_functions }, - {"GL_ARB_shader_objects", GL_ARB_shader_objects_functions}, - {"GL_ARB_texture_border_clamp", NULL}, - {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, - {"GL_ARB_texture_cube_map", NULL}, - {"GL_ARB_texture_env_add", NULL}, - {"GL_ARB_texture_env_combine", NULL}, - {"GL_ARB_texture_env_dot3", NULL}, - {"GL_ARB_texture_mirrored_repeat", NULL}, - {"GL_ARB_texture_non_power_of_two", NULL}, - {"GL_ARB_texture_rectangle", NULL}, - {"GL_ARB_vertex_array_object", GL_ARB_vertex_array_object_functions}, - {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, - {"GL_ARB_vertex_shader", GL_ARB_vertex_shader_functions}, - {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, - {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, - {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, - {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, - {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, - {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, - {"GL_EXT_blend_subtract", NULL}, - {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, - {"GL_EXT_draw_buffers2", GL_EXT_draw_buffers2_functions}, - {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, - {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, - {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, - {"GL_EXT_packed_depth_stencil", NULL}, - {"GL_EXT_pixel_buffer_object", NULL}, - {"GL_EXT_provoking_vertex", GL_EXT_provoking_vertex_functions}, - {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, - {"GL_EXT_stencil_two_side", GL_EXT_stencil_two_side_functions}, - {"GL_EXT_stencil_wrap", NULL}, - {"GL_EXT_texture_edge_clamp", NULL}, - {"GL_EXT_texture_env_combine", NULL}, - {"GL_EXT_texture_env_dot3", NULL}, - {"GL_EXT_texture_filter_anisotropic", NULL}, - {"GL_EXT_texture_lod_bias", NULL}, - {"GL_3DFX_texture_compression_FXT1", NULL}, - {"GL_APPLE_client_storage", NULL}, - {"GL_APPLE_vertex_array_object", GL_APPLE_vertex_array_object_functions}, - {"GL_MESA_pack_invert", NULL}, - {"GL_MESA_ycbcr_texture", NULL}, - {"GL_NV_blend_square", NULL}, - {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, - {"GL_NV_vertex_program1_1", NULL}, - {"GL_SGIS_generate_mipmap", NULL}, - {NULL, NULL} -}; - -void -dri_init_extensions(struct dri_context *ctx) -{ - /* The card_extensions list should be pruned according to the - * capabilities of the pipe_screen. This is actually something - * that can/should be done inside st_create_context(). - * XXX Not pruning is very bogus. Always all these extensions above - * will be advertized, regardless what st_init_extensions - * (which depends on the pipe cap bits) does. - */ - driInitExtensions(ctx->st->ctx, card_extensions, GL_TRUE); -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c deleted file mode 100644 index 60bc560049c..00000000000 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ /dev/null @@ -1,400 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell <[email protected]> - * Author: Jakob Bornecrantz <[email protected]> - */ - -#include "utils.h" -#include "vblank.h" -#include "xmlpool.h" - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" - -#include "pipe/p_screen.h" -#include "pipe/p_format.h" -#include "state_tracker/drm_api.h" -#include "state_tracker/dri1_api.h" - -#include "util/u_debug.h" - -PUBLIC const char __driConfigOptions[] = - DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE - DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) - DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) - DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY - /*DRI_CONF_FORCE_S3TC_ENABLE(false) */ - DRI_CONF_ALLOW_LARGE_TEXTURES(1) - DRI_CONF_SECTION_END DRI_CONF_END; - - const uint __driNConfigOptions = 3; - -static const __DRItexBufferExtension dri2TexBufferExtension = { - { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, - dri2_set_tex_buffer, - dri2_set_tex_buffer2, -}; - -static void -dri2_flush_drawable(__DRIdrawable *draw) -{ -} - -static const __DRI2flushExtension dri2FlushExtension = { - { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, - dri2_flush_drawable, - dri2InvalidateDrawable, -}; - - static const __DRIextension *dri_screen_extensions[] = { - &driReadDrawableExtension, - &driCopySubBufferExtension.base, - &driSwapControlExtension.base, - &driFrameTrackingExtension.base, - &driMediaStreamCounterExtension.base, - &dri2TexBufferExtension.base, - &dri2FlushExtension.base, - NULL - }; - -struct dri1_api *__dri1_api_hooks = NULL; - -static const __DRIconfig ** -dri_fill_in_modes(struct dri_screen *screen, - unsigned pixel_bits) -{ - __DRIconfig **configs = NULL; - unsigned num_modes; - uint8_t depth_bits_array[5]; - uint8_t stencil_bits_array[5]; - uint8_t msaa_samples_array[2]; - unsigned depth_buffer_factor; - unsigned back_buffer_factor; - unsigned msaa_samples_factor; - struct pipe_screen *p_screen = screen->pipe_screen; - boolean pf_r5g6b5, pf_a8r8g8b8, pf_x8r8g8b8; - boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; - - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML - }; - - depth_bits_array[0] = 0; - stencil_bits_array[0] = 0; - depth_buffer_factor = 1; - - pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); - pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); - - /* we support buffers with different depths only if we can tell the driver - * the actual depth of each of them. */ - if (screen->sPriv->dri2.loader - && (screen->sPriv->dri2.loader->base.version > 2) - && (screen->sPriv->dri2.loader->getBuffersWithFormat != NULL)) { - pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM, - PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); - } else { - pf_z16 = FALSE; - pf_z32 = FALSE; - pf_r5g6b5 = FALSE; - } - - if (pf_z16) { - depth_bits_array[depth_buffer_factor] = 16; - stencil_bits_array[depth_buffer_factor++] = 0; - } - if (pf_x8z24 || pf_z24x8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 0; - screen->d_depth_bits_last = pf_x8z24; - } - if (pf_s8z24 || pf_z24s8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 8; - screen->sd_depth_bits_last = pf_s8z24; - } - if (pf_z32) { - depth_bits_array[depth_buffer_factor] = 32; - stencil_bits_array[depth_buffer_factor++] = 0; - } - - msaa_samples_array[0] = 0; - msaa_samples_array[1] = 4; - back_buffer_factor = 3; - msaa_samples_factor = 2; - - num_modes = - depth_buffer_factor * back_buffer_factor * msaa_samples_factor * 4; - - if (pixel_bits == 16 && pf_r5g6b5) { - configs = driCreateConfigs(GL_RGB, GL_UNSIGNED_SHORT_5_6_5, - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - back_buffer_factor, - msaa_samples_array, msaa_samples_factor, - GL_TRUE); - } else { - __DRIconfig **configs_a8r8g8b8 = NULL; - __DRIconfig **configs_x8r8g8b8 = NULL; - - if (pf_a8r8g8b8) - configs_a8r8g8b8 = driCreateConfigs(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, - depth_bits_array, - stencil_bits_array, - depth_buffer_factor, - back_buffer_modes, - back_buffer_factor, - msaa_samples_array, - msaa_samples_factor, - GL_TRUE); - if (pf_x8r8g8b8) - configs_x8r8g8b8 = driCreateConfigs(GL_BGR, GL_UNSIGNED_INT_8_8_8_8_REV, - depth_bits_array, - stencil_bits_array, - depth_buffer_factor, - back_buffer_modes, - back_buffer_factor, - msaa_samples_array, - msaa_samples_factor, - GL_TRUE); - - if (configs_a8r8g8b8 && configs_x8r8g8b8) - configs = driConcatConfigs(configs_x8r8g8b8, configs_a8r8g8b8); - else if (configs_a8r8g8b8) - configs = configs_a8r8g8b8; - else if (configs_x8r8g8b8) - configs = configs_x8r8g8b8; - else - configs = NULL; - } - - if (configs == NULL) { - debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); - return NULL; - } - - return (const __DRIconfig **)configs; -} - -/** - * Get information about previous buffer swaps. - */ -static int -dri_get_swap_info(__DRIdrawable * dPriv, __DRIswapInfo * sInfo) -{ - if (dPriv == NULL || dPriv->driverPrivate == NULL || sInfo == NULL) - return -1; - else - return 0; -} - -static INLINE void -dri_copy_version(struct dri1_api_version *dst, - const struct __DRIversionRec *src) -{ - dst->major = src->major; - dst->minor = src->minor; - dst->patch_level = src->patch; -} - -static const __DRIconfig ** -dri_init_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen; - const __DRIconfig **configs; - struct dri1_create_screen_arg arg; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->api = drm_api_create(); - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; - - sPriv->private = (void *)screen; - sPriv->extensions = dri_screen_extensions; - - arg.base.mode = DRM_CREATE_DRI1; - arg.lf = &dri1_lf; - arg.ddx_info = sPriv->pDevPriv; - arg.ddx_info_size = sPriv->devPrivSize; - arg.sarea = sPriv->pSAREA; - dri_copy_version(&arg.ddx_version, &sPriv->ddx_version); - dri_copy_version(&arg.dri_version, &sPriv->dri_version); - dri_copy_version(&arg.drm_version, &sPriv->drm_version); - arg.api = NULL; - - screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg.base); - - if (!screen->pipe_screen || !arg.api) { - debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); - goto out_no_screen; - } - - __dri1_api_hooks = arg.api; - - screen->pipe_screen->flush_frontbuffer = dri1_flush_frontbuffer; - driParseOptionInfo(&screen->optionCache, - __driConfigOptions, __driNConfigOptions); - - /** - * FIXME: If the driver supports format conversion swapbuffer blits, we might - * want to support other color bit depths than the server is currently - * using. - */ - - configs = dri_fill_in_modes(screen, sPriv->fbBPP); - if (!configs) - goto out_no_configs; - - return configs; - out_no_configs: - screen->pipe_screen->destroy(screen->pipe_screen); - out_no_screen: - FREE(screen); - return NULL; -} - -/** - * This is the driver specific part of the createNewScreen entry point. - * - * Returns the __GLcontextModes supported by this driver. - */ -static const __DRIconfig ** -dri_init_screen2(__DRIscreen * sPriv) -{ - struct dri_screen *screen; - struct drm_create_screen_arg arg; - const __DRIdri2LoaderExtension *dri2_ext = - sPriv->dri2.loader; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - goto fail; - - screen->api = drm_api_create(); - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - sPriv->private = (void *)screen; - sPriv->extensions = dri_screen_extensions; - arg.mode = DRM_CREATE_NORMAL; - - screen->pipe_screen = screen->api->create_screen(screen->api, screen->fd, &arg); - if (!screen->pipe_screen) { - debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); - goto fail; - } - - /* We need to hook in here */ - screen->pipe_screen->update_buffer = dri_update_buffer; - screen->pipe_screen->flush_frontbuffer = dri_flush_frontbuffer; - - driParseOptionInfo(&screen->optionCache, - __driConfigOptions, __driNConfigOptions); - - screen->auto_fake_front = dri2_ext->base.version >= 3 && - dri2_ext->getBuffersWithFormat != NULL; - - return dri_fill_in_modes(screen, 32); - fail: - return NULL; -} - -static void -dri_destroy_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - int i; - - screen->pipe_screen->destroy(screen->pipe_screen); - - for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { - FREE(screen->optionCache.info[i].name); - FREE(screen->optionCache.info[i].ranges); - } - - FREE(screen->optionCache.info); - FREE(screen->optionCache.values); - - FREE(screen); - sPriv->private = NULL; -} - -PUBLIC const struct __DriverAPIRec driDriverAPI = { - .InitScreen = dri_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = dri_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .SwapBuffers = dri_swap_buffers, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - .GetSwapInfo = dri_get_swap_info, - .GetDrawableMSC = driDrawableGetMSC32, - .WaitForMSC = driWaitForMSC32, - .CopySubBuffer = dri_copy_sub_buffer, - .InitScreen = dri_init_screen, - .InitScreen2 = dri_init_screen2, -}; - -/* This is the table of extensions that the loader will dlsym() for. */ -PUBLIC const __DRIextension *__driDriverExtensions[] = { - &driCoreExtension.base, - &driLegacyExtension.base, - &driDRI2Extension.base, - NULL -}; - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drm/Makefile b/src/gallium/state_trackers/dri/drm/Makefile new file mode 100644 index 00000000000..d9a973e3c3e --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/Makefile @@ -0,0 +1,31 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = dridrm + +LIBRARY_INCLUDES = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/gallium/state_trackers/dri/common \ + -I$(TOP)/src/mesa/drivers/dri/common \ + -I$(TOP)/src/mesa/main \ + $(shell pkg-config --cflags-only-I libdrm) + + +C_SOURCES = \ + dri_context.c \ + dri_screen.c \ + dri_drawable.c \ + dri1_helper.c \ + dri1.c \ + dri2.c + +# $(TOP)/src/mesa/drivers/dri/common/utils.c \ + $(TOP)/src/mesa/drivers/dri/common/vblank.c \ + $(TOP)/src/mesa/drivers/dri/common/dri_util.c \ + $(TOP)/src/mesa/drivers/dri/common/xmlconfig.c \ + $(TOP)/src/mesa/drivers/common/driverfuncs.c \ + $(TOP)/src/mesa/drivers/dri/common/texmem.c \ + $(TOP)/src/mesa/drivers/dri/common/drirenderbuffer.c + +include ../../../Makefile.template diff --git a/src/gallium/state_trackers/dri/drm/SConscript b/src/gallium/state_trackers/dri/drm/SConscript new file mode 100644 index 00000000000..8800b655343 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/SConscript @@ -0,0 +1,28 @@ +####################################################################### +# SConscript for dri state_tracker + +Import('*') + +if env['dri']: + + env = env.Clone() + + env.ParseConfig('pkg-config --cflags --libs libdrm') + + env.Append(CPPPATH = [ + '#/src/mesa', + '#/src/gallium/state_trackers/dri/common', + '#/src/mesa/drivers/dri/common', + ]) + + st_dri = env.ConvenienceLibrary( + target = 'st_dri', + source = [ 'dri_context.c', + 'dri_drawable.c', + 'dri_screen.c', + 'dri1_helper.c', + 'dri1.c', + 'dri2.c', + ] + ) + Export('st_dri') diff --git a/src/gallium/state_trackers/dri/drm/dri1.c b/src/gallium/state_trackers/dri/drm/dri1.c new file mode 100644 index 00000000000..23c21ed8398 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri1.c @@ -0,0 +1,520 @@ +/************************************************************************** + * + * Copyright 2009, 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, 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell <[email protected]> + * Author: Jakob Bornecrantz <[email protected]> + */ + +/* XXX DRI1 is untested after the switch to st_api.h */ + +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "state_tracker/dri1_api.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri1_helper.h" +#include "dri1.h" + +static INLINE void +dri1_lock(struct dri_context *ctx) +{ + drm_context_t hw_context = ctx->cPriv->hHWContext; + char ret = 0; + + DRM_CAS(ctx->lock, hw_context, DRM_LOCK_HELD | hw_context, ret); + if (ret) { + drmGetLock(ctx->sPriv->fd, hw_context, 0); + ctx->stLostLock = TRUE; + ctx->wsLostLock = TRUE; + } + ctx->isLocked = TRUE; +} + +static INLINE void +dri1_unlock(struct dri_context *ctx) +{ + ctx->isLocked = FALSE; + DRM_UNLOCK(ctx->sPriv->fd, ctx->lock, ctx->cPriv->hHWContext); +} + +static void +dri1_update_drawables_locked(struct dri_context *ctx, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) +{ + if (ctx->stLostLock) { + ctx->stLostLock = FALSE; + if (driDrawPriv == driReadPriv) + DRI_VALIDATE_DRAWABLE_INFO(ctx->sPriv, driDrawPriv); + else + DRI_VALIDATE_TWO_DRAWABLES_INFO(ctx->sPriv, driDrawPriv, + driReadPriv); + } +} + +/** + * This ensures all contexts which bind to a drawable pick up the + * drawable change and signal new buffer state. + */ +static void +dri1_propagate_drawable_change(struct dri_context *ctx) +{ + __DRIdrawable *dPriv = ctx->dPriv; + __DRIdrawable *rPriv = ctx->rPriv; + struct dri_drawable *draw; + struct dri_drawable *read; + boolean flushed = FALSE; + + if (dPriv) { + draw = dri_drawable(dPriv); + } + + if (rPriv) { + read = dri_drawable(rPriv); + } + + if (dPriv && draw->texture_stamp != dPriv->lastStamp) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + flushed = TRUE; + ctx->st->notify_invalid_framebuffer(ctx->st, &draw->base); + } + + if (rPriv && dPriv != rPriv && read->texture_stamp != rPriv->lastStamp) { + if (!flushed) + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + ctx->st->notify_invalid_framebuffer(ctx->st, &read->base); + } +} + +static INLINE boolean +dri1_intersect_src_bbox(struct drm_clip_rect *dst, + int dst_x, + int dst_y, + const struct drm_clip_rect *src, + const struct drm_clip_rect *bbox) +{ + int xy1; + int xy2; + + xy1 = ((int)src->x1 > (int)bbox->x1 + dst_x) ? src->x1 : + (int)bbox->x1 + dst_x; + xy2 = ((int)src->x2 < (int)bbox->x2 + dst_x) ? src->x2 : + (int)bbox->x2 + dst_x; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->x1 = xy1; + dst->x2 = xy2; + + xy1 = ((int)src->y1 > (int)bbox->y1 + dst_y) ? src->y1 : + (int)bbox->y1 + dst_y; + xy2 = ((int)src->y2 < (int)bbox->y2 + dst_y) ? src->y2 : + (int)bbox->y2 + dst_y; + if (xy1 >= xy2 || xy1 < 0) + return FALSE; + + dst->y1 = xy1; + dst->y2 = xy2; + return TRUE; +} + +static void +dri1_swap_copy(struct pipe_context *pipe, + struct pipe_surface *dst, + struct pipe_surface *src, + __DRIdrawable * dPriv, const struct drm_clip_rect *bbox) +{ + struct drm_clip_rect clip; + struct drm_clip_rect *cur; + int i; + + cur = dPriv->pClipRects; + + for (i = 0; i < dPriv->numClipRects; ++i) { + if (dri1_intersect_src_bbox(&clip, dPriv->x, dPriv->y, cur++, bbox)) { + if (pipe->surface_copy) { + pipe->surface_copy(pipe, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } else { + util_surface_copy(pipe, FALSE, dst, clip.x1, clip.y1, + src, + (int)clip.x1 - dPriv->x, + (int)clip.y1 - dPriv->y, + clip.x2 - clip.x1, clip.y2 - clip.y1); + } + } + } +} + +static void +dri1_present_texture_locked(__DRIdrawable * dPriv, + struct pipe_resource *ptex, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_context *pipe; + struct pipe_surface *psurf; + struct drm_clip_rect bbox; + boolean visible = TRUE; + + *fence = NULL; + + bbox.x1 = 0; + bbox.x2 = ptex->width0; + bbox.y1 = 0; + bbox.y2 = ptex->height0; + + if (sub_box) + visible = dri1_intersect_src_bbox(&bbox, 0, 0, &bbox, sub_box); + if (!visible) + return; + + pipe = dri1_get_pipe_context(screen); + psurf = dri1_get_pipe_surface(drawable, ptex); + if (!pipe || !psurf) + return; + + if (__dri1_api_hooks->present_locked) { + __dri1_api_hooks->present_locked(pipe, psurf, + dPriv->pClipRects, dPriv->numClipRects, + dPriv->x, dPriv->y, &bbox, fence); + } else if (__dri1_api_hooks->front_srf_locked) { + struct pipe_surface *front = __dri1_api_hooks->front_srf_locked(pipe); + + if (front) + dri1_swap_copy(pipe, front, psurf, dPriv, &bbox); + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, fence); + } +} + +static void +dri1_copy_to_front(struct dri_context *ctx, + struct pipe_resource *ptex, + __DRIdrawable * dPriv, + const struct drm_clip_rect *sub_box, + struct pipe_fence_handle **fence) +{ + boolean save_lost_lock; + + dri1_lock(ctx); + save_lost_lock = ctx->stLostLock; + dri1_update_drawables_locked(ctx, dPriv, dPriv); + + dri1_present_texture_locked(dPriv, ptex, sub_box, fence); + + ctx->stLostLock = save_lost_lock; + + /** + * FIXME: Revisit this: Update drawables on copy_sub_buffer ? + */ + + if (!sub_box) + dri1_update_drawables_locked(ctx, ctx->dPriv, ctx->rPriv); + + dri1_unlock(ctx); + dri1_propagate_drawable_change(ctx); +} + +/* + * Backend functions for st_framebuffer interface and swap_buffers. + */ + +static void +dri1_flush_frontbuffer(struct dri_drawable *draw, + enum st_attachment_type statt) +{ + struct dri_context *ctx = dri_get_current(draw->sPriv); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->base.screen; + struct pipe_fence_handle *dummy_fence; + struct pipe_resource *ptex; + + if (!ctx) + return; /* For now */ + + ptex = draw->textures[statt]; + if (ptex) { + dri1_copy_to_front(ctx, ptex, ctx->dPriv, NULL, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + } + + /** + * FIXME: Do we need swap throttling here? + */ +} + +void +dri1_swap_buffers(__DRIdrawable * dPriv) +{ + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_context *ctx = dri_get_current(draw->sPriv); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->base.screen; + struct pipe_fence_handle *fence; + struct pipe_resource *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; /* For now */ + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + fence = dri1_swap_fences_pop_front(draw); + if (fence) { + (void)pipe_screen->fence_finish(pipe_screen, fence, 0); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } + dri1_copy_to_front(ctx, ptex, dPriv, NULL, &fence); + dri1_swap_fences_push_back(draw, fence); + pipe_screen->fence_reference(pipe_screen, &fence, NULL); + } +} + +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct pipe_screen *pipe_screen = screen->base.screen; + struct drm_clip_rect sub_bbox; + struct dri_drawable *draw = dri_drawable(dPriv); + struct pipe_fence_handle *dummy_fence; + struct pipe_resource *ptex; + + assert(__dri1_api_hooks != NULL); + + if (!ctx) + return; + + sub_bbox.x1 = x; + sub_bbox.x2 = x + w; + sub_bbox.y1 = y; + sub_bbox.y2 = y + h; + + ptex = draw->textures[ST_ATTACHMENT_BACK_LEFT]; + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + dri1_copy_to_front(ctx, ptex, dPriv, &sub_bbox, &dummy_fence); + pipe_screen->fence_reference(pipe_screen, &dummy_fence, NULL); + } +} + +/** + * Allocate framebuffer attachments. + * + * During fixed-size operation, the function keeps allocating new attachments + * as they are requested. Unused attachments are not removed, not until the + * framebuffer is resized or destroyed. + */ +static void +dri1_allocate_textures(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_resource templ; + unsigned width, height; + boolean resized; + int i; + + width = drawable->dPriv->w; + height = drawable->dPriv->h; + + resized = (drawable->old_w != width || + drawable->old_h != height); + + /* remove outdated textures */ + if (resized) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < count; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists */ + if (drawable->textures[statts[i]]) + continue; + + dri_drawable_get_format(drawable, statts[i], &format, &bind); + + if (format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + + drawable->textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + } + + drawable->old_w = width; + drawable->old_h = height; +} + +/* + * Backend function for init_screen. + */ + +static const __DRIextension *dri1_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + +static void +st_dri_lock(struct pipe_context *pipe) +{ + dri1_lock((struct dri_context *)pipe->priv); +} + +static void +st_dri_unlock(struct pipe_context *pipe) +{ + dri1_unlock((struct dri_context *)pipe->priv); +} + +static boolean +st_dri_is_locked(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->isLocked; +} + +static boolean +st_dri_lost_lock(struct pipe_context *pipe) +{ + return ((struct dri_context *)pipe->priv)->wsLostLock; +} + +static void +st_dri_clear_lost_lock(struct pipe_context *pipe) +{ + ((struct dri_context *)pipe->priv)->wsLostLock = FALSE; +} + +static struct dri1_api_lock_funcs dri1_lf = { + .lock = st_dri_lock, + .unlock = st_dri_unlock, + .is_locked = st_dri_is_locked, + .is_lock_lost = st_dri_lost_lock, + .clear_lost_lock = st_dri_clear_lost_lock +}; + +static INLINE void +dri1_copy_version(struct dri1_api_version *dst, + const struct __DRIversionRec *src) +{ + dst->major = src->major; + dst->minor = src->minor; + dst->patch_level = src->patch; +} + +struct dri1_api *__dri1_api_hooks = NULL; + +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct pipe_screen *pscreen; + struct dri_screen *screen; + struct dri1_create_screen_arg arg; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->api = drm_api_create(); + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + screen->drmLock = (drmLock *) & sPriv->pSAREA->lock; + screen->allocate_textures = dri1_allocate_textures; + screen->flush_frontbuffer = dri1_flush_frontbuffer; + + sPriv->private = (void *)screen; + sPriv->extensions = dri1_screen_extensions; + + arg.base.mode = DRM_CREATE_DRI1; + arg.lf = &dri1_lf; + arg.ddx_info = sPriv->pDevPriv; + arg.ddx_info_size = sPriv->devPrivSize; + arg.sarea = sPriv->pSAREA; + dri1_copy_version(&arg.ddx_version, &sPriv->ddx_version); + dri1_copy_version(&arg.dri_version, &sPriv->dri_version); + dri1_copy_version(&arg.drm_version, &sPriv->drm_version); + arg.api = NULL; + + /** + * FIXME: If the driver supports format conversion swapbuffer blits, we might + * want to support other color bit depths than the server is currently + * using. + */ + + pscreen = screen->api->create_screen(screen->api, screen->fd, &arg.base); + /* dri_init_screen_helper checks pscreen for us */ + + configs = dri_init_screen_helper(screen, pscreen, sPriv->fbBPP); + if (!configs) + goto fail; + + if (!arg.api) { + debug_printf("%s: failed to create dri1 screen\n", __FUNCTION__); + goto fail; + } + + __dri1_api_hooks = arg.api; + + return configs; +fail: + if (configs) + FREE(configs); + dri_destroy_screen_helper(screen); + FREE(screen); + return NULL; +} diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/drm/dri1.h index 75a0ee4250e..a50188b3682 100644 --- a/src/gallium/state_trackers/dri/dri_screen.h +++ b/src/gallium/state_trackers/dri/drm/dri1.h @@ -29,52 +29,23 @@ * Author: Jakob Bornecrantz <[email protected]> */ -#ifndef DRI_SCREEN_H -#define DRI_SCREEN_H +#ifndef DRI1_H +#define DRI1_H -#include "dri_util.h" -#include "xmlconfig.h" +#include "dri_context.h" +#include "dri_drawable.h" -#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" +#include "dri_wrapper.h" -#include "state_tracker/dri1_api.h" - -struct dri_screen -{ - /* dri */ - __DRIscreen *sPriv; - - /** - * Configuration cache with default values for all contexts - */ - driOptionCache optionCache; - - /* drm */ - int fd; - drmLock *drmLock; - - /* gallium */ - struct drm_api *api; - struct pipe_winsys *pipe_winsys; - struct pipe_screen *pipe_screen; - boolean d_depth_bits_last; - boolean sd_depth_bits_last; - boolean auto_fake_front; -}; - -/** cast wrapper */ -static INLINE struct dri_screen * -dri_screen(__DRIscreen * sPriv) -{ - return (struct dri_screen *)sPriv->private; -} +extern struct dri1_api *__dri1_api_hooks; -/*********************************************************************** - * dri_screen.c - */ +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv); -extern struct dri1_api *__dri1_api_hooks; +void dri1_swap_buffers(__DRIdrawable * dPriv); -#endif +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); -/* vim: set sw=3 ts=8 sts=3 expandtab: */ +#endif /* DRI1_H */ diff --git a/src/gallium/state_trackers/dri/drm/dri1_helper.c b/src/gallium/state_trackers/dri/drm/dri1_helper.c new file mode 120000 index 00000000000..c45ebf5c102 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri1_helper.c @@ -0,0 +1 @@ +../common/dri1_helper.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c new file mode 100644 index 00000000000..e1216f14c0e --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -0,0 +1,545 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright (C) 2010 LunarG Inc. + * + * 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 + * BRIAN PAUL 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. + * + * Authors: + * Keith Whitwell <[email protected]> + * Jakob Bornecrantz <[email protected]> + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "state_tracker/drm_api.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri2.h" + +#include "GL/internal/dri_interface.h" + +/** + * DRI2 flush extension. + */ +static void +dri2_flush_drawable(__DRIdrawable *draw) +{ +} + +static void +dri2_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_context *ctx = dri_context(dPriv->driContextPriv); + + dri2InvalidateDrawable(dPriv); + drawable->dPriv->lastStamp = *drawable->dPriv->pStamp; + + if (ctx) + ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); +} + +static const __DRI2flushExtension dri2FlushExtension = { + { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, + dri2_flush_drawable, + dri2_invalidate_drawable, +}; + +/** + * These are used for GLX_EXT_texture_from_pixmap + */ +static void +dri2_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, + GLint format, __DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_context(pDRICtx); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *pt; + + dri_drawable_validate_att(drawable, ST_ATTACHMENT_FRONT_LEFT); + + pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + + if (pt) { + enum pipe_format internal_format = pt->format; + + if (format == __DRI_TEXTURE_FORMAT_RGB) { + /* only need to cover the formats recognized by dri_fill_st_visual */ + switch (internal_format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + internal_format = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case PIPE_FORMAT_A8R8G8B8_UNORM: + internal_format = PIPE_FORMAT_X8R8G8B8_UNORM; + break; + default: + break; + } + } + + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, internal_format, pt, FALSE); + } +} + +static void +dri2_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, + __DRIdrawable *dPriv) +{ + dri2_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); +} + +static const __DRItexBufferExtension dri2TexBufferExtension = { + { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION }, + dri2_set_tex_buffer, + dri2_set_tex_buffer2, +}; + +/** + * Get the format and binding of an attachment. + */ +static INLINE void +dri2_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind) +{ + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + *format = drawable->stvis.color_format; + *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + *format = drawable->stvis.depth_stencil_format; + *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + *format = PIPE_FORMAT_NONE; + *bind = 0; + break; + } +} + + +/** + * Retrieve __DRIbuffer from the DRI loader. + */ +static __DRIbuffer * +dri2_drawable_get_buffers(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned *count) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; + boolean with_format; + __DRIbuffer *buffers; + int num_buffers; + unsigned attachments[10]; + unsigned num_attachments, i; + + assert(loader); + with_format = dri_with_format(drawable->sPriv); + + num_attachments = 0; + + /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ + if (!with_format) + attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; + + for (i = 0; i < *count; i++) { + enum pipe_format format; + unsigned bind; + int att, bpp; + + dri2_drawable_get_format(drawable, statts[i], &format, &bind); + if (format == PIPE_FORMAT_NONE) + continue; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + /* already added */ + if (!with_format) + continue; + att = __DRI_BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + att = __DRI_BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + att = __DRI_BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + att = __DRI_BUFFER_BACK_RIGHT; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + att = __DRI_BUFFER_DEPTH_STENCIL; + break; + default: + att = -1; + break; + } + + bpp = util_format_get_blocksizebits(format); + + if (att >= 0) { + attachments[num_attachments++] = att; + if (with_format) { + attachments[num_attachments++] = bpp; + } + } + } + + if (with_format) { + num_attachments /= 2; + buffers = loader->getBuffersWithFormat(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + else { + buffers = loader->getBuffers(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + + if (buffers) { + /* set one cliprect to cover the whole dri_drawable */ + dri_drawable->x = 0; + dri_drawable->y = 0; + dri_drawable->backX = 0; + dri_drawable->backY = 0; + dri_drawable->numClipRects = 1; + dri_drawable->pClipRects[0].x1 = 0; + dri_drawable->pClipRects[0].y1 = 0; + dri_drawable->pClipRects[0].x2 = dri_drawable->w; + dri_drawable->pClipRects[0].y2 = dri_drawable->h; + dri_drawable->numBackClipRects = 1; + dri_drawable->pBackClipRects[0].x1 = 0; + dri_drawable->pBackClipRects[0].y1 = 0; + dri_drawable->pBackClipRects[0].x2 = dri_drawable->w; + dri_drawable->pBackClipRects[0].y2 = dri_drawable->h; + + *count = num_buffers; + } + + return buffers; +} + +/** + * Process __DRIbuffer and convert them into pipe_resources. + */ +static void +dri2_drawable_process_buffers(struct dri_drawable *drawable, + __DRIbuffer *buffers, unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + __DRIdrawable *dri_drawable = drawable->dPriv; + struct pipe_resource templ; + struct winsys_handle whandle; + boolean have_depth = FALSE; + unsigned i, bind; + + if (drawable->old_num == count && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, sizeof(__DRIbuffer) * count) == 0) + return; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + templ.depth0 = 1; + + memset(&whandle, 0, sizeof(whandle)); + + for (i = 0; i < count; i++) { + __DRIbuffer *buf = &buffers[i]; + enum st_attachment_type statt; + enum pipe_format format; + + switch (buf->attachment) { + case __DRI_BUFFER_FRONT_LEFT: + if (!screen->auto_fake_front) { + statt = ST_ATTACHMENT_INVALID; + break; + } + /* fallthrough */ + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + /* use only the first depth/stencil buffer */ + if (!have_depth) { + have_depth = TRUE; + statt = ST_ATTACHMENT_DEPTH_STENCIL; + } + else { + statt = ST_ATTACHMENT_INVALID; + } + break; + default: + statt = ST_ATTACHMENT_INVALID; + break; + } + + dri2_drawable_get_format(drawable, statt, &format, &bind); + if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + + drawable->textures[statt] = + screen->base.screen->resource_from_handle(screen->base.screen, + &templ, &whandle); + } + + drawable->old_num = count; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * count); +} + +/* + * Backend functions for st_framebuffer interface. + */ + +static void +dri2_allocate_textures(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count) +{ + __DRIbuffer *buffers; + unsigned num_buffers = count; + + buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); + dri2_drawable_process_buffers(drawable, buffers, num_buffers); +} + +static void +dri2_flush_frontbuffer(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + struct __DRIdri2LoaderExtensionRec *loader = drawable->sPriv->dri2.loader; + + if (loader->flushFrontBuffer == NULL) + return; + + if (statt == ST_ATTACHMENT_FRONT_LEFT) { + loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } +} + +static __DRIimage * +dri2_lookup_egl_image(struct dri_context *ctx, void *handle) +{ + __DRIimageLookupExtension *loader = ctx->sPriv->dri2.image; + __DRIimage *img; + + if (!loader->lookupEGLImage) + return NULL; + + img = loader->lookupEGLImage(ctx->cPriv, handle, ctx->cPriv->loaderPrivate); + + return img; +} + +static __DRIimage * +dri2_create_image_from_name(__DRIcontext *context, + int width, int height, int format, + int name, int pitch, void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(context->driScreenPriv); + __DRIimage *img; + struct pipe_resource templ; + struct winsys_handle whandle; + unsigned tex_usage; + enum pipe_format pf; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + switch (format) { + case __DRI_IMAGE_FORMAT_RGB565: + pf = PIPE_FORMAT_B5G6R5_UNORM; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + pf = PIPE_FORMAT_NONE; + break; + } + if (pf == PIPE_FORMAT_NONE) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + + memset(&whandle, 0, sizeof(whandle)); + whandle.handle = name; + whandle.stride = pitch * util_format_get_blocksize(pf); + + img->texture = screen->base.screen->resource_from_handle(screen->base.screen, + &templ, &whandle); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->face = 0; + img->level = 0; + img->zslice = 0; + img->loader_private = loaderPrivate; + + return img; +} + +static __DRIimage * +dri2_create_image_from_renderbuffer(__DRIcontext *context, + int renderbuffer, void *loaderPrivate) +{ + struct dri_context *ctx = dri_context(context->driverPrivate); + + if (!ctx->st->get_resource_for_egl_image) + return NULL; + + /* TODO */ + return NULL; +} + +static void +dri2_destroy_image(__DRIimage *img) +{ + pipe_resource_reference(&img->texture, NULL); + FREE(img); +} + +static struct __DRIimageExtensionRec dri2ImageExtension = { + { __DRI_IMAGE, __DRI_IMAGE_VERSION }, + dri2_create_image_from_name, + dri2_create_image_from_renderbuffer, + dri2_destroy_image, +}; + +/* + * Backend function init_screen. + */ + +static const __DRIextension *dri_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + &dri2TexBufferExtension.base, + &dri2FlushExtension.base, + &dri2ImageExtension.base, + NULL +}; + +/** + * This is the driver specific part of the createNewScreen entry point. + * + * Returns the __GLcontextModes supported by this driver. + */ +const __DRIconfig ** +dri2_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->api = drm_api_create(); + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + screen->lookup_egl_image = dri2_lookup_egl_image; + screen->allocate_textures = dri2_allocate_textures; + screen->flush_frontbuffer = dri2_flush_frontbuffer; + + sPriv->private = (void *)screen; + sPriv->extensions = dri_screen_extensions; + + pscreen = screen->api->create_screen(screen->api, screen->fd, NULL); + /* dri_init_screen_helper checks pscreen for us */ + + configs = dri_init_screen_helper(screen, pscreen, 32); + if (!configs) + goto fail; + + screen->auto_fake_front = dri_with_format(sPriv); + + return configs; +fail: + dri_destroy_screen_helper(screen); + FREE(screen); + return NULL; +} + +/* This is the table of extensions that the loader will dlsym() for. */ +PUBLIC const __DRIextension *__driDriverExtensions[] = { + &driCoreExtension.base, + &driLegacyExtension.base, + &driDRI2Extension.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.h b/src/gallium/state_trackers/dri/drm/dri2.h index f96c5a14b0a..07adfe4f6c5 100644 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.h +++ b/src/gallium/state_trackers/dri/drm/dri2.h @@ -1,8 +1,8 @@ /************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * + * Copyright 2009, 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 @@ -10,31 +10,28 @@ * 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 above copyright notice and this permission notice (including the * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE 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. - * + * **************************************************************************/ +#ifndef DRI2_H +#define DRI2_H -#ifndef SW_WINSYS_H -#define SW_WINSYS_H +#include "dri_drawable.h" +#include "dri_wrapper.h" +const __DRIconfig ** +dri2_init_screen(__DRIscreen * sPriv); -struct pipe_winsys; - - -extern struct pipe_winsys * -create_sw_winsys(void); - - -#endif /* SW_WINSYS_H */ +#endif /* DRI2_H */ diff --git a/src/gallium/state_trackers/dri/drm/dri_context.c b/src/gallium/state_trackers/dri/drm/dri_context.c new file mode 120000 index 00000000000..5cfbbaeb068 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_context.c @@ -0,0 +1 @@ +../common/dri_context.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_drawable.c b/src/gallium/state_trackers/dri/drm/dri_drawable.c new file mode 120000 index 00000000000..0fc19be6ea6 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_drawable.c @@ -0,0 +1 @@ +../common/dri_drawable.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_screen.c b/src/gallium/state_trackers/dri/drm/dri_screen.c new file mode 120000 index 00000000000..847f6515f25 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_screen.c @@ -0,0 +1 @@ +../common/dri_screen.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/Makefile b/src/gallium/state_trackers/dri/sw/Makefile new file mode 100644 index 00000000000..c0ae71451b2 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/Makefile @@ -0,0 +1,25 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = drisw + +LIBRARY_DEFINES = -D__NOT_HAVE_DRM_H + +LIBRARY_INCLUDES = \ + -I../dri \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/gallium/state_trackers/dri/common \ + -I$(TOP)/src/mesa/drivers/dri/common \ + -I$(TOP)/src/mesa/main \ + -D__NOT_HAVE_DRM_H + + +C_SOURCES = \ + dri_context.c \ + dri_screen.c \ + dri_drawable.c \ + dri1_helper.c \ + drisw.c + +include ../../../Makefile.template diff --git a/src/gallium/state_trackers/dri/sw/SConscript b/src/gallium/state_trackers/dri/sw/SConscript new file mode 100644 index 00000000000..6bb282d1a4c --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/SConscript @@ -0,0 +1,27 @@ +####################################################################### +# SConscript for dri state_tracker + +Import('*') + +if env['dri']: + + env = env.Clone() + + env.Append(CPPPATH = [ + '#/src/mesa', + '#/src/gallium/state_trackers/dri/common', + '#/src/mesa/drivers/dri/common', + ]) + + env.Append(CPPDEFINES = [('__NOT_HAVE_DRM_H', '1')]) + + st_drisw = env.ConvenienceLibrary( + target = 'st_drisw', + source = [ 'dri_context.c', + 'dri_drawable.c', + 'dri_screen.c', + 'dri1_helper.c', + 'drisw.c', + ] + ) + Export('st_drisw') diff --git a/src/gallium/state_trackers/dri/sw/dri1_helper.c b/src/gallium/state_trackers/dri/sw/dri1_helper.c new file mode 120000 index 00000000000..c45ebf5c102 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/dri1_helper.c @@ -0,0 +1 @@ +../common/dri1_helper.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/dri_context.c b/src/gallium/state_trackers/dri/sw/dri_context.c new file mode 120000 index 00000000000..5cfbbaeb068 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/dri_context.c @@ -0,0 +1 @@ +../common/dri_context.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/dri_drawable.c b/src/gallium/state_trackers/dri/sw/dri_drawable.c new file mode 120000 index 00000000000..0fc19be6ea6 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/dri_drawable.c @@ -0,0 +1 @@ +../common/dri_drawable.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/dri_screen.c b/src/gallium/state_trackers/dri/sw/dri_screen.c new file mode 120000 index 00000000000..847f6515f25 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/dri_screen.c @@ -0,0 +1 @@ +../common/dri_screen.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c new file mode 100644 index 00000000000..dcf645593fb --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/drisw.c @@ -0,0 +1,289 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * + * 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ + +/* TODO: + * + * xshm / texture_from_pixmap / EGLImage: + * + * Allow the loaders to use the XSHM extension. It probably requires callbacks + * for createImage/destroyImage similar to DRI2 getBuffers. + */ + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "pipe/p_context.h" +#include "state_tracker/drisw_api.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri1_helper.h" +#include "drisw.h" + + +static INLINE void +get_drawable_info(__DRIdrawable *dPriv, int *w, int *h) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + int x, y; + + loader->getDrawableInfo(dPriv, + &x, &y, w, h, + dPriv->loaderPrivate); +} + +static INLINE void +put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + 0, 0, width, height, + data, dPriv->loaderPrivate); +} + +static void +drisw_update_drawable_info(struct dri_drawable *drawable) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + get_drawable_info(dPriv, &dPriv->w, &dPriv->h); +} + +static void +drisw_put_image(struct dri_drawable *drawable, + void *data, unsigned width, unsigned height) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image(dPriv, data, width, height); +} + +static INLINE void +drisw_present_texture(__DRIdrawable *dPriv, + struct pipe_resource *ptex) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_surface *psurf; + + psurf = dri1_get_pipe_surface(drawable, ptex); + if (!psurf) + return; + + screen->base.screen->flush_frontbuffer(screen->base.screen, psurf, drawable); +} + +static INLINE void +drisw_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + + drawable->texture_stamp = dPriv->lastStamp - 1; + + /* check if swapping currently bound buffer */ + if (ctx && ctx->dPriv == dPriv) + ctx->st->notify_invalid_framebuffer(ctx->st, &drawable->base); +} + +static INLINE void +drisw_copy_to_front(__DRIdrawable * dPriv, + struct pipe_resource *ptex) +{ + drisw_present_texture(dPriv, ptex); + + drisw_invalidate_drawable(dPriv); +} + +/* + * Backend functions for st_framebuffer interface and swap_buffers. + */ + +void +drisw_swap_buffers(__DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex; + + if (!ctx) + return; + + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + if (ptex) { + ctx->st->flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + + drisw_copy_to_front(dPriv, ptex); + } +} + +static void +drisw_flush_frontbuffer(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + struct dri_context *ctx = dri_get_current(drawable->sPriv); + struct pipe_resource *ptex; + + if (!ctx) + return; + + ptex = drawable->textures[statt]; + + if (ptex) { + drisw_copy_to_front(ctx->dPriv, ptex); + } +} + +/** + * Allocate framebuffer attachments. + * + * During fixed-size operation, the function keeps allocating new attachments + * as they are requested. Unused attachments are not removed, not until the + * framebuffer is resized or destroyed. + * + * It should be possible for DRI1 and DRISW to share this function, but it + * seems a better seperation and safer for each DRI version to provide its own + * function. + */ +static void +drisw_allocate_textures(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_resource templ; + unsigned width, height; + boolean resized; + int i; + + width = drawable->dPriv->w; + height = drawable->dPriv->h; + + resized = (drawable->old_w != width || + drawable->old_h != height); + + /* remove outdated textures */ + if (resized) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (drawable->textures[statts[i]]) + continue; + + dri_drawable_get_format(drawable, statts[i], &format, &bind); + + if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL) + bind |= PIPE_BIND_DISPLAY_TARGET; + + if (format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + + drawable->textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + } + + drawable->old_w = width; + drawable->old_h = height; +} + +/* + * Backend function for init_screen. + */ + +static const __DRIextension *drisw_screen_extensions[] = { + NULL +}; + +static struct drisw_loader_funcs drisw_lf = { + .put_image = drisw_put_image +}; + +const __DRIconfig ** +drisw_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->api = NULL; /* not needed */ + screen->sPriv = sPriv; + screen->fd = -1; + screen->allocate_textures = drisw_allocate_textures; + screen->update_drawable_info = drisw_update_drawable_info; + screen->flush_frontbuffer = drisw_flush_frontbuffer; + + sPriv->private = (void *)screen; + sPriv->extensions = drisw_screen_extensions; + + pscreen = drisw_create_screen(&drisw_lf); + /* dri_init_screen_helper checks pscreen for us */ + + configs = dri_init_screen_helper(screen, pscreen, 32); + if (!configs) + goto fail; + + return configs; +fail: + dri_destroy_screen_helper(screen); + FREE(screen); + return NULL; +} + +/* This is the table of extensions that the loader will dlsym() for. */ +PUBLIC const __DRIextension *__driDriverExtensions[] = { + &driCoreExtension.base, + &driSWRastExtension.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/sw/drisw.h b/src/gallium/state_trackers/dri/sw/drisw.h new file mode 100644 index 00000000000..6c6c891f356 --- /dev/null +++ b/src/gallium/state_trackers/dri/sw/drisw.h @@ -0,0 +1,43 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis <[email protected]> + * + * 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 above copyright notice and this permission notice (including the + * next paragraph) 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 NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE 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. + * + **************************************************************************/ + +#ifndef DRISW_H +#define DRISW_H + +#include "dri_context.h" +#include "dri_drawable.h" + +#include "state_tracker/st_api.h" +#include "dri_wrapper.h" + +const __DRIconfig ** +drisw_init_screen(__DRIscreen * sPriv); + +void drisw_swap_buffers(__DRIdrawable * dPriv); + +#endif /* DRISW_H */ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 794785006f5..1768241352f 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -16,6 +16,7 @@ x11_INCLUDES = \ -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/glx \ -I$(TOP)/src/mesa \ + $(X11_CFLAGS) \ $(shell pkg-config --cflags-only-I libdrm) x11_SOURCES = $(wildcard x11/*.c) \ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 04268c71c5a..3ab72dce2f3 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -14,276 +14,28 @@ * 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, + * 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 - * BRIAN PAUL 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 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 <assert.h> -#include <stdio.h> -#include <string.h> -#include "pipe/p_screen.h" -#include "util/u_memory.h" -#include "util/u_rect.h" -#include "util/u_inlines.h" #include "egldriver.h" #include "eglcurrent.h" -#include "eglconfigutil.h" #include "egllog.h" -#include "native.h" -#include "egl_g3d.h" -#include "egl_st.h" - -/** - * Validate the draw/read surfaces of the context. - */ -static void -egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_screen *screen = gdpy->native->screen; - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { - ST_SURFACE_FRONT_LEFT, - ST_SURFACE_BACK_LEFT, - ST_SURFACE_FRONT_RIGHT, - ST_SURFACE_BACK_RIGHT, - }; - EGLint num_surfaces, s; - - /* validate draw and/or read buffers */ - num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; - for (s = 0; s < num_surfaces; s++) { - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - EGLint att; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - if (!gctx->force_validate) { - unsigned int seq_num; - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &seq_num, NULL, NULL, NULL); - /* skip validation */ - if (gsurf->sequence_number == seq_num) - continue; - } - - pipe_surface_reference(&gsurf->render_surface, NULL); - memset(textures, 0, sizeof(textures)); - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &gsurf->sequence_number, textures, - &gsurf->base.Width, &gsurf->base.Height); - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct pipe_texture *pt = textures[att]; - struct pipe_surface *ps; - - if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { - ps = screen->get_tex_surface(screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, - st_att_map[att], ps); - - if (gsurf->render_att == att) - pipe_surface_reference(&gsurf->render_surface, ps); - - pipe_surface_reference(&ps, NULL); - pipe_texture_reference(&pt, NULL); - } - } - - gctx->stapi->st_resize_framebuffer(gbuf->st_fb, - gsurf->base.Width, gsurf->base.Height); - } - - gctx->force_validate = EGL_FALSE; - -} - -/** - * Create a st_framebuffer. - */ -static struct st_framebuffer * -create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - return gctx->stapi->st_create_framebuffer(&gconf->native->mode, - gconf->native->color_format, gconf->native->depth_format, - gconf->native->stencil_format, - gsurf->base.Width, gsurf->base.Height, &gsurf->base); -} - -/** - * Update the attachments of draw/read surfaces. - */ -static void -egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - EGLint s; - - /* route draw and read buffers' attachments */ - for (s = 0; s < 2; s++) { - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - gbuf->attachment_mask = (1 << gsurf->render_att); - - /* FIXME OpenGL defaults to draw the front or back buffer when the - * context is single-buffered or double-buffered respectively. In EGL, - * however, the buffer to be drawn is determined by the surface, instead - * of the context. As a result, rendering to a pixmap surface with a - * double-buffered context does not work as expected. - * - * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == - * NATIVE_ATTACHMENT_FRONT_LEFT); - */ - - /* - * FIXME If the back buffer is asked for here, and the front buffer is - * later needed by the client API (e.g. glDrawBuffer is called to draw - * the front buffer), it will create a new pipe texture and draw there. - * One fix is to ask for both buffers here, but it would be a waste if - * the front buffer is never used. A better fix is to add a callback to - * the pipe screen with context private (just like flush_frontbuffer). - */ - } -} - -/** - * Reallocate the context's framebuffers after draw/read surfaces change. - */ -static EGLBoolean -egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); - struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); - - /* unreference the old framebuffers */ - if (gctx->draw.st_fb) { - EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); - void *priv; - - priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); - if (!gdraw || priv != (void *) &gdraw->base) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - - if (is_equal) { - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - else { - priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); - if (!gread || priv != (void *) &gread->base) { - gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - } - } - - if (!gdraw) - return EGL_TRUE; - - /* create the draw fb */ - if (!gctx->draw.st_fb) { - gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); - if (!gctx->draw.st_fb) - return EGL_FALSE; - } - - /* create the read fb */ - if (!gctx->read.st_fb) { - if (gread != gdraw) { - gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); - if (!gctx->read.st_fb) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - return EGL_FALSE; - } - } - else { - /* there is no st_reference_framebuffer... */ - gctx->read.st_fb = gctx->draw.st_fb; - } - } - - egl_g3d_route_context(dpy, &gctx->base); - gctx->force_validate = EGL_TRUE; - - return EGL_TRUE; -} - -/** - * Return the state tracker for the given context. - */ -static const struct egl_g3d_st * -egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) -{ - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - const struct egl_g3d_st *stapi; - EGLint idx = -1; - - switch (ctx->ClientAPI) { - case EGL_OPENGL_ES_API: - switch (ctx->ClientVersion) { - case 1: - idx = EGL_G3D_ST_OPENGL_ES; - break; - case 2: - idx = EGL_G3D_ST_OPENGL_ES2; - break; - default: - _eglLog(_EGL_WARNING, "unknown client version %d", - ctx->ClientVersion); - break; - } - break; - case EGL_OPENVG_API: - idx = EGL_G3D_ST_OPENVG; - break; - case EGL_OPENGL_API: - idx = EGL_G3D_ST_OPENGL; - break; - default: - _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); - break; - } +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_format.h" +#include "util/u_string.h" - stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; - return stapi; -} +#include "egl_g3d.h" +#include "egl_g3d_api.h" +#include "egl_g3d_st.h" +#include "native.h" /** * Initialize the state trackers. @@ -298,10 +50,10 @@ egl_g3d_init_st(_EGLDriver *drv) if (gdrv->api_mask) return; - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - gdrv->stapis[i] = egl_g3d_get_st(i); + for (i = 0; i < ST_API_COUNT; i++) { + gdrv->stapis[i] = egl_g3d_create_st_api(i); if (gdrv->stapis[i]) - gdrv->api_mask |= gdrv->stapis[i]->api_bit; + gdrv->api_mask |= egl_g3d_st_api_bit(i); } if (gdrv->api_mask) @@ -350,35 +102,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) } } -/** - * Return an API mask that consists of the state trackers that supports the - * given mode. - * - * FIXME add st_is_mode_supported()? - */ -static EGLint -get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) -{ - EGLint check; - - /* OpenGL ES 1.x and 2.x are checked together */ - check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; - if (api_mask & check) { - /* this is required by EGL, not by OpenGL ES */ - if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) - api_mask &= ~check; - } - - check = EGL_OPENVG_BIT; - if (api_mask & check) { - /* vega st needs the depth/stencil rb */ - if (!mode->depthBits && !mode->stencilBits) - api_mask &= ~check; - } - - return api_mask; -} - #ifdef EGL_MESA_screen_surface static void @@ -392,7 +115,7 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL); if (!num_connectors) { if (native_connectors) - free(native_connectors); + FREE(native_connectors); return; } @@ -407,13 +130,13 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes); if (!num_modes) { if (native_modes) - free(native_modes); + FREE(native_modes); continue; } gscr = CALLOC_STRUCT(egl_g3d_screen); if (!gscr) { - free(native_modes); + FREE(native_modes); continue; } @@ -437,100 +160,275 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) _eglAddScreen(dpy, &gscr->base); } - free(native_connectors); + FREE(native_connectors); } #endif /* EGL_MESA_screen_surface */ /** - * Add configs to display and return the next config ID. + * Initialize and validate the EGL config attributes. */ -static EGLint -egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) +static EGLBoolean +init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, + EGLint api_mask, enum pipe_format depth_stencil_format) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - const struct native_config **native_configs; - int num_configs, i; + uint rgba[4], depth_stencil[2], buffer_size; + EGLint surface_type; + EGLint i; - native_configs = gdpy->native->get_configs(gdpy->native, - &num_configs); - if (!num_configs) { - if (native_configs) - free(native_configs); - return id; + /* get the color and depth/stencil component sizes */ + assert(nconf->color_format != PIPE_FORMAT_NONE); + buffer_size = 0; + for (i = 0; i < 4; i++) { + rgba[i] = util_format_get_component_bits(nconf->color_format, + UTIL_FORMAT_COLORSPACE_RGB, i); + buffer_size += rgba[i]; + } + for (i = 0; i < 2; i++) { + if (depth_stencil_format != PIPE_FORMAT_NONE) { + depth_stencil[i] = + util_format_get_component_bits(depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, i); + } + else { + depth_stencil[i] = 0; + } } - for (i = 0; i < num_configs; i++) { - EGLint api_mask; - struct egl_g3d_config *gconf; - EGLBoolean valid; + surface_type = 0x0; + if (nconf->window_bit) + surface_type |= EGL_WINDOW_BIT; + if (nconf->pixmap_bit) + surface_type |= EGL_PIXMAP_BIT; +#ifdef EGL_MESA_screen_surface + if (nconf->scanout_bit) + surface_type |= EGL_SCREEN_BIT_MESA; +#endif - gconf = CALLOC_STRUCT(egl_g3d_config); - if (!gconf) - continue; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) + surface_type |= EGL_PBUFFER_BIT; - _eglInitConfig(&gconf->base, dpy, id); + SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask); + SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask); - api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); - if (!api_mask) { - _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", - native_configs[i]->mode.visualID); - } + SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]); + SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]); + SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]); + SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]); + SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size); - valid = _eglConfigFromContextModesRec(&gconf->base, - &native_configs[i]->mode, api_mask, api_mask); - if (valid) { -#ifdef EGL_MESA_screen_surface - /* check if scanout surface bit is set */ - if (native_configs[i]->scanout_bit) { - EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); - val |= EGL_SCREEN_BIT_MESA; - SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); - } -#endif - valid = _eglValidateConfig(&gconf->base, EGL_FALSE); - } - if (!valid) { - _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", - native_configs[i]->mode.visualID); - free(gconf); - continue; + SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]); + SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]); + + SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type); + + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE); + if (surface_type & EGL_WINDOW_BIT) { + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id); + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, + nconf->native_visual_type); + } + + if (surface_type & EGL_PBUFFER_BIT) { + SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); + if (rgba[3]) + SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); + + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096); + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096); + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096); + } + + SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level); + SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples); + SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1); + + if (nconf->slow_config) + SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG); + + if (nconf->transparent_rgb) { + rgba[0] = nconf->transparent_rgb_values[0]; + rgba[1] = nconf->transparent_rgb_values[1]; + rgba[2] = nconf->transparent_rgb_values[2]; + + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]); + } + + return _eglValidateConfig(conf, EGL_FALSE); +} + +/** + * Initialize an EGL config from the native config. + */ +static EGLBoolean +egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const struct native_config *nconf, + enum pipe_format depth_stencil_format) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + EGLint buffer_mask, api_mask; + EGLBoolean valid; + EGLint i; + + buffer_mask = 0x0; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) + buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) + buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) + buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) + buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + + gconf->stvis.buffer_mask = buffer_mask; + gconf->stvis.color_format = nconf->color_format; + gconf->stvis.depth_stencil_format = depth_stencil_format; + gconf->stvis.accum_format = PIPE_FORMAT_NONE; + gconf->stvis.samples = nconf->samples; + + gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? + ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; + + api_mask = 0; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; + if (stapi) { + if (stapi->is_visual_supported(stapi, &gconf->stvis)) + api_mask |= egl_g3d_st_api_bit(i); } + } + /* this is required by EGL, not by OpenGL ES */ + if (nconf->window_bit && + gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) + api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); - gconf->native = native_configs[i]; - _eglAddConfig(dpy, &gconf->base); - id++; + if (!api_mask) { + _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", + nconf->native_visual_id); } - free(native_configs); - return id; + valid = init_config_attributes(&gconf->base, + nconf, api_mask, depth_stencil_format); + if (!valid) { + _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); + return EGL_FALSE; + } + + gconf->native = nconf; + + return EGL_TRUE; } /** - * Flush the front buffer of the context's draw surface. + * Get all interested depth/stencil formats of a display. */ -static void -egl_g3d_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) +static EGLint +egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, + enum pipe_format formats[8]) { - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface); + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct pipe_screen *screen = gdpy->native->screen; + const EGLint candidates[] = { + 1, PIPE_FORMAT_Z16_UNORM, + 1, PIPE_FORMAT_Z32_UNORM, + 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, + 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, + 0 + }; + const EGLint *fmt = candidates; + EGLint count; + + count = 0; + formats[count++] = PIPE_FORMAT_NONE; + + while (*fmt) { + EGLint i, n = *fmt++; + + /* pick the first supported format */ + for (i = 0; i < n; i++) { + if (screen->is_format_supported(screen, fmt[i], + PIPE_TEXTURE_2D, PIPE_BIND_DEPTH_STENCIL, 0)) { + formats[count++] = fmt[i]; + break; + } + } + + fmt += n; + } - if (gsurf) - gsurf->native->flush_frontbuffer(gsurf->native); + return count; } /** - * Re-validate the context. + * Add configs to display and return the next config ID. */ +static EGLint +egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + const struct native_config **native_configs; + enum pipe_format depth_stencil_formats[8]; + int num_formats, num_configs, i, j; + + native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); + if (!num_configs) { + if (native_configs) + FREE(native_configs); + return id; + } + + num_formats = egl_g3d_fill_depth_stencil_formats(dpy, + depth_stencil_formats); + + for (i = 0; i < num_configs; i++) { + for (j = 0; j < num_formats; j++) { + struct egl_g3d_config *gconf; + + gconf = CALLOC_STRUCT(egl_g3d_config); + if (gconf) { + _eglInitConfig(&gconf->base, dpy, id); + if (!egl_g3d_init_config(drv, dpy, &gconf->base, + native_configs[i], depth_stencil_formats[j])) { + FREE(gconf); + break; + } + + _eglAddConfig(dpy, &gconf->base); + id++; + } + } + } + + FREE(native_configs); + return id; +} + static void -egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) +egl_g3d_invalid_surface(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num) { - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); + /* XXX not thread safe? */ + struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); + struct egl_g3d_context *gctx; + + /* + * Some functions such as egl_g3d_copy_buffers create a temporary native + * surface. There is no gsurf associated with it. + */ + gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; + if (gctx) + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } +static struct native_event_handler egl_g3d_native_event_handler = { + .invalid_surface = egl_g3d_invalid_surface +}; + static EGLBoolean egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) { @@ -540,19 +438,25 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) _eglReleaseDisplayResources(drv, dpy); _eglCleanupDisplay(dpy); + if (gdpy->pipe) + gdpy->pipe->destroy(gdpy->pipe); + if (dpy->Screens) { for (i = 0; i < dpy->NumScreens; i++) { struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); - free(gscr->native_modes); - free(gscr); + FREE(gscr->native_modes); + FREE(gscr); } - free(dpy->Screens); + FREE(dpy->Screens); } + if (gdpy->smapi) + egl_g3d_destroy_st_manager(gdpy->smapi); + if (gdpy->native) gdpy->native->destroy(gdpy->native); - free(gdpy); + FREE(gdpy); dpy->DriverData = NULL; return EGL_TRUE; @@ -575,18 +479,25 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } dpy->DriverData = gdpy; - gdpy->native = native_create_display(dpy->NativeDisplay); + gdpy->native = native_create_display(dpy->NativeDisplay, + &egl_g3d_native_event_handler); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } - gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; - gdpy->native->screen->update_buffer = egl_g3d_update_buffer; + gdpy->native->user_data = (void *) dpy; egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; + gdpy->smapi = egl_g3d_create_st_manager(dpy); + if (!gdpy->smapi) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to create st manager)"); + goto fail; + } + #ifdef EGL_MESA_screen_surface /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { @@ -595,6 +506,10 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } #endif + dpy->Extensions.KHR_image_base = EGL_TRUE; + if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) + dpy->Extensions.KHR_image_pixmap = EGL_TRUE; + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; @@ -611,448 +526,6 @@ fail: return EGL_FALSE; } -static _EGLContext * -egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - _EGLContext *share, const EGLint *attribs) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_context *gshare = egl_g3d_context(share); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_context *gctx; - const __GLcontextModes *mode; - - gctx = CALLOC_STRUCT(egl_g3d_context); - if (!gctx) { - _eglError(EGL_BAD_ALLOC, "eglCreateContext"); - return NULL; - } - - if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { - free(gctx); - return NULL; - } - - gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); - if (!gctx->stapi) { - free(gctx); - return NULL; - } - - mode = &gconf->native->mode; - - gctx->pipe = gdpy->native->screen->context_create( - gdpy->native->screen, - (void *) &gctx->base); - - if (!gctx->pipe) { - free(gctx); - return NULL; - } - - gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, - (gshare) ? gshare->st_ctx : NULL); - if (!gctx->st_ctx) { - gctx->pipe->destroy(gctx->pipe); - free(gctx); - return NULL; - } - - return &gctx->base; -} - -/** - * Destroy a context. - */ -static void -destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - - /* FIXME a context might live longer than its display */ - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); - - egl_g3d_realloc_context(dpy, &gctx->base); - /* it will destroy the associated pipe context */ - gctx->stapi->st_destroy_context(gctx->st_ctx); - - free(gctx); -} - -static EGLBoolean -egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - if (!_eglIsContextBound(ctx)) - destroy_context(dpy, ctx); - return EGL_TRUE; -} - -struct egl_g3d_create_surface_arg { - EGLint type; - union { - EGLNativeWindowType win; - EGLNativePixmapType pix; - } u; -}; - -static _EGLSurface * -egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - struct egl_g3d_create_surface_arg *arg, - const EGLint *attribs) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - struct native_surface *nsurf; - const char *err; - - switch (arg->type) { - case EGL_WINDOW_BIT: - err = "eglCreateWindowSurface"; - break; - case EGL_PIXMAP_BIT: - err = "eglCreatePixmapSurface"; - break; - case EGL_PBUFFER_BIT: - err = "eglCreatePBufferSurface"; - break; -#ifdef EGL_MESA_screen_surface - case EGL_SCREEN_BIT_MESA: - err = "eglCreateScreenSurface"; - break; -#endif - default: - err = "eglCreateUnknownSurface"; - break; - } - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, err); - return NULL; - } - - if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { - free(gsurf); - return NULL; - } - - /* create the native surface */ - switch (arg->type) { - case EGL_WINDOW_BIT: - nsurf = gdpy->native->create_window_surface(gdpy->native, - arg->u.win, gconf->native); - break; - case EGL_PIXMAP_BIT: - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - arg->u.pix, gconf->native); - break; - case EGL_PBUFFER_BIT: - nsurf = gdpy->native->create_pbuffer_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - break; -#ifdef EGL_MESA_screen_surface - case EGL_SCREEN_BIT_MESA: - /* prefer back buffer (move to _eglInitSurface?) */ - gsurf->base.RenderBuffer = EGL_BACK_BUFFER; - nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - break; -#endif - default: - nsurf = NULL; - break; - } - - if (!nsurf) { - free(gsurf); - return NULL; - } - /* initialize the geometry */ - if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, - &gsurf->base.Width, &gsurf->base.Height)) { - nsurf->destroy(nsurf); - free(gsurf); - return NULL; - } - - gsurf->native = nsurf; - - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - if (!gconf->native->mode.doubleBufferMode) - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; - - return &gsurf->base; -} - -static _EGLSurface * -egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativeWindowType win, - const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_WINDOW_BIT; - arg.u.win = win; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static _EGLSurface * -egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativePixmapType pix, - const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_PIXMAP_BIT; - arg.u.pix = pix; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static _EGLSurface * -egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_PBUFFER_BIT; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -/** - * Destroy a surface. - */ -static void -destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - /* FIXME a surface might live longer than its display */ - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); - - pipe_surface_reference(&gsurf->render_surface, NULL); - gsurf->native->destroy(gsurf->native); - free(gsurf); -} - -static EGLBoolean -egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - if (!_eglIsSurfaceBound(surf)) - destroy_surface(dpy, surf); - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); - struct egl_g3d_context *old_gctx; - EGLBoolean ok = EGL_TRUE; - - /* bind the new context and return the "orphaned" one */ - if (!_eglBindContext(&ctx, &draw, &read)) - return EGL_FALSE; - old_gctx = egl_g3d_context(ctx); - - if (old_gctx) { - /* flush old context */ - old_gctx->stapi->st_flush(old_gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - - /* - * The old context is no longer current, and egl_g3d_realloc_context() - * should be called to destroy the framebuffers. However, it is possible - * that it will be made current again with the same draw/read surfaces. - * It might be better to keep it around. - */ - } - - if (gctx) { - ok = egl_g3d_realloc_context(dpy, &gctx->base); - if (ok) { - ok = gctx->stapi->st_make_current(gctx->st_ctx, - gctx->draw.st_fb, gctx->read.st_fb); - if (ok) { - egl_g3d_validate_context(dpy, &gctx->base); - if (gdraw->base.Type == EGL_WINDOW_BIT) { - gctx->base.WindowRenderBuffer = - (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? - EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; - } - } - } - } - else if (old_gctx) { - ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL); - old_gctx->base.WindowRenderBuffer = EGL_NONE; - } - - if (ctx && !_eglIsContextLinked(ctx)) - destroy_context(dpy, ctx); - if (draw && !_eglIsSurfaceLinked(draw)) - destroy_surface(dpy, draw); - if (read && read != draw && !_eglIsSurfaceLinked(read)) - destroy_surface(dpy, read); - - return ok; -} - -static EGLBoolean -egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *ctx = _eglGetCurrentContext(); - struct egl_g3d_context *gctx = NULL; - - /* no-op for pixmap or pbuffer surface */ - if (gsurf->base.Type == EGL_PIXMAP_BIT || - gsurf->base.Type == EGL_PBUFFER_BIT) - return EGL_TRUE; - - /* or when the surface is single-buffered */ - if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) - return EGL_TRUE; - - if (ctx && ctx->DrawSurface == surf) - gctx = egl_g3d_context(ctx); - - /* flush if the surface is current */ - if (gctx) - gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); - - return gsurf->native->swap_buffers(gsurf->native); -} - -/** - * Find a config that supports the pixmap. - */ -static _EGLConfig * -find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf; - EGLint i; - - for (i = 0; i < dpy->NumConfigs; i++) { - gconf = egl_g3d_config(dpy->Configs[i]); - if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) - break; - } - - return (i < dpy->NumConfigs) ? &gconf->base : NULL; -} - -/** - * Get the pipe surface of the given attachment of the native surface. - */ -static struct pipe_surface * -get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, - enum native_attachment natt) -{ - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct pipe_surface *psurf; - - textures[natt] = NULL; - nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); - if (!textures[natt]) - return NULL; - - psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], - 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); - pipe_texture_reference(&textures[natt], NULL); - - return psurf; -} - -static EGLBoolean -egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLNativePixmapType target) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *ctx = _eglGetCurrentContext(); - struct egl_g3d_config *gconf; - struct native_surface *nsurf; - struct pipe_screen *screen = gdpy->native->screen; - struct pipe_surface *psurf; - - if (!gsurf->render_surface) - return EGL_TRUE; - - gconf = egl_g3d_config(find_pixmap_config(dpy, target)); - if (!gconf) - return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); - - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - target, gconf->native); - if (!nsurf) - return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); - - /* flush if the surface is current */ - if (ctx && ctx->DrawSurface == &gsurf->base) { - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_flush(gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - } - - psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); - if (psurf) { - struct pipe_context pipe; - - /** - * XXX This is hacky. If we might allow the EGLDisplay to create a pipe - * context of its own and use the blitter context for this. - */ - memset(&pipe, 0, sizeof(pipe)); - pipe.screen = screen; - - util_surface_copy(&pipe, FALSE, psurf, 0, 0, - gsurf->render_surface, 0, 0, psurf->width, psurf->height); - - pipe_surface_reference(&psurf, NULL); - nsurf->flush_frontbuffer(nsurf); - } - - nsurf->destroy(nsurf); - - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_finish(gctx->st_ctx); - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - - if (engine != EGL_CORE_NATIVE_ENGINE) - return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); - - if (ctx && ctx->DrawSurface) { - struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); - gsurf->native->wait(gsurf->native); - } - - return EGL_TRUE; -} - static _EGLProc egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) { @@ -1063,10 +536,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) /* in case this is called before a display is initialized */ egl_g3d_init_st(&gdrv->base); - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - const struct egl_g3d_st *stapi = gdrv->stapis[i]; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; if (stapi) { - proc = (_EGLProc) stapi->st_get_proc_address(procname); + proc = (_EGLProc) stapi->get_proc_address(stapi, procname); if (proc) return proc; } @@ -1075,161 +548,6 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) return (_EGLProc) NULL; } -static EGLBoolean -egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *surf, EGLint buffer) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); - struct egl_g3d_context *gctx; - enum pipe_format target_format; - int target; - - if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) - return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); - if (gsurf->base.BoundToTexture) - return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); - - switch (gsurf->base.TextureFormat) { - case EGL_TEXTURE_RGB: - target_format = PIPE_FORMAT_R8G8B8_UNORM; - break; - case EGL_TEXTURE_RGBA: - target_format = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - switch (gsurf->base.TextureTarget) { - case EGL_TEXTURE_2D: - target = ST_TEXTURE_2D; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - if (!es1) - return EGL_TRUE; - if (!gsurf->render_surface) - return EGL_FALSE; - - /* flush properly if the surface is bound */ - if (gsurf->base.CurrentContext) { - gctx = egl_g3d_context(gsurf->base.CurrentContext); - gctx->stapi->st_flush(gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - } - - gctx = egl_g3d_context(es1); - gctx->stapi->st_bind_texture_surface(gsurf->render_surface, - target, gsurf->base.MipmapLevel, target_format); - - gsurf->base.BoundToTexture = EGL_TRUE; - - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *surf, EGLint buffer) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || - !gsurf->base.BoundToTexture) - return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - - if (gsurf->render_surface) { - _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - - /* what if the context the surface binds to is no longer current? */ - if (gctx) - gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, - ST_TEXTURE_2D, gsurf->base.MipmapLevel); - } - - gsurf->base.BoundToTexture = EGL_FALSE; - - return EGL_TRUE; -} - -#ifdef EGL_MESA_screen_surface - -static _EGLSurface * -egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_SCREEN_BIT_MESA; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static EGLBoolean -egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLScreen *scr, _EGLSurface *surf, - _EGLMode *mode) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_screen *gscr = egl_g3d_screen(scr); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct native_surface *nsurf; - const struct native_mode *nmode; - EGLBoolean changed; - - if (gsurf) { - EGLint idx; - - if (!mode) - return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); - if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) - return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); - if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) - return _eglError(EGL_BAD_MATCH, - "eglShowSurfaceMESA(surface smaller than mode size)"); - - /* find the index of the mode */ - for (idx = 0; idx < gscr->base.NumModes; idx++) - if (mode == &gscr->base.Modes[idx]) - break; - if (idx >= gscr->base.NumModes) { - return _eglError(EGL_BAD_MODE_MESA, - "eglShowSurfaceMESA(unknown mode)"); - } - - nsurf = gsurf->native; - nmode = gscr->native_modes[idx]; - } - else { - if (mode) - return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); - - /* disable the screen */ - nsurf = NULL; - nmode = NULL; - } - - /* TODO surface panning by CRTC choosing */ - changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, - gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); - if (changed) { - gscr->base.CurrentSurface = &gsurf->base; - gscr->base.CurrentMode = mode; - } - - return changed; -} - -#endif /* EGL_MESA_screen_surface */ - static EGLint egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) { @@ -1263,9 +581,15 @@ static void egl_g3d_unload(_EGLDriver *drv) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + EGLint i; + + for (i = 0; i < ST_API_COUNT; i++) { + if (gdrv->stapis[i]) + gdrv->stapis[i]->destroy(gdrv->stapis[i]); + } egl_g3d_destroy_probe(drv, NULL); - free(gdrv); + FREE(gdrv); } _EGLDriver * @@ -1274,38 +598,18 @@ _eglMain(const char *args) static char driver_name[64]; struct egl_g3d_driver *gdrv; - snprintf(driver_name, sizeof(driver_name), + util_snprintf(driver_name, sizeof(driver_name), "Gallium/%s", native_get_name()); gdrv = CALLOC_STRUCT(egl_g3d_driver); if (!gdrv) return NULL; - _eglInitDriverFallbacks(&gdrv->base); - + egl_g3d_init_driver_api(&gdrv->base); gdrv->base.API.Initialize = egl_g3d_initialize; gdrv->base.API.Terminate = egl_g3d_terminate; - gdrv->base.API.CreateContext = egl_g3d_create_context; - gdrv->base.API.DestroyContext = egl_g3d_destroy_context; - gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface; - gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; - gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; - gdrv->base.API.DestroySurface = egl_g3d_destroy_surface; - gdrv->base.API.MakeCurrent = egl_g3d_make_current; - gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers; - gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers; - gdrv->base.API.WaitClient = egl_g3d_wait_client; - gdrv->base.API.WaitNative = egl_g3d_wait_native; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; - gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image; - gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image; - -#ifdef EGL_MESA_screen_surface - gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; - gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; -#endif - gdrv->base.Name = driver_name; gdrv->base.Probe = egl_g3d_probe; gdrv->base.Unload = egl_g3d_unload; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 5d2d9c481ab..5a3c80b9689 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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 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 _EGL_G3D_H_ @@ -34,15 +35,16 @@ #include "eglcontext.h" #include "eglsurface.h" #include "eglconfig.h" +#include "eglimage.h" #include "eglscreen.h" #include "eglmode.h" #include "native.h" -#include "egl_st.h" +#include "egl_g3d_st.h" struct egl_g3d_driver { _EGLDriver base; - const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; + struct st_api *stapis[ST_API_COUNT]; EGLint api_mask; EGLint probe_key; @@ -50,35 +52,44 @@ struct egl_g3d_driver { struct egl_g3d_display { struct native_display *native; -}; -struct egl_g3d_buffer { - struct st_framebuffer *st_fb; - uint attachment_mask; + struct st_manager *smapi; + struct pipe_context *pipe; }; struct egl_g3d_context { _EGLContext base; - const struct egl_g3d_st *stapi; - struct pipe_context *pipe; + struct st_api *stapi; - struct st_context *st_ctx; - EGLBoolean force_validate; - struct egl_g3d_buffer draw, read; + struct st_context_iface *stctxi; }; struct egl_g3d_surface { _EGLSurface base; + + struct st_visual stvis; + struct st_framebuffer_iface *stfbi; + + /* the native surface; NULL for pbuffers */ struct native_surface *native; - enum native_attachment render_att; - struct pipe_surface *render_surface; + struct pipe_resource *render_texture; + unsigned int sequence_number; }; struct egl_g3d_config { _EGLConfig base; const struct native_config *native; + struct st_visual stvis; +}; + +struct egl_g3d_image { + _EGLImage base; + struct pipe_resource *texture; + unsigned face; + unsigned level; + unsigned zslice; }; struct egl_g3d_screen { @@ -90,5 +101,6 @@ struct egl_g3d_screen { /* standard typecasts */ _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d) _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) +_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) #endif /* _EGL_G3D_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c new file mode 100644 index 00000000000..478516453ce --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -0,0 +1,731 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * + * 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 "egldriver.h" +#include "eglcurrent.h" +#include "egllog.h" + +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "egl_g3d.h" +#include "egl_g3d_api.h" +#include "egl_g3d_image.h" +#include "egl_g3d_st.h" +#include "native.h" + +/** + * Return the state tracker for the given context. + */ +static struct st_api * +egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct st_api *stapi; + EGLint idx = -1; + + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + switch (ctx->ClientVersion) { + case 1: + idx = ST_API_OPENGL_ES1; + break; + case 2: + idx = ST_API_OPENGL_ES2; + break; + default: + _eglLog(_EGL_WARNING, "unknown client version %d", + ctx->ClientVersion); + break; + } + break; + case EGL_OPENVG_API: + idx = ST_API_OPENVG; + break; + case EGL_OPENGL_API: + idx = ST_API_OPENGL; + break; + default: + _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); + break; + } + + stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; + return stapi; +} + +static _EGLContext * +egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share, const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_context *gshare = egl_g3d_context(share); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_context *gctx; + + gctx = CALLOC_STRUCT(egl_g3d_context); + if (!gctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { + FREE(gctx); + return NULL; + } + + gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); + if (!gctx->stapi) { + FREE(gctx); + return NULL; + } + + gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, + &gconf->stvis, (gshare) ? gshare->stctxi : NULL); + if (!gctx->stctxi) { + FREE(gctx); + return NULL; + } + + gctx->stctxi->st_manager_private = (void *) &gctx->base; + + return &gctx->base; +} + +/** + * Destroy a context. + */ +static void +destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + /* FIXME a context might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); + + gctx->stctxi->destroy(gctx->stctxi); + + FREE(gctx); +} + +static EGLBoolean +egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + if (!_eglIsContextBound(ctx)) + destroy_context(dpy, ctx); + return EGL_TRUE; +} + +struct egl_g3d_create_surface_arg { + EGLint type; + union { + EGLNativeWindowType win; + EGLNativePixmapType pix; + } u; +}; + +static _EGLSurface * +egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + struct egl_g3d_create_surface_arg *arg, + const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + struct native_surface *nsurf; + const char *err; + + switch (arg->type) { + case EGL_WINDOW_BIT: + err = "eglCreateWindowSurface"; + break; + case EGL_PIXMAP_BIT: + err = "eglCreatePixmapSurface"; + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + err = "eglCreateScreenSurface"; + break; +#endif + default: + err = "eglCreateUnknownSurface"; + break; + } + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, err); + return NULL; + } + + if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { + FREE(gsurf); + return NULL; + } + + /* create the native surface */ + switch (arg->type) { + case EGL_WINDOW_BIT: + nsurf = gdpy->native->create_window_surface(gdpy->native, + arg->u.win, gconf->native); + break; + case EGL_PIXMAP_BIT: + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + arg->u.pix, gconf->native); + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + /* prefer back buffer (move to _eglInitSurface?) */ + gsurf->base.RenderBuffer = EGL_BACK_BUFFER; + nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#endif + default: + nsurf = NULL; + break; + } + + if (!nsurf) { + FREE(gsurf); + return NULL; + } + /* initialize the geometry */ + if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + nsurf->destroy(nsurf); + FREE(gsurf); + return NULL; + } + + gsurf->stvis = gconf->stvis; + if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) + gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + nsurf->destroy(nsurf); + FREE(gsurf); + return NULL; + } + + nsurf->user_data = &gsurf->base; + gsurf->native = nsurf; + + return &gsurf->base; +} + +static _EGLSurface * +egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativeWindowType win, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_WINDOW_BIT; + arg.u.win = win; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static _EGLSurface * +egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativePixmapType pix, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PIXMAP_BIT; + arg.u.pix = pix; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static _EGLSurface * +egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const EGLint *attribs) +{ + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { + FREE(gsurf); + return NULL; + } + + gsurf->stvis = gconf->stvis; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + FREE(gsurf); + return NULL; + } + + return &gsurf->base; +} + +/** + * Destroy a surface. + */ +static void +destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + /* FIXME a surface might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); + + pipe_resource_reference(&gsurf->render_texture, NULL); + egl_g3d_destroy_st_framebuffer(gsurf->stfbi); + if (gsurf->native) + gsurf->native->destroy(gsurf->native); + FREE(gsurf); +} + +static EGLBoolean +egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + if (!_eglIsSurfaceBound(surf)) + destroy_surface(dpy, surf); + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); + struct egl_g3d_surface *gread = egl_g3d_surface(read); + struct egl_g3d_context *old_gctx; + EGLBoolean ok = EGL_TRUE; + + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&ctx, &draw, &read)) + return EGL_FALSE; + old_gctx = egl_g3d_context(ctx); + + if (old_gctx) { + /* flush old context */ + old_gctx->stctxi->flush(old_gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + if (gctx) { + ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi, + (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); + if (ok) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi); + if (gread != gdraw) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, + gread->stfbi); + } + + if (gdraw->base.Type == EGL_WINDOW_BIT) { + gctx->base.WindowRenderBuffer = + (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? + EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; + } + } + } + else if (old_gctx) { + ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); + old_gctx->base.WindowRenderBuffer = EGL_NONE; + } + + if (ctx && !_eglIsContextLinked(ctx)) + destroy_context(dpy, ctx); + if (draw && !_eglIsSurfaceLinked(draw)) + destroy_surface(dpy, draw); + if (read && read != draw && !_eglIsSurfaceLinked(read)) + destroy_surface(dpy, read); + + return ok; +} + +static EGLBoolean +egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_context *gctx = NULL; + + /* no-op for pixmap or pbuffer surface */ + if (gsurf->base.Type == EGL_PIXMAP_BIT || + gsurf->base.Type == EGL_PBUFFER_BIT) + return EGL_TRUE; + + /* or when the surface is single-buffered */ + if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) + return EGL_TRUE; + + if (ctx && ctx->DrawSurface == surf) + gctx = egl_g3d_context(ctx); + + /* flush if the surface is current */ + if (gctx) { + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + return gsurf->native->swap_buffers(gsurf->native); +} + +/** + * Get the pipe surface of the given attachment of the native surface. + */ +static struct pipe_surface * +get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, + enum native_attachment natt, + unsigned bind) +{ + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_surface *psurf; + + textures[natt] = NULL; + nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); + if (!textures[natt]) + return NULL; + + psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], + 0, 0, 0, bind); + pipe_resource_reference(&textures[natt], NULL); + + return psurf; +} + +static EGLBoolean +egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLNativePixmapType target) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_config *gconf; + struct native_surface *nsurf; + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_surface *psurf; + + if (!gsurf->render_texture) + return EGL_TRUE; + + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); + if (!gconf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + target, gconf->native); + if (!nsurf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + /* flush if the surface is current */ + if (ctx && ctx->DrawSurface == &gsurf->base) { + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + /* create a pipe context to copy surfaces */ + if (!gdpy->pipe) { + gdpy->pipe = + gdpy->native->screen->context_create(gdpy->native->screen, NULL); + if (!gdpy->pipe) + return EGL_FALSE; + } + + psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, + PIPE_BIND_BLIT_DESTINATION); + if (psurf) { + struct pipe_surface *psrc; + + psrc = screen->get_tex_surface(screen, gsurf->render_texture, + 0, 0, 0, PIPE_BIND_BLIT_SOURCE); + if (psrc) { + gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0, + psrc, 0, 0, psurf->width, psurf->height); + pipe_surface_reference(&psrc, NULL); + + nsurf->flush_frontbuffer(nsurf); + } + + pipe_surface_reference(&psurf, NULL); + } + + nsurf->destroy(nsurf); + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_fence_handle *fence = NULL; + + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + screen->fence_finish(screen, fence, 0); + screen->fence_reference(screen, &fence, NULL); + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + + if (engine != EGL_CORE_NATIVE_ENGINE) + return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); + + if (ctx && ctx->DrawSurface) { + struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); + + if (gsurf->native) + gsurf->native->wait(gsurf->native); + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx; + enum pipe_format internal_format; + enum st_texture_type target; + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + if (gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); + + switch (gsurf->base.TextureFormat) { + case EGL_TEXTURE_RGB: + internal_format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case EGL_TEXTURE_RGBA: + internal_format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + switch (gsurf->base.TextureTarget) { + case EGL_TEXTURE_2D: + target = ST_TEXTURE_2D; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + if (!es1) + return EGL_TRUE; + if (!gsurf->render_texture) + return EGL_FALSE; + + /* flush properly if the surface is bound */ + if (gsurf->base.CurrentContext) { + gctx = egl_g3d_context(gsurf->base.CurrentContext); + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + gctx = egl_g3d_context(es1); + if (gctx->stctxi->teximage) { + if (!gctx->stctxi->teximage(gctx->stctxi, target, + gsurf->base.MipmapLevel, internal_format, + gsurf->render_texture, gsurf->base.MipmapTexture)) + return EGL_FALSE; + gsurf->base.BoundToTexture = EGL_TRUE; + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || + !gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + + if (gsurf->render_texture) { + _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + /* what if the context the surface binds to is no longer current? */ + if (gctx) { + gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D, + gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE); + } + } + + gsurf->base.BoundToTexture = EGL_FALSE; + + return EGL_TRUE; +} + +#ifdef EGL_MESA_screen_surface + +static _EGLSurface * +egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_SCREEN_BIT_MESA; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static EGLBoolean +egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scr, _EGLSurface *surf, + _EGLMode *mode) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_screen *gscr = egl_g3d_screen(scr); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct native_surface *nsurf; + const struct native_mode *nmode; + EGLBoolean changed; + + if (gsurf) { + EGLint idx; + + if (!mode) + return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); + if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) + return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); + if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) + return _eglError(EGL_BAD_MATCH, + "eglShowSurfaceMESA(surface smaller than mode size)"); + + /* find the index of the mode */ + for (idx = 0; idx < gscr->base.NumModes; idx++) + if (mode == &gscr->base.Modes[idx]) + break; + if (idx >= gscr->base.NumModes) { + return _eglError(EGL_BAD_MODE_MESA, + "eglShowSurfaceMESA(unknown mode)"); + } + + nsurf = gsurf->native; + nmode = gscr->native_modes[idx]; + } + else { + if (mode) + return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); + + /* disable the screen */ + nsurf = NULL; + nmode = NULL; + } + + /* TODO surface panning by CRTC choosing */ + changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, + gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); + if (changed) { + gscr->base.CurrentSurface = &gsurf->base; + gscr->base.CurrentMode = mode; + } + + return changed; +} + +#endif /* EGL_MESA_screen_surface */ + +/** + * Find a config that supports the pixmap. + */ +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf; + EGLint i; + + for (i = 0; i < dpy->NumConfigs; i++) { + gconf = egl_g3d_config(dpy->Configs[i]); + if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) + break; + } + + return (i < dpy->NumConfigs) ? &gconf->base : NULL; +} + +void +egl_g3d_init_driver_api(_EGLDriver *drv) +{ + _eglInitDriverFallbacks(drv); + + drv->API.CreateContext = egl_g3d_create_context; + drv->API.DestroyContext = egl_g3d_destroy_context; + drv->API.CreateWindowSurface = egl_g3d_create_window_surface; + drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; + drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; + drv->API.DestroySurface = egl_g3d_destroy_surface; + drv->API.MakeCurrent = egl_g3d_make_current; + drv->API.SwapBuffers = egl_g3d_swap_buffers; + drv->API.CopyBuffers = egl_g3d_copy_buffers; + drv->API.WaitClient = egl_g3d_wait_client; + drv->API.WaitNative = egl_g3d_wait_native; + + drv->API.BindTexImage = egl_g3d_bind_tex_image; + drv->API.ReleaseTexImage = egl_g3d_release_tex_image; + + drv->API.CreateImageKHR = egl_g3d_create_image; + drv->API.DestroyImageKHR = egl_g3d_destroy_image; + +#ifdef EGL_MESA_screen_surface + drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; + drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; +#endif +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.h b/src/gallium/state_trackers/egl/common/egl_g3d_api.h new file mode 100644 index 00000000000..d5196c12fe9 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.h @@ -0,0 +1,37 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * + * 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 _EGL_G3D_API_H_ +#define _EGL_G3D_API_H_ + +#include "egl_g3d.h" + +void +egl_g3d_init_driver_api(_EGLDriver *drv); + +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix); + +#endif /* _EGL_G3D_API_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c new file mode 100644 index 00000000000..b1fe30a776c --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -0,0 +1,136 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "eglcurrent.h" + +#include "native.h" +#include "egl_g3d.h" +#include "egl_g3d_api.h" +#include "egl_g3d_image.h" + +/** + * Reference and return the front left buffer of the native pixmap. + */ +static struct pipe_resource * +egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf; + struct native_surface *nsurf; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; + enum native_attachment natt; + + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); + if (!gconf) + return NULL; + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + pix, gconf->native); + if (!nsurf) + return NULL; + + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL)) + textures[natt] = NULL; + + nsurf->destroy(nsurf); + + return textures[natt]; +} + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs) +{ + struct pipe_resource *ptex; + struct egl_g3d_image *gimg; + unsigned face = 0, level = 0, zslice = 0; + + gimg = CALLOC_STRUCT(egl_g3d_image); + if (!gimg) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitImage(&gimg->base, dpy, attribs)) { + FREE(gimg); + return NULL; + } + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + ptex = egl_g3d_reference_native_pixmap(dpy, + (EGLNativePixmapType) buffer); + break; + default: + ptex = NULL; + break; + } + + if (!ptex) { + FREE(gimg); + return NULL; + } + + if (level > ptex->last_level) { + _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR"); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); + return NULL; + } + if (zslice > ptex->depth0) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); + return NULL; + } + + /* transfer the ownership to the image */ + gimg->texture = ptex; + gimg->face = face; + gimg->level = level; + gimg->zslice = zslice; + + return &gimg->base; +} + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) +{ + struct egl_g3d_image *gimg = egl_g3d_image(img); + + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h new file mode 100644 index 00000000000..adda9333715 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h @@ -0,0 +1,42 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef _EGL_G3D_IMAGE_H_ +#define _EGL_G3D_IMAGE_H_ + +#include "egl_g3d.h" + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs); + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image); + +#endif /* _EGL_G3D_IMAGE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c new file mode 100644 index 00000000000..97445478684 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -0,0 +1,312 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_dl.h" +#include "eglimage.h" +#include "eglmutex.h" + +#include "egl_g3d.h" +#include "egl_g3d_st.h" + +struct egl_g3d_st_manager { + struct st_manager base; + _EGLDisplay *display; +}; + +static INLINE struct egl_g3d_st_manager * +egl_g3d_st_manager(struct st_manager *smapi) +{ + return (struct egl_g3d_st_manager *) smapi; +} + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api) +{ + struct util_dl_library *lib; + const char *proc_name; + struct st_api * (*proc)(void) = NULL; + + switch (api) { + case ST_API_OPENGL: + proc_name = ST_CREATE_OPENGL_SYMBOL; + break; + case ST_API_OPENGL_ES1: + proc_name = ST_CREATE_OPENGL_ES1_SYMBOL; + break; + case ST_API_OPENGL_ES2: + proc_name = ST_CREATE_OPENGL_ES2_SYMBOL; + break; + case ST_API_OPENVG: + proc_name = ST_CREATE_OPENVG_SYMBOL; + break; + default: + assert(!"Unknown API Type\n"); + return NULL; + } + + lib = util_dl_open(NULL); + if (lib) { + proc = util_dl_get_proc_address(lib, proc_name); + debug_printf("%s: %s %p\n", __func__, proc_name, proc); + util_dl_close(lib); + } + + if (!proc) + return NULL; + + return proc(); +} + +static boolean +egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, + struct st_egl_image *stimg) +{ + struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); + EGLImageKHR handle = (EGLImageKHR) stimg->egl_image; + _EGLImage *img; + struct egl_g3d_image *gimg; + + /* this is called from state trackers */ + _eglLockMutex(&gsmapi->display->Mutex); + + img = _eglLookupImage(handle, gsmapi->display); + if (!img) { + _eglUnlockMutex(&gsmapi->display->Mutex); + return FALSE; + } + + gimg = egl_g3d_image(img); + + stimg->texture = NULL; + pipe_resource_reference(&stimg->texture, gimg->texture); + stimg->face = gimg->face; + stimg->level = gimg->level; + stimg->zslice = gimg->zslice; + + _eglUnlockMutex(&gsmapi->display->Mutex); + + return TRUE; +} + +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_st_manager *gsmapi; + + gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); + if (gsmapi) { + gsmapi->display = dpy; + + gsmapi->base.screen = gdpy->native->screen; + gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; + } + + return &gsmapi->base;; +} + +void +egl_g3d_destroy_st_manager(struct st_manager *smapi) +{ + struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); + FREE(gsmapi); +} + +static boolean +egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + return TRUE; +} + +static boolean +egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct pipe_resource templ; + unsigned i; + + for (i = 0; i < count; i++) { + out[i] = NULL; + + if (gsurf->stvis.render_buffer != statts[i]) + continue; + + if (!gsurf->render_texture) { + struct egl_g3d_display *gdpy = + egl_g3d_display(gsurf->base.Resource.Display); + struct pipe_screen *screen = gdpy->native->screen; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = gsurf->base.Width; + templ.height0 = gsurf->base.Height; + templ.depth0 = 1; + templ.format = gsurf->stvis.color_format; + templ.bind = PIPE_BIND_RENDER_TARGET; + + gsurf->render_texture = screen->resource_create(screen, &templ); + } + + pipe_resource_reference(&out[i], gsurf->render_texture); + } + + return TRUE; +} + +static boolean +egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + return gsurf->native->flush_frontbuffer(gsurf->native); +} + +static boolean +egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; + uint attachment_mask = 0; + unsigned i; + + for (i = 0; i < count; i++) { + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + break; + default: + natt = -1; + break; + } + + if (natt >= 0) + attachment_mask |= 1 << natt; + } + + if (!gsurf->native->validate(gsurf->native, attachment_mask, + &gsurf->sequence_number, textures, &gsurf->base.Width, + &gsurf->base.Height)) + return FALSE; + + for (i = 0; i < count; i++) { + struct pipe_resource *tex; + int natt; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + natt = NATIVE_ATTACHMENT_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + natt = NATIVE_ATTACHMENT_BACK_RIGHT; + break; + default: + natt = -1; + break; + } + + if (natt >= 0) { + tex = textures[natt]; + + if (statts[i] == stfbi->visual->render_buffer) + pipe_resource_reference(&gsurf->render_texture, tex); + + if (attachment_mask & (1 << natt)) { + /* transfer the ownership to the caller */ + out[i] = tex; + attachment_mask &= ~(1 << natt); + } + else { + /* the attachment is listed more than once */ + pipe_resource_reference(&out[i], tex); + } + } + } + + return TRUE; +} + +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct st_framebuffer_iface *stfbi; + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + if (!stfbi) + return NULL; + + stfbi->visual = &gsurf->stvis; + if (gsurf->base.Type != EGL_PBUFFER_BIT) { + stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; + stfbi->validate = egl_g3d_st_framebuffer_validate; + } + else { + stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; + stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; + } + stfbi->st_manager_private = (void *) &gsurf->base; + + return stfbi; +} + +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + FREE(stfbi); +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h new file mode 100644 index 00000000000..c82681a22d8 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h @@ -0,0 +1,80 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef _EGL_G3D_ST_H_ +#define _EGL_G3D_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" +#include "egltypedefs.h" + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api); + +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy); + +void +egl_g3d_destroy_st_manager(struct st_manager *smapi); + +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf); + +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +/** + * Return the EGL_<api>_BIT of the st api. + */ +static INLINE int +egl_g3d_st_api_bit(enum st_api_type api) +{ + int bit; + + switch (api) { + case ST_API_OPENGL: + bit = EGL_OPENGL_BIT; + break; + case ST_API_OPENGL_ES1: + bit = EGL_OPENGL_ES_BIT; + break; + case ST_API_OPENGL_ES2: + bit = EGL_OPENGL_ES2_BIT; + break; + case ST_API_OPENVG: + bit = EGL_OPENVG_BIT; + break; + default: + bit = 0; + break; + } + + return bit; +} + +#endif /* _EGL_G3D_ST_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c deleted file mode 100644 index a88ff911cd5..00000000000 --- a/src/gallium/state_trackers/egl/common/egl_st.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.8 - * - * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> - * - * 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 - * BRIAN PAUL 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 <dlfcn.h> -#include "pipe/p_compiler.h" -#include "util/u_memory.h" -#include "egllog.h" -#include "EGL/egl.h" /* for EGL_api_BIT */ - -#include "egl_st.h" - -#ifndef HAVE_DLADDR -#define HAVE_DLADDR 1 -#endif - -#if HAVE_DLADDR - -static const char * -egl_g3d_st_names[] = { -#define ST_PUBLIC(name, ...) #name, -#include "st_public_tmp.h" - NULL -}; - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ - st_proc *procs = (st_proc *) stapi; - void *handle; - Dl_info info; - const char **name; - - if (!dladdr(sym, &info)) - return FALSE; - handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); - if (!handle) - return FALSE; - - for (name = egl_g3d_st_names; *name; name++) { - st_proc proc = (st_proc) dlsym(handle, *name); - if (!proc) { - _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); - memset(stapi, 0, sizeof(*stapi)); - dlclose(handle); - return FALSE; - } - *procs++ = proc; - } - - dlclose(handle); - return TRUE; -} - -#else /* HAVE_DLADDR */ - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ -#define ST_PUBLIC(name, ...) stapi->name = name; -#include "st_public_tmp.h" - return TRUE; -} - -#endif /* HAVE_DLADDR */ - -static boolean -egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) -{ - void *handle, *sym; - boolean res = FALSE; - - /* already initialized */ - if (stapi->st_notify_swapbuffers != NULL) - return TRUE; - - handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); - if (!handle) - return FALSE; - - sym = dlsym(handle, api); - if (sym && egl_g3d_fill_st(stapi, sym)) - res = TRUE; - - dlclose(handle); - return res; -} - -static struct { - const char *symbol; - EGLint api_bit; -} egl_g3d_st_info[NUM_EGL_G3D_STS] = { - { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, - { "st_api_OpenVG", EGL_OPENVG_BIT }, - { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, - { "st_api_OpenGL", EGL_OPENGL_BIT }, -}; - -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api) -{ - static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; - - if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { - all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; - return &all_trackers[api]; - } - else { - return NULL; - } -} diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 4f9758545ab..3f60348c489 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -14,26 +14,28 @@ * 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, + * 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 - * BRIAN PAUL 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 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 _NATIVE_H_ #define _NATIVE_H_ #include "EGL/egl.h" /* for EGL native types */ -#include "GL/gl.h" /* for GL types needed by __GLcontextModes */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ #include "pipe/p_compiler.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "native_probe.h" +#include "native_modeset.h" + /** * Only color buffers are listed. The others are allocated privately through, * for example, st_renderbuffer_alloc_storage(). @@ -47,28 +49,20 @@ enum native_attachment { NUM_NATIVE_ATTACHMENTS }; -/** - * Enumerations for probe results. - */ -enum native_probe_result { - NATIVE_PROBE_UNKNOWN, - NATIVE_PROBE_FALLBACK, - NATIVE_PROBE_SUPPORTED, - NATIVE_PROBE_EXACT, -}; - -/** - * A probe object for display probe. - */ -struct native_probe { - int magic; - EGLNativeDisplayType display; - void *data; - - void (*destroy)(struct native_probe *nprobe); +enum native_param_type { + /* + * Return TRUE if window/pixmap surfaces use the buffers of the native + * types. + */ + NATIVE_PARAM_USE_NATIVE_BUFFER }; struct native_surface { + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_surface *nsurf); /** @@ -97,7 +91,7 @@ struct native_surface { * behavior might change in the future. */ boolean (*validate)(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height); /** @@ -106,29 +100,28 @@ struct native_surface { void (*wait)(struct native_surface *nsurf); }; +/** + * Describe a native display config. + */ struct native_config { - /* __GLcontextModes should go away some day */ - __GLcontextModes mode; + /* available buffers and their format */ + uint buffer_mask; enum pipe_format color_format; - enum pipe_format depth_format; - enum pipe_format stencil_format; - /* treat it as an additional flag to mode.drawableType */ + /* supported surface types */ + boolean window_bit; + boolean pixmap_bit; boolean scanout_bit; -}; -struct native_connector { - int dummy; + int native_visual_id; + int native_visual_type; + int level; + int samples; + boolean slow_config; + boolean transparent_rgb; + int transparent_rgb_values[3]; }; -struct native_mode { - const char *desc; - int width, height; - int refresh_rate; -}; - -struct native_display_modeset; - /** * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis * hardware. A native display consists of a pipe winsys, a pipe screen, and @@ -137,28 +130,34 @@ struct native_display_modeset; struct native_display { /** * The pipe screen of the native display. - * - * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be - * overridden. */ struct pipe_screen *screen; + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_display *ndpy); /** - * Get the supported configs. The configs are owned by the display, but - * the returned array should be free()ed. + * Query the parameters of the native display. * - * The configs will be converted to EGL config by - * _eglConfigFromContextModesRec and validated by _eglValidateConfig. - * Those failing to pass the test will be skipped. + * The return value is defined by the parameter. + */ + int (*get_param)(struct native_display *ndpy, + enum native_param_type param); + + /** + * Get the supported configs. The configs are owned by the display, but + * the returned array should be FREE()ed. */ const struct native_config **(*get_configs)(struct native_display *ndpy, int *num_configs); /** * Test if a pixmap is supported by the given config. Required unless no - * config has GLX_PIXMAP_BIT set. + * config has pixmap_bit set. * * This function is usually called to find a config that supports a given * pixmap. Thus, it is usually called with the same pixmap in a row. @@ -169,73 +168,34 @@ struct native_display { /** - * Create a window surface. Required unless no config has GLX_WINDOW_BIT - * set. + * Create a window surface. Required unless no config has window_bit set. */ struct native_surface *(*create_window_surface)(struct native_display *ndpy, EGLNativeWindowType win, const struct native_config *nconf); /** - * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT - * set. + * Create a pixmap surface. Required unless no config has pixmap_bit set. */ struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy, EGLNativePixmapType pix, const struct native_config *nconf); - /** - * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT - * set. - */ - struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height); - const struct native_display_modeset *modeset; }; /** - * Mode setting interface of the native display. It exposes the mode setting - * capabilities of the underlying graphics hardware. + * The handler for events that a native display may generate. The events are + * generated asynchronously and the handler may be called by any thread at any + * time. */ -struct native_display_modeset { - /** - * Get the available physical connectors and the number of CRTCs. - */ - const struct native_connector **(*get_connectors)(struct native_display *ndpy, - int *num_connectors, - int *num_crtcs); - - /** - * Get the current supported modes of a connector. The returned modes may - * change every time this function is called and those from previous calls - * might become invalid. - */ - const struct native_mode **(*get_modes)(struct native_display *ndpy, - const struct native_connector *nconn, - int *num_modes); - +struct native_event_handler { /** - * Create a scan-out surface. Required unless no config has - * GLX_SCREEN_BIT_MESA set. + * This function is called when a surface needs to be validated. */ - struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height); - - /** - * Program the CRTC to output the surface to the given connectors with the - * given mode. When surface is not given, the CRTC is disabled. - * - * This interface does not export a way to query capabilities of the CRTCs. - * The native display usually needs to dynamically map the index to a CRTC - * that supports the given connectors. - */ - boolean (*program)(struct native_display *ndpy, int crtc_idx, - struct native_surface *nsurf, uint x, uint y, - const struct native_connector **nconns, int num_nconns, - const struct native_mode *nmode); + void (*invalid_surface)(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num); }; /** @@ -247,26 +207,11 @@ native_attachment_mask_test(uint mask, enum native_attachment att) return !!(mask & (1 << att)); } -/** - * Return a probe object for the given display. - * - * Note that the returned object may be cached and used by different native - * display modules. It allows fast probing when multiple modules probe the - * same display. - */ -struct native_probe * -native_create_probe(EGLNativeDisplayType dpy); - -/** - * Probe the probe object. - */ -enum native_probe_result -native_get_probe_result(struct native_probe *nprobe); - const char * native_get_name(void); struct native_display * -native_create_display(EGLNativeDisplayType dpy); +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *handler); #endif /* _NATIVE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h new file mode 100644 index 00000000000..dee757b3a88 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_modeset.h @@ -0,0 +1,88 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * + * 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 _NATIVE_MODESET_H_ +#define _NATIVE_MODESET_H_ + +#include "pipe/p_compiler.h" + +struct native_display; +struct native_surface; +struct native_config; + +struct native_connector { + int dummy; +}; + +struct native_mode { + const char *desc; + int width, height; + int refresh_rate; +}; + +/** + * Mode setting interface of the native display. It exposes the mode setting + * capabilities of the underlying graphics hardware. + */ +struct native_display_modeset { + /** + * Get the available physical connectors and the number of CRTCs. + */ + const struct native_connector **(*get_connectors)(struct native_display *ndpy, + int *num_connectors, + int *num_crtcs); + + /** + * Get the current supported modes of a connector. The returned modes may + * change every time this function is called and those from previous calls + * might become invalid. + */ + const struct native_mode **(*get_modes)(struct native_display *ndpy, + const struct native_connector *nconn, + int *num_modes); + + /** + * Create a scan-out surface. Required unless no config has scanout_bit + * set. + */ + struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height); + + /** + * Program the CRTC to output the surface to the given connectors with the + * given mode. When surface is not given, the CRTC is disabled. + * + * This interface does not export a way to query capabilities of the CRTCs. + * The native display usually needs to dynamically map the index to a CRTC + * that supports the given connectors. + */ + boolean (*program)(struct native_display *ndpy, int crtc_idx, + struct native_surface *nsurf, uint x, uint y, + const struct native_connector **nconns, int num_nconns, + const struct native_mode *nmode); +}; + +#endif /* _NATIVE_MODESET_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_probe.h b/src/gallium/state_trackers/egl/common/native_probe.h new file mode 100644 index 00000000000..aeed9f85dd5 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_probe.h @@ -0,0 +1,68 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * + * 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 _NATIVE_PROBE_H_ +#define _NATIVE_PROBE_H_ + +#include "EGL/egl.h" /* for EGL native types */ + +/** + * Enumerations for probe results. + */ +enum native_probe_result { + NATIVE_PROBE_UNKNOWN, + NATIVE_PROBE_FALLBACK, + NATIVE_PROBE_SUPPORTED, + NATIVE_PROBE_EXACT, +}; + +/** + * A probe object for display probe. + */ +struct native_probe { + int magic; + EGLNativeDisplayType display; + void *data; + + void (*destroy)(struct native_probe *nprobe); +}; + +/** + * Return a probe object for the given display. + * + * Note that the returned object may be cached and used by different native + * display modules. It allows fast probing when multiple modules probe the + * same display. + */ +struct native_probe * +native_create_probe(EGLNativeDisplayType dpy); + +/** + * Probe the probe object. + */ +enum native_probe_result +native_get_probe_result(struct native_probe *nprobe); + +#endif /* _NATIVE_PROBE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h deleted file mode 100644 index 507a0ec4027..00000000000 --- a/src/gallium/state_trackers/egl/common/st_public_tmp.h +++ /dev/null @@ -1,20 +0,0 @@ -ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) -ST_PUBLIC(st_destroy_context, void, struct st_context *st) -ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) -ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) -ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) -ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) -ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) -ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) -ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) -ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) -ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read) -ST_PUBLIC(st_get_current, struct st_context *, void) -ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) -ST_PUBLIC(st_finish, void, struct st_context *st) -ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) -ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) -ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) -#undef ST_PUBLIC diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index aedf3d430ca..cf7188dfdb7 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -14,35 +14,34 @@ * 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, + * 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 - * BRIAN PAUL 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 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 <stdio.h> -#include <string.h> - #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "util/u_debug.h" #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_string.h" #include "egllog.h" #include "native_kms.h" static boolean kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct kms_surface *ksurf = kms_surface(nsurf); struct kms_display *kdpy = ksurf->kdpy; struct pipe_screen *screen = kdpy->base.screen; - struct pipe_texture templ, *ptex; + struct pipe_resource templ, *ptex; int att; if (attachment_mask) { @@ -53,9 +52,7 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, templ.height0 = ksurf->height; templ.depth0 = 1; templ.format = ksurf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT) - templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SCANOUT; } /* create textures */ @@ -66,13 +63,13 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, ptex = ksurf->textures[att]; if (!ptex) { - ptex = screen->texture_create(screen, &templ); + ptex = screen->resource_create(screen, &templ); ksurf->textures[att] = ptex; } if (textures) { textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } @@ -100,7 +97,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) for (i = 0; i < num_framebuffers; i++) { struct kms_framebuffer *fb; enum native_attachment natt; - unsigned int handle, stride; + struct winsys_handle whandle; uint block_bits; if (i == 0) { @@ -118,7 +115,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) if (!ksurf->textures[natt]) return FALSE; - pipe_texture_reference(&fb->texture, ksurf->textures[natt]); + pipe_resource_reference(&fb->texture, ksurf->textures[natt]); } /* already initialized */ @@ -128,13 +125,17 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) /* TODO detect the real value */ fb->is_passive = TRUE; - if (!kdpy->api->local_handle_from_texture(kdpy->api, - kdpy->base.screen, fb->texture, &stride, &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen, + fb->texture, &whandle)) return FALSE; block_bits = util_format_get_blocksizebits(ksurf->color_format); err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height, - block_bits, block_bits, stride, handle, &fb->buffer_id); + block_bits, block_bits, whandle.stride, whandle.handle, + &fb->buffer_id); if (err) { fb->buffer_id = 0; return FALSE; @@ -151,10 +152,6 @@ kms_surface_flush_frontbuffer(struct native_surface *nsurf) struct kms_surface *ksurf = kms_surface(nsurf); struct kms_display *kdpy = ksurf->kdpy; - /* pbuffer is private */ - if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) - return TRUE; - if (ksurf->front_fb.is_passive) drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0); #endif @@ -169,13 +166,9 @@ kms_surface_swap_buffers(struct native_surface *nsurf) struct kms_crtc *kcrtc = &ksurf->current_crtc; struct kms_display *kdpy = ksurf->kdpy; struct kms_framebuffer tmp_fb; - struct pipe_texture *tmp_texture; + struct pipe_resource *tmp_texture; int err; - /* pbuffer is private */ - if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) - return TRUE; - if (!ksurf->back_fb.buffer_id) { if (!kms_surface_init_framebuffers(&ksurf->base, TRUE)) return FALSE; @@ -201,6 +194,8 @@ kms_surface_swap_buffers(struct native_surface *nsurf) /* the front/back textures are swapped */ ksurf->sequence_number++; + kdpy->event_handler->invalid_surface(&kdpy->base, + &ksurf->base, ksurf->sequence_number); return TRUE; } @@ -222,23 +217,22 @@ kms_surface_destroy(struct native_surface *nsurf) if (ksurf->front_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id); - pipe_texture_reference(&ksurf->front_fb.texture, NULL); + pipe_resource_reference(&ksurf->front_fb.texture, NULL); if (ksurf->back_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id); - pipe_texture_reference(&ksurf->back_fb.texture, NULL); + pipe_resource_reference(&ksurf->back_fb.texture, NULL); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = ksurf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = ksurf->textures[i]; + pipe_resource_reference(&ptex, NULL); } - free(ksurf); + FREE(ksurf); } static struct kms_surface * kms_display_create_surface(struct native_display *ndpy, - enum kms_surface_type type, const struct native_config *nconf, uint width, uint height) { @@ -251,7 +245,6 @@ kms_display_create_surface(struct native_display *ndpy, return NULL; ksurf->kdpy = kdpy; - ksurf->type = type; ksurf->color_format = kconf->base.color_format; ksurf->width = width; ksurf->height = height; @@ -469,7 +462,7 @@ kms_display_get_modes(struct native_display *ndpy, /* delete old data */ if (kconn->connector) { drmModeFreeConnector(kconn->connector); - free(kconn->kms_modes); + FREE(kconn->kms_modes); kconn->connector = NULL; kconn->kms_modes = NULL; @@ -482,7 +475,7 @@ kms_display_get_modes(struct native_display *ndpy, return NULL; count = kconn->connector->count_modes; - kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes)); + kconn->kms_modes = CALLOC(count, sizeof(*kconn->kms_modes)); if (!kconn->kms_modes) { drmModeFreeConnector(kconn->connector); kconn->connector = NULL; @@ -505,7 +498,7 @@ kms_display_get_modes(struct native_display *ndpy, kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000; } - nmodes_return = malloc(count * sizeof(*nmodes_return)); + nmodes_return = MALLOC(count * sizeof(*nmodes_return)); if (nmodes_return) { for (i = 0; i < count; i++) nmodes_return[i] = &kconn->kms_modes[i].base; @@ -526,7 +519,7 @@ kms_display_get_connectors(struct native_display *ndpy, int *num_connectors, if (!kdpy->connectors) { kdpy->connectors = - calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors)); + CALLOC(kdpy->resources->count_connectors, sizeof(*kdpy->connectors)); if (!kdpy->connectors) return NULL; @@ -540,7 +533,7 @@ kms_display_get_connectors(struct native_display *ndpy, int *num_connectors, kdpy->num_connectors = kdpy->resources->count_connectors; } - connectors = malloc(kdpy->num_connectors * sizeof(*connectors)); + connectors = MALLOC(kdpy->num_connectors * sizeof(*connectors)); if (connectors) { for (i = 0; i < kdpy->num_connectors; i++) connectors[i] = &kdpy->connectors[i].base; @@ -561,32 +554,18 @@ kms_display_create_scanout_surface(struct native_display *ndpy, { struct kms_surface *ksurf; - ksurf = kms_display_create_surface(ndpy, - KMS_SURFACE_TYPE_SCANOUT, nconf, width, height); - return &ksurf->base; -} - -static struct native_surface * -kms_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct kms_surface *ksurf; - - ksurf = kms_display_create_surface(ndpy, - KMS_SURFACE_TYPE_PBUFFER, nconf, width, height); + ksurf = kms_display_create_surface(ndpy, nconf, width, height); return &ksurf->base; } - static boolean kms_display_is_format_supported(struct native_display *ndpy, enum pipe_format fmt, boolean is_color) { return ndpy->screen->is_format_supported(ndpy->screen, fmt, PIPE_TEXTURE_2D, - (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + (is_color) ? PIPE_BIND_RENDER_TARGET : + PIPE_BIND_DEPTH_STENCIL, 0); } static const struct native_config ** @@ -600,14 +579,15 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) struct native_config *nconf; enum pipe_format format; - kdpy->config = calloc(1, sizeof(*kdpy->config)); + kdpy->config = CALLOC(1, sizeof(*kdpy->config)); if (!kdpy->config) return NULL; nconf = &kdpy->config->base; - /* always double-buffered */ - nconf->mode.doubleBufferMode = TRUE; + nconf->buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); format = PIPE_FORMAT_B8G8R8A8_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) { @@ -615,45 +595,18 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) format = PIPE_FORMAT_NONE; } - if (format == PIPE_FORMAT_NONE) + if (format == PIPE_FORMAT_NONE) { + FREE(kdpy->config); + kdpy->config = NULL; return NULL; + } nconf->color_format = format; - nconf->mode.redBits = 8; - nconf->mode.greenBits = 8; - nconf->mode.blueBits = 8; - nconf->mode.alphaBits = 8; - nconf->mode.rgbBits = 32; - - format = PIPE_FORMAT_Z24S8_UNORM; - if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) { - format = PIPE_FORMAT_S8Z24_UNORM; - if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) - format = PIPE_FORMAT_NONE; - } - if (format != PIPE_FORMAT_NONE) { - nconf->depth_format = format; - nconf->stencil_format = format; - - nconf->mode.depthBits = 24; - nconf->mode.stencilBits = 8; - nconf->mode.haveDepthBuffer = TRUE; - nconf->mode.haveStencilBuffer = TRUE; - } nconf->scanout_bit = TRUE; - nconf->mode.drawableType = GLX_PBUFFER_BIT; - nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML; - - nconf->mode.visualID = 0; - nconf->mode.visualType = EGL_NONE; - - nconf->mode.renderType = GLX_RGBA_BIT; - nconf->mode.rgbMode = TRUE; - nconf->mode.xRenderable = FALSE; } - configs = malloc(sizeof(*configs)); + configs = MALLOC(sizeof(*configs)); if (configs) { configs[0] = &kdpy->config->base; if (num_configs) @@ -663,6 +616,21 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) return configs; } +static int +kms_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + default: + val = 0; + break; + } + + return val; +} + static void kms_display_destroy(struct native_display *ndpy) { @@ -670,21 +638,21 @@ kms_display_destroy(struct native_display *ndpy) int i; if (kdpy->config) - free(kdpy->config); + FREE(kdpy->config); if (kdpy->connectors) { for (i = 0; i < kdpy->num_connectors; i++) { struct kms_connector *kconn = &kdpy->connectors[i]; if (kconn->connector) { drmModeFreeConnector(kconn->connector); - free(kconn->kms_modes); + FREE(kconn->kms_modes); } } - free(kdpy->connectors); + FREE(kdpy->connectors); } if (kdpy->shown_surfaces) - free(kdpy->shown_surfaces); + FREE(kdpy->shown_surfaces); if (kdpy->saved_crtcs) { for (i = 0; i < kdpy->resources->count_crtcs; i++) { @@ -700,7 +668,7 @@ kms_display_destroy(struct native_display *ndpy) drmModeFreeCrtc(kcrtc->crtc); } } - free(kdpy->saved_crtcs); + FREE(kdpy->saved_crtcs); } if (kdpy->resources) @@ -712,9 +680,9 @@ kms_display_destroy(struct native_display *ndpy) if (kdpy->fd >= 0) drmClose(kdpy->fd); - if (kdpy->api) + if (kdpy->api && kdpy->api->destroy) kdpy->api->destroy(kdpy->api); - free(kdpy); + FREE(kdpy); } /** @@ -724,10 +692,9 @@ static boolean kms_display_init_screen(struct native_display *ndpy) { struct kms_display *kdpy = kms_display(ndpy); - struct drm_create_screen_arg arg; int fd; - fd = drmOpen(kdpy->api->name, NULL); + fd = drmOpen(kdpy->api->driver_name, NULL); if (fd < 0) { _eglLog(_EGL_WARNING, "failed to open DRM device"); return FALSE; @@ -740,9 +707,7 @@ kms_display_init_screen(struct native_display *ndpy) } #endif - memset(&arg, 0, sizeof(arg)); - arg.mode = DRM_CREATE_NORMAL; - kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg); + kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, NULL); if (!kdpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); drmClose(fd); @@ -762,7 +727,9 @@ static struct native_display_modeset kms_display_modeset = { }; static struct native_display * -kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) +kms_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct kms_display *kdpy; @@ -770,10 +737,12 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!kdpy) return NULL; + kdpy->event_handler = event_handler; + kdpy->api = api; if (!kdpy->api) { _eglLog(_EGL_WARNING, "failed to create DRM API"); - free(kdpy); + FREE(kdpy); return NULL; } @@ -791,22 +760,22 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) } kdpy->saved_crtcs = - calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs)); + CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs)); if (!kdpy->saved_crtcs) { kms_display_destroy(&kdpy->base); return NULL; } kdpy->shown_surfaces = - calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces)); + CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces)); if (!kdpy->shown_surfaces) { kms_display_destroy(&kdpy->base); return NULL; } kdpy->base.destroy = kms_display_destroy; + kdpy->base.get_param = kms_display_get_param; kdpy->base.get_configs = kms_display_get_configs; - kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface; kdpy->base.modeset = &kms_display_modeset; @@ -837,15 +806,16 @@ native_get_name(void) drm_api = drm_api_create(); if (drm_api) - snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name); + util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name); else - snprintf(kms_name, sizeof(kms_name), "KMS"); + util_snprintf(kms_name, sizeof(kms_name), "KMS"); return kms_name; } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; @@ -853,7 +823,7 @@ native_create_display(EGLNativeDisplayType dpy) drm_api = drm_api_create(); if (drm_api) - ndpy = kms_create_display(dpy, drm_api); + ndpy = kms_create_display(dpy, event_handler, drm_api); return ndpy; } diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index 095186e3cf3..3b08e930c52 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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 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 _NATIVE_KMS_H_ @@ -35,11 +36,6 @@ #include "common/native.h" -enum kms_surface_type { - KMS_SURFACE_TYPE_PBUFFER, - KMS_SURFACE_TYPE_SCANOUT -}; - struct kms_config; struct kms_connector; struct kms_mode; @@ -53,6 +49,8 @@ struct kms_crtc { struct kms_display { struct native_display base; + struct native_event_handler *event_handler; + int fd; struct drm_api *api; drmModeResPtr resources; @@ -67,7 +65,7 @@ struct kms_display { }; struct kms_framebuffer { - struct pipe_texture *texture; + struct pipe_resource *texture; boolean is_passive; uint32_t buffer_id; @@ -75,12 +73,11 @@ struct kms_framebuffer { struct kms_surface { struct native_surface base; - enum kms_surface_type type; enum pipe_format color_format; struct kms_display *kdpy; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; unsigned int sequence_number; struct kms_framebuffer front_fb, back_fb; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 74d3d104b94..d37f66da07e 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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 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" @@ -40,7 +41,6 @@ enum dri2_surface_type { DRI2_SURFACE_TYPE_WINDOW, DRI2_SURFACE_TYPE_PIXMAP, - DRI2_SURFACE_TYPE_PBUFFER }; struct dri2_display { @@ -48,6 +48,8 @@ struct dri2_display { Display *dpy; boolean own_dpy; + struct native_event_handler *event_handler; + struct drm_api *api; struct x11_screen *xscr; int xscr_number; @@ -70,7 +72,7 @@ struct dri2_surface { unsigned int server_stamp; unsigned int client_stamp; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; boolean have_back, have_fake; @@ -111,13 +113,14 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - struct pipe_texture templ; + struct pipe_resource templ; + struct winsys_handle whandle; uint valid_mask; int i; /* free the old textures */ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) - pipe_texture_reference(&dri2surf->textures[i], NULL); + pipe_resource_reference(&dri2surf->textures[i], NULL); dri2surf->valid_mask = 0x0; dri2surf->have_back = FALSE; @@ -133,7 +136,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, templ.height0 = dri2surf->height; templ.depth0 = 1; templ.format = dri2surf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + templ.bind = PIPE_BIND_RENDER_TARGET; valid_mask = 0x0; for (i = 0; i < num_xbufs; i++) { @@ -169,9 +172,11 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, continue; } - dri2surf->textures[natt] = - dri2dpy->api->texture_from_shared_handle(dri2dpy->api, - dri2dpy->base.screen, &templ, desc, xbuf->pitch, xbuf->name); + memset(&whandle, 0, sizeof(whandle)); + whandle.stride = xbuf->pitch; + whandle.handle = xbuf->name; + dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( + dri2dpy->base.screen, &templ, &whandle); if (dri2surf->textures[natt]) valid_mask |= 1 << natt; } @@ -187,9 +192,19 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; + unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2]; int num_ins, num_outs, att; struct x11_drawable_buffer *xbufs; + uint bpp = util_format_get_blocksizebits(dri2surf->color_format); + boolean with_format = FALSE; /* never ask for depth/stencil */ + + /* We must get the front on servers which doesn't support with format + * due to a silly bug in core dri2. You can't copy to/from a buffer + * that you haven't requested and you recive BadValue errors */ + if (dri2surf->dri2dpy->dri_minor < 1) { + with_format = FALSE; + buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT); + } /* prepare the attachments */ num_ins = 0; @@ -216,19 +231,22 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) break; } - dri2atts[num_ins] = dri2att; - num_ins++; + dri2atts[num_ins++] = dri2att; + if (with_format) + dri2atts[num_ins++] = bpp; } } + if (with_format) + num_ins /= 2; xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, &dri2surf->width, &dri2surf->height, - dri2atts, FALSE, num_ins, &num_outs); + dri2atts, with_format, num_ins, &num_outs); /* we should be able to do better... */ if (xbufs && dri2surf->last_num_xbufs == num_outs && memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { - free(xbufs); + FREE(xbufs); dri2surf->client_stamp = dri2surf->server_stamp; return; } @@ -239,7 +257,7 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) dri2surf->client_stamp = dri2surf->server_stamp; if (dri2surf->last_xbufs) - free(dri2surf->last_xbufs); + FREE(dri2surf->last_xbufs); dri2surf->last_xbufs = xbufs; dri2surf->last_num_xbufs = num_outs; } @@ -252,47 +270,8 @@ static boolean dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); - struct dri2_display *dri2dpy = dri2surf->dri2dpy; - - /* create textures for pbuffer */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { - struct pipe_screen *screen = dri2dpy->base.screen; - struct pipe_texture templ; - uint new_valid = 0x0; - int att; - - buffer_mask &= ~dri2surf->valid_mask; - if (!buffer_mask) - return TRUE; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = dri2surf->width; - templ.height0 = dri2surf->height; - templ.depth0 = 1; - templ.format = dri2surf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - if (native_attachment_mask_test(buffer_mask, att)) { - assert(!dri2surf->textures[att]); - dri2surf->textures[att] = screen->texture_create(screen, &templ); - if (!dri2surf->textures[att]) - break; - - new_valid |= 1 << att; - if (new_valid == buffer_mask) - break; - } - } - dri2surf->valid_mask |= new_valid; - /* no need to update the stamps */ - } - else { - dri2_surface_get_buffers(&dri2surf->base, buffer_mask); - } + dri2_surface_get_buffers(&dri2surf->base, buffer_mask); return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); } @@ -313,10 +292,6 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf) struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; - /* copy to real front buffer */ if (dri2surf->have_fake) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, @@ -324,8 +299,11 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf) DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); /* force buffers to be updated in next validation call */ - if (!dri2_surface_receive_events(&dri2surf->base)) + if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); + } return TRUE; } @@ -336,10 +314,6 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; - /* copy to front buffer */ if (dri2surf->have_back) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, @@ -353,15 +327,18 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); /* force buffers to be updated in next validation call */ - if (!dri2_surface_receive_events(&dri2surf->base)) + if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); + } return TRUE; } static boolean dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct dri2_surface *dri2surf = dri2_surface(nsurf); @@ -379,10 +356,10 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, int att; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(attachment_mask, att)) { - struct pipe_texture *ptex = dri2surf->textures[att]; + struct pipe_resource *ptex = dri2surf->textures[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } } @@ -415,11 +392,11 @@ dri2_surface_destroy(struct native_surface *nsurf) int i; if (dri2surf->last_xbufs) - free(dri2surf->last_xbufs); + FREE(dri2surf->last_xbufs); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = dri2surf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = dri2surf->textures[i]; + pipe_resource_reference(&ptex, NULL); } if (dri2surf->drawable) { @@ -429,7 +406,7 @@ dri2_surface_destroy(struct native_surface *nsurf) util_hash_table_remove(dri2surf->dri2dpy->surfaces, (void *) dri2surf->drawable); } - free(dri2surf); + FREE(dri2surf); } static struct dri2_surface * @@ -493,22 +470,6 @@ dri2_display_create_pixmap_surface(struct native_display *ndpy, return (dri2surf) ? &dri2surf->base : NULL; } -static struct native_surface * -dri2_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct dri2_surface *dri2surf; - - dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER, - (Drawable) None, nconf); - if (dri2surf) { - dri2surf->width = width; - dri2surf->height = height; - } - return (dri2surf) ? &dri2surf->base : NULL; -} - static int choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) { @@ -535,43 +496,13 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) return count; } -static int -choose_depth_stencil_format(const __GLcontextModes *mode, - enum pipe_format formats[32]) -{ - int count = 0; - - switch (mode->depthBits) { - case 32: - formats[count++] = PIPE_FORMAT_Z32_UNORM; - break; - case 24: - if (mode->stencilBits) { - formats[count++] = PIPE_FORMAT_Z24S8_UNORM; - formats[count++] = PIPE_FORMAT_S8Z24_UNORM; - } - else { - formats[count++] = PIPE_FORMAT_Z24X8_UNORM; - formats[count++] = PIPE_FORMAT_X8Z24_UNORM; - } - break; - case 16: - formats[count++] = PIPE_FORMAT_Z16_UNORM; - break; - default: - break; - } - - return count; -} - static boolean is_format_supported(struct pipe_screen *screen, enum pipe_format fmt, boolean is_color) { return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, - (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + (is_color) ? PIPE_BIND_RENDER_TARGET : + PIPE_BIND_DEPTH_STENCIL, 0); } static boolean @@ -589,30 +520,18 @@ dri2_display_convert_config(struct native_display *ndpy, if (!mode->doubleBufferMode) return FALSE; - nconf->mode = *mode; - nconf->mode.renderType = GLX_RGBA_BIT; - nconf->mode.rgbMode = TRUE; - /* pbuffer is allocated locally and is always supported */ - nconf->mode.drawableType |= GLX_PBUFFER_BIT; - /* the swap method is always copy */ - nconf->mode.swapMethod = GLX_SWAP_COPY_OML; - - /* fix up */ - nconf->mode.rgbBits = - nconf->mode.redBits + nconf->mode.greenBits + - nconf->mode.blueBits + nconf->mode.alphaBits; - if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) { - nconf->mode.visualID = 0; - nconf->mode.visualType = GLX_NONE; - } - if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) { - nconf->mode.bindToTextureRgb = FALSE; - nconf->mode.bindToTextureRgba = FALSE; - } + /* only interested in native renderable configs */ + if (!mode->xRenderable || !mode->drawableType) + return FALSE; - nconf->color_format = PIPE_FORMAT_NONE; - nconf->depth_format = PIPE_FORMAT_NONE; - nconf->stencil_format = PIPE_FORMAT_NONE; + nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; + if (mode->doubleBufferMode) + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; + if (mode->stereoMode) { + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; + if (mode->doubleBufferMode) + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; + } /* choose color format */ num_formats = choose_color_format(mode, formats); @@ -625,18 +544,24 @@ dri2_display_convert_config(struct native_display *ndpy, if (nconf->color_format == PIPE_FORMAT_NONE) return FALSE; - /* choose depth/stencil format */ - num_formats = choose_depth_stencil_format(mode, formats); - for (i = 0; i < num_formats; i++) { - if (is_format_supported(ndpy->screen, formats[i], FALSE)) { - nconf->depth_format = formats[i]; - nconf->stencil_format = formats[i]; - break; - } + if (mode->drawableType & GLX_WINDOW_BIT) + nconf->window_bit = TRUE; + if (mode->drawableType & GLX_PIXMAP_BIT) + nconf->pixmap_bit = TRUE; + + nconf->native_visual_id = mode->visualID; + nconf->native_visual_type = mode->visualType; + nconf->level = mode->level; + nconf->samples = mode->samples; + + nconf->slow_config = (mode->visualRating == GLX_SLOW_CONFIG); + + if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { + nconf->transparent_rgb = TRUE; + nconf->transparent_rgb_values[0] = mode->transparentRed; + nconf->transparent_rgb_values[1] = mode->transparentGreen; + nconf->transparent_rgb_values[2] = mode->transparentBlue; } - if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) || - (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE)) - return FALSE; return TRUE; } @@ -658,7 +583,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) return NULL; num_modes = x11_context_modes_count(modes); - dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs)); + dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); if (!dri2dpy->configs) return NULL; @@ -673,7 +598,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) dri2dpy->num_configs = count; } - configs = malloc(dri2dpy->num_configs * sizeof(*configs)); + configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); if (configs) { for (i = 0; i < dri2dpy->num_configs; i++) configs[i] = (const struct native_config *) &dri2dpy->configs[i]; @@ -699,13 +624,32 @@ dri2_display_is_pixmap_supported(struct native_display *ndpy, return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); } +static int +dri2_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* DRI2GetBuffers use the native buffers */ + val = TRUE; + break; + default: + val = 0; + break; + } + + return val; +} + static void dri2_display_destroy(struct native_display *ndpy) { struct dri2_display *dri2dpy = dri2_display(ndpy); if (dri2dpy->configs) - free(dri2dpy->configs); + FREE(dri2dpy->configs); if (dri2dpy->base.screen) dri2dpy->base.screen->destroy(dri2dpy->base.screen); @@ -719,7 +663,7 @@ dri2_display_destroy(struct native_display *ndpy) XCloseDisplay(dri2dpy->dpy); if (dri2dpy->api && dri2dpy->api->destroy) dri2dpy->api->destroy(dri2dpy->api); - free(dri2dpy); + FREE(dri2dpy); } static void @@ -737,7 +681,10 @@ dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, return; dri2surf = dri2_surface(nsurf); + dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); } /** @@ -748,7 +695,6 @@ dri2_display_init_screen(struct native_display *ndpy) { struct dri2_display *dri2dpy = dri2_display(ndpy); const char *driver = dri2dpy->api->name; - struct drm_create_screen_arg arg; int fd; if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || @@ -771,9 +717,7 @@ dri2_display_init_screen(struct native_display *ndpy) if (fd < 0) return FALSE; - memset(&arg, 0, sizeof(arg)); - arg.mode = DRM_CREATE_NORMAL; - dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg); + dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, NULL); if (!dri2dpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); return FALSE; @@ -796,7 +740,9 @@ dri2_display_hash_table_compare(void *key1, void *key2) } struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct dri2_display *dri2dpy; @@ -804,6 +750,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!dri2dpy) return NULL; + dri2dpy->event_handler = event_handler; dri2dpy->api = api; dri2dpy->dpy = dpy; @@ -836,11 +783,11 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) } dri2dpy->base.destroy = dri2_display_destroy; + dri2dpy->base.get_param = dri2_display_get_param; dri2dpy->base.get_configs = dri2_display_get_configs; dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; - dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface; return &dri2dpy->base; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 3add95d0aca..b6d51bbf9fb 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -14,18 +14,19 @@ * 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, + * 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 - * BRIAN PAUL 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 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 <stdio.h> #include <string.h> #include "util/u_debug.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "state_tracker/drm_api.h" #include "egllog.h" @@ -40,8 +41,8 @@ static void x11_probe_destroy(struct native_probe *nprobe) { if (nprobe->data) - free(nprobe->data); - free(nprobe); + FREE(nprobe->data); + FREE(nprobe); } struct native_probe * @@ -61,7 +62,7 @@ native_create_probe(EGLNativeDisplayType dpy) if (!xdpy) { xdpy = XOpenDisplay(NULL); if (!xdpy) { - free(nprobe); + FREE(nprobe); return NULL; } } @@ -118,15 +119,16 @@ native_get_name(void) api = drm_api_create(); if (api) - snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name); + util_snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name); else - snprintf(x11_name, sizeof(x11_name), "X11"); + util_snprintf(x11_name, sizeof(x11_name), "X11"); return x11_name; } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; boolean force_sw; @@ -136,21 +138,14 @@ native_create_display(EGLNativeDisplayType dpy) force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); if (api && !force_sw) { - ndpy = x11_create_dri2_display(dpy, api); + ndpy = x11_create_dri2_display(dpy, event_handler, api); } if (!ndpy) { EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; - boolean use_shm; - - /* - * XXX st/mesa calls pipe_screen::update_buffer in st_validate_state. - * When SHM is used, there is a good chance that the shared memory - * segment is detached before the softpipe tile cache is flushed. - */ - use_shm = FALSE; - _eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : ""); - ndpy = x11_create_ximage_display(dpy, use_shm); + + _eglLog(level, "use software fallback"); + ndpy = x11_create_ximage_display(dpy, event_handler); } return ndpy; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 622ddac5df6..1678403b459 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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 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 _NATIVE_X11_H_ @@ -29,9 +30,12 @@ #include "common/native.h" struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm); +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler); struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api); +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api); #endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index a8633b1501e..47f5423b67e 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -14,38 +14,35 @@ * 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, + * 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 - * BRIAN PAUL 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 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 <assert.h> -#include <sys/ipc.h> -#include <sys/types.h> -#include <sys/shm.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/extensions/XShm.h> #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_format.h" #include "pipe/p_compiler.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" -#include "softpipe/sp_winsys.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "target-helpers/wrap_screen.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" #include "egllog.h" -#include "sw_winsys.h" #include "native_x11.h" #include "x11_screen.h" enum ximage_surface_type { XIMAGE_SURFACE_TYPE_WINDOW, XIMAGE_SURFACE_TYPE_PIXMAP, - XIMAGE_SURFACE_TYPE_PBUFFER }; struct ximage_display { @@ -53,22 +50,18 @@ struct ximage_display { Display *dpy; boolean own_dpy; + struct native_event_handler *event_handler; + struct x11_screen *xscr; int xscr_number; - boolean use_xshm; - - struct pipe_winsys *winsys; struct ximage_config *configs; int num_configs; }; struct ximage_buffer { - XImage *ximage; - - struct pipe_texture *texture; - XShmSegmentInfo *shm_info; - boolean xshm_attached; + struct pipe_resource *texture; + struct xlib_drawable xdraw; }; struct ximage_surface { @@ -79,13 +72,13 @@ struct ximage_surface { XVisualInfo visual; struct ximage_display *xdpy; - GC gc; - unsigned int server_stamp; unsigned int client_stamp; int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; + + struct pipe_surface *draw_surface; }; struct ximage_config { @@ -118,19 +111,7 @@ ximage_surface_free_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; - pipe_texture_reference(&xbuf->texture, NULL); - - if (xbuf->shm_info) { - if (xbuf->xshm_attached) - XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); - if (xbuf->shm_info->shmaddr != (void *) -1) - shmdt(xbuf->shm_info->shmaddr); - if (xbuf->shm_info->shmid != -1) - shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); - - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->shmid = -1; - } + pipe_resource_reference(&xbuf->texture, NULL); } static boolean @@ -140,7 +121,7 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_texture templ; + struct pipe_resource templ; /* free old data */ if (xbuf->texture) @@ -152,42 +133,25 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, templ.width0 = xsurf->width; templ.height0 = xsurf->height; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - - if (xbuf->shm_info) { - struct pipe_buffer *pbuf; - unsigned stride, size; - void *addr = NULL; - - stride = util_format_get_stride(xsurf->color_format, xsurf->width); - /* alignment should depend on visual? */ - stride = align(stride, 4); - size = stride * xsurf->height; - - /* create and attach shm object */ - xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); - if (xbuf->shm_info->shmid != -1) { - xbuf->shm_info->shmaddr = - shmat(xbuf->shm_info->shmid, NULL, 0); - if (xbuf->shm_info->shmaddr != (void *) -1) { - if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { - addr = xbuf->shm_info->shmaddr; - xbuf->xshm_attached = TRUE; - } - } - } + templ.bind = PIPE_BIND_RENDER_TARGET; - if (addr) { - pbuf = screen->user_buffer_create(screen, addr, size); - if (pbuf) { - xbuf->texture = - screen->texture_blanket(screen, &templ, &stride, pbuf); - pipe_buffer_reference(&pbuf, NULL); - } - } + switch (which) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + case NATIVE_ATTACHMENT_FRONT_RIGHT: + templ.bind |= PIPE_BIND_SCANOUT; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + case NATIVE_ATTACHMENT_BACK_RIGHT: + templ.bind |= PIPE_BIND_DISPLAY_TARGET; + break; + default: + break; } - else { - xbuf->texture = screen->texture_create(screen, &templ); + xbuf->texture = screen->resource_create(screen, &templ); + if (xbuf->texture) { + xbuf->xdraw.visual = xsurf->visual.visual; + xbuf->xdraw.depth = xsurf->visual.depth; + xbuf->xdraw.drawable = xsurf->drawable; } /* clean up the buffer if allocation failed */ @@ -211,10 +175,6 @@ ximage_surface_update_geometry(struct native_surface *nsurf) unsigned int w, h, border, depth; boolean updated = FALSE; - /* pbuffer has fixed geometry */ - if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) - return FALSE; - ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, &root, &x, &y, &w, &h, &border, &depth); if (ok && (xsurf->width != w || xsurf->height != h)) { @@ -228,6 +188,16 @@ ximage_surface_update_geometry(struct native_surface *nsurf) return updated; } +static void +ximage_surface_notify_invalid(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_display *xdpy = xsurf->xdpy; + + xdpy->event_handler->invalid_surface(&xdpy->base, + &xsurf->base, xsurf->server_stamp); +} + /** * Update the buffers of the surface. It is a slow function due to the * round-trip to the server. @@ -257,18 +227,10 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) new_valid = 0x0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(buffer_mask, att)) { - struct ximage_buffer *xbuf = &xsurf->buffers[att]; - /* reallocate the texture */ if (!ximage_surface_alloc_buffer(&xsurf->base, att)) break; - /* update ximage */ - if (xbuf->ximage) { - xbuf->ximage->width = xsurf->width; - xbuf->ximage->height = xsurf->height; - } - new_valid |= (1 << att); if (buffer_mask == new_valid) break; @@ -288,43 +250,23 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_transfer *transfer; + struct pipe_surface *psurf; - if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) - return TRUE; + assert(xsurf->drawable && xbuf->texture); - assert(xsurf->drawable && xbuf->ximage && xbuf->texture); + psurf = xsurf->draw_surface; + if (!psurf || psurf->texture != xbuf->texture) { + pipe_surface_reference(&xsurf->draw_surface, NULL); - transfer = screen->get_tex_transfer(screen, xbuf->texture, - 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); - if (!transfer) - return FALSE; + psurf = screen->get_tex_surface(screen, + xbuf->texture, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET); + if (!psurf) + return FALSE; - xbuf->ximage->bytes_per_line = transfer->stride; - xbuf->ximage->data = screen->transfer_map(screen, transfer); - if (!xbuf->ximage->data) { - screen->tex_transfer_destroy(transfer); - return FALSE; + xsurf->draw_surface = psurf; } - - if (xbuf->shm_info) - XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); - else - XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); - - xbuf->ximage->data = NULL; - screen->transfer_unmap(screen, transfer); - - /* - * softpipe allows the pipe transfer to be re-used, but we don't want to - * rely on that behavior. - */ - screen->tex_transfer_destroy(transfer); - - XSync(xsurf->xdpy->dpy, FALSE); + screen->flush_frontbuffer(screen, psurf, &xbuf->xdraw); return TRUE; } @@ -339,6 +281,7 @@ ximage_surface_flush_frontbuffer(struct native_surface *nsurf) NATIVE_ATTACHMENT_FRONT_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); return ret; } @@ -351,27 +294,28 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) boolean ret; /* display the back buffer first */ - ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_BACK_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; - /* skip swapping so that the front buffer is allocated only when needed */ - if (!xfront->texture) - return ret; - - xtmp = *xfront; - *xfront = *xback; - *xback = xtmp; + /* skip swapping unless there is a front buffer */ + if (xfront->texture) { + xtmp = *xfront; + *xfront = *xback; + *xback = xtmp; + } return ret; } static boolean ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) { struct ximage_surface *xsurf = ximage_surface(nsurf); @@ -392,7 +336,7 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, struct ximage_buffer *xbuf = &xsurf->buffers[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], xbuf->texture); + pipe_resource_reference(&textures[att], xbuf->texture); } } } @@ -419,19 +363,12 @@ ximage_surface_destroy(struct native_surface *nsurf) struct ximage_surface *xsurf = ximage_surface(nsurf); int i; - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; + pipe_surface_reference(&xsurf->draw_surface, NULL); + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) ximage_surface_free_buffer(&xsurf->base, i); - /* xbuf->shm_info is owned by xbuf->ximage? */ - if (xbuf->ximage) { - XDestroyImage(xbuf->ximage); - xbuf->ximage = NULL; - } - } - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) - XFreeGC(xsurf->xdpy->dpy, xsurf->gc); - free(xsurf); + FREE(xsurf); } static struct ximage_surface * @@ -443,7 +380,6 @@ ximage_display_create_surface(struct native_display *ndpy, struct ximage_display *xdpy = ximage_display(ndpy); struct ximage_config *xconf = ximage_config(nconf); struct ximage_surface *xsurf; - int i; xsurf = CALLOC_STRUCT(ximage_surface); if (!xsurf) @@ -454,56 +390,10 @@ ximage_display_create_surface(struct native_display *ndpy, xsurf->color_format = xconf->base.color_format; xsurf->drawable = drawable; - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { - xsurf->drawable = drawable; - xsurf->visual = *xconf->visual; - - xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); - if (!xsurf->gc) { - free(xsurf); - return NULL; - } - - /* initialize the geometry */ - ximage_surface_update_buffers(&xsurf->base, 0x0); - - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; - - if (xdpy->use_xshm) { - xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); - if (xbuf->shm_info) { - /* initialize shm info */ - xbuf->shm_info->shmid = -1; - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->readOnly = TRUE; - - xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, NULL, - xbuf->shm_info, - 0, 0); - } - } - else { - xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 8, /* bitmap_pad */ - 0); /* bytes_per_line */ - } - - if (!xbuf->ximage) { - XFreeGC(xdpy->dpy, xsurf->gc); - free(xsurf); - return NULL; - } - } - } + xsurf->drawable = drawable; + xsurf->visual = *xconf->visual; + /* initialize the geometry */ + ximage_surface_update_buffers(&xsurf->base, 0x0); xsurf->base.destroy = ximage_surface_destroy; xsurf->base.swap_buffers = ximage_surface_swap_buffers; @@ -538,22 +428,6 @@ ximage_display_create_pixmap_surface(struct native_display *ndpy, return (xsurf) ? &xsurf->base : NULL; } -static struct native_surface * -ximage_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct ximage_surface *xsurf; - - xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER, - (Drawable) None, nconf); - if (xsurf) { - xsurf->width = width; - xsurf->height = height; - } - return (xsurf) ? &xsurf->base : NULL; -} - static enum pipe_format choose_format(const XVisualInfo *vinfo) { @@ -587,7 +461,7 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) /* first time */ if (!xdpy->configs) { const XVisualInfo *visuals; - int num_visuals, count, j; + int num_visuals, count; visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); if (!visuals) @@ -597,57 +471,42 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) * Create two configs for each visual. * One with depth/stencil buffer; one without */ - xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs)); + xdpy->configs = CALLOC(num_visuals * 2, sizeof(*xdpy->configs)); if (!xdpy->configs) return NULL; count = 0; for (i = 0; i < num_visuals; i++) { - for (j = 0; j < 2; j++) { - struct ximage_config *xconf = &xdpy->configs[count]; - __GLcontextModes *mode = &xconf->base.mode; - - xconf->visual = &visuals[i]; - xconf->base.color_format = choose_format(xconf->visual); - if (xconf->base.color_format == PIPE_FORMAT_NONE) - continue; - - x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode); - /* support double buffer mode */ - mode->doubleBufferMode = TRUE; - - xconf->base.depth_format = PIPE_FORMAT_NONE; - xconf->base.stencil_format = PIPE_FORMAT_NONE; - /* create the second config with depth/stencil buffer */ - if (j == 1) { - xconf->base.depth_format = PIPE_FORMAT_Z24S8_UNORM; - xconf->base.stencil_format = PIPE_FORMAT_Z24S8_UNORM; - mode->depthBits = 24; - mode->stencilBits = 8; - mode->haveDepthBuffer = TRUE; - mode->haveStencilBuffer = TRUE; - } - - mode->maxPbufferWidth = 4096; - mode->maxPbufferHeight = 4096; - mode->maxPbufferPixels = 4096 * 4096; - mode->drawableType = - GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; - mode->swapMethod = GLX_SWAP_EXCHANGE_OML; - - if (mode->alphaBits) - mode->bindToTextureRgba = TRUE; - else - mode->bindToTextureRgb = TRUE; - - count++; - } + struct ximage_config *xconf = &xdpy->configs[count]; + + xconf->visual = &visuals[i]; + xconf->base.color_format = choose_format(xconf->visual); + if (xconf->base.color_format == PIPE_FORMAT_NONE) + continue; + + xconf->base.buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + xconf->base.window_bit = TRUE; + xconf->base.pixmap_bit = TRUE; + + xconf->base.native_visual_id = xconf->visual->visualid; +#if defined(__cplusplus) || defined(c_plusplus) + xconf->base.native_visual_type = xconf->visual->c_class; +#else + xconf->base.native_visual_type = xconf->visual->class; +#endif + + xconf->base.slow_config = TRUE; + + count++; } xdpy->num_configs = count; } - configs = malloc(xdpy->num_configs * sizeof(*configs)); + configs = MALLOC(xdpy->num_configs * sizeof(*configs)); if (configs) { for (i = 0; i < xdpy->num_configs; i++) configs[i] = (const struct native_config *) &xdpy->configs[i]; @@ -685,25 +544,98 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy, return (fmt == nconf->color_format); } +static int +ximage_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* private buffers are allocated */ + val = FALSE; + break; + default: + val = 0; + break; + } + + return val; +} + static void ximage_display_destroy(struct native_display *ndpy) { struct ximage_display *xdpy = ximage_display(ndpy); if (xdpy->configs) - free(xdpy->configs); + FREE(xdpy->configs); xdpy->base.screen->destroy(xdpy->base.screen); - free(xdpy->winsys); x11_screen_destroy(xdpy->xscr); if (xdpy->own_dpy) XCloseDisplay(xdpy->dpy); - free(xdpy); + FREE(xdpy); +} + + +/* Helper function to build a subset of a driver stack consisting of + * one of the software rasterizers (cell, llvmpipe, softpipe) and the + * xlib winsys. + * + * This function could be shared, but currently causes headaches for + * the build systems, particularly scons if we try. + * + * Long term, want to avoid having global #defines for things like + * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates + * those #defines, so things that are painful for it now are likely to + * be painful for other build systems in the future. + */ +static struct pipe_screen * +swrast_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_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; + + /* Create a software rasterizer on top of that winsys. Use + * llvmpipe if it is available. + */ +#if defined(GALLIUM_LLVMPIPE) + if (screen == NULL && + !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) + screen = llvmpipe_create_screen( winsys ); +#endif + + if (screen == NULL) + screen = softpipe_create_screen( winsys ); + + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return gallium_wrap_screen( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; } + + struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct ximage_display *xdpy; @@ -715,32 +647,30 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) if (!xdpy->dpy) { xdpy->dpy = XOpenDisplay(NULL); if (!xdpy->dpy) { - free(xdpy); + FREE(xdpy); return NULL; } xdpy->own_dpy = TRUE; } + xdpy->event_handler = event_handler; + xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); if (!xdpy->xscr) { - free(xdpy); + FREE(xdpy); return NULL; } - xdpy->use_xshm = - (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); - - xdpy->winsys = create_sw_winsys(); - xdpy->base.screen = softpipe_create_screen(xdpy->winsys); + xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy); xdpy->base.destroy = ximage_display_destroy; + xdpy->base.get_param = ximage_display_get_param; xdpy->base.get_configs = ximage_display_get_configs; xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; xdpy->base.create_window_surface = ximage_display_create_window_surface; xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; - xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface; return &xdpy->base; } diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c deleted file mode 100644 index 33328aadf26..00000000000 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.c +++ /dev/null @@ -1,231 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -/** - * Totally software-based winsys layer. - * Note that the one winsys function that we can't implement here - * is flush_frontbuffer(). - * Whoever uses this code will have to provide that. - * - * Authors: Brian Paul - */ - - -#include "util/u_simple_screen.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "sw_winsys.h" - - - -/** Subclass of pipe_winsys */ -struct sw_pipe_winsys -{ - struct pipe_winsys Base; - /* no extra fields for now */ -}; - - -/** subclass of pipe_buffer */ -struct sw_pipe_buffer -{ - struct pipe_buffer Base; - boolean UserBuffer; /** Is this a user-space buffer? */ - void *Data; - void *Mapped; -}; - - -/** cast wrapper */ -static INLINE struct sw_pipe_buffer * -sw_pipe_buffer(struct pipe_buffer *b) -{ - return (struct sw_pipe_buffer *) b; -} - - -static const char * -get_name(struct pipe_winsys *pws) -{ - return "software"; -} - - -/** Create new pipe_buffer and allocate storage of given size */ -static struct pipe_buffer * -buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.alignment = alignment; - buffer->Base.usage = usage; - buffer->Base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->Data = align_malloc(size, MAX2(alignment, 16)); - - return &buffer->Base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.size = bytes; - buffer->UserBuffer = TRUE; - buffer->Data = ptr; - - return &buffer->Base; -} - - -static void * -buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = buffer->Data; - return buffer->Mapped; -} - - -static void -buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = NULL; -} - - -static void -buffer_destroy(struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - - if (buffer->Data && !buffer->UserBuffer) { - align_free(buffer->Data); - buffer->Data = NULL; - } - - free(buffer); -} - - -static struct pipe_buffer * -surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ - /* no-op */ -} - - -static int -fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -static int -fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -/** - * Create/return a new pipe_winsys object. - */ -struct pipe_winsys * -create_sw_winsys(void) -{ - struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); - if (!ws) - return NULL; - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->Base.buffer_create = buffer_create; - ws->Base.user_buffer_create = user_buffer_create; - ws->Base.buffer_map = buffer_map; - ws->Base.buffer_unmap = buffer_unmap; - ws->Base.buffer_destroy = buffer_destroy; - - ws->Base.surface_buffer_create = surface_buffer_create; - - ws->Base.fence_reference = fence_reference; - ws->Base.fence_signalled = fence_signalled; - ws->Base.fence_finish = fence_finish; - - ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ - - ws->Base.get_name = get_name; - - return &ws->Base; -} diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index f4096114844..6bdff26ec08 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -14,24 +14,24 @@ * 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, + * 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 - * BRIAN PAUL 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 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 <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> +#include <xf86drm.h> #include <X11/Xlibint.h> #include <X11/extensions/XShm.h> + #include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_format.h" -#include "xf86drm.h" #include "egllog.h" #include "x11_screen.h" @@ -109,7 +109,7 @@ x11_screen_destroy(struct x11_screen *xscr) if (xscr->visuals) XFree(xscr->visuals); - free(xscr); + FREE(xscr); } static boolean @@ -176,63 +176,6 @@ x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals) return xscr->visuals; } -void -x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, - __GLcontextModes *mode) -{ - int r, g, b, a; - int visual_type; - - r = util_bitcount(visual->red_mask); - g = util_bitcount(visual->green_mask); - b = util_bitcount(visual->blue_mask); - a = visual->depth - (r + g + b); -#if defined(__cplusplus) || defined(c_plusplus) - visual_type = visual->c_class; -#else - visual_type = visual->class; -#endif - - /* convert to GLX visual type */ - switch (visual_type) { - case TrueColor: - visual_type = GLX_TRUE_COLOR; - break; - case DirectColor: - visual_type = GLX_DIRECT_COLOR; - break; - case PseudoColor: - visual_type = GLX_PSEUDO_COLOR; - break; - case StaticColor: - visual_type = GLX_STATIC_COLOR; - break; - case GrayScale: - visual_type = GLX_GRAY_SCALE; - break; - case StaticGray: - visual_type = GLX_STATIC_GRAY; - break; - default: - visual_type = GLX_NONE; - break; - } - - mode->rgbBits = r + g + b + a; - mode->redBits = r; - mode->greenBits = g; - mode->blueBits = b; - mode->alphaBits = a; - mode->visualID = visual->visualid; - mode->visualType = visual_type; - - /* sane defaults */ - mode->renderType = GLX_RGBA_BIT; - mode->rgbMode = TRUE; - mode->visualRating = GLX_SLOW_CONFIG; - mode->xRenderable = TRUE; -} - /** * Return the GLX fbconfigs. */ @@ -435,7 +378,7 @@ x11_context_modes_create(unsigned count) next = &base; for (i = 0; i < count; i++) { - *next = (__GLcontextModes *) calloc(1, size); + *next = (__GLcontextModes *) CALLOC(1, size); if (*next == NULL) { x11_context_modes_destroy(base); base = NULL; @@ -455,7 +398,7 @@ x11_context_modes_destroy(__GLcontextModes *modes) { while (modes != NULL) { __GLcontextModes *next = modes->next; - free(modes); + FREE(modes); modes = next; } } diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h index 37e8d5a40e6..a3c5ee1491e 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.h +++ b/src/gallium/state_trackers/egl/x11/x11_screen.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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 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 _X11_SCREEN_H_ @@ -28,6 +29,8 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/extensions/dri2tokens.h> +#include "GL/gl.h" /* for GL types needed by __GLcontextModes */ +#include "GL/internal/glcore.h" /* for __GLcontextModes */ #include "pipe/p_compiler.h" #include "common/native.h" @@ -64,10 +67,6 @@ x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext); const XVisualInfo * x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals); -void -x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, - __GLcontextModes *mode); - const __GLcontextModes * x11_screen_get_glx_configs(struct x11_screen *xscr); diff --git a/src/gallium/state_trackers/es/Makefile b/src/gallium/state_trackers/es/Makefile index b0365512719..7370634ea24 100644 --- a/src/gallium/state_trackers/es/Makefile +++ b/src/gallium/state_trackers/es/Makefile @@ -22,6 +22,8 @@ GLES_2_LIB = GLESv2 GLES_2_LIB_NAME = lib$(GLES_2_LIB).so +# These two objects indirectly reference all public functions thanks to the use +# of _glapi_get_proc_address. ES1_OBJECTS = st_es1.o ES2_OBJECTS = st_es2.o @@ -38,6 +40,8 @@ SYS_LIBS = -lm -pthread INCLUDE_DIRS = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ -I$(TOP)/src/gallium/include .c.o: @@ -54,9 +58,7 @@ $(TOP)/$(LIB_DIR)/$(GLES_1_LIB_NAME): $(ES1_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXIL -minor $(GLES_1_VERSION_MINOR) \ -patch $(GLES_1_VERSION_PATCH) \ -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ - $(ES1_OBJECTS) \ - -Wl,--whole-archive $(ES1_LIBS) -Wl,--no-whole-archive \ - $(GALLIUM_AUXILIARIES) $(SYS_LIBS) + $(ES1_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXILIARIES) $(SYS_LIBS) $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME): $(ES2_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXILIARIES) $(MKLIB) -o $(GLES_2_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \ @@ -64,9 +66,7 @@ $(TOP)/$(LIB_DIR)/$(GLES_2_LIB_NAME): $(ES2_OBJECTS) $(ES1_LIBS) $(GALLIUM_AUXIL -minor $(GLES_2_VERSION_MINOR) \ -patch $(GLES_2_VERSION_PATCH) \ -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ - $(ES2_OBJECTS) \ - -Wl,--whole-archive $(ES2_LIBS) -Wl,--no-whole-archive \ - $(GALLIUM_AUXILIARIES) $(SYS_LIBS) + $(ES2_OBJECTS) $(ES2_LIBS) $(GALLIUM_AUXILIARIES) $(SYS_LIBS) install: default $(INSTALL) -d $(DESTDIR)$(INSTALL_DIR)/include/GLES diff --git a/src/gallium/state_trackers/es/st_es1.c b/src/gallium/state_trackers/es/st_es1.c index 25bc53b21eb..825fdac2150 100644 --- a/src/gallium/state_trackers/es/st_es1.c +++ b/src/gallium/state_trackers/es/st_es1.c @@ -1,3 +1,7 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_gl_api.h" -PUBLIC const int st_api_OpenGL_ES1 = 1; +PUBLIC struct st_api * +st_api_create_OpenGL_ES1() +{ + return st_gl_api_create(); +} diff --git a/src/gallium/state_trackers/es/st_es2.c b/src/gallium/state_trackers/es/st_es2.c index 171ea62b97f..5c773aaf93b 100644 --- a/src/gallium/state_trackers/es/st_es2.c +++ b/src/gallium/state_trackers/es/st_es2.c @@ -1,3 +1,8 @@ -#include "pipe/p_compiler.h" +#include "state_tracker/st_gl_api.h" -PUBLIC const int st_api_OpenGL_ES2 = 1; +PUBLIC struct st_api * +st_api_create_OpenGL_ES2() +{ + /* linker magic creates different versions */ + return st_gl_api_create(); +} diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile index 7b2adc62c34..35509fd708b 100644 --- a/src/gallium/state_trackers/glx/xlib/Makefile +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -5,12 +5,14 @@ LIBNAME = xlib LIBRARY_INCLUDES = \ -I$(TOP)/include \ - -I$(TOP)/src/mesa + -I$(TOP)/src/mesa \ + $(X11_CFLAGS) C_SOURCES = \ glx_api.c \ glx_getproc.c \ glx_usefont.c \ - xm_api.c + xm_api.c \ + xm_st.c include ../../../Makefile.template diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript index fa96df357d5..d6c16ad2f52 100644 --- a/src/gallium/state_trackers/glx/xlib/SConscript +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -13,8 +13,6 @@ if env['platform'] == 'linux' \ '#/src/mesa/main', ]) - env.Append(CPPDEFINES = ['USE_XSHM']) - st_xlib = env.ConvenienceLibrary( target = 'st_xlib', source = [ @@ -22,6 +20,7 @@ if env['platform'] == 'linux' \ 'glx_getproc.c', 'glx_usefont.c', 'xm_api.c', + 'xm_st.c', ] ) Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 08bf624b5c1..eb8d6a19333 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -35,12 +35,9 @@ #include "xm_api.h" #include "main/context.h" -#include "main/config.h" #include "main/macros.h" #include "main/imports.h" #include "main/version.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" /* This indicates the client-side GLX API and GLX encoder version. */ @@ -689,7 +686,7 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) int desiredVisualID = -1; int numAux = 0; - xmesa_init(); + xmesa_init( dpy ); parselist = list; @@ -1304,7 +1301,7 @@ glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, if (MakeCurrent_PrevContext == src) { _mesa_Flush(); } - st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask ); + XMesaCopyContext(xm_src, xm_dst, mask); } @@ -1761,6 +1758,10 @@ glXGetFBConfigs( Display *dpy, int screen, int *nelements ) } for (i = 0; i < *nelements; i++) { results[i] = create_glx_visual(dpy, visuals + i); + if (!results[i]) { + *nelements = i; + break; + } } return (GLXFBConfig *) results; } diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index 217bdeff75e..f3b0617f76b 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -35,10 +35,6 @@ * corner of the window. Therefore, most drawing functions in this * file have to flip Y coordinates. * - * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile - * in support for the MIT Shared Memory extension. If enabled, when you - * use an Ximage for the back buffer in double buffered mode, the "swap" - * operation will be faster. You must also link with -lXext. * * Byte swapping: If the Mesa host and the X display use a different * byte order then there's some trickiness to be aware of when using @@ -58,20 +54,14 @@ #endif #include "xm_api.h" -#include "main/context.h" -#include "main/framebuffer.h" +#include "xm_st.h" -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" +#include "main/context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" -#include "trace/tr_screen.h" -#include "trace/tr_context.h" -#include "trace/tr_texture.h" - -#include "xm_winsys.h" +#include "xm_public.h" #include <GL/glx.h> @@ -80,20 +70,78 @@ * global. */ static struct xm_driver driver; +static struct st_api *stapi; void xmesa_set_driver( const struct xm_driver *templ ) { driver = *templ; + stapi = driver.create_st_api(); } -/** - * Global X driver lock + +/* + * XXX replace this with a linked list, or better yet, try to attach the + * gallium/mesa extra bits to the X Display object with XAddExtension(). */ -pipe_mutex _xmesa_lock; +#define MAX_DISPLAYS 10 +static struct xmesa_display Displays[MAX_DISPLAYS]; +static int NumDisplays = 0; + + +static XMesaDisplay +xmesa_init_display( Display *display ) +{ + pipe_static_mutex(init_mutex); + XMesaDisplay xmdpy; + int i; + + pipe_mutex_lock(init_mutex); + + /* Look for XMesaDisplay which corresponds to 'display' */ + for (i = 0; i < NumDisplays; i++) { + if (Displays[i].display == display) { + /* Found it */ + pipe_mutex_unlock(init_mutex); + return &Displays[i]; + } + } + + /* Create new XMesaDisplay */ -static struct pipe_screen *_screen = NULL; -static struct pipe_screen *screen = NULL; + assert(NumDisplays < MAX_DISPLAYS); + xmdpy = &Displays[NumDisplays]; + NumDisplays++; + if (!xmdpy->display && display) { + xmdpy->display = display; + xmdpy->screen = driver.create_pipe_screen(display); + xmdpy->smapi = CALLOC_STRUCT(st_manager); + if (xmdpy->smapi) + xmdpy->smapi->screen = xmdpy->screen; + + if (xmdpy->screen && xmdpy->smapi) { + pipe_mutex_init(xmdpy->mutex); + } + else { + if (xmdpy->screen) { + xmdpy->screen->destroy(xmdpy->screen); + xmdpy->screen = NULL; + } + if (xmdpy->smapi) { + FREE(xmdpy->smapi); + xmdpy->smapi = NULL; + } + + xmdpy->display = NULL; + } + } + if (!xmdpy->display || xmdpy->display != display) + xmdpy = NULL; + + pipe_mutex_unlock(init_mutex); + + return xmdpy; +} /**********************************************************************/ /***** X Utility Functions *****/ @@ -111,41 +159,6 @@ static int host_byte_order( void ) } -/** - * Check if the X Shared Memory extension is available. - * Return: 0 = not available - * 1 = shared XImage support available - * 2 = shared Pixmap support available also - */ -int xmesa_check_for_xshm( Display *display ) -{ -#if defined(USE_XSHM) - int major, minor, ignore; - Bool pixmaps; - - if (getenv("SP_NO_RAST")) - return 0; - - if (getenv("MESA_NOSHM")) { - return 0; - } - - if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { - if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { - return (pixmaps==True) ? 2 : 1; - } - else { - return 0; - } - } - else { - return 0; - } -#else - /* No XSHM support */ - return 0; -#endif -} /** @@ -238,12 +251,13 @@ void xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height) { + XMesaDisplay xmdpy = xmesa_init_display(dpy); Status stat; - pipe_mutex_lock(_xmesa_lock); + pipe_mutex_lock(xmdpy->mutex); XSync(b->xm_visual->display, 0); /* added for Chromium */ - stat = get_drawable_size(dpy, b->drawable, width, height); - pipe_mutex_unlock(_xmesa_lock); + stat = get_drawable_size(dpy, b->ws.drawable, width, height); + pipe_mutex_unlock(xmdpy->mutex); if (!stat) { /* probably querying a window that's recently been destroyed */ @@ -313,53 +327,51 @@ choose_pixel_format(XMesaVisual v) return PIPE_FORMAT_B5G6R5_UNORM; } - assert(0); - return 0; + return PIPE_FORMAT_NONE; } - /** - * Query the default gallium screen for a Z/Stencil format that - * at least matches the given depthBits and stencilBits. + * Choose a depth/stencil format that satisfies the given depth and + * stencil sizes. */ -static void -xmesa_choose_z_stencil_format(int depthBits, int stencilBits, - enum pipe_format *depthFormat, - enum pipe_format *stencilFormat) +static enum pipe_format +choose_depth_stencil_format(XMesaDisplay xmdpy, int depth, int stencil) { const enum pipe_texture_target target = PIPE_TEXTURE_2D; - const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + const unsigned tex_usage = PIPE_BIND_DEPTH_STENCIL; const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE | PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO); - static enum pipe_format formats[] = { - PIPE_FORMAT_S8Z24_UNORM, - PIPE_FORMAT_Z24S8_UNORM, - PIPE_FORMAT_Z16_UNORM, - PIPE_FORMAT_Z32_UNORM - }; - int i; + enum pipe_format formats[8], fmt; + int count, i; - assert(screen); + count = 0; - *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + if (depth <= 16 && stencil == 0) { + formats[count++] = PIPE_FORMAT_Z16_UNORM; + } + if (depth <= 24 && stencil == 0) { + formats[count++] = PIPE_FORMAT_X8Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24X8_UNORM; + } + if (depth <= 24 && stencil <= 8) { + formats[count++] = PIPE_FORMAT_S8_USCALED_Z24_UNORM; + formats[count++] = PIPE_FORMAT_Z24_UNORM_S8_USCALED; + } + if (depth <= 32 && stencil == 0) { + formats[count++] = PIPE_FORMAT_Z32_UNORM; + } - /* search for supported format */ - for (i = 0; i < Elements(formats); i++) { - if (screen->is_format_supported(screen, formats[i], + fmt = PIPE_FORMAT_NONE; + for (i = 0; i < count; i++) { + if (xmdpy->screen->is_format_supported(xmdpy->screen, formats[i], target, tex_usage, geom_flags)) { - *depthFormat = formats[i]; + fmt = formats[i]; break; } } - if (stencilBits) { - *stencilFormat = *depthFormat; - } - - /* XXX we should check that he chosen format has at least as many bits - * as what was requested. - */ + return fmt; } @@ -368,7 +380,7 @@ xmesa_choose_z_stencil_format(int depthBits, int stencilBits, /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ -XMesaBuffer XMesaBufferList = NULL; +static XMesaBuffer XMesaBufferList = NULL; /** @@ -386,53 +398,33 @@ static XMesaBuffer create_xmesa_buffer(Drawable d, BufferType type, XMesaVisual vis, Colormap cmap) { + XMesaDisplay xmdpy = xmesa_init_display(vis->display); XMesaBuffer b; - GLframebuffer *fb; - enum pipe_format colorFormat, depthFormat, stencilFormat; uint width, height; ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + if (!xmdpy) + return NULL; + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); if (!b) return NULL; - b->drawable = d; + b->ws.drawable = d; + b->ws.visual = vis->visinfo->visual; + b->ws.depth = vis->visinfo->depth; b->xm_visual = vis; b->type = type; b->cmap = cmap; - /* determine PIPE_FORMATs for buffers */ - colorFormat = choose_pixel_format(vis); - - xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits, - vis->mesa_visual.stencilBits, - &depthFormat, &stencilFormat); - - get_drawable_size(vis->display, d, &width, &height); /* * Create framebuffer, but we'll plug in our own renderbuffers below. */ - b->stfb = st_create_framebuffer(&vis->mesa_visual, - colorFormat, depthFormat, stencilFormat, - width, height, - (void *) b); - fb = &b->stfb->Base; - - /* - * Create scratch XImage for xmesa_display_surface() - */ - b->tempImage = XCreateImage(vis->display, - vis->visinfo->visual, - vis->visinfo->depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 32, /* bitmap_pad */ - 0); /* bytes_per_line */ + b->stfb = xmesa_create_st_framebuffer(xmdpy, b); /* GLX_EXT_texture_from_pixmap */ b->TextureTarget = 0; @@ -476,29 +468,21 @@ xmesa_free_buffer(XMesaBuffer buffer) for (b = XMesaBufferList; b; b = b->Next) { if (b == buffer) { - struct gl_framebuffer *fb = &buffer->stfb->Base; - /* unlink buffer from list */ if (prev) prev->Next = buffer->Next; else XMesaBufferList = buffer->Next; - /* mark as delete pending */ - fb->DeletePending = GL_TRUE; - /* Since the X window for the XMesaBuffer is going away, we don't * want to dereference this pointer in the future. */ - b->drawable = 0; - - buffer->tempImage->data = NULL; - XDestroyImage(buffer->tempImage); + b->ws.drawable = 0; - /* Unreference. If count = zero we'll really delete the buffer */ - _mesa_reference_framebuffer(&fb, NULL); - - XFreeGC(b->xm_visual->display, b->gc); + /* XXX we should move the buffer to a delete-pending list and destroy + * the buffer until it is no longer current. + */ + xmesa_destroy_st_framebuffer(buffer->stfb); free(buffer); @@ -576,21 +560,6 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); } - if (b && window) { - /* these should have been set in create_xmesa_buffer */ - ASSERT(b->drawable == window); - - /* Setup for single/double buffering */ - if (v->mesa_visual.doubleBufferMode) { - /* Double buffered */ - b->shm = xmesa_check_for_xshm( v->display ); - } - - /* X11 graphics context */ - b->gc = XCreateGC( v->display, window, 0, NULL ); - XSetFunction( v->display, b->gc, GXcopy ); - } - return GL_TRUE; } @@ -670,10 +639,12 @@ XMesaVisual XMesaCreateVisual( Display *display, GLint level, GLint visualCaveat ) { + XMesaDisplay xmdpy = xmesa_init_display(display); XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; - xmesa_init(); + if (!xmdpy) + return NULL; /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { @@ -755,6 +726,32 @@ XMesaVisual XMesaCreateVisual( Display *display, accum_blue_size, accum_alpha_size, 0 ); + v->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (stereo_flag) { + v->stvis.buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (db_flag) + v->stvis.buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + v->stvis.color_format = choose_pixel_format(v); + if (v->stvis.color_format == PIPE_FORMAT_NONE) { + FREE(v->visinfo); + FREE(v); + return NULL; + } + + v->stvis.depth_stencil_format = + choose_depth_stencil_format(xmdpy, depth_size, stencil_size); + + v->stvis.accum_format = (accum_red_size + + accum_green_size + accum_blue_size + accum_alpha_size) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + v->stvis.samples = num_samples; + v->stvis.render_buffer = ST_ATTACHMENT_INVALID; + /* XXX minor hack */ v->mesa_visual.level = level; return v; @@ -770,18 +767,12 @@ void XMesaDestroyVisual( XMesaVisual v ) /** - * Do one-time initializations. + * Do per-display initializations. */ void -xmesa_init(void) +xmesa_init( Display *display ) { - static GLboolean firstTime = GL_TRUE; - if (firstTime) { - pipe_mutex_init(_xmesa_lock); - _screen = driver.create_pipe_screen(); - screen = trace_screen_create( _screen ); - firstTime = GL_FALSE; - } + xmesa_init_display(display); } @@ -795,51 +786,33 @@ xmesa_init(void) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - struct pipe_context *pipe = NULL; + XMesaDisplay xmdpy = xmesa_init_display(v->display); XMesaContext c; - GLcontext *mesaCtx; - uint pf; - xmesa_init(); + if (!xmdpy) + return NULL; /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); if (!c) return NULL; - pf = choose_pixel_format(v); - assert(pf); - c->xm_visual = v; c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ c->xm_read_buffer = NULL; - if (screen == NULL) - goto fail; - - /* Trace screen knows how to properly wrap context creation in the - * wrapped screen, so nothing special to do here: - */ - pipe = screen->context_create(screen, (void *) c); - if (pipe == NULL) - goto fail; - - c->st = st_create_context(pipe, - &v->mesa_visual, - share_list ? share_list->st : NULL); + c->st = stapi->create_context(stapi, xmdpy->smapi, + &v->stvis, (share_list) ? share_list->st : NULL); if (c->st == NULL) goto fail; - mesaCtx = c->st->ctx; - c->st->ctx->DriverCtx = c; + c->st->st_manager_private = (void *) c; return c; fail: if (c->st) - st_destroy_context(c->st); - else if (pipe) - pipe->destroy(pipe); + c->st->destroy(c->st); free(c); return NULL; @@ -850,7 +823,7 @@ fail: PUBLIC void XMesaDestroyContext( XMesaContext c ) { - st_destroy_context(c->st); + c->st->destroy(c->st); /* FIXME: We should destroy the screen here, but if we do so, surfaces may * outlive it, causing segfaults @@ -956,7 +929,6 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, { GET_CURRENT_CONTEXT(ctx); XMesaBuffer b; - GLuint width, height; assert(v); @@ -964,19 +936,18 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, if (!b) return NULL; - /* get pixmap size, update framebuffer/renderbuffer dims */ - xmesa_get_window_size(v->display, b, &width, &height); - _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); + /* get pixmap size */ + xmesa_get_window_size(v->display, b, &b->width, &b->height); if (target == 0) { /* examine dims */ if (ctx->Extensions.ARB_texture_non_power_of_two) { target = GLX_TEXTURE_2D_EXT; } - else if ( _mesa_bitcount(width) == 1 - && _mesa_bitcount(height) == 1) { + else if ( _mesa_bitcount(b->width) == 1 + && _mesa_bitcount(b->height) == 1) { /* power of two size */ - if (height == 1) { + if (b->height == 1) { target = GLX_TEXTURE_1D_EXT; } else { @@ -1049,23 +1020,20 @@ XMesaDestroyBuffer(XMesaBuffer b) /** - * Query the current window size and update the corresponding GLframebuffer - * and all attached renderbuffers. - * Called when: - * 1. the first time a buffer is bound to a context. - * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... - * Note: it's possible (and legal) for xmctx to be NULL. That can happen - * when resizing a buffer when no rendering context is bound. + * Query the current drawable size and notify the binding context. */ void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +xmesa_check_buffer_size(XMesaBuffer b) { - GLuint width, height; - xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); - st_resize_framebuffer(drawBuffer->stfb, width, height); -} + XMesaContext xmctx = XMesaGetCurrentContext(); + if (b->type == PBUFFER) + return; + xmesa_get_window_size(b->xm_visual->display, b, &b->width, &b->height); + if (xmctx && xmctx->xm_buffer == b) + xmctx->st->notify_invalid_framebuffer(xmctx->st, b->stfb); +} /* @@ -1092,21 +1060,21 @@ GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, c->xm_read_buffer == readBuffer) return GL_TRUE; + xmesa_check_buffer_size(drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_buffer_size(readBuffer); + c->xm_buffer = drawBuffer; c->xm_read_buffer = readBuffer; - st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb); - - xmesa_check_and_update_buffer_size(c, drawBuffer); - if (readBuffer != drawBuffer) - xmesa_check_and_update_buffer_size(c, readBuffer); + stapi->make_current(stapi, c->st, drawBuffer->stfb, readBuffer->stfb); /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ drawBuffer->wasCurrent = GL_TRUE; } else { /* Detach */ - st_make_current( NULL, NULL, NULL ); + stapi->make_current(stapi, NULL, NULL, NULL); } return GL_TRUE; @@ -1125,14 +1093,8 @@ GLboolean XMesaUnbindContext( XMesaContext c ) XMesaContext XMesaGetCurrentContext( void ) { - GET_CURRENT_CONTEXT(ctx); - if (ctx) { - XMesaContext xmesa = xmesa_context(ctx); - return xmesa; - } - else { - return 0; - } + struct st_context_iface *st = stapi->get_current(stapi); + return (XMesaContext) (st) ? st->st_manager_private : NULL; } @@ -1144,21 +1106,17 @@ XMesaContext XMesaGetCurrentContext( void ) PUBLIC void XMesaSwapBuffers( XMesaBuffer b ) { - struct pipe_surface *frontLeftSurf; - - st_swapbuffers(b->stfb, &frontLeftSurf, NULL); - - if (frontLeftSurf) { - if (_screen != screen) { - struct trace_surface *tr_surf = trace_surface( frontLeftSurf ); - struct pipe_surface *surf = tr_surf->surface; - frontLeftSurf = surf; - } - - driver.display_surface(b, frontLeftSurf); + XMesaContext xmctx = XMesaGetCurrentContext(); + + if (xmctx && xmctx->xm_buffer == b) { + xmctx->st->flush( xmctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); } - xmesa_check_and_update_buffer_size(NULL, b); + xmesa_swap_st_framebuffer(b->stfb); } @@ -1168,21 +1126,9 @@ void XMesaSwapBuffers( XMesaBuffer b ) */ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) { - struct pipe_surface *surf_front; - struct pipe_surface *surf_back; - struct pipe_context *pipe = NULL; /* XXX fix */ - - st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); - st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); - - if (!surf_front || !surf_back) - return; - - assert(pipe); - pipe->surface_copy(pipe, - surf_front, x, y, /* dest */ - surf_back, x, y, /* src */ - width, height); + xmesa_copy_st_framebuffer(b->stfb, + ST_ATTACHMENT_BACK_LEFT, ST_ATTACHMENT_FRONT_LEFT, + x, y, width, height); } @@ -1190,7 +1136,14 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) void XMesaFlush( XMesaContext c ) { if (c && c->xm_visual->display) { - st_finish(c->st); + XMesaDisplay xmdpy = xmesa_init_display(c->xm_visual->display); + struct pipe_fence_handle *fence = NULL; + + c->st->flush(c->st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + if (fence) { + xmdpy->screen->fence_finish(xmdpy->screen, fence, 0); + xmdpy->screen->fence_reference(xmdpy->screen, &fence, NULL); + } XSync( c->xm_visual->display, False ); } } @@ -1203,7 +1156,7 @@ XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) { XMesaBuffer b; for (b = XMesaBufferList; b; b = b->Next) { - if (b->drawable == d && b->xm_visual->display == dpy) { + if (b->ws.drawable == d && b->xm_visual->display == dpy) { return b; } } @@ -1237,10 +1190,10 @@ void XMesaGarbageCollect( void ) next = b->Next; if (b->xm_visual && b->xm_visual->display && - b->drawable && + b->ws.drawable && b->type == WINDOW) { XSync(b->xm_visual->display, False); - if (!window_exists( b->xm_visual->display, b->drawable )) { + if (!window_exists( b->xm_visual->display, b->ws.drawable )) { /* found a dead window, free the ancillary info */ XMesaDestroyBuffer( b ); } @@ -1264,3 +1217,10 @@ XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) { } + +void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask) +{ + if (dst->st->copy) + dst->st->copy(dst->st, src->st, mask); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index 004cb260dcd..4f2c8a6e6a9 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -58,25 +58,31 @@ and create a window, you must do the following to use the X/Mesa interface: #include "main/mtypes.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" +#include "state_tracker/st_api.h" #include "os/os_thread.h" +#include "state_tracker/xlib_sw_winsys.h" # include <X11/Xlib.h> # include <X11/Xlibint.h> # include <X11/Xutil.h> -# ifdef USE_XSHM /* was SHM */ -# include <sys/ipc.h> -# include <sys/shm.h> -# include <X11/extensions/XShm.h> -# endif +typedef struct xmesa_display *XMesaDisplay; typedef struct xmesa_buffer *XMesaBuffer; typedef struct xmesa_context *XMesaContext; typedef struct xmesa_visual *XMesaVisual; +struct xmesa_display { + pipe_mutex mutex; + + Display *display; + struct pipe_screen *screen; + struct st_manager *smapi; + + struct pipe_context *pipe; +}; + /* * Create a new X/Mesa visual. @@ -262,16 +268,13 @@ XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, int format, int target, int mipmap); +extern void +XMesaCopyContext(XMesaContext src, XMesaContext dst, unsigned long mask); /*********************************************************************** */ -extern pipe_mutex _xmesa_lock; - -extern struct xmesa_buffer *XMesaBufferList; - - /** * Visual inforation, derived from GLvisual. * Basically corresponds to an XVisualInfo. @@ -284,6 +287,8 @@ struct xmesa_visual { GLint BitsPerPixel; /* True bits per pixel for XImages */ GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + struct st_visual stvis; }; @@ -292,7 +297,7 @@ struct xmesa_visual { * Basically corresponds to a GLXContext. */ struct xmesa_context { - struct st_context *st; + struct st_context_iface *st; XMesaVisual xm_visual; /** pixel format info */ XMesaBuffer xm_buffer; /** current drawbuffer */ XMesaBuffer xm_read_buffer; /** current readbuffer */ @@ -315,7 +320,8 @@ typedef enum { * Basically corresponds to a GLXDrawable. */ struct xmesa_buffer { - struct st_framebuffer *stfb; + struct st_framebuffer_iface *stfb; + struct xlib_drawable ws; GLboolean wasCurrent; /* was ever the current buffer? */ XMesaVisual xm_visual; /* the X/Mesa visual */ @@ -329,13 +335,6 @@ struct xmesa_buffer { XImage *tempImage; unsigned long selectedEvents;/* for pbuffers only */ - GLuint shm; /* X Shared Memory extension status: */ - /* 0 = not available */ - /* 1 = XImage support available */ - /* 2 = Pixmap support available too */ -#if defined(USE_XSHM) - XShmSegmentInfo shminfo; -#endif GC gc; /* scratch GC for span, line, tri drawing */ @@ -345,32 +344,14 @@ struct xmesa_buffer { GLint TextureMipmap; /** 0 or 1 */ struct xmesa_buffer *Next; /* Linked list pointer: */ -}; + unsigned width, height; +}; -/** cast wrapper */ -static INLINE XMesaContext -xmesa_context(GLcontext *ctx) -{ - return (XMesaContext) ctx->DriverCtx; -} - - -/** cast wrapper */ -static INLINE XMesaBuffer -xmesa_buffer(GLframebuffer *fb) -{ - struct st_framebuffer *stfb = (struct st_framebuffer *) fb; - return (XMesaBuffer) st_framebuffer_private(stfb); -} - - -extern void -xmesa_init(void); extern void -xmesa_delete_framebuffer(struct gl_framebuffer *fb); +xmesa_init(Display *dpy); extern XMesaBuffer xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); @@ -380,7 +361,7 @@ xmesa_get_window_size(Display *dpy, XMesaBuffer b, GLuint *width, GLuint *height); extern void -xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer); +xmesa_check_buffer_size(XMesaBuffer b); extern void xmesa_destroy_buffers_on_display(Display *dpy); @@ -388,17 +369,15 @@ xmesa_destroy_buffers_on_display(Display *dpy); static INLINE GLuint xmesa_buffer_width(XMesaBuffer b) { - return b->stfb->Base.Width; + return b->width; } static INLINE GLuint xmesa_buffer_height(XMesaBuffer b) { - return b->stfb->Base.Height; + return b->height; } -extern int -xmesa_check_for_xshm(Display *display); #endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_winsys.h b/src/gallium/state_trackers/glx/xlib/xm_public.h index 4bd5b5c8d3b..950eb21521f 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_winsys.h +++ b/src/gallium/state_trackers/glx/xlib/xm_public.h @@ -26,27 +26,23 @@ * **************************************************************************/ -#ifndef XM_WINSYS_H -#define XM_WINSYS_H +#ifndef XM_PUBLIC_H +#define XM_PUBLIC_H -struct pipe_context; -struct pipe_screen; -struct pipe_surface; -struct xmesa_buffer; +#include <X11/Xlib.h> +struct pipe_screen; +struct st_api; +/* This is the driver interface required by the glx/xlib state tracker. + */ struct xm_driver { - - struct pipe_screen *(*create_pipe_screen)( void ); - - void (*display_surface)( struct xmesa_buffer *, - struct pipe_surface * ); - + struct pipe_screen *(*create_pipe_screen)( Display *display ); + struct st_api *(*create_st_api)( void ); }; - extern void xmesa_set_driver( const struct xm_driver *driver ); -#endif +#endif /* XM_PUBLIC_H */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.c b/src/gallium/state_trackers/glx/xlib/xm_st.c new file mode 100644 index 00000000000..1c678b4f760 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.c @@ -0,0 +1,340 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "xm_api.h" +#include "xm_st.h" + +struct xmesa_st_framebuffer { + XMesaDisplay display; + XMesaBuffer buffer; + struct pipe_screen *screen; + + struct st_visual stvis; + + unsigned texture_width, texture_height, texture_mask; + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + + struct pipe_surface *display_surface; +}; + +static INLINE struct xmesa_st_framebuffer * +xmesa_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + return (struct xmesa_st_framebuffer *) stfbi->st_manager_private; +} + +/** + * Display an attachment to the xlib_drawable of the framebuffer. + */ +static boolean +xmesa_st_framebuffer_display(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *ptex = xstfb->textures[statt]; + struct pipe_surface *psurf; + + if (!ptex) + return TRUE; + + psurf = xstfb->display_surface; + /* (re)allocate the surface for the texture to be displayed */ + if (!psurf || psurf->texture != ptex) { + pipe_surface_reference(&xstfb->display_surface, NULL); + + psurf = xstfb->screen->get_tex_surface(xstfb->screen, + ptex, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET); + if (!psurf) + return FALSE; + + xstfb->display_surface = psurf; + } + + xstfb->screen->flush_frontbuffer(xstfb->screen, psurf, &xstfb->buffer->ws); + + return TRUE; +} + +/** + * Copy the contents between the attachments. + */ +static void +xmesa_st_framebuffer_copy_textures(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src_statt, + enum st_attachment_type dst_statt, + unsigned x, unsigned y, + unsigned width, unsigned height) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource *src_ptex = xstfb->textures[src_statt]; + struct pipe_resource *dst_ptex = xstfb->textures[dst_statt]; + struct pipe_surface *src, *dst; + struct pipe_context *pipe; + + if (!src_ptex || !dst_ptex) + return; + + pipe = xstfb->display->pipe; + if (!pipe) { + pipe = xstfb->screen->context_create(xstfb->screen, NULL); + if (!pipe) + return; + xstfb->display->pipe = pipe; + } + + src = xstfb->screen->get_tex_surface(xstfb->screen, + src_ptex, 0, 0, 0, PIPE_BIND_BLIT_SOURCE); + dst = xstfb->screen->get_tex_surface(xstfb->screen, + dst_ptex, 0, 0, 0, PIPE_BIND_BLIT_DESTINATION); + + if (src && dst) + pipe->surface_copy(pipe, dst, x, y, src, x, y, width, height); + + pipe_surface_reference(&src, NULL); + pipe_surface_reference(&dst, NULL); +} + +/** + * Remove outdated textures and create the requested ones. + */ +static boolean +xmesa_st_framebuffer_validate_textures(struct st_framebuffer_iface *stfbi, + unsigned width, unsigned height, + unsigned mask) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + struct pipe_resource templ; + enum st_attachment_type i; + + /* remove outdated textures */ + if (xstfb->texture_width != width || xstfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (xstfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (xstfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + format = xstfb->stvis.color_format; + bind = PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = xstfb->stvis.depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.bind = bind; + + xstfb->textures[i] = + xstfb->screen->resource_create(xstfb->screen, &templ); + if (!xstfb->textures[i]) + return FALSE; + } + } + + xstfb->texture_width = width; + xstfb->texture_height = height; + xstfb->texture_mask = mask; + + return TRUE; +} + +static boolean +xmesa_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + unsigned statt_mask, new_mask, i; + boolean resized; + boolean ret; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + /* record newly allocated textures */ + new_mask = statt_mask & ~xstfb->texture_mask; + + resized = (xstfb->buffer->width != xstfb->texture_width || + xstfb->buffer->height != xstfb->texture_height); + + /* revalidate textures */ + if (resized || new_mask) { + ret = xmesa_st_framebuffer_validate_textures(stfbi, + xstfb->buffer->width, xstfb->buffer->height, statt_mask); + if (!ret) + return ret; + + if (!resized) { + enum st_attachment_type back, front; + + back = ST_ATTACHMENT_BACK_LEFT; + front = ST_ATTACHMENT_FRONT_LEFT; + /* copy the contents if front is newly allocated and back is not */ + if ((statt_mask & (1 << back)) && + (new_mask & (1 << front)) && + !(new_mask & (1 << back))) { + xmesa_st_framebuffer_copy_textures(stfbi, back, front, + 0, 0, xstfb->texture_width, xstfb->texture_height); + } + } + } + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], xstfb->textures[statts[i]]); + } + + return TRUE; +} + +static boolean +xmesa_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, statt); + if (ret) + xmesa_check_buffer_size(xstfb->buffer); + + return ret; +} + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b) +{ + struct st_framebuffer_iface *stfbi; + struct xmesa_st_framebuffer *xstfb; + + assert(xmdpy->display == b->xm_visual->display); + + stfbi = CALLOC_STRUCT(st_framebuffer_iface); + xstfb = CALLOC_STRUCT(xmesa_st_framebuffer); + if (!stfbi || !xstfb) { + if (stfbi) + FREE(stfbi); + if (xstfb) + FREE(xstfb); + return NULL; + } + + xstfb->display = xmdpy; + xstfb->buffer = b; + xstfb->screen = xmdpy->screen; + xstfb->stvis = b->xm_visual->stvis; + + stfbi->visual = &xstfb->stvis; + stfbi->flush_front = xmesa_st_framebuffer_flush_front; + stfbi->validate = xmesa_st_framebuffer_validate; + stfbi->st_manager_private = (void *) xstfb; + + return stfbi; +} + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + int i; + + pipe_surface_reference(&xstfb->display_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&xstfb->textures[i], NULL); + + FREE(xstfb); + FREE(stfbi); +} + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi) +{ + struct xmesa_st_framebuffer *xstfb = xmesa_st_framebuffer(stfbi); + boolean ret; + + ret = xmesa_st_framebuffer_display(stfbi, ST_ATTACHMENT_BACK_LEFT); + if (ret) { + struct pipe_resource **front, **back, *tmp; + + front = &xstfb->textures[ST_ATTACHMENT_FRONT_LEFT]; + back = &xstfb->textures[ST_ATTACHMENT_BACK_LEFT]; + /* swap textures only if the front texture has been allocated */ + if (*front) { + tmp = *front; + *front = *back; + *back = tmp; + } + + xmesa_check_buffer_size(xstfb->buffer); + } +} + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h) +{ + xmesa_st_framebuffer_copy_textures(stfbi, src, dst, x, y, w, h); + if (dst == ST_ATTACHMENT_FRONT_LEFT) + xmesa_st_framebuffer_display(stfbi, dst); +} diff --git a/src/gallium/state_trackers/glx/xlib/xm_st.h b/src/gallium/state_trackers/glx/xlib/xm_st.h new file mode 100644 index 00000000000..862597617e3 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_st.h @@ -0,0 +1,52 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef _XM_ST_H_ +#define _XM_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" + +#include "xm_api.h" + +struct st_framebuffer_iface * +xmesa_create_st_framebuffer(XMesaDisplay xmdpy, XMesaBuffer b); + +void +xmesa_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_swap_st_framebuffer(struct st_framebuffer_iface *stfbi); + +void +xmesa_copy_st_framebuffer(struct st_framebuffer_iface *stfbi, + enum st_attachment_type src, + enum st_attachment_type dst, + int x, int y, int w, int h); + +#endif /* _XM_ST_H_ */ diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript index 527e065cd91..aadeaa0a359 100644 --- a/src/gallium/state_trackers/python/SConscript +++ b/src/gallium/state_trackers/python/SConscript @@ -24,6 +24,7 @@ if 'python' in env['statetrackers']: 'ws2_32', ]) else: + env.Append(CPPDEFINES = ['GCC_HASCLASSVISIBILITY']) env.Append(LIBS = [ 'GL', 'X11', @@ -33,31 +34,26 @@ if 'python' in env['statetrackers']: 'gallium.i', 'st_device.c', 'st_sample.c', + 'st_hardpipe_winsys.c', + 'st_softpipe_winsys.c', ] - drivers = [ - trace - ] - - if 'llvmpipe' in env['drivers']: - env.Tool('llvm') - sources += ['st_llvmpipe_winsys.c'] - drivers += [llvmpipe] - else: - sources += ['st_softpipe_winsys.c'] - drivers += [softpipe] + env.Prepend(LIBS = [ + ws_null, + trace, + gallium, + ]) - pyst = env.ConvenienceLibrary( - target = 'pyst', - source = sources, - ) + if env['llvm']: + env.Append(CPPDEFINES = ['HAVE_LLVMPIPE']) + env.Prepend(LIBS = [llvmpipe]) + if True: + env.Append(CPPDEFINES = ['HAVE_SOFTPIPE']) + env.Prepend(LIBS = [softpipe]) env['no_import_lib'] = 1 env.SharedLibrary( target = '_gallium', - source = [ - 'st_hardpipe_winsys.c', - ], - LIBS = [pyst] + drivers + gallium + env['LIBS'], + source = sources, ) diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i index ffb084e358b..c6084f78aee 100644 --- a/src/gallium/state_trackers/python/gallium.i +++ b/src/gallium/state_trackers/python/gallium.i @@ -49,6 +49,7 @@ #include "util/u_format.h" #include "util/u_dump.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" #include "tgsi/tgsi_text.h" #include "tgsi/tgsi_dump.h" @@ -71,9 +72,8 @@ %rename(Device) st_device; %rename(Context) st_context; -%rename(Texture) pipe_texture; +%rename(Resource) pipe_resource; %rename(Surface) st_surface; -%rename(Buffer) pipe_buffer; %rename(BlendColor) pipe_blend_color; %rename(Blend) pipe_blend_state; @@ -94,7 +94,7 @@ %include "p_compiler.i" -%include "p_defines.h"; +%include "p_defines.h" %include "p_format.h" %include "p_device.i" @@ -102,3 +102,4 @@ %include "p_texture.i" %include "p_state.i" +%include "u_format.i" diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index 3f36ccb6217..3c5509cb5e4 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -51,7 +51,7 @@ struct st_context { void set_blend( const struct pipe_blend_state *state ) { cso_set_blend($self->cso, state); } - + void set_fragment_sampler( unsigned index, const struct pipe_sampler_state *state ) { cso_single_sampler($self->cso, index, state); cso_single_sampler_done($self->cso); @@ -127,6 +127,45 @@ struct st_context { $self->gs = gs; } + struct pipe_sampler_view * + create_sampler_view(struct pipe_resource *texture, + enum pipe_format format = PIPE_FORMAT_NONE, + unsigned first_level = 0, + unsigned last_level = ~0, + unsigned swizzle_r = 0, + unsigned swizzle_g = 1, + unsigned swizzle_b = 2, + unsigned swizzle_a = 3) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_sampler_view templat; + + memset(&templat, 0, sizeof templat); + if (format == PIPE_FORMAT_NONE) { + templat.format = texture->format; + } else { + templat.format = format; + } + templat.last_level = MIN2(last_level, texture->last_level); + templat.first_level = first_level; + templat.last_level = last_level; + templat.swizzle_r = swizzle_r; + templat.swizzle_g = swizzle_g; + templat.swizzle_b = swizzle_b; + templat.swizzle_a = swizzle_a; + + return pipe->create_sampler_view(pipe, texture, &templat); + } + + void + sampler_view_destroy(struct pipe_context *ctx, + struct pipe_sampler_view *view) + { + struct pipe_context *pipe = $self->pipe; + + pipe->sampler_view_destroy(pipe, view); + } + /* * Parameter-like state (or properties) */ @@ -144,7 +183,7 @@ struct st_context { } void set_constant_buffer(unsigned shader, unsigned index, - struct pipe_buffer *buffer ) + struct pipe_resource *buffer ) { $self->pipe->set_constant_buffer($self->pipe, shader, index, buffer); } @@ -167,31 +206,68 @@ struct st_context { cso_set_viewport($self->cso, state); } + void set_fragment_sampler_view(unsigned index, + struct pipe_sampler_view *view) + { + pipe_sampler_view_reference(&$self->fragment_sampler_views[index], view); + + $self->pipe->set_fragment_sampler_views($self->pipe, + PIPE_MAX_SAMPLERS, + $self->fragment_sampler_views); + } + + void set_vertex_sampler_view(unsigned index, + struct pipe_sampler_view *view) + { + pipe_sampler_view_reference(&$self->vertex_sampler_views[index], view); + + $self->pipe->set_vertex_sampler_views($self->pipe, + PIPE_MAX_VERTEX_SAMPLERS, + $self->vertex_sampler_views); + } + void set_fragment_sampler_texture(unsigned index, - struct pipe_texture *texture) { + struct pipe_resource *texture) { + struct pipe_sampler_view templ; + if(!texture) texture = $self->default_texture; - pipe_texture_reference(&$self->fragment_sampler_textures[index], texture); - $self->pipe->set_fragment_sampler_textures($self->pipe, - PIPE_MAX_SAMPLERS, - $self->fragment_sampler_textures); + pipe_sampler_view_reference(&$self->fragment_sampler_views[index], NULL); + u_sampler_view_default_template(&templ, + texture, + texture->format); + $self->fragment_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe, + texture, + &templ); + $self->pipe->set_fragment_sampler_views($self->pipe, + PIPE_MAX_SAMPLERS, + $self->fragment_sampler_views); } void set_vertex_sampler_texture(unsigned index, - struct pipe_texture *texture) { + struct pipe_resource *texture) { + struct pipe_sampler_view templ; + if(!texture) texture = $self->default_texture; - pipe_texture_reference(&$self->vertex_sampler_textures[index], texture); - $self->pipe->set_vertex_sampler_textures($self->pipe, - PIPE_MAX_VERTEX_SAMPLERS, - $self->vertex_sampler_textures); + pipe_sampler_view_reference(&$self->vertex_sampler_views[index], NULL); + u_sampler_view_default_template(&templ, + texture, + texture->format); + $self->vertex_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe, + texture, + &templ); + + $self->pipe->set_vertex_sampler_views($self->pipe, + PIPE_MAX_VERTEX_SAMPLERS, + $self->vertex_sampler_views); } void set_vertex_buffer(unsigned index, unsigned stride, unsigned max_index, unsigned buffer_offset, - struct pipe_buffer *buffer) + struct pipe_resource *buffer) { unsigned i; struct pipe_vertex_buffer state; @@ -222,9 +298,9 @@ struct st_context { void set_vertex_elements(unsigned num) { $self->num_vertex_elements = num; - $self->pipe->set_vertex_elements($self->pipe, - $self->num_vertex_elements, - $self->vertex_elements); + cso_set_vertex_elements($self->cso, + $self->num_vertex_elements, + $self->vertex_elements); } /* @@ -235,23 +311,25 @@ struct st_context { $self->pipe->draw_arrays($self->pipe, mode, start, count); } - void draw_elements( struct pipe_buffer *indexBuffer, - unsigned indexSize, + void draw_elements( struct pipe_resource *indexBuffer, + unsigned indexSize, int indexBias, unsigned mode, unsigned start, unsigned count) { $self->pipe->draw_elements($self->pipe, indexBuffer, indexSize, + indexBias, mode, start, count); } - void draw_range_elements( struct pipe_buffer *indexBuffer, - unsigned indexSize, unsigned minIndex, unsigned maxIndex, + void draw_range_elements( struct pipe_resource *indexBuffer, + unsigned indexSize, int indexBias, + unsigned minIndex, unsigned maxIndex, unsigned mode, unsigned start, unsigned count) { $self->pipe->draw_range_elements($self->pipe, - indexBuffer, - indexSize, minIndex, maxIndex, + indexBuffer, indexSize, indexBias, + minIndex, maxIndex, mode, start, count); } @@ -262,34 +340,66 @@ struct st_context { { struct pipe_context *pipe = $self->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_buffer *vbuf; + struct pipe_resource *vbuf; + struct pipe_transfer *transfer; + struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS]; + struct pipe_vertex_buffer vbuffer; float *map; unsigned size; + unsigned i; size = num_verts * num_attribs * 4 * sizeof(float); vbuf = pipe_buffer_create(screen, - 32, - PIPE_BUFFER_USAGE_VERTEX, + PIPE_BIND_VERTEX_BUFFER, size); if(!vbuf) goto error1; - - map = pipe_buffer_map(screen, vbuf, PIPE_BUFFER_USAGE_CPU_WRITE); + + map = pipe_buffer_map(pipe, vbuf, PIPE_TRANSFER_WRITE, &transfer); if (!map) goto error2; memcpy(map, vertices, size); - pipe_buffer_unmap(screen, vbuf); - - util_draw_vertex_buffer(pipe, vbuf, 0, prim, num_verts, num_attribs); - + pipe_buffer_unmap(pipe, vbuf, transfer); + + cso_save_vertex_elements($self->cso); + + /* tell pipe about the vertex attributes */ + for (i = 0; i < num_attribs; i++) { + velements[i].src_offset = i * 4 * sizeof(float); + velements[i].instance_divisor = 0; + velements[i].vertex_buffer_index = 0; + velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + cso_set_vertex_elements($self->cso, num_attribs, velements); + + /* tell pipe about the vertex buffer */ + memset(&vbuffer, 0, sizeof(vbuffer)); + vbuffer.buffer = vbuf; + vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */ + vbuffer.buffer_offset = 0; + vbuffer.max_index = num_verts - 1; + pipe->set_vertex_buffers(pipe, 1, &vbuffer); + + /* draw */ + pipe->draw_arrays(pipe, prim, 0, num_verts); + + cso_restore_vertex_elements($self->cso); + error2: - pipe_buffer_reference(&vbuf, NULL); + pipe_resource_reference(&vbuf, NULL); error1: ; } void + clear(unsigned buffers, const float *rgba, double depth = 0.0f, + unsigned stencil = 0) + { + $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil); + } + + void flush(unsigned flags = 0) { struct pipe_fence_handle *fence = NULL; $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence); @@ -313,11 +423,11 @@ error1: struct pipe_surface *_dst = NULL; struct pipe_surface *_src = NULL; - _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE); + _dst = st_pipe_surface(dst, PIPE_BIND_BLIT_DESTINATION); if(!_dst) SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing"); - _src = st_pipe_surface(src, PIPE_BUFFER_USAGE_GPU_READ); + _src = st_pipe_surface(src, PIPE_BIND_BLIT_SOURCE); if(!_src) SWIG_exception(SWIG_ValueError, "couldn't acquire source surface for reading"); @@ -335,7 +445,7 @@ error1: { struct pipe_surface *_dst = NULL; - _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE); + _dst = st_pipe_surface(dst, PIPE_BIND_BLIT_DESTINATION); if(!_dst) SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing"); @@ -345,10 +455,303 @@ error1: pipe_surface_reference(&_dst, NULL); } - void clear(unsigned buffers, const float *rgba, double depth = 0.0f, - unsigned stencil = 0) + %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); + void + surface_read_raw(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + char **STRING, int *LENGTH) { - $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil); + struct pipe_resource *texture = surface->texture; + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + unsigned stride; + + stride = util_format_get_stride(texture->format, w); + *LENGTH = util_format_get_nblocksy(texture->format, h) * stride; + *STRING = (char *) malloc(*LENGTH); + if(!*STRING) + return; + + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_READ, + x, y, w, h); + if(transfer) { + pipe_get_tile_raw(pipe, transfer, 0, 0, w, h, *STRING, stride); + pipe->transfer_destroy(pipe, transfer); + } + } + + %cstring_input_binary(const char *STRING, unsigned LENGTH); + void + surface_write_raw(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + const char *STRING, unsigned LENGTH, unsigned stride = 0) + { + struct pipe_resource *texture = surface->texture; + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + + if(stride == 0) + stride = util_format_get_stride(texture->format, w); + + if(LENGTH < util_format_get_nblocksy(texture->format, h) * stride) + SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); + + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_WRITE, + x, y, w, h); + if(!transfer) + SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer"); + + pipe_put_tile_raw(pipe, transfer, 0, 0, w, h, STRING, stride); + pipe->transfer_destroy(pipe, transfer); + + fail: + return; + } + + void + surface_read_rgba(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + float *rgba) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_READ, + x, y, w, h); + if(transfer) { + pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba); + pipe->transfer_destroy(pipe, transfer); + } + } + + void + surface_write_rgba(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + const float *rgba) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_WRITE, + x, y, w, h); + if(transfer) { + pipe_put_tile_rgba(pipe, transfer, 0, 0, w, h, rgba); + pipe->transfer_destroy(pipe, transfer); + } + } + + %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); + void + surface_read_rgba8(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + char **STRING, int *LENGTH) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + float *rgba; + unsigned char *rgba8; + unsigned i, j, k; + + *LENGTH = 0; + *STRING = NULL; + + if (!surface) + return; + + *LENGTH = h*w*4; + *STRING = (char *) malloc(*LENGTH); + if(!*STRING) + return; + + rgba = malloc(h*w*4*sizeof(float)); + if(!rgba) + return; + + rgba8 = (unsigned char *) *STRING; + + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_READ, + x, y, w, h); + if(transfer) { + pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba); + for(j = 0; j < h; ++j) { + for(i = 0; i < w; ++i) + for(k = 0; k <4; ++k) + rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]); + } + pipe->transfer_destroy(pipe, transfer); + } + + free(rgba); + } + + void + surface_read_z(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + unsigned *z) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_READ, + x, y, w, h); + if(transfer) { + pipe_get_tile_z(pipe, transfer, 0, 0, w, h, z); + pipe->transfer_destroy(pipe, transfer); + } + } + + void + surface_write_z(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + const unsigned *z) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_WRITE, + x, y, w, h); + if(transfer) { + pipe_put_tile_z(pipe, transfer, 0, 0, w, h, z); + pipe->transfer_destroy(pipe, transfer); + } + } + + void + surface_sample_rgba(struct st_surface *surface, + float *rgba, + int norm = 0) + { + st_sample_surface($self->pipe, surface, rgba, norm != 0); + } + + unsigned + surface_compare_rgba(struct st_surface *surface, + unsigned x, unsigned y, unsigned w, unsigned h, + const float *rgba, float tol = 0.0) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_transfer *transfer; + float *rgba2; + const float *p1; + const float *p2; + unsigned i, j, n; + + rgba2 = MALLOC(h*w*4*sizeof(float)); + if(!rgba2) + return ~0; + + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_READ, + x, y, w, h); + if(!transfer) { + FREE(rgba2); + return ~0; + } + + pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba2); + pipe->transfer_destroy(pipe, transfer); + + p1 = rgba; + p2 = rgba2; + n = 0; + for(i = h*w; i; --i) { + unsigned differs = 0; + for(j = 4; j; --j) { + float delta = *p2++ - *p1++; + if (delta < -tol || delta > tol) + differs = 1; + } + n += differs; + } + + FREE(rgba2); + + return n; + } + + %cstring_input_binary(const char *STRING, unsigned LENGTH); + void + transfer_inline_write(struct pipe_resource *resource, + struct pipe_subresource *sr, + unsigned usage, + const struct pipe_box *box, + const char *STRING, unsigned LENGTH, + unsigned stride, + unsigned slice_stride) + { + struct pipe_context *pipe = $self->pipe; + + pipe->transfer_inline_write(pipe, resource, *sr, usage, box, STRING, stride, slice_stride); + } + + %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); + void buffer_read(struct pipe_resource *buffer, + char **STRING, int *LENGTH) + { + struct pipe_context *pipe = $self->pipe; + + assert(buffer->target == PIPE_BUFFER); + + *LENGTH = buffer->width0; + *STRING = (char *) malloc(buffer->width0); + if(!*STRING) + return; + + pipe_buffer_read(pipe, buffer, 0, buffer->width0, *STRING); + } + + void buffer_write(struct pipe_resource *buffer, + const char *STRING, unsigned LENGTH, unsigned offset = 0) + { + struct pipe_context *pipe = $self->pipe; + + assert(buffer->target == PIPE_BUFFER); + + if(offset > buffer->width0) + SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); + + if(offset + LENGTH > buffer->width0) + SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer"); + + pipe_buffer_write(pipe, buffer, offset, LENGTH, STRING); + +fail: + return; } }; diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i index 0eba488a078..959c13f54d9 100644 --- a/src/gallium/state_trackers/python/p_device.i +++ b/src/gallium/state_trackers/python/p_device.i @@ -81,20 +81,20 @@ struct st_device { /** * Check if the given pipe_format is supported as a texture or * drawing surface. - * \param type one of PIPE_TEXTURE, PIPE_SURFACE + * \param bind bitmask of PIPE_BIND flags */ int is_format_supported( enum pipe_format format, enum pipe_texture_target target, - unsigned tex_usage, + unsigned bind, unsigned geom_flags ) { /* We can't really display surfaces with the python statetracker so mask * out that usage */ - tex_usage &= ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + bind &= ~PIPE_BIND_DISPLAY_TARGET; return $self->screen->is_format_supported( $self->screen, format, target, - tex_usage, + bind, geom_flags ); } @@ -103,21 +103,21 @@ struct st_device { return st_context_create($self); } - struct pipe_texture * - texture_create( + struct pipe_resource * + resource_create( enum pipe_format format, unsigned width, unsigned height, unsigned depth = 1, unsigned last_level = 0, enum pipe_texture_target target = PIPE_TEXTURE_2D, - unsigned tex_usage = 0 + unsigned bind = 0 ) { - struct pipe_texture templat; + struct pipe_resource templat; /* We can't really display surfaces with the python statetracker so mask * out that usage */ - tex_usage &= ~PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + bind &= ~PIPE_BIND_DISPLAY_TARGET; memset(&templat, 0, sizeof(templat)); templat.format = format; @@ -126,14 +126,13 @@ struct st_device { templat.depth0 = depth; templat.last_level = last_level; templat.target = target; - templat.tex_usage = tex_usage; + templat.bind = bind; - return $self->screen->texture_create($self->screen, &templat); - } - - struct pipe_buffer * - buffer_create(unsigned size, unsigned alignment = 0, unsigned usage = 0) { - return pipe_buffer_create($self->screen, alignment, usage, size); + return $self->screen->resource_create($self->screen, &templat); } + struct pipe_resource * + buffer_create(unsigned size, unsigned bind = 0) { + return pipe_buffer_create($self->screen, bind, size); + } }; diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i index eda77b56f8e..c1e6ea1b43c 100644 --- a/src/gallium/state_trackers/python/p_state.i +++ b/src/gallium/state_trackers/python/p_state.i @@ -114,7 +114,7 @@ SWIG_exception(SWIG_ValueError, "index out of bounds"); if(surface) { - _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE); + _surface = st_pipe_surface(surface, PIPE_BIND_RENDER_TARGET); if(!_surface) SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing"); } @@ -131,7 +131,7 @@ struct pipe_surface *_surface = NULL; if(surface) { - _surface = st_pipe_surface(surface, PIPE_BUFFER_USAGE_GPU_WRITE); + _surface = st_pipe_surface(surface, PIPE_BIND_DEPTH_STENCIL); if(!_surface) SWIG_exception(SWIG_ValueError, "couldn't acquire surface for writing"); } diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i index 761587dc533..ae506944c45 100644 --- a/src/gallium/state_trackers/python/p_texture.i +++ b/src/gallium/state_trackers/python/p_texture.i @@ -33,325 +33,105 @@ */ -%nodefaultctor pipe_texture; +%nodefaultctor pipe_resource; %nodefaultctor st_surface; -%nodefaultctor pipe_buffer; -%nodefaultdtor pipe_texture; +%nodefaultdtor pipe_resource; %nodefaultdtor st_surface; -%nodefaultdtor pipe_buffer; -%ignore pipe_texture::screen; +%ignore pipe_resource::screen; %immutable st_surface::texture; %immutable st_surface::face; %immutable st_surface::level; %immutable st_surface::zslice; -%newobject pipe_texture::get_surface; +%newobject pipe_resource::get_surface; +/* Avoid naming conflict with p_inlines.h's pipe_buffer_read/write */ +%rename(read) read_; +%rename(write) write_; -%extend pipe_texture { - - ~pipe_texture() { - struct pipe_texture *ptr = $self; - pipe_texture_reference(&ptr, NULL); +%extend pipe_resource { + + ~pipe_resource() { + struct pipe_resource *ptr = $self; + pipe_resource_reference(&ptr, NULL); } - + unsigned get_width(unsigned level=0) { return u_minify($self->width0, level); } - + unsigned get_height(unsigned level=0) { return u_minify($self->height0, level); } - + unsigned get_depth(unsigned level=0) { return u_minify($self->depth0, level); } - + /** Get a surface which is a "view" into a texture */ struct st_surface * get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0) { struct st_surface *surface; - + if(face >= ($self->target == PIPE_TEXTURE_CUBE ? 6U : 1U)) SWIG_exception(SWIG_ValueError, "face out of bounds"); if(level > $self->last_level) SWIG_exception(SWIG_ValueError, "level out of bounds"); if(zslice >= u_minify($self->depth0, level)) SWIG_exception(SWIG_ValueError, "zslice out of bounds"); - + surface = CALLOC_STRUCT(st_surface); if(!surface) return NULL; - - pipe_texture_reference(&surface->texture, $self); + + pipe_resource_reference(&surface->texture, $self); surface->face = face; surface->level = level; surface->zslice = zslice; - + return surface; fail: return NULL; } - + + unsigned __len__(void) + { + assert($self->target == PIPE_BUFFER); + assert(p_atomic_read(&$self->reference.count) > 0); + return $self->width0; + } + }; struct st_surface { %immutable; - - struct pipe_texture *texture; + + struct pipe_resource *texture; unsigned face; unsigned level; unsigned zslice; - + }; %extend st_surface { - + %immutable; - + unsigned format; unsigned width; unsigned height; - + ~st_surface() { - pipe_texture_reference(&$self->texture, NULL); + pipe_resource_reference(&$self->texture, NULL); FREE($self); } - - %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); - void get_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH) - { - struct pipe_texture *texture = $self->texture; - struct pipe_screen *screen = texture->screen; - struct pipe_transfer *transfer; - unsigned stride; - - stride = util_format_get_stride(texture->format, w); - *LENGTH = util_format_get_nblocksy(texture->format, h) * stride; - *STRING = (char *) malloc(*LENGTH); - if(!*STRING) - return; - - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_READ, - x, y, w, h); - if(transfer) { - pipe_get_tile_raw(transfer, 0, 0, w, h, *STRING, stride); - screen->tex_transfer_destroy(transfer); - } - } - - %cstring_input_binary(const char *STRING, unsigned LENGTH); - void put_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, const char *STRING, unsigned LENGTH, unsigned stride = 0) - { - struct pipe_texture *texture = $self->texture; - struct pipe_screen *screen = texture->screen; - struct pipe_transfer *transfer; - - if(stride == 0) - stride = util_format_get_stride(texture->format, w); - - if(LENGTH < util_format_get_nblocksy(texture->format, h) * stride) - SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); - - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_WRITE, - x, y, w, h); - if(!transfer) - SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer"); - - pipe_put_tile_raw(transfer, 0, 0, w, h, STRING, stride); - screen->tex_transfer_destroy(transfer); - - fail: - return; - } - - void - get_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, float *rgba) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_READ, - x, y, w, h); - if(transfer) { - pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba); - screen->tex_transfer_destroy(transfer); - } - } - void - put_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_WRITE, - x, y, w, h); - if(transfer) { - pipe_put_tile_rgba(transfer, 0, 0, w, h, rgba); - screen->tex_transfer_destroy(transfer); - } - } - - %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); - void - get_tile_rgba8(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - float *rgba; - unsigned char *rgba8; - unsigned i, j, k; - - *LENGTH = 0; - *STRING = NULL; - - if (!$self) - return; - - *LENGTH = h*w*4; - *STRING = (char *) malloc(*LENGTH); - if(!*STRING) - return; - - rgba = malloc(h*w*4*sizeof(float)); - if(!rgba) - return; - - rgba8 = (unsigned char *) *STRING; - - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_READ, - x, y, - w, h); - if(transfer) { - pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba); - for(j = 0; j < h; ++j) { - for(i = 0; i < w; ++i) - for(k = 0; k <4; ++k) - rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]); - } - screen->tex_transfer_destroy(transfer); - } - - free(rgba); - } - - void - get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_READ, - x, y, w, h); - if(transfer) { - pipe_get_tile_z(transfer, 0, 0, w, h, z); - screen->tex_transfer_destroy(transfer); - } - } - - void - put_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, const unsigned *z) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_WRITE, - x, y, w, h); - if(transfer) { - pipe_put_tile_z(transfer, 0, 0, w, h, z); - screen->tex_transfer_destroy(transfer); - } - } - - void - sample_rgba(float *rgba) { - st_sample_surface($self, rgba); - } - - unsigned - compare_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba, float tol = 0.0) - { - struct pipe_screen *screen = $self->texture->screen; - struct pipe_transfer *transfer; - float *rgba2; - const float *p1; - const float *p2; - unsigned i, j, n; - - rgba2 = MALLOC(h*w*4*sizeof(float)); - if(!rgba2) - return ~0; - - transfer = screen->get_tex_transfer(screen, - $self->texture, - $self->face, - $self->level, - $self->zslice, - PIPE_TRANSFER_READ, - x, y, w, h); - if(!transfer) { - FREE(rgba2); - return ~0; - } - - pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba2); - screen->tex_transfer_destroy(transfer); - - p1 = rgba; - p2 = rgba2; - n = 0; - for(i = h*w; i; --i) { - unsigned differs = 0; - for(j = 4; j; --j) { - float delta = *p2++ - *p1++; - if (delta < -tol || delta > tol) - differs = 1; - } - n += differs; - } - - FREE(rgba2); - - return n; - } }; @@ -374,55 +154,3 @@ struct st_surface return u_minify(surface->texture->height0, surface->level); } %} - -/* Avoid naming conflict with p_inlines.h's pipe_buffer_read/write */ -%rename(read) read_; -%rename(write) write_; - -%extend pipe_buffer { - - ~pipe_buffer() { - struct pipe_buffer *ptr = $self; - pipe_buffer_reference(&ptr, NULL); - } - - unsigned __len__(void) - { - assert(p_atomic_read(&$self->reference.count) > 0); - return $self->size; - } - - %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); - void read_(char **STRING, int *LENGTH) - { - struct pipe_screen *screen = $self->screen; - - assert(p_atomic_read(&$self->reference.count) > 0); - - *LENGTH = $self->size; - *STRING = (char *) malloc($self->size); - if(!*STRING) - return; - - pipe_buffer_read(screen, $self, 0, $self->size, *STRING); - } - - %cstring_input_binary(const char *STRING, unsigned LENGTH); - void write_(const char *STRING, unsigned LENGTH, unsigned offset = 0) - { - struct pipe_screen *screen = $self->screen; - - assert(p_atomic_read(&$self->reference.count) > 0); - - if(offset > $self->size) - SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); - - if(offset + LENGTH > $self->size) - SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer"); - - pipe_buffer_write(screen, $self, offset, LENGTH, STRING); - -fail: - return; - } -}; diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c index 45e78417500..aac28cacfde 100644 --- a/src/gallium/state_trackers/python/st_device.c +++ b/src/gallium/state_trackers/python/st_device.c @@ -31,11 +31,12 @@ #include "pipe/p_shader_tokens.h" #include "util/u_inlines.h" #include "cso_cache/cso_context.h" +#include "util/u_inlines.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "util/u_simple_shaders.h" -#include "trace/tr_screen.h" -#include "trace/tr_context.h" +#include "trace/tr_public.h" #include "st_device.h" #include "st_winsys.h" @@ -75,43 +76,34 @@ st_device_destroy(struct st_device *st_dev) } -static struct st_device * -st_device_create_from_st_winsys(const struct st_winsys *st_ws) +struct st_device * +st_device_create(boolean hardware) { + struct pipe_screen *screen; struct st_device *st_dev; - - if(!st_ws->screen_create) - return NULL; - + + if (hardware) + screen = st_hardware_screen_create(); + else + screen = st_software_screen_create("softpipe"); + + screen = trace_screen_create(screen); + if (!screen) + goto no_screen; + st_dev = CALLOC_STRUCT(st_device); - if(!st_dev) - return NULL; + if (!st_dev) + goto no_device; pipe_reference_init(&st_dev->reference, 1); - st_dev->st_ws = st_ws; - - st_dev->real_screen = st_ws->screen_create(); - if(!st_dev->real_screen) { - st_device_destroy(st_dev); - return NULL; - } - - st_dev->screen = trace_screen_create(st_dev->real_screen); - if(!st_dev->screen) { - st_device_destroy(st_dev); - return NULL; - } + st_dev->screen = screen; return st_dev; -} - -struct st_device * -st_device_create(boolean hardware) { - if(hardware) - return st_device_create_from_st_winsys(&st_hardpipe_winsys); - else - return st_device_create_from_st_winsys(&st_softpipe_winsys); +no_device: + screen->destroy(screen); +no_screen: + return NULL; } @@ -134,10 +126,10 @@ st_context_destroy(struct st_context *st_ctx) st_ctx->pipe->destroy(st_ctx->pipe); for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) - pipe_texture_reference(&st_ctx->fragment_sampler_textures[i], NULL); + pipe_sampler_view_reference(&st_ctx->fragment_sampler_views[i], NULL); for(i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; ++i) - pipe_texture_reference(&st_ctx->vertex_sampler_textures[i], NULL); - pipe_texture_reference(&st_ctx->default_texture, NULL); + pipe_sampler_view_reference(&st_ctx->vertex_sampler_views[i], NULL); + pipe_resource_reference(&st_ctx->default_texture, NULL); FREE(st_ctx); @@ -237,9 +229,11 @@ st_context_create(struct st_device *st_dev) /* default textures */ { + struct pipe_context *pipe = st_ctx->pipe; struct pipe_screen *screen = st_dev->screen; - struct pipe_texture templat; - struct pipe_transfer *transfer; + struct pipe_resource templat; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; unsigned i; memset( &templat, 0, sizeof( templat ) ); @@ -249,34 +243,45 @@ st_context_create(struct st_device *st_dev) templat.height0 = 1; templat.depth0 = 1; templat.last_level = 0; + templat.bind = PIPE_BIND_SAMPLER_VIEW; - st_ctx->default_texture = screen->texture_create( screen, &templat ); + st_ctx->default_texture = screen->resource_create( screen, &templat ); if(st_ctx->default_texture) { - transfer = screen->get_tex_transfer(screen, - st_ctx->default_texture, - 0, 0, 0, - PIPE_TRANSFER_WRITE, - 0, 0, - st_ctx->default_texture->width0, - st_ctx->default_texture->height0); - if (transfer) { - uint32_t *map; - map = (uint32_t *) screen->transfer_map(screen, transfer); - if(map) { - *map = 0x00000000; - screen->transfer_unmap(screen, transfer); - } - screen->tex_transfer_destroy(transfer); - } + struct pipe_box box; + uint32_t zero = 0; + + u_box_origin_2d( 1, 1, &box ); + + pipe->transfer_inline_write(pipe, + st_ctx->default_texture, + u_subresource(0,0), + PIPE_TRANSFER_WRITE, + &box, + &zero, + sizeof zero, + 0); } - + + u_sampler_view_default_template(&view_templ, + st_ctx->default_texture, + st_ctx->default_texture->format); + view = st_ctx->pipe->create_sampler_view(st_ctx->pipe, + st_ctx->default_texture, + &view_templ); + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) - pipe_texture_reference(&st_ctx->fragment_sampler_textures[i], st_ctx->default_texture); + pipe_sampler_view_reference(&st_ctx->fragment_sampler_views[i], view); for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) - pipe_texture_reference(&st_ctx->vertex_sampler_textures[i], st_ctx->default_texture); - - cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->fragment_sampler_textures); - cso_set_vertex_sampler_textures(st_ctx->cso, PIPE_MAX_VERTEX_SAMPLERS, st_ctx->vertex_sampler_textures); + pipe_sampler_view_reference(&st_ctx->vertex_sampler_views[i], view); + + st_ctx->pipe->set_fragment_sampler_views(st_ctx->pipe, + PIPE_MAX_SAMPLERS, + st_ctx->fragment_sampler_views); + st_ctx->pipe->set_vertex_sampler_views(st_ctx->pipe, + PIPE_MAX_VERTEX_SAMPLERS, + st_ctx->vertex_sampler_views); + + pipe_sampler_view_reference(&view, NULL); } /* vertex shader */ diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h index de9e0215d8e..2dca7a1974e 100644 --- a/src/gallium/state_trackers/python/st_device.h +++ b/src/gallium/state_trackers/python/st_device.h @@ -40,14 +40,15 @@ struct st_winsys; struct st_surface { - struct pipe_texture *texture; + struct pipe_resource *texture; unsigned face; unsigned level; unsigned zslice; }; -struct st_context { +struct st_context +{ struct st_device *st_dev; struct pipe_context *pipe; @@ -58,9 +59,9 @@ struct st_context { void *fs; void *gs; - struct pipe_texture *default_texture; - struct pipe_texture *fragment_sampler_textures[PIPE_MAX_SAMPLERS]; - struct pipe_texture *vertex_sampler_textures[PIPE_MAX_VERTEX_SAMPLERS]; + struct pipe_resource *default_texture; + struct pipe_sampler_view *fragment_sampler_views[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *vertex_sampler_views[PIPE_MAX_VERTEX_SAMPLERS]; unsigned num_vertex_buffers; struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; @@ -72,13 +73,11 @@ struct st_context { }; -struct st_device { +struct st_device +{ /* FIXME: we also need to refcount for textures and surfaces... */ struct pipe_reference reference; - const struct st_winsys *st_ws; - - struct pipe_screen *real_screen; struct pipe_screen *screen; }; @@ -86,7 +85,7 @@ struct st_device { static INLINE struct pipe_surface * st_pipe_surface(struct st_surface *surface, unsigned usage) { - struct pipe_texture *texture = surface->texture; + struct pipe_resource *texture = surface->texture; struct pipe_screen *screen = texture->screen; return screen->get_tex_surface(screen, texture, surface->face, surface->level, surface->zslice, usage); } diff --git a/src/gallium/state_trackers/python/st_hardpipe_winsys.c b/src/gallium/state_trackers/python/st_hardpipe_winsys.c index a3110a19d5d..c6743dbd9c4 100644 --- a/src/gallium/state_trackers/python/st_hardpipe_winsys.c +++ b/src/gallium/state_trackers/python/st_hardpipe_winsys.c @@ -54,11 +54,6 @@ static PFNGETGALLIUMSCREENMESAPROC pfnGetGalliumScreenMESA = NULL; static PFNCREATEGALLIUMCONTEXTMESAPROC pfnCreateGalliumContextMESA = NULL; -/* XXX: Force init_gallium symbol to be linked */ -extern void init_gallium(void); -void (*force_init_gallium_linkage)(void) = &init_gallium; - - #ifdef PIPE_OS_WINDOWS static INLINE boolean @@ -207,16 +202,11 @@ st_hardpipe_load(void) #endif -static struct pipe_screen * -st_hardpipe_screen_create(void) +struct pipe_screen * +st_hardware_screen_create(void) { if(st_hardpipe_load()) return pfnGetGalliumScreenMESA(); else - return st_softpipe_winsys.screen_create(); + return st_software_screen_create(NULL); } - - -const struct st_winsys st_hardpipe_winsys = { - &st_hardpipe_screen_create -}; diff --git a/src/gallium/state_trackers/python/st_llvmpipe_winsys.c b/src/gallium/state_trackers/python/st_llvmpipe_winsys.c deleted file mode 100644 index 5d83b5a9e15..00000000000 --- a/src/gallium/state_trackers/python/st_llvmpipe_winsys.c +++ /dev/null @@ -1,141 +0,0 @@ -/************************************************************************** - * - * 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, 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. - * - * - **************************************************************************/ - -/** - * @file - * Llvmpipe support. - * - * @author Jose Fonseca - */ - - -#include "pipe/p_format.h" -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "util/u_math.h" -#include "util/u_memory.h" -#include "llvmpipe/lp_winsys.h" -#include "st_winsys.h" - - -static boolean -llvmpipe_ws_is_displaytarget_format_supported( struct llvmpipe_winsys *ws, - enum pipe_format format ) -{ - return FALSE; -} - - -static void * -llvmpipe_ws_displaytarget_map(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt, - unsigned flags ) -{ - assert(0); - return NULL; -} - - -static void -llvmpipe_ws_displaytarget_unmap(struct llvmpipe_winsys *ws, - struct llvmpipe_displaytarget *dt ) -{ - assert(0); -} - - -static void -llvmpipe_ws_displaytarget_destroy(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt) -{ - assert(0); -} - - -static struct llvmpipe_displaytarget * -llvmpipe_ws_displaytarget_create(struct llvmpipe_winsys *winsys, - enum pipe_format format, - unsigned width, unsigned height, - unsigned alignment, - unsigned *stride) -{ - return NULL; -} - - -static void -llvmpipe_ws_displaytarget_display(struct llvmpipe_winsys *winsys, - struct llvmpipe_displaytarget *dt, - void *context_private) -{ - assert(0); -} - - -static void -llvmpipe_ws_destroy(struct llvmpipe_winsys *winsys) -{ - FREE(winsys); -} - - -static struct pipe_screen * -st_llvmpipe_screen_create(void) -{ - static struct llvmpipe_winsys *winsys; - struct pipe_screen *screen; - - winsys = CALLOC_STRUCT(llvmpipe_winsys); - if (!winsys) - goto no_winsys; - - winsys->destroy = llvmpipe_ws_destroy; - winsys->is_displaytarget_format_supported = llvmpipe_ws_is_displaytarget_format_supported; - winsys->displaytarget_create = llvmpipe_ws_displaytarget_create; - winsys->displaytarget_map = llvmpipe_ws_displaytarget_map; - winsys->displaytarget_unmap = llvmpipe_ws_displaytarget_unmap; - winsys->displaytarget_display = llvmpipe_ws_displaytarget_display; - winsys->displaytarget_destroy = llvmpipe_ws_displaytarget_destroy; - - screen = llvmpipe_create_screen(winsys); - if (!screen) - goto no_screen; - - return screen; - -no_screen: - FREE(winsys); -no_winsys: - return NULL; -} - - - -const struct st_winsys st_softpipe_winsys = { - &st_llvmpipe_screen_create -}; diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c index e1808153461..25bfbf1ab73 100644 --- a/src/gallium/state_trackers/python/st_sample.c +++ b/src/gallium/state_trackers/python/st_sample.c @@ -50,7 +50,7 @@ static uint32_t st_random(void) { seed = UINT64_C(134775813) * seed + UINT64_C(1); - return (uint16_t)(seed >> 32); + return (uint32_t)(seed >> 32); } @@ -470,25 +470,42 @@ static INLINE void st_sample_generic_pixel_block(enum pipe_format format, uint8_t *raw, float *rgba, unsigned rgba_stride, - unsigned w, unsigned h) + unsigned w, unsigned h, + boolean norm) { unsigned i; unsigned x, y, ch; int blocksize = util_format_get_blocksize(format); - for(i = 0; i < blocksize; ++i) - raw[i] = (uint8_t)st_random(); - - - pipe_tile_raw_to_rgba(format, - raw, - w, h, - rgba, rgba_stride); - - if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { - for(y = 0; y < h; ++y) { - for(x = 0; x < w; ++x) { - for(ch = 0; ch < 4; ++ch) { + if (norm) { + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + for (ch = 0; ch < 4; ++ch) { + unsigned offset = y*rgba_stride + x*4 + ch; + rgba[offset] = (st_random() & 0xff) / (double)0xff; + } + } + } + + util_format_write_4f(format, + rgba, rgba_stride * sizeof(float), + raw, util_format_get_stride(format, w), + 0, 0, w, h); + + } else { + for (i = 0; i < blocksize; ++i) + raw[i] = (uint8_t)st_random(); + } + + util_format_read_4f(format, + rgba, rgba_stride * sizeof(float), + raw, util_format_get_stride(format, w), + 0, 0, w, h); + + if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { + for (y = 0; y < h; ++y) { + for (x = 0; x < w; ++x) { + for (ch = 0; ch < 4; ++ch) { unsigned offset = y*rgba_stride + x*4 + ch; rgba[offset] = CLAMP(rgba[offset], 0.0f, 1.0f); } @@ -505,7 +522,8 @@ void st_sample_pixel_block(enum pipe_format format, void *raw, float *rgba, unsigned rgba_stride, - unsigned w, unsigned h) + unsigned w, unsigned h, + boolean norm) { switch(format) { case PIPE_FORMAT_DXT1_RGB: @@ -516,36 +534,38 @@ st_sample_pixel_block(enum pipe_format format, break; default: - st_sample_generic_pixel_block(format, raw, rgba, rgba_stride, w, h); + st_sample_generic_pixel_block(format, raw, rgba, rgba_stride, w, h, norm); break; } } void -st_sample_surface(struct st_surface *surface, float *rgba) +st_sample_surface(struct pipe_context *pipe, + struct st_surface *surface, + float *rgba, + boolean norm) { - struct pipe_texture *texture = surface->texture; - struct pipe_screen *screen = texture->screen; + struct pipe_resource *texture = surface->texture; unsigned width = u_minify(texture->width0, surface->level); unsigned height = u_minify(texture->height0, surface->level); uint rgba_stride = width * 4; struct pipe_transfer *transfer; void *raw; - transfer = screen->get_tex_transfer(screen, - surface->texture, - surface->face, - surface->level, - surface->zslice, - PIPE_TRANSFER_WRITE, - 0, 0, - width, - height); + transfer = pipe_get_transfer(pipe, + surface->texture, + surface->face, + surface->level, + surface->zslice, + PIPE_TRANSFER_WRITE, + 0, 0, + width, + height); if (!transfer) return; - raw = screen->transfer_map(screen, transfer); + raw = pipe->transfer_map(pipe, transfer); if (raw) { enum pipe_format format = texture->format; uint x, y; @@ -563,12 +583,13 @@ st_sample_surface(struct st_surface *surface, float *rgba) rgba + y * blockheight * rgba_stride + x * blockwidth * 4, rgba_stride, MIN2(blockwidth, width - x*blockwidth), - MIN2(blockheight, height - y*blockheight)); + MIN2(blockheight, height - y*blockheight), + norm); } } - screen->transfer_unmap(screen, transfer); + pipe->transfer_unmap(pipe, transfer); } - - screen->tex_transfer_destroy(transfer); + + pipe->transfer_destroy(pipe, transfer); } diff --git a/src/gallium/state_trackers/python/st_sample.h b/src/gallium/state_trackers/python/st_sample.h index 888114d3021..2fdbb391f36 100644 --- a/src/gallium/state_trackers/python/st_sample.h +++ b/src/gallium/state_trackers/python/st_sample.h @@ -32,15 +32,22 @@ #include "pipe/p_format.h" +struct pipe_context; +struct st_surface; + void st_sample_pixel_block(enum pipe_format format, void *raw, float *rgba, unsigned rgba_stride, - unsigned w, unsigned h); + unsigned w, unsigned h, + boolean norm); void -st_sample_surface(struct st_surface *surface, float *rgba); +st_sample_surface(struct pipe_context *pipe, + struct st_surface *surface, + float *rgba, + boolean norm); #endif /* ST_SAMPLE_H_ */ diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c index 81676bc3a4f..8584bad4679 100644 --- a/src/gallium/state_trackers/python/st_softpipe_winsys.c +++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c @@ -26,18 +26,53 @@ * **************************************************************************/ -/** - * @file - * Softpipe support. - * - * @author Keith Whitwell - * @author Brian Paul - * @author Jose Fonseca - */ - -#include "softpipe/sp_winsys.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" +#include "state_tracker/sw_winsys.h" +#include "sw/null/null_sw_winsys.h" #include "st_winsys.h" -const struct st_winsys st_softpipe_winsys = { - &softpipe_create_screen_malloc -}; + +struct pipe_screen * +st_software_screen_create(const char *driver) +{ + struct sw_winsys *ws; + struct pipe_screen *screen = NULL; + + if (!driver) { + const char *default_driver; + +#if defined(HAVE_LLVMPIPE) + default_driver = "llvmpipe"; +#elif defined(HAVE_SOFTPIPE) + default_driver = "softpipe"; +#else + default_driver = ""; +#endif + + driver = debug_get_option("GALLIUM_DRIVER", default_driver); + } + + ws = null_sw_create(); + if(!ws) + return NULL; + +#ifdef HAVE_LLVMPIPE + if (strcmp(driver, "llvmpipe") == 0) { + screen = llvmpipe_create_screen(ws); + } +#endif + +#ifdef HAVE_SOFTPIPE + if (strcmp(driver, "softpipe") == 0) { + screen = softpipe_create_screen(ws); + } +#endif + + if (!screen) { + ws->destroy(ws); + } + + return screen; +} diff --git a/src/gallium/state_trackers/python/st_winsys.h b/src/gallium/state_trackers/python/st_winsys.h index 0c7b6a200e1..7d4066d947b 100644 --- a/src/gallium/state_trackers/python/st_winsys.h +++ b/src/gallium/state_trackers/python/st_winsys.h @@ -31,19 +31,13 @@ struct pipe_screen; -struct pipe_context; -struct st_winsys -{ - struct pipe_screen * - (*screen_create)(void); -}; +struct pipe_screen * +st_hardware_screen_create(void); - -extern const struct st_winsys st_softpipe_winsys; - -extern const struct st_winsys st_hardpipe_winsys; +struct pipe_screen * +st_software_screen_create(const char *driver); #endif /* ST_WINSYS_H_ */ diff --git a/src/gallium/state_trackers/python/u_format.i b/src/gallium/state_trackers/python/u_format.i new file mode 100644 index 00000000000..2184b420843 --- /dev/null +++ b/src/gallium/state_trackers/python/u_format.i @@ -0,0 +1,88 @@ +/************************************************************************** + * + * 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, 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. + * + **************************************************************************/ + + +static INLINE const char * +util_format_name(enum pipe_format format); + +static INLINE boolean +util_format_is_s3tc(enum pipe_format format); + +static INLINE boolean +util_format_is_depth_or_stencil(enum pipe_format format); + +static INLINE boolean +util_format_is_depth_and_stencil(enum pipe_format format); + + +uint +util_format_get_blocksizebits(enum pipe_format format); + +uint +util_format_get_blocksize(enum pipe_format format); + +uint +util_format_get_blockwidth(enum pipe_format format); + +uint +util_format_get_blockheight(enum pipe_format format); + +unsigned +util_format_get_nblocksx(enum pipe_format format, + unsigned x); + +unsigned +util_format_get_nblocksy(enum pipe_format format, + unsigned y); + +unsigned +util_format_get_nblocks(enum pipe_format format, + unsigned width, + unsigned height); + +size_t +util_format_get_stride(enum pipe_format format, + unsigned width); + +size_t +util_format_get_2d_size(enum pipe_format format, + size_t stride, + unsigned height); + +uint +util_format_get_component_bits(enum pipe_format format, + enum util_format_colorspace colorspace, + uint component); + +boolean +util_format_has_alpha(enum pipe_format format); + + +unsigned +util_format_get_nr_components(enum pipe_format format); + + diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 037d8dc911a..b871990cd9a 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -25,8 +25,8 @@ VG_SOURCES = \ api_transform.c \ vgu.c \ vg_context.c \ + vg_manager.c \ vg_state.c \ - vg_tracker.c \ vg_translate.c \ polygon.c \ bezier.c \ @@ -42,7 +42,8 @@ VG_SOURCES = \ VG_OBJECTS = $(VG_SOURCES:.c=.o) -VG_LIBS = $(GALLIUM_AUXILIARIES) -lm +VG_LIBS = $(GALLIUM_AUXILIARIES) +VG_LIB_DEPS = $(EXTRA_LIB_PATH) -lm ### Include directories @@ -53,7 +54,7 @@ INCLUDE_DIRS = \ .c.o: - $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ default: depend $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) @@ -64,7 +65,7 @@ $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME): $(VG_OBJECTS) $(VG_LIBS) -minor $(VG_MINOR) \ -patch $(VG_TINY) \ -install $(TOP)/$(LIB_DIR) \ - $(VG_OBJECTS) $(VG_LIBS) + $(VG_OBJECTS) $(VG_LIBS) $(VG_LIB_DEPS) ###################################################################### # Generic stuff diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c index 47db102dd2d..eb2fbe26e7f 100644 --- a/src/gallium/state_trackers/vega/api_context.c +++ b/src/gallium/state_trackers/vega/api_context.c @@ -26,6 +26,7 @@ #include "VG/openvg.h" +#include "vg_manager.h" #include "vg_context.h" #include "pipe/p_context.h" @@ -55,6 +56,8 @@ void vgFlush(void) pipe = ctx->pipe; pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); + + vg_manager_flush_frontbuffer(ctx); } void vgFinish(void) diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 02248ad4337..b1c08af9382 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -40,6 +40,7 @@ #include "util/u_format.h" #include "util/u_memory.h" +#include "util/u_sampler.h" #include "asm_filters.h" @@ -53,17 +54,17 @@ struct filter_info { const void *const_buffer; VGint const_buffer_len; VGTilingMode tiling_mode; - struct pipe_texture *extra_texture; + struct pipe_sampler_view *extra_texture_view; }; -static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx, +static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx, const VGuint *color_data, const VGint color_data_len) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_texture *tex = 0; - struct pipe_texture templ; + struct pipe_resource *tex = 0; + struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_1D; @@ -72,33 +73,55 @@ static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx, templ.width0 = color_data_len; templ.height0 = 1; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + templ.bind = PIPE_BIND_SAMPLER_VIEW; - tex = screen->texture_create(screen, &templ); + tex = screen->resource_create(screen, &templ); { /* upload color_data */ struct pipe_transfer *transfer = - screen->get_tex_transfer(screen, tex, - 0, 0, 0, - PIPE_TRANSFER_READ_WRITE , - 0, 0, tex->width0, tex->height0); - void *map = screen->transfer_map(screen, transfer); + pipe_get_transfer(pipe, tex, + 0, 0, 0, + PIPE_TRANSFER_READ_WRITE , + 0, 0, tex->width0, tex->height0); + void *map = pipe->transfer_map(pipe, transfer); memcpy(map, color_data, sizeof(VGint)*color_data_len); - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); } return tex; } +static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context *ctx, + const VGuint *color_data, + const VGint color_data_len) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture_1d(ctx, color_data, color_data_len); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst) { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; struct pipe_framebuffer_state fb; struct pipe_surface *dst_surf = pipe->screen->get_tex_surface( - pipe->screen, dst->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + pipe->screen, dst->sampler_view->texture, 0, 0, 0, + PIPE_BIND_RENDER_TARGET); /* drawing dest */ memset(&fb, 0, sizeof(fb)); @@ -147,14 +170,14 @@ static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, VGint param_bytes) { struct pipe_context *pipe = ctx->pipe; - struct pipe_buffer **cbuf = &ctx->filter.buffer; + struct pipe_resource **cbuf = &ctx->filter.buffer; /* We always need to get a new buffer, to keep the drivers simple and * avoid gratuitous rendering synchronization. */ - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); - *cbuf = pipe_buffer_create(pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, + *cbuf = pipe_buffer_create(pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, param_bytes); if (*cbuf) { @@ -168,7 +191,7 @@ static void setup_constant_buffer(struct vg_context *ctx, const void *buffer, static void setup_samplers(struct vg_context *ctx, struct filter_info *info) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler[3]; int num_samplers = 0; int num_textures = 0; @@ -177,10 +200,10 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; memset(&sampler[0], 0, sizeof(struct pipe_sampler_state)); sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -215,21 +238,21 @@ static void setup_samplers(struct vg_context *ctx, struct filter_info *info) } samplers[0] = &sampler[0]; - textures[0] = info->src->texture; + sampler_views[0] = info->src->sampler_view; ++num_samplers; ++num_textures; - if (info->extra_texture) { + if (info->extra_texture_view) { memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state)); samplers[1] = &sampler[1]; - textures[1] = info->extra_texture; + sampler_views[1] = info->extra_texture_view; ++num_samplers; ++num_textures; } cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, num_textures, textures); + cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views); } static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data) @@ -308,7 +331,7 @@ static void execute_filter(struct vg_context *ctx, cso_save_viewport(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); dst_surf = setup_framebuffer(info->dst); setup_viewport(info->dst); @@ -318,7 +341,7 @@ static void execute_filter(struct vg_context *ctx, setup_samplers(ctx, info); renderer_draw_texture(ctx->renderer, - info->src->texture, + info->src->sampler_view->texture, info->dst->x, info->dst->y, info->dst->x + info->dst->width, info->dst->y + info->dst->height, @@ -331,7 +354,7 @@ static void execute_filter(struct vg_context *ctx, cso_restore_viewport(ctx->cso_context); cso_restore_blend(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); vg_shader_destroy(ctx, shader); @@ -369,7 +392,7 @@ void vgColorMatrix(VGImage dst, VGImage src, info.const_buffer = matrix; info.const_buffer_len = 20 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); } @@ -479,7 +502,7 @@ void vgConvolve(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -669,7 +692,7 @@ void vgGaussianBlur(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = buffer_len * sizeof(VGfloat); info.tiling_mode = tilingMode; - info.extra_texture = 0; + info.extra_texture_view = NULL; execute_filter(ctx, &info); free(buffer); @@ -688,7 +711,7 @@ void vgLookup(VGImage dst, VGImage src, struct vg_image *d, *s; VGuint color_data[256]; VGint i; - struct pipe_texture *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; @@ -714,7 +737,7 @@ void vgLookup(VGImage dst, VGImage src, color_data[i] = blueLUT[i] << 24 | greenLUT[i] << 16 | redLUT[i] << 8 | alphaLUT[i]; } - lut_texture = create_texture_1d(ctx, color_data, 255); + lut_texture_view = create_texture_1d_view(ctx, color_data, 255); buffer[0] = 0.f; buffer[1] = 0.f; @@ -728,11 +751,11 @@ void vgLookup(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_texture_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } void vgLookupSingle(VGImage dst, VGImage src, @@ -743,7 +766,7 @@ void vgLookupSingle(VGImage dst, VGImage src, { struct vg_context *ctx = vg_current_context(); struct vg_image *d, *s; - struct pipe_texture *lut_texture; + struct pipe_sampler_view *lut_texture_view; VGfloat buffer[4]; struct filter_info info; VGuint color_data[256]; @@ -783,7 +806,7 @@ void vgLookupSingle(VGImage dst, VGImage src, color_data[i] = blue << 24 | green << 16 | red << 8 | alpha; } - lut_texture = create_texture_1d(ctx, color_data, 256); + lut_texture_view = create_texture_1d_view(ctx, color_data, 256); buffer[0] = 0.f; buffer[1] = 0.f; @@ -797,9 +820,9 @@ void vgLookupSingle(VGImage dst, VGImage src, info.const_buffer = buffer; info.const_buffer_len = 4 * sizeof(VGfloat); info.tiling_mode = VG_TILE_PAD; - info.extra_texture = lut_texture; + info.extra_texture_view = lut_texture_view; execute_filter(ctx, &info); - pipe_texture_reference(&lut_texture, NULL); + pipe_sampler_view_reference(&lut_texture_view, NULL); } diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c index 015241498ed..6c7fd3b346c 100644 --- a/src/gallium/state_trackers/vega/api_images.c +++ b/src/gallium/state_trackers/vega/api_images.c @@ -397,7 +397,6 @@ void vgReadPixels(void * data, VGint dataStride, { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; @@ -442,23 +441,23 @@ void vgReadPixels(void * data, VGint dataStride, { struct pipe_transfer *transfer; - transfer = screen->get_tex_transfer(screen, strb->texture, 0, 0, 0, - PIPE_TRANSFER_READ, - 0, 0, width, height); + transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 0, + PIPE_TRANSFER_READ, + 0, 0, width, height); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif - pipe_get_tile_rgba(transfer, sx, y, width, 1, df); + pipe_get_tile_rgba(pipe, transfer, sx, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst + yoffset + xoffset); dst += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->transfer_destroy(pipe, transfer); } } diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c index 9c123a4cf95..7c28ea5c872 100644 --- a/src/gallium/state_trackers/vega/api_masks.c +++ b/src/gallium/state_trackers/vega/api_masks.c @@ -51,7 +51,7 @@ draw_clear_quad(struct vg_context *st, const VGfloat color[4]) { struct pipe_context *pipe = st->pipe; - struct pipe_buffer *buf; + struct pipe_resource *buf; VGuint i; /* positions */ @@ -81,17 +81,20 @@ draw_clear_quad(struct vg_context *st, /* put vertex data into vbuf */ buf = pipe_user_buffer_create(pipe->screen, st->clear.vertices, - sizeof(st->clear.vertices)); + sizeof(st->clear.vertices), + PIPE_BIND_VERTEX_BUFFER); /* draw */ if (buf) { + cso_set_vertex_elements(st->cso_context, 2, st->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -115,10 +118,6 @@ clear_with_quad(struct vg_context *st, float x0, float y0, x1, y1); */ - if (st->pipe->screen && st->pipe->screen->update_buffer) - st->pipe->screen->update_buffer( st->pipe->screen, - st->pipe->priv ); - cso_save_blend(st->cso_context); cso_save_rasterizer(st->cso_context); cso_save_fragment_shader(st->cso_context); diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 41c979bfecf..9c323b1809c 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -43,6 +43,7 @@ #include "util/u_tile.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" static enum pipe_format vg_format_to_pipe(VGImageFormat format) { @@ -80,8 +81,8 @@ static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc) static void vg_copy_texture(struct vg_context *ctx, - struct pipe_texture *dst, VGint dx, VGint dy, - struct pipe_texture *src, VGint sx, VGint sy, + struct pipe_resource *dst, VGint dx, VGint dy, + struct pipe_sampler_view *src, VGint sx, VGint sy, VGint width, VGint height) { VGfloat dst_loc[4], src_loc[4]; @@ -103,8 +104,8 @@ static void vg_copy_texture(struct vg_context *ctx, src_loc[3] = height; src_bounds[0] = 0.f; src_bounds[1] = 0.f; - src_bounds[2] = src->width0; - src_bounds[3] = src->height0; + src_bounds[2] = src->texture->width0; + src_bounds[3] = src->texture->height0; vg_bound_rect(src_loc, src_bounds, src_shift); vg_bound_rect(dst_loc, dst_bounds, dst_shift); @@ -216,9 +217,9 @@ void vg_copy_surface(struct vg_context *ctx, } -static struct pipe_texture *image_texture(struct vg_image *img) +static struct pipe_resource *image_texture(struct vg_image *img) { - struct pipe_texture *tex = img->texture; + struct pipe_resource *tex = img->sampler_view->texture; return tex; } @@ -247,9 +248,12 @@ struct vg_image * image_create(VGImageFormat format, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_context *pipe = ctx->pipe; struct vg_image *image = CALLOC_STRUCT(vg_image); enum pipe_format pformat = vg_format_to_pipe(format); - struct pipe_texture pt, *newtex; + struct pipe_resource pt, *newtex; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; struct pipe_screen *screen = ctx->pipe->screen; vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE); @@ -266,7 +270,7 @@ struct vg_image * image_create(VGImageFormat format, image->sampler.normalized_coords = 1; assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); + PIPE_BIND_SAMPLER_VIEW, 0)); memset(&pt, 0, sizeof(pt)); pt.target = PIPE_TEXTURE_2D; @@ -275,13 +279,18 @@ struct vg_image * image_create(VGImageFormat format, pt.width0 = width; pt.height0 = height; pt.depth0 = 1; - pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + pt.bind = PIPE_BIND_SAMPLER_VIEW; - newtex = screen->texture_create(screen, &pt); + newtex = screen->resource_create(screen, &pt); debug_assert(newtex); - image->texture = newtex; + u_sampler_view_default_template(&view_templ, newtex, newtex->format); + view = pipe->create_sampler_view(pipe, newtex, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&newtex, NULL); + + image->sampler_view = view; vg_context_add_object(ctx, VG_OBJECT_IMAGE, image); @@ -345,7 +354,7 @@ void image_destroy(struct vg_image *img) array_destroy(img->children_array); } - pipe_texture_reference(&img->texture, NULL); + pipe_sampler_view_reference(&img->sampler_view, NULL); free(img); } @@ -378,8 +387,8 @@ void image_sub_data(struct vg_image *image, VGfloat *df = (VGfloat*)temp; VGint i; struct vg_context *ctx = vg_current_context(); - struct pipe_screen *screen = ctx->pipe->screen; - struct pipe_texture *texture = image_texture(image); + struct pipe_context *pipe = ctx->pipe; + struct pipe_resource *texture = image_texture(image); VGint xoffset = 0, yoffset = 0; if (x < 0) { @@ -412,17 +421,17 @@ void image_sub_data(struct vg_image *image, } { /* upload color_data */ - struct pipe_transfer *transfer = screen->get_tex_transfer( - screen, texture, 0, 0, 0, + struct pipe_transfer *transfer = pipe_get_transfer( + pipe, texture, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0); src += (dataStride * yoffset); for (i = 0; i < height; i++) { _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp); - pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df); + pipe_put_tile_rgba(pipe, transfer, x+image->x, y+image->y, width, 1, df); y += yStep; src += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->transfer_destroy(pipe, transfer); } } @@ -435,7 +444,6 @@ void image_get_sub_data(struct vg_image * image, { struct vg_context *ctx = vg_current_context(); struct pipe_context *pipe = ctx->pipe; - struct pipe_screen *screen = pipe->screen; VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4]; VGfloat *df = (VGfloat*)temp; VGint y = 0, yStep = 1; @@ -444,8 +452,8 @@ void image_get_sub_data(struct vg_image * image, { struct pipe_transfer *transfer = - screen->get_tex_transfer(screen, - image->texture, 0, 0, 0, + pipe_get_transfer(pipe, + image->sampler_view->texture, 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, image->x + image->width, @@ -455,13 +463,13 @@ void image_get_sub_data(struct vg_image * image, #if 0 debug_printf("%d-%d == %d\n", sy, height, y); #endif - pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df); + pipe_get_tile_rgba(pipe, transfer, sx+image->x, y, width, 1, df); y += yStep; _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst); dst += dataStride; } - screen->tex_transfer_destroy(transfer); + pipe->transfer_destroy(pipe, transfer); } } @@ -479,9 +487,9 @@ struct vg_image * image_child_image(struct vg_image *parent, image->width = width; image->height = height; image->parent = parent; - image->texture = 0; - pipe_texture_reference(&image->texture, - parent->texture); + image->sampler_view = NULL; + pipe_sampler_view_reference(&image->sampler_view, + parent->sampler_view); image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -515,8 +523,8 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy, } /* make sure rendering has completed */ ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL); - vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy, - src->texture, src->x + sx, src->y + sy, width, height); + vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + dy, + src->sampler_view, src->x + sx, src->y + sy, width, height); } void image_draw(struct vg_image *img) @@ -568,7 +576,7 @@ void image_set_pixels(VGint dx, VGint dy, pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); surf = screen->get_tex_surface(screen, image_texture(src), 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); + PIPE_BIND_BLIT_SOURCE); vg_copy_surface(ctx, strb->surface, dx, dy, surf, sx+src->x, sy+src->y, width, height); @@ -593,8 +601,8 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); surf = screen->get_tex_surface(screen, image_texture(dst), 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ); + PIPE_BIND_BLIT_SOURCE); + vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy, strb->surface, sx, sy, width, height); @@ -625,12 +633,12 @@ VGboolean vg_image_overlaps(struct vg_image *dst, } VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers, - struct pipe_texture **textures) + struct pipe_sampler_view **sampler_views) { img->sampler.min_img_filter = image_sampler_filter(img->base.ctx); img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx); samplers[3] = &img->sampler; - textures[3] = img->texture; + sampler_views[3] = img->sampler_view; return 1; } diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h index 78e17cffa64..a990c9c5873 100644 --- a/src/gallium/state_trackers/vega/image.h +++ b/src/gallium/state_trackers/vega/image.h @@ -30,7 +30,7 @@ #include "vg_context.h" #include "pipe/p_state.h" -struct pipe_texture; +struct pipe_resource; struct array; struct vg_context; struct pipe_surface; @@ -43,7 +43,7 @@ struct vg_image { struct vg_image *parent; - struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; struct array *children_array; @@ -89,7 +89,7 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy, VGint width, VGint height); VGint image_bind_samplers(struct vg_image *dst, struct pipe_sampler_state **samplers, - struct pipe_texture **textures); + struct pipe_sampler_view **sampler_views); VGboolean vg_image_overlaps(struct vg_image *dst, struct vg_image *src); diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 839dc19a3b8..6d627b0e8da 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -45,7 +45,7 @@ struct vg_mask_layer { VGint width; VGint height; - struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; }; static INLINE struct pipe_surface * @@ -54,7 +54,7 @@ alpha_mask_surface(struct vg_context *ctx, int usage) struct pipe_screen *screen = ctx->pipe->screen; struct st_framebuffer *stfb = ctx->draw_buffer; return screen->get_tex_surface(screen, - stfb->alpha_mask, + stfb->alpha_mask_view->texture, 0, 0, 0, usage); } @@ -143,7 +143,7 @@ static void read_alpha_mask(void * data, VGint dataStride, struct pipe_surface *surf; surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_CPU_READ); + PIPE_BIND_TRANSFER_READ); /* Do a row at a time to flip image data vertically */ for (i = 0; i < height; i++) { @@ -217,7 +217,7 @@ static void setup_mask_framebuffer(struct pipe_surface *surf, static void setup_mask_operation(VGMaskOperation operation) { struct vg_context *ctx = vg_current_context(); - struct pipe_buffer **cbuf = &ctx->mask.cbuf; + struct pipe_resource **cbuf = &ctx->mask.cbuf; const VGint param_bytes = 4 * sizeof(VGfloat); const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f}; void *shader = 0; @@ -225,10 +225,10 @@ static void setup_mask_operation(VGMaskOperation operation) /* We always need to get a new buffer, to keep the drivers simple and * avoid gratuitous rendering synchronization. */ - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); - *cbuf = pipe_buffer_create(ctx->pipe->screen, 1, - PIPE_BUFFER_USAGE_CONSTANT, + *cbuf = pipe_buffer_create(ctx->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, param_bytes); if (*cbuf) { st_no_flush_pipe_buffer_write(ctx, *cbuf, @@ -284,35 +284,33 @@ static void setup_mask_operation(VGMaskOperation operation) cso_set_fragment_shader_handle(ctx->cso_context, shader); } -static void setup_mask_samplers(struct pipe_texture *umask) +static void setup_mask_samplers(struct pipe_sampler_view *umask) { struct vg_context *ctx = vg_current_context(); struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct st_framebuffer *fb_buffers = ctx->draw_buffer; - struct pipe_texture *uprev = NULL; + struct pipe_sampler_view *uprev = NULL; struct pipe_sampler_state sampler; - uprev = fb_buffers->blend_texture; + uprev = fb_buffers->blend_texture_view; sampler = ctx->mask.sampler; sampler.normalized_coords = 1; samplers[0] = NULL; samplers[1] = NULL; - samplers[2] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; + sampler_views[0] = NULL; + sampler_views[1] = NULL; samplers[0] = &sampler; samplers[1] = &ctx->mask.sampler; - textures[0] = umask; - textures[1] = uprev; + sampler_views[0] = umask; + sampler_views[1] = uprev; cso_set_samplers(ctx->cso_context, 2, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 2, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views); } @@ -320,16 +318,16 @@ static void setup_mask_samplers(struct pipe_texture *umask) static void setup_mask_fill(const VGfloat color[4]) { struct vg_context *ctx = vg_current_context(); - struct pipe_buffer **cbuf = &ctx->mask.cbuf; + struct pipe_resource **cbuf = &ctx->mask.cbuf; const VGint param_bytes = 4 * sizeof(VGfloat); /* We always need to get a new buffer, to keep the drivers simple and * avoid gratuitous rendering synchronization. */ - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); - *cbuf = pipe_buffer_create(ctx->pipe->screen, 1, - PIPE_BUFFER_USAGE_CONSTANT, + *cbuf = pipe_buffer_create(ctx->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, param_bytes); if (*cbuf) { st_no_flush_pipe_buffer_write(ctx, *cbuf, 0, param_bytes, color); @@ -411,14 +409,15 @@ static void surface_fill(struct pipe_surface *surf, } -static void mask_using_texture(struct pipe_texture *texture, +static void mask_using_texture(struct pipe_sampler_view *sampler_view, VGMaskOperation operation, VGint x, VGint y, VGint width, VGint height) { struct vg_context *ctx = vg_current_context(); + struct pipe_resource *texture = sampler_view->texture; struct pipe_surface *surface = - alpha_mask_surface(ctx, PIPE_BUFFER_USAGE_GPU_WRITE); + alpha_mask_surface(ctx, PIPE_BIND_RENDER_TARGET); VGint offsets[4], loc[4]; if (!surface) @@ -439,13 +438,13 @@ static void mask_using_texture(struct pipe_texture *texture, vg_prepare_blend_surface_from_mask(ctx); cso_save_samplers(ctx->cso_context); - cso_save_sampler_textures(ctx->cso_context); + cso_save_fragment_sampler_views(ctx->cso_context); cso_save_framebuffer(ctx->cso_context); cso_save_blend(ctx->cso_context); cso_save_fragment_shader(ctx->cso_context); cso_save_viewport(ctx->cso_context); - setup_mask_samplers(texture); + setup_mask_samplers(sampler_view); setup_mask_blend(); setup_mask_operation(operation); setup_mask_framebuffer(surface, surface->width, surface->height); @@ -463,7 +462,7 @@ static void mask_using_texture(struct pipe_texture *texture, cso_restore_framebuffer(ctx->cso_context); cso_restore_fragment_shader(ctx->cso_context); cso_restore_samplers(ctx->cso_context); - cso_restore_sampler_textures(ctx->cso_context); + cso_restore_fragment_sampler_views(ctx->cso_context); cso_restore_viewport(ctx->cso_context); pipe_surface_reference(&surface, NULL); @@ -483,8 +482,12 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) mask->height = height; { - struct pipe_texture pt; + struct pipe_resource pt; + struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = ctx->pipe->screen; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view = NULL; + struct pipe_resource *texture; memset(&pt, 0, sizeof(pt)); pt.target = PIPE_TEXTURE_2D; @@ -493,10 +496,17 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) pt.width0 = width; pt.height0 = height; pt.depth0 = 1; - pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + pt.bind = PIPE_BIND_SAMPLER_VIEW; pt.compressed = 0; - mask->texture = screen->texture_create(screen, &pt); + texture = screen->resource_create(screen, &pt); + + if (texture) { + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + } + pipe_resource_reference(&texture, NULL); + mask->sampler_view = view; } vg_context_add_object(ctx, VG_OBJECT_MASK, mask); @@ -509,7 +519,7 @@ void mask_layer_destroy(struct vg_mask_layer *layer) struct vg_context *ctx = vg_current_context(); vg_context_remove_object(ctx, VG_OBJECT_MASK, layer); - pipe_texture_release(&layer->texture); + pipe_resource_release(&layer->texture); free(layer); } @@ -525,9 +535,9 @@ void mask_layer_fill(struct vg_mask_layer *layer, alpha_color[3] = value; surface = ctx->pipe->screen->get_tex_surface( - ctx->pipe->screen, layer->texture, + ctx->pipe->screen, layer->sampler_view->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_RENDER_TARGET); surface_fill(surface, layer->width, layer->height, @@ -545,10 +555,10 @@ void mask_copy(struct vg_mask_layer *layer, struct st_framebuffer *fb_buffers = ctx->draw_buffer; renderer_copy_texture(ctx->renderer, - layer->texture, + layer->sampler_view, sx, sy, sx + width, sy + height, - fb_buffers->alpha_mask, + fb_buffers->alpha_mask_view->texture, dx, dy, dx + width, dy + height); } @@ -562,8 +572,8 @@ static void mask_layer_render_to(struct vg_mask_layer *layer, struct pipe_screen *screen = ctx->pipe->screen; struct pipe_surface *surface; - surface = screen->get_tex_surface(screen, layer->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0, + PIPE_BIND_RENDER_TARGET); cso_save_framebuffer(ctx->cso_context); cso_save_fragment_shader(ctx->cso_context); @@ -604,8 +614,8 @@ void mask_render_to(struct path *path, struct vg_mask_layer *temp_layer; VGint width, height; - width = fb_buffers->alpha_mask->width0; - height = fb_buffers->alpha_mask->width0; + width = fb_buffers->alpha_mask_view->texture->width0; + height = fb_buffers->alpha_mask_view->texture->width0; temp_layer = mask_layer_create(width, height); @@ -622,7 +632,7 @@ void mask_using_layer(struct vg_mask_layer *layer, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(layer->texture, operation, + mask_using_texture(layer->sampler_view, operation, x, y, width, height); } @@ -644,7 +654,7 @@ void mask_using_image(struct vg_image *image, VGint x, VGint y, VGint width, VGint height) { - mask_using_texture(image->texture, operation, + mask_using_texture(image->sampler_view, operation, x, y, width, height); } @@ -654,7 +664,7 @@ void mask_fill(VGint x, VGint y, VGint width, VGint height, struct vg_context *ctx = vg_current_context(); VGfloat alpha_color[4] = {.0f, .0f, .0f, value}; struct pipe_surface *surf = alpha_mask_surface( - ctx, PIPE_BUFFER_USAGE_GPU_WRITE); + ctx, PIPE_BIND_RENDER_TARGET); #if DEBUG_MASKS debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n", @@ -672,7 +682,7 @@ void mask_fill(VGint x, VGint y, VGint width, VGint height, } VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_texture **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); @@ -680,7 +690,7 @@ VGint mask_bind_samplers(struct pipe_sampler_state **samplers, struct st_framebuffer *fb_buffers = ctx->draw_buffer; samplers[1] = &ctx->mask.sampler; - textures[1] = fb_buffers->alpha_mask; + sampler_views[1] = fb_buffers->alpha_mask_view; return 1; } else return 0; diff --git a/src/gallium/state_trackers/vega/mask.h b/src/gallium/state_trackers/vega/mask.h index 5eaaede0e3a..c626402c864 100644 --- a/src/gallium/state_trackers/vega/mask.h +++ b/src/gallium/state_trackers/vega/mask.h @@ -31,7 +31,7 @@ struct path; struct vg_image; -struct pipe_texture; +struct pipe_resource; struct vg_mask_layer *mask_layer_create(VGint width, VGint height); void mask_layer_destroy(struct vg_mask_layer *layer); @@ -63,6 +63,6 @@ void mask_fill(VGint x, VGint y, VGfloat value); VGint mask_bind_samplers(struct pipe_sampler_state **samplers, - struct pipe_texture **textures); + struct pipe_sampler_view **sampler_views); #endif diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index caf0c14b745..05540e82752 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -37,6 +37,7 @@ #include "util/u_format.h" #include "util/u_memory.h" #include "util/u_math.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -61,7 +62,7 @@ struct vg_paint { VGfloat vals[5]; VGint valsi[5]; } radial; - struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; struct pipe_sampler_state sampler; VGfloat *ramp_stops; @@ -72,13 +73,13 @@ struct vg_paint { } gradient; struct { - struct pipe_texture *texture; + struct pipe_sampler_view *sampler_view; VGTilingMode tiling_mode; struct pipe_sampler_state sampler; } pattern; /* XXX next 3 all unneded? */ - struct pipe_buffer *cbuf; + struct pipe_resource *cbuf; struct pipe_shader_state fs_state; void *fs; }; @@ -142,12 +143,12 @@ static INLINE void create_gradient_data(const VGfloat *ramp_stops, data[size-1] = last_color; } -static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) +static INLINE struct pipe_resource *create_gradient_texture(struct vg_paint *p) { struct pipe_context *pipe = p->base.ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_texture *tex = 0; - struct pipe_texture templ; + struct pipe_resource *tex = 0; + struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_1D; @@ -156,23 +157,43 @@ static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) templ.width0 = 1024; templ.height0 = 1; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + templ.bind = PIPE_BIND_SAMPLER_VIEW; - tex = screen->texture_create(screen, &templ); + tex = screen->resource_create(screen, &templ); { /* upload color_data */ struct pipe_transfer *transfer = - st_no_flush_get_tex_transfer(p->base.ctx, tex, 0, 0, 0, + st_no_flush_get_transfer(p->base.ctx, tex, 0, 0, 0, PIPE_TRANSFER_WRITE, 0, 0, 1024, 1); - void *map = screen->transfer_map(screen, transfer); + void *map = pipe->transfer_map(pipe, transfer); memcpy(map, p->gradient.color_data, sizeof(VGint)*1024); - screen->transfer_unmap(screen, transfer); - screen->tex_transfer_destroy(transfer); + pipe->transfer_unmap(pipe, transfer); + pipe->transfer_destroy(pipe, transfer); } return tex; } +static INLINE struct pipe_sampler_view *create_gradient_sampler_view(struct vg_paint *p) +{ + struct pipe_context *pipe = p->base.ctx->pipe; + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_gradient_texture(p); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + struct vg_paint * paint_create(struct vg_context *ctx) { struct vg_paint *paint = CALLOC_STRUCT(vg_paint); @@ -207,8 +228,9 @@ struct vg_paint * paint_create(struct vg_context *ctx) void paint_destroy(struct vg_paint *paint) { struct vg_context *ctx = paint->base.ctx; - if (paint->pattern.texture) - pipe_texture_reference(&paint->pattern.texture, NULL); + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); if (ctx) vg_context_remove_object(ctx, VG_OBJECT_PAINT, paint); @@ -329,8 +351,8 @@ static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer) map[4] = 0.f; map[5] = 1.f; - map[6] = paint->pattern.texture->width0; - map[7] = paint->pattern.texture->height0; + map[6] = paint->pattern.sampler_view->texture->width0; + map[7] = paint->pattern.sampler_view->texture->height0; { struct matrix mat; memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix, @@ -394,12 +416,12 @@ void paint_set_ramp_stops(struct vg_paint *paint, const VGfloat *stops, create_gradient_data(stops, num / 5, paint->gradient.color_data, 1024); - if (paint->gradient.texture) { - pipe_texture_reference(&paint->gradient.texture, NULL); - paint->gradient.texture = 0; + if (paint->gradient.sampler_view) { + pipe_sampler_view_reference(&paint->gradient.sampler_view, NULL); + paint->gradient.sampler_view = NULL; } - paint->gradient.texture = create_gradient_texture(paint); + paint->gradient.sampler_view = create_gradient_sampler_view(paint); } void paint_set_colori(struct vg_paint *p, @@ -459,12 +481,12 @@ void paint_set_radial_gradient(struct vg_paint *paint, void paint_set_pattern(struct vg_paint *paint, struct vg_image *img) { - if (paint->pattern.texture) - pipe_texture_reference(&paint->pattern.texture, NULL); + if (paint->pattern.sampler_view) + pipe_sampler_view_reference(&paint->pattern.sampler_view, NULL); - paint->pattern.texture = 0; - pipe_texture_reference(&paint->pattern.texture, - img->texture); + paint->pattern.sampler_view = NULL; + pipe_sampler_view_reference(&paint->pattern.sampler_view, + img->sampler_view); } void paint_set_pattern_tiling(struct vg_paint *paint, @@ -611,18 +633,18 @@ VGTilingMode paint_pattern_tiling(struct vg_paint *paint) } VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_texture **textures) + struct pipe_sampler_view **sampler_views) { struct vg_context *ctx = vg_current_context(); switch(paint->type) { case VG_PAINT_TYPE_LINEAR_GRADIENT: case VG_PAINT_TYPE_RADIAL_GRADIENT: { - if (paint->gradient.texture) { + if (paint->gradient.sampler_view) { paint->gradient.sampler.min_img_filter = image_sampler_filter(ctx); paint->gradient.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->gradient.sampler; - textures[0] = paint->gradient.texture; + sampler_views[0] = paint->gradient.sampler_view; return 1; } } @@ -634,14 +656,11 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa paint->pattern.sampler.min_img_filter = image_sampler_filter(ctx); paint->pattern.sampler.mag_img_filter = image_sampler_filter(ctx); samplers[0] = &paint->pattern.sampler; - textures[0] = paint->pattern.texture; + sampler_views[0] = paint->pattern.sampler_view; return 1; } break; default: - samplers[0] = &paint->pattern.sampler; /* dummy */ - textures[0] = 0; - return 0; break; } return 0; @@ -650,7 +669,7 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa void paint_resolve_type(struct vg_paint *paint) { if (paint->type == VG_PAINT_TYPE_PATTERN && - !paint->pattern.texture) { + !paint->pattern.sampler_view) { paint->type = VG_PAINT_TYPE_COLOR; } } diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h index 999b5c167ca..012cd3e5618 100644 --- a/src/gallium/state_trackers/vega/paint.h +++ b/src/gallium/state_trackers/vega/paint.h @@ -35,7 +35,7 @@ struct vg_paint; struct vg_image; struct pipe_sampler_state; -struct pipe_texture; +struct pipe_resource; struct vg_paint *paint_create(struct vg_context *ctx); void paint_destroy(struct vg_paint *paint); @@ -108,7 +108,7 @@ VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint); VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers, - struct pipe_texture **textures); + struct pipe_sampler_view **sampler_views); VGint paint_constant_buffer_size(struct vg_paint *paint); void paint_fill_constant_buffer(struct vg_paint *paint, diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c index c06dbf52069..d2b7e489124 100644 --- a/src/gallium/state_trackers/vega/polygon.c +++ b/src/gallium/state_trackers/vega/polygon.c @@ -58,7 +58,7 @@ struct polygon VGint num_verts; VGboolean dirty; - struct pipe_buffer *vbuf; + struct pipe_resource *vbuf; struct pipe_screen *screen; }; @@ -110,7 +110,7 @@ struct polygon * polygon_create_from_data(float *data, int size) void polygon_destroy(struct polygon *poly) { if (poly->vbuf) - pipe_buffer_reference(&poly->vbuf, NULL); + pipe_resource_reference(&poly->vbuf, NULL); free(poly->data); free(poly); @@ -272,13 +272,14 @@ static void draw_polygon(struct vg_context *ctx, if (poly->vbuf == NULL || poly->dirty) { if (poly->vbuf) { - pipe_buffer_reference(&poly->vbuf, + pipe_resource_reference(&poly->vbuf, NULL); } poly->screen = pipe->screen; poly->vbuf= pipe_user_buffer_create(poly->screen, poly->data, - vert_size); + vert_size, + PIPE_BIND_VERTEX_BUFFER); poly->dirty = VG_FALSE; } @@ -292,12 +293,12 @@ static void draw_polygon(struct vg_context *ctx, pipe->set_vertex_buffers(pipe, 1, &vbuffer); /* tell pipe about the vertex attributes */ + memset(&velement, 0, sizeof(velement)); velement.src_offset = 0; velement.instance_divisor = 0; velement.vertex_buffer_index = 0; velement.src_format = PIPE_FORMAT_R32G32_FLOAT; - velement.nr_components = COMPONENTS; - pipe->set_vertex_elements(pipe, 1, &velement); + cso_set_vertex_elements(ctx->cso_context, 1, &velement); /* draw */ pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c index 05620efa9c0..48fbc3b330e 100644 --- a/src/gallium/state_trackers/vega/renderer.c +++ b/src/gallium/state_trackers/vega/renderer.c @@ -39,6 +39,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "cso_cache/cso_context.h" @@ -60,7 +61,7 @@ static void setup_shaders(struct renderer *ctx) ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D); } -static struct pipe_buffer * +static struct pipe_resource * setup_vertex_data(struct renderer *ctx, float x0, float y0, float x1, float y1, float z) { @@ -90,10 +91,11 @@ setup_vertex_data(struct renderer *ctx, return pipe_user_buffer_create( ctx->pipe->screen, ctx->vertices, - sizeof(ctx->vertices) ); + sizeof(ctx->vertices), + PIPE_BIND_VERTEX_BUFFER); } -static struct pipe_buffer * +static struct pipe_resource * setup_vertex_data_tex(struct renderer *ctx, float x0, float y0, float x1, float y1, float s0, float t0, float s1, float t1, @@ -125,11 +127,12 @@ setup_vertex_data_tex(struct renderer *ctx, return pipe_user_buffer_create( ctx->pipe->screen, ctx->vertices, - sizeof(ctx->vertices) ); + sizeof(ctx->vertices), + PIPE_BIND_VERTEX_BUFFER); } -static struct pipe_buffer * +static struct pipe_resource * setup_vertex_data_qtex(struct renderer *ctx, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, @@ -162,7 +165,8 @@ setup_vertex_data_qtex(struct renderer *ctx, return pipe_user_buffer_create( ctx->pipe->screen, ctx->vertices, - sizeof(ctx->vertices) ); + sizeof(ctx->vertices), + PIPE_BIND_VERTEX_BUFFER); } struct renderer * renderer_create(struct vg_context *owner) @@ -205,30 +209,31 @@ void renderer_draw_quad(struct renderer *r, VGfloat x2, VGfloat y2, VGfloat depth) { - struct pipe_buffer *buf; + struct pipe_resource *buf; buf = setup_vertex_data(r, x1, y1, x2, y2, depth); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(r->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference( &buf, + pipe_resource_reference( &buf, NULL ); } } void renderer_draw_texture(struct renderer *r, - struct pipe_texture *tex, + struct pipe_resource *tex, VGfloat x1offset, VGfloat y1offset, VGfloat x2offset, VGfloat y2offset, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf; + struct pipe_resource *buf; VGfloat s0, t0, s1, t1; assert(tex->width0 != 0); @@ -248,12 +253,13 @@ void renderer_draw_texture(struct renderer *r, s0, t0, s1, t1, 0.0f); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference( &buf, + pipe_resource_reference( &buf, NULL ); } @@ -261,24 +267,25 @@ void renderer_draw_texture(struct renderer *r, } void renderer_copy_texture(struct renderer *ctx, - struct pipe_texture *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, - struct pipe_texture *dst, + struct pipe_resource *dst, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2) { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_buffer *buf; + struct pipe_resource *tex = src->texture; + struct pipe_resource *buf; struct pipe_surface *dst_surf = screen->get_tex_surface( screen, dst, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_RENDER_TARGET); struct pipe_framebuffer_state fb; float s0, t0, s1, t1; - assert(src->width0 != 0); - assert(src->height0 != 0); + assert(tex->width0 != 0); + assert(tex->height0 != 0); assert(dst->width0 != 0); assert(dst->height0 != 0); @@ -288,10 +295,10 @@ void renderer_copy_texture(struct renderer *ctx, #endif #if 1 - s0 = sx1 / src->width0; - s1 = sx2 / src->width0; - t0 = sy1 / src->height0; - t1 = sy2 / src->height0; + s0 = sx1 / tex->width0; + s1 = sx2 / tex->width0; + t0 = sy1 / tex->height0; + t1 = sy2 / tex->height0; #else s0 = 0; s1 = 1; @@ -300,12 +307,12 @@ void renderer_copy_texture(struct renderer *ctx, #endif assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + PIPE_BIND_RENDER_TARGET, 0)); /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -343,7 +350,7 @@ void renderer_copy_texture(struct renderer *ctx, vg_set_viewport(ctx->owner, VEGA_Y0_TOP); /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &src); + cso_set_fragment_sampler_views(ctx->cso, 1, &src); /* shaders */ cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); @@ -370,19 +377,20 @@ void renderer_copy_texture(struct renderer *ctx, 0.0f); if (buf) { + cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems); util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference( &buf, + pipe_resource_reference( &buf, NULL ); } /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_fragment_shader(ctx->cso); @@ -402,8 +410,10 @@ void renderer_copy_surface(struct renderer *ctx, { struct pipe_context *pipe = ctx->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_buffer *buf; - struct pipe_texture texTemp, *tex; + struct pipe_resource *buf; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + struct pipe_resource texTemp, *tex; struct pipe_surface *texSurf; struct pipe_framebuffer_state fb; struct st_framebuffer *stfb = ctx->owner->draw_buffer; @@ -430,11 +440,11 @@ void renderer_copy_surface(struct renderer *ctx, } assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); + PIPE_BIND_SAMPLER_VIEW, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); + PIPE_BIND_SAMPLER_VIEW, 0)); assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); + PIPE_BIND_RENDER_TARGET, 0)); /* * XXX for now we're always creating a temporary texture. @@ -450,12 +460,18 @@ void renderer_copy_surface(struct renderer *ctx, texTemp.height0 = srcH; texTemp.depth0 = 1; - tex = screen->texture_create(screen, &texTemp); + tex = screen->resource_create(screen, &texTemp); if (!tex) return; + u_sampler_view_default_template(&view_templ, tex, tex->format); + view = pipe->create_sampler_view(pipe, tex, &view_templ); + + if (!view) + return; + texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_RENDER_TARGET); /* load temp texture */ if (pipe->surface_copy) { @@ -476,7 +492,7 @@ void renderer_copy_surface(struct renderer *ctx, /* save state (restored below) */ cso_save_blend(ctx->cso); cso_save_samplers(ctx->cso); - cso_save_sampler_textures(ctx->cso); + cso_save_fragment_sampler_views(ctx->cso); cso_save_framebuffer(ctx->cso); cso_save_fragment_shader(ctx->cso); cso_save_vertex_shader(ctx->cso); @@ -512,7 +528,7 @@ void renderer_copy_surface(struct renderer *ctx, } /* texture */ - cso_set_sampler_textures(ctx->cso, 1, &tex); + cso_set_fragment_sampler_views(ctx->cso, 1, &view); /* shaders */ cso_set_fragment_shader_handle(ctx->cso, ctx->fs); @@ -535,12 +551,13 @@ void renderer_copy_surface(struct renderer *ctx, (float) dstX1, (float) dstY1, z); if (buf) { + cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems); util_draw_vertex_buffer(ctx->pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference( &buf, + pipe_resource_reference( &buf, NULL ); } @@ -548,17 +565,18 @@ void renderer_copy_surface(struct renderer *ctx, /* restore state we changed */ cso_restore_blend(ctx->cso); cso_restore_samplers(ctx->cso); - cso_restore_sampler_textures(ctx->cso); + cso_restore_fragment_sampler_views(ctx->cso); cso_restore_framebuffer(ctx->cso); cso_restore_fragment_shader(ctx->cso); cso_restore_vertex_shader(ctx->cso); cso_restore_viewport(ctx->cso); - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&tex, NULL); + pipe_sampler_view_reference(&view, NULL); } void renderer_texture_quad(struct renderer *r, - struct pipe_texture *tex, + struct pipe_resource *tex, VGfloat x1offset, VGfloat y1offset, VGfloat x2offset, VGfloat y2offset, VGfloat x1, VGfloat y1, @@ -567,7 +585,7 @@ void renderer_texture_quad(struct renderer *r, VGfloat x4, VGfloat y4) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf; + struct pipe_resource *buf; VGfloat s0, t0, s1, t1; assert(tex->width0 != 0); @@ -587,12 +605,13 @@ void renderer_texture_quad(struct renderer *r, s0, t0, s1, t1, 0.0f); if (buf) { + cso_set_vertex_elements(r->cso, 2, r->owner->velems); util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, /* verts */ 2); /* attribs/vert */ - pipe_buffer_reference(&buf, + pipe_resource_reference(&buf, NULL); } diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h index 990cd32c313..b1a9fb58be6 100644 --- a/src/gallium/state_trackers/vega/renderer.h +++ b/src/gallium/state_trackers/vega/renderer.h @@ -32,7 +32,8 @@ struct renderer; struct vg_context; -struct pipe_texture; +struct pipe_resource; +struct pipe_sampler_view; struct pipe_surface; struct renderer *renderer_create(struct vg_context *owner); @@ -43,13 +44,13 @@ void renderer_draw_quad(struct renderer *, VGfloat x2, VGfloat y2, VGfloat depth); void renderer_draw_texture(struct renderer *, - struct pipe_texture *texture, + struct pipe_resource *texture, VGfloat x1offset, VGfloat y1offset, VGfloat x2offset, VGfloat y2offset, VGfloat x1, VGfloat y1, VGfloat x2, VGfloat y2); void renderer_texture_quad(struct renderer *, - struct pipe_texture *texture, + struct pipe_resource *texture, VGfloat x1offset, VGfloat y1offset, VGfloat x2offset, VGfloat y2offset, VGfloat x1, VGfloat y1, @@ -57,10 +58,10 @@ void renderer_texture_quad(struct renderer *, VGfloat x3, VGfloat y3, VGfloat x4, VGfloat y4); void renderer_copy_texture(struct renderer *r, - struct pipe_texture *src, + struct pipe_sampler_view *src, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, - struct pipe_texture *dst, + struct pipe_resource *dst, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2); void renderer_copy_surface(struct renderer *r, diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c index 0e71a507bff..6eef94ce767 100644 --- a/src/gallium/state_trackers/vega/shader.c +++ b/src/gallium/state_trackers/vega/shader.c @@ -51,7 +51,7 @@ struct shader { VGImageMode image_mode; float constants[MAX_CONSTANTS]; - struct pipe_buffer *cbuf; + struct pipe_resource *cbuf; struct pipe_shader_state fs_state; void *fs; }; @@ -96,7 +96,7 @@ static void setup_constant_buffer(struct shader *shader) { struct vg_context *ctx = shader->context; struct pipe_context *pipe = shader->context->pipe; - struct pipe_buffer **cbuf = &shader->cbuf; + struct pipe_resource **cbuf = &shader->cbuf; VGint param_bytes = paint_constant_buffer_size(shader->paint); float temp_buf[MAX_CONSTANTS]; @@ -106,12 +106,13 @@ static void setup_constant_buffer(struct shader *shader) if (*cbuf == NULL || memcmp(temp_buf, shader->constants, param_bytes) != 0) { - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); memcpy(shader->constants, temp_buf, param_bytes); *cbuf = pipe_user_buffer_create(pipe->screen, &shader->constants, - sizeof(shader->constants)); + sizeof(shader->constants), + PIPE_BIND_VERTEX_BUFFER); } ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf); @@ -119,7 +120,7 @@ static void setup_constant_buffer(struct shader *shader) static VGint blend_bind_samplers(struct vg_context *ctx, struct pipe_sampler_state **samplers, - struct pipe_texture **textures) + struct pipe_sampler_view **sampler_views) { VGBlendMode bmode = ctx->state.vg.blend_mode; @@ -132,15 +133,15 @@ static VGint blend_bind_samplers(struct vg_context *ctx, vg_prepare_blend_surface(ctx); samplers[2] = &ctx->blend_sampler; - textures[2] = stfb->blend_texture; + sampler_views[2] = stfb->blend_texture_view; - if (!samplers[0] || !textures[0]) { + if (!samplers[0] || !sampler_views[0]) { samplers[0] = samplers[2]; - textures[0] = textures[2]; + sampler_views[0] = sampler_views[2]; } - if (!samplers[1] || !textures[1]) { + if (!samplers[1] || !sampler_views[1]) { samplers[1] = samplers[0]; - textures[1] = textures[0]; + sampler_views[1] = sampler_views[0]; } return 1; @@ -151,7 +152,7 @@ static VGint blend_bind_samplers(struct vg_context *ctx, static void setup_samplers(struct shader *shader) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; - struct pipe_texture *textures[PIPE_MAX_SAMPLERS]; + struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct vg_context *ctx = shader->context; /* a little wonky: we use the num as a boolean that just says * whether any sampler/textures have been set. the actual numbering @@ -167,20 +168,20 @@ static void setup_samplers(struct shader *shader) samplers[1] = NULL; samplers[2] = NULL; samplers[3] = NULL; - textures[0] = NULL; - textures[1] = NULL; - textures[2] = NULL; - textures[3] = NULL; - - num += paint_bind_samplers(shader->paint, samplers, textures); - num += mask_bind_samplers(samplers, textures); - num += blend_bind_samplers(ctx, samplers, textures); + sampler_views[0] = NULL; + sampler_views[1] = NULL; + sampler_views[2] = NULL; + sampler_views[3] = NULL; + + num += paint_bind_samplers(shader->paint, samplers, sampler_views); + num += mask_bind_samplers(samplers, sampler_views); + num += blend_bind_samplers(ctx, samplers, sampler_views); if (shader->drawing_image && shader->image) - num += image_bind_samplers(shader->image, samplers, textures); + num += image_bind_samplers(shader->image, samplers, sampler_views); if (num) { cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(ctx->cso_context, 4, textures); + cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views); } } diff --git a/src/gallium/state_trackers/vega/st_inlines.h b/src/gallium/state_trackers/vega/st_inlines.h index 419151c3aee..7eaa67c76ae 100644 --- a/src/gallium/state_trackers/vega/st_inlines.h +++ b/src/gallium/state_trackers/vega/st_inlines.h @@ -42,8 +42,8 @@ #include "pipe/p_state.h" static INLINE struct pipe_transfer * -st_cond_flush_get_tex_transfer(struct vg_context *st, - struct pipe_texture *pt, +st_cond_flush_get_transfer(struct vg_context *st, + struct pipe_resource *pt, unsigned int face, unsigned int level, unsigned int zslice, @@ -51,22 +51,15 @@ st_cond_flush_get_tex_transfer(struct vg_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; struct pipe_context *pipe = st->pipe; - unsigned referenced = - pipe->is_texture_referenced(pipe, pt, face, level); - if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || - (usage & PIPE_TRANSFER_WRITE))) - vgFlush(); - - return screen->get_tex_transfer(screen, pt, face, level, zslice, usage, - x, y, w, h); + return pipe_get_transfer(pipe, pt, face, level, zslice, usage, + x, y, w, h); } static INLINE struct pipe_transfer * -st_no_flush_get_tex_transfer(struct vg_context *st, - struct pipe_texture *pt, +st_no_flush_get_transfer(struct vg_context *st, + struct pipe_resource *pt, unsigned int face, unsigned int level, unsigned int zslice, @@ -74,84 +67,55 @@ st_no_flush_get_tex_transfer(struct vg_context *st, unsigned int x, unsigned int y, unsigned int w, unsigned int h) { - struct pipe_screen *screen = st->pipe->screen; - - return screen->get_tex_transfer(screen, pt, face, level, - zslice, usage, x, y, w, h); -} - -static INLINE void * -st_cond_flush_pipe_buffer_map(struct vg_context *st, - struct pipe_buffer *buf, - unsigned int map_flags) -{ struct pipe_context *pipe = st->pipe; - unsigned int referenced = pipe->is_buffer_referenced(pipe, buf); - - if (referenced && ((referenced & PIPE_REFERENCED_FOR_WRITE) || - (map_flags & PIPE_BUFFER_USAGE_CPU_WRITE))) - vgFlush(); - return pipe_buffer_map(pipe->screen, buf, map_flags); -} - -static INLINE void * -st_no_flush_pipe_buffer_map(struct vg_context *st, - struct pipe_buffer *buf, - unsigned int map_flags) -{ - return pipe_buffer_map(st->pipe->screen, buf, map_flags); + return pipe_get_transfer(pipe, pt, face, level, + zslice, usage, x, y, w, h); } static INLINE void st_cond_flush_pipe_buffer_write(struct vg_context *st, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned int offset, unsigned int size, const void * data) { struct pipe_context *pipe = st->pipe; - if (pipe->is_buffer_referenced(pipe, buf)) - vgFlush(); - - pipe_buffer_write(pipe->screen, buf, offset, size, data); + pipe_buffer_write(pipe, buf, offset, size, data); } static INLINE void st_no_flush_pipe_buffer_write(struct vg_context *st, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned int offset, unsigned int size, const void * data) { - pipe_buffer_write(st->pipe->screen, buf, offset, size, data); + pipe_buffer_write(st->pipe, buf, offset, size, data); } static INLINE void st_cond_flush_pipe_buffer_read(struct vg_context *st, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned int offset, unsigned int size, void * data) { struct pipe_context *pipe = st->pipe; - if (pipe->is_buffer_referenced(pipe, buf) & PIPE_REFERENCED_FOR_WRITE) - vgFlush(); - - pipe_buffer_read(pipe->screen, buf, offset, size, data); + pipe_buffer_read(pipe, buf, offset, size, data); } static INLINE void st_no_flush_pipe_buffer_read(struct vg_context *st, - struct pipe_buffer *buf, + struct pipe_resource *buf, unsigned int offset, unsigned int size, void * data) { - pipe_buffer_read(st->pipe->screen, buf, offset, size, data); + pipe_buffer_read(st->pipe, buf, offset, size, data); } #endif diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c index 426bf9bc62b..1a8952ce34a 100644 --- a/src/gallium/state_trackers/vega/vg_context.c +++ b/src/gallium/state_trackers/vega/vg_context.c @@ -32,6 +32,7 @@ #include "shader.h" #include "asm_util.h" #include "st_inlines.h" +#include "vg_manager.h" #include "pipe/p_context.h" #include "util/u_inlines.h" @@ -42,6 +43,7 @@ #include "util/u_simple_shaders.h" #include "util/u_memory.h" #include "util/u_blit.h" +#include "util/u_sampler.h" struct vg_context *_vg_context = 0; @@ -72,6 +74,7 @@ struct vg_context * vg_create_context(struct pipe_context *pipe, struct vg_context *share) { struct vg_context *ctx; + unsigned i; ctx = CALLOC_STRUCT(vg_context); @@ -103,6 +106,13 @@ struct vg_context * vg_create_context(struct pipe_context *pipe, ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; ctx->blend_sampler.normalized_coords = 0; + for (i = 0; i < 2; i++) { + ctx->velems[i].src_offset = i * 4 * sizeof(float); + ctx->velems[i].instance_divisor = 0; + ctx->velems[i].vertex_buffer_index = 0; + ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } + vg_set_error(ctx, VG_NO_ERROR); ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); @@ -122,8 +132,8 @@ struct vg_context * vg_create_context(struct pipe_context *pipe, void vg_destroy_context(struct vg_context *ctx) { - struct pipe_buffer **cbuf = &ctx->mask.cbuf; - struct pipe_buffer **vsbuf = &ctx->vs_const_buffer; + struct pipe_resource **cbuf = &ctx->mask.cbuf; + struct pipe_resource **vsbuf = &ctx->vs_const_buffer; util_destroy_blit(ctx->blit); renderer_destroy(ctx->renderer); @@ -132,10 +142,10 @@ void vg_destroy_context(struct vg_context *ctx) paint_destroy(ctx->default_paint); if (*cbuf) - pipe_buffer_reference(cbuf, NULL); + pipe_resource_reference(cbuf, NULL); if (*vsbuf) - pipe_buffer_reference(vsbuf, NULL); + pipe_resource_reference(vsbuf, NULL); if (ctx->clear.fs) { cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs); @@ -297,6 +307,8 @@ static void update_clip_state(struct vg_context *ctx) void vg_validate_state(struct vg_context *ctx) { + vg_manager_validate_framebuffer(ctx); + if ((ctx->state.dirty & BLEND_DIRTY)) { struct pipe_blend_state *blend = &ctx->state.g3d.blend; memset(blend, 0, sizeof(struct pipe_blend_state)); @@ -369,14 +381,14 @@ void vg_validate_state(struct vg_context *ctx) 2.f/fb->width, 2.f/fb->height, 1, 1, -1, -1, 0, 0 }; - struct pipe_buffer **cbuf = &ctx->vs_const_buffer; + struct pipe_resource **cbuf = &ctx->vs_const_buffer; vg_set_viewport(ctx, VEGA_Y0_BOTTOM); - pipe_buffer_reference(cbuf, NULL); - *cbuf = pipe_buffer_create(ctx->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, - param_bytes); + pipe_resource_reference(cbuf, NULL); + *cbuf = pipe_buffer_create(ctx->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, + param_bytes); if (*cbuf) { st_no_flush_pipe_buffer_write(ctx, *cbuf, @@ -425,19 +437,25 @@ void vg_prepare_blend_surface(struct vg_context *ctx) { struct pipe_surface *dest_surface = NULL; struct pipe_context *pipe = ctx->pipe; + struct pipe_sampler_view *view; + struct pipe_sampler_view view_templ; struct st_framebuffer *stfb = ctx->draw_buffer; struct st_renderbuffer *strb = stfb->strb; /* first finish all pending rendering */ vgFinish(); + u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format); + view = pipe->create_sampler_view(pipe, strb->texture, &view_templ); + dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION | + PIPE_BIND_RENDER_TARGET); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - strb->texture, + view, 0, strb->height, strb->width, 0, dest_surface, @@ -450,6 +468,8 @@ void vg_prepare_blend_surface(struct vg_context *ctx) /* make sure it's complete */ vgFinish(); + + pipe_sampler_view_reference(&view, NULL); } @@ -466,13 +486,14 @@ void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) vgFinish(); dest_surface = pipe->screen->get_tex_surface(pipe->screen, - stfb->blend_texture, + stfb->blend_texture_view->texture, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION | + PIPE_BIND_RENDER_TARGET); /* flip it, because we want to use it as a sampler */ util_blit_pixels_tex(ctx->blit, - stfb->alpha_mask, + stfb->alpha_mask_view, 0, strb->height, strb->width, 0, dest_surface, diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h index bc88c8d139d..dac67192a54 100644 --- a/src/gallium/state_trackers/vega/vg_context.h +++ b/src/gallium/state_trackers/vega/vg_context.h @@ -33,6 +33,7 @@ #include "pipe/p_state.h" #include "util/u_pointer.h" #include "util/u_math.h" +#include "state_tracker/st_api.h" #include "cso_cache/cso_hash.h" #include "cso_cache/cso_context.h" @@ -45,7 +46,7 @@ struct vg_shader; struct st_renderbuffer { enum pipe_format format; struct pipe_surface *surface; - struct pipe_texture *texture; + struct pipe_resource *texture; VGint width, height; }; @@ -54,9 +55,13 @@ struct st_framebuffer { struct st_renderbuffer *strb; struct st_renderbuffer *dsrb; - struct pipe_texture *alpha_mask; + struct pipe_sampler_view *alpha_mask_view; - struct pipe_texture *blend_texture; + struct pipe_sampler_view *blend_texture_view; + + + struct st_framebuffer_iface *iface; + enum st_attachment_type strb_att; void *privateData; }; @@ -84,6 +89,8 @@ enum dirty_state { struct vg_context { + struct st_context_iface iface; + struct pipe_context *pipe; struct { @@ -101,6 +108,7 @@ struct vg_context VGErrorCode _error; struct st_framebuffer *draw_buffer; + int32_t draw_buffer_invalid; struct cso_hash *owned_objects[VG_OBJECT_LAST]; @@ -113,7 +121,7 @@ struct vg_context } clear; struct { - struct pipe_buffer *cbuf; + struct pipe_resource *cbuf; struct pipe_sampler_state sampler; struct vg_shader *union_fs; @@ -126,7 +134,7 @@ struct vg_context struct cso_context *cso_context; - struct pipe_buffer *stencil_quad; + struct pipe_resource *stencil_quad; VGfloat stencil_vertices[4][2][4]; struct renderer *renderer; @@ -135,7 +143,7 @@ struct vg_context struct pipe_sampler_state blend_sampler; struct { - struct pipe_buffer *buffer; + struct pipe_resource *buffer; void *color_matrix_fs; } filter; struct vg_paint *default_paint; @@ -145,7 +153,8 @@ struct vg_context struct vg_shader *plain_vs; struct vg_shader *clear_vs; struct vg_shader *texture_vs; - struct pipe_buffer *vs_const_buffer; + struct pipe_resource *vs_const_buffer; + struct pipe_vertex_element velems[2]; }; struct vg_object { diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c new file mode 100644 index 00000000000..aecac28e7ee --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.c @@ -0,0 +1,562 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright 2009 VMware, Inc. All Rights Reserved. + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "state_tracker/st_api.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_sampler.h" + +#include "vg_manager.h" +#include "vg_context.h" +#include "image.h" +#include "mask.h" + +static struct pipe_resource * +create_texture(struct pipe_context *pipe, enum pipe_format format, + VGint width, VGint height) +{ + struct pipe_resource templ; + + memset(&templ, 0, sizeof(templ)); + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + } + else { + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; + } + + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { + templ.bind = PIPE_BIND_DEPTH_STENCIL; + } else { + templ.bind = (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SAMPLER_VIEW); + } + + return pipe->screen->resource_create(pipe->screen, &templ); +} + +static struct pipe_sampler_view * +create_tex_and_view(struct pipe_context *pipe, enum pipe_format format, + VGint width, VGint height) +{ + struct pipe_resource *texture; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *view; + + texture = create_texture(pipe, format, width, height); + + if (!texture) + return NULL; + + u_sampler_view_default_template(&view_templ, texture, texture->format); + view = pipe->create_sampler_view(pipe, texture, &view_templ); + /* want the texture to go away if the view is freed */ + pipe_resource_reference(&texture, NULL); + + return view; +} + +static void +setup_new_alpha_mask(struct vg_context *ctx, struct st_framebuffer *stfb) +{ + struct pipe_context *pipe = ctx->pipe; + struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view; + + /* + we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to + this texture and use it as a sampler, so while this wastes some + space it makes both of those a lot simpler + */ + stfb->alpha_mask_view = create_tex_and_view(pipe, + PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height); + + if (!stfb->alpha_mask_view) { + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); + return; + } + + /* XXX could this call be avoided? */ + vg_validate_state(ctx); + + /* alpha mask starts with 1.f alpha */ + mask_fill(0, 0, stfb->width, stfb->height, 1.f); + + /* if we had an old surface copy it over */ + if (old_sampler_view) { + struct pipe_surface *surface = pipe->screen->get_tex_surface( + pipe->screen, + stfb->alpha_mask_view->texture, + 0, 0, 0, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLIT_DESTINATION); + struct pipe_surface *old_surface = pipe->screen->get_tex_surface( + pipe->screen, + old_sampler_view->texture, + 0, 0, 0, + PIPE_BIND_BLIT_SOURCE); + pipe->surface_copy(pipe, + surface, + 0, 0, + old_surface, + 0, 0, + MIN2(old_surface->width, surface->width), + MIN2(old_surface->height, surface->height)); + if (surface) + pipe_surface_reference(&surface, NULL); + if (old_surface) + pipe_surface_reference(&old_surface, NULL); + } + + /* Free the old texture + */ + if (old_sampler_view) + pipe_sampler_view_reference(&old_sampler_view, NULL); +} + +static boolean +vg_context_update_depth_stencil_rb(struct vg_context * ctx, + uint width, uint height) +{ + struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb; + struct pipe_context *pipe = ctx->pipe; + unsigned surface_usage; + + if ((dsrb->width == width && dsrb->height == height) && dsrb->texture) + return FALSE; + + /* unreference existing ones */ + pipe_surface_reference(&dsrb->surface, NULL); + pipe_resource_reference(&dsrb->texture, NULL); + dsrb->width = dsrb->height = 0; + + /* Probably need dedicated flags for surface usage too: + */ + surface_usage = (PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLIT_SOURCE | + PIPE_BIND_BLIT_DESTINATION); + + dsrb->texture = create_texture(pipe, dsrb->format, width, height); + if (!dsrb->texture) + return TRUE; + + dsrb->surface = pipe->screen->get_tex_surface(pipe->screen, + dsrb->texture, + 0, 0, 0, + surface_usage); + if (!dsrb->surface) { + pipe_resource_reference(&dsrb->texture, NULL); + return TRUE; + } + + dsrb->width = width; + dsrb->height = height; + + assert(dsrb->surface->width == width); + assert(dsrb->surface->height == height); + + return TRUE; +} + +static boolean +vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt) +{ + struct st_renderbuffer *strb = ctx->draw_buffer->strb; + struct pipe_screen *screen = ctx->pipe->screen; + + if (strb->texture == pt) { + pipe_resource_reference(&pt, NULL); + return FALSE; + } + + /* unreference existing ones */ + pipe_surface_reference(&strb->surface, NULL); + pipe_resource_reference(&strb->texture, NULL); + strb->width = strb->height = 0; + + strb->texture = pt; + strb->surface = screen->get_tex_surface(screen, strb->texture, 0, 0, 0, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_BLIT_SOURCE | + PIPE_BIND_BLIT_DESTINATION); + if (!strb->surface) { + pipe_resource_reference(&strb->texture, NULL); + return TRUE; + } + + strb->width = pt->width0; + strb->height = pt->height0; + + return TRUE; +} + +static void +vg_context_update_draw_buffer(struct vg_context *ctx, struct pipe_resource *pt) +{ + struct st_framebuffer *stfb = ctx->draw_buffer; + boolean new_cbuf, new_zsbuf, new_size; + + new_cbuf = vg_context_update_color_rb(ctx, pt); + new_zsbuf = + vg_context_update_depth_stencil_rb(ctx, pt->width0, pt->height0); + + new_size = (stfb->width != pt->width0 || stfb->height != pt->height0); + stfb->width = pt->width0; + stfb->height = pt->height0; + + if (new_cbuf || new_zsbuf || new_size) { + struct pipe_framebuffer_state *state = &ctx->state.g3d.fb; + + memset(state, 0, sizeof(struct pipe_framebuffer_state)); + state->width = stfb->width; + state->height = stfb->height; + state->nr_cbufs = 1; + state->cbufs[0] = stfb->strb->surface; + state->zsbuf = stfb->dsrb->surface; + + cso_set_framebuffer(ctx->cso_context, state); + } + + if (new_zsbuf || new_size) { + ctx->state.dirty |= VIEWPORT_DIRTY; + ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/ + + ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0); + + /* we need all the other state already set */ + + setup_new_alpha_mask(ctx, stfb); + + pipe_sampler_view_reference( &stfb->blend_texture_view, NULL); + stfb->blend_texture_view = create_tex_and_view(ctx->pipe, + PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height); + } +} + +/** + * Flush the front buffer if the current context renders to the front buffer. + */ +void +vg_manager_flush_frontbuffer(struct vg_context *ctx) +{ + struct st_framebuffer *stfb = ctx->draw_buffer; + + if (!stfb) + return; + + switch (stfb->strb_att) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + stfb->iface->flush_front(stfb->iface, stfb->strb_att); + break; + default: + break; + } +} + +/** + * Re-validate the framebuffer. + */ +void +vg_manager_validate_framebuffer(struct vg_context *ctx) +{ + struct st_framebuffer *stfb = ctx->draw_buffer; + struct pipe_resource *pt; + + /* no binding surface */ + if (!stfb) + return; + + if (!p_atomic_read(&ctx->draw_buffer_invalid)) + return; + + /* validate the fb */ + if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt) + return; + + /* + * unset draw_buffer_invalid first because vg_context_update_draw_buffer + * will cause the framebuffer to be validated again because of a call to + * vg_validate_state + */ + p_atomic_set(&ctx->draw_buffer_invalid, FALSE); + vg_context_update_draw_buffer(ctx, pt); +} + + +static void +vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stfbi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); +} + +static void +vg_context_flush(struct st_context_iface *stctxi, unsigned flags, + struct pipe_fence_handle **fence) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + ctx->pipe->flush(ctx->pipe, flags, fence); + if (flags & PIPE_FLUSH_RENDER_CACHE) + vg_manager_flush_frontbuffer(ctx); +} + +static void +vg_context_destroy(struct st_context_iface *stctxi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + vg_destroy_context(ctx); +} + +static struct st_context_iface * +vg_api_create_context(struct st_api *stapi, struct st_manager *smapi, + const struct st_visual *visual, + struct st_context_iface *shared_stctxi) +{ + struct vg_context *shared_ctx = (struct vg_context *) shared_stctxi; + struct vg_context *ctx; + struct pipe_context *pipe; + + pipe = smapi->screen->context_create(smapi->screen, NULL); + if (!pipe) + return NULL; + ctx = vg_create_context(pipe, NULL, shared_ctx); + if (!ctx) { + pipe->destroy(pipe); + return NULL; + } + + ctx->iface.destroy = vg_context_destroy; + + ctx->iface.notify_invalid_framebuffer = + vg_context_notify_invalid_framebuffer; + ctx->iface.flush = vg_context_flush; + + ctx->iface.teximage = NULL; + ctx->iface.copy = NULL; + + ctx->iface.st_context_private = (void *) smapi; + + return &ctx->iface; +} + +static struct st_renderbuffer * +create_renderbuffer(enum pipe_format format) +{ + struct st_renderbuffer *strb; + + strb = CALLOC_STRUCT(st_renderbuffer); + if (strb) + strb->format = format; + + return strb; +} + +static void +destroy_renderbuffer(struct st_renderbuffer *strb) +{ + pipe_surface_reference(&strb->surface, NULL); + pipe_resource_reference(&strb->texture, NULL); + free(strb); +} + +/** + * Decide the buffer to render to. + */ +static enum st_attachment_type +choose_attachment(struct st_framebuffer_iface *stfbi) +{ + enum st_attachment_type statt; + + statt = stfbi->visual->render_buffer; + if (statt != ST_ATTACHMENT_INVALID) { + /* use the buffer given by the visual, unless it is unavailable */ + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) { + switch (statt) { + case ST_ATTACHMENT_BACK_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + statt = ST_ATTACHMENT_FRONT_RIGHT; + break; + default: + break; + } + + if (!st_visual_have_buffers(stfbi->visual, 1 << statt)) + statt = ST_ATTACHMENT_INVALID; + } + } + + return statt; +} + +/** + * Bind the context to the given framebuffers. + */ +static boolean +vg_context_bind_framebuffers(struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + struct st_framebuffer *stfb; + enum st_attachment_type strb_att; + + /* the draw and read framebuffers must be the same */ + if (stdrawi != streadi) + return FALSE; + + p_atomic_set(&ctx->draw_buffer_invalid, TRUE); + + strb_att = (stdrawi) ? choose_attachment(stdrawi) : ST_ATTACHMENT_INVALID; + + if (ctx->draw_buffer) { + stfb = ctx->draw_buffer; + + /* free the existing fb */ + if (!stdrawi || + stfb->strb_att != strb_att || + stfb->strb->format != stdrawi->visual->color_format || + stfb->dsrb->format != stdrawi->visual->depth_stencil_format) { + destroy_renderbuffer(stfb->strb); + destroy_renderbuffer(stfb->dsrb); + free(stfb); + + ctx->draw_buffer = NULL; + } + } + + if (!stdrawi) + return TRUE; + + if (strb_att == ST_ATTACHMENT_INVALID) + return FALSE; + + /* create a new fb */ + if (!ctx->draw_buffer) { + stfb = CALLOC_STRUCT(st_framebuffer); + if (!stfb) + return FALSE; + + stfb->strb = create_renderbuffer(stdrawi->visual->color_format); + if (!stfb->strb) { + free(stfb); + return FALSE; + } + + stfb->dsrb = create_renderbuffer(stdrawi->visual->depth_stencil_format); + if (!stfb->dsrb) { + free(stfb->strb); + free(stfb); + return FALSE; + } + + stfb->width = 0; + stfb->height = 0; + stfb->strb_att = strb_att; + + ctx->draw_buffer = stfb; + } + + ctx->draw_buffer->iface = stdrawi; + + return TRUE; +} + +static boolean +vg_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi, + struct st_framebuffer_iface *stdrawi, + struct st_framebuffer_iface *streadi) +{ + struct vg_context *ctx = (struct vg_context *) stctxi; + + if (stctxi) + vg_context_bind_framebuffers(stctxi, stdrawi, streadi); + vg_set_current_context(ctx); + + return TRUE; +} + +static struct st_context_iface * +vg_api_get_current(struct st_api *stapi) +{ + struct vg_context *ctx = vg_current_context(); + + return (ctx) ? &ctx->iface : NULL; +} + +static boolean +vg_api_is_visual_supported(struct st_api *stapi, + const struct st_visual *visual) +{ + /* the impl requires a depth/stencil buffer */ + return util_format_is_depth_and_stencil(visual->depth_stencil_format); +} + +static st_proc_t +vg_api_get_proc_address(struct st_api *stapi, const char *procname) +{ + /* TODO */ + return (st_proc_t) NULL; +} + +static void +vg_api_destroy(struct st_api *stapi) +{ + free(stapi); +} + +struct st_api st_vg_api = { + vg_api_destroy, + vg_api_get_proc_address, + vg_api_is_visual_supported, + vg_api_create_context, + vg_api_make_current, + vg_api_get_current, +}; + +struct st_api * +st_api_create_OpenVG(void) +{ + return &st_vg_api; +} diff --git a/src/gallium/state_trackers/vega/vg_manager.h b/src/gallium/state_trackers/vega/vg_manager.h new file mode 100644 index 00000000000..1d97eb864ba --- /dev/null +++ b/src/gallium/state_trackers/vega/vg_manager.h @@ -0,0 +1,41 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#ifndef VG_MANAGER_H +#define VG_MANAGER_H + +#include "state_tracker/st_api.h" +#include "vg_context.h" + +void +vg_manager_flush_frontbuffer(struct vg_context *ctx); + +void +vg_manager_validate_framebuffer(struct vg_context *ctx); + +#endif /* VG_MANAGER_H */ diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c deleted file mode 100644 index 57d3baad7fb..00000000000 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ /dev/null @@ -1,439 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 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, 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE 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. - * - **************************************************************************/ - -#include "vg_context.h" -#include "vg_tracker.h" -#include "mask.h" - -#include "pipe/p_context.h" -#include "util/u_inlines.h" -#include "pipe/p_screen.h" -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_rect.h" - -/* advertise OpenVG support */ -PUBLIC const int st_api_OpenVG = 1; - -static struct pipe_texture * -create_texture(struct pipe_context *pipe, enum pipe_format format, - VGint width, VGint height) -{ - struct pipe_texture templ; - - memset(&templ, 0, sizeof(templ)); - - if (format != PIPE_FORMAT_NONE) { - templ.format = format; - } - else { - templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; - } - - templ.target = PIPE_TEXTURE_2D; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.last_level = 0; - - if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) { - templ.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; - } else { - templ.tex_usage = (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_SAMPLER); - } - - return pipe->screen->texture_create(pipe->screen, &templ); -} - -/** - * Allocate a renderbuffer for a an on-screen window (not a user-created - * renderbuffer). The window system code determines the format. - */ -static struct st_renderbuffer * -st_new_renderbuffer_fb(enum pipe_format format) -{ - struct st_renderbuffer *strb; - - strb = CALLOC_STRUCT(st_renderbuffer); - if (!strb) { - /*_vega_error(NULL, VG_OUT_OF_MEMORY, "creating renderbuffer");*/ - return NULL; - } - - strb->format = format; - - return strb; -} - - -/** - * This is called to allocate the original drawing surface, and - * during window resize. - */ -static VGboolean -st_renderbuffer_alloc_storage(struct vg_context * ctx, - struct st_renderbuffer *strb, - VGuint width, VGuint height) -{ - struct pipe_context *pipe = ctx->pipe; - unsigned surface_usage; - - /* Free the old surface and texture - */ - pipe_surface_reference(&strb->surface, NULL); - pipe_texture_reference(&strb->texture, NULL); - - - /* Probably need dedicated flags for surface usage too: - */ - surface_usage = (PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - - strb->texture = create_texture(pipe, strb->format, - width, height); - - if (!strb->texture) - return FALSE; - - strb->surface = pipe->screen->get_tex_surface(pipe->screen, - strb->texture, - 0, 0, 0, - surface_usage); - strb->width = width; - strb->height = height; - - assert(strb->surface->width == width); - assert(strb->surface->height == height); - - return strb->surface != NULL; -} - -struct vg_context * st_create_context(struct pipe_context *pipe, - const void *visual, - struct vg_context *share) -{ - struct vg_context *ctx = vg_create_context(pipe, visual, share); - /*debug_printf("--------- CREATE CONTEXT %p\n", ctx);*/ - return ctx; -} - -void st_destroy_context(struct vg_context *st) -{ - /*debug_printf("--------- DESTROY CONTEXT %p\n", st);*/ - vg_destroy_context(st); -} - -void st_copy_context_state(struct vg_context *dst, struct vg_context *src, - uint mask) -{ - fprintf(stderr, "FIXME: %s\n", __FUNCTION__); -} - -void st_get_framebuffer_dimensions(struct st_framebuffer *stfb, - uint *width, - uint *height) -{ - *width = stfb->strb->width; - *height = stfb->strb->height; -} - -struct st_framebuffer * st_create_framebuffer(const void *visual, - enum pipe_format colorFormat, - enum pipe_format depthFormat, - enum pipe_format stencilFormat, - uint width, uint height, - void *privateData) -{ - struct st_framebuffer *stfb = CALLOC_STRUCT(st_framebuffer); - if (stfb) { - struct st_renderbuffer *rb = - st_new_renderbuffer_fb(colorFormat); - stfb->strb = rb; -#if 0 - if (doubleBuffer) { - struct st_renderbuffer *rb = - st_new_renderbuffer_fb(colorFormat); - } -#endif - - /* we want to combine the depth/stencil */ - if (stencilFormat == depthFormat) - stfb->dsrb = st_new_renderbuffer_fb(stencilFormat); - else - stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_Z24S8_UNORM); - - /*### currently we always allocate it but it's possible it's - not necessary if EGL_ALPHA_MASK_SIZE was 0 - */ - stfb->alpha_mask = 0; - - stfb->width = width; - stfb->height = height; - stfb->privateData = privateData; - } - - return stfb; -} - -static void setup_new_alpha_mask(struct vg_context *ctx, - struct st_framebuffer *stfb, - uint width, uint height) -{ - struct pipe_context *pipe = ctx->pipe; - struct pipe_texture *old_texture = stfb->alpha_mask; - - /* - we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to - this texture and use it as a sampler, so while this wastes some - space it makes both of those a lot simpler - */ - stfb->alpha_mask = - create_texture(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); - - if (!stfb->alpha_mask) { - if (old_texture) - pipe_texture_reference(&old_texture, NULL); - return; - } - - vg_validate_state(ctx); - - /* alpha mask starts with 1.f alpha */ - mask_fill(0, 0, width, height, 1.f); - - /* if we had an old surface copy it over */ - if (old_texture) { - struct pipe_surface *surface = pipe->screen->get_tex_surface( - pipe->screen, - stfb->alpha_mask, - 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); - struct pipe_surface *old_surface = pipe->screen->get_tex_surface( - pipe->screen, - old_texture, - 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); - if (pipe->surface_copy) { - pipe->surface_copy(pipe, - surface, - 0, 0, - old_surface, - 0, 0, - MIN2(old_surface->width, width), - MIN2(old_surface->height, height)); - } else { - util_surface_copy(pipe, FALSE, - surface, - 0, 0, - old_surface, - 0, 0, - MIN2(old_surface->width, width), - MIN2(old_surface->height, height)); - } - if (surface) - pipe_surface_reference(&surface, NULL); - if (old_surface) - pipe_surface_reference(&old_surface, NULL); - } - - /* Free the old texture - */ - if (old_texture) - pipe_texture_reference(&old_texture, NULL); -} - -void st_resize_framebuffer(struct st_framebuffer *stfb, - uint width, uint height) -{ - struct vg_context *ctx = vg_current_context(); - struct st_renderbuffer *strb = stfb->strb; - struct pipe_framebuffer_state *state; - - if (!ctx) - return; - - state = &ctx->state.g3d.fb; - - /* If this is a noop, exit early and don't do the clear, etc below. - */ - if (stfb->width == width && - stfb->height == height && - state->zsbuf) - return; - - stfb->width = width; - stfb->height = height; - - if (strb->width != width || strb->height != height) - st_renderbuffer_alloc_storage(ctx, strb, - width, height); - - if (stfb->dsrb->width != width || stfb->dsrb->height != height) - st_renderbuffer_alloc_storage(ctx, stfb->dsrb, - width, height); - - { - VGuint i; - - memset(state, 0, sizeof(struct pipe_framebuffer_state)); - - state->width = width; - state->height = height; - - state->nr_cbufs = 1; - state->cbufs[0] = strb->surface; - for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) - state->cbufs[i] = 0; - - state->zsbuf = stfb->dsrb->surface; - - cso_set_framebuffer(ctx->cso_context, state); - } - - ctx->state.dirty |= VIEWPORT_DIRTY; - ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/ - - ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, - NULL, 0.0, 0); - - /* we need all the other state already set */ - - setup_new_alpha_mask(ctx, stfb, width, height); - - pipe_texture_reference( &stfb->blend_texture, NULL ); - stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, - width, height); -} - -void st_set_framebuffer_surface(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_surface *surf) -{ - struct st_renderbuffer *rb = stfb->strb; - - /* unreference existing surfaces */ - pipe_surface_reference( &rb->surface, NULL ); - pipe_texture_reference( &rb->texture, NULL ); - - /* reference new ones */ - pipe_surface_reference( &rb->surface, surf ); - pipe_texture_reference( &rb->texture, surf->texture ); - - rb->width = surf->width; - rb->height = surf->height; -} - -int st_get_framebuffer_surface(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_surface **surf) -{ - struct st_renderbuffer *rb = stfb->strb; - *surf = rb->surface; - return VG_TRUE; -} - -int st_get_framebuffer_texture(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_texture **tex) -{ - struct st_renderbuffer *rb = stfb->strb; - *tex = rb->texture; - return VG_TRUE; -} - -void * st_framebuffer_private(struct st_framebuffer *stfb) -{ - return stfb->privateData; -} - -void st_unreference_framebuffer(struct st_framebuffer *stfb) -{ - /* FIXME */ -} - -boolean st_make_current(struct vg_context *st, - struct st_framebuffer *draw, - struct st_framebuffer *read) -{ - vg_set_current_context(st); - if (st) { - st->draw_buffer = draw; - } - return VG_TRUE; -} - -struct vg_context *st_get_current(void) -{ - return vg_current_context(); -} - -void st_flush(struct vg_context *st, uint pipeFlushFlags, - struct pipe_fence_handle **fence) -{ - st->pipe->flush(st->pipe, pipeFlushFlags, fence); -} - -void st_finish(struct vg_context *st) -{ - struct pipe_fence_handle *fence = NULL; - - st_flush(st, PIPE_FLUSH_RENDER_CACHE, &fence); - - st->pipe->screen->fence_finish(st->pipe->screen, fence, 0); - st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL); -} - -void st_notify_swapbuffers(struct st_framebuffer *stfb) -{ - struct vg_context *ctx = vg_current_context(); - if (ctx && ctx->draw_buffer == stfb) { - st_flush(ctx, - PIPE_FLUSH_RENDER_CACHE | - PIPE_FLUSH_SWAPBUFFERS | - PIPE_FLUSH_FRAME, - NULL); - } -} - -void st_notify_swapbuffers_complete(struct st_framebuffer *stfb) -{ -} - -int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, - enum pipe_format format) -{ - return 0; -} - -int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level) -{ - return 0; -} - -st_proc st_get_proc_address(const char *procname) -{ - return NULL; -} diff --git a/src/gallium/state_trackers/vega/vg_tracker.h b/src/gallium/state_trackers/vega/vg_tracker.h deleted file mode 100644 index c1196954a76..00000000000 --- a/src/gallium/state_trackers/vega/vg_tracker.h +++ /dev/null @@ -1,127 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 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, 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL VMWARE 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. - * - **************************************************************************/ - -#ifndef VG_TRACKER_H -#define VG_TRACKER_H - -#include "VG/openvg.h" - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" - -#define ST_SURFACE_FRONT_LEFT 0 -#define ST_SURFACE_BACK_LEFT 1 -#define ST_SURFACE_FRONT_RIGHT 2 -#define ST_SURFACE_BACK_RIGHT 3 -#define ST_SURFACE_DEPTH 8 - -struct vg_context; -struct st_framebuffer; -struct pipe_context; -struct pipe_fence_handle; -struct pipe_surface; - - -PUBLIC -struct vg_context *st_create_context(struct pipe_context *pipe, - const void *visual, - struct vg_context *share); - -PUBLIC -void st_destroy_context( struct vg_context *st ); - -PUBLIC -void st_copy_context_state(struct vg_context *dst, struct vg_context *src, - uint mask); - -PUBLIC -struct st_framebuffer *st_create_framebuffer(const void *visual, - enum pipe_format colorFormat, - enum pipe_format depthFormat, - enum pipe_format stencilFormat, - uint width, uint height, - void *privateData); - -PUBLIC -void st_resize_framebuffer(struct st_framebuffer *stfb, - uint width, uint height); - -PUBLIC -void st_set_framebuffer_surface(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_surface *surf); - -PUBLIC -void st_get_framebuffer_dimensions( struct st_framebuffer *stfb, - uint *width, uint *height); - -PUBLIC -int st_bind_texture_surface(struct pipe_surface *ps, int target, int level, - enum pipe_format format); - -PUBLIC -int st_unbind_texture_surface(struct pipe_surface *ps, int target, int level); - -PUBLIC -int st_get_framebuffer_surface(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_surface **surf); - -PUBLIC -int st_get_framebuffer_texture(struct st_framebuffer *stfb, - uint surfIndex, struct pipe_texture **tex); - -PUBLIC -void *st_framebuffer_private(struct st_framebuffer *stfb); - -PUBLIC -void st_unreference_framebuffer(struct st_framebuffer *stfb); - -PUBLIC -boolean st_make_current(struct vg_context *st, - struct st_framebuffer *draw, - struct st_framebuffer *read); - -PUBLIC -struct vg_context *st_get_current(void); - -PUBLIC -void st_flush(struct vg_context *st, uint pipeFlushFlags, - struct pipe_fence_handle **fence); -PUBLIC -void st_finish(struct vg_context *st); - -PUBLIC -void st_notify_swapbuffers(struct st_framebuffer *stfb); -PUBLIC -void st_notify_swapbuffers_complete(struct st_framebuffer *stfb); - - -/** Generic function type */ -typedef void (*st_proc)(); - -PUBLIC -st_proc st_get_proc_address(const char *procname); - -#endif diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript index 352c087475e..f59f3a9638a 100644 --- a/src/gallium/state_trackers/wgl/SConscript +++ b/src/gallium/state_trackers/wgl/SConscript @@ -28,6 +28,7 @@ if env['platform'] in ['windows']: 'stw_framebuffer.c', 'stw_getprocaddress.c', 'stw_pixelformat.c', + 'stw_st.c', 'stw_tls.c', 'stw_wgl.c', ] diff --git a/src/gallium/state_trackers/wgl/stw_context.c b/src/gallium/state_trackers/wgl/stw_context.c index 05ccd5febcf..0fb7cd83069 100644 --- a/src/gallium/state_trackers/wgl/stw_context.c +++ b/src/gallium/state_trackers/wgl/stw_context.c @@ -27,12 +27,13 @@ #include <windows.h> -#include "main/mtypes.h" -#include "main/context.h" #include "pipe/p_compiler.h" #include "pipe/p_context.h" +#include "state_tracker/st_api.h" + +/* for _mesa_share_state */ #include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" +#include "main/context.h" #include "stw_icd.h" #include "stw_device.h" @@ -44,25 +45,13 @@ static INLINE struct stw_context * -stw_context(GLcontext *glctx) -{ - if(!glctx) - return NULL; - assert(glctx->DriverCtx); - return (struct stw_context *)glctx->DriverCtx; -} - -static INLINE struct stw_context * stw_current_context(void) { - /* We must check if multiple threads are being used or GET_CURRENT_CONTEXT - * might return the current context of the thread first seen. */ - _glapi_check_multithread(); + struct st_context_iface *st; - { - GET_CURRENT_CONTEXT( glctx ); - return stw_context(glctx); - } + st = (stw_dev) ? stw_dev->stapi->get_current(stw_dev->stapi) : NULL; + + return (struct stw_context *) ((st) ? st->st_manager_private : NULL); } BOOL APIENTRY @@ -114,7 +103,11 @@ DrvShareLists( ctx2 = stw_lookup_context_locked( dhglrc2 ); if (ctx1 && ctx2) { - ret = _mesa_share_state(ctx2->st->ctx, ctx1->st->ctx); + struct st_context *st1, *st2; + + st1 = (struct st_context *) ctx1->st; + st2 = (struct st_context *) ctx2->st; + ret = _mesa_share_state(st2->ctx, st1->ctx); } pipe_mutex_unlock( stw_dev->ctx_mutex ); @@ -122,20 +115,6 @@ DrvShareLists( return ret; } -static void -stw_viewport(GLcontext * glctx, GLint x, GLint y, - GLsizei width, GLsizei height) -{ - struct stw_context *ctx = (struct stw_context *)glctx->DriverCtx; - struct stw_framebuffer *fb; - - fb = stw_framebuffer_from_hdc( ctx->hdc ); - if(fb) { - stw_framebuffer_update(fb); - stw_framebuffer_release(fb); - } -} - DHGLRC APIENTRY DrvCreateContext( HDC hdc ) @@ -150,9 +129,7 @@ DrvCreateLayerContext( { int iPixelFormat; const struct stw_pixelformat_info *pfi; - GLvisual visual; struct stw_context *ctx = NULL; - struct pipe_context *pipe = NULL; if(!stw_dev) return 0; @@ -165,7 +142,6 @@ DrvCreateLayerContext( return 0; pfi = stw_pixelformat_get_info( iPixelFormat - 1 ); - stw_pixelformat_visual(&visual, pfi); ctx = CALLOC_STRUCT( stw_context ); if (ctx == NULL) @@ -174,18 +150,12 @@ DrvCreateLayerContext( ctx->hdc = hdc; ctx->iPixelFormat = iPixelFormat; - /* priv == hdc, pass to stw_flush_frontbuffer as context_private - */ - pipe = stw_dev->screen->context_create( stw_dev->screen, hdc ); - if (pipe == NULL) - goto no_pipe; - - ctx->st = st_create_context( pipe, &visual, NULL ); + ctx->st = stw_dev->stapi->create_context(stw_dev->stapi, + stw_dev->smapi, &pfi->stvis, NULL); if (ctx->st == NULL) goto no_st_ctx; - ctx->st->ctx->DriverCtx = ctx; - ctx->st->ctx->Driver.Viewport = stw_viewport; + ctx->st->st_manager_private = (void *) ctx; pipe_mutex_lock( stw_dev->ctx_mutex ); ctx->dhglrc = handle_table_add(stw_dev->ctx_table, ctx); @@ -196,11 +166,8 @@ DrvCreateLayerContext( return ctx->dhglrc; no_hglrc: - st_destroy_context(ctx->st); - goto no_pipe; /* st_context_destroy already destroys pipe */ + ctx->st->destroy(ctx->st); no_st_ctx: - pipe->destroy( pipe ); -no_pipe: FREE(ctx); no_ctx: return 0; @@ -226,9 +193,9 @@ DrvDeleteContext( /* Unbind current if deleting current context. */ if (curctx == ctx) - st_make_current( NULL, NULL, NULL ); + stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); - st_destroy_context(ctx->st); + ctx->st->destroy(ctx->st); FREE(ctx); ret = TRUE; @@ -306,7 +273,7 @@ stw_make_current( curctx = stw_current_context(); if (curctx != NULL) { if (curctx->dhglrc != dhglrc) - st_flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + curctx->st->flush(curctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); /* Return if already current. */ if (curctx->dhglrc == dhglrc && curctx->hdc == hdc) { @@ -314,10 +281,12 @@ stw_make_current( fb = stw_framebuffer_from_hdc( hdc ); goto success; } + + stw_framebuffer_reference(&curctx->current_framebuffer, NULL); } if (hdc == NULL || dhglrc == 0) { - return st_make_current( NULL, NULL, NULL ); + return stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); } pipe_mutex_lock( stw_dev->ctx_mutex ); @@ -327,7 +296,10 @@ stw_make_current( goto fail; fb = stw_framebuffer_from_hdc( hdc ); - if(!fb) { + if (fb) { + stw_framebuffer_update(fb); + } + else { /* Applications should call SetPixelFormat before creating a context, * but not all do, and the opengl32 runtime seems to use a default pixel * format in some cases, so we must create a framebuffer for those here @@ -342,23 +314,17 @@ stw_make_current( if(fb->iPixelFormat != ctx->iPixelFormat) goto fail; - /* Lazy allocation of the frame buffer */ - if(!stw_framebuffer_allocate(fb)) - goto fail; - /* Bind the new framebuffer */ ctx->hdc = hdc; - /* pass to stw_flush_frontbuffer as context_private */ - ctx->st->pipe->priv = hdc; - - if(!st_make_current( ctx->st, fb->stfb, fb->stfb )) + if (!stw_dev->stapi->make_current(stw_dev->stapi, ctx->st, fb->stfb, fb->stfb)) goto fail; + stw_framebuffer_reference(&ctx->current_framebuffer, fb); + success: assert(fb); if(fb) { - stw_framebuffer_update(fb); stw_framebuffer_release(fb); } @@ -367,11 +333,40 @@ success: fail: if(fb) stw_framebuffer_release(fb); - st_make_current( NULL, NULL, NULL ); + stw_dev->stapi->make_current(stw_dev->stapi, NULL, NULL, NULL); return FALSE; } /** + * Flush the current context if it is bound to the framebuffer. + */ +void +stw_flush_current_locked( struct stw_framebuffer *fb ) +{ + struct stw_context *ctx = stw_current_context(); + + if (ctx && ctx->current_framebuffer == fb) { + ctx->st->flush(ctx->st, + PIPE_FLUSH_RENDER_CACHE | + PIPE_FLUSH_SWAPBUFFERS | + PIPE_FLUSH_FRAME, + NULL); + } +} + +/** + * Notify the current context that the framebuffer has become invalid. + */ +void +stw_notify_current_locked( struct stw_framebuffer *fb ) +{ + struct stw_context *ctx = stw_current_context(); + + if (ctx && ctx->current_framebuffer == fb) + ctx->st->notify_invalid_framebuffer(ctx->st, fb->stfb); +} + +/** * Although WGL allows different dispatch entrypoints per context */ static const GLCLTPROCTABLE cpt = diff --git a/src/gallium/state_trackers/wgl/stw_context.h b/src/gallium/state_trackers/wgl/stw_context.h index 256c27e21ef..0bbed84104a 100644 --- a/src/gallium/state_trackers/wgl/stw_context.h +++ b/src/gallium/state_trackers/wgl/stw_context.h @@ -30,14 +30,17 @@ #include <windows.h> -struct st_context; +struct stw_framebuffer; +struct st_context_iface; struct stw_context { - struct st_context *st; + struct st_context_iface *st; DHGLRC dhglrc; int iPixelFormat; HDC hdc; + + struct stw_framebuffer *current_framebuffer; }; DHGLRC stw_get_current_context( void ); @@ -46,4 +49,7 @@ HDC stw_get_current_dc( void ); BOOL stw_make_current( HDC hdc, DHGLRC dhglrc ); +void stw_flush_current_locked( struct stw_framebuffer *fb ); +void stw_notify_current_locked( struct stw_framebuffer *fb ); + #endif /* STW_CONTEXT_H */ diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c index 472a2a5379a..61b207525ca 100644 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ b/src/gallium/state_trackers/wgl/stw_device.c @@ -30,13 +30,8 @@ #include "glapi/glthread.h" #include "util/u_debug.h" #include "util/u_math.h" +#include "util/u_memory.h" #include "pipe/p_screen.h" -#include "state_tracker/st_public.h" - -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_texture.h" -#endif #include "stw_device.h" #include "stw_winsys.h" @@ -44,6 +39,7 @@ #include "stw_icd.h" #include "stw_tls.h" #include "stw_framebuffer.h" +#include "stw_st.h" #ifdef WIN32_THREADS extern _glthread_Mutex OneTimeLock; @@ -53,28 +49,6 @@ extern _glthread_Mutex OneTimeLock; struct stw_device *stw_dev = NULL; -/** - * XXX: Dispatch pipe_screen::flush_front_buffer to our - * stw_winsys::flush_front_buffer. - */ -static void -stw_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surface, - void *context_private ) -{ - HDC hdc = (HDC)context_private; - struct stw_framebuffer *fb; - - fb = stw_framebuffer_from_hdc( hdc ); - if (!fb) { - /* fb can be NULL if window was destroyed already */ - return; - } - - stw_framebuffer_present_locked(hdc, fb, surface); -} - - boolean stw_init(const struct stw_winsys *stw_winsys) { @@ -100,6 +74,11 @@ stw_init(const struct stw_winsys *stw_winsys) _glthread_INIT_MUTEX(OneTimeLock); #endif + stw_dev->stapi = stw_st_create_api(); + stw_dev->smapi = CALLOC_STRUCT(st_manager); + if (!stw_dev->stapi || !stw_dev->smapi) + goto error1; + screen = stw_winsys->create_screen(); if(!screen) goto error1; @@ -107,15 +86,9 @@ stw_init(const struct stw_winsys *stw_winsys) if(stw_winsys->get_adapter_luid) stw_winsys->get_adapter_luid(screen, &stw_dev->AdapterLuid); -#ifdef DEBUG - stw_dev->screen = trace_screen_create(screen); - stw_dev->trace_running = stw_dev->screen != screen ? TRUE : FALSE; -#else + stw_dev->smapi->screen = screen; stw_dev->screen = screen; -#endif - - stw_dev->screen->flush_frontbuffer = &stw_flush_frontbuffer; - + pipe_mutex_init( stw_dev->ctx_mutex ); pipe_mutex_init( stw_dev->fb_mutex ); @@ -129,6 +102,11 @@ stw_init(const struct stw_winsys *stw_winsys) return TRUE; error1: + if (stw_dev->smapi) + FREE(stw_dev->smapi); + if (stw_dev->stapi) + stw_dev->stapi->destroy(stw_dev->stapi); + stw_dev = NULL; return FALSE; } @@ -178,6 +156,9 @@ stw_cleanup(void) pipe_mutex_destroy( stw_dev->fb_mutex ); pipe_mutex_destroy( stw_dev->ctx_mutex ); + FREE(stw_dev->smapi); + stw_dev->stapi->destroy(stw_dev->stapi); + stw_dev->screen->destroy(stw_dev->screen); #ifdef WIN32_THREADS diff --git a/src/gallium/state_trackers/wgl/stw_device.h b/src/gallium/state_trackers/wgl/stw_device.h index a83841f6b7d..1b836960d0d 100644 --- a/src/gallium/state_trackers/wgl/stw_device.h +++ b/src/gallium/state_trackers/wgl/stw_device.h @@ -40,6 +40,8 @@ struct pipe_screen; +struct st_api; +struct st_manager; struct stw_framebuffer; struct stw_device @@ -48,9 +50,8 @@ struct stw_device struct pipe_screen *screen; -#ifdef DEBUG - boolean trace_running; -#endif + struct st_api *stapi; + struct st_manager *smapi; LUID AdapterLuid; diff --git a/src/gallium/state_trackers/wgl/stw_ext_gallium.c b/src/gallium/state_trackers/wgl/stw_ext_gallium.c index 8dd63f124ad..5ecbd8048de 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_gallium.c +++ b/src/gallium/state_trackers/wgl/stw_ext_gallium.c @@ -31,11 +31,6 @@ #include "stw_winsys.h" #include "stw_ext_gallium.h" -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_context.h" -#endif - struct pipe_screen * APIENTRY wglGetGalliumScreenMESA(void) diff --git a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c index 8a9995aba8e..ab56800e28d 100644 --- a/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_ext_pixelformat.c @@ -227,11 +227,11 @@ stw_query_attrib( break; case WGL_SAMPLE_BUFFERS_ARB: - *pvalue = pfi->numSampleBuffers; + *pvalue = 1; break; case WGL_SAMPLES_ARB: - *pvalue = pfi->numSamples; + *pvalue = pfi->stvis.samples; break; default: diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.c b/src/gallium/state_trackers/wgl/stw_framebuffer.c index 02de21ccb2b..259b22f22c7 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.c +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.c @@ -27,23 +27,19 @@ #include <windows.h> -#include "main/context.h" #include "pipe/p_format.h" #include "pipe/p_screen.h" #include "util/u_format.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_public.h" - -#ifdef DEBUG -#include "trace/tr_screen.h" -#include "trace/tr_texture.h" -#endif +#include "util/u_memory.h" +#include "state_tracker/st_api.h" #include "stw_icd.h" #include "stw_framebuffer.h" #include "stw_device.h" #include "stw_winsys.h" #include "stw_tls.h" +#include "stw_context.h" +#include "stw_st.h" /** @@ -68,8 +64,8 @@ stw_framebuffer_from_hwnd_locked( /** * Destroy this framebuffer. Both stw_dev::fb_mutex and stw_framebuffer::mutex - * must be held, by this order. Obviously no further access to fb can be done - * after this. + * must be held, by this order. If there are still references to the + * framebuffer, nothing will happen. */ static INLINE void stw_framebuffer_destroy_locked( @@ -77,6 +73,13 @@ stw_framebuffer_destroy_locked( { struct stw_framebuffer **link; + /* check the reference count */ + fb->refcnt--; + if (fb->refcnt) { + pipe_mutex_unlock( fb->mutex ); + return; + } + link = &stw_dev->fb_head; while (*link != fb) link = &(*link)->next; @@ -87,7 +90,7 @@ stw_framebuffer_destroy_locked( if(fb->shared_surface) stw_dev->stw_winsys->shared_surface_close(stw_dev->screen, fb->shared_surface); - st_unreference_framebuffer(fb->stfb); + stw_st_destroy_framebuffer_locked(fb->stfb); pipe_mutex_unlock( fb->mutex ); @@ -235,9 +238,14 @@ stw_framebuffer_create( fb->iPixelFormat = iPixelFormat; fb->pfi = pfi = stw_pixelformat_get_info( iPixelFormat - 1 ); + fb->stfb = stw_st_create_framebuffer( fb ); + if (!fb->stfb) { + FREE( fb ); + return NULL; + } + + fb->refcnt = 1; - stw_pixelformat_visual(&fb->visual, pfi); - stw_framebuffer_get_size(fb); pipe_mutex_init( fb->mutex ); @@ -256,47 +264,31 @@ stw_framebuffer_create( return fb; } - -BOOL -stw_framebuffer_allocate( +/** + * Have ptr reference fb. The referenced framebuffer should be locked. + */ +void +stw_framebuffer_reference( + struct stw_framebuffer **ptr, struct stw_framebuffer *fb) { - assert(fb); - - if(!fb->stfb) { - const struct stw_pixelformat_info *pfi = fb->pfi; - enum pipe_format colorFormat, depthFormat, stencilFormat; + struct stw_framebuffer *old_fb = *ptr; + + if (old_fb == fb) + return; - colorFormat = pfi->color_format; + if (fb) + fb->refcnt++; + if (old_fb) { + pipe_mutex_lock(stw_dev->fb_mutex); - if(util_format_get_component_bits(pfi->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 0)) - depthFormat = pfi->depth_stencil_format; - else - depthFormat = PIPE_FORMAT_NONE; - - if(util_format_get_component_bits(pfi->depth_stencil_format, UTIL_FORMAT_COLORSPACE_ZS, 1)) - stencilFormat = pfi->depth_stencil_format; - else - stencilFormat = PIPE_FORMAT_NONE; - - assert(fb->must_resize); - assert(fb->width); - assert(fb->height); - - fb->stfb = st_create_framebuffer( - &fb->visual, - colorFormat, - depthFormat, - stencilFormat, - fb->width, - fb->height, - (void *) fb ); - - // to notify the context - fb->must_resize = TRUE; + pipe_mutex_lock(old_fb->mutex); + stw_framebuffer_destroy_locked(old_fb); + + pipe_mutex_unlock(stw_dev->fb_mutex); } - - return fb->stfb ? TRUE : FALSE; + + *ptr = fb; } @@ -318,11 +310,6 @@ stw_framebuffer_update( * to know of their existing without using the not very portable PSAPI. */ stw_framebuffer_get_size(fb); - - if(fb->must_resize) { - st_resize_framebuffer(fb->stfb, fb->width, fb->height); - fb->must_resize = FALSE; - } } @@ -495,13 +482,6 @@ DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data) surface = (struct pipe_surface *)data->pPrivateData; -#ifdef DEBUG - if(stw_dev->trace_running) { - screen = trace_screen(screen)->screen; - surface = trace_surface(surface)->surface; - } -#endif - if(data->hSharedSurface != fb->hSharedSurface) { if(fb->shared_surface) { stw_dev->stw_winsys->shared_surface_close(screen, fb->shared_surface); @@ -528,6 +508,7 @@ DrvPresentBuffers(HDC hdc, PGLPRESENTBUFFERSDATA data) } stw_framebuffer_update(fb); + stw_notify_current_locked(fb); stw_framebuffer_release(fb); @@ -556,6 +537,7 @@ stw_framebuffer_present_locked(HDC hdc, data.rect = fb->client_rect; data.pPrivateData = (void *)surface; + stw_notify_current_locked(fb); stw_framebuffer_release(fb); return stw_dev->callbacks.wglCbPresentBuffers(hdc, &data); @@ -563,17 +545,10 @@ stw_framebuffer_present_locked(HDC hdc, else { struct pipe_screen *screen = stw_dev->screen; -#ifdef DEBUG - if(stw_dev->trace_running) { - screen = trace_screen(screen)->screen; - surface = trace_surface(surface)->surface; - } -#endif - stw_dev->stw_winsys->present( screen, surface, hdc ); stw_framebuffer_update(fb); - + stw_notify_current_locked(fb); stw_framebuffer_release(fb); return TRUE; @@ -586,7 +561,6 @@ DrvSwapBuffers( HDC hdc ) { struct stw_framebuffer *fb; - struct pipe_surface *surface = NULL; if (!stw_dev) return FALSE; @@ -600,9 +574,9 @@ DrvSwapBuffers( return TRUE; } - st_swapbuffers(fb->stfb, &surface, NULL); + stw_flush_current_locked(fb); - return stw_framebuffer_present_locked(hdc, fb, surface); + return stw_st_swap_framebuffer_locked(fb->stfb); } diff --git a/src/gallium/state_trackers/wgl/stw_framebuffer.h b/src/gallium/state_trackers/wgl/stw_framebuffer.h index 08cc4973bce..89d12300e67 100644 --- a/src/gallium/state_trackers/wgl/stw_framebuffer.h +++ b/src/gallium/state_trackers/wgl/stw_framebuffer.h @@ -30,11 +30,10 @@ #include <windows.h> -#include "main/mtypes.h" - #include "os/os_thread.h" struct pipe_surface; +struct st_framebuffer_iface; struct stw_pixelformat_info; /** @@ -45,7 +44,7 @@ struct stw_framebuffer /** * This mutex has two purposes: * - protect the access to the mutable data members below - * - prevent the the framebuffer from being deleted while being accessed. + * - prevent the framebuffer from being deleted while being accessed. * * It is OK to lock this mutex while holding the stw_device::fb_mutex lock, * but the opposite must never happen. @@ -64,13 +63,15 @@ struct stw_framebuffer int iPixelFormat; const struct stw_pixelformat_info *pfi; - GLvisual visual; + + struct st_framebuffer_iface *stfb; /* * Mutable members. */ - struct st_framebuffer *stfb; + unsigned refcnt; + /* FIXME: Make this work for multiple contexts bound to the same framebuffer */ boolean must_resize; @@ -114,6 +115,11 @@ stw_framebuffer_create( HDC hdc, int iPixelFormat ); +void +stw_framebuffer_reference( + struct stw_framebuffer **ptr, + struct stw_framebuffer *fb); + /** * Search a framebuffer with a matching HWND. * @@ -135,10 +141,6 @@ stw_framebuffer_from_hdc( HDC hdc ); BOOL -stw_framebuffer_allocate( - struct stw_framebuffer *fb ); - -BOOL stw_framebuffer_present_locked(HDC hdc, struct stw_framebuffer *fb, struct pipe_surface *surface); diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c index bc28f31ed1c..11e779d25f8 100644 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c @@ -96,8 +96,8 @@ stw_pf_depth_stencil[] = { { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, { PIPE_FORMAT_Z16_UNORM, {16, 0} }, /* combined depth-stencil */ - { PIPE_FORMAT_Z24S8_UNORM, {24, 8} }, - { PIPE_FORMAT_S8Z24_UNORM, {24, 8} } + { PIPE_FORMAT_Z24_UNORM_S8_USCALED, {24, 8} }, + { PIPE_FORMAT_S8_USCALED_Z24_UNORM, {24, 8} } }; @@ -142,9 +142,6 @@ stw_pixelformat_add( memset(pfi, 0, sizeof *pfi); - pfi->color_format = color->format; - pfi->depth_stencil_format = depth->format; - pfi->pfd.nSize = sizeof pfi->pfd; pfi->pfd.nVersion = 1; @@ -184,11 +181,22 @@ stw_pixelformat_add( pfi->pfd.dwVisibleMask = 0; pfi->pfd.dwDamageMask = 0; - if(samples) { - pfi->numSampleBuffers = 1; - pfi->numSamples = samples; - extended = TRUE; - } + /* + * since state trackers can allocate depth/stencil/accum buffers, we provide + * only color buffers here + */ + pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK; + if (doublebuffer) + pfi->stvis.buffer_mask = ST_ATTACHMENT_BACK_LEFT_MASK; + + pfi->stvis.color_format = color->format; + pfi->stvis.depth_stencil_format = depth->format; + + pfi->stvis.accum_format = (accum) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + pfi->stvis.samples = samples; + pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID; ++stw_dev->pixelformat_extended_count; @@ -218,8 +226,8 @@ stw_pixelformat_init( void ) const struct stw_pf_color_info *color = &stw_pf_color[j]; if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET, 0)) + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_DISPLAY_TARGET, 0)) continue; for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) { @@ -229,7 +237,7 @@ stw_pixelformat_init( void ) const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l]; if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0)) + PIPE_BIND_DEPTH_STENCIL, 0)) continue; stw_pixelformat_add( stw_dev, color, depth, 0, doublebuffer, samples ); @@ -264,29 +272,6 @@ stw_pixelformat_get_info( uint index ) } -void -stw_pixelformat_visual(GLvisual *visual, - const struct stw_pixelformat_info *pfi ) -{ - memset(visual, 0, sizeof *visual); - _mesa_initialize_visual( - visual, - (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE, - (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE, - pfi->pfd.cRedBits, - pfi->pfd.cGreenBits, - pfi->pfd.cBlueBits, - pfi->pfd.cAlphaBits, - pfi->pfd.cDepthBits, - pfi->pfd.cStencilBits, - pfi->pfd.cAccumRedBits, - pfi->pfd.cAccumGreenBits, - pfi->pfd.cAccumBlueBits, - pfi->pfd.cAccumAlphaBits, - pfi->numSamples ); -} - - LONG APIENTRY DrvDescribePixelFormat( HDC hdc, diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.h b/src/gallium/state_trackers/wgl/stw_pixelformat.h index 3a690b35bad..d405172773c 100644 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.h +++ b/src/gallium/state_trackers/wgl/stw_pixelformat.h @@ -38,16 +38,13 @@ #include "pipe/p_compiler.h" #include "pipe/p_format.h" +#include "state_tracker/st_api.h" struct stw_pixelformat_info { - enum pipe_format color_format; - enum pipe_format depth_stencil_format; - PIXELFORMATDESCRIPTOR pfd; - unsigned numSampleBuffers; - unsigned numSamples; + struct st_visual stvis; }; void @@ -62,10 +59,6 @@ stw_pixelformat_get_extended_count( void ); const struct stw_pixelformat_info * stw_pixelformat_get_info( uint index ); -void -stw_pixelformat_visual(GLvisual *visual, - const struct stw_pixelformat_info *pfi ); - int stw_pixelformat_choose( HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd ); diff --git a/src/gallium/state_trackers/wgl/stw_st.c b/src/gallium/state_trackers/wgl/stw_st.c new file mode 100644 index 00000000000..bcdd82e4f66 --- /dev/null +++ b/src/gallium/state_trackers/wgl/stw_st.c @@ -0,0 +1,312 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * 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 + * BRIAN PAUL 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. + * + * Authors: + * Chia-I Wu <[email protected]> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ + +#include "stw_st.h" +#include "stw_device.h" +#include "stw_framebuffer.h" +#include "stw_pixelformat.h" + +struct stw_st_framebuffer { + struct st_framebuffer_iface base; + + struct stw_framebuffer *fb; + struct st_visual stvis; + + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + unsigned texture_width, texture_height; + unsigned texture_mask; + + struct pipe_surface *front_surface, *back_surface; +}; + +static INLINE struct stw_st_framebuffer * +stw_st_framebuffer(struct st_framebuffer_iface *stfb) +{ + return (struct stw_st_framebuffer *) stfb; +} + +/** + * Remove outdated textures and create the requested ones. + */ +static void +stw_st_framebuffer_validate_locked(struct st_framebuffer_iface *stfb, + unsigned width, unsigned height, + unsigned mask) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + struct pipe_resource templ; + unsigned i; + + /* remove outdated surface */ + pipe_surface_reference(&stwfb->front_surface, NULL); + pipe_surface_reference(&stwfb->back_surface, NULL); + + /* remove outdated textures */ + if (stwfb->texture_width != width || stwfb->texture_height != height) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&stwfb->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.last_level = 0; + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (stwfb->textures[i] || !(mask & (1 << i))) { + /* remember the texture */ + if (stwfb->textures[i]) + mask |= (1 << i); + continue; + } + + switch (i) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + format = stwfb->stvis.color_format; + bind = PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = stwfb->stvis.depth_stencil_format; + bind = PIPE_BIND_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.bind = bind; + + stwfb->textures[i] = + stw_dev->screen->resource_create(stw_dev->screen, &templ); + } + } + + stwfb->texture_width = width; + stwfb->texture_height = height; + stwfb->texture_mask = mask; +} + +static boolean +stw_st_framebuffer_validate(struct st_framebuffer_iface *stfb, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + unsigned statt_mask, i; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= 1 << statts[i]; + + pipe_mutex_lock(stwfb->fb->mutex); + + if (stwfb->fb->must_resize || (statt_mask & ~stwfb->texture_mask)) { + stw_st_framebuffer_validate_locked(&stwfb->base, + stwfb->fb->width, stwfb->fb->height, statt_mask); + stwfb->fb->must_resize = FALSE; + } + + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], stwfb->textures[statts[i]]); + } + + stw_framebuffer_release(stwfb->fb); + + return TRUE; +} + +static struct pipe_surface * +get_present_surface_locked(struct st_framebuffer_iface *stfb, + enum st_attachment_type statt) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + struct pipe_resource *ptex; + struct pipe_surface *psurf, **cache; + + ptex = stwfb->textures[statt]; + if (!ptex) + return NULL; + + psurf = NULL; + + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + cache = &stwfb->front_surface; + break; + case ST_ATTACHMENT_BACK_LEFT: + cache = &stwfb->back_surface; + break; + default: + cache = &psurf; + break; + } + + if (!*cache) { + *cache = stw_dev->screen->get_tex_surface(stw_dev->screen, + ptex, 0, 0, 0, + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_RENDER_TARGET); + } + + if (psurf != *cache) + pipe_surface_reference(&psurf, *cache); + + return psurf; +} + +/** + * Present an attachment of the framebuffer. + */ +static boolean +stw_st_framebuffer_present_locked(struct st_framebuffer_iface *stfb, + enum st_attachment_type statt) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + struct pipe_surface *psurf; + + psurf = get_present_surface_locked(&stwfb->base, statt); + if (psurf) { + stw_framebuffer_present_locked(stwfb->fb->hDC, stwfb->fb, psurf); + pipe_surface_reference(&psurf, NULL); + } + + return TRUE; +} + +static boolean +stw_st_framebuffer_flush_front(struct st_framebuffer_iface *stfb, + enum st_attachment_type statt) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + + pipe_mutex_lock(stwfb->fb->mutex); + + return stw_st_framebuffer_present_locked(&stwfb->base, statt); +} + +/** + * Create a framebuffer interface. + */ +struct st_framebuffer_iface * +stw_st_create_framebuffer(struct stw_framebuffer *fb) +{ + struct stw_st_framebuffer *stwfb; + + stwfb = CALLOC_STRUCT(stw_st_framebuffer); + if (!stwfb) + return NULL; + + stwfb->fb = fb; + stwfb->stvis = fb->pfi->stvis; + + stwfb->base.visual = &stwfb->stvis; + stwfb->base.flush_front = stw_st_framebuffer_flush_front; + stwfb->base.validate = stw_st_framebuffer_validate; + + return &stwfb->base; +} + +/** + * Destroy a framebuffer interface. + */ +void +stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + int i; + + pipe_surface_reference(&stwfb->front_surface, NULL); + pipe_surface_reference(&stwfb->back_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&stwfb->textures[i], NULL); + + FREE(stwfb); +} + +/** + * Swap the buffers of the given framebuffer. + */ +boolean +stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb) +{ + struct stw_st_framebuffer *stwfb = stw_st_framebuffer(stfb); + unsigned front = ST_ATTACHMENT_FRONT_LEFT, back = ST_ATTACHMENT_BACK_LEFT; + struct pipe_resource *ptex; + struct pipe_surface *psurf; + unsigned mask; + + /* swap the textures */ + ptex = stwfb->textures[front]; + stwfb->textures[front] = stwfb->textures[back]; + stwfb->textures[back] = ptex; + + /* swap the surfaces */ + psurf = stwfb->front_surface; + stwfb->front_surface = stwfb->back_surface; + stwfb->back_surface = psurf; + + /* convert to mask */ + front = 1 << front; + back = 1 << back; + + /* swap the bits in mask */ + mask = stwfb->texture_mask & ~(front | back); + if (stwfb->texture_mask & front) + mask |= back; + if (stwfb->texture_mask & back) + mask |= front; + stwfb->texture_mask = mask; + + front = ST_ATTACHMENT_FRONT_LEFT; + return stw_st_framebuffer_present_locked(&stwfb->base, front); +} + +/** + * Create an st_api of the state tracker. + */ +struct st_api * +stw_st_create_api(void) +{ + return st_gl_api_create(); +} diff --git a/src/gallium/state_trackers/egl/common/egl_st.h b/src/gallium/state_trackers/wgl/stw_st.h index 8fb464bd3d7..23771d8bef6 100644 --- a/src/gallium/state_trackers/egl/common/egl_st.h +++ b/src/gallium/state_trackers/wgl/stw_st.h @@ -1,8 +1,8 @@ /* * Mesa 3-D graphics library - * Version: 7.8 + * Version: 7.9 * - * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,54 +20,28 @@ * BRIAN PAUL 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. + * + * Authors: + * Chia-I Wu <[email protected]> */ -#ifndef _EGL_ST_H_ -#define _EGL_ST_H_ - -#include "GL/gl.h" /* for GL types */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" - -/* avoid calling st functions directly */ -#if 1 - -#define ST_SURFACE_FRONT_LEFT 0 -#define ST_SURFACE_BACK_LEFT 1 -#define ST_SURFACE_FRONT_RIGHT 2 -#define ST_SURFACE_BACK_RIGHT 3 - -#define ST_TEXTURE_2D 0x2 +#ifndef STW_ST_H +#define STW_ST_H -struct st_context; -struct st_framebuffer; -typedef void (*st_proc)(); +#include "state_tracker/st_api.h" -#else -#include "state_tracker/st_public.h" -#endif +struct stw_framebuffer; -/* remember to update egl_g3d_get_st() when update the enums */ -enum egl_g3d_st_api { - EGL_G3D_ST_OPENGL_ES = 0, - EGL_G3D_ST_OPENVG, - EGL_G3D_ST_OPENGL_ES2, - EGL_G3D_ST_OPENGL, +struct st_api * +stw_st_create_api(void); - NUM_EGL_G3D_STS -}; +struct st_framebuffer_iface * +stw_st_create_framebuffer(struct stw_framebuffer *fb); -struct egl_g3d_st { -#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__); -#include "st_public_tmp.h" - /* fields must be added here */ - EGLint api_bit; -}; +void +stw_st_destroy_framebuffer_locked(struct st_framebuffer_iface *stfb); -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api); +boolean +stw_st_swap_framebuffer_locked(struct st_framebuffer_iface *stfb); -#endif /* _EGL_ST_H_ */ +#endif /* STW_ST_H */ diff --git a/src/gallium/state_trackers/xorg/xorg_composite.c b/src/gallium/state_trackers/xorg/xorg_composite.c index c50873c1508..4ff48026e50 100644 --- a/src/gallium/state_trackers/xorg/xorg_composite.c +++ b/src/gallium/state_trackers/xorg/xorg_composite.c @@ -4,6 +4,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" /*XXX also in Xrender.h but the including it here breaks compilition */ @@ -356,17 +357,12 @@ bind_samplers(struct exa_context *exa, int op, { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state src_sampler, mask_sampler; + struct pipe_sampler_view view_templ; + struct pipe_sampler_view *src_view; + struct pipe_context *pipe = exa->pipe; exa->num_bound_samplers = 0; -#if 0 - if ((pSrc && (exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE)) || - (pMask && (exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE))) - xorg_exa_flush(exa, PIPE_FLUSH_RENDER_CACHE, NULL); -#endif - memset(&src_sampler, 0, sizeof(struct pipe_sampler_state)); memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state)); @@ -374,7 +370,7 @@ bind_samplers(struct exa_context *exa, int op, if (exa->has_solid_color) { debug_assert(!"solid color with textures"); samplers[0] = NULL; - exa->bound_textures[0] = NULL; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); } else { unsigned src_wrap = render_repeat_to_gallium( pSrcPicture->repeatType); @@ -389,8 +385,13 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; src_sampler.normalized_coords = 1; samplers[0] = &src_sampler; - exa->bound_textures[0] = pSrc->tex; exa->num_bound_samplers = 1; + u_sampler_view_default_template(&view_templ, + pSrc->tex, + pSrc->tex->format); + src_view = pipe->create_sampler_view(pipe, pSrc->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + exa->bound_sampler_views[0] = src_view; } } @@ -408,14 +409,19 @@ bind_samplers(struct exa_context *exa, int op, src_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; mask_sampler.normalized_coords = 1; samplers[1] = &mask_sampler; - exa->bound_textures[1] = pMask->tex; exa->num_bound_samplers = 2; + u_sampler_view_default_template(&view_templ, + pMask->tex, + pMask->tex->format); + src_view = pipe->create_sampler_view(pipe, pMask->tex, &view_templ); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + exa->bound_sampler_views[1] = src_view; } cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers, - exa->bound_textures); + cso_set_fragment_sampler_views(exa->renderer->cso, exa->num_bound_samplers, + exa->bound_sampler_views); } @@ -484,7 +490,6 @@ boolean xorg_composite_bind_state(struct exa_context *exa, renderer_begin_solid(exa->renderer); } else { renderer_begin_textures(exa->renderer, - exa->bound_textures, exa->num_bound_samplers); } @@ -514,7 +519,7 @@ void xorg_composite(struct exa_context *exa, renderer_texture(exa->renderer, pos, width, height, - exa->bound_textures, + exa->bound_sampler_views, exa->num_bound_samplers, src_matrix, mask_matrix); } @@ -546,7 +551,7 @@ boolean xorg_solid_bind_state(struct exa_context *exa, pixmap->width, pixmap->height); bind_blend_state(exa, PictOpSrc, NULL, NULL, NULL); cso_set_samplers(exa->renderer->cso, 0, NULL); - cso_set_sampler_textures(exa->renderer->cso, 0, NULL); + cso_set_fragment_sampler_views(exa->renderer->cso, 0, NULL); shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits); cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs); diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 000ec9048f5..669bd9edcf0 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -39,6 +39,7 @@ #include <xf86.h> #include <xf86i2c.h> #include <xf86Crtc.h> +#include <cursorstr.h> #include "xorg_tracker.h" #include "xf86Modes.h" @@ -61,7 +62,7 @@ struct crtc_private drmModeCrtcPtr drm_crtc; /* hwcursor */ - struct pipe_texture *cursor_tex; + struct pipe_resource *cursor_tex; struct kms_bo *cursor_bo; unsigned cursor_handle; @@ -196,12 +197,12 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) struct pipe_transfer *transfer; if (!crtcp->cursor_tex) { - struct pipe_texture templat; - unsigned pitch; + struct pipe_resource templat; + struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); - templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templat.bind |= PIPE_BIND_RENDER_TARGET; + templat.bind |= PIPE_BIND_SCANOUT; templat.target = PIPE_TEXTURE_2D; templat.last_level = 0; templat.depth0 = 1; @@ -209,25 +210,26 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) templat.width0 = 64; templat.height0 = 64; - crtcp->cursor_tex = ms->screen->texture_create(ms->screen, + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + crtcp->cursor_tex = ms->screen->resource_create(ms->screen, &templat); - ms->api->local_handle_from_texture(ms->api, - ms->screen, - crtcp->cursor_tex, - &pitch, - &crtcp->cursor_handle); + ms->screen->resource_get_handle(ms->screen, crtcp->cursor_tex, &whandle); + + crtcp->cursor_handle = whandle.handle; } - transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, - 0, 0, 0, - PIPE_TRANSFER_WRITE, - 0, 0, 64, 64); - ptr = ms->screen->transfer_map(ms->screen, transfer); + transfer = pipe_get_transfer(ms->ctx, crtcp->cursor_tex, + 0, 0, 0, + PIPE_TRANSFER_WRITE, + 0, 0, 64, 64); + ptr = ms->ctx->transfer_map(ms->ctx, transfer); util_copy_rect(ptr, crtcp->cursor_tex->format, transfer->stride, 0, 0, 64, 64, (void*)image, 64 * 4, 0, 0); - ms->screen->transfer_unmap(ms->screen, transfer); - ms->screen->tex_transfer_destroy(transfer); + ms->ctx->transfer_unmap(ms->ctx, transfer); + ms->ctx->transfer_destroy(ms->ctx, transfer); } #if HAVE_LIBKMS @@ -275,7 +277,21 @@ err_bo_destroy: static void crtc_load_cursor_argb(xf86CrtcPtr crtc, CARD32 * image) { + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(crtc->scrn); modesettingPtr ms = modesettingPTR(crtc->scrn); + + /* Older X servers have cursor reference counting bugs leading to use of + * freed memory and consequently random crashes. Should be fixed as of + * xserver 1.8, but this workaround shouldn't hurt anyway. + */ + if (config->cursor) + config->cursor->refcnt++; + + if (ms->cursor) + FreeCursor(ms->cursor, None); + + ms->cursor = config->cursor; + if (ms->screen) crtc_load_cursor_argb_ga3d(crtc, image); #ifdef HAVE_LIBKMS @@ -313,7 +329,7 @@ xorg_crtc_cursor_destroy(xf86CrtcPtr crtc) struct crtc_private *crtcp = crtc->driver_private; if (crtcp->cursor_tex) - pipe_texture_reference(&crtcp->cursor_tex, NULL); + pipe_resource_reference(&crtcp->cursor_tex, NULL); #ifdef HAVE_LIBKMS if (crtcp->cursor_bo) kms_bo_destroy(&crtcp->cursor_bo); diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index 5fc85c0e98c..b90f9c908d2 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -53,21 +53,21 @@ static Bool set_format_in_do_create_buffer; typedef struct { PixmapPtr pPixmap; - struct pipe_texture *tex; + struct pipe_resource *tex; struct pipe_fence_handle *fence; } *BufferPrivatePtr; static Bool dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int format) { - struct pipe_texture *tex = NULL; + struct pipe_resource *tex = NULL; ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); struct exa_pixmap_priv *exa_priv; BufferPrivatePtr private = buffer->driverPrivate; PixmapPtr pPixmap; - unsigned stride, handle; + struct winsys_handle whandle; if (pDraw->type == DRAWABLE_PIXMAP) pPixmap = (PixmapPtr) pDraw; @@ -75,6 +75,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw); exa_priv = exaGetPixmapDriverPrivate(pPixmap); + switch (buffer->attachment) { default: if (buffer->attachment != DRI2BufferFakeFrontLeft || @@ -100,9 +101,9 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form /* Fall through */ case DRI2BufferDepth: if (exa_priv->depth_stencil_tex) - pipe_texture_reference(&tex, exa_priv->depth_stencil_tex); + pipe_resource_reference(&tex, exa_priv->depth_stencil_tex); else { - struct pipe_texture template; + struct pipe_resource template; unsigned depthBits = (format != 0) ? format : pDraw->depth; memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; @@ -121,16 +122,16 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form } } else { template.format = ms->ds_depth_bits_last ? - PIPE_FORMAT_Z24S8_UNORM : PIPE_FORMAT_S8Z24_UNORM; + PIPE_FORMAT_Z24_UNORM_S8_USCALED : PIPE_FORMAT_S8_USCALED_Z24_UNORM; } template.width0 = pDraw->width; template.height0 = pDraw->height; template.depth0 = 1; template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET; - tex = ms->screen->texture_create(ms->screen, &template); - pipe_texture_reference(&exa_priv->depth_stencil_tex, tex); + template.bind = PIPE_BIND_DEPTH_STENCIL | + PIPE_BIND_SHARED; + tex = ms->screen->resource_create(ms->screen, &template); + pipe_resource_reference(&exa_priv->depth_stencil_tex, tex); } break; } @@ -153,10 +154,13 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form if (!tex) FatalError("NO TEXTURE IN DRI2\n"); - ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + + ms->screen->resource_get_handle(ms->screen, tex, &whandle); - buffer->name = handle; - buffer->pitch = stride; + buffer->name = whandle.handle; + buffer->pitch = whandle.stride; buffer->cpp = 4; buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ @@ -181,9 +185,9 @@ dri2_do_destroy_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer) BufferPrivatePtr private = buffer->driverPrivate; struct exa_pixmap_priv *exa_priv = exaGetPixmapDriverPrivate(private->pPixmap); - pipe_texture_reference(&private->tex, NULL); + pipe_resource_reference(&private->tex, NULL); ms->screen->fence_reference(ms->screen, &private->fence, NULL); - pipe_texture_reference(&exa_priv->depth_stencil_tex, NULL); + pipe_resource_reference(&exa_priv->depth_stencil_tex, NULL); (*pScreen->DestroyPixmap)(private->pPixmap); } @@ -433,11 +437,11 @@ xorg_dri2_init(ScreenPtr pScreen) ms->d_depth_bits_last = ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_Z24X8_UNORM, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + PIPE_BIND_DEPTH_STENCIL, 0); ms->ds_depth_bits_last = - ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_Z24S8_UNORM, + ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + PIPE_BIND_DEPTH_STENCIL, 0); return DRI2ScreenInit(pScreen, &dri2info); } diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index 8fb6e5a96dd..3687ee0db4e 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -676,10 +676,9 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) } if (ms->screen) { - float maxf; int max; - maxf = ms->screen->get_paramf(ms->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); - max = (1 << (int)(maxf - 1.0f)); + max = ms->screen->get_param(ms->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + max = 1 << (max - 1); max_width = max < max_width ? max : max_width; max_height = max < max_height ? max : max_height; } @@ -922,6 +921,11 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) drv_leave_vt(scrnIndex, 0); } + if (ms->cursor) { + FreeCursor(ms->cursor, None); + ms->cursor = NULL; + } + if (cust && cust->winsys_screen_close) cust->winsys_screen_close(cust); @@ -981,7 +985,7 @@ drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) ms->fb_id = -1; } - pipe_texture_reference(&ms->root_texture, NULL); + pipe_resource_reference(&ms->root_texture, NULL); return TRUE; } @@ -989,8 +993,9 @@ static Bool drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - unsigned handle, stride, fb_id; - struct pipe_texture *tex; + struct pipe_resource *tex; + struct winsys_handle whandle; + unsigned fb_id; int ret; ms->noEvict = TRUE; @@ -1001,10 +1006,10 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) if (!tex) return FALSE; - if (!ms->api->local_handle_from_texture(ms->api, ms->screen, - tex, - &stride, - &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!ms->screen->resource_get_handle(ms->screen, tex, &whandle)) goto err_destroy; ret = drmModeAddFB(ms->fd, @@ -1012,8 +1017,8 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, - stride, - handle, + whandle.stride, + whandle.handle, &fb_id); if (ret) { debug_printf("%s: failed to create framebuffer (%i, %s)\n", @@ -1028,14 +1033,14 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) pScrn->frameY0 = 0; drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); - pipe_texture_reference(&ms->root_texture, tex); - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&ms->root_texture, tex); + pipe_resource_reference(&tex, NULL); ms->fb_id = fb_id; return TRUE; err_destroy: - pipe_texture_reference(&tex, NULL); + pipe_resource_reference(&tex, NULL); return FALSE; } @@ -1045,7 +1050,7 @@ drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen); - struct pipe_texture *check; + struct pipe_resource *check; xorg_exa_set_displayed_usage(rootPixmap); xorg_exa_set_shared_usage(rootPixmap); @@ -1057,7 +1062,7 @@ drv_bind_front_buffer_ga3d(ScrnInfoPtr pScrn) if (ms->root_texture != check) FatalError("Created new root texture\n"); - pipe_texture_reference(&check, NULL); + pipe_resource_reference(&check, NULL); return TRUE; } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index a242e02ee77..d5a1be81747 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -188,11 +188,7 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, if (!priv || !priv->tex) return FALSE; - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE) - exa->pipe->flush(exa->pipe, 0, NULL); - - transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_READ, x, y, w, h); if (!transfer) return FALSE; @@ -203,11 +199,11 @@ ExaDownloadFromScreen(PixmapPtr pPix, int x, int y, int w, int h, char *dst, #endif util_copy_rect((unsigned char*)dst, priv->tex->format, dst_pitch, 0, 0, - w, h, exa->scrn->transfer_map(exa->scrn, transfer), + w, h, exa->pipe->transfer_map(exa->pipe, transfer), transfer->stride, 0, 0); - exa->scrn->transfer_unmap(exa->scrn, transfer); - exa->scrn->tex_transfer_destroy(transfer); + exa->pipe->transfer_unmap(exa->pipe, transfer); + exa->pipe->transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -226,12 +222,7 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, if (!priv || !priv->tex) return FALSE; - /* make sure that any pending operations are flushed to hardware */ - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - (PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE)) - xorg_exa_flush(exa, 0, NULL); - - transfer = exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + transfer = pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, PIPE_TRANSFER_WRITE, x, y, w, h); if (!transfer) return FALSE; @@ -241,12 +232,12 @@ ExaUploadToScreen(PixmapPtr pPix, int x, int y, int w, int h, char *src, x, y, w, h, src_pitch); #endif - util_copy_rect(exa->scrn->transfer_map(exa->scrn, transfer), + util_copy_rect(exa->pipe->transfer_map(exa->pipe, transfer), priv->tex->format, transfer->stride, 0, 0, w, h, (unsigned char*)src, src_pitch, 0, 0); - exa->scrn->transfer_unmap(exa->scrn, transfer); - exa->scrn->tex_transfer_destroy(transfer); + exa->pipe->transfer_unmap(exa->pipe, transfer); + exa->pipe->transfer_destroy(exa->pipe, transfer); return TRUE; } @@ -270,15 +261,11 @@ ExaPrepareAccess(PixmapPtr pPix, int index) if (priv->map_count == 0) { - if (exa->pipe->is_texture_referenced(exa->pipe, priv->tex, 0, 0) & - PIPE_REFERENCED_FOR_WRITE) - exa->pipe->flush(exa->pipe, 0, NULL); - assert(pPix->drawable.width <= priv->tex->width0); assert(pPix->drawable.height <= priv->tex->height0); priv->map_transfer = - exa->scrn->get_tex_transfer(exa->scrn, priv->tex, 0, 0, 0, + pipe_get_transfer(exa->pipe, priv->tex, 0, 0, 0, #ifdef EXA_MIXED_PIXMAPS PIPE_TRANSFER_MAP_DIRECTLY | #endif @@ -294,7 +281,7 @@ ExaPrepareAccess(PixmapPtr pPix, int index) #endif pPix->devPrivate.ptr = - exa->scrn->transfer_map(exa->scrn, priv->map_transfer); + exa->pipe->transfer_map(exa->pipe, priv->map_transfer); pPix->devKind = priv->map_transfer->stride; } @@ -321,8 +308,8 @@ ExaFinishAccess(PixmapPtr pPix, int index) if (--priv->map_count == 0) { assert(priv->map_transfer); - exa->scrn->transfer_unmap(exa->scrn, priv->map_transfer); - exa->scrn->tex_transfer_destroy(priv->map_transfer); + exa->pipe->transfer_unmap(exa->pipe, priv->map_transfer); + exa->pipe->transfer_destroy(exa->pipe, priv->map_transfer); priv->map_transfer = NULL; pPix->devPrivate.ptr = NULL; } @@ -360,7 +347,7 @@ ExaPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planeMask, Pixel fg) if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, priv->tex->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) { + PIPE_BIND_RENDER_TARGET, 0)) { XORG_FALLBACK("format %s", util_format_name(priv->tex->format)); } @@ -441,12 +428,12 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, priv->tex->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) + PIPE_BIND_RENDER_TARGET, 0)) XORG_FALLBACK("pDst format %s", util_format_name(priv->tex->format)); if (!exa->scrn->is_format_supported(exa->scrn, src_priv->tex->format, src_priv->tex->target, - PIPE_TEXTURE_USAGE_SAMPLER, 0)) + PIPE_BIND_SAMPLER_VIEW, 0)) XORG_FALLBACK("pSrc format %s", util_format_name(src_priv->tex->format)); exa->copy.src = src_priv; @@ -466,13 +453,13 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, exa->scrn->get_tex_surface( exa->scrn, exa->copy.src->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ); + PIPE_BIND_BLIT_SOURCE); exa->copy.dst_surface = exa->scrn->get_tex_surface( exa->scrn, exa->copy.dst->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE ); + PIPE_BIND_BLIT_DESTINATION ); } else { exa->copy.use_surface_copy = FALSE; @@ -481,14 +468,14 @@ ExaPrepareCopy(PixmapPtr pSrcPixmap, PixmapPtr pDstPixmap, int xdir, exa->copy.src_texture = renderer_clone_texture( exa->renderer, exa->copy.src->tex ); else - pipe_texture_reference(&exa->copy.src_texture, + pipe_resource_reference(&exa->copy.src_texture, exa->copy.src->tex); exa->copy.dst_surface = exa->scrn->get_tex_surface(exa->scrn, exa->copy.dst->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_DESTINATION); renderer_copy_prepare(exa->renderer, @@ -554,7 +541,7 @@ ExaDoneCopy(PixmapPtr pPixmap) exa->copy.dst = NULL; pipe_surface_reference(&exa->copy.src_surface, NULL); pipe_surface_reference(&exa->copy.dst_surface, NULL); - pipe_texture_reference(&exa->copy.src_texture, NULL); + pipe_resource_reference(&exa->copy.src_texture, NULL); } @@ -652,7 +639,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, priv->tex->target, - PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) + PIPE_BIND_RENDER_TARGET, 0)) XORG_FALLBACK("pDst format: %s", util_format_name(priv->tex->format)); if (priv->picture_format != pDstPicture->format) @@ -667,7 +654,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, priv->tex->target, - PIPE_TEXTURE_USAGE_SAMPLER, 0)) + PIPE_BIND_SAMPLER_VIEW, 0)) XORG_FALLBACK("pSrc format: %s", util_format_name(priv->tex->format)); if (!picture_check_formats(priv, pSrcPicture)) @@ -684,7 +671,7 @@ ExaPrepareComposite(int op, PicturePtr pSrcPicture, if (!exa->scrn->is_format_supported(exa->scrn, priv->tex->format, priv->tex->target, - PIPE_TEXTURE_USAGE_SAMPLER, 0)) + PIPE_BIND_SAMPLER_VIEW, 0)) XORG_FALLBACK("pMask format: %s", util_format_name(priv->tex->format)); if (!picture_check_formats(priv, pMaskPicture)) @@ -757,7 +744,7 @@ ExaDestroyPixmap(ScreenPtr pScreen, void *dPriv) if (!priv) return; - pipe_texture_reference(&priv->tex, NULL); + pipe_resource_reference(&priv->tex, NULL); xfree(priv); } @@ -789,7 +776,7 @@ xorg_exa_set_displayed_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY; + priv->flags |= PIPE_BIND_SCANOUT; return 0; } @@ -805,7 +792,7 @@ xorg_exa_set_shared_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + priv->flags |= PIPE_BIND_SHARED; return 0; } @@ -880,8 +867,8 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, !size_match(width, priv->tex->width0) || !size_match(height, priv->tex->height0) || priv->tex_flags != priv->flags)) { - struct pipe_texture *texture = NULL; - struct pipe_texture template; + struct pipe_resource *texture = NULL; + struct pipe_resource template; memset(&template, 0, sizeof(template)); template.target = PIPE_TEXTURE_2D; @@ -897,16 +884,16 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, template.depth0 = 1; template.last_level = 0; - template.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET | priv->flags; + template.bind = PIPE_BIND_RENDER_TARGET | priv->flags; priv->tex_flags = priv->flags; - texture = exa->scrn->texture_create(exa->scrn, &template); + texture = exa->scrn->resource_create(exa->scrn, &template); if (priv->tex) { struct pipe_surface *dst_surf; struct pipe_surface *src_surf; dst_surf = exa->scrn->get_tex_surface( - exa->scrn, texture, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE); + exa->scrn, texture, 0, 0, 0, PIPE_BIND_BLIT_DESTINATION); src_surf = xorg_gpu_surface(exa->pipe->screen, priv); if (exa->pipe->surface_copy) { exa->pipe->surface_copy(exa->pipe, dst_surf, 0, 0, src_surf, @@ -921,29 +908,29 @@ ExaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, exa->scrn->tex_surface_destroy(src_surf); } - pipe_texture_reference(&priv->tex, texture); + pipe_resource_reference(&priv->tex, texture); /* the texture we create has one reference */ - pipe_texture_reference(&texture, NULL); + pipe_resource_reference(&texture, NULL); } return TRUE; } -struct pipe_texture * +struct pipe_resource * xorg_exa_get_texture(PixmapPtr pPixmap) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); - struct pipe_texture *tex = NULL; - pipe_texture_reference(&tex, priv->tex); + struct pipe_resource *tex = NULL; + pipe_resource_reference(&tex, priv->tex); return tex; } Bool -xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) +xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); - int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + int mask = PIPE_BIND_SHARED | PIPE_BIND_SCANOUT; if (!priv) return FALSE; @@ -952,20 +939,20 @@ xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) pPixmap->drawable.height != tex->height0) return FALSE; - pipe_texture_reference(&priv->tex, tex); - priv->tex_flags = tex->tex_usage & mask; + pipe_resource_reference(&priv->tex, tex); + priv->tex_flags = tex->bind & mask; return TRUE; } -struct pipe_texture * +struct pipe_resource * xorg_exa_create_root_texture(ScrnInfoPtr pScrn, int width, int height, int depth, int bitsPerPixel) { modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; - struct pipe_texture template; + struct pipe_resource template; int dummy; memset(&template, 0, sizeof(template)); @@ -975,11 +962,11 @@ xorg_exa_create_root_texture(ScrnInfoPtr pScrn, template.height0 = height; template.depth0 = 1; template.last_level = 0; - template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; - template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.bind |= PIPE_BIND_RENDER_TARGET; + template.bind |= PIPE_BIND_SCANOUT; + template.bind |= PIPE_BIND_SHARED; - return exa->scrn->texture_create(exa->scrn, &template); + return exa->scrn->resource_create(exa->scrn, &template); } void @@ -988,6 +975,9 @@ xorg_exa_close(ScrnInfoPtr pScrn) modesettingPtr ms = modesettingPTR(pScrn); struct exa_context *exa = ms->exa; + pipe_sampler_view_reference(&exa->bound_sampler_views[0], NULL); + pipe_sampler_view_reference(&exa->bound_sampler_views[1], NULL); + renderer_destroy(exa->renderer); if (exa->pipe) @@ -1083,9 +1073,12 @@ out_err: struct pipe_surface * xorg_gpu_surface(struct pipe_screen *scrn, struct exa_pixmap_priv *priv) { + + /* seems to get called both for blits and render target usage */ return scrn->get_tex_surface(scrn, priv->tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); + PIPE_BIND_BLIT_SOURCE | + PIPE_BIND_BLIT_DESTINATION | + PIPE_BIND_RENDER_TARGET); } diff --git a/src/gallium/state_trackers/xorg/xorg_exa.h b/src/gallium/state_trackers/xorg/xorg_exa.h index f2cefe23b99..a35e9a5c901 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.h +++ b/src/gallium/state_trackers/xorg/xorg_exa.h @@ -18,7 +18,7 @@ struct exa_context struct pipe_screen *scrn; struct xorg_renderer *renderer; - struct pipe_texture *bound_textures[MAX_EXA_SAMPLERS]; + struct pipe_sampler_view *bound_sampler_views[MAX_EXA_SAMPLERS]; int num_bound_samplers; float solid_color[4]; @@ -43,7 +43,7 @@ struct exa_context struct pipe_surface *src_surface; struct pipe_surface *dst_surface; - struct pipe_texture *src_texture; + struct pipe_resource *src_texture; } copy; }; @@ -56,8 +56,8 @@ struct exa_pixmap_priv int picture_format; - struct pipe_texture *tex; - struct pipe_texture *depth_stencil_tex; + struct pipe_resource *tex; + struct pipe_resource *depth_stencil_tex; struct pipe_transfer *map_transfer; unsigned map_count; diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.c b/src/gallium/state_trackers/xorg/xorg_renderer.c index 83b0d31e38d..13fa561390f 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.c +++ b/src/gallium/state_trackers/xorg/xorg_renderer.c @@ -8,6 +8,7 @@ #include "util/u_math.h" #include "util/u_memory.h" #include "util/u_rect.h" +#include "util/u_sampler.h" #include "util/u_inlines.h" @@ -41,14 +42,16 @@ static INLINE void map_point(float *mat, float x, float y, } } -static INLINE struct pipe_buffer * +static INLINE struct pipe_resource * renderer_buffer_create(struct xorg_renderer *r) { - struct pipe_buffer *buf = + struct pipe_resource *buf = pipe_user_buffer_create(r->pipe->screen, r->buffer, sizeof(float)* - r->buffer_size); + r->buffer_size, +/* XXX was: PIPE_BUFFER_USAGE_PIXEL/PIPE_BUFFER_USAGE_GPU_WRITE even though this is a vertex buffer??? */ + PIPE_BIND_VERTEX_BUFFER); r->buffer_size = 0; return buf; @@ -58,7 +61,7 @@ static INLINE void renderer_draw(struct xorg_renderer *r) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf = 0; + struct pipe_resource *buf = 0; int num_verts = r->buffer_size/(r->attrs_per_vertex * NUM_COMPONENTS); if (!r->buffer_size) @@ -68,12 +71,14 @@ renderer_draw(struct xorg_renderer *r) if (buf) { + cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, num_verts, /* verts */ r->attrs_per_vertex); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -92,6 +97,7 @@ renderer_init_state(struct xorg_renderer *r) { struct pipe_depth_stencil_alpha_state dsa; struct pipe_rasterizer_state raster; + unsigned i; /* set common initial clip state */ memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); @@ -103,6 +109,14 @@ renderer_init_state(struct xorg_renderer *r) raster.gl_rasterization_rules = 1; cso_set_rasterizer(r->cso, &raster); + /* vertex elements state */ + memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3); + for (i = 0; i < 3; i++) { + r->velems[i].src_offset = i * 4 * sizeof(float); + r->velems[i].instance_divisor = 0; + r->velems[i].vertex_buffer_index = 0; + r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + } } @@ -149,7 +163,7 @@ static void add_vertex_data1(struct xorg_renderer *r, float srcX, float srcY, float dstX, float dstY, float width, float height, - struct pipe_texture *src, float *src_matrix) + struct pipe_resource *src, float *src_matrix) { float s0, t0, s1, t1, s2, t2, s3, t3; float pt0[2], pt1[2], pt2[2], pt3[2]; @@ -219,8 +233,8 @@ static void add_vertex_data2(struct xorg_renderer *r, float srcX, float srcY, float maskX, float maskY, float dstX, float dstY, float width, float height, - struct pipe_texture *src, - struct pipe_texture *mask, + struct pipe_resource *src, + struct pipe_resource *mask, float *src_matrix, float *mask_matrix) { float src_s0, src_t0, src_s1, src_t1; @@ -272,11 +286,11 @@ add_vertex_data2(struct xorg_renderer *r, src_s0, src_t1, mask_s0, mask_t1); } -static struct pipe_buffer * +static struct pipe_resource * setup_vertex_data_yuv(struct xorg_renderer *r, float srcX, float srcY, float srcW, float srcH, float dstX, float dstY, float dstW, float dstH, - struct pipe_texture **tex) + struct pipe_resource **tex) { float s0, t0, s1, t1; float spt0[2], spt1[2]; @@ -378,14 +392,14 @@ struct xorg_renderer * renderer_create(struct pipe_context *pipe) void renderer_destroy(struct xorg_renderer *r) { - struct pipe_buffer **vsbuf = &r->vs_const_buffer; - struct pipe_buffer **fsbuf = &r->fs_const_buffer; + struct pipe_resource **vsbuf = &r->vs_const_buffer; + struct pipe_resource **fsbuf = &r->fs_const_buffer; if (*vsbuf) - pipe_buffer_reference(vsbuf, NULL); + pipe_resource_reference(vsbuf, NULL); if (*fsbuf) - pipe_buffer_reference(fsbuf, NULL); + pipe_resource_reference(fsbuf, NULL); if (r->shaders) { xorg_shaders_destroy(r->shaders); @@ -408,17 +422,17 @@ void renderer_set_constants(struct xorg_renderer *r, const float *params, int param_bytes) { - struct pipe_buffer **cbuf = + struct pipe_resource **cbuf = (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer : &r->fs_const_buffer; - pipe_buffer_reference(cbuf, NULL); - *cbuf = pipe_buffer_create(r->pipe->screen, 16, - PIPE_BUFFER_USAGE_CONSTANT, + pipe_resource_reference(cbuf, NULL); + *cbuf = pipe_buffer_create(r->pipe->screen, + PIPE_BIND_CONSTANT_BUFFER, param_bytes); if (*cbuf) { - pipe_buffer_write(r->pipe->screen, *cbuf, + pipe_buffer_write(r->pipe, *cbuf, 0, param_bytes, params); } r->pipe->set_constant_buffer(r->pipe, shader_type, 0, *cbuf); @@ -427,7 +441,7 @@ void renderer_set_constants(struct xorg_renderer *r, void renderer_copy_prepare(struct xorg_renderer *r, struct pipe_surface *dst_surface, - struct pipe_texture *src_texture) + struct pipe_resource *src_texture) { struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; @@ -435,7 +449,7 @@ void renderer_copy_prepare(struct xorg_renderer *r, assert(screen->is_format_supported(screen, dst_surface->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_RENDER_TARGET, + PIPE_BIND_RENDER_TARGET, 0)); (void) screen; @@ -471,8 +485,17 @@ void renderer_copy_prepare(struct xorg_renderer *r, dst_surface->width, dst_surface->height); - /* texture */ - cso_set_sampler_textures(r->cso, 1, &src_texture); + /* texture/sampler view */ + { + struct pipe_sampler_view templ; + struct pipe_sampler_view *src_view; + u_sampler_view_default_template(&templ, + src_texture, + src_texture->format); + src_view = pipe->create_sampler_view(pipe, src_texture, &templ); + cso_set_fragment_sampler_views(r->cso, 1, &src_view); + pipe_sampler_view_reference(&src_view, NULL); + } /* shaders */ shader = xorg_shaders_get(r->shaders, @@ -485,24 +508,24 @@ void renderer_copy_prepare(struct xorg_renderer *r, r->attrs_per_vertex = 2; } -struct pipe_texture * +struct pipe_resource * renderer_clone_texture(struct xorg_renderer *r, - struct pipe_texture *src) + struct pipe_resource *src) { enum pipe_format format; struct pipe_context *pipe = r->pipe; struct pipe_screen *screen = pipe->screen; - struct pipe_texture *pt; - struct pipe_texture templ; + struct pipe_resource *pt; + struct pipe_resource templ; - if (pipe->is_texture_referenced(pipe, src, 0, 0) & + if (pipe->is_resource_referenced(pipe, src, 0, 0) & PIPE_REFERENCED_FOR_WRITE) pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); /* the coming in texture should already have that invariance */ debug_assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, - PIPE_TEXTURE_USAGE_SAMPLER, 0)); + PIPE_BIND_SAMPLER_VIEW, 0)); format = src->format; @@ -513,9 +536,9 @@ renderer_clone_texture(struct xorg_renderer *r, templ.width0 = src->width0; templ.height0 = src->height0; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + templ.bind = PIPE_BIND_SAMPLER_VIEW; - pt = screen->texture_create(screen, &templ); + pt = screen->resource_create(screen, &templ); debug_assert(!pt || pipe_is_referenced(&pt->reference)); @@ -525,9 +548,9 @@ renderer_clone_texture(struct xorg_renderer *r, { /* copy source framebuffer surface into texture */ struct pipe_surface *ps_read = screen->get_tex_surface( - screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ); + screen, src, 0, 0, 0, PIPE_BIND_BLIT_SOURCE); struct pipe_surface *ps_tex = screen->get_tex_surface( - screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE ); + screen, pt, 0, 0, 0, PIPE_BIND_BLIT_DESTINATION ); if (pipe->surface_copy) { pipe->surface_copy(pipe, ps_tex, /* dest */ @@ -587,10 +610,10 @@ void renderer_copy_pixmap(struct xorg_renderer *r, void renderer_draw_yuv(struct xorg_renderer *r, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, - struct pipe_texture **textures) + struct pipe_resource **textures) { struct pipe_context *pipe = r->pipe; - struct pipe_buffer *buf = 0; + struct pipe_resource *buf = 0; buf = setup_vertex_data_yuv(r, src_x, src_y, src_w, src_h, @@ -600,12 +623,14 @@ void renderer_draw_yuv(struct xorg_renderer *r, if (buf) { const int num_attribs = 2; /*pos + tex coord*/ + cso_set_vertex_elements(r->cso, num_attribs, r->velems); + util_draw_vertex_buffer(pipe, buf, 0, PIPE_PRIM_QUADS, 4, /* verts */ num_attribs); /* attribs/vert */ - pipe_buffer_reference(&buf, NULL); + pipe_resource_reference(&buf, NULL); } } @@ -642,7 +667,6 @@ void renderer_draw_flush(struct xorg_renderer *r) } void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures) { r->attrs_per_vertex = 1 + num_textures; @@ -652,7 +676,7 @@ void renderer_begin_textures(struct xorg_renderer *r, void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **sampler_view, int num_textures, float *src_matrix, float *mask_matrix) @@ -680,7 +704,7 @@ void renderer_texture(struct xorg_renderer *r, pos[0], pos[1], /* src */ pos[4], pos[5], /* dst */ width, height, - textures[0], src_matrix); + sampler_view[0]->texture, src_matrix); break; case 3: renderer_draw_conditional(r, 4 * 12); @@ -689,7 +713,7 @@ void renderer_texture(struct xorg_renderer *r, pos[2], pos[3], /* mask */ pos[4], pos[5], /* dst */ width, height, - textures[0], textures[1], + sampler_view[0]->texture, sampler_view[1]->texture, src_matrix, mask_matrix); break; default: diff --git a/src/gallium/state_trackers/xorg/xorg_renderer.h b/src/gallium/state_trackers/xorg/xorg_renderer.h index af6aa0567d6..0454a6513d4 100644 --- a/src/gallium/state_trackers/xorg/xorg_renderer.h +++ b/src/gallium/state_trackers/xorg/xorg_renderer.h @@ -23,11 +23,12 @@ struct xorg_renderer { int fb_width; int fb_height; - struct pipe_buffer *vs_const_buffer; - struct pipe_buffer *fs_const_buffer; + struct pipe_resource *vs_const_buffer; + struct pipe_resource *fs_const_buffer; float buffer[BUF_SIZE]; int buffer_size; + struct pipe_vertex_element velems[3]; /* number of attributes per vertex for the current * draw operation */ @@ -55,7 +56,7 @@ void renderer_set_constants(struct xorg_renderer *r, void renderer_draw_yuv(struct xorg_renderer *r, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h, - struct pipe_texture **textures); + struct pipe_resource **textures); void renderer_begin_solid(struct xorg_renderer *r); void renderer_solid(struct xorg_renderer *r, @@ -64,25 +65,25 @@ void renderer_solid(struct xorg_renderer *r, float *color); void renderer_begin_textures(struct xorg_renderer *r, - struct pipe_texture **textures, int num_textures); + void renderer_texture(struct xorg_renderer *r, int *pos, int width, int height, - struct pipe_texture **textures, + struct pipe_sampler_view **textures, int num_textures, float *src_matrix, float *mask_matrix); void renderer_draw_flush(struct xorg_renderer *r); -struct pipe_texture * +struct pipe_resource * renderer_clone_texture(struct xorg_renderer *r, - struct pipe_texture *src); + struct pipe_resource *src); void renderer_copy_prepare(struct xorg_renderer *r, struct pipe_surface *dst_surface, - struct pipe_texture *src_texture); + struct pipe_resource *src_texture); void renderer_copy_pixmap(struct xorg_renderer *r, int dx, int dy, diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 2f5cc64d9c5..cb6773424a8 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -90,6 +90,7 @@ typedef struct _modesettingRec Bool noAccel; Bool SWCursor; + CursorPtr cursor; CloseScreenProcPtr CloseScreen; /* Broken-out options. */ @@ -117,7 +118,7 @@ typedef struct _modesettingRec struct pipe_context *ctx; boolean d_depth_bits_last; boolean ds_depth_bits_last; - struct pipe_texture *root_texture; + struct pipe_resource *root_texture; /* exa */ struct exa_context *exa; @@ -141,7 +142,7 @@ Bool xorg_has_gallium(ScrnInfoPtr pScrn); /*********************************************************************** * xorg_exa.c */ -struct pipe_texture * +struct pipe_resource * xorg_exa_get_texture(PixmapPtr pPixmap); int @@ -151,9 +152,9 @@ int xorg_exa_set_shared_usage(PixmapPtr pPixmap); Bool -xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex); +xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_resource *tex); -struct pipe_texture * +struct pipe_resource * xorg_exa_create_root_texture(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp); diff --git a/src/gallium/state_trackers/xorg/xorg_xv.c b/src/gallium/state_trackers/xorg/xorg_xv.c index e37a1c39596..a221594454e 100644 --- a/src/gallium/state_trackers/xorg/xorg_xv.c +++ b/src/gallium/state_trackers/xorg/xorg_xv.c @@ -9,6 +9,7 @@ #include "xorg_exa_tgsi.h" #include "cso_cache/cso_context.h" +#include "util/u_sampler.h" #include "pipe/p_screen.h" @@ -90,7 +91,8 @@ struct xorg_xv_port_priv { int current_set; /* juggle two sets of seperate Y, U and V * textures */ - struct pipe_texture *yuv[2][3]; + struct pipe_resource *yuv[2][3]; + struct pipe_sampler_view *yuv_views[2][3]; }; @@ -154,13 +156,13 @@ query_best_size(ScrnInfoPtr pScrn, *p_h = drw_h; } -static INLINE struct pipe_texture * +static INLINE struct pipe_resource * create_component_texture(struct pipe_context *pipe, int width, int height) { struct pipe_screen *screen = pipe->screen; - struct pipe_texture *tex = 0; - struct pipe_texture templ; + struct pipe_resource *tex = 0; + struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; @@ -169,9 +171,9 @@ create_component_texture(struct pipe_context *pipe, templ.width0 = width; templ.height0 = height; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + templ.bind = PIPE_BIND_SAMPLER_VIEW; - tex = screen->texture_create(screen, &templ); + tex = screen->resource_create(screen, &templ); return tex; } @@ -179,33 +181,61 @@ create_component_texture(struct pipe_context *pipe, static int check_yuv_textures(struct xorg_xv_port_priv *priv, int width, int height) { - struct pipe_texture **dst = priv->yuv[priv->current_set]; + struct pipe_resource **dst = priv->yuv[priv->current_set]; + struct pipe_sampler_view **dst_view = priv->yuv_views[priv->current_set]; + struct pipe_sampler_view view_templ; + struct pipe_context *pipe = priv->r->pipe; + if (!dst[0] || dst[0]->width0 != width || dst[0]->height0 != height) { - pipe_texture_reference(&dst[0], NULL); + pipe_resource_reference(&dst[0], NULL); + pipe_sampler_view_reference(&dst_view[0], NULL); } if (!dst[1] || dst[1]->width0 != width || dst[1]->height0 != height) { - pipe_texture_reference(&dst[1], NULL); + pipe_resource_reference(&dst[1], NULL); + pipe_sampler_view_reference(&dst_view[1], NULL); } if (!dst[2] || dst[2]->width0 != width || dst[2]->height0 != height) { - pipe_texture_reference(&dst[2], NULL); + pipe_resource_reference(&dst[2], NULL); + pipe_sampler_view_reference(&dst_view[2], NULL); } - if (!dst[0]) + if (!dst[0]) { dst[0] = create_component_texture(priv->r->pipe, width, height); + if (dst[0]) { + u_sampler_view_default_template(&view_templ, + dst[0], + dst[0]->format); + dst_view[0] = pipe->create_sampler_view(pipe, dst[0], &view_templ); + } + } - if (!dst[1]) + if (!dst[1]) { dst[1] = create_component_texture(priv->r->pipe, width, height); + if (dst[1]) { + u_sampler_view_default_template(&view_templ, + dst[1], + dst[1]->format); + dst_view[1] = pipe->create_sampler_view(pipe, dst[1], &view_templ); + } + } - if (!dst[2]) + if (!dst[2]) { dst[2] = create_component_texture(priv->r->pipe, width, height); + if (dst[2]) { + u_sampler_view_default_template(&view_templ, + dst[2], + dst[2]->format); + dst_view[2] = pipe->create_sampler_view(pipe, dst[2], &view_templ); + } + } - if (!dst[0] || !dst[1] || !dst[2]) + if (!dst[0] || !dst[1] || !dst[2] || !dst_view[0] || !dst_view[1] || !dst_view[2] ) return BadAlloc; return Success; @@ -273,30 +303,30 @@ copy_packed_data(ScrnInfoPtr pScrn, unsigned short w, unsigned short h) { int i, j; - struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_resource **dst = port->yuv[port->current_set]; struct pipe_transfer *ytrans, *utrans, *vtrans; - struct pipe_screen *screen = port->r->pipe->screen; + struct pipe_context *pipe = port->r->pipe; char *ymap, *vmap, *umap; unsigned char y1, y2, u, v; int yidx, uidx, vidx; int y_array_size = w * h; - ytrans = screen->get_tex_transfer(screen, dst[0], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - utrans = screen->get_tex_transfer(screen, dst[1], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - vtrans = screen->get_tex_transfer(screen, dst[2], - 0, 0, 0, - PIPE_TRANSFER_WRITE, - left, top, w, h); - - ymap = (char*)screen->transfer_map(screen, ytrans); - umap = (char*)screen->transfer_map(screen, utrans); - vmap = (char*)screen->transfer_map(screen, vtrans); + ytrans = pipe_get_transfer(pipe, dst[0], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + utrans = pipe_get_transfer(pipe, dst[1], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + vtrans = pipe_get_transfer(pipe, dst[2], + 0, 0, 0, + PIPE_TRANSFER_WRITE, + left, top, w, h); + + ymap = (char*)pipe->transfer_map(pipe, ytrans); + umap = (char*)pipe->transfer_map(pipe, utrans); + vmap = (char*)pipe->transfer_map(pipe, vtrans); yidx = uidx = vidx = 0; @@ -362,12 +392,12 @@ copy_packed_data(ScrnInfoPtr pScrn, break; } - screen->transfer_unmap(screen, ytrans); - screen->transfer_unmap(screen, utrans); - screen->transfer_unmap(screen, vtrans); - screen->tex_transfer_destroy(ytrans); - screen->tex_transfer_destroy(utrans); - screen->tex_transfer_destroy(vtrans); + pipe->transfer_unmap(pipe, ytrans); + pipe->transfer_unmap(pipe, utrans); + pipe->transfer_unmap(pipe, vtrans); + pipe->transfer_destroy(pipe, ytrans); + pipe->transfer_destroy(pipe, utrans); + pipe->transfer_destroy(pipe, vtrans); } @@ -386,7 +416,7 @@ draw_yuv(struct xorg_xv_port_priv *port, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int dst_w, int dst_h) { - struct pipe_texture **textures = port->yuv[port->current_set]; + struct pipe_resource **textures = port->yuv[port->current_set]; /*debug_printf(" draw_yuv([%d, %d, %d ,%d], [%d, %d, %d, %d])\n", src_x, src_y, src_w, src_h, @@ -431,12 +461,12 @@ bind_shaders(struct xorg_xv_port_priv *port) } static INLINE void -conditional_flush(struct pipe_context *pipe, struct pipe_texture **tex, +conditional_flush(struct pipe_context *pipe, struct pipe_resource **tex, int num) { int i; for (i = 0; i < num; ++i) { - if (tex[i] && pipe->is_texture_referenced(pipe, tex[i], 0, 0) & + if (tex[i] && pipe->is_resource_referenced(pipe, tex[i], 0, 0) & PIPE_REFERENCED_FOR_WRITE) { pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL); return; @@ -449,7 +479,8 @@ bind_samplers(struct xorg_xv_port_priv *port) { struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS]; struct pipe_sampler_state sampler; - struct pipe_texture **dst = port->yuv[port->current_set]; + struct pipe_resource **dst = port->yuv[port->current_set]; + struct pipe_sampler_view **dst_views = port->yuv_views[port->current_set]; memset(&sampler, 0, sizeof(struct pipe_sampler_state)); @@ -469,8 +500,7 @@ bind_samplers(struct xorg_xv_port_priv *port) cso_set_samplers(port->r->cso, 3, (const struct pipe_sampler_state **)samplers); - cso_set_sampler_textures(port->r->cso, 3, - dst); + cso_set_fragment_sampler_views(port->r->cso, 3, dst_views); } static int diff --git a/src/gallium/state_trackers/xorg/xvmc/SConscript b/src/gallium/state_trackers/xorg/xvmc/SConscript deleted file mode 100644 index cb25d68bd80..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/SConscript +++ /dev/null @@ -1,27 +0,0 @@ -####################################################################### -# SConscript for xvmc state_tracker - -Import('*') - -if 'xorg/xvmc' in env['statetrackers']: - - env = env.Clone() - - env.Append(CPPPATH = [ - '#/src/gallium/include', - '#/src/gallium/auxiliary', - '#/src/gallium/winsys/g3dvl', - ]) - - env.ParseConfig('pkg-config --cflags --libs xvmc') - - st_xvmc = env.ConvenienceLibrary( - target = 'st_xvmc', - source = [ 'block.c', - 'surface.c', - 'context.c', - 'subpicture.c', - 'attributes.c', - ] - ) - Export('st_xvmc') diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c index 5bfccfaf37f..59842c90d0d 100644 --- a/src/gallium/state_trackers/xorg/xvmc/subpicture.c +++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c @@ -133,8 +133,8 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture * XvMCContextPrivate *context_priv; XvMCSubpicturePrivate *subpicture_priv; struct pipe_video_context *vpipe; - struct pipe_texture template; - struct pipe_texture *tex; + struct pipe_resource template; + struct pipe_resource *tex; Status ret; XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); @@ -162,7 +162,7 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture * if (!subpicture_priv) return BadAlloc; - memset(&template, 0, sizeof(struct pipe_texture)); + memset(&template, 0, sizeof(struct pipe_resource)); template.target = PIPE_TEXTURE_2D; template.format = XvIDToPipe(xvimage_id); template.last_level = 0; @@ -175,14 +175,15 @@ Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture * template.height0 = util_next_power_of_two(height); } template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER; + template.usage = PIPE_USAGE_DYNAMIC; + template.bind = PIPE_BIND_SAMPLER_VIEW; + template.flags = 0; subpicture_priv->context = context; - tex = vpipe->screen->texture_create(vpipe->screen, &template); + tex = vpipe->screen->resource_create(vpipe->screen, &template); subpicture_priv->sfc = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0, - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ); - pipe_texture_reference(&tex, NULL); + PIPE_BIND_SAMPLER_VIEW); + pipe_resource_reference(&tex, NULL); if (!subpicture_priv->sfc) { FREE(subpicture_priv); return BadAlloc; @@ -260,6 +261,7 @@ Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage /* TODO: Assert rects are within bounds? Or clip? */ +#if 0 xfer = screen->get_tex_transfer(screen, subpicture_priv->sfc->texture, 0, 0, 0, PIPE_TRANSFER_WRITE, dstx, dsty, width, height); if (!xfer) @@ -290,6 +292,7 @@ Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage screen->transfer_unmap(screen, xfer); screen->tex_transfer_destroy(xfer); +#endif XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 42df9e49ea5..decb2e896cd 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -99,8 +99,8 @@ CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned i struct pipe_surface **backbuffer) { struct pipe_video_context *vpipe; - struct pipe_texture template; - struct pipe_texture *tex; + struct pipe_resource template; + struct pipe_resource *tex; assert(vctx); @@ -113,22 +113,24 @@ CreateOrResizeBackBuffer(struct vl_context *vctx, unsigned int width, unsigned i return true; } - memset(&template, 0, sizeof(struct pipe_texture)); + memset(&template, 0, sizeof(struct pipe_resource)); template.target = PIPE_TEXTURE_2D; template.format = vctx->vscreen->format; template.last_level = 0; template.width0 = width; template.height0 = height; template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.usage = PIPE_USAGE_DEFAULT; + template.bind = PIPE_BIND_RENDER_TARGET; + template.flags = 0; - tex = vpipe->screen->texture_create(vpipe->screen, &template); + tex = vpipe->screen->resource_create(vpipe->screen, &template); if (!tex) return false; *backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ_WRITE); - pipe_texture_reference(&tex, NULL); + PIPE_BIND_RENDER_TARGET | PIPE_BIND_BLIT_SOURCE); + pipe_resource_reference(&tex, NULL); if (!*backbuffer) return false; @@ -190,8 +192,8 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac XvMCContextPrivate *context_priv; struct pipe_video_context *vpipe; XvMCSurfacePrivate *surface_priv; - struct pipe_texture template; - struct pipe_texture *vsfc_tex; + struct pipe_resource template; + struct pipe_resource *vsfc_tex; struct pipe_surface *vsfc; XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); @@ -210,36 +212,36 @@ Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surfac if (!surface_priv) return BadAlloc; - memset(&template, 0, sizeof(struct pipe_texture)); + memset(&template, 0, sizeof(struct pipe_resource)); template.target = PIPE_TEXTURE_2D; template.format = (enum pipe_format)vpipe->get_param(vpipe, PIPE_CAP_DECODE_TARGET_PREFERRED_FORMAT); template.last_level = 0; if (vpipe->is_format_supported(vpipe, template.format, - PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_RENDER_TARGET, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO)) { template.width0 = context->width; template.height0 = context->height; } else { assert(vpipe->is_format_supported(vpipe, template.format, - PIPE_TEXTURE_USAGE_SAMPLER | - PIPE_TEXTURE_USAGE_RENDER_TARGET, + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET, PIPE_TEXTURE_GEOM_NON_SQUARE)); template.width0 = util_next_power_of_two(context->width); template.height0 = util_next_power_of_two(context->height); } template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET; - vsfc_tex = vpipe->screen->texture_create(vpipe->screen, &template); + template.usage = PIPE_USAGE_DEFAULT; + template.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + template.flags = 0; + vsfc_tex = vpipe->screen->resource_create(vpipe->screen, &template); if (!vsfc_tex) { FREE(surface_priv); return BadAlloc; } vsfc = vpipe->screen->get_tex_surface(vpipe->screen, vsfc_tex, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ_WRITE); - pipe_texture_reference(&vsfc_tex, NULL); + PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET); + pipe_resource_reference(&vsfc_tex, NULL); if (!vsfc) { FREE(surface_priv); return BadAlloc; diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c deleted file mode 100644 index 994e3ca4d14..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include <assert.h> -#include <error.h> -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int min_required_blocks = 1, min_required_macroblocks = 1; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray blocks = {0}; - XvMCMacroBlockArray macroblocks = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - error(1, 0, "Error, unable to find a good port.\n"); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - - /* Test NULL context */ - assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); - /* Test 0 blocks */ - assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); - /* Test valid params */ - assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); - /* Test context id assigned and correct */ - assert(blocks.context_id == context.context_id); - /* Test number of blocks assigned and correct */ - assert(blocks.num_blocks == min_required_blocks); - /* Test block pointer valid */ - assert(blocks.blocks != NULL); - /* Test NULL context */ - assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); - /* Test 0 macroblocks */ - assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); - /* Test valid params */ - assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); - /* Test context id assigned and correct */ - assert(macroblocks.context_id == context.context_id); - /* Test macroblock pointer valid */ - assert(macroblocks.macro_blocks != NULL); - /* Test valid params */ - assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); - /* Test valid params */ - assert(XvMCDestroyBlocks(display, &blocks) == Success); - - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c deleted file mode 100644 index 3da957c9330..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c +++ /dev/null @@ -1,119 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include <assert.h> -#include <error.h> -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - error(1, 0, "Error, unable to find a good port.\n"); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - /* Test NULL context */ - /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); - /* Test invalid port */ - /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */ - assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); - /* Test invalid surface */ - assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch); - /* Test invalid flags */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); - /* Test huge width */ - assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); - /* Test huge height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); - /* Test huge width & height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); - /* Test valid params */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - /* Test context id assigned */ - assert(context.context_id != 0); - /* Test surface type id assigned and correct */ - assert(context.surface_type_id == surface_type_id); - /* Test width & height assigned and correct */ - assert(context.width == width && context.height == height); - /* Test port assigned and correct */ - assert(context.port == port_num); - /* Test flags assigned and correct */ - assert(context.flags == XVMC_DIRECT); - /* Test NULL context */ - assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); - /* Test valid params */ - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid width */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); - assert(context.width >= width + 1); - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); - assert(context.height >= height + 1); - assert(XvMCDestroyContext(display, &context) == Success); - /* Test awkward but valid width & height */ - assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); - assert(context.width >= width + 1 && context.height >= height + 1); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c deleted file mode 100644 index 6058783a798..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c +++ /dev/null @@ -1,317 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <error.h> -#include "testlib.h" - -#define BLOCK_WIDTH 8 -#define BLOCK_HEIGHT 8 -#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) -#define MACROBLOCK_WIDTH 16 -#define MACROBLOCK_HEIGHT 16 -#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) -#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) -#define BLOCKS_PER_MACROBLOCK 6 - -#define INPUT_WIDTH 16 -#define INPUT_HEIGHT 16 -#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) -#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) -#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) - -#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH -#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT -#define DEFAULT_ACCEPTABLE_ERR 0.01 - -void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt); -void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal); - -void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt) -{ - int fail = 0; - int i; - - *output_width = DEFAULT_OUTPUT_WIDTH; - *output_height = DEFAULT_OUTPUT_WIDTH; - *acceptable_error = DEFAULT_ACCEPTABLE_ERR; - *prompt = 1; - - for (i = 1; i < argc && !fail; ++i) - { - if (!strcmp(argv[i], "-w")) - { - if (sscanf(argv[++i], "%u", output_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-h")) - { - if (sscanf(argv[++i], "%u", output_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-e")) - { - if (sscanf(argv[++i], "%lf", acceptable_error) != 1) - fail = 1; - } - else if (strcmp(argv[i], "-n")) - *prompt = 0; - else - fail = 1; - } - - if (fail) - error - ( - 1, 0, - "Bad argument.\n" - "\n" - "Usage: %s [options]\n" - "\t-w <width>\tOutput width\n" - "\t-h <height>\tOutput height\n" - "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n" - "\t-n\tDon't prompt for quit\n", - argv[0] - ); -} - -void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal) -{ - unsigned int x, y; - unsigned int range = stop - start; - - if (horizontal) - { - for (y = 0; y < BLOCK_HEIGHT; ++y) - for (x = 0; x < BLOCK_WIDTH; ++x) - block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); - } - else - { - for (y = 0; y < BLOCK_HEIGHT; ++y) - for (x = 0; x < BLOCK_WIDTH; ++x) - block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1))); - } -} - -int main(int argc, char **argv) -{ - unsigned int output_width; - unsigned int output_height; - double acceptable_error; - int prompt; - Display *display; - Window root, window; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray block_array; - XvMCMacroBlockArray mb_array; - int mbx, mby, bx, by; - XvMCMacroBlock *mb; - short *blocks; - int quit = 0; - - ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - INPUT_WIDTH, - INPUT_HEIGHT, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - error(1, 0, "Error, unable to find a good port.\n"); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - root = XDefaultRootWindow(display); - window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); - - assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); - assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); - - mb = mb_array.macro_blocks; - blocks = block_array.blocks; - - for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) - for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) - { - mb->x = mbx; - mb->y = mby; - mb->macroblock_type = XVMC_MB_TYPE_INTRA; - /*mb->motion_type = ;*/ - /*mb->motion_vertical_field_select = ;*/ - mb->dct_type = XVMC_DCT_TYPE_FRAME; - /*mb->PMV[0][0][0] = ; - mb->PMV[0][0][1] = ; - mb->PMV[0][1][0] = ; - mb->PMV[0][1][1] = ; - mb->PMV[1][0][0] = ; - mb->PMV[1][0][1] = ; - mb->PMV[1][1][0] = ; - mb->PMV[1][1][1] = ;*/ - mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; - mb->coded_block_pattern = 0x3F; - - mb++; - - for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) - for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) - { - const int start = 16, stop = 235, range = stop - start; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1 - ); - - blocks += BLOCK_SIZE; - } - - for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) - for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) - { - const int start = 16, stop = 240, range = stop - start; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1 - ); - - blocks += BLOCK_SIZE; - - Gradient - ( - blocks, - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), - (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), - 1 - ); - - blocks += BLOCK_SIZE; - } - } - - XSelectInput(display, window, ExposureMask | KeyPressMask); - XMapWindow(display, window); - XSync(display, 0); - - /* Test NULL context */ - assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); - /* Test NULL surface */ - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); - /* Test bad picture structure */ - assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); - /* Test valid params */ - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); - - /* Test NULL surface */ - assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); - /* Test bad window */ - /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ - /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ - - if (prompt) - { - puts("Press any button to quit..."); - - while (!quit) - { - if (XPending(display) > 0) - { - XEvent event; - - XNextEvent(display, &event); - - switch (event.type) - { - case Expose: - { - /* Test valid params */ - assert - ( - XvMCPutSurface - ( - display, &surface, window, - 0, 0, INPUT_WIDTH, INPUT_HEIGHT, - 0, 0, output_width, output_height, - XVMC_FRAME_PICTURE - ) == Success - ); - break; - } - case KeyPress: - { - quit = 1; - break; - } - } - } - } - } - - assert(XvMCDestroyBlocks(display, &block_array) == Success); - assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XDestroyWindow(display, window); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c deleted file mode 100644 index b65eb265c0a..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c +++ /dev/null @@ -1,98 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include <assert.h> -#include <error.h> -#include "testlib.h" - -int main(int argc, char **argv) -{ - const unsigned int width = 16, height = 16; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - - Display *display; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface = {0}; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - width, - height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - error(1, 0, "Error, unable to find a good port.\n"); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); - - /* Test NULL context */ - assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext); - /* Test NULL surface */ - assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); - /* Test valid params */ - assert(XvMCCreateSurface(display, &context, &surface) == Success); - /* Test surface id assigned */ - assert(surface.surface_id != 0); - /* Test context id assigned and correct */ - assert(surface.context_id == context.context_id); - /* Test surface type id assigned and correct */ - assert(surface.surface_type_id == surface_type_id); - /* Test width & height assigned and correct */ - assert(surface.width == width && surface.height == height); - /* Test valid params */ - assert(XvMCDestroySurface(display, &surface) == Success); - /* Test NULL surface */ - assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface); - - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XCloseDisplay(display); - - return 0; -} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c deleted file mode 100644 index 142c09bb590..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c +++ /dev/null @@ -1,146 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include "testlib.h" -#include <stdio.h> - -/* -void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) -{ - fputs(doc_string, stderr); - if (!pred) - fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); - else - fputs(" PASS!\n", stderr); -} -*/ - -int GetPort -( - Display *display, - unsigned int width, - unsigned int height, - unsigned int chroma_format, - const unsigned int *mc_types, - unsigned int num_mc_types, - XvPortID *port_id, - int *surface_type_id, - unsigned int *is_overlay, - unsigned int *intra_unsigned -) -{ - unsigned int found_port = 0; - XvAdaptorInfo *adaptor_info; - unsigned int num_adaptors; - int num_types; - int ev_base, err_base; - unsigned int i, j, k, l; - - if (!XvMCQueryExtension(display, &ev_base, &err_base)) - return 0; - if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) - return 0; - - for (i = 0; i < num_adaptors && !found_port; ++i) - { - if (adaptor_info[i].type & XvImageMask) - { - XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); - - if (surface_info) - { - for (j = 0; j < num_types && !found_port; ++j) - { - if - ( - surface_info[j].chroma_format == chroma_format && - surface_info[j].max_width >= width && - surface_info[j].max_height >= height - ) - { - for (k = 0; k < num_mc_types && !found_port; ++k) - { - if (surface_info[j].mc_type == mc_types[k]) - { - for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) - { - if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) - { - *port_id = adaptor_info[i].base_id + l; - *surface_type_id = surface_info[j].surface_type_id; - *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; - *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; - found_port = 1; - } - } - } - } - } - } - - XFree(surface_info); - } - } - } - - XvFreeAdaptorInfo(adaptor_info); - - return found_port; -} - -unsigned int align(unsigned int value, unsigned int alignment) -{ - return (value + alignment - 1) & ~(alignment - 1); -} - -/* From the glibc manual */ -int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) -{ - /* Perform the carry for the later subtraction by updating y. */ - if (x->tv_usec < y->tv_usec) - { - int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; - y->tv_usec -= 1000000 * nsec; - y->tv_sec += nsec; - } - if (x->tv_usec - y->tv_usec > 1000000) - { - int nsec = (x->tv_usec - y->tv_usec) / 1000000; - y->tv_usec += 1000000 * nsec; - y->tv_sec -= nsec; - } - - /* - * Compute the time remaining to wait. - * tv_usec is certainly positive. - */ - result->tv_sec = x->tv_sec - y->tv_sec; - result->tv_usec = x->tv_usec - y->tv_usec; - - /* Return 1 if result is negative. */ - return x->tv_sec < y->tv_sec; -} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h deleted file mode 100644 index 0438e52928b..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h +++ /dev/null @@ -1,69 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#ifndef testlib_h -#define testlib_h - -/* -#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__) - -void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); -*/ - -#include <sys/time.h> -#include <X11/Xlib.h> -#include <X11/extensions/XvMClib.h> - -/* - * display: IN A valid X display - * width, height: IN Surface size that the port must display - * chroma_format: IN Chroma format that the port must display - * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned - * port_id: OUT Your port's ID - * surface_type_id: OUT Your port's surface ID - * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey - * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks - */ -int GetPort -( - Display *display, - unsigned int width, - unsigned int height, - unsigned int chroma_format, - const unsigned int *mc_types, - unsigned int num_mc_types, - XvPortID *port_id, - int *surface_type_id, - unsigned int *is_overlay, - unsigned int *intra_unsigned -); - -unsigned int align(unsigned int value, unsigned int alignment); - -int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); - -#endif diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c deleted file mode 100644 index bf94d856234..00000000000 --- a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c +++ /dev/null @@ -1,300 +0,0 @@ -/************************************************************************** - * - * Copyright 2009 Younes Manton. - * 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 above copyright notice and this permission notice (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS 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. - * - **************************************************************************/ - -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <error.h> -#include <sys/time.h> -#include "testlib.h" - -#define MACROBLOCK_WIDTH 16 -#define MACROBLOCK_HEIGHT 16 -#define BLOCKS_PER_MACROBLOCK 6 - -#define DEFAULT_INPUT_WIDTH 720 -#define DEFAULT_INPUT_HEIGHT 480 -#define DEFAULT_REPS 100 - -#define PIPELINE_STEP_MC 1 -#define PIPELINE_STEP_CSC 2 -#define PIPELINE_STEP_SWAP 4 - -#define MB_TYPE_I 1 -#define MB_TYPE_P 2 -#define MB_TYPE_B 4 - -struct Config -{ - unsigned int input_width; - unsigned int input_height; - unsigned int output_width; - unsigned int output_height; - unsigned int pipeline; - unsigned int mb_types; - unsigned int reps; -}; - -void ParseArgs(int argc, char **argv, struct Config *config); - -void ParseArgs(int argc, char **argv, struct Config *config) -{ - int fail = 0; - int i; - - config->input_width = DEFAULT_INPUT_WIDTH; - config->input_height = DEFAULT_INPUT_HEIGHT; - config->output_width = 0; - config->output_height = 0; - config->pipeline = 0; - config->mb_types = 0; - config->reps = DEFAULT_REPS; - - for (i = 1; i < argc && !fail; ++i) - { - if (!strcmp(argv[i], "-iw")) - { - if (sscanf(argv[++i], "%u", &config->input_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-ih")) - { - if (sscanf(argv[++i], "%u", &config->input_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-ow")) - { - if (sscanf(argv[++i], "%u", &config->output_width) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-oh")) - { - if (sscanf(argv[++i], "%u", &config->output_height) != 1) - fail = 1; - } - else if (!strcmp(argv[i], "-p")) - { - char *token = strtok(argv[++i], ","); - - while (token && !fail) - { - if (!strcmp(token, "mc")) - config->pipeline |= PIPELINE_STEP_MC; - else if (!strcmp(token, "csc")) - config->pipeline |= PIPELINE_STEP_CSC; - else if (!strcmp(token, "swp")) - config->pipeline |= PIPELINE_STEP_SWAP; - else - fail = 1; - - if (!fail) - token = strtok(NULL, ","); - } - } - else if (!strcmp(argv[i], "-mb")) - { - char *token = strtok(argv[++i], ","); - - while (token && !fail) - { - if (strcmp(token, "i")) - config->mb_types |= MB_TYPE_I; - else if (strcmp(token, "p")) - config->mb_types |= MB_TYPE_P; - else if (strcmp(token, "b")) - config->mb_types |= MB_TYPE_B; - else - fail = 1; - - if (!fail) - token = strtok(NULL, ","); - } - } - else if (!strcmp(argv[i], "-r")) - { - if (sscanf(argv[++i], "%u", &config->reps) != 1) - fail = 1; - } - else - fail = 1; - } - - if (fail) - error - ( - 1, 0, - "Bad argument.\n" - "\n" - "Usage: %s [options]\n" - "\t-iw <width>\tInput width\n" - "\t-ih <height>\tInput height\n" - "\t-ow <width>\tOutput width\n" - "\t-oh <height>\tOutput height\n" - "\t-p <pipeline>\tPipeline to test\n" - "\t-mb <mb type>\tMacroBlock types to use\n" - "\t-r <reps>\tRepetitions\n\n" - "\tPipeline steps: mc,csc,swap\n" - "\tMB types: i,p,b\n", - argv[0] - ); - - if (config->output_width == 0) - config->output_width = config->input_width; - if (config->output_height == 0) - config->output_height = config->input_height; - if (!config->pipeline) - config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP; - if (!config->mb_types) - config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B; -} - -int main(int argc, char **argv) -{ - struct Config config; - Display *display; - Window root, window; - const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; - XvPortID port_num; - int surface_type_id; - unsigned int is_overlay, intra_unsigned; - int colorkey; - XvMCContext context; - XvMCSurface surface; - XvMCBlockArray block_array; - XvMCMacroBlockArray mb_array; - unsigned int mbw, mbh; - unsigned int mbx, mby; - unsigned int reps; - struct timeval start, stop, diff; - double diff_secs; - - ParseArgs(argc, argv, &config); - - mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; - mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; - - display = XOpenDisplay(NULL); - - if (!GetPort - ( - display, - config.input_width, - config.input_height, - XVMC_CHROMA_FORMAT_420, - mc_types, - 2, - &port_num, - &surface_type_id, - &is_overlay, - &intra_unsigned - )) - { - XCloseDisplay(display); - error(1, 0, "Error, unable to find a good port.\n"); - } - - if (is_overlay) - { - Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0); - XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey); - } - - root = XDefaultRootWindow(display); - window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey); - - assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success); - assert(XvMCCreateSurface(display, &context, &surface) == Success); - assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success); - assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success); - - for (mby = 0; mby < mbh; ++mby) - for (mbx = 0; mbx < mbw; ++mbx) - { - mb_array.macro_blocks[mby * mbw + mbx].x = mbx; - mb_array.macro_blocks[mby * mbw + mbx].y = mby; - mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA; - /*mb->motion_type = ;*/ - /*mb->motion_vertical_field_select = ;*/ - mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME; - /*mb->PMV[0][0][0] = ; - mb->PMV[0][0][1] = ; - mb->PMV[0][1][0] = ; - mb->PMV[0][1][1] = ; - mb->PMV[1][0][0] = ; - mb->PMV[1][0][1] = ; - mb->PMV[1][1][0] = ; - mb->PMV[1][1][1] = ;*/ - mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK; - mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F; - } - - XSelectInput(display, window, ExposureMask | KeyPressMask); - XMapWindow(display, window); - XSync(display, 0); - - gettimeofday(&start, NULL); - - for (reps = 0; reps < config.reps; ++reps) - { - if (config.pipeline & PIPELINE_STEP_MC) - { - assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success); - assert(XvMCFlushSurface(display, &surface) == Success); - } - if (config.pipeline & PIPELINE_STEP_CSC) - assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success); - } - - gettimeofday(&stop, NULL); - - timeval_subtract(&diff, &stop, &start); - diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0; - - printf("XvMC Benchmark\n"); - printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height); - printf("Pipeline: "); - if (config.pipeline & PIPELINE_STEP_MC) - printf("|mc|"); - if (config.pipeline & PIPELINE_STEP_CSC) - printf("|csc|"); - if (config.pipeline & PIPELINE_STEP_SWAP) - printf("|swap|"); - printf("\n"); - printf("Reps: %u\n", config.reps); - printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs); - - assert(XvMCDestroyBlocks(display, &block_array) == Success); - assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); - assert(XvMCDestroySurface(display, &surface) == Success); - assert(XvMCDestroyContext(display, &context) == Success); - - XvUngrabPort(display, port_num, CurrentTime); - XDestroyWindow(display, window); - XCloseDisplay(display); - - return 0; -} |