diff options
Diffstat (limited to 'src/gallium/state_trackers/dri/drm')
-rw-r--r-- | src/gallium/state_trackers/dri/drm/Makefile | 33 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/drm/SConscript | 28 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/drm/dri1.c | 526 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/drm/dri1.h | 59 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri1_helper.c | 1 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/drm/dri2.c | 413 | ||||
-rw-r--r-- | src/gallium/state_trackers/dri/drm/dri2.h | 46 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri_context.c | 1 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri_drawable.c | 1 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri_extensions.c | 1 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri_screen.c | 1 | ||||
l--------- | src/gallium/state_trackers/dri/drm/dri_st_api.c | 1 |
12 files changed, 1111 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/dri/drm/Makefile b/src/gallium/state_trackers/dri/drm/Makefile new file mode 100644 index 0000000000..c43bfee8b8 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/Makefile @@ -0,0 +1,33 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = dridrm + +LIBRARY_INCLUDES = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/gallium/state_trackers/dri \ + -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 \ + dri_st_api.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 0000000000..a9c359c2e8 --- /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.Append(CPPPATH = [ + '#/src/mesa', + '#/src/gallium/state_trackers/dri', + '#/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', + 'dri_st_api.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 0000000000..98bdb2936a --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri1.c @@ -0,0 +1,526 @@ +/************************************************************************** + * + * 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 <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ + +/* 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 "dri_st_api.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 = dri_drawable(dPriv); + struct dri_drawable *read = dri_drawable(rPriv); + boolean flushed = FALSE; + + 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->stfb); + } + + 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->stfb); + } +} + +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_texture *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_texture *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. + */ + +void +dri1_flush_frontbuffer(struct dri_drawable *draw, + enum st_attachment_type statt) +{ + struct dri_context *ctx = dri_get_current(); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_fence_handle *dummy_fence; + struct pipe_texture *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_context *ctx = dri_get_current(); + struct dri_drawable *draw = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(draw->sPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_fence_handle *fence; + struct pipe_texture *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(); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct drm_clip_rect sub_bbox; + struct dri_drawable *draw = dri_drawable(dPriv); + struct pipe_fence_handle *dummy_fence; + struct pipe_texture *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. + */ +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned mask) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_texture 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_texture_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 tex_usage; + + /* the texture already exists or not requested */ + if (drawable->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 = drawable->stvis.color_format; + tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET | + PIPE_TEXTURE_USAGE_RENDER_TARGET; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + if (format != PIPE_FORMAT_NONE) { + templ.format = format; + templ.tex_usage = tex_usage; + + drawable->textures[i] = + screen->pipe_screen->texture_create(screen->pipe_screen, &templ); + } + } + + drawable->old_w = width; + drawable->old_h = height; +} + +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 +}; + +/* + * Backend function for init_screen. + */ + +static const __DRIextension *dri1_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + +struct dri1_api *__dri1_api_hooks = NULL; + +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; +} + +const __DRIconfig ** +dri1_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 = 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; + + 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; + + 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; +} diff --git a/src/gallium/state_trackers/dri/drm/dri1.h b/src/gallium/state_trackers/dri/drm/dri1.h new file mode 100644 index 0000000000..f7441f98ab --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri1.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * 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 <keithw@vmware.com> + * Author: Jakob Bornecrantz <wallbraker@gmail.com> + */ + +#ifndef DRI1_H +#define DRI1_H + +#include "dri_context.h" +#include "dri_drawable.h" + +#include "state_tracker/st_api.h" +#include "dri_wrapper.h" + +extern struct dri1_api *__dri1_api_hooks; + +const __DRIconfig ** +dri1_init_screen(__DRIscreen * sPriv); + +void +dri1_flush_frontbuffer(struct dri_drawable *drawable, + enum st_attachment_type statt); + +void +dri1_allocate_textures(struct dri_drawable *drawable, + unsigned mask); + +void dri1_swap_buffers(__DRIdrawable * dPriv); + +void +dri1_copy_sub_buffer(__DRIdrawable * dPriv, int x, int y, int w, int h); + +#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 0000000000..7006a8d882 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri1_helper.c @@ -0,0 +1 @@ +../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 0000000000..108b18e9d3 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri2.c @@ -0,0 +1,413 @@ +/* + * 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 <keithw@vmware.com> + * Jakob Bornecrantz <wallbraker@gmail.com> + * Chia-I Wu <olv@lunarg.com> + */ + +#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 "dri_st_api.h" +#include "dri2.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->stfb); +} + +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_texture *pt; + + dri_st_framebuffer_validate_att(drawable->stfb, ST_ATTACHMENT_FRONT_LEFT); + + pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + + if (pt) { + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, drawable->stvis.color_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 of an attachment. + */ +static INLINE enum pipe_format +dri2_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum pipe_format format; + + 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; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + format = drawable->stvis.depth_stencil_format; + break; + default: + format = PIPE_FORMAT_NONE; + break; + } + + return format; +} + +/** + * 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; + int att, bpp; + + format = dri2_drawable_get_format(drawable, statts[i]); + 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_textures. + */ +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_texture templ; + struct winsys_handle whandle; + boolean have_depth = FALSE; + unsigned i; + + 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_texture_reference(&drawable->textures[i], NULL); + + memset(&templ, 0, sizeof(templ)); + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + 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; + } + + format = dri2_drawable_get_format(drawable, statt); + if (statt == ST_ATTACHMENT_INVALID || format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + + drawable->textures[statt] = + screen->pipe_screen->texture_from_handle(screen->pipe_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. + */ + +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); +} + +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); + } +} + +/* + * Backend function init_screen. + */ + +static const __DRIextension *dri_screen_extensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + &dri2TexBufferExtension.base, + &dri2FlushExtension.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) +{ + struct dri_screen *screen; + struct drm_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; + 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; + } + + screen->smapi = dri_create_st_manager(screen); + if (!screen->smapi) + goto fail; + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, __driNConfigOptions); + + screen->auto_fake_front = dri_with_format(sPriv); + + return dri_fill_in_modes(screen, 32); +fail: + dri_destroy_screen(sPriv); + return NULL; +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drm/dri2.h b/src/gallium/state_trackers/dri/drm/dri2.h new file mode 100644 index 0000000000..379963431f --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri2.h @@ -0,0 +1,46 @@ +/************************************************************************** + * + * 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 DRI2_H +#define DRI2_H + +#include "dri_drawable.h" +#include "dri_wrapper.h" + +const __DRIconfig ** +dri2_init_screen(__DRIscreen * sPriv); + +void +dri2_flush_frontbuffer(struct dri_drawable *drawable, + enum st_attachment_type statt); + +void +dri2_allocate_textures(struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count); + +#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 0000000000..989ef4438a --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_context.c @@ -0,0 +1 @@ +../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 0000000000..422c4c1d74 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_drawable.c @@ -0,0 +1 @@ +../dri_drawable.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_extensions.c b/src/gallium/state_trackers/dri/drm/dri_extensions.c new file mode 120000 index 0000000000..b793f06747 --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_extensions.c @@ -0,0 +1 @@ +../dri_extensions.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 0000000000..938f4c3bdc --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_screen.c @@ -0,0 +1 @@ +../dri_screen.c
\ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_st_api.c b/src/gallium/state_trackers/dri/drm/dri_st_api.c new file mode 120000 index 0000000000..9ae88230dd --- /dev/null +++ b/src/gallium/state_trackers/dri/drm/dri_st_api.c @@ -0,0 +1 @@ +../dri_st_api.c
\ No newline at end of file |