diff options
Diffstat (limited to 'src/mesa/drivers/dri/i915')
-rw-r--r--[l---------] | src/mesa/drivers/dri/i915/intel_ioctl.c | 660 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915/intel_ioctl.h | 72 | ||||
-rw-r--r--[l---------] | src/mesa/drivers/dri/i915/intel_screen.c | 691 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915/server/i830_common.h | 211 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i915/server/i830_dri.h | 72 |
5 files changed, 1704 insertions, 2 deletions
diff --git a/src/mesa/drivers/dri/i915/intel_ioctl.c b/src/mesa/drivers/dri/i915/intel_ioctl.c index effd0f378d..aa7c6d106c 120000..100644 --- a/src/mesa/drivers/dri/i915/intel_ioctl.c +++ b/src/mesa/drivers/dri/i915/intel_ioctl.c @@ -1 +1,659 @@ -../intel/intel_ioctl.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 <stdio.h> +#include <unistd.h> +#include <errno.h> +#include <sched.h> + +#include "mtypes.h" +#include "context.h" +#include "swrast/swrast.h" + +#include "intel_context.h" +#include "intel_ioctl.h" +#include "intel_batchbuffer.h" +#include "drm.h" + +uint32_t intelGetLastFrame (intelContextPtr intel) +{ + int ret; + uint32_t frame; + drm_i915_getparam_t gp; + + gp.param = I915_PARAM_LAST_DISPATCH; + gp.value = (int *)&frame; + ret = drmCommandWriteRead( intel->driFd, DRM_I915_GETPARAM, + &gp, sizeof(gp) ); + return frame; +} + +int intelEmitIrqLocked( intelContextPtr intel ) +{ + drmI830IrqEmit ie; + int ret, seq; + + assert(((*(int *)intel->driHwLock) & ~DRM_LOCK_CONT) == + (DRM_LOCK_HELD|intel->hHWContext)); + + ie.irq_seq = &seq; + + ret = drmCommandWriteRead( intel->driFd, DRM_I830_IRQ_EMIT, + &ie, sizeof(ie) ); + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret ); + exit(1); + } + + if (0) + fprintf(stderr, "%s --> %d\n", __FUNCTION__, seq ); + + return seq; +} + +void intelWaitIrq( intelContextPtr intel, int seq ) +{ + int ret; + + if (0) + fprintf(stderr, "%s %d\n", __FUNCTION__, seq ); + + intel->iw.irq_seq = seq; + + do { + ret = drmCommandWrite( intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, sizeof(intel->iw) ); + } while (ret == -EAGAIN || ret == -EINTR); + + if ( ret ) { + fprintf( stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret ); + if (0) + intel_dump_batchbuffer( intel->alloc.offset, + intel->alloc.ptr, + intel->alloc.size ); + exit(1); + } +} + + + +static void age_intel( intelContextPtr intel, int age ) +{ + GLuint i; + + for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) + if (intel->CurrentTexObj[i]) + intel->CurrentTexObj[i]->age = age; +} + +void intel_dump_batchbuffer( long offset, + int *ptr, + int count ) +{ + int i; + fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count); + for (i = 0; i < count/4; i += 4) + fprintf(stderr, "\t0x%x: 0x%08x 0x%08x 0x%08x 0x%08x\n", + (unsigned int)offset + i*4, ptr[i], ptr[i+1], ptr[i+2], ptr[i+3]); + fprintf(stderr, "END BATCH\n\n\n"); +} + +void intelRefillBatchLocked( intelContextPtr intel, GLboolean allow_unlock ) +{ + GLuint last_irq = intel->alloc.irq_emitted; + GLuint half = intel->alloc.size / 2; + GLuint buf = (intel->alloc.active_buf ^= 1); + + intel->alloc.irq_emitted = intelEmitIrqLocked( intel ); + + if (last_irq) { + if (allow_unlock) UNLOCK_HARDWARE( intel ); + intelWaitIrq( intel, last_irq ); + if (allow_unlock) LOCK_HARDWARE( intel ); + } + + if (0) + fprintf(stderr, "%s: now using half %d\n", __FUNCTION__, buf); + + intel->batch.start_offset = intel->alloc.offset + buf * half; + intel->batch.ptr = (unsigned char *)intel->alloc.ptr + buf * half; + intel->batch.size = half - 8; + intel->batch.space = half - 8; + assert(intel->batch.space >= 0); +} + +#define MI_BATCH_BUFFER_END (0xA<<23) + + +void intelFlushBatchLocked( intelContextPtr intel, + GLboolean ignore_cliprects, + GLboolean refill, + GLboolean allow_unlock) +{ + drmI830BatchBuffer batch; + + assert(intel->locked); + + if (0) + fprintf(stderr, "%s used %d of %d offset %x..%x refill %d (started in %s)\n", + __FUNCTION__, + (intel->batch.size - intel->batch.space), + intel->batch.size, + intel->batch.start_offset, + intel->batch.start_offset + + (intel->batch.size - intel->batch.space), + refill, + intel->batch.func); + + /* Throw away non-effective packets. Won't work once we have + * hardware contexts which would preserve statechanges beyond a + * single buffer. + */ + if (intel->numClipRects == 0 && !ignore_cliprects) { + + /* Without this yeild, an application with no cliprects can hog + * the hardware. Without unlocking, the effect is much worse - + * effectively a lock-out of other contexts. + */ + if (allow_unlock) { + UNLOCK_HARDWARE( intel ); + sched_yield(); + LOCK_HARDWARE( intel ); + } + + /* Note that any state thought to have been emitted actually + * hasn't: + */ + intel->batch.ptr -= (intel->batch.size - intel->batch.space); + intel->batch.space = intel->batch.size; + intel->vtbl.lost_hardware( intel ); + } + + if (intel->batch.space != intel->batch.size) { + + if (intel->sarea->ctxOwner != intel->hHWContext) { + intel->perf_boxes |= I830_BOX_LOST_CONTEXT; + intel->sarea->ctxOwner = intel->hHWContext; + } + + batch.start = intel->batch.start_offset; + batch.used = intel->batch.size - intel->batch.space; + batch.cliprects = intel->pClipRects; + batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; + batch.DR1 = 0; + batch.DR4 = ((((GLuint)intel->drawX) & 0xffff) | + (((GLuint)intel->drawY) << 16)); + + if (intel->alloc.offset) { + if ((batch.used & 0x4) == 0) { + ((int *)intel->batch.ptr)[0] = 0; + ((int *)intel->batch.ptr)[1] = MI_BATCH_BUFFER_END; + batch.used += 0x8; + intel->batch.ptr += 0x8; + } + else { + ((int *)intel->batch.ptr)[0] = MI_BATCH_BUFFER_END; + batch.used += 0x4; + intel->batch.ptr += 0x4; + } + } + + if (0) + intel_dump_batchbuffer( batch.start, + (int *)(intel->batch.ptr - batch.used), + batch.used ); + + intel->batch.start_offset += batch.used; + intel->batch.size -= batch.used; + + if (intel->batch.size < 8) { + refill = GL_TRUE; + intel->batch.space = intel->batch.size = 0; + } + else { + intel->batch.size -= 8; + intel->batch.space = intel->batch.size; + } + + + assert(intel->batch.space >= 0); + assert(batch.start >= intel->alloc.offset); + assert(batch.start < intel->alloc.offset + intel->alloc.size); + assert(batch.start + batch.used > intel->alloc.offset); + assert(batch.start + batch.used <= + intel->alloc.offset + intel->alloc.size); + + + if (intel->alloc.offset) { + if (drmCommandWrite (intel->driFd, DRM_I830_BATCHBUFFER, &batch, + sizeof(batch))) { + fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno); + UNLOCK_HARDWARE(intel); + exit(1); + } + } else { + drmI830CmdBuffer cmd; + cmd.buf = (char *)intel->alloc.ptr + batch.start; + cmd.sz = batch.used; + cmd.DR1 = batch.DR1; + cmd.DR4 = batch.DR4; + cmd.num_cliprects = batch.num_cliprects; + cmd.cliprects = batch.cliprects; + + if (drmCommandWrite (intel->driFd, DRM_I830_CMDBUFFER, &cmd, + sizeof(cmd))) { + fprintf(stderr, "DRM_I830_CMDBUFFER: %d\n", -errno); + UNLOCK_HARDWARE(intel); + exit(1); + } + } + + + age_intel(intel, intel->sarea->last_enqueue); + + /* FIXME: use hardware contexts to avoid 'losing' hardware after + * each buffer flush. + */ + if (intel->batch.contains_geometry) + assert(intel->batch.last_emit_state == intel->batch.counter); + + intel->batch.counter++; + intel->batch.contains_geometry = 0; + intel->batch.func = 0; + intel->vtbl.lost_hardware( intel ); + } + + if (refill) + intelRefillBatchLocked( intel, allow_unlock ); +} + +void intelFlushBatch( intelContextPtr intel, GLboolean refill ) +{ + if (intel->locked) { + intelFlushBatchLocked( intel, GL_FALSE, refill, GL_FALSE ); + } + else { + LOCK_HARDWARE(intel); + intelFlushBatchLocked( intel, GL_FALSE, refill, GL_TRUE ); + UNLOCK_HARDWARE(intel); + } +} + + +void intelWaitForIdle( intelContextPtr intel ) +{ + if (0) + fprintf(stderr, "%s\n", __FUNCTION__); + + intel->vtbl.emit_flush( intel ); + intelFlushBatch( intel, GL_TRUE ); + + /* Use an irq to wait for dma idle -- Need to track lost contexts + * to shortcircuit consecutive calls to this function: + */ + intelWaitIrq( intel, intel->alloc.irq_emitted ); + intel->alloc.irq_emitted = 0; +} + + +/** + * Check if we need to rotate/warp the front color buffer to the + * rotated screen. We generally need to do this when we get a glFlush + * or glFinish after drawing to the front color buffer. + */ +static void +intelCheckFrontRotate(GLcontext *ctx) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { + intelScreenPrivate *screen = intel->intelScreen; + if (screen->current_rotation != 0) { + __DRIdrawablePrivate *dPriv = intel->driDrawable; + intelRotateWindow(intel, dPriv, BUFFER_BIT_FRONT_LEFT); + } + } +} + + +/** + * NOT directly called via glFlush. + */ +void intelFlush( GLcontext *ctx ) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + + if (intel->Fallback) + _swrast_flush( ctx ); + + INTEL_FIREVERTICES( intel ); + + if (intel->batch.size != intel->batch.space) + intelFlushBatch( intel, GL_FALSE ); +} + + +/** + * Called via glFlush. + */ +void intelglFlush( GLcontext *ctx ) +{ + intelFlush(ctx); + intelCheckFrontRotate(ctx); +} + + +void intelFinish( GLcontext *ctx ) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + intelFlush( ctx ); + intelWaitForIdle( intel ); + intelCheckFrontRotate(ctx); +} + + +void intelClear(GLcontext *ctx, GLbitfield mask) +{ + intelContextPtr intel = INTEL_CONTEXT( ctx ); + const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); + GLbitfield tri_mask = 0; + GLbitfield blit_mask = 0; + GLbitfield swrast_mask = 0; + + if (0) + fprintf(stderr, "%s\n", __FUNCTION__); + + /* Take care of cliprects, which are handled differently for + * clears, etc. + */ + intelFlush( &intel->ctx ); + + if (mask & BUFFER_BIT_FRONT_LEFT) { + if (colorMask == ~0) { + blit_mask |= BUFFER_BIT_FRONT_LEFT; + } + else { + tri_mask |= BUFFER_BIT_FRONT_LEFT; + } + } + + if (mask & BUFFER_BIT_BACK_LEFT) { + if (colorMask == ~0) { + blit_mask |= BUFFER_BIT_BACK_LEFT; + } + else { + tri_mask |= BUFFER_BIT_BACK_LEFT; + } + } + + if (mask & BUFFER_BIT_DEPTH) { + blit_mask |= BUFFER_BIT_DEPTH; + } + + if (mask & BUFFER_BIT_STENCIL) { + if (!intel->hw_stencil) { + swrast_mask |= BUFFER_BIT_STENCIL; + } + else if ((ctx->Stencil.WriteMask[0] & 0xff) != 0xff) { + tri_mask |= BUFFER_BIT_STENCIL; + } + else { + blit_mask |= BUFFER_BIT_STENCIL; + } + } + + swrast_mask |= (mask & BUFFER_BIT_ACCUM); + + if (blit_mask) + intelClearWithBlit( ctx, blit_mask, 0, 0, 0, 0, 0); + + if (tri_mask) + intel->vtbl.clear_with_tris( intel, tri_mask, 0, 0, 0, 0, 0); + + if (swrast_mask) + _swrast_Clear( ctx, swrast_mask ); +} + + +void +intelRotateWindow(intelContextPtr intel, __DRIdrawablePrivate *dPriv, + GLuint srcBuffer) +{ + if (intel->vtbl.rotate_window) { + intel->vtbl.rotate_window(intel, dPriv, srcBuffer); + } +} + + +void *intelAllocateAGP( intelContextPtr intel, GLsizei size ) +{ + int region_offset; + drmI830MemAlloc alloc; + int ret; + + if (0) + fprintf(stderr, "%s: %d bytes\n", __FUNCTION__, size); + + alloc.region = I830_MEM_REGION_AGP; + alloc.alignment = 0; + alloc.size = size; + alloc.region_offset = ®ion_offset; + + LOCK_HARDWARE(intel); + + /* Make sure the global heap is initialized + */ + if (intel->texture_heaps[0]) + driAgeTextures( intel->texture_heaps[0] ); + + + ret = drmCommandWriteRead( intel->driFd, + DRM_I830_ALLOC, + &alloc, sizeof(alloc)); + + if (ret) { + fprintf(stderr, "%s: DRM_I830_ALLOC ret %d\n", __FUNCTION__, ret); + UNLOCK_HARDWARE(intel); + return NULL; + } + + if (0) + fprintf(stderr, "%s: allocated %d bytes\n", __FUNCTION__, size); + + /* Need to propogate this information (agp memory in use) to our + * local texture lru. The kernel has already updated the global + * lru. An alternative would have been to allocate memory the + * usual way and then notify the kernel to pin the allocation. + */ + if (intel->texture_heaps[0]) + driAgeTextures( intel->texture_heaps[0] ); + + UNLOCK_HARDWARE(intel); + + return (void *)((char *)intel->intelScreen->tex.map + region_offset); +} + +void intelFreeAGP( intelContextPtr intel, void *pointer ) +{ + int region_offset; + drmI830MemFree memfree; + int ret; + + region_offset = (char *)pointer - (char *)intel->intelScreen->tex.map; + + if (region_offset < 0 || + region_offset > intel->intelScreen->tex.size) { + fprintf(stderr, "offset %d outside range 0..%d\n", region_offset, + intel->intelScreen->tex.size); + return; + } + + memfree.region = I830_MEM_REGION_AGP; + memfree.region_offset = region_offset; + + ret = drmCommandWrite( intel->driFd, + DRM_I830_FREE, + &memfree, sizeof(memfree)); + + if (ret) + fprintf(stderr, "%s: DRM_I830_FREE ret %d\n", __FUNCTION__, ret); +} + +/* This version of AllocateMemoryMESA allocates only agp memory, and + * only does so after the point at which the driver has been + * initialized. + * + * Theoretically a valid context isn't required. However, in this + * implementation, it is, as I'm using the hardware lock to protect + * the kernel data structures, and the current context to get the + * device fd. + */ +void *intelAllocateMemoryMESA(__DRInativeDisplay *dpy, int scrn, + GLsizei size, GLfloat readfreq, + GLfloat writefreq, GLfloat priority) +{ + GET_CURRENT_CONTEXT(ctx); + + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s sz %d %f/%f/%f\n", __FUNCTION__, size, readfreq, + writefreq, priority); + + if (getenv("INTEL_NO_ALLOC")) + return NULL; + + if (!ctx || INTEL_CONTEXT(ctx) == 0) + return NULL; + + return intelAllocateAGP( INTEL_CONTEXT(ctx), size ); +} + + +/* Called via glXFreeMemoryMESA() */ +void intelFreeMemoryMESA(__DRInativeDisplay *dpy, int scrn, GLvoid *pointer) +{ + GET_CURRENT_CONTEXT(ctx); + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s %p\n", __FUNCTION__, pointer); + + if (!ctx || INTEL_CONTEXT(ctx) == 0) { + fprintf(stderr, "%s: no context\n", __FUNCTION__); + return; + } + + intelFreeAGP( INTEL_CONTEXT(ctx), pointer ); +} + +/* Called via glXGetMemoryOffsetMESA() + * + * Returns offset of pointer from the start of agp aperture. + */ +GLuint intelGetMemoryOffsetMESA(__DRInativeDisplay *dpy, int scrn, + const GLvoid *pointer) +{ + GET_CURRENT_CONTEXT(ctx); + intelContextPtr intel; + + if (!ctx || !(intel = INTEL_CONTEXT(ctx)) ) { + fprintf(stderr, "%s: no context\n", __FUNCTION__); + return ~0; + } + + if (!intelIsAgpMemory( intel, pointer, 0 )) + return ~0; + + return intelAgpOffsetFromVirtual( intel, pointer ); +} + + +GLboolean intelIsAgpMemory( intelContextPtr intel, const GLvoid *pointer, + GLint size ) +{ + int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; + int valid = (size >= 0 && + offset >= 0 && + offset + size < intel->intelScreen->tex.size); + + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "intelIsAgpMemory( %p ) : %d\n", pointer, valid ); + + return valid; +} + + +GLuint intelAgpOffsetFromVirtual( intelContextPtr intel, const GLvoid *pointer ) +{ + int offset = (char *)pointer - (char *)intel->intelScreen->tex.map; + + if (offset < 0 || offset > intel->intelScreen->tex.size) + return ~0; + else + return intel->intelScreen->tex.offset + offset; +} + + + + + +/* Flip the front & back buffes + */ +void intelPageFlip( const __DRIdrawablePrivate *dPriv ) +{ +#if 0 + intelContextPtr intel; + int tmp, ret; + + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate; + + intelFlush( &intel->ctx ); + LOCK_HARDWARE( intel ); + + if (dPriv->pClipRects) { + *(drm_clip_rect_t *)intel->sarea->boxes = dPriv->pClipRects[0]; + intel->sarea->nbox = 1; + } + + ret = drmCommandNone(intel->driFd, DRM_I830_FLIP); + if (ret) { + fprintf(stderr, "%s: %d\n", __FUNCTION__, ret); + UNLOCK_HARDWARE( intel ); + exit(1); + } + + tmp = intel->sarea->last_enqueue; + intelRefillBatchLocked( intel ); + UNLOCK_HARDWARE( intel ); + + + intelSetDrawBuffer( &intel->ctx, intel->ctx.Color.DriverDrawBuffer ); +#endif +} 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 |