diff options
Diffstat (limited to 'src/mesa/drivers/dri')
20 files changed, 3886 insertions, 93 deletions
diff --git a/src/mesa/drivers/dri/Makefile.template b/src/mesa/drivers/dri/Makefile.template index 2dc3664cc6..2fa36bab3f 100644 --- a/src/mesa/drivers/dri/Makefile.template +++ b/src/mesa/drivers/dri/Makefile.template @@ -2,13 +2,16 @@ MESA_MODULES = $(TOP)/src/mesa/libmesa.a -COMMON_SOURCES = \ +COMMON_GALLIUM_SOURCES = \ ../common/utils.c \ - ../common/texmem.c \ ../common/vblank.c \ ../common/dri_util.c \ - ../common/xmlconfig.c \ - ../common/drirenderbuffer.c + ../common/xmlconfig.c + +COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \ + ../../common/driverfuncs.c \ + ../common/texmem.c \ + ../common/drirenderbuffer.c ifeq ($(WINDOW_SYSTEM),dri) WINOBJ= @@ -59,9 +62,9 @@ SHARED_INCLUDES = \ default: symlinks depend $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME) -$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template +$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template $(MKLIB) -o $@ -noprefix -linker '$(CC)' -ldflags '$(LDFLAGS)' \ - $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) + $(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS) $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME) @@ -69,6 +72,7 @@ $(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME) depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS) + rm -f depend touch depend $(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \ $(ASM_SOURCES) diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.c b/src/mesa/drivers/dri/common/dri_bufmgr.c new file mode 100644 index 0000000000..5747307f3b --- /dev/null +++ b/src/mesa/drivers/dri/common/dri_bufmgr.c @@ -0,0 +1,535 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Keith Whitwell <keithw-at-tungstengraphics-dot-com> + */ + +#include <xf86drm.h> +#include <stdlib.h> +#include "glthread.h" +#include "errno.h" +#include "dri_bufmgr.h" +#include "string.h" +#include "imports.h" +#include "dri_bufpool.h" + +_glthread_DECLARE_STATIC_MUTEX(bmMutex); + +/* + * TODO: Introduce fence pools in the same way as + * buffer object pools. + */ + + + +typedef struct _DriFenceObject +{ + int fd; + _glthread_Mutex mutex; + int refCount; + const char *name; + drmFence fence; +} DriFenceObject; + +typedef struct _DriBufferObject +{ + DriBufferPool *pool; + _glthread_Mutex mutex; + int refCount; + const char *name; + unsigned flags; + unsigned hint; + unsigned alignment; + void *private; + /* user-space buffer: */ + unsigned userBuffer; + void *userData; + unsigned userSize; +} DriBufferObject; + + +void +bmError(int val, const char *file, const char *function, int line) +{ + _mesa_printf("Fatal video memory manager error \"%s\".\n" + "Check kernel logs or set the LIBGL_DEBUG\n" + "environment variable to \"verbose\" for more info.\n" + "Detected in file %s, line %d, function %s.\n", + strerror(-val), file, line, function); +#ifndef NDEBUG + abort(); +#else + abort(); +#endif +} + +DriFenceObject * +driFenceBuffers(int fd, char *name, unsigned flags) +{ + DriFenceObject *fence = (DriFenceObject *) malloc(sizeof(*fence)); + int ret; + + if (!fence) + BM_CKFATAL(-EINVAL); + + _glthread_LOCK_MUTEX(bmMutex); + fence->refCount = 1; + fence->name = name; + fence->fd = fd; + _glthread_INIT_MUTEX(fence->mutex); + ret = drmFenceBuffers(fd, flags, &fence->fence); + _glthread_UNLOCK_MUTEX(bmMutex); + if (ret) { + free(fence); + BM_CKFATAL(ret); + } + return fence; +} + + +unsigned +driFenceType(DriFenceObject * fence) +{ + unsigned ret; + + _glthread_LOCK_MUTEX(bmMutex); + ret = fence->fence.flags; + _glthread_UNLOCK_MUTEX(bmMutex); + + return ret; +} + + +DriFenceObject * +driFenceReference(DriFenceObject * fence) +{ + _glthread_LOCK_MUTEX(bmMutex); + ++fence->refCount; + _glthread_UNLOCK_MUTEX(bmMutex); + return fence; +} + +void +driFenceUnReference(DriFenceObject * fence) +{ + if (!fence) + return; + + _glthread_LOCK_MUTEX(bmMutex); + if (--fence->refCount == 0) { + drmFenceDestroy(fence->fd, &fence->fence); + free(fence); + } + _glthread_UNLOCK_MUTEX(bmMutex); +} + +void +driFenceFinish(DriFenceObject * fence, unsigned type, int lazy) +{ + int ret; + unsigned flags = (lazy) ? DRM_FENCE_FLAG_WAIT_LAZY : 0; + + _glthread_LOCK_MUTEX(fence->mutex); + ret = drmFenceWait(fence->fd, flags, &fence->fence, type); + _glthread_UNLOCK_MUTEX(fence->mutex); + BM_CKFATAL(ret); +} + +int +driFenceSignaled(DriFenceObject * fence, unsigned type) +{ + int signaled; + int ret; + + if (fence == NULL) + return GL_TRUE; + + _glthread_LOCK_MUTEX(fence->mutex); + ret = drmFenceSignaled(fence->fd, &fence->fence, type, &signaled); + _glthread_UNLOCK_MUTEX(fence->mutex); + BM_CKFATAL(ret); + return signaled; +} + + +extern drmBO * +driBOKernel(struct _DriBufferObject *buf) +{ + drmBO *ret; + + assert(buf->private != NULL); + ret = buf->pool->kernel(buf->pool, buf->private); + if (!ret) + BM_CKFATAL(-EINVAL); + + return ret; +} + +void +driBOWaitIdle(struct _DriBufferObject *buf, int lazy) +{ + struct _DriBufferPool *pool; + void *priv; + + _glthread_LOCK_MUTEX(buf->mutex); + pool = buf->pool; + priv = buf->private; + _glthread_UNLOCK_MUTEX(buf->mutex); + + assert(priv != NULL); + BM_CKFATAL(buf->pool->waitIdle(pool, priv, lazy)); +} + +void * +driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint) +{ + if (buf->userBuffer) { + return buf->userData; + } + else { + void *virtual; + + assert(buf->private != NULL); + + _glthread_LOCK_MUTEX(buf->mutex); + BM_CKFATAL(buf->pool->map(buf->pool, buf->private, flags, hint, &virtual)); + _glthread_UNLOCK_MUTEX(buf->mutex); + return virtual; + } +} + +void +driBOUnmap(struct _DriBufferObject *buf) +{ + if (!buf->userBuffer) { + assert(buf->private != NULL); + + buf->pool->unmap(buf->pool, buf->private); + } +} + +unsigned long +driBOOffset(struct _DriBufferObject *buf) +{ + unsigned long ret; + + assert(buf->private != NULL); + + _glthread_LOCK_MUTEX(buf->mutex); + ret = buf->pool->offset(buf->pool, buf->private); + _glthread_UNLOCK_MUTEX(buf->mutex); + return ret; +} + +unsigned +driBOFlags(struct _DriBufferObject *buf) +{ + unsigned ret; + + assert(buf->private != NULL); + + _glthread_LOCK_MUTEX(buf->mutex); + ret = buf->pool->flags(buf->pool, buf->private); + _glthread_UNLOCK_MUTEX(buf->mutex); + return ret; +} + +struct _DriBufferObject * +driBOReference(struct _DriBufferObject *buf) +{ + _glthread_LOCK_MUTEX(bmMutex); + if (++buf->refCount == 1) { + BM_CKFATAL(-EINVAL); + } + _glthread_UNLOCK_MUTEX(bmMutex); + return buf; +} + +void +driBOUnReference(struct _DriBufferObject *buf) +{ + int tmp; + + if (!buf) + return; + + _glthread_LOCK_MUTEX(bmMutex); + tmp = --buf->refCount; + _glthread_UNLOCK_MUTEX(bmMutex); + if (!tmp) { + if (buf->private) + buf->pool->destroy(buf->pool, buf->private); + free(buf); + } +} + +void +driBOData(struct _DriBufferObject *buf, + unsigned size, const void *data, unsigned flags) +{ + void *virtual; + int newBuffer; + struct _DriBufferPool *pool; + + assert(!buf->userBuffer); /* XXX just do a memcpy? */ + + _glthread_LOCK_MUTEX(buf->mutex); + pool = buf->pool; + if (!pool->create) { + _mesa_error(NULL, GL_INVALID_OPERATION, + "driBOData called on invalid buffer\n"); + BM_CKFATAL(-EINVAL); + } + newBuffer = !buf->private || (pool->size(pool, buf->private) < size) || + pool->map(pool, buf->private, DRM_BO_FLAG_WRITE, + DRM_BO_HINT_DONT_BLOCK, &virtual); + + if (newBuffer) { + if (buf->private) + pool->destroy(pool, buf->private); + if (!flags) + flags = buf->flags; + buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE, + buf->alignment); + if (!buf->private) + BM_CKFATAL(-ENOMEM); + BM_CKFATAL(pool->map(pool, buf->private, + DRM_BO_FLAG_WRITE, + DRM_BO_HINT_DONT_BLOCK, &virtual)); + } + + if (data != NULL) + memcpy(virtual, data, size); + + BM_CKFATAL(pool->unmap(pool, buf->private)); + _glthread_UNLOCK_MUTEX(buf->mutex); +} + +void +driBOSubData(struct _DriBufferObject *buf, + unsigned long offset, unsigned long size, const void *data) +{ + void *virtual; + + assert(!buf->userBuffer); /* XXX just do a memcpy? */ + + _glthread_LOCK_MUTEX(buf->mutex); + if (size && data) { + BM_CKFATAL(buf->pool->map(buf->pool, buf->private, + DRM_BO_FLAG_WRITE, 0, &virtual)); + memcpy((unsigned char *) virtual + offset, data, size); + BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); + } + _glthread_UNLOCK_MUTEX(buf->mutex); +} + +void +driBOGetSubData(struct _DriBufferObject *buf, + unsigned long offset, unsigned long size, void *data) +{ + void *virtual; + + assert(!buf->userBuffer); /* XXX just do a memcpy? */ + + _glthread_LOCK_MUTEX(buf->mutex); + if (size && data) { + BM_CKFATAL(buf->pool->map(buf->pool, buf->private, + DRM_BO_FLAG_READ, 0, &virtual)); + memcpy(data, (unsigned char *) virtual + offset, size); + BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private)); + } + _glthread_UNLOCK_MUTEX(buf->mutex); +} + +void +driBOSetStatic(struct _DriBufferObject *buf, + unsigned long offset, + unsigned long size, void *virtual, unsigned flags) +{ + assert(!buf->userBuffer); /* XXX what to do? */ + + _glthread_LOCK_MUTEX(buf->mutex); + if (buf->private != NULL) { + _mesa_error(NULL, GL_INVALID_OPERATION, + "Invalid buffer for setStatic\n"); + BM_CKFATAL(-EINVAL); + } + if (buf->pool->setstatic == NULL) { + _mesa_error(NULL, GL_INVALID_OPERATION, + "Invalid buffer pool for setStatic\n"); + BM_CKFATAL(-EINVAL); + } + + if (!flags) + flags = buf->flags; + + buf->private = buf->pool->setstatic(buf->pool, offset, size, + virtual, flags); + if (!buf->private) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, + "Invalid buffer pool for setStatic\n"); + BM_CKFATAL(-ENOMEM); + } + _glthread_UNLOCK_MUTEX(buf->mutex); +} + + + +void +driGenBuffers(struct _DriBufferPool *pool, + const char *name, + unsigned n, + struct _DriBufferObject *buffers[], + unsigned alignment, unsigned flags, unsigned hint) +{ + struct _DriBufferObject *buf; + int i; + + flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM | + DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE; + + + for (i = 0; i < n; ++i) { + buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf)); + if (!buf) + BM_CKFATAL(-ENOMEM); + + _glthread_INIT_MUTEX(buf->mutex); + _glthread_LOCK_MUTEX(buf->mutex); + _glthread_LOCK_MUTEX(bmMutex); + buf->refCount = 1; + _glthread_UNLOCK_MUTEX(bmMutex); + buf->flags = flags; + buf->hint = hint; + buf->name = name; + buf->alignment = alignment; + buf->pool = pool; + _glthread_UNLOCK_MUTEX(buf->mutex); + buffers[i] = buf; + } +} + +void +driGenUserBuffer(struct _DriBufferPool *pool, + const char *name, + struct _DriBufferObject **buffers, + void *ptr, unsigned bytes) +{ + const unsigned alignment = 1, flags = 0, hint = 0; + + driGenBuffers(pool, name, 1, buffers, alignment, flags, hint); + + (*buffers)->userBuffer = 1; + (*buffers)->userData = ptr; + (*buffers)->userSize = bytes; +} + + +void +driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]) +{ + int i; + + for (i = 0; i < n; ++i) { + driBOUnReference(buffers[i]); + } +} + + +void +driInitBufMgr(int fd) +{ + ; +} + + +void +driBOCreateList(int target, drmBOList * list) +{ + _glthread_LOCK_MUTEX(bmMutex); + BM_CKFATAL(drmBOCreateList(target, list)); + _glthread_UNLOCK_MUTEX(bmMutex); +} + +void +driBOResetList(drmBOList * list) +{ + _glthread_LOCK_MUTEX(bmMutex); + BM_CKFATAL(drmBOResetList(list)); + _glthread_UNLOCK_MUTEX(bmMutex); +} + +void +driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf, + unsigned flags, unsigned mask) +{ + int newItem; + + _glthread_LOCK_MUTEX(buf->mutex); + _glthread_LOCK_MUTEX(bmMutex); + BM_CKFATAL(drmAddValidateItem(list, driBOKernel(buf), + flags, mask, &newItem)); + _glthread_UNLOCK_MUTEX(bmMutex); + + /* + * Tell userspace pools to validate the buffer. This should be a + * noop if the pool is already validated. + * FIXME: We should have a list for this as well. + */ + + if (buf->pool->validate) { + BM_CKFATAL(buf->pool->validate(buf->pool, buf->private)); + } + + _glthread_UNLOCK_MUTEX(buf->mutex); +} + +void +driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence) +{ + _glthread_LOCK_MUTEX(buf->mutex); + BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence)); + _glthread_UNLOCK_MUTEX(buf->mutex); + +} + +void +driBOValidateList(int fd, drmBOList * list) +{ + _glthread_LOCK_MUTEX(bmMutex); + BM_CKFATAL(drmBOValidateList(fd, list)); + _glthread_UNLOCK_MUTEX(bmMutex); +} + +void +driPoolTakeDown(struct _DriBufferPool *pool) +{ + pool->takeDown(pool); + +} diff --git a/src/mesa/drivers/dri/common/dri_bufmgr.h b/src/mesa/drivers/dri/common/dri_bufmgr.h new file mode 100644 index 0000000000..ee4ce2cbde --- /dev/null +++ b/src/mesa/drivers/dri/common/dri_bufmgr.h @@ -0,0 +1,103 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ +/* + * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> + * Keith Whitwell <keithw-at-tungstengraphics-dot-com> + */ + +#ifndef _DRI_BUFMGR_H_ +#define _DRI_BUFMGR_H_ +#include <xf86drm.h> + + +struct _DriFenceObject; +struct _DriBufferObject; +struct _DriBufferPool; + +extern struct _DriFenceObject *driFenceBuffers(int fd, char *name, + unsigned flags); + +extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence); + +extern void driFenceUnReference(struct _DriFenceObject *fence); + +extern void +driFenceFinish(struct _DriFenceObject *fence, unsigned type, int lazy); + +extern int driFenceSignaled(struct _DriFenceObject *fence, unsigned type); +extern unsigned driFenceType(struct _DriFenceObject *fence); + +/* + * Return a pointer to the libdrm buffer object this DriBufferObject + * uses. + */ + +extern drmBO *driBOKernel(struct _DriBufferObject *buf); +extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags, + unsigned hint); +extern void driBOUnmap(struct _DriBufferObject *buf); +extern unsigned long driBOOffset(struct _DriBufferObject *buf); +extern unsigned driBOFlags(struct _DriBufferObject *buf); +extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf); +extern void driBOUnReference(struct _DriBufferObject *buf); +extern void driBOData(struct _DriBufferObject *r_buf, + unsigned size, const void *data, unsigned flags); +extern void driBOSubData(struct _DriBufferObject *buf, + unsigned long offset, unsigned long size, + const void *data); +extern void driBOGetSubData(struct _DriBufferObject *buf, + unsigned long offset, unsigned long size, + void *data); +extern void driGenBuffers(struct _DriBufferPool *pool, + const char *name, + unsigned n, + struct _DriBufferObject *buffers[], + unsigned alignment, unsigned flags, unsigned hint); +extern void driGenUserBuffer(struct _DriBufferPool *pool, + const char *name, + struct _DriBufferObject *buffers[], + void *ptr, unsigned bytes); +extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]); +extern void driInitBufMgr(int fd); +extern void driBOCreateList(int target, drmBOList * list); +extern void driBOResetList(drmBOList * list); +extern void driBOAddListItem(drmBOList * list, struct _DriBufferObject *buf, + unsigned flags, unsigned mask); +extern void driBOValidateList(int fd, drmBOList * list); + +extern void driBOFence(struct _DriBufferObject *buf, + struct _DriFenceObject *fence); + +extern void driPoolTakeDown(struct _DriBufferPool *pool); +extern void driBOSetStatic(struct _DriBufferObject *buf, + unsigned long offset, + unsigned long size, void *virtual, unsigned flags); +extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy); +extern void driPoolTakeDown(struct _DriBufferPool *pool); + +#endif diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h index c0e1bea5e0..0feb57b3c6 100644 --- a/src/mesa/drivers/dri/common/dri_util.h +++ b/src/mesa/drivers/dri/common/dri_util.h @@ -1,25 +1,3 @@ -/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */ -/** - * \file dri_util.h - * DRI utility functions definitions. - * - * This module acts as glue between GLX and the actual hardware driver. A DRI - * driver doesn't really \e have to use any of this - it's optional. But, some - * useful stuff is done here that otherwise would have to be duplicated in most - * drivers. - * - * Basically, these utility functions take care of some of the dirty details of - * screen initialization, context creation, context binding, DRM setup, etc. - * - * These functions are compiled into each DRI driver so libGL.so knows nothing - * about them. - * - * \sa dri_util.c. - * - * \author Kevin E. Martin <kevin@precisioninsight.com> - * \author Brian Paul <brian@precisioninsight.com> - */ - /* * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. * All Rights Reserved. @@ -45,6 +23,26 @@ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/** + * \file dri_util.h + * DRI utility functions definitions. + * + * This module acts as glue between GLX and the actual hardware driver. A DRI + * driver doesn't really \e have to use any of this - it's optional. But, some + * useful stuff is done here that otherwise would have to be duplicated in most + * drivers. + * + * Basically, these utility functions take care of some of the dirty details of + * screen initialization, context creation, context binding, DRM setup, etc. + * + * These functions are compiled into each DRI driver so libGL.so knows nothing + * about them. + * + * \sa dri_util.c. + * + * \author Kevin E. Martin <kevin@precisioninsight.com> + * \author Brian Paul <brian@precisioninsight.com> + */ #ifndef _DRI_UTIL_H_ #define _DRI_UTIL_H_ diff --git a/src/mesa/drivers/dri/common/drirenderbuffer.c b/src/mesa/drivers/dri/common/drirenderbuffer.c index b99bf2033b..15af99136c 100644 --- a/src/mesa/drivers/dri/common/drirenderbuffer.c +++ b/src/mesa/drivers/dri/common/drirenderbuffer.c @@ -209,6 +209,8 @@ driUpdateFramebufferSize(GLcontext *ctx, const __DRIdrawablePrivate *dPriv) struct gl_framebuffer *fb = (struct gl_framebuffer *) dPriv->driverPrivate; if (fb && (dPriv->w != fb->Width || dPriv->h != fb->Height)) { ctx->Driver.ResizeBuffers(ctx, fb, dPriv->w, dPriv->h); + /* if the driver needs the hw lock for ResizeBuffers, the drawable + might have changed again by now */ assert(fb->Width == dPriv->w); assert(fb->Height == dPriv->h); } diff --git a/src/mesa/drivers/dri/common/utils.c b/src/mesa/drivers/dri/common/utils.c index 30c860b96c..2a1ded3871 100644 --- a/src/mesa/drivers/dri/common/utils.c +++ b/src/mesa/drivers/dri/common/utils.c @@ -310,8 +310,10 @@ void driInitSingleExtension( GLcontext * ctx, */ offset = _glapi_add_dispatch( functions, parameter_signature ); if (offset == -1) { +#if 0 /* this causes noise with egl */ fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed " "to add %s!\n", functions[0]); +#endif } else if (ext->functions[i].remap_index != -1) { driDispatchRemapTable[ ext->functions[i].remap_index ] = @@ -504,6 +506,9 @@ GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer, * \c GLX_SWAP_UNDEFINED_OML. See the * GLX_OML_swap_method extension spec for more details. * \param num_db_modes Number of entries in \c db_modes. + * \param msaa_samples Array of msaa sample count. 0 represents a visual + * without a multisample buffer. + * \param num_msaa_modes Number of entries in \c msaa_samples. * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or * \c GLX_DIRECT_COLOR. * @@ -523,7 +528,8 @@ __DRIconfig ** driCreateConfigs(GLenum fb_format, GLenum fb_type, const uint8_t * depth_bits, const uint8_t * stencil_bits, unsigned num_depth_stencil_bits, - const GLenum * db_modes, unsigned num_db_modes) + const GLenum * db_modes, unsigned num_db_modes, + const u_int8_t * msaa_samples, unsigned num_msaa_modes) { static const uint8_t bits_table[4][4] = { /* R G B A */ @@ -583,9 +589,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type, int index; __DRIconfig **configs, **c; __GLcontextModes *modes; - unsigned i; - unsigned j; - unsigned k; + unsigned i, j, k, h; unsigned num_modes; unsigned num_accum_bits = 2; @@ -658,7 +662,7 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type, break; } - num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits; + num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes; configs = _mesa_calloc((num_modes + 1) * sizeof *configs); if (configs == NULL) return NULL; @@ -666,66 +670,72 @@ driCreateConfigs(GLenum fb_format, GLenum fb_type, c = configs; for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { for ( i = 0 ; i < num_db_modes ; i++ ) { - for ( j = 0 ; j < num_accum_bits ; j++ ) { - *c = _mesa_malloc (sizeof **c); - modes = &(*c)->modes; - c++; - - memset(modes, 0, sizeof *modes); - modes->redBits = bits[0]; - modes->greenBits = bits[1]; - modes->blueBits = bits[2]; - modes->alphaBits = bits[3]; - modes->redMask = masks[0]; - modes->greenMask = masks[1]; - modes->blueMask = masks[2]; - modes->alphaMask = masks[3]; - modes->rgbBits = modes->redBits + modes->greenBits - + modes->blueBits + modes->alphaBits; - - modes->accumRedBits = 16 * j; - modes->accumGreenBits = 16 * j; - modes->accumBlueBits = 16 * j; - modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; - modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; - - modes->stencilBits = stencil_bits[k]; - modes->depthBits = depth_bits[k]; - - modes->transparentPixel = GLX_NONE; - modes->transparentRed = GLX_DONT_CARE; - modes->transparentGreen = GLX_DONT_CARE; - modes->transparentBlue = GLX_DONT_CARE; - modes->transparentAlpha = GLX_DONT_CARE; - modes->transparentIndex = GLX_DONT_CARE; - modes->visualType = GLX_DONT_CARE; - modes->renderType = GLX_RGBA_BIT; - modes->drawableType = GLX_WINDOW_BIT; - modes->rgbMode = GL_TRUE; - - if ( db_modes[i] == GLX_NONE ) { - modes->doubleBufferMode = GL_FALSE; - } - else { - modes->doubleBufferMode = GL_TRUE; - modes->swapMethod = db_modes[i]; - } - - modes->haveAccumBuffer = ((modes->accumRedBits + + for ( h = 0 ; h < num_msaa_modes; h++ ) { + for ( j = 0 ; j < num_accum_bits ; j++ ) { + *c = _mesa_malloc (sizeof **c); + modes = &(*c)->modes; + c++; + + memset(modes, 0, sizeof *modes); + modes->redBits = bits[0]; + modes->greenBits = bits[1]; + modes->blueBits = bits[2]; + modes->alphaBits = bits[3]; + modes->redMask = masks[0]; + modes->greenMask = masks[1]; + modes->blueMask = masks[2]; + modes->alphaMask = masks[3]; + modes->rgbBits = modes->redBits + modes->greenBits + + modes->blueBits + modes->alphaBits; + + modes->accumRedBits = 16 * j; + modes->accumGreenBits = 16 * j; + modes->accumBlueBits = 16 * j; + modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; + modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; + + modes->stencilBits = stencil_bits[k]; + modes->depthBits = depth_bits[k]; + + modes->transparentPixel = GLX_NONE; + modes->transparentRed = GLX_DONT_CARE; + modes->transparentGreen = GLX_DONT_CARE; + modes->transparentBlue = GLX_DONT_CARE; + modes->transparentAlpha = GLX_DONT_CARE; + modes->transparentIndex = GLX_DONT_CARE; + modes->visualType = GLX_DONT_CARE; + modes->renderType = GLX_RGBA_BIT; + modes->drawableType = GLX_WINDOW_BIT; + modes->rgbMode = GL_TRUE; + + if ( db_modes[i] == GLX_NONE ) { + modes->doubleBufferMode = GL_FALSE; + } + else { + modes->doubleBufferMode = GL_TRUE; + modes->swapMethod = db_modes[i]; + } + + modes->samples = msaa_samples[h]; + modes->sampleBuffers = modes->samples ? 1 : 0; + + + modes->haveAccumBuffer = ((modes->accumRedBits + modes->accumGreenBits + modes->accumBlueBits + modes->accumAlphaBits) > 0); - modes->haveDepthBuffer = (modes->depthBits > 0); - modes->haveStencilBuffer = (modes->stencilBits > 0); - - modes->bindToTextureRgb = GL_TRUE; - modes->bindToTextureRgba = GL_TRUE; - modes->bindToMipmapTexture = GL_FALSE; - modes->bindToTextureTargets = modes->rgbMode ? - __DRI_ATTRIB_TEXTURE_1D_BIT | - __DRI_ATTRIB_TEXTURE_2D_BIT | - __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT : - 0; + modes->haveDepthBuffer = (modes->depthBits > 0); + modes->haveStencilBuffer = (modes->stencilBits > 0); + + modes->bindToTextureRgb = GL_TRUE; + modes->bindToTextureRgba = GL_TRUE; + modes->bindToMipmapTexture = GL_FALSE; + modes->bindToTextureTargets = modes->rgbMode ? + __DRI_ATTRIB_TEXTURE_1D_BIT | + __DRI_ATTRIB_TEXTURE_2D_BIT | + __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT : + 0; + } } } } diff --git a/src/mesa/drivers/dri/common/utils.h b/src/mesa/drivers/dri/common/utils.h index 0c974dbff3..4e27bd21a1 100644 --- a/src/mesa/drivers/dri/common/utils.h +++ b/src/mesa/drivers/dri/common/utils.h @@ -131,7 +131,8 @@ extern __DRIconfig ** driCreateConfigs(GLenum fb_format, GLenum fb_type, const uint8_t * depth_bits, const uint8_t * stencil_bits, unsigned num_depth_stencil_bits, - const GLenum * db_modes, unsigned num_db_modes); + const GLenum * db_modes, unsigned num_db_modes, + const uint8_t * msaa_samples, unsigned num_msaa_modes); const __DRIconfig **driConcatConfigs(__DRIconfig **a, __DRIconfig **b); diff --git a/src/mesa/drivers/dri/glcore/Makefile b/src/mesa/drivers/dri/glcore/Makefile new file mode 100644 index 0000000000..ac7e1de928 --- /dev/null +++ b/src/mesa/drivers/dri/glcore/Makefile @@ -0,0 +1,84 @@ +# src/mesa/drivers/dri/glcore/Makefile + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = glcore_dri.so + +DRIVER_SOURCES = glcore_driver.c \ + $(TOP)/src/mesa/drivers/common/driverfuncs.c \ + ../common/dri_util.c + +C_SOURCES = \ + $(DRIVER_SOURCES) \ + $(DRI_SOURCES) + + +# Include directories +INCLUDE_DIRS = \ + -I. \ + -I../common \ + -I../dri_client \ + -I../dri_client/imports \ + -Iserver \ + -I$(TOP)/include \ + -I$(DRM_SOURCE_PATH)/shared-core \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/mesa/math \ + -I$(TOP)/src/mesa/transform \ + -I$(TOP)/src/mesa/shader \ + -I$(TOP)/src/mesa/swrast \ + -I$(TOP)/src/mesa/swrast_setup + +# Core Mesa objects +MESA_MODULES = $(TOP)/src/mesa/libmesa.a + +# Libraries that the driver shared lib depends on +LIB_DEPS = -lm -lpthread -lc +# LIB_DEPS = -lGL -lm -lpthread -lc + + +ASM_SOURCES = + +OBJECTS = $(C_SOURCES:.c=.o) \ + $(ASM_SOURCES:.S=.o) + + +##### RULES ##### + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@ + +.S.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(DEFINES) $< -o $@ + + +##### TARGETS ##### + +default: depend $(TOP)/$(LIB_DIR)/$(LIBNAME) + + +$(TOP)/$(LIB_DIR)/$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile + CC="$(CC)" CXX="$(CXX)" $(TOP)/bin/mklib -o $(LIBNAME) -noprefix -install $(TOP)/$(LIB_DIR) \ + $(OBJECTS) $(WINLIB) $(LIB_DEPS) $(WINOBJ) $(MESA_MODULES) + + +depend: $(C_SOURCES) $(ASM_SOURCES) + rm -f depend + touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(INCLUDE_DIRS) $(C_SOURCES) $(ASM_SOURCES) \ + > /dev/null + + +# Emacs tags +tags: + etags `find . -name \*.[ch]` `find ../include` + + +clean: + -rm -f *.o server/*.o + + +include depend diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.h b/src/mesa/drivers/dri/i915/intel_ioctl.h new file mode 100644 index 0000000000..8d79e9d73b --- /dev/null +++ b/src/mesa/drivers/dri/i915/intel_ioctl.h @@ -0,0 +1,72 @@ +/************************************************************************** + * + * Copyright 2003 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. + * + **************************************************************************/ + +#ifndef INTEL_IOCTL_H +#define INTEL_IOCTL_H + +#include "intel_context.h" + +extern void intelWaitAgeLocked( intelContextPtr intel, int age, GLboolean unlock ); + +extern void intelClear(GLcontext *ctx, GLbitfield mask); + +extern void intelPageFlip( const __DRIdrawablePrivate *dpriv ); + +extern void intelRotateWindow(intelContextPtr intel, + __DRIdrawablePrivate *dPriv, GLuint srcBuffer); + +extern void intelWaitForIdle( intelContextPtr intel ); +extern void intelFlushBatch( intelContextPtr intel, GLboolean refill ); +extern void intelFlushBatchLocked( intelContextPtr intel, + GLboolean ignore_cliprects, + GLboolean refill, + GLboolean allow_unlock); +extern void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ); +extern void intelFinish( GLcontext *ctx ); +extern void intelFlush( GLcontext *ctx ); +extern void intelglFlush( GLcontext *ctx ); + +extern void *intelAllocateAGP( intelContextPtr intel, GLsizei size ); +extern void intelFreeAGP( intelContextPtr intel, void *pointer ); + +extern void *intelAllocateMemoryMESA( __DRInativeDisplay *dpy, int scrn, + GLsizei size, GLfloat readfreq, + GLfloat writefreq, GLfloat priority ); + +extern void intelFreeMemoryMESA( __DRInativeDisplay *dpy, int scrn, + GLvoid *pointer ); + +extern GLuint intelGetMemoryOffsetMESA( __DRInativeDisplay *dpy, int scrn, const GLvoid *pointer ); +extern GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, + GLint size ); + +extern GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *p ); + +extern void intelWaitIrq( intelContextPtr intel, int seq ); +extern uint32_t intelGetLastFrame (intelContextPtr intel); +extern int intelEmitIrqLocked( intelContextPtr intel ); +#endif diff --git a/src/mesa/drivers/dri/i915/intel_screen.c b/src/mesa/drivers/dri/i915/intel_screen.c index f2db48272b..7e7935510a 120000..100644 --- a/src/mesa/drivers/dri/i915/intel_screen.c +++ b/src/mesa/drivers/dri/i915/intel_screen.c @@ -1 +1,690 @@ -../intel/intel_screen.c
\ No newline at end of file +/************************************************************************** + * + * Copyright 2003 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. + * + **************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "framebuffer.h" +#include "matrix.h" +#include "renderbuffer.h" +#include "simple_list.h" +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + + +#include "intel_screen.h" + +#include "intel_tex.h" +#include "intel_span.h" +#include "intel_tris.h" +#include "intel_ioctl.h" + +#include "i830_dri.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 GLuint __driNConfigOptions = 4; + +#ifdef USE_NEW_INTERFACE +static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; +#endif /*USE_NEW_INTERFACE*/ + +extern const struct dri_extension card_extensions[]; + +/** + * Map all the memory regions described by the screen. + * \return GL_TRUE if success, GL_FALSE if error. + */ +GLboolean +intelMapScreenRegions(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + if (intelScreen->front.handle) { + if (drmMap(sPriv->fd, + intelScreen->front.handle, + intelScreen->front.size, + (drmAddress *)&intelScreen->front.map) != 0) { + _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); + return GL_FALSE; + } + } + else { + _mesa_warning(NULL, "no front buffer handle in intelMapScreenRegions!"); + } + + if (drmMap(sPriv->fd, + intelScreen->back.handle, + intelScreen->back.size, + (drmAddress *)&intelScreen->back.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->depth.handle, + intelScreen->depth.size, + (drmAddress *)&intelScreen->depth.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->tex.handle, + intelScreen->tex.size, + (drmAddress *)&intelScreen->tex.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (0) + printf("Mappings: front: %p back: %p depth: %p tex: %p\n", + intelScreen->front.map, + intelScreen->back.map, + intelScreen->depth.map, + intelScreen->tex.map); + return GL_TRUE; +} + + +void +intelUnmapScreenRegions(intelScreenPrivate *intelScreen) +{ +#define REALLY_UNMAP 1 + if (intelScreen->front.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0) + printf("drmUnmap front failed!\n"); +#endif + intelScreen->front.map = NULL; + } + if (intelScreen->back.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0) + printf("drmUnmap back failed!\n"); +#endif + intelScreen->back.map = NULL; + } + if (intelScreen->depth.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->depth.map, intelScreen->depth.size); + intelScreen->depth.map = NULL; +#endif + } + if (intelScreen->tex.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->tex.map, intelScreen->tex.size); + intelScreen->tex.map = NULL; +#endif + } +} + + +static void +intelPrintDRIInfo(intelScreenPrivate *intelScreen, + __DRIscreenPrivate *sPriv, + I830DRIPtr gDRIPriv) +{ + fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->front.size, intelScreen->front.offset, + intelScreen->front.pitch); + fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->back.size, intelScreen->back.offset, + intelScreen->back.pitch); + fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->depth.size, intelScreen->depth.offset, + intelScreen->depth.pitch); + fprintf(stderr, "*** Rotated size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->rotated.size, intelScreen->rotated.offset, + intelScreen->rotated.pitch); + fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n", + intelScreen->tex.size, intelScreen->tex.offset); + fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); +} + + +static void +intelPrintSAREA(const drmI830Sarea *sarea) +{ + fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, sarea->height); + fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); + fprintf(stderr, + "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->front_offset, sarea->front_size, + (unsigned) sarea->front_handle); + fprintf(stderr, + "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->back_offset, sarea->back_size, + (unsigned) sarea->back_handle); + fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->depth_offset, sarea->depth_size, + (unsigned) sarea->depth_handle); + fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->tex_offset, sarea->tex_size, + (unsigned) sarea->tex_handle); + fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); + fprintf(stderr, + "SAREA: rotated offset: 0x%08x size: 0x%x\n", + sarea->rotated_offset, sarea->rotated_size); + fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); +} + + +/** + * A number of the screen parameters are obtained/computed from + * information in the SAREA. This function updates those parameters. + */ +void +intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen, + drmI830Sarea *sarea) +{ + intelScreen->width = sarea->width; + intelScreen->height = sarea->height; + + intelScreen->front.offset = sarea->front_offset; + intelScreen->front.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->front.handle = sarea->front_handle; + intelScreen->front.size = sarea->front_size; + + intelScreen->back.offset = sarea->back_offset; + intelScreen->back.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->back.handle = sarea->back_handle; + intelScreen->back.size = sarea->back_size; + + intelScreen->depth.offset = sarea->depth_offset; + intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->depth.handle = sarea->depth_handle; + intelScreen->depth.size = sarea->depth_size; + + intelScreen->tex.offset = sarea->tex_offset; + intelScreen->logTextureGranularity = sarea->log_tex_granularity; + intelScreen->tex.handle = sarea->tex_handle; + intelScreen->tex.size = sarea->tex_size; + + intelScreen->rotated.offset = sarea->rotated_offset; + intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp; + intelScreen->rotated.size = sarea->rotated_size; + intelScreen->current_rotation = sarea->rotation; + matrix23Rotate(&intelScreen->rotMatrix, + sarea->width, sarea->height, sarea->rotation); + intelScreen->rotatedWidth = sarea->virtualX; + intelScreen->rotatedHeight = sarea->virtualY; + + if (0) + intelPrintSAREA(sarea); +} + + +static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen; + I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv; + drmI830Sarea *sarea; + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); + void * const psc = sPriv->psc->screenConfigs; + + if (sPriv->devPrivSize != sizeof(I830DRIRec)) { + fprintf(stderr,"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); + return GL_FALSE; + } + + /* Allocate the private area */ + intelScreen = (intelScreenPrivate *)CALLOC(sizeof(intelScreenPrivate)); + if (!intelScreen) { + fprintf(stderr,"\nERROR! Allocating private area failed\n"); + return GL_FALSE; + } + /* parse information in __driConfigOptions */ + driParseOptionInfo (&intelScreen->optionCache, + __driConfigOptions, __driNConfigOptions); + + intelScreen->driScrnPriv = sPriv; + sPriv->private = (void *)intelScreen; + intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + sarea = (drmI830Sarea *) + (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset); + + intelScreen->deviceID = gDRIPriv->deviceID; + intelScreen->mem = gDRIPriv->mem; + intelScreen->cpp = gDRIPriv->cpp; + + switch (gDRIPriv->bitsPerPixel) { + case 15: intelScreen->fbFormat = DV_PF_555; break; + case 16: intelScreen->fbFormat = DV_PF_565; break; + case 32: intelScreen->fbFormat = DV_PF_8888; break; + } + + intelUpdateScreenFromSAREA(intelScreen, sarea); + + if (0) + intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); + + if (!intelMapScreenRegions(sPriv)) { + fprintf(stderr,"\nERROR! mapping regions\n"); + _mesa_free(intelScreen); + sPriv->private = NULL; + return GL_FALSE; + } + + intelScreen->drmMinor = sPriv->drmMinor; + + /* Determine if IRQs are active? */ + { + int ret; + drmI830GetParam gp; + + gp.param = I830_PARAM_IRQ_ACTIVE; + gp.value = &intelScreen->irq_active; + + ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmI830GetParam: %d\n", ret); + return GL_FALSE; + } + } + + /* Determine if batchbuffers are allowed */ + { + int ret; + drmI830GetParam gp; + + gp.param = I830_PARAM_ALLOW_BATCHBUFFER; + gp.value = &intelScreen->allow_batchbuffer; + + ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret); + return GL_FALSE; + } + } + + if (glx_enable_extension != NULL) { + (*glx_enable_extension)( psc, "GLX_SGI_swap_control" ); + (*glx_enable_extension)( psc, "GLX_SGI_video_sync" ); + (*glx_enable_extension)( psc, "GLX_MESA_swap_control" ); + (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); + (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); + (*glx_enable_extension)( psc, "GLX_MESA_allocate_memory" ); + (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" ); + } + + sPriv->psc->allocateMemory = (void *) intelAllocateMemoryMESA; + sPriv->psc->freeMemory = (void *) intelFreeMemoryMESA; + sPriv->psc->memoryOffset = (void *) intelGetMemoryOffsetMESA; + + return GL_TRUE; +} + + +static void intelDestroyScreen(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + intelUnmapScreenRegions(intelScreen); + + driDestroyOptionInfo (&intelScreen->optionCache); + + FREE(intelScreen); + sPriv->private = NULL; +} + + +static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private; + + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } else { + GLboolean swStencil = (mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24); + + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, + screen->front.map, + screen->cpp, + screen->front.offset, screen->front.pitch, + driDrawPriv); + intelSetSpanFunctions(frontRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, + screen->back.map, + screen->cpp, + screen->back.offset, screen->back.pitch, + driDrawPriv); + intelSetSpanFunctions(backRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else if (mesaVis->depthBits == 24) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT24, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(stencilRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + mesaVis->accumRedBits > 0, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; + + return (driDrawPriv->driverPrivate != NULL); + } +} + +static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + + +/** + * Get information about previous buffer swaps. + */ +static int +intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ) +{ + intelContextPtr intel; + + if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL) + || (dPriv->driContextPriv->driverPrivate == NULL) + || (sInfo == NULL) ) { + return -1; + } + + intel = dPriv->driContextPriv->driverPrivate; + sInfo->swap_count = intel->swap_count; + sInfo->swap_ust = intel->swap_ust; + sInfo->swap_missed_count = intel->swap_missed_count; + + sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) + ? driCalculateSwapUsage( dPriv, 0, intel->swap_missed_ust ) + : 0.0; + + return 0; +} + + +/* There are probably better ways to do this, such as an + * init-designated function to register chipids and createcontext + * functions. + */ +extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate); + +extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate); + + + + +static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + switch (intelScreen->deviceID) { + case PCI_CHIP_845_G: + case PCI_CHIP_I830_M: + case PCI_CHIP_I855_GM: + case PCI_CHIP_I865_G: + return i830CreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); + + case PCI_CHIP_I915_G: + case PCI_CHIP_I915_GM: + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: + case PCI_CHIP_I945_GME: + case PCI_CHIP_G33_G: + case PCI_CHIP_Q35_G: + case PCI_CHIP_Q33_G: + return i915CreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); + + default: + fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); + return GL_FALSE; + } +} + + +static const struct __DriverAPIRec intelAPI = { + .InitDriver = intelInitDriver, + .DestroyScreen = intelDestroyScreen, + .CreateContext = intelCreateContext, + .DestroyContext = intelDestroyContext, + .CreateBuffer = intelCreateBuffer, + .DestroyBuffer = intelDestroyBuffer, + .SwapBuffers = intelSwapBuffers, + .MakeCurrent = intelMakeCurrent, + .UnbindContext = intelUnbindContext, + .GetSwapInfo = intelGetSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = intelCopySubBuffer +}; + + +static __GLcontextModes * +intelFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if ( pixel_bits == 16 ) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); + m = modes; + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_DIRECT_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for ( m = modes ; m != NULL ; m = m->next ) { + if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes ) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 5, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 4, 0 }; + + dri_interface = interface; + + if ( ! driCheckDriDdxDrmVersions2( "i915", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected ) ) { + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &intelAPI); + if ( psp != NULL ) { + I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; + *driver_modes = intelFillInModes( dri_priv->cpp * 8, + (dri_priv->cpp == 2) ? 16 : 24, + (dri_priv->cpp == 2) ? 0 : 8, + 1 ); + + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + } + + return (void *) psp; +} diff --git a/src/mesa/drivers/dri/i915/server/i830_common.h b/src/mesa/drivers/dri/i915/server/i830_common.h new file mode 100644 index 0000000000..2b0fee82a8 --- /dev/null +++ b/src/mesa/drivers/dri/i915/server/i830_common.h @@ -0,0 +1,211 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. +Copyright 2002 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 +on 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 +ATI, VA LINUX SYSTEMS AND/OR THEIR 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 _I830_COMMON_H_ +#define _I830_COMMON_H_ + + +#define I830_NR_TEX_REGIONS 255 /* maximum due to use of chars for next/prev */ +#define I830_LOG_MIN_TEX_REGION_SIZE 14 + + +/* Driver specific DRM command indices + * NOTE: these are not OS specific, but they are driver specific + */ +#define DRM_I830_INIT 0x00 +#define DRM_I830_FLUSH 0x01 +#define DRM_I830_FLIP 0x02 +#define DRM_I830_BATCHBUFFER 0x03 +#define DRM_I830_IRQ_EMIT 0x04 +#define DRM_I830_IRQ_WAIT 0x05 +#define DRM_I830_GETPARAM 0x06 +#define DRM_I830_SETPARAM 0x07 +#define DRM_I830_ALLOC 0x08 +#define DRM_I830_FREE 0x09 +#define DRM_I830_INIT_HEAP 0x0a +#define DRM_I830_CMDBUFFER 0x0b +#define DRM_I830_DESTROY_HEAP 0x0c + +typedef struct { + enum { + I830_INIT_DMA = 0x01, + I830_CLEANUP_DMA = 0x02, + I830_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drmI830Init; + +typedef struct { + drmTextureRegion texList[I830_NR_TEX_REGIONS+1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; + + int pipeA_x; + int pipeA_y; + int pipeA_w; + int pipeA_h; + int pipeB_x; + int pipeB_y; + int pipeB_w; + int pipeB_h; +} drmI830Sarea; + +/* Flags for perf_boxes + */ +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ + + +typedef struct { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/ + int num_cliprects; /* mulitpass with multiple cliprects? */ + drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ +} drmI830BatchBuffer; + +typedef struct { + char *buf; /* agp offset */ + int sz; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/ + int num_cliprects; /* mulitpass with multiple cliprects? */ + drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ +} drmI830CmdBuffer; + +typedef struct { + int *irq_seq; +} drmI830IrqEmit; + +typedef struct { + int irq_seq; +} drmI830IrqWait; + +typedef struct { + int param; + int *value; +} drmI830GetParam; + +#define I830_PARAM_IRQ_ACTIVE 1 +#define I830_PARAM_ALLOW_BATCHBUFFER 2 + +typedef struct { + int param; + int value; +} drmI830SetParam; + +#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I830_SETPARAM_ALLOW_BATCHBUFFER 3 + + +/* A memory manager for regions of shared memory: + */ +#define I830_MEM_REGION_AGP 1 + +typedef struct { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drmI830MemAlloc; + +typedef struct { + int region; + int region_offset; +} drmI830MemFree; + +typedef struct { + int region; + int size; + int start; +} drmI830MemInitHeap; + +typedef struct { + int region; +} drmI830MemDestroyHeap; + + +#endif /* _I830_DRM_H_ */ diff --git a/src/mesa/drivers/dri/i915/server/i830_dri.h b/src/mesa/drivers/dri/i915/server/i830_dri.h new file mode 100644 index 0000000000..313eb759b0 --- /dev/null +++ b/src/mesa/drivers/dri/i915/server/i830_dri.h @@ -0,0 +1,72 @@ + +#ifndef _I830_DRI_H +#define _I830_DRI_H + +#include "xf86drm.h" +#include "i830_common.h" + +#define I830_MAX_DRAWABLES 256 + +#define I830_MAJOR_VERSION 1 +#define I830_MINOR_VERSION 3 +#define I830_PATCHLEVEL 0 + +#define I830_REG_SIZE 0x80000 + +typedef struct _I830DRIRec { + drm_handle_t regs; + drmSize regsSize; + + drmSize backbufferSize; + drm_handle_t backbuffer; + + drmSize depthbufferSize; + drm_handle_t depthbuffer; + + drmSize rotatedSize; + drm_handle_t rotatedbuffer; + + drm_handle_t textures; + int textureSize; + + drm_handle_t agp_buffers; + drmSize agp_buf_size; + + int deviceID; + int width; + int height; + int mem; + int cpp; + int bitsPerPixel; + + int fbOffset; + int fbStride; + + int backOffset; + int backPitch; + + int depthOffset; + int depthPitch; + + int rotatedOffset; + int rotatedPitch; + + int logTextureGranularity; + int textureOffset; + + int irq; + int sarea_priv_offset; +} I830DRIRec, *I830DRIPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830ConfigPrivRec, *I830ConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830DRIContextRec, *I830DRIContextPtr; + + +#endif diff --git a/src/mesa/drivers/dri/i965/intel_screen.c b/src/mesa/drivers/dri/i965/intel_screen.c index f2db48272b..bc3dd30b7e 120000..100644 --- a/src/mesa/drivers/dri/i965/intel_screen.c +++ b/src/mesa/drivers/dri/i965/intel_screen.c @@ -1 +1,701 @@ -../intel/intel_screen.c
\ No newline at end of file +/************************************************************************** + * + * Copyright 2003 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. + * + **************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "framebuffer.h" +#include "matrix.h" +#include "renderbuffer.h" +#include "simple_list.h" +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + + +#include "intel_screen.h" + +#include "intel_context.h" +#include "intel_tex.h" +#include "intel_span.h" +#include "intel_ioctl.h" + +#include "i830_dri.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 GLuint __driNConfigOptions = 4; + +#ifdef USE_NEW_INTERFACE +static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; +#endif /*USE_NEW_INTERFACE*/ + +/** + * Map all the memory regions described by the screen. + * \return GL_TRUE if success, GL_FALSE if error. + */ +GLboolean +intelMapScreenRegions(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + if (intelScreen->front.handle) { + if (drmMap(sPriv->fd, + intelScreen->front.handle, + intelScreen->front.size, + (drmAddress *)&intelScreen->front.map) != 0) { + _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); + return GL_FALSE; + } + } else { + /* Use the old static allocation method if the server isn't setting up + * a movable handle for us. Add in the front buffer offset from + * framebuffer start, as our span routines (unlike other drivers) expect + * the renderbuffer address to point to the beginning of the + * renderbuffer. + */ + intelScreen->front.map = (char *)sPriv->pFB; + if (intelScreen->front.map == NULL) { + fprintf(stderr, "Failed to find framebuffer mapping\n"); + return GL_FALSE; + } + } + + if (drmMap(sPriv->fd, + intelScreen->back.handle, + intelScreen->back.size, + (drmAddress *)&intelScreen->back.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->depth.handle, + intelScreen->depth.size, + (drmAddress *)&intelScreen->depth.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (drmMap(sPriv->fd, + intelScreen->tex.handle, + intelScreen->tex.size, + (drmAddress *)&intelScreen->tex.map) != 0) { + intelUnmapScreenRegions(intelScreen); + return GL_FALSE; + } + + if (0) + printf("Mappings: front: %p back: %p depth: %p tex: %p\n", + intelScreen->front.map, + intelScreen->back.map, + intelScreen->depth.map, + intelScreen->tex.map); + return GL_TRUE; +} + + +void +intelUnmapScreenRegions(intelScreenPrivate *intelScreen) +{ +#define REALLY_UNMAP 1 + /* If front.handle is present, we're doing the dynamic front buffer mapping, + * but if we've fallen back to static allocation then we shouldn't try to + * unmap here. + */ + if (intelScreen->front.handle) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->front.map, intelScreen->front.size) != 0) + printf("drmUnmap front failed!\n"); +#endif + intelScreen->front.map = NULL; + } + if (intelScreen->back.map) { +#if REALLY_UNMAP + if (drmUnmap(intelScreen->back.map, intelScreen->back.size) != 0) + printf("drmUnmap back failed!\n"); +#endif + intelScreen->back.map = NULL; + } + if (intelScreen->depth.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->depth.map, intelScreen->depth.size); + intelScreen->depth.map = NULL; +#endif + } + if (intelScreen->tex.map) { +#if REALLY_UNMAP + drmUnmap(intelScreen->tex.map, intelScreen->tex.size); + intelScreen->tex.map = NULL; +#endif + } +} + + +static void +intelPrintDRIInfo(intelScreenPrivate *intelScreen, + __DRIscreenPrivate *sPriv, + I830DRIPtr gDRIPriv) +{ + fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->front.size, intelScreen->front.offset, + intelScreen->front.pitch); + fprintf(stderr, "*** Back size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->back.size, intelScreen->back.offset, + intelScreen->back.pitch); + fprintf(stderr, "*** Depth size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->depth.size, intelScreen->depth.offset, + intelScreen->depth.pitch); + fprintf(stderr, "*** Rotated size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->rotated.size, intelScreen->rotated.offset, + intelScreen->rotated.pitch); + fprintf(stderr, "*** Texture size: 0x%x offset: 0x%x\n", + intelScreen->tex.size, intelScreen->tex.offset); + fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); +} + + +static void +intelPrintSAREA(volatile drmI830Sarea *sarea) +{ + fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, sarea->height); + fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); + fprintf(stderr, + "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->front_offset, sarea->front_size, + (unsigned) sarea->front_handle); + fprintf(stderr, + "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->back_offset, sarea->back_size, + (unsigned) sarea->back_handle); + fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->depth_offset, sarea->depth_size, + (unsigned) sarea->depth_handle); + fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->tex_offset, sarea->tex_size, + (unsigned) sarea->tex_handle); + fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); + fprintf(stderr, + "SAREA: rotated offset: 0x%08x size: 0x%x\n", + sarea->rotated_offset, sarea->rotated_size); + fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); +} + + +/** + * A number of the screen parameters are obtained/computed from + * information in the SAREA. This function updates those parameters. + */ +void +intelUpdateScreenFromSAREA(intelScreenPrivate *intelScreen, + volatile drmI830Sarea *sarea) +{ + intelScreen->width = sarea->width; + intelScreen->height = sarea->height; + + intelScreen->front.offset = sarea->front_offset; + intelScreen->front.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->front.handle = sarea->front_handle; + intelScreen->front.size = sarea->front_size; + intelScreen->front.tiled = sarea->front_tiled; + + intelScreen->back.offset = sarea->back_offset; + intelScreen->back.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->back.handle = sarea->back_handle; + intelScreen->back.size = sarea->back_size; + intelScreen->back.tiled = sarea->back_tiled; + + intelScreen->depth.offset = sarea->depth_offset; + intelScreen->depth.pitch = sarea->pitch * intelScreen->cpp; + intelScreen->depth.handle = sarea->depth_handle; + intelScreen->depth.size = sarea->depth_size; + intelScreen->depth.tiled = sarea->depth_tiled; + + intelScreen->tex.offset = sarea->tex_offset; + intelScreen->logTextureGranularity = sarea->log_tex_granularity; + intelScreen->tex.handle = sarea->tex_handle; + intelScreen->tex.size = sarea->tex_size; + + intelScreen->rotated.offset = sarea->rotated_offset; + intelScreen->rotated.pitch = sarea->rotated_pitch * intelScreen->cpp; + intelScreen->rotated.size = sarea->rotated_size; + intelScreen->rotated.tiled = sarea->rotated_tiled; + intelScreen->current_rotation = sarea->rotation; +#if 0 + matrix23Rotate(&intelScreen->rotMatrix, + sarea->width, sarea->height, sarea->rotation); +#endif + intelScreen->rotatedWidth = sarea->virtualX; + intelScreen->rotatedHeight = sarea->virtualY; + + if (0) + intelPrintSAREA(sarea); +} + + +static GLboolean intelInitDriver(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen; + I830DRIPtr gDRIPriv = (I830DRIPtr)sPriv->pDevPriv; + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->getProcAddress("glxEnableExtension")); + void * const psc = sPriv->psc->screenConfigs; + volatile drmI830Sarea *sarea; + + if (sPriv->devPrivSize != sizeof(I830DRIRec)) { + fprintf(stderr,"\nERROR! sizeof(I830DRIRec) (%ld) does not match passed size from device driver (%d)\n", (unsigned long)sizeof(I830DRIRec), sPriv->devPrivSize); + return GL_FALSE; + } + + /* Allocate the private area */ + intelScreen = (intelScreenPrivate *)CALLOC(sizeof(intelScreenPrivate)); + if (!intelScreen) { + fprintf(stderr,"\nERROR! Allocating private area failed\n"); + return GL_FALSE; + } + /* parse information in __driConfigOptions */ + driParseOptionInfo (&intelScreen->optionCache, + __driConfigOptions, __driNConfigOptions); + + intelScreen->driScrnPriv = sPriv; + sPriv->private = (void *)intelScreen; + intelScreen->sarea_priv_offset = gDRIPriv->sarea_priv_offset; + sarea = (volatile drmI830Sarea *) + (((GLubyte *)sPriv->pSAREA)+intelScreen->sarea_priv_offset); + + intelScreen->deviceID = gDRIPriv->deviceID; + intelScreen->mem = gDRIPriv->mem; + intelScreen->cpp = gDRIPriv->cpp; + + switch (gDRIPriv->bitsPerPixel) { + case 15: intelScreen->fbFormat = DV_PF_555; break; + case 16: intelScreen->fbFormat = DV_PF_565; break; + case 32: intelScreen->fbFormat = DV_PF_8888; break; + } + + intelUpdateScreenFromSAREA(intelScreen, sarea); + + if (0) + intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv); + + if (!intelMapScreenRegions(sPriv)) { + fprintf(stderr,"\nERROR! mapping regions\n"); + _mesa_free(intelScreen); + sPriv->private = NULL; + return GL_FALSE; + } + + intelScreen->drmMinor = sPriv->drmMinor; + + /* Determine if IRQs are active? */ + { + int ret; + drmI830GetParam gp; + + gp.param = I830_PARAM_IRQ_ACTIVE; + gp.value = &intelScreen->irq_active; + + ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmI830GetParam: %d\n", ret); + return GL_FALSE; + } + } + + /* Determine if batchbuffers are allowed */ + { + int ret; + drmI830GetParam gp; + + gp.param = I830_PARAM_ALLOW_BATCHBUFFER; + gp.value = &intelScreen->allow_batchbuffer; + + ret = drmCommandWriteRead( sPriv->fd, DRM_I830_GETPARAM, + &gp, sizeof(gp)); + if (ret) { + fprintf(stderr, "drmI830GetParam: (%d) %d\n", gp.param, ret); + return GL_FALSE; + } + } + + if (glx_enable_extension != NULL) { + (*glx_enable_extension)( psc, "GLX_SGI_swap_control" ); + (*glx_enable_extension)( psc, "GLX_SGI_video_sync" ); + (*glx_enable_extension)( psc, "GLX_MESA_swap_control" ); + (*glx_enable_extension)( psc, "GLX_MESA_swap_frame_usage" ); + (*glx_enable_extension)( psc, "GLX_SGI_make_current_read" ); + (*glx_enable_extension)( psc, "GLX_MESA_copy_sub_buffer" ); + } + + return GL_TRUE; +} + + +static void intelDestroyScreen(__DRIscreenPrivate *sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + + intelUnmapScreenRegions(intelScreen); + FREE(intelScreen); + sPriv->private = NULL; +} + +static GLboolean intelCreateBuffer( __DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap ) +{ + intelScreenPrivate *screen = (intelScreenPrivate *) driScrnPriv->private; + + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } else { + GLboolean swStencil = (mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24); + + struct gl_framebuffer *fb = _mesa_create_framebuffer(mesaVis); + + { + driRenderbuffer *frontRb + = driNewRenderbuffer(GL_RGBA, + screen->front.map, + screen->cpp, + screen->front.offset, screen->front.pitch, + driDrawPriv); + intelSetSpanFunctions(frontRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &frontRb->Base); + } + + if (mesaVis->doubleBufferMode) { + driRenderbuffer *backRb + = driNewRenderbuffer(GL_RGBA, + screen->back.map, + screen->cpp, + screen->back.offset, screen->back.pitch, + driDrawPriv); + intelSetSpanFunctions(backRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &backRb->Base); + } + + if (mesaVis->depthBits == 16) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT16, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + else if (mesaVis->depthBits == 24) { + driRenderbuffer *depthRb + = driNewRenderbuffer(GL_DEPTH_COMPONENT24, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(depthRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &depthRb->Base); + } + + if (mesaVis->stencilBits > 0 && !swStencil) { + driRenderbuffer *stencilRb + = driNewRenderbuffer(GL_STENCIL_INDEX8_EXT, + screen->depth.map, + screen->cpp, + screen->depth.offset, screen->depth.pitch, + driDrawPriv); + intelSetSpanFunctions(stencilRb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &stencilRb->Base); + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + mesaVis->accumRedBits > 0, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + driDrawPriv->driverPrivate = (void *) fb; + + return (driDrawPriv->driverPrivate != NULL); + } +} + +static void intelDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + + +/** + * Get information about previous buffer swaps. + */ +static int +intelGetSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo ) +{ + struct intel_context *intel; + + if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL) + || (dPriv->driContextPriv->driverPrivate == NULL) + || (sInfo == NULL) ) { + return -1; + } + + intel = dPriv->driContextPriv->driverPrivate; + sInfo->swap_count = intel->swap_count; + sInfo->swap_ust = intel->swap_ust; + sInfo->swap_missed_count = intel->swap_missed_count; + + sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) + ? driCalculateSwapUsage( dPriv, 0, intel->swap_missed_ust ) + : 0.0; + + return 0; +} + + +/* There are probably better ways to do this, such as an + * init-designated function to register chipids and createcontext + * functions. + */ +extern GLboolean i830CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate); + +extern GLboolean i915CreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate); + +extern GLboolean brwCreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate); + + + + +static GLboolean intelCreateContext( const __GLcontextModes *mesaVis, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate) +{ +#if 0 + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + intelScreenPrivate *intelScreen = (intelScreenPrivate *)sPriv->private; + switch (intelScreen->deviceID) { + case PCI_CHIP_845_G: + case PCI_CHIP_I830_M: + case PCI_CHIP_I855_GM: + case PCI_CHIP_I865_G: + return i830CreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); + + case PCI_CHIP_I915_G: + case PCI_CHIP_I915_GM: + case PCI_CHIP_I945_G: + case PCI_CHIP_I945_GM: + return i915CreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); + + default: + fprintf(stderr, "Unrecognized deviceID %x\n", intelScreen->deviceID); + return GL_FALSE; + } +#else + return brwCreateContext( mesaVis, driContextPriv, + sharedContextPrivate ); +#endif +} + + +static const struct __DriverAPIRec intelAPI = { + .InitDriver = intelInitDriver, + .DestroyScreen = intelDestroyScreen, + .CreateContext = intelCreateContext, + .DestroyContext = intelDestroyContext, + .CreateBuffer = intelCreateBuffer, + .DestroyBuffer = intelDestroyBuffer, + .SwapBuffers = intelSwapBuffers, + .MakeCurrent = intelMakeCurrent, + .UnbindContext = intelUnbindContext, + .GetSwapInfo = intelGetSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = intelCopySubBuffer +}; + + +static __GLcontextModes * +intelFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + /* Just like with the accumulation buffer, always provide some modes + * with a stencil buffer. It will be a sw fallback, but some apps won't + * care about that. + */ + stencil_bits_array[0] = 0; + stencil_bits_array[1] = 0; + stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits; + + depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if ( pixel_bits == 16 ) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + modes = (*dri_interface->createContextModes)( num_modes, sizeof( __GLcontextModes ) ); + m = modes; + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_TRUE_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + if ( ! driFillInModes( & m, fb_format, fb_type, + depth_bits_array, stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + GLX_DIRECT_COLOR ) ) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + /* Mark the visual as slow if there are "fake" stencil bits. + */ + for ( m = modes ; m != NULL ; m = m->next ) { + if ( (m->stencilBits != 0) && (m->stencilBits != stencil_bits) ) { + m->visualRating = GLX_SLOW_CONFIG; + } + } + + return modes; +} + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes ) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 6, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 3, 0 }; + + dri_interface = interface; + + if ( ! driCheckDriDdxDrmVersions2( "i915", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected ) ) { + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &intelAPI); + if ( psp != NULL ) { + I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv; + *driver_modes = intelFillInModes( dri_priv->cpp * 8, + (dri_priv->cpp == 2) ? 16 : 24, + (dri_priv->cpp == 2) ? 0 : 8, + GL_TRUE ); + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + intelInitExtensions(NULL, GL_FALSE); + } + + return (void *) psp; +} diff --git a/src/mesa/drivers/dri/i965/server/i830_common.h b/src/mesa/drivers/dri/i965/server/i830_common.h new file mode 100644 index 0000000000..49eb145f8b --- /dev/null +++ b/src/mesa/drivers/dri/i965/server/i830_common.h @@ -0,0 +1,221 @@ +/************************************************************************** + +Copyright 2001 VA Linux Systems Inc., Fremont, California. +Copyright 2002 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 +on 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 +ATI, VA LINUX SYSTEMS AND/OR THEIR 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 _I830_COMMON_H_ +#define _I830_COMMON_H_ + + +#define I830_NR_TEX_REGIONS 255 /* maximum due to use of chars for next/prev */ +#define I830_LOG_MIN_TEX_REGION_SIZE 14 + + +/* Driver specific DRM command indices + * NOTE: these are not OS specific, but they are driver specific + */ +#define DRM_I830_INIT 0x00 +#define DRM_I830_FLUSH 0x01 +#define DRM_I830_FLIP 0x02 +#define DRM_I830_BATCHBUFFER 0x03 +#define DRM_I830_IRQ_EMIT 0x04 +#define DRM_I830_IRQ_WAIT 0x05 +#define DRM_I830_GETPARAM 0x06 +#define DRM_I830_SETPARAM 0x07 +#define DRM_I830_ALLOC 0x08 +#define DRM_I830_FREE 0x09 +#define DRM_I830_INIT_HEAP 0x0a +#define DRM_I830_CMDBUFFER 0x0b +#define DRM_I830_DESTROY_HEAP 0x0c +#define DRM_I830_MMIO 0x10 + +typedef struct { + enum { + I830_INIT_DMA = 0x01, + I830_CLEANUP_DMA = 0x02, + I830_RESUME_DMA = 0x03 + } func; + unsigned int mmio_offset; + int sarea_priv_offset; + unsigned int ring_start; + unsigned int ring_end; + unsigned int ring_size; + unsigned int front_offset; + unsigned int back_offset; + unsigned int depth_offset; + unsigned int w; + unsigned int h; + unsigned int pitch; + unsigned int pitch_bits; + unsigned int back_pitch; + unsigned int depth_pitch; + unsigned int cpp; + unsigned int chipset; +} drmI830Init; + +typedef struct { + drmTextureRegion texList[I830_NR_TEX_REGIONS+1]; + int last_upload; /* last time texture was uploaded */ + int last_enqueue; /* last time a buffer was enqueued */ + volatile int last_dispatch; /* age of the most recently dispatched buffer */ + int ctxOwner; /* last context to upload state */ + int texAge; + int pf_enabled; /* is pageflipping allowed? */ + int pf_active; + int pf_current_page; /* which buffer is being displayed? */ + int perf_boxes; /* performance boxes to be displayed */ + int width, height; /* screen size in pixels */ + + drm_handle_t front_handle; + int front_offset; + int front_size; + + drm_handle_t back_handle; + int back_offset; + int back_size; + + drm_handle_t depth_handle; + int depth_offset; + int depth_size; + + drm_handle_t tex_handle; + int tex_offset; + int tex_size; + int log_tex_granularity; + int pitch; + int rotation; /* 0, 90, 180 or 270 */ + int rotated_offset; + int rotated_size; + int rotated_pitch; + int virtualX, virtualY; + + unsigned int front_tiled; + unsigned int back_tiled; + unsigned int depth_tiled; + unsigned int rotated_tiled; + unsigned int rotated2_tiled; +} drmI830Sarea; + +/* Flags for perf_boxes + */ +#define I830_BOX_RING_EMPTY 0x1 /* populated by kernel */ +#define I830_BOX_FLIP 0x2 /* populated by kernel */ +#define I830_BOX_WAIT 0x4 /* populated by kernel & client */ +#define I830_BOX_TEXTURE_LOAD 0x8 /* populated by kernel */ +#define I830_BOX_LOST_CONTEXT 0x10 /* populated by client */ + + +typedef struct { + int start; /* agp offset */ + int used; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/ + int num_cliprects; /* mulitpass with multiple cliprects? */ + drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ +} drmI830BatchBuffer; + +typedef struct { + char *buf; /* agp offset */ + int sz; /* nr bytes in use */ + int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */ + int DR4; /* window origin for GFX_OP_DRAWRECT_INFO*/ + int num_cliprects; /* mulitpass with multiple cliprects? */ + drm_clip_rect_t *cliprects; /* pointer to userspace cliprects */ +} drmI830CmdBuffer; + +typedef struct { + int *irq_seq; +} drmI830IrqEmit; + +typedef struct { + int irq_seq; +} drmI830IrqWait; + +typedef struct { + int param; + int *value; +} drmI830GetParam; + +#define I830_PARAM_IRQ_ACTIVE 1 +#define I830_PARAM_ALLOW_BATCHBUFFER 2 + +typedef struct { + int param; + int value; +} drmI830SetParam; + +#define I830_SETPARAM_USE_MI_BATCHBUFFER_START 1 +#define I830_SETPARAM_TEX_LRU_LOG_GRANULARITY 2 +#define I830_SETPARAM_ALLOW_BATCHBUFFER 3 + + +/* A memory manager for regions of shared memory: + */ +#define I830_MEM_REGION_AGP 1 + +typedef struct { + int region; + int alignment; + int size; + int *region_offset; /* offset from start of fb or agp */ +} drmI830MemAlloc; + +typedef struct { + int region; + int region_offset; +} drmI830MemFree; + +typedef struct { + int region; + int size; + int start; +} drmI830MemInitHeap; + +typedef struct { + int region; +} drmI830MemDestroyHeap; + +#define MMIO_READ 0 +#define MMIO_WRITE 1 + +#define MMIO_REGS_IA_PRIMATIVES_COUNT 0 +#define MMIO_REGS_IA_VERTICES_COUNT 1 +#define MMIO_REGS_VS_INVOCATION_COUNT 2 +#define MMIO_REGS_GS_PRIMITIVES_COUNT 3 +#define MMIO_REGS_GS_INVOCATION_COUNT 4 +#define MMIO_REGS_CL_PRIMITIVES_COUNT 5 +#define MMIO_REGS_CL_INVOCATION_COUNT 6 +#define MMIO_REGS_PS_INVOCATION_COUNT 7 +#define MMIO_REGS_PS_DEPTH_COUNT 8 + +typedef struct { + unsigned int read_write:1; + unsigned int reg:31; + void __user *data; +} drmI830MMIO; + +#endif /* _I830_DRM_H_ */ diff --git a/src/mesa/drivers/dri/i965/server/i830_dri.h b/src/mesa/drivers/dri/i965/server/i830_dri.h new file mode 100644 index 0000000000..68213f69f5 --- /dev/null +++ b/src/mesa/drivers/dri/i965/server/i830_dri.h @@ -0,0 +1,62 @@ + +#ifndef _I830_DRI_H +#define _I830_DRI_H + +#include "xf86drm.h" +#include "i830_common.h" + +#define I830_MAX_DRAWABLES 256 + +#define I830_MAJOR_VERSION 1 +#define I830_MINOR_VERSION 3 +#define I830_PATCHLEVEL 0 + +#define I830_REG_SIZE 0x80000 + +typedef struct _I830DRIRec { + drm_handle_t regs; + drmSize regsSize; + + drmSize unused1; /* backbufferSize */ + drm_handle_t unused2; /* backbuffer */ + + drmSize unused3; /* depthbufferSize */ + drm_handle_t unused4; /* depthbuffer */ + + drmSize unused5; /* rotatedSize /*/ + drm_handle_t unused6; /* rotatedbuffer */ + + drm_handle_t unused7; /* textures */ + int unused8; /* textureSize */ + + drm_handle_t unused9; /* agp_buffers */ + drmSize unused10; /* agp_buf_size */ + + int deviceID; + int width; + int height; + int mem; + int cpp; + int bitsPerPixel; + + int unused11[8]; /* was front/back/depth/rotated offset/pitch */ + + int unused12; /* logTextureGranularity */ + int unused13; /* textureOffset */ + + int irq; + int sarea_priv_offset; +} I830DRIRec, *I830DRIPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830ConfigPrivRec, *I830ConfigPrivPtr; + +typedef struct { + /* Nothing here yet */ + int dummy; +} I830DRIContextRec, *I830DRIContextPtr; + + +#endif diff --git a/src/mesa/drivers/dri/nouveau/nouveau_context.h b/src/mesa/drivers/dri/nouveau/nouveau_context.h new file mode 100644 index 0000000000..db4d4cb6b7 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_context.h @@ -0,0 +1,239 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +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 +on 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 +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_CONTEXT_H__ +#define __NOUVEAU_CONTEXT_H__ + +#include "dri_util.h" +#include "drm.h" +#include "nouveau_drm.h" + +#include "mtypes.h" +#include "tnl/t_vertex.h" + +#include "nouveau_screen.h" +#include "nouveau_state_cache.h" +#include "nouveau_buffers.h" +#include "nouveau_shader.h" +#include "nouveau_sync.h" + +#include "xmlconfig.h" + +typedef struct nouveau_fifo_t{ + int channel; + uint32_t* buffer; + uint32_t* mmio; + uint32_t put_base; + uint32_t current; + uint32_t put; + uint32_t free; + uint32_t max; +} +nouveau_fifo; + +#define TAG(x) nouveau##x +#include "tnl_dd/t_dd_vertex.h" +#undef TAG + +/* Subpixel offsets for window coordinates (triangles): */ +#define SUBPIXEL_X (0.0F) +#define SUBPIXEL_Y (0.125F) + +struct nouveau_context; + +typedef void (*nouveau_tri_func)( struct nouveau_context*, + nouveauVertex *, + nouveauVertex *, + nouveauVertex * ); + +typedef void (*nouveau_line_func)( struct nouveau_context*, + nouveauVertex *, + nouveauVertex * ); + +typedef void (*nouveau_point_func)( struct nouveau_context*, + nouveauVertex * ); + +typedef struct nouveau_hw_func_t { + /* Initialise any card-specific non-GL related state */ + GLboolean (*InitCard)(struct nouveau_context *); + /* Update buffer offset/pitch/format */ + GLboolean (*BindBuffers)(struct nouveau_context *, int num_color, + nouveau_renderbuffer **color, + nouveau_renderbuffer *depth); + /* Update anything that depends on the window position/size */ + void (*WindowMoved)(struct nouveau_context *); +} nouveau_hw_func; + +typedef struct nouveau_context { + /* Mesa context */ + GLcontext *glCtx; + + /* The per-context fifo */ + nouveau_fifo fifo; + + /* The read-only regs */ + volatile unsigned char* mmio; + + /* The per-channel notifier block */ + volatile void *notifier_block; + + /* Physical addresses of AGP/VRAM apertures */ + uint64_t vram_phys; + uint64_t vram_size; + uint64_t gart_phys; + uint64_t gart_size; + + /* Channel synchronisation */ + struct drm_nouveau_notifier_alloc *syncNotifier; + + /* ARB_occlusion_query / EXT_timer_query */ + GLuint query_object_max; + GLboolean * query_alloc; + struct drm_nouveau_notifier_alloc *queryNotifier; + + /* Additional hw-specific functions */ + nouveau_hw_func hw_func; + + /* FIXME : do we want to put all state into a separate struct ? */ + /* State for tris */ + GLuint color_offset; + GLuint specular_offset; + + /* Vertex state */ + GLuint vertex_size; + GLubyte *verts; + struct tnl_attr_map vertex_attrs[VERT_ATTRIB_MAX]; + GLuint vertex_attr_count; + + /* Color buffer clear value */ + uint32_t clear_color_value; + + /* Depth/stencil clear value */ + uint32_t clear_value; + + /* Light state */ + GLboolean lighting_enabled; + uint32_t enabled_lights; + + /* Cached state */ + nouveau_state_cache state_cache; + + /* The drawing fallbacks */ + GLuint Fallback; + nouveau_tri_func draw_tri; + nouveau_line_func draw_line; + nouveau_point_func draw_point; + + /* Cliprects information */ + GLuint numClipRects; + drm_clip_rect_t *pClipRects; + drm_clip_rect_t osClipRect; + GLuint drawX, drawY, drawW, drawH; + + /* The rendering context information */ + GLenum current_primitive; /* the current primitive enum */ + DECLARE_RENDERINPUTS(render_inputs_bitset); /* the current render inputs */ + + /* Shader state */ + nvsFunc VPfunc; + nvsFunc FPfunc; + nouveauShader *current_fragprog; + nouveauShader *current_vertprog; + nouveauShader *passthrough_vp; + nouveauShader *passthrough_fp; + + nouveauScreenRec *screen; + struct drm_nouveau_sarea *sarea; + + __DRIcontextPrivate *driContext; /* DRI context */ + __DRIscreenPrivate *driScreen; /* DRI screen */ + __DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */ + GLint lastStamp; + + drm_context_t hHWContext; + drm_hw_lock_t *driHwLock; + int driFd; + + /* Configuration cache */ + driOptionCache optionCache; + + /* vblank stuff */ + uint32_t vblank_flags; + uint32_t vblank_seq; + + GLuint new_state; + GLuint new_render_state; + GLuint render_index; + GLmatrix viewport; + GLfloat depth_scale; + +}nouveauContextRec, *nouveauContextPtr; + + +#define NOUVEAU_CONTEXT(ctx) ((nouveauContextPtr)(ctx->DriverCtx)) + +/* Flags for software fallback cases: */ +#define NOUVEAU_FALLBACK_TEXTURE 0x0001 +#define NOUVEAU_FALLBACK_DRAW_BUFFER 0x0002 +#define NOUVEAU_FALLBACK_READ_BUFFER 0x0004 +#define NOUVEAU_FALLBACK_STENCIL 0x0008 +#define NOUVEAU_FALLBACK_RENDER_MODE 0x0010 +#define NOUVEAU_FALLBACK_LOGICOP 0x0020 +#define NOUVEAU_FALLBACK_SEP_SPECULAR 0x0040 +#define NOUVEAU_FALLBACK_BLEND_EQ 0x0080 +#define NOUVEAU_FALLBACK_BLEND_FUNC 0x0100 +#define NOUVEAU_FALLBACK_PROJTEX 0x0200 +#define NOUVEAU_FALLBACK_DISABLE 0x0400 + + +extern GLboolean nouveauCreateContext( const __GLcontextModes *glVisual, + __DRIcontextPrivate *driContextPriv, + void *sharedContextPrivate ); + +extern void nouveauDestroyContext( __DRIcontextPrivate * ); + +extern GLboolean nouveauMakeCurrent( __DRIcontextPrivate *driContextPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv ); + +extern GLboolean nouveauUnbindContext( __DRIcontextPrivate *driContextPriv ); + +extern void nouveauSwapBuffers(__DRIdrawablePrivate *dPriv); + +extern void nouveauCopySubBuffer(__DRIdrawablePrivate *dPriv, + int x, int y, int w, int h); + +/* Debugging utils: */ +extern int NOUVEAU_DEBUG; + +#define DEBUG_SHADERS 0x00000001 +#define DEBUG_MEM 0x00000002 +#define DEBUG_BUFFEROBJ 0x00000004 + +#endif /* __NOUVEAU_CONTEXT_H__ */ + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.c b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c new file mode 100644 index 0000000000..5eb53aa46c --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_fifo.c @@ -0,0 +1,152 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +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 +on 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 +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "vblank.h" +#include <errno.h> +#include "mtypes.h" +#include "macros.h" +#include "dd.h" +#include "swrast/swrast.h" +#include "nouveau_context.h" +#include "nouveau_msg.h" +#include "nouveau_fifo.h" +#include "nouveau_lock.h" +#include "nouveau_object.h" +#include "nouveau_sync.h" + +#ifdef NOUVEAU_RING_DEBUG +int nouveau_fifo_remaining=0; +#endif + + +#define RING_SKIPS 8 + +void WAIT_RING(nouveauContextPtr nmesa,uint32_t size) +{ +#ifdef NOUVEAU_RING_DEBUG + return; +#endif + uint32_t fifo_get; + while(nmesa->fifo.free < size+1) { + fifo_get = NV_FIFO_READ_GET(); + + if(nmesa->fifo.put >= fifo_get) { + nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; + if(nmesa->fifo.free < size+1) { + OUT_RING(NV03_FIFO_CMD_JUMP | nmesa->fifo.put_base); + if(fifo_get <= RING_SKIPS) { + if(nmesa->fifo.put <= RING_SKIPS) /* corner case - will be idle */ + NV_FIFO_WRITE_PUT(RING_SKIPS + 1); + do { fifo_get = NV_FIFO_READ_GET(); } + while(fifo_get <= RING_SKIPS); + } + NV_FIFO_WRITE_PUT(RING_SKIPS); + nmesa->fifo.current = nmesa->fifo.put = RING_SKIPS; + nmesa->fifo.free = fifo_get - (RING_SKIPS + 1); + } + } else + nmesa->fifo.free = fifo_get - nmesa->fifo.current - 1; + } +} + +/* + * Wait for the channel to be idle + */ +void nouveauWaitForIdleLocked(nouveauContextPtr nmesa) +{ + /* Wait for FIFO idle */ + FIRE_RING(); + while(RING_AHEAD()>0); + + /* Wait on notifier to indicate all commands in the channel have + * been completed. + */ + nouveau_notifier_wait_nop(nmesa->glCtx, nmesa->syncNotifier, NvSub3D); +} + +void nouveauWaitForIdle(nouveauContextPtr nmesa) +{ + LOCK_HARDWARE(nmesa); + nouveauWaitForIdleLocked(nmesa); + UNLOCK_HARDWARE(nmesa); +} + +// here we call the fifo initialization ioctl and fill in stuff accordingly +GLboolean nouveauFifoInit(nouveauContextPtr nmesa) +{ + struct drm_nouveau_fifo_alloc fifo_init; + int i, ret; + +#ifdef NOUVEAU_RING_DEBUG + return GL_TRUE; +#endif + + fifo_init.fb_ctxdma_handle = NvDmaFB; + fifo_init.tt_ctxdma_handle = NvDmaTT; + ret=drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_FIFO_ALLOC, &fifo_init, sizeof(fifo_init)); + if (ret) { + FATAL("Fifo initialization ioctl failed (returned %d)\n",ret); + return GL_FALSE; + } + + ret = drmMap(nmesa->driFd, fifo_init.cmdbuf, fifo_init.cmdbuf_size, &nmesa->fifo.buffer); + if (ret) { + FATAL("Unable to map the fifo (returned %d)\n",ret); + return GL_FALSE; + } + + ret = drmMap(nmesa->driFd, fifo_init.ctrl, fifo_init.ctrl_size, &nmesa->fifo.mmio); + if (ret) { + FATAL("Unable to map the control regs (returned %d)\n",ret); + return GL_FALSE; + } + + ret = drmMap(nmesa->driFd, fifo_init.notifier, + fifo_init.notifier_size, + &nmesa->notifier_block); + if (ret) { + FATAL("Unable to map the notifier block (returned %d)\n",ret); + return GL_FALSE; + } + + /* Setup our initial FIFO tracking params */ + nmesa->fifo.channel = fifo_init.channel; + nmesa->fifo.put_base = fifo_init.put_base; + nmesa->fifo.current = 0; + nmesa->fifo.put = 0; + nmesa->fifo.max = (fifo_init.cmdbuf_size >> 2) - 1; + nmesa->fifo.free = nmesa->fifo.max - nmesa->fifo.current; + + for (i=0; i<RING_SKIPS; i++) + OUT_RING(0); + nmesa->fifo.free -= RING_SKIPS; + + MESSAGE("Fifo init ok. Using context %d\n", fifo_init.channel); + return GL_TRUE; +} + + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_fifo.h b/src/mesa/drivers/dri/nouveau/nouveau_fifo.h new file mode 100644 index 0000000000..67f9cd4fc8 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_fifo.h @@ -0,0 +1,195 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +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 +on 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 +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_FIFO_H__ +#define __NOUVEAU_FIFO_H__ + +#include "nouveau_context.h" +#include "nouveau_ctrlreg.h" +#include "nouveau_state_cache.h" + +//#define NOUVEAU_RING_TRACE +//#define NOUVEAU_RING_DEBUG +//#define NOUVEAU_STATE_CACHE_DISABLE + +#ifndef NOUVEAU_RING_TRACE +#define NOUVEAU_RING_TRACE 0 +#else +#undef NOUVEAU_RING_TRACE +#define NOUVEAU_RING_TRACE 1 +#endif + +#define NV_READ(reg) *(volatile uint32_t *)(nmesa->mmio + (reg)) + +#define NV_FIFO_READ(reg) *(volatile uint32_t *)(nmesa->fifo.mmio + (reg/4)) +#define NV_FIFO_WRITE(reg,value) *(volatile uint32_t *)(nmesa->fifo.mmio + (reg/4)) = value; +#define NV_FIFO_READ_GET() ((NV_FIFO_READ(NV03_FIFO_REGS_DMAGET) - nmesa->fifo.put_base) >> 2) +#define NV_FIFO_WRITE_PUT(val) do { \ + if (NOUVEAU_RING_TRACE) {\ + printf("FIRE_RING : 0x%08x\n", nmesa->fifo.current << 2); \ + fflush(stdout); \ + sleep(1); \ + } \ + NV_FIFO_WRITE(NV03_FIFO_REGS_DMAPUT, ((val)<<2) + nmesa->fifo.put_base); \ +} while(0) + +/* + * Ring/fifo interface + * + * - Begin a ring section with BEGIN_RING_SIZE (if you know the full size in advance) + * - Output stuff to the ring with either OUT_RINGp (outputs a raw mem chunk), OUT_RING (1 uint32_t) or OUT_RINGf (1 float) + * - RING_AVAILABLE returns the available fifo (in uint32_ts) + * - RING_AHEAD returns how much ahead of the last submission point we are + * - FIRE_RING fires whatever we have that wasn't fired before + * - WAIT_RING waits for size (in uint32_ts) to be available in the fifo + */ + +/* Enable for ring debugging. Prints out writes to the ring buffer + * but does not actually write to it. + */ +#ifdef NOUVEAU_RING_DEBUG + +extern int nouveau_fifo_remaining; + +#define OUT_RINGp(ptr,sz) do { \ +uint32_t* p=(uint32_t*)(ptr); \ +int i; printf("OUT_RINGp: (size 0x%x dwords)\n",sz); for(i=0;i<sz;i++) printf(" 0x%08x %f\n", *(p+i), *((float*)(p+i))); \ +nouveau_fifo_remaining-=sz; \ +}while(0) + +#define OUT_RING(n) do { \ + printf("OUT_RINGn: 0x%08x (%s)\n", n, __func__); \ + nouveau_fifo_remaining--; \ +}while(0) + +#define OUT_RINGf(n) do { \ + printf("OUT_RINGf: %.04f (%s)\n", n, __func__); \ + nouveau_fifo_remaining--; \ +}while(0) + +#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ + if (nouveau_fifo_remaining!=0) \ + printf("RING ERROR : remaining %d\n",nouveau_fifo_remaining); \ + nouveau_state_cache_flush(nmesa); \ + if (nmesa->fifo.free <= (size)) \ + WAIT_RING(nmesa,(size)); \ + OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ + nmesa->fifo.free -= ((size) + 1); \ + nouveau_fifo_remaining=size; \ +}while(0) + +#else + +#define OUT_RINGp(ptr,sz) do{ \ + if (NOUVEAU_RING_TRACE) { \ + uint32_t* p=(uint32_t*)(ptr); \ + int i; printf("OUT_RINGp: (size 0x%x dwords) (%s)\n",sz, __func__); for(i=0;i<sz;i++) printf(" [0x%08x] 0x%08x %f\n", (nmesa->fifo.current+i) << 2, *(p+i), *((float*)(p+i))); \ + } \ + memcpy(nmesa->fifo.buffer+nmesa->fifo.current,ptr,(sz)*4); \ + nmesa->fifo.current+=(sz); \ +}while(0) + +#define OUT_RING(n) do { \ +if (NOUVEAU_RING_TRACE) \ + printf("OUT_RINGn: [0x%08x] 0x%08x (%s)\n", nmesa->fifo.current << 2, n, __func__); \ +nmesa->fifo.buffer[nmesa->fifo.current++]=(n); \ +}while(0) + +#define OUT_RINGf(n) do { \ +if (NOUVEAU_RING_TRACE) \ + printf("OUT_RINGf: [0x%08x] %.04f (%s)\n", nmesa->fifo.current << 2, n, __func__); \ +*((float*)(nmesa->fifo.buffer+nmesa->fifo.current++))=(n); \ +}while(0) + +#define BEGIN_RING_SIZE(subchannel,tag,size) do { \ + nouveau_state_cache_flush(nmesa); \ + if (nmesa->fifo.free <= (size)) \ + WAIT_RING(nmesa,(size)); \ + OUT_RING( ((size)<<18) | ((subchannel) << 13) | (tag)); \ + nmesa->fifo.free -= ((size) + 1); \ +}while(0) + +#endif + +extern void WAIT_RING(nouveauContextPtr nmesa,uint32_t size); +extern void nouveau_state_cache_flush(nouveauContextPtr nmesa); +extern void nouveau_state_cache_init(nouveauContextPtr nmesa); + +#ifdef NOUVEAU_STATE_CACHE_DISABLE +#define BEGIN_RING_CACHE(subc,tag,size) BEGIN_RING_SIZE((subc), (tag), (size)) +#define OUT_RING_CACHE(n) OUT_RING((n)) +#define OUT_RING_CACHEf(n) OUT_RINGf((n)) +#define OUT_RING_CACHEp(ptr, sz) OUT_RINGp((ptr), (sz)) +#else +#define BEGIN_RING_CACHE(subchannel,tag,size) do { \ + nmesa->state_cache.dirty=1; \ + nmesa->state_cache.current_pos=((tag)/4); \ +}while(0) + +#define OUT_RING_CACHE(n) do { \ + if (nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value!=(n)) { \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ + nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value=(n); \ + } \ + nmesa->state_cache.current_pos++; \ +}while(0) + +#define OUT_RING_CACHEf(n) do { \ + if ((*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))!=(n)){ \ + nmesa->state_cache.atoms[nmesa->state_cache.current_pos].dirty=1; \ + nmesa->state_cache.hdirty[nmesa->state_cache.current_pos/NOUVEAU_STATE_CACHE_HIER_SIZE]=1; \ + (*(float*)(&nmesa->state_cache.atoms[nmesa->state_cache.current_pos].value))=(n);\ + } \ + nmesa->state_cache.current_pos++; \ +}while(0) + +#define OUT_RING_CACHEp(ptr,sz) do { \ +uint32_t* p=(uint32_t*)(ptr); \ +int i; for(i=0;i<sz;i++) OUT_RING_CACHE(*(p+i)); \ +}while(0) +#endif + +#define RING_AVAILABLE() (nmesa->fifo.free-1) + +#define RING_AHEAD() ((nmesa->fifo.put<=nmesa->fifo.current)?(nmesa->fifo.current-nmesa->fifo.put):nmesa->fifo.max-nmesa->fifo.put+nmesa->fifo.current) + +#define FIRE_RING() do { \ + if (nmesa->fifo.current!=nmesa->fifo.put) { \ + nmesa->fifo.put=nmesa->fifo.current; \ + NV_FIFO_WRITE_PUT(nmesa->fifo.put); \ + } \ +}while(0) + +extern void nouveauWaitForIdle(nouveauContextPtr nmesa); +extern void nouveauWaitForIdleLocked(nouveauContextPtr nmesa); +extern GLboolean nouveauFifoInit(nouveauContextPtr nmesa); + +#endif /* __NOUVEAU_FIFO_H__ */ + + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.c b/src/mesa/drivers/dri/nouveau/nouveau_screen.c new file mode 100644 index 0000000000..2cf6f979e4 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.c @@ -0,0 +1,382 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +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 +on 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 +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 "glheader.h" +#include "imports.h" +#include "mtypes.h" +#include "framebuffer.h" +#include "renderbuffer.h" + +#include "nouveau_context.h" +#include "nouveau_screen.h" +#include "nouveau_object.h" +#include "nouveau_span.h" + +#include "utils.h" +#include "context.h" +#include "vblank.h" +#include "drirenderbuffer.h" + +#include "GL/internal/dri_interface.h" + +#include "xmlpool.h" + +PUBLIC const char __driConfigOptions[] = +DRI_CONF_BEGIN + DRI_CONF_SECTION_DEBUG + DRI_CONF_NO_RAST(false) + DRI_CONF_SECTION_END +DRI_CONF_END; +static const GLuint __driNConfigOptions = 1; + +extern const struct dri_extension common_extensions[]; +extern const struct dri_extension nv10_extensions[]; +extern const struct dri_extension nv20_extensions[]; +extern const struct dri_extension nv30_extensions[]; +extern const struct dri_extension nv40_extensions[]; +extern const struct dri_extension nv50_extensions[]; + +static nouveauScreenPtr nouveauCreateScreen(__DRIscreenPrivate *sPriv) +{ + nouveauScreenPtr screen; + NOUVEAUDRIPtr dri_priv=(NOUVEAUDRIPtr)sPriv->pDevPriv; + + /* allocate screen */ + screen = (nouveauScreenPtr) CALLOC( sizeof(*screen) ); + if ( !screen ) { + __driUtilMessage("%s: Could not allocate memory for screen structure",__FUNCTION__); + return NULL; + } + + screen->card=nouveau_card_lookup(dri_priv->device_id); + if (!screen->card) { + __driUtilMessage("%s: Unknown card type 0x%04x:0x%04x\n", + __func__, dri_priv->device_id >> 16, dri_priv->device_id & 0xFFFF); + FREE(screen); + return NULL; + } + + /* parse information in __driConfigOptions */ + driParseOptionInfo (&screen->optionCache,__driConfigOptions, __driNConfigOptions); + + screen->fbFormat = dri_priv->bpp / 8; + screen->frontOffset = dri_priv->front_offset; + screen->frontPitch = dri_priv->front_pitch; + screen->backOffset = dri_priv->back_offset; + screen->backPitch = dri_priv->back_pitch; + screen->depthOffset = dri_priv->depth_offset; + screen->depthPitch = dri_priv->depth_pitch; + + screen->driScreen = sPriv; + return screen; +} + +static void +nouveauDestroyScreen(__DRIscreenPrivate *sPriv) +{ + nouveauScreenPtr screen = (nouveauScreenPtr)sPriv->private; + + if (!screen) return; + + /* free all option information */ + driDestroyOptionInfo (&screen->optionCache); + + FREE(screen); + sPriv->private = NULL; +} + +static GLboolean nouveauInitDriver(__DRIscreenPrivate *sPriv) +{ + sPriv->private = (void *) nouveauCreateScreen( sPriv ); + if ( !sPriv->private ) { + nouveauDestroyScreen( sPriv ); + return GL_FALSE; + } + + return GL_TRUE; +} + +/** + * Create the Mesa framebuffer and renderbuffers for a given window/drawable. + * + * \todo This function (and its interface) will need to be updated to support + * pbuffers. + */ +static GLboolean +nouveauCreateBuffer(__DRIscreenPrivate *driScrnPriv, + __DRIdrawablePrivate *driDrawPriv, + const __GLcontextModes *mesaVis, + GLboolean isPixmap) +{ + nouveauScreenPtr screen = (nouveauScreenPtr) driScrnPriv->private; + nouveau_renderbuffer *nrb; + struct gl_framebuffer *fb; + const GLboolean swAccum = mesaVis->accumRedBits > 0; + const GLboolean swStencil = mesaVis->stencilBits > 0 && mesaVis->depthBits != 24; + GLenum color_format = screen->fbFormat == 4 ? GL_RGBA8 : GL_RGB5; + + if (isPixmap) + return GL_FALSE; /* not implemented */ + + fb = _mesa_create_framebuffer(mesaVis); + if (!fb) + return GL_FALSE; + + /* Front buffer */ + nrb = nouveau_renderbuffer_new(color_format, + driScrnPriv->pFB + screen->frontOffset, + screen->frontOffset, + screen->frontPitch * screen->fbFormat, + driDrawPriv); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_FRONT_LEFT, &nrb->mesa); + + if (0 /* unified buffers if we choose to support them.. */) { + } else { + if (mesaVis->doubleBufferMode) { + nrb = nouveau_renderbuffer_new(color_format, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_BACK_LEFT, &nrb->mesa); + } + + if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { + nrb = nouveau_renderbuffer_new(GL_DEPTH24_STENCIL8_EXT, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + _mesa_add_renderbuffer(fb, BUFFER_STENCIL, &nrb->mesa); + } else if (mesaVis->depthBits == 24) { + nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT24, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + } else if (mesaVis->depthBits == 16) { + nrb = nouveau_renderbuffer_new(GL_DEPTH_COMPONENT16, NULL, + 0, 0, + NULL); + nouveauSpanSetFunctions(nrb, mesaVis); + _mesa_add_renderbuffer(fb, BUFFER_DEPTH, &nrb->mesa); + } + } + + _mesa_add_soft_renderbuffers(fb, + GL_FALSE, /* color */ + GL_FALSE, /* depth */ + swStencil, + swAccum, + GL_FALSE, /* alpha */ + GL_FALSE /* aux */); + + driDrawPriv->driverPrivate = (void *) fb; + return (driDrawPriv->driverPrivate != NULL); +} + + +static void +nouveauDestroyBuffer(__DRIdrawablePrivate *driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + +static int +nouveauGetSwapInfo(__DRIdrawablePrivate *dpriv, __DRIswapInfo *sInfo) +{ + return -1; +} + +static const struct __DriverAPIRec nouveauAPI = { + .InitDriver = nouveauInitDriver, + .DestroyScreen = nouveauDestroyScreen, + .CreateContext = nouveauCreateContext, + .DestroyContext = nouveauDestroyContext, + .CreateBuffer = nouveauCreateBuffer, + .DestroyBuffer = nouveauDestroyBuffer, + .SwapBuffers = nouveauSwapBuffers, + .MakeCurrent = nouveauMakeCurrent, + .UnbindContext = nouveauUnbindContext, + .GetSwapInfo = nouveauGetSwapInfo, + .GetMSC = driGetMSC32, + .WaitForMSC = driWaitForMSC32, + .WaitForSBC = NULL, + .SwapBuffersMSC = NULL, + .CopySubBuffer = nouveauCopySubBuffer +}; + + +static __GLcontextModes * +nouveauFillInModes( unsigned pixel_bits, unsigned depth_bits, + unsigned stencil_bits, GLboolean have_back_buffer ) +{ + __GLcontextModes * modes; + __GLcontextModes * m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + int i; + + static const struct { + GLenum format; + GLenum type; + } fb_format_array[] = { + { GL_RGB , GL_UNSIGNED_SHORT_5_6_5 }, + { GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV }, + { GL_BGR , GL_UNSIGNED_INT_8_8_8_8_REV }, + }; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + uint8_t depth_bits_array[4] = { 0, 16, 24, 24 }; + uint8_t stencil_bits_array[4] = { 0, 0, 0, 8 }; + + depth_buffer_factor = 4; + back_buffer_factor = (have_back_buffer) ? 3 : 1; + + num_modes = ((pixel_bits==16) ? 1 : 2) * + depth_buffer_factor * back_buffer_factor * 4; + modes = (*dri_interface->createContextModes)(num_modes, + sizeof(__GLcontextModes)); + m = modes; + + for (i=((pixel_bits==16)?0:1);i<((pixel_bits==16)?1:3);i++) { + if (!driFillInModes(&m, fb_format_array[i].format, + fb_format_array[i].type, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + GLX_TRUE_COLOR)) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + + if (!driFillInModes(&m, fb_format_array[i].format, + fb_format_array[i].type, + depth_bits_array, + stencil_bits_array, + depth_buffer_factor, + back_buffer_modes, + back_buffer_factor, + GLX_DIRECT_COLOR)) { + fprintf( stderr, "[%s:%u] Error creating FBConfig!\n", + __func__, __LINE__ ); + return NULL; + } + } + + return modes; +} + + +/** + * This is the bootstrap function for the driver. libGL supplies all of the + * requisite information about the system, and the driver initializes itself. + * This routine also fills in the linked list pointed to by \c driver_modes + * with the \c __GLcontextModes that the driver can support for windows or + * pbuffers. + * + * \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on + * failure. + */ +PUBLIC +void * __driCreateNewScreen_20050727( __DRInativeDisplay *dpy, int scrn, __DRIscreen *psc, + const __GLcontextModes * modes, + const __DRIversion * ddx_version, + const __DRIversion * dri_version, + const __DRIversion * drm_version, + const __DRIframebuffer * frame_buffer, + drmAddress pSAREA, int fd, + int internal_api_version, + const __DRIinterfaceMethods * interface, + __GLcontextModes ** driver_modes) + +{ + __DRIscreenPrivate *psp; + static const __DRIversion ddx_expected = { 1, 2, 0 }; + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 0, 0, NOUVEAU_DRM_HEADER_PATCHLEVEL }; +#if NOUVEAU_DRM_HEADER_PATCHLEVEL != 9 +#error nouveau_drm.h version doesn't match expected version +#endif + dri_interface = interface; + + if (!driCheckDriDdxDrmVersions2("nouveau", + dri_version, & dri_expected, + ddx_version, & ddx_expected, + drm_version, & drm_expected)) { + return NULL; + } + + // temporary lock step versioning + if (drm_expected.patch!=drm_version->patch) { + __driUtilMessage("%s: wrong DRM version, expected %d, got %d\n", + __func__, + drm_expected.patch, drm_version->patch); + return NULL; + } + + psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL, + ddx_version, dri_version, drm_version, + frame_buffer, pSAREA, fd, + internal_api_version, &nouveauAPI); + if ( psp != NULL ) { + NOUVEAUDRIPtr dri_priv = (NOUVEAUDRIPtr)psp->pDevPriv; + + *driver_modes = nouveauFillInModes(dri_priv->bpp, + (dri_priv->bpp == 16) ? 16 : 24, + (dri_priv->bpp == 16) ? 0 : 8, + 1 + ); + + /* Calling driInitExtensions here, with a NULL context pointer, does not actually + * enable the extensions. It just makes sure that all the dispatch offsets for all + * the extensions that *might* be enables are known. This is needed because the + * dispatch offsets need to be known when _mesa_context_create is called, but we can't + * enable the extensions until we have a context pointer. + * + * Hello chicken. Hello egg. How are you two today? + */ + driInitExtensions( NULL, common_extensions, GL_FALSE ); + driInitExtensions( NULL, nv10_extensions, GL_FALSE ); + driInitExtensions( NULL, nv10_extensions, GL_FALSE ); + driInitExtensions( NULL, nv30_extensions, GL_FALSE ); + driInitExtensions( NULL, nv40_extensions, GL_FALSE ); + driInitExtensions( NULL, nv50_extensions, GL_FALSE ); + } + + return (void *) psp; +} + diff --git a/src/mesa/drivers/dri/nouveau/nouveau_screen.h b/src/mesa/drivers/dri/nouveau/nouveau_screen.h new file mode 100644 index 0000000000..bbe5810128 --- /dev/null +++ b/src/mesa/drivers/dri/nouveau/nouveau_screen.h @@ -0,0 +1,61 @@ +/************************************************************************** + +Copyright 2006 Stephane Marchesin +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 +on 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 +ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 __NOUVEAU_SCREEN_H__ +#define __NOUVEAU_SCREEN_H__ + +#include "xmlconfig.h" + +#include "nouveau_dri.h" +#include "nouveau_card.h" + +typedef struct { + nouveau_card* card; + uint32_t bus_type; + uint32_t agp_mode; + + GLint fbFormat; + + GLuint frontOffset; + GLuint frontPitch; + GLuint backOffset; + GLuint backPitch; + + GLuint depthOffset; + GLuint depthPitch; + GLuint spanOffset; + + __DRIscreenPrivate *driScreen; + unsigned int sarea_priv_offset; + + /* Configuration cache with default values for all contexts */ + driOptionCache optionCache; + +} nouveauScreenRec, *nouveauScreenPtr; + + +#endif /* __NOUVEAU_SCREEN_H__ */ |