summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/dri
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/dri')
-rw-r--r--src/gallium/winsys/dri/intel/Makefile38
-rw-r--r--src/gallium/winsys/dri/intel/SConscript41
-rw-r--r--src/gallium/winsys/dri/intel/intel_batchbuffer.c357
-rw-r--r--src/gallium/winsys/dri/intel/intel_batchbuffer.h149
-rw-r--r--src/gallium/winsys/dri/intel/intel_batchpool.c424
-rw-r--r--src/gallium/winsys/dri/intel/intel_batchpool.h37
-rw-r--r--src/gallium/winsys/dri/intel/intel_context.c304
-rw-r--r--src/gallium/winsys/dri/intel/intel_context.h158
-rw-r--r--src/gallium/winsys/dri/intel/intel_lock.c102
-rw-r--r--src/gallium/winsys/dri/intel/intel_reg.h53
-rw-r--r--src/gallium/winsys/dri/intel/intel_screen.c537
-rw-r--r--src/gallium/winsys/dri/intel/intel_screen.h113
-rw-r--r--src/gallium/winsys/dri/intel/intel_swapbuffers.c253
-rw-r--r--src/gallium/winsys/dri/intel/intel_swapbuffers.h47
-rw-r--r--src/gallium/winsys/dri/intel/intel_winsys.h73
-rw-r--r--src/gallium/winsys/dri/intel/intel_winsys_i915.c154
-rw-r--r--src/gallium/winsys/dri/intel/intel_winsys_pipe.c302
-rw-r--r--src/gallium/winsys/dri/intel/intel_winsys_softpipe.c81
-rw-r--r--src/gallium/winsys/dri/intel/server/i830_common.h226
-rw-r--r--src/gallium/winsys/dri/intel/server/i830_dri.h63
-rw-r--r--src/gallium/winsys/dri/intel/server/intel.h331
-rw-r--r--src/gallium/winsys/dri/intel/server/intel_dri.c1306
22 files changed, 5149 insertions, 0 deletions
diff --git a/src/gallium/winsys/dri/intel/Makefile b/src/gallium/winsys/dri/intel/Makefile
new file mode 100644
index 00000000000..9ae0f013256
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/Makefile
@@ -0,0 +1,38 @@
+
+TOP = ../../../../..
+include $(TOP)/configs/current
+
+LIBNAME = i915tex_dri.so
+
+MINIGLX_SOURCES = server/intel_dri.c
+
+PIPE_DRIVERS = \
+ $(TOP)/src/mesa/pipe/softpipe/libsoftpipe.a \
+ $(TOP)/src/mesa/pipe/i915simple/libi915simple.a
+
+DRIVER_SOURCES = \
+ intel_winsys_pipe.c \
+ intel_winsys_softpipe.c \
+ intel_winsys_i915.c \
+ intel_batchbuffer.c \
+ intel_swapbuffers.c \
+ intel_context.c \
+ intel_lock.c \
+ intel_screen.c \
+ intel_batchpool.c
+
+C_SOURCES = \
+ $(COMMON_GALLIUM_SOURCES) \
+ $(COMMON_BM_SOURCES) \
+ $(DRIVER_SOURCES)
+
+ASM_SOURCES =
+
+DRIVER_DEFINES = -I../intel $(shell pkg-config libdrm --atleast-version=2.3.1 \
+ && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
+
+include ../Makefile.template
+
+intel_tex_layout.o: ../intel/intel_tex_layout.c
+
+symlinks:
diff --git a/src/gallium/winsys/dri/intel/SConscript b/src/gallium/winsys/dri/intel/SConscript
new file mode 100644
index 00000000000..a7cc10450e3
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/SConscript
@@ -0,0 +1,41 @@
+Import('*')
+
+env = drienv.Clone()
+
+env.Append(CPPPATH = [
+ '../intel',
+ 'server'
+])
+
+#MINIGLX_SOURCES = server/intel_dri.c
+
+pipe_drivers = [
+ softpipe,
+ i915simple
+]
+
+DRIVER_SOURCES = [
+ 'intel_winsys_pipe.c',
+ 'intel_winsys_softpipe.c',
+ 'intel_winsys_i915.c',
+ 'intel_batchbuffer.c',
+ 'intel_swapbuffers.c',
+ 'intel_context.c',
+ 'intel_lock.c',
+ 'intel_screen.c',
+ 'intel_batchpool.c',
+]
+
+sources = \
+ COMMON_GALLIUM_SOURCES + \
+ COMMON_BM_SOURCES + \
+ DRIVER_SOURCES
+
+# DRIVER_DEFINES = -I../intel $(shell pkg-config libdrm --atleast-version=2.3.1 \
+# && echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
+
+env.SharedLibrary(
+ target ='i915tex_dri.so',
+ source = sources,
+ LIBS = pipe_drivers + env['LIBS'],
+) \ No newline at end of file
diff --git a/src/gallium/winsys/dri/intel/intel_batchbuffer.c b/src/gallium/winsys/dri/intel/intel_batchbuffer.c
new file mode 100644
index 00000000000..49e04d81ec1
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_batchbuffer.c
@@ -0,0 +1,357 @@
+/**************************************************************************
+ *
+ * Copyright 2006 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 <errno.h>
+#include "intel_batchbuffer.h"
+#include "intel_context.h"
+#include "intel_screen.h"
+#include "intel_reg.h"
+#include "drm.h"
+
+/* Relocations in kernel space:
+ * - pass dma buffer seperately
+ * - memory manager knows how to patch
+ * - pass list of dependent buffers
+ * - pass relocation list
+ *
+ * Either:
+ * - get back an offset for buffer to fire
+ * - memory manager knows how to fire buffer
+ *
+ * Really want the buffer to be AGP and pinned.
+ *
+ */
+
+/* Cliprect fence: The highest fence protecting a dma buffer
+ * containing explicit cliprect information. Like the old drawable
+ * lock but irq-driven. X server must wait for this fence to expire
+ * before changing cliprects [and then doing sw rendering?]. For
+ * other dma buffers, the scheduler will grab current cliprect info
+ * and mix into buffer. X server must hold the lock while changing
+ * cliprects??? Make per-drawable. Need cliprects in shared memory
+ * -- beats storing them with every cmd buffer in the queue.
+ *
+ * ==> X server must wait for this fence to expire before touching the
+ * framebuffer with new cliprects.
+ *
+ * ==> Cliprect-dependent buffers associated with a
+ * cliprect-timestamp. All of the buffers associated with a timestamp
+ * must go to hardware before any buffer with a newer timestamp.
+ *
+ * ==> Dma should be queued per-drawable for correct X/GL
+ * synchronization. Or can fences be used for this?
+ *
+ * Applies to: Blit operations, metaops, X server operations -- X
+ * server automatically waits on its own dma to complete before
+ * modifying cliprects ???
+ */
+
+static void
+intel_dump_batchbuffer(uint offset, uint * ptr, uint count)
+{
+ int i;
+ printf("\n\n\nSTART BATCH (%d dwords):\n", count / 4);
+ for (i = 0; i < count / 4; i += 1)
+ printf("\t0x%08x\n", ptr[i]);
+ printf("END BATCH\n\n\n");
+}
+
+
+void
+intel_batchbuffer_reset(struct intel_batchbuffer *batch)
+{
+ int i;
+
+ if (batch->map) {
+ driBOUnmap(batch->buffer);
+ batch->map = NULL;
+ }
+
+ /*
+ * Get a new, free batchbuffer.
+ */
+ batch->size = BATCH_SZ;
+ driBOData(batch->buffer, batch->size, NULL, 0);
+
+ driBOResetList(&batch->list);
+
+ /*
+ * Unreference buffers previously on the relocation list.
+ */
+ for (i = 0; i < batch->nr_relocs; i++) {
+ struct buffer_reloc *r = &batch->reloc[i];
+ driBOUnReference(r->buf);
+ }
+
+ batch->list_count = 0;
+ batch->nr_relocs = 0;
+ batch->flags = 0;
+
+ /*
+ * We don't refcount the batchbuffer itself since we can't destroy it
+ * while it's on the list.
+ */
+
+ driBOAddListItem(&batch->list, batch->buffer,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE,
+ DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE);
+
+
+ batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
+ batch->ptr = batch->map;
+}
+
+
+/*======================================================================
+ * Public functions
+ */
+struct intel_batchbuffer *
+intel_batchbuffer_alloc(struct intel_context *intel)
+{
+ struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
+
+ batch->intel = intel;
+
+ driGenBuffers(intel->intelScreen->batchPool, "batchbuffer", 1,
+ &batch->buffer, 4096,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
+ batch->last_fence = NULL;
+ driBOCreateList(20, &batch->list);
+ intel_batchbuffer_reset(batch);
+ return batch;
+}
+
+
+void
+intel_batchbuffer_free(struct intel_batchbuffer *batch)
+{
+ if (batch->last_fence) {
+ driFenceFinish(batch->last_fence,
+ DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
+ GL_FALSE);
+ driFenceUnReference(batch->last_fence);
+ batch->last_fence = NULL;
+ }
+ if (batch->map) {
+ driBOUnmap(batch->buffer);
+ batch->map = NULL;
+ }
+ driBOUnReference(batch->buffer);
+ batch->buffer = NULL;
+ free(batch);
+}
+
+
+static void
+intel_batch_ioctl(struct intel_context *intel,
+ uint start_offset, uint used, boolean allow_unlock)
+{
+ drmI830BatchBuffer batch;
+
+ batch.start = start_offset;
+ batch.used = used;
+ batch.cliprects = NULL; /* unused */
+ batch.num_cliprects = 0;
+ batch.DR1 = 0;
+ batch.DR4 = 0; /* still need this ? */
+
+ DBG(IOCTL, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
+ __FUNCTION__,
+ batch.start,
+ batch.start + batch.used * 4, batch.DR4, batch.num_cliprects);
+
+ if (drmCommandWrite(intel->driFd, DRM_I830_BATCHBUFFER, &batch,
+ sizeof(batch))) {
+ printf("DRM_I830_BATCHBUFFER: %d\n", -errno);
+ UNLOCK_HARDWARE(intel);
+ exit(1);
+ }
+}
+
+
+/* TODO: Push this whole function into bufmgr.
+ */
+static void
+do_flush_locked(struct intel_batchbuffer *batch,
+ uint used, boolean allow_unlock)
+{
+ uint *ptr;
+ uint i, fenceFlags;
+ struct _DriFenceObject *fo;
+
+ driBOValidateList(batch->intel->driFd, &batch->list);
+
+ /* Apply the relocations. This nasty map indicates to me that the
+ * whole task should be done internally by the memory manager, and
+ * that dma buffers probably need to be pinned within agp space.
+ */
+ ptr = (uint *) driBOMap(batch->buffer, DRM_BO_FLAG_WRITE,
+ DRM_BO_HINT_ALLOW_UNFENCED_MAP);
+
+ for (i = 0; i < batch->nr_relocs; i++) {
+ struct buffer_reloc *r = &batch->reloc[i];
+
+ ptr[r->offset / 4] = driBOOffset(r->buf) + r->delta;
+ }
+
+ if (0)
+ intel_dump_batchbuffer(0, ptr, used);
+
+ driBOUnmap(batch->buffer);
+ batch->map = NULL;
+
+ intel_batch_ioctl(batch->intel,
+ driBOOffset(batch->buffer),
+ used, allow_unlock);
+
+ /*
+ * Kernel fencing. The flags tells the kernel that we've
+ * programmed an MI_FLUSH.
+ */
+ fenceFlags = DRM_I915_FENCE_FLAG_FLUSHED;
+ fo = driFenceBuffers(batch->intel->driFd, "Batch fence", fenceFlags);
+
+ /*
+ * User space fencing.
+ */
+ driBOFence(batch->buffer, fo);
+
+ if (driFenceType(fo) == DRM_FENCE_TYPE_EXE) {
+ /*
+ * Oops. We only validated a batch buffer. This means we
+ * didn't do any proper rendering. Discard this fence object.
+ */
+ driFenceUnReference(fo);
+ }
+ else {
+ driFenceUnReference(batch->last_fence);
+ batch->last_fence = fo;
+ for (i = 0; i < batch->nr_relocs; i++) {
+ struct buffer_reloc *r = &batch->reloc[i];
+ driBOFence(r->buf, fo);
+ }
+ }
+}
+
+
+struct _DriFenceObject *
+intel_batchbuffer_flush(struct intel_batchbuffer *batch)
+{
+ struct intel_context *intel = batch->intel;
+ uint used = batch->ptr - batch->map;
+ const boolean was_locked = intel->locked;
+
+ if (used == 0)
+ return batch->last_fence;
+
+#define MI_FLUSH ((0 << 29) | (4 << 23))
+
+ /* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
+ * performance drain that we would like to avoid.
+ */
+ if (used & 4) {
+ ((int *) batch->ptr)[0] = MI_FLUSH;
+ ((int *) batch->ptr)[1] = 0;
+ ((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END;
+ used += 12;
+ }
+ else {
+ ((int *) batch->ptr)[0] = MI_FLUSH;
+ ((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END;
+ used += 8;
+ }
+
+ driBOUnmap(batch->buffer);
+ batch->ptr = NULL;
+ batch->map = NULL;
+
+ /* TODO: Just pass the relocation list and dma buffer up to the
+ * kernel.
+ */
+ if (!was_locked)
+ LOCK_HARDWARE(intel);
+
+ do_flush_locked(batch, used, GL_FALSE);
+
+ if (!was_locked)
+ UNLOCK_HARDWARE(intel);
+
+ /* Reset the buffer:
+ */
+ intel_batchbuffer_reset(batch);
+ return batch->last_fence;
+}
+
+
+void
+intel_batchbuffer_finish(struct intel_batchbuffer *batch)
+{
+ struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
+ if (fence) {
+ driFenceReference(fence);
+ driFenceFinish(fence,
+ DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
+ GL_FALSE);
+ driFenceUnReference(fence);
+ }
+}
+
+
+/* This is the only way buffers get added to the validate list.
+ */
+boolean
+intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+ struct _DriBufferObject *buffer,
+ uint flags, uint mask, uint delta)
+{
+ assert(batch->nr_relocs < MAX_RELOCS);
+
+ driBOAddListItem(&batch->list, buffer, flags, mask);
+
+ {
+ struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
+ driBOReference(buffer);
+ r->buf = buffer;
+ r->offset = batch->ptr - batch->map;
+ r->delta = delta;
+ *(uint *) batch->ptr = 0x12345678;
+ }
+
+ batch->ptr += 4;
+ return GL_TRUE;
+}
+
+
+void
+intel_batchbuffer_data(struct intel_batchbuffer *batch,
+ const void *data, uint bytes, uint flags)
+{
+ assert((bytes & 3) == 0);
+ intel_batchbuffer_require_space(batch, bytes, flags);
+ memcpy(batch->ptr, data, bytes);
+ batch->ptr += bytes;
+}
diff --git a/src/gallium/winsys/dri/intel/intel_batchbuffer.h b/src/gallium/winsys/dri/intel/intel_batchbuffer.h
new file mode 100644
index 00000000000..82feafa21f6
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_batchbuffer.h
@@ -0,0 +1,149 @@
+/**************************************************************************
+ *
+ * Copyright 2007 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_BATCHBUFFER_H
+#define INTEL_BATCHBUFFER_H
+
+#include "pipe/p_compiler.h"
+#include "dri_bufmgr.h"
+
+struct intel_context;
+
+#define BATCH_SZ 16384
+#define BATCH_RESERVED 16
+
+#define MAX_RELOCS 4096
+
+#define INTEL_BATCH_NO_CLIPRECTS 0x1
+#define INTEL_BATCH_CLIPRECTS 0x2
+
+struct buffer_reloc
+{
+ struct _DriBufferObject *buf;
+ uint offset;
+ uint delta; /* not needed? */
+};
+
+struct intel_batchbuffer
+{
+ struct bufmgr *bm;
+ struct intel_context *intel;
+
+ struct _DriBufferObject *buffer;
+ struct _DriFenceObject *last_fence;
+ uint flags;
+
+ drmBOList list;
+ uint list_count;
+ ubyte *map;
+ ubyte *ptr;
+
+ struct buffer_reloc reloc[MAX_RELOCS];
+ uint nr_relocs;
+ uint size;
+};
+
+struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context *intel);
+
+void intel_batchbuffer_free(struct intel_batchbuffer *batch);
+
+
+void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
+
+struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
+ *batch);
+
+void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
+
+
+/* Unlike bmBufferData, this currently requires the buffer be mapped.
+ * Consider it a convenience function wrapping multiple
+ * intel_buffer_dword() calls.
+ */
+void intel_batchbuffer_data(struct intel_batchbuffer *batch,
+ const void *data, uint bytes, uint flags);
+
+void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
+ uint bytes);
+
+boolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
+ struct _DriBufferObject *buffer,
+ uint flags,
+ uint mask, uint offset);
+
+/* Inline functions - might actually be better off with these
+ * non-inlined. Certainly better off switching all command packets to
+ * be passed as structs rather than dwords, but that's a little bit of
+ * work...
+ */
+static INLINE uint
+intel_batchbuffer_space(struct intel_batchbuffer *batch)
+{
+ return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
+}
+
+
+static INLINE void
+intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, uint dword)
+{
+ assert(batch->map);
+ assert(intel_batchbuffer_space(batch) >= 4);
+ *(uint *) (batch->ptr) = dword;
+ batch->ptr += 4;
+}
+
+static INLINE void
+intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
+ uint sz, uint flags)
+{
+ assert(sz < batch->size - 8);
+ if (intel_batchbuffer_space(batch) < sz ||
+ (batch->flags != 0 && flags != 0 && batch->flags != flags))
+ intel_batchbuffer_flush(batch);
+
+ batch->flags |= flags;
+}
+
+/* Here are the crusty old macros, to be removed:
+ */
+#define BATCH_LOCALS
+
+#define BEGIN_BATCH(n, flags) do { \
+ intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
+} while (0)
+
+#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
+
+#define OUT_RELOC(buf,flags,mask,delta) do { \
+ assert((delta) >= 0); \
+ intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta); \
+} while (0)
+
+#define ADVANCE_BATCH() do { } while(0)
+
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/intel_batchpool.c b/src/gallium/winsys/dri/intel/intel_batchpool.c
new file mode 100644
index 00000000000..33b56817f6a
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_batchpool.c
@@ -0,0 +1,424 @@
+/**************************************************************************
+ *
+ * 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>
+ */
+
+/**
+ * XXX NOTE: there are no intel dependencies in this file.
+ * Rename to dri_batchpool.c?
+ */
+
+#include <xf86drm.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "imports.h"
+#include "glthread.h"
+#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
+#include "intel_batchpool.h"
+
+
+typedef struct
+{
+ drmMMListHead head;
+ struct _BPool *parent;
+ struct _DriFenceObject *fence;
+ unsigned long start;
+ int unfenced;
+ int mapped;
+} BBuf;
+
+typedef struct _BPool
+{
+ _glthread_Mutex mutex;
+ unsigned long bufSize;
+ unsigned poolSize;
+ unsigned numFree;
+ unsigned numTot;
+ unsigned numDelayed;
+ unsigned checkDelayed;
+ drmMMListHead free;
+ drmMMListHead delayed;
+ drmMMListHead head;
+ drmBO kernelBO;
+ void *virtual;
+ BBuf *bufs;
+} BPool;
+
+
+static BPool *
+createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags,
+ unsigned checkDelayed)
+{
+ BPool *p = (BPool *) malloc(sizeof(*p));
+ BBuf *buf;
+ int i;
+
+ if (!p)
+ return NULL;
+
+ p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs));
+ if (!p->bufs) {
+ free(p);
+ return NULL;
+ }
+
+ DRMINITLISTHEAD(&p->free);
+ DRMINITLISTHEAD(&p->head);
+ DRMINITLISTHEAD(&p->delayed);
+
+ p->numTot = numBufs;
+ p->numFree = numBufs;
+ p->bufSize = bufSize;
+ p->numDelayed = 0;
+ p->checkDelayed = checkDelayed;
+
+ _glthread_INIT_MUTEX(p->mutex);
+
+ if (drmBOCreate(fd, 0, numBufs * bufSize, 0, NULL, drm_bo_type_dc,
+ flags, DRM_BO_HINT_DONT_FENCE, &p->kernelBO)) {
+ free(p->bufs);
+ free(p);
+ return NULL;
+ }
+ if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0,
+ &p->virtual)) {
+ drmBODestroy(fd, &p->kernelBO);
+ free(p->bufs);
+ free(p);
+ return NULL;
+ }
+
+ /*
+ * We unmap the buffer so that we can validate it later. Note that this is
+ * just a synchronizing operation. The buffer will have a virtual mapping
+ * until it is destroyed.
+ */
+
+ drmBOUnmap(fd, &p->kernelBO);
+
+ buf = p->bufs;
+ for (i = 0; i < numBufs; ++i) {
+ buf->parent = p;
+ buf->fence = NULL;
+ buf->start = i * bufSize;
+ buf->mapped = 0;
+ buf->unfenced = 0;
+ DRMLISTADDTAIL(&buf->head, &p->free);
+ buf++;
+ }
+
+ return p;
+}
+
+
+static void
+pool_checkFree(BPool * p, int wait)
+{
+ drmMMListHead *list, *prev;
+ BBuf *buf;
+ int signaled = 0;
+ int i;
+
+ list = p->delayed.next;
+
+ if (p->numDelayed > 3) {
+ for (i = 0; i < p->numDelayed; i += 3) {
+ list = list->next;
+ }
+ }
+
+ prev = list->prev;
+ for (; list != &p->delayed; list = prev, prev = list->prev) {
+
+ buf = DRMLISTENTRY(BBuf, list, head);
+
+ if (!signaled) {
+ if (wait) {
+ driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1);
+ signaled = 1;
+ }
+ else {
+ signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE);
+ }
+ }
+
+ if (!signaled)
+ break;
+
+ driFenceUnReference(buf->fence);
+ buf->fence = NULL;
+ DRMLISTDEL(list);
+ p->numDelayed--;
+ DRMLISTADD(list, &p->free);
+ p->numFree++;
+ }
+}
+
+static void *
+pool_create(struct _DriBufferPool *pool,
+ unsigned long size, unsigned flags, unsigned hint,
+ unsigned alignment)
+{
+ BPool *p = (BPool *) pool->data;
+
+ drmMMListHead *item;
+
+ if (alignment && (alignment != 4096))
+ return NULL;
+
+ _glthread_LOCK_MUTEX(p->mutex);
+
+ if (p->numFree == 0)
+ pool_checkFree(p, GL_TRUE);
+
+ if (p->numFree == 0) {
+ fprintf(stderr, "Out of fixed size buffer objects\n");
+ BM_CKFATAL(-ENOMEM);
+ }
+
+ item = p->free.next;
+
+ if (item == &p->free) {
+ fprintf(stderr, "Fixed size buffer pool corruption\n");
+ }
+
+ DRMLISTDEL(item);
+ --p->numFree;
+
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ return (void *) DRMLISTENTRY(BBuf, item, head);
+}
+
+
+static int
+pool_destroy(struct _DriBufferPool *pool, void *private)
+{
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+
+ _glthread_LOCK_MUTEX(p->mutex);
+
+ if (buf->fence) {
+ DRMLISTADDTAIL(&buf->head, &p->delayed);
+ p->numDelayed++;
+ }
+ else {
+ buf->unfenced = 0;
+ DRMLISTADD(&buf->head, &p->free);
+ p->numFree++;
+ }
+
+ if ((p->numDelayed % p->checkDelayed) == 0)
+ pool_checkFree(p, 0);
+
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ return 0;
+}
+
+
+static int
+pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
+ int hint, void **virtual)
+{
+
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+
+ _glthread_LOCK_MUTEX(p->mutex);
+
+ /*
+ * Currently Mesa doesn't have any condition variables to resolve this
+ * cleanly in a multithreading environment.
+ * We bail out instead.
+ */
+
+ if (buf->mapped) {
+ fprintf(stderr, "Trying to map already mapped buffer object\n");
+ BM_CKFATAL(-EINVAL);
+ }
+
+#if 0
+ if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
+ fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x"
+ " 0x%08x %d\n", hint, flags, buf->start);
+ BM_CKFATAL(-EINVAL);
+ }
+
+#endif
+
+ if (buf->fence) {
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ return -EBUSY;
+ }
+
+ buf->mapped = GL_TRUE;
+ *virtual = (unsigned char *) p->virtual + buf->start;
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ return 0;
+}
+
+static int
+pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
+{
+ BBuf *buf = (BBuf *) private;
+ driFenceFinish(buf->fence, 0x0, lazy);
+ return 0;
+}
+
+static int
+pool_unmap(struct _DriBufferPool *pool, void *private)
+{
+ BBuf *buf = (BBuf *) private;
+
+ buf->mapped = 0;
+ return 0;
+}
+
+static unsigned long
+pool_offset(struct _DriBufferPool *pool, void *private)
+{
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+
+ return p->kernelBO.offset + buf->start;
+}
+
+static unsigned
+pool_flags(struct _DriBufferPool *pool, void *private)
+{
+ BPool *p = (BPool *) pool->data;
+
+ return p->kernelBO.flags;
+}
+
+static unsigned long
+pool_size(struct _DriBufferPool *pool, void *private)
+{
+ BPool *p = (BPool *) pool->data;
+
+ return p->bufSize;
+}
+
+
+static int
+pool_fence(struct _DriBufferPool *pool, void *private,
+ struct _DriFenceObject *fence)
+{
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+
+ _glthread_LOCK_MUTEX(p->mutex);
+ if (buf->fence) {
+ driFenceUnReference(buf->fence);
+ }
+ buf->fence = fence;
+ buf->unfenced = 0;
+ driFenceReference(buf->fence);
+ _glthread_UNLOCK_MUTEX(p->mutex);
+
+ return 0;
+}
+
+static drmBO *
+pool_kernel(struct _DriBufferPool *pool, void *private)
+{
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+
+ return &p->kernelBO;
+}
+
+static int
+pool_validate(struct _DriBufferPool *pool, void *private)
+{
+ BBuf *buf = (BBuf *) private;
+ BPool *p = buf->parent;
+ _glthread_LOCK_MUTEX(p->mutex);
+ buf->unfenced = GL_TRUE;
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ return 0;
+}
+
+static void
+pool_takedown(struct _DriBufferPool *pool)
+{
+ BPool *p = (BPool *) pool->data;
+
+ /*
+ * Wait on outstanding fences.
+ */
+
+ _glthread_LOCK_MUTEX(p->mutex);
+ while ((p->numFree < p->numTot) && p->numDelayed) {
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ sched_yield();
+ pool_checkFree(p, GL_TRUE);
+ _glthread_LOCK_MUTEX(p->mutex);
+ }
+
+ drmBODestroy(pool->fd, &p->kernelBO);
+ free(p->bufs);
+ _glthread_UNLOCK_MUTEX(p->mutex);
+ free(p);
+ free(pool);
+}
+
+
+struct _DriBufferPool *
+driBatchPoolInit(int fd, unsigned flags,
+ unsigned long bufSize,
+ unsigned numBufs, unsigned checkDelayed)
+{
+ struct _DriBufferPool *pool;
+
+ pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
+ if (!pool)
+ return NULL;
+
+ pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed);
+ if (!pool->data)
+ return NULL;
+
+ pool->fd = fd;
+ pool->map = &pool_map;
+ pool->unmap = &pool_unmap;
+ pool->destroy = &pool_destroy;
+ pool->offset = &pool_offset;
+ pool->flags = &pool_flags;
+ pool->size = &pool_size;
+ pool->create = &pool_create;
+ pool->fence = &pool_fence;
+ pool->kernel = &pool_kernel;
+ pool->validate = &pool_validate;
+ pool->waitIdle = &pool_waitIdle;
+ pool->setstatic = NULL;
+ pool->takeDown = &pool_takedown;
+ return pool;
+}
diff --git a/src/gallium/winsys/dri/intel/intel_batchpool.h b/src/gallium/winsys/dri/intel/intel_batchpool.h
new file mode 100644
index 00000000000..f6a95723bcf
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_batchpool.h
@@ -0,0 +1,37 @@
+/**************************************************************************
+ *
+ * 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_BATCHPOOL_H
+#define INTEL_BATCHPOOL_H
+
+extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags,
+ unsigned long bufSize,
+ unsigned numBufs,
+ unsigned checkDelayed);
+
+
+#endif /* INTEL_BATCHPOOL_H */
diff --git a/src/gallium/winsys/dri/intel/intel_context.c b/src/gallium/winsys/dri/intel/intel_context.c
new file mode 100644
index 00000000000..c033f2a592c
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_context.c
@@ -0,0 +1,304 @@
+/**************************************************************************
+ *
+ * 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 "i830_dri.h"
+
+#include "intel_screen.h"
+#include "intel_context.h"
+#include "intel_swapbuffers.h"
+#include "intel_winsys.h"
+#include "intel_batchbuffer.h"
+
+#include "state_tracker/st_public.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_context.h"
+
+#include "utils.h"
+
+
+#ifdef DEBUG
+int __intel_debug = 0;
+#endif
+
+
+#define need_GL_ARB_multisample
+#define need_GL_ARB_point_parameters
+#define need_GL_ARB_texture_compression
+#define need_GL_ARB_vertex_buffer_object
+#define need_GL_ARB_vertex_program
+#define need_GL_ARB_window_pos
+#define need_GL_EXT_blend_color
+#define need_GL_EXT_blend_equation_separate
+#define need_GL_EXT_blend_func_separate
+#define need_GL_EXT_blend_minmax
+#define need_GL_EXT_cull_vertex
+#define need_GL_EXT_fog_coord
+#define need_GL_EXT_framebuffer_object
+#define need_GL_EXT_multi_draw_arrays
+#define need_GL_EXT_secondary_color
+#define need_GL_NV_vertex_program
+#include "extension_helper.h"
+
+
+/**
+ * Extension strings exported by the intel driver.
+ *
+ * \note
+ * It appears that ARB_texture_env_crossbar has "disappeared" compared to the
+ * old i830-specific driver.
+ */
+const struct dri_extension card_extensions[] = {
+ {"GL_ARB_multisample", GL_ARB_multisample_functions},
+ {"GL_ARB_multitexture", NULL},
+ {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
+ {"GL_ARB_texture_border_clamp", NULL},
+ {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
+ {"GL_ARB_texture_cube_map", NULL},
+ {"GL_ARB_texture_env_add", NULL},
+ {"GL_ARB_texture_env_combine", NULL},
+ {"GL_ARB_texture_env_dot3", NULL},
+ {"GL_ARB_texture_mirrored_repeat", NULL},
+ {"GL_ARB_texture_rectangle", NULL},
+ {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
+ {"GL_ARB_pixel_buffer_object", NULL},
+ {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
+ {"GL_ARB_window_pos", GL_ARB_window_pos_functions},
+ {"GL_EXT_blend_color", GL_EXT_blend_color_functions},
+ {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
+ {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
+ {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
+ {"GL_EXT_blend_subtract", NULL},
+ {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
+ {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
+ {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
+ {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
+ {"GL_EXT_packed_depth_stencil", NULL},
+ {"GL_EXT_pixel_buffer_object", NULL},
+ {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
+ {"GL_EXT_stencil_wrap", NULL},
+ {"GL_EXT_texture_edge_clamp", NULL},
+ {"GL_EXT_texture_env_combine", NULL},
+ {"GL_EXT_texture_env_dot3", NULL},
+ {"GL_EXT_texture_filter_anisotropic", NULL},
+ {"GL_EXT_texture_lod_bias", NULL},
+ {"GL_3DFX_texture_compression_FXT1", NULL},
+ {"GL_APPLE_client_storage", NULL},
+ {"GL_MESA_pack_invert", NULL},
+ {"GL_MESA_ycbcr_texture", NULL},
+ {"GL_NV_blend_square", NULL},
+ {"GL_NV_vertex_program", GL_NV_vertex_program_functions},
+ {"GL_NV_vertex_program1_1", NULL},
+ {"GL_SGIS_generate_mipmap", NULL },
+ {NULL, NULL}
+};
+
+
+
+#ifdef DEBUG
+static const struct dri_debug_control debug_control[] = {
+ {"ioctl", DEBUG_IOCTL},
+ {"bat", DEBUG_BATCH},
+ {"lock", DEBUG_LOCK},
+ {"swap", DEBUG_SWAP},
+ {NULL, 0}
+};
+#endif
+
+
+
+GLboolean
+intelCreateContext(const __GLcontextModes * visual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate)
+{
+ struct intel_context *intel = CALLOC_STRUCT(intel_context);
+ __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
+ struct intel_screen *intelScreen = intel_screen(sPriv);
+ drmI830Sarea *saPriv = intelScreen->sarea;
+ int fthrottle_mode;
+ GLboolean havePools;
+ struct pipe_context *pipe;
+ struct st_context *st_share = NULL;
+
+ if (sharedContextPrivate) {
+ st_share = ((struct intel_context *) sharedContextPrivate)->st;
+ }
+
+ driContextPriv->driverPrivate = intel;
+ intel->intelScreen = intelScreen;
+ intel->driScreen = sPriv;
+ intel->sarea = saPriv;
+
+ driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
+ intel->driScreen->myNum, "i915");
+
+
+ /*
+ * memory pools
+ */
+ DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
+ havePools = intelCreatePools(sPriv);
+ DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
+ if (!havePools)
+ return GL_FALSE;
+
+
+ /* Dri stuff */
+ intel->hHWContext = driContextPriv->hHWContext;
+ intel->driFd = sPriv->fd;
+ intel->driHwLock = (drmLock *) & sPriv->pSAREA->lock;
+
+ fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode");
+ intel->iw.irq_seq = -1;
+ intel->irqsEmitted = 0;
+
+ intel->batch = intel_batchbuffer_alloc(intel);
+ intel->last_swap_fence = NULL;
+ intel->first_swap_fence = NULL;
+
+#ifdef DEBUG
+ __intel_debug = driParseDebugString(getenv("INTEL_DEBUG"), debug_control);
+#endif
+
+ /*
+ * Pipe-related setup
+ */
+ if (!getenv("INTEL_HW")) {
+ pipe = intel_create_softpipe( intel, intelScreen->winsys );
+ }
+ else {
+ switch (intel->intelScreen->deviceID) {
+ case PCI_CHIP_I945_G:
+ case PCI_CHIP_I945_GM:
+ case PCI_CHIP_I945_GME:
+ case PCI_CHIP_G33_G:
+ case PCI_CHIP_Q33_G:
+ case PCI_CHIP_Q35_G:
+ case PCI_CHIP_I915_G:
+ case PCI_CHIP_I915_GM:
+ pipe = intel_create_i915simple( intel, intelScreen->winsys );
+ break;
+ default:
+ fprintf(stderr, "Unknown PCIID %x in %s, using software driver\n",
+ intel->intelScreen->deviceID, __FUNCTION__);
+
+ pipe = intel_create_softpipe( intel, intelScreen->winsys );
+ break;
+ }
+ }
+
+ pipe->priv = intel;
+
+ intel->st = st_create_context(pipe, visual, st_share);
+
+ return GL_TRUE;
+}
+
+
+void
+intelDestroyContext(__DRIcontextPrivate * driContextPriv)
+{
+ struct intel_context *intel = intel_context(driContextPriv);
+
+ assert(intel); /* should never be null */
+ if (intel) {
+ st_flush(intel->st, PIPE_FLUSH_WAIT);
+
+ intel_batchbuffer_free(intel->batch);
+
+ if (intel->last_swap_fence) {
+ driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
+ driFenceUnReference(intel->last_swap_fence);
+ intel->last_swap_fence = NULL;
+ }
+ if (intel->first_swap_fence) {
+ driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
+ driFenceUnReference(intel->first_swap_fence);
+ intel->first_swap_fence = NULL;
+ }
+
+ if (intel->intelScreen->dummyContext == intel)
+ intel->intelScreen->dummyContext = NULL;
+
+ st_destroy_context(intel->st);
+ free(intel);
+ }
+}
+
+
+GLboolean
+intelUnbindContext(__DRIcontextPrivate * driContextPriv)
+{
+ struct intel_context *intel = intel_context(driContextPriv);
+ st_flush(intel->st, 0x0);
+ /* XXX make_current(NULL)? */
+ return GL_TRUE;
+}
+
+
+GLboolean
+intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv)
+{
+ if (driContextPriv) {
+ struct intel_context *intel = intel_context(driContextPriv);
+ struct intel_framebuffer *draw_fb = intel_framebuffer(driDrawPriv);
+ struct intel_framebuffer *read_fb = intel_framebuffer(driReadPriv);
+
+ assert(draw_fb->stfb);
+ assert(read_fb->stfb);
+
+ /* This is for situations in which we need a rendering context but
+ * there may not be any currently bound.
+ */
+ intel->intelScreen->dummyContext = intel;
+
+ st_make_current(intel->st, draw_fb->stfb, read_fb->stfb);
+
+ if ((intel->driDrawable != driDrawPriv) ||
+ (intel->lastStamp != driDrawPriv->lastStamp)) {
+ intel->driDrawable = driDrawPriv;
+ intelUpdateWindowSize(driDrawPriv);
+ intel->lastStamp = driDrawPriv->lastStamp;
+ }
+
+ /* The size of the draw buffer will have been updated above.
+ * If the readbuffer is a different window, check/update its size now.
+ */
+ if (driReadPriv != driDrawPriv) {
+ intelUpdateWindowSize(driReadPriv);
+ }
+
+ }
+ else {
+ st_make_current(NULL, NULL, NULL);
+ }
+
+ return GL_TRUE;
+}
diff --git a/src/gallium/winsys/dri/intel/intel_context.h b/src/gallium/winsys/dri/intel/intel_context.h
new file mode 100644
index 00000000000..b01370c049c
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_context.h
@@ -0,0 +1,158 @@
+/**************************************************************************
+ *
+ * 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_CONTEXT_H
+#define INTEL_CONTEXT_H
+
+
+#include "drm.h"
+#include "intel_screen.h"
+#include "i915_drm.h"
+
+
+struct pipe_context;
+struct intel_context;
+struct _DriBufferObject;
+struct st_context;
+
+
+#define INTEL_MAX_FIXUP 64
+
+/**
+ * Intel rendering context, contains a state tracker and intel-specific info.
+ */
+struct intel_context
+{
+ struct st_context *st;
+
+ struct _DriFenceObject *last_swap_fence;
+ struct _DriFenceObject *first_swap_fence;
+
+ struct intel_batchbuffer *batch;
+
+ boolean locked;
+ char *prevLockFile;
+ int prevLockLine;
+
+ uint irqsEmitted;
+ drm_i915_irq_wait_t iw;
+
+ drm_context_t hHWContext;
+ drmLock *driHwLock;
+ int driFd;
+
+ __DRIdrawablePrivate *driDrawable;
+ __DRIscreenPrivate *driScreen;
+ struct intel_screen *intelScreen;
+ drmI830Sarea *sarea;
+
+ uint lastStamp;
+
+ /**
+ * Configuration cache
+ */
+ driOptionCache optionCache;
+};
+
+
+
+/**
+ * Intel framebuffer.
+ */
+struct intel_framebuffer
+{
+ struct st_framebuffer *stfb;
+
+ /* other fields TBD */
+ int other;
+};
+
+
+
+
+/* These are functions now:
+ */
+void LOCK_HARDWARE( struct intel_context *intel );
+void UNLOCK_HARDWARE( struct intel_context *intel );
+
+extern char *__progname;
+
+
+
+/* ================================================================
+ * Debugging:
+ */
+#ifdef DEBUG
+extern int __intel_debug;
+
+#define DEBUG_SWAP 0x1
+#define DEBUG_LOCK 0x2
+#define DEBUG_IOCTL 0x4
+#define DEBUG_BATCH 0x8
+
+#define DBG(flag, ...) do { \
+ if (__intel_debug & (DEBUG_##flag)) \
+ printf(__VA_ARGS__); \
+} while(0)
+
+#else
+#define DBG(flag, ...)
+#endif
+
+
+
+#define PCI_CHIP_845_G 0x2562
+#define PCI_CHIP_I830_M 0x3577
+#define PCI_CHIP_I855_GM 0x3582
+#define PCI_CHIP_I865_G 0x2572
+#define PCI_CHIP_I915_G 0x2582
+#define PCI_CHIP_I915_GM 0x2592
+#define PCI_CHIP_I945_G 0x2772
+#define PCI_CHIP_I945_GM 0x27A2
+#define PCI_CHIP_I945_GME 0x27AE
+#define PCI_CHIP_G33_G 0x29C2
+#define PCI_CHIP_Q35_G 0x29B2
+#define PCI_CHIP_Q33_G 0x29D2
+
+
+/** Cast wrapper */
+static INLINE struct intel_context *
+intel_context(__DRIcontextPrivate *driContextPriv)
+{
+ return (struct intel_context *) driContextPriv->driverPrivate;
+}
+
+
+/** Cast wrapper */
+static INLINE struct intel_framebuffer *
+intel_framebuffer(__DRIdrawablePrivate * driDrawPriv)
+{
+ return (struct intel_framebuffer *) driDrawPriv->driverPrivate;
+}
+
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/intel_lock.c b/src/gallium/winsys/dri/intel/intel_lock.c
new file mode 100644
index 00000000000..70aa7ea5f46
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_lock.c
@@ -0,0 +1,102 @@
+/**************************************************************************
+ *
+ * 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 "main/glheader.h"
+#include "glapi/glthread.h"
+#include <GL/internal/glcore.h>
+#include "state_tracker/st_public.h"
+#include "intel_context.h"
+#include "i830_dri.h"
+
+
+
+_glthread_DECLARE_STATIC_MUTEX( lockMutex );
+
+
+static void
+intelContendedLock(struct intel_context *intel, uint flags)
+{
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+ __DRIscreenPrivate *sPriv = intel->driScreen;
+ struct intel_screen *intelScreen = intel_screen(sPriv);
+ drmI830Sarea *sarea = intel->sarea;
+
+ drmGetLock(intel->driFd, intel->hHWContext, flags);
+
+ DBG(LOCK, "%s - got contended lock\n", __progname);
+
+ /* If the window moved, may need to set a new cliprect now.
+ *
+ * NOTE: This releases and regains the hw lock, so all state
+ * checking must be done *after* this call:
+ */
+ if (dPriv)
+ DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
+
+ if (sarea->width != intelScreen->front.width ||
+ sarea->height != intelScreen->front.height) {
+
+ intelUpdateScreenRotation(sPriv, sarea);
+ }
+}
+
+
+/* Lock the hardware and validate our state.
+ */
+void LOCK_HARDWARE( struct intel_context *intel )
+{
+ char __ret = 0;
+
+ _glthread_LOCK_MUTEX(lockMutex);
+ assert(!intel->locked);
+
+ DRM_CAS(intel->driHwLock, intel->hHWContext,
+ (DRM_LOCK_HELD|intel->hHWContext), __ret);
+
+ if (__ret)
+ intelContendedLock( intel, 0 );
+
+ DBG(LOCK, "%s - locked\n", __progname);
+
+ intel->locked = 1;
+}
+
+
+/* Unlock the hardware using the global current context
+ */
+void UNLOCK_HARDWARE( struct intel_context *intel )
+{
+ assert(intel->locked);
+ intel->locked = 0;
+
+ DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
+
+ _glthread_UNLOCK_MUTEX(lockMutex);
+
+ DBG(LOCK, "%s - unlocked\n", __progname);
+}
diff --git a/src/gallium/winsys/dri/intel/intel_reg.h b/src/gallium/winsys/dri/intel/intel_reg.h
new file mode 100644
index 00000000000..f37c24fda9a
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_reg.h
@@ -0,0 +1,53 @@
+/**************************************************************************
+ *
+ * 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_REG_H_
+#define _INTEL_REG_H_
+
+
+#define BR00_BITBLT_CLIENT 0x40000000
+#define BR00_OP_COLOR_BLT 0x10000000
+#define BR00_OP_SRC_COPY_BLT 0x10C00000
+#define BR13_SOLID_PATTERN 0x80000000
+
+#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4)
+#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
+#define XY_COLOR_BLT_WRITE_RGB (1<<20)
+
+#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
+#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
+#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
+
+#define MI_WAIT_FOR_EVENT ((0x3<<23))
+#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
+#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
+
+#define MI_BATCH_BUFFER_END (0xA<<23)
+
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/intel_screen.c b/src/gallium/winsys/dri/intel/intel_screen.c
new file mode 100644
index 00000000000..9e31c013a95
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_screen.c
@@ -0,0 +1,537 @@
+/**************************************************************************
+ *
+ * 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 "utils.h"
+#include "vblank.h"
+#include "xmlpool.h"
+
+#include "intel_context.h"
+#include "intel_screen.h"
+#include "intel_batchbuffer.h"
+#include "intel_batchpool.h"
+#include "intel_swapbuffers.h"
+#include "intel_winsys.h"
+
+#include "i830_dri.h"
+#include "dri_bufpool.h"
+
+#include "pipe/p_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_cb_fbo.h"
+
+
+
+PUBLIC const char __driConfigOptions[] =
+ DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
+ DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
+ DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
+ DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
+ DRI_CONF_FORCE_S3TC_ENABLE(false)
+ DRI_CONF_ALLOW_LARGE_TEXTURES(1)
+ DRI_CONF_SECTION_END DRI_CONF_END;
+
+const uint __driNConfigOptions = 4;
+
+#ifdef USE_NEW_INTERFACE
+static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
+#endif /*USE_NEW_INTERFACE */
+
+extern const struct dri_extension card_extensions[];
+
+
+
+
+static void
+intelPrintDRIInfo(struct intel_screen * 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, "*** Memory : 0x%x\n", gDRIPriv->mem);
+}
+
+
+#if 0
+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);
+}
+#endif
+
+
+/**
+ * Use the information in the sarea to update the screen parameters
+ * related to screen rotation. Needs to be called locked.
+ */
+void
+intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
+{
+ struct intel_screen *intelScreen = intel_screen(sPriv);
+
+ if (intelScreen->front.map) {
+ drmUnmap(intelScreen->front.map, intelScreen->front.size);
+ intelScreen->front.map = NULL;
+ }
+
+ if (intelScreen->front.buffer)
+ driDeleteBuffers(1, &intelScreen->front.buffer);
+
+ intelScreen->front.width = sarea->width;
+ intelScreen->front.height = sarea->height;
+ intelScreen->front.offset = sarea->front_offset;
+ intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp;
+ intelScreen->front.size = sarea->front_size;
+ intelScreen->front.handle = sarea->front_handle;
+
+ assert( sarea->front_size >=
+ intelScreen->front.pitch * intelScreen->front.height );
+
+ if (!sarea->front_handle)
+ return;
+
+ if (drmMap(sPriv->fd,
+ sarea->front_handle,
+ intelScreen->front.size,
+ (drmAddress *) & intelScreen->front.map) != 0) {
+ fprintf(stderr, "drmMap(frontbuffer) failed!\n");
+ return;
+ }
+
+ if (intelScreen->staticPool) {
+ driGenBuffers(intelScreen->staticPool, "static region", 1,
+ &intelScreen->front.buffer, 64,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
+ DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
+
+ driBOSetStatic(intelScreen->front.buffer,
+ intelScreen->front.offset,
+ intelScreen->front.pitch * intelScreen->front.height,
+ intelScreen->front.map, 0);
+ }
+}
+
+
+boolean
+intelCreatePools(__DRIscreenPrivate * sPriv)
+{
+ unsigned batchPoolSize = 1024*1024;
+ struct intel_screen *intelScreen = intel_screen(sPriv);
+
+ if (intelScreen->havePools)
+ return GL_TRUE;
+
+ intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
+ if (!intelScreen->staticPool)
+ return GL_FALSE;
+
+ batchPoolSize /= BATCH_SZ;
+ intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
+ DRM_BO_FLAG_EXE |
+ DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_MEM_LOCAL,
+ BATCH_SZ,
+ batchPoolSize, 5);
+ if (!intelScreen->batchPool) {
+ fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
+ return GL_FALSE;
+ }
+
+ intelScreen->havePools = GL_TRUE;
+
+ intelUpdateScreenRotation(sPriv, intelScreen->sarea);
+
+ return GL_TRUE;
+}
+
+
+static boolean
+intelInitDriver(__DRIscreenPrivate * sPriv)
+{
+ struct intel_screen *intelScreen;
+ I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
+
+ 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 = CALLOC_STRUCT(intel_screen);
+ if (!intelScreen)
+ return GL_FALSE;
+
+ /* parse information in __driConfigOptions */
+ driParseOptionInfo(&intelScreen->optionCache,
+ __driConfigOptions, __driNConfigOptions);
+
+ sPriv->private = (void *) intelScreen;
+
+ intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) +
+ gDRIPriv->sarea_priv_offset);
+ intelScreen->deviceID = gDRIPriv->deviceID;
+ intelScreen->front.cpp = gDRIPriv->cpp;
+ intelScreen->drmMinor = sPriv->drmMinor;
+
+ assert(gDRIPriv->bitsPerPixel == 16 ||
+ gDRIPriv->bitsPerPixel == 32);
+
+ intelUpdateScreenRotation(sPriv, intelScreen->sarea);
+
+ if (0)
+ intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
+
+ 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");
+ }
+
+ intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd);
+
+ return GL_TRUE;
+}
+
+
+static void
+intelDestroyScreen(__DRIscreenPrivate * sPriv)
+{
+ struct intel_screen *intelScreen = intel_screen(sPriv);
+
+ /* intelUnmapScreenRegions(intelScreen); */
+
+ if (intelScreen->havePools) {
+ driPoolTakeDown(intelScreen->staticPool);
+ driPoolTakeDown(intelScreen->batchPool);
+ }
+ FREE(intelScreen);
+ sPriv->private = NULL;
+}
+
+
+/**
+ * This is called when we need to set up GL rendering to a new X window.
+ */
+static boolean
+intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ const __GLcontextModes * visual, boolean isPixmap)
+{
+ if (isPixmap) {
+ return GL_FALSE; /* not implemented */
+ }
+ else {
+ enum pipe_format colorFormat, depthFormat, stencilFormat;
+ struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
+
+ if (!intelfb)
+ return GL_FALSE;
+
+ if (visual->redBits == 5)
+ colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
+ else
+ colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
+
+ if (visual->depthBits == 16)
+ depthFormat = PIPE_FORMAT_Z16_UNORM;
+ else if (visual->depthBits == 24)
+ depthFormat = PIPE_FORMAT_S8Z24_UNORM;
+ else
+ depthFormat = PIPE_FORMAT_NONE;
+
+ if (visual->stencilBits == 8)
+ stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
+ else
+ stencilFormat = PIPE_FORMAT_NONE;
+
+ intelfb->stfb = st_create_framebuffer(visual,
+ colorFormat,
+ depthFormat,
+ stencilFormat,
+ driDrawPriv->w,
+ driDrawPriv->h,
+ (void*) intelfb);
+ if (!intelfb->stfb) {
+ free(intelfb);
+ return GL_FALSE;
+ }
+
+ driDrawPriv->driverPrivate = (void *) intelfb;
+ return GL_TRUE;
+ }
+}
+
+static void
+intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
+{
+ struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv);
+ assert(intelfb->stfb);
+ st_unreference_framebuffer(&intelfb->stfb);
+ free(intelfb);
+}
+
+
+/**
+ * Get information about previous buffer swaps.
+ */
+static int
+intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
+{
+ if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
+ || (sInfo == NULL)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static void
+intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
+ unsigned long long offset, int depth, uint pitch)
+{
+ abort();
+#if 0
+ struct intel_context *intel = (struct intel_context*)
+ ((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate;
+ struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
+ struct st_texture_object *stObj = st_texture_object(tObj);
+
+ if (!stObj)
+ return;
+
+ if (stObj->pt)
+ st->pipe->texture_release(intel->st->pipe, &stObj->pt);
+
+ stObj->imageOverride = GL_TRUE;
+ stObj->depthOverride = depth;
+ stObj->pitchOverride = pitch;
+
+ if (offset)
+ stObj->textureOffset = offset;
+#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,
+ .setTexOffset = intelSetTexOffset,
+};
+
+
+static __GLcontextModes *
+intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
+ unsigned stencil_bits, boolean 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
+ };
+
+ u_int8_t depth_bits_array[3];
+ u_int8_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;
+ if (depth_bits == 24)
+ stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
+
+ 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, 7, 0 };
+ static const __DRIversion dri_expected = { 4, 0, 0 };
+ static const __DRIversion drm_expected = { 1, 7, 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/gallium/winsys/dri/intel/intel_screen.h b/src/gallium/winsys/dri/intel/intel_screen.h
new file mode 100644
index 00000000000..3396f9e5643
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_screen.h
@@ -0,0 +1,113 @@
+/**************************************************************************
+ *
+ * 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_SCREEN_H_
+#define _INTEL_SCREEN_H_
+
+#include "dri_util.h"
+#include "i830_common.h"
+#include "xmlconfig.h"
+#include "dri_bufpool.h"
+
+#include "pipe/p_compiler.h"
+
+
+struct intel_screen
+{
+ struct {
+ drm_handle_t handle;
+
+ /* We create a static dri buffer for the frontbuffer.
+ */
+ struct _DriBufferObject *buffer;
+
+ char *map; /* memory map */
+ int offset; /* from start of video mem, in bytes */
+ int pitch; /* row stride, in bytes */
+ int width;
+ int height;
+ int size;
+ int cpp; /* for front and back buffers */
+ } front;
+
+ int deviceID;
+ int drmMinor;
+
+ drmI830Sarea *sarea;
+
+ /**
+ * Configuration cache with default values for all contexts
+ */
+ driOptionCache optionCache;
+
+ struct _DriBufferPool *batchPool;
+ struct _DriBufferPool *staticPool; /** for the X screen/framebuffer */
+ boolean havePools;
+
+ /**
+ * Temporary(?) context to use for SwapBuffers or other situations in
+ * which we need a rendering context, but none is currently bound.
+ */
+ struct intel_context *dummyContext;
+
+ struct pipe_winsys *winsys;
+};
+
+
+
+/** cast wrapper */
+static INLINE struct intel_screen *
+intel_screen(__DRIscreenPrivate *sPriv)
+{
+ return (struct intel_screen *) sPriv->private;
+}
+
+
+extern void
+intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea);
+
+
+extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv);
+
+extern boolean intelUnbindContext(__DRIcontextPrivate * driContextPriv);
+
+extern boolean
+intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
+ __DRIdrawablePrivate * driDrawPriv,
+ __DRIdrawablePrivate * driReadPriv);
+
+
+extern boolean
+intelCreatePools(__DRIscreenPrivate *sPriv);
+
+extern boolean
+intelCreateContext(const __GLcontextModes * visual,
+ __DRIcontextPrivate * driContextPriv,
+ void *sharedContextPrivate);
+
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/intel_swapbuffers.c b/src/gallium/winsys/dri/intel/intel_swapbuffers.c
new file mode 100644
index 00000000000..56b86d6a636
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_swapbuffers.c
@@ -0,0 +1,253 @@
+/**************************************************************************
+ *
+ * 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 "intel_screen.h"
+#include "intel_context.h"
+#include "intel_swapbuffers.h"
+#include "intel_batchbuffer.h"
+#include "intel_reg.h"
+#include "intel_winsys.h"
+
+#include "pipe/p_context.h"
+#include "state_tracker/st_public.h"
+#include "state_tracker/st_context.h"
+#include "state_tracker/st_cb_fbo.h"
+
+
+/**
+ * Display a colorbuffer surface in an X window.
+ * Used for SwapBuffers and flushing front buffer rendering.
+ *
+ * \param dPriv the window/drawable to display into
+ * \param surf the surface to display
+ * \param rect optional subrect of surface to display (may be NULL).
+ */
+void
+intelDisplaySurface(__DRIdrawablePrivate *dPriv,
+ struct pipe_surface *surf,
+ const drm_clip_rect_t *rect)
+{
+ struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
+ struct intel_context *intel = intelScreen->dummyContext;
+
+ DBG(SWAP, "%s\n", __FUNCTION__);
+
+ if (!intel) {
+ /* XXX this is where some kind of extra/meta context could be useful */
+ return;
+ }
+
+ if (intel->last_swap_fence) {
+ driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
+ driFenceUnReference(intel->last_swap_fence);
+ intel->last_swap_fence = NULL;
+ }
+ intel->last_swap_fence = intel->first_swap_fence;
+ intel->first_swap_fence = NULL;
+
+ /* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
+ * should work regardless.
+ */
+ LOCK_HARDWARE(intel);
+ /* if this drawable isn't currently bound the LOCK_HARDWARE done on the
+ * current context (which is what intelScreenContext should return) might
+ * not get a contended lock and thus cliprects not updated (tests/manywin)
+ */
+ if (intel_context(dPriv->driContextPriv) != intel)
+ DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);
+
+
+ if (dPriv && dPriv->numClipRects) {
+ const int srcWidth = surf->width;
+ const int srcHeight = surf->height;
+ const int nbox = dPriv->numClipRects;
+ const drm_clip_rect_t *pbox = dPriv->pClipRects;
+ const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
+ const int cpp = intelScreen->front.cpp;
+ const int srcpitch = surf->pitch;
+ int BR13, CMD;
+ int i;
+
+ ASSERT(surf->buffer);
+ ASSERT(surf->cpp == cpp);
+
+ DBG(SWAP, "screen pitch %d src surface pitch %d\n",
+ pitch, surf->pitch);
+
+ if (cpp == 2) {
+ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
+ CMD = XY_SRC_COPY_BLT_CMD;
+ }
+ else {
+ BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
+ CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+ XY_SRC_COPY_BLT_WRITE_RGB);
+ }
+
+ for (i = 0; i < nbox; i++, pbox++) {
+ drm_clip_rect_t box;
+ drm_clip_rect_t sbox;
+
+ if (pbox->x1 > pbox->x2 ||
+ pbox->y1 > pbox->y2 ||
+ pbox->x2 > intelScreen->front.width ||
+ pbox->y2 > intelScreen->front.height) {
+ /* invalid cliprect, skip it */
+ continue;
+ }
+
+ box = *pbox;
+
+ if (rect) {
+ /* intersect cliprect with user-provided src rect */
+ drm_clip_rect_t rrect;
+
+ rrect.x1 = dPriv->x + rect->x1;
+ rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
+ rrect.x2 = rect->x2 + rrect.x1;
+ rrect.y2 = rect->y2 + rrect.y1;
+ if (rrect.x1 > box.x1)
+ box.x1 = rrect.x1;
+ if (rrect.y1 > box.y1)
+ box.y1 = rrect.y1;
+ if (rrect.x2 < box.x2)
+ box.x2 = rrect.x2;
+ if (rrect.y2 < box.y2)
+ box.y2 = rrect.y2;
+
+ if (box.x1 > box.x2 || box.y1 > box.y2)
+ continue;
+ }
+
+ /* restrict blit to size of actually rendered area */
+ if (box.x2 - box.x1 > srcWidth)
+ box.x2 = srcWidth + box.x1;
+ if (box.y2 - box.y1 > srcHeight)
+ box.y2 = srcHeight + box.y1;
+
+ DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
+ box.x1, box.x2, box.y1, box.y2);
+
+ sbox.x1 = box.x1 - dPriv->x;
+ sbox.y1 = box.y1 - dPriv->y;
+
+ assert(box.x1 < box.x2);
+ assert(box.y1 < box.y2);
+
+ /* XXX this could be done with pipe->surface_copy() */
+ BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
+ OUT_BATCH(CMD);
+ OUT_BATCH(BR13);
+ OUT_BATCH((box.y1 << 16) | box.x1);
+ OUT_BATCH((box.y2 << 16) | box.x2);
+
+ OUT_RELOC(intelScreen->front.buffer,
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+ DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
+ OUT_BATCH((sbox.y1 << 16) | sbox.x1);
+ OUT_BATCH((srcpitch * cpp) & 0xffff);
+ OUT_RELOC(dri_bo(surf->buffer),
+ DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+ DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
+
+ ADVANCE_BATCH();
+ }
+
+ if (intel->first_swap_fence)
+ driFenceUnReference(intel->first_swap_fence);
+ intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
+ driFenceReference(intel->first_swap_fence);
+ }
+
+ UNLOCK_HARDWARE(intel);
+
+ if (intel->lastStamp != dPriv->lastStamp) {
+ intelUpdateWindowSize(dPriv);
+ intel->lastStamp = dPriv->lastStamp;
+ }
+}
+
+
+
+/**
+ * This will be called whenever the currently bound window is moved/resized.
+ */
+void
+intelUpdateWindowSize(__DRIdrawablePrivate *dPriv)
+{
+ struct intel_framebuffer *intelfb = intel_framebuffer(dPriv);
+ assert(intelfb->stfb);
+ st_resize_framebuffer(intelfb->stfb, dPriv->w, dPriv->h);
+}
+
+
+
+void
+intelSwapBuffers(__DRIdrawablePrivate * dPriv)
+{
+ struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
+ struct pipe_surface *back_surf;
+
+ assert(intel_fb);
+ assert(intel_fb->stfb);
+
+ back_surf = st_get_framebuffer_surface(intel_fb->stfb,
+ ST_SURFACE_BACK_LEFT);
+ if (back_surf) {
+ st_notify_swapbuffers(intel_fb->stfb);
+ intelDisplaySurface(dPriv, back_surf, NULL);
+ st_notify_swapbuffers_complete(intel_fb->stfb);
+ }
+}
+
+
+/**
+ * Called via glXCopySubBufferMESA() to copy a subrect of the back
+ * buffer to the front buffer/screen.
+ */
+void
+intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
+{
+ struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
+ struct pipe_surface *back_surf;
+
+ assert(intel_fb);
+ assert(intel_fb->stfb);
+
+ back_surf = st_get_framebuffer_surface(intel_fb->stfb,
+ ST_SURFACE_BACK_LEFT);
+ if (back_surf) {
+ drm_clip_rect_t rect;
+ rect.x1 = x;
+ rect.y1 = y;
+ rect.x2 = w;
+ rect.y2 = h;
+
+ st_notify_swapbuffers(intel_fb->stfb);
+ intelDisplaySurface(dPriv, back_surf, &rect);
+ }
+}
diff --git a/src/gallium/winsys/dri/intel/intel_swapbuffers.h b/src/gallium/winsys/dri/intel/intel_swapbuffers.h
new file mode 100644
index 00000000000..7ae5fd15a5f
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_swapbuffers.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2006 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_SWAPBUFFERS_H
+#define INTEL_SWAPBUFFERS_H
+
+
+struct pipe_surface;
+
+
+extern void intelDisplaySurface(__DRIdrawablePrivate * dPriv,
+ struct pipe_surface *surf,
+ const drm_clip_rect_t * rect);
+
+extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
+
+extern void intelCopySubBuffer(__DRIdrawablePrivate * dPriv,
+ int x, int y, int w, int h);
+
+extern void intelUpdateWindowSize(__DRIdrawablePrivate *dPriv);
+
+
+#endif /* INTEL_SWAPBUFFERS_H */
diff --git a/src/gallium/winsys/dri/intel/intel_winsys.h b/src/gallium/winsys/dri/intel/intel_winsys.h
new file mode 100644
index 00000000000..ffc40782be7
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_winsys.h
@@ -0,0 +1,73 @@
+/**************************************************************************
+ *
+ * Copyright 2006 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_WINSYS_H
+#define INTEL_WINSYS_H
+
+#include "pipe/p_state.h"
+
+struct intel_context;
+struct pipe_context;
+struct pipe_winsys;
+struct pipe_buffer;
+struct _DriBufferObject;
+
+struct pipe_winsys *
+intel_create_pipe_winsys( int fd );
+
+void
+intel_destroy_pipe_winsys( struct pipe_winsys *winsys );
+
+struct pipe_context *
+intel_create_softpipe( struct intel_context *intel,
+ struct pipe_winsys *winsys );
+
+struct pipe_context *
+intel_create_i915simple( struct intel_context *intel,
+ struct pipe_winsys *winsys );
+
+
+struct intel_buffer {
+ struct pipe_buffer base;
+ struct _DriBufferObject *driBO;
+};
+
+static INLINE struct intel_buffer *
+intel_buffer( struct pipe_buffer *buf )
+{
+ return (struct intel_buffer *)buf;
+}
+
+static INLINE struct _DriBufferObject *
+dri_bo( struct pipe_buffer *buf )
+{
+ return intel_buffer(buf)->driBO;
+}
+
+
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/intel_winsys_i915.c b/src/gallium/winsys/dri/intel/intel_winsys_i915.c
new file mode 100644
index 00000000000..1ba6a9e1b25
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_winsys_i915.c
@@ -0,0 +1,154 @@
+/**************************************************************************
+ *
+ * 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: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include <stdlib.h>
+#include <xf86drm.h>
+#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
+
+#include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_winsys.h"
+
+#include "pipe/p_util.h"
+#include "pipe/i915simple/i915_winsys.h"
+
+
+struct intel_i915_winsys {
+ struct i915_winsys winsys; /**< batch buffer funcs */
+ struct intel_context *intel;
+};
+
+
+/* Turn a i915simple winsys into an intel/i915simple winsys:
+ */
+static inline struct intel_i915_winsys *
+intel_i915_winsys( struct i915_winsys *sws )
+{
+ return (struct intel_i915_winsys *)sws;
+}
+
+
+/* Simple batchbuffer interface:
+ */
+
+static unsigned *intel_i915_batch_start( struct i915_winsys *sws,
+ unsigned dwords,
+ unsigned relocs )
+{
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+
+ /* XXX: check relocs.
+ */
+ if (intel_batchbuffer_space( intel->batch ) >= dwords * 4) {
+ /* XXX: Hmm, the driver can't really do much with this pointer:
+ */
+ return (unsigned *)intel->batch->ptr;
+ }
+ else
+ return NULL;
+}
+
+static void intel_i915_batch_dword( struct i915_winsys *sws,
+ unsigned dword )
+{
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+ intel_batchbuffer_emit_dword( intel->batch, dword );
+}
+
+static void intel_i915_batch_reloc( struct i915_winsys *sws,
+ struct pipe_buffer *buf,
+ unsigned access_flags,
+ unsigned delta )
+{
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+ unsigned flags = DRM_BO_FLAG_MEM_TT;
+ unsigned mask = DRM_BO_MASK_MEM;
+
+ if (access_flags & I915_BUFFER_ACCESS_WRITE) {
+ flags |= DRM_BO_FLAG_WRITE;
+ mask |= DRM_BO_FLAG_WRITE;
+ }
+
+ if (access_flags & I915_BUFFER_ACCESS_READ) {
+ flags |= DRM_BO_FLAG_READ;
+ mask |= DRM_BO_FLAG_READ;
+ }
+
+ intel_batchbuffer_emit_reloc( intel->batch,
+ dri_bo( buf ),
+ flags, mask,
+ delta );
+}
+
+
+
+static void intel_i915_batch_flush( struct i915_winsys *sws )
+{
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+
+ intel_batchbuffer_flush( intel->batch );
+// if (0) intel_i915_batch_wait_idle( sws );
+}
+
+
+static void intel_i915_batch_finish( struct i915_winsys *sws )
+{
+ struct intel_context *intel = intel_i915_winsys(sws)->intel;
+ intel_batchbuffer_finish( intel->batch );
+}
+
+
+/**
+ * Create i915 hardware rendering context.
+ */
+struct pipe_context *
+intel_create_i915simple( struct intel_context *intel,
+ struct pipe_winsys *winsys )
+{
+ struct intel_i915_winsys *iws = CALLOC_STRUCT( intel_i915_winsys );
+
+ /* Fill in this struct with callbacks that i915simple will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ iws->winsys.batch_start = intel_i915_batch_start;
+ iws->winsys.batch_dword = intel_i915_batch_dword;
+ iws->winsys.batch_reloc = intel_i915_batch_reloc;
+ iws->winsys.batch_flush = intel_i915_batch_flush;
+ iws->winsys.batch_finish = intel_i915_batch_finish;
+ iws->intel = intel;
+
+ /* Create the i915simple context:
+ */
+ return i915_create( winsys,
+ &iws->winsys,
+ intel->intelScreen->deviceID );
+}
diff --git a/src/gallium/winsys/dri/intel/intel_winsys_pipe.c b/src/gallium/winsys/dri/intel/intel_winsys_pipe.c
new file mode 100644
index 00000000000..789a386500a
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_winsys_pipe.c
@@ -0,0 +1,302 @@
+/**************************************************************************
+ *
+ * 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: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include <stdlib.h>
+#include <xf86drm.h>
+#include "dri_bufpool.h"
+#include "dri_bufmgr.h"
+
+#include "intel_context.h"
+#include "intel_winsys.h"
+#include "intel_swapbuffers.h"
+#include "intel_batchbuffer.h"
+
+#include "pipe/p_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_state.h"
+#include "pipe/p_util.h"
+#include "pipe/p_inlines.h"
+
+
+
+struct intel_pipe_winsys {
+ struct pipe_winsys winsys;
+ struct _DriBufferPool *regionPool;
+};
+
+
+
+/* Turn a pipe winsys into an intel/pipe winsys:
+ */
+static inline struct intel_pipe_winsys *
+intel_pipe_winsys( struct pipe_winsys *winsys )
+{
+ return (struct intel_pipe_winsys *)winsys;
+}
+
+
+/* Most callbacks map direcly onto dri_bufmgr operations:
+ */
+static void *intel_buffer_map(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf,
+ unsigned flags )
+{
+ unsigned drm_flags = 0;
+
+ if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
+ drm_flags |= DRM_BO_FLAG_WRITE;
+
+ if (flags & PIPE_BUFFER_USAGE_CPU_READ)
+ drm_flags |= DRM_BO_FLAG_READ;
+
+ return driBOMap( dri_bo(buf), drm_flags, 0 );
+}
+
+static void intel_buffer_unmap(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ driBOUnmap( dri_bo(buf) );
+}
+
+
+static void
+intel_buffer_destroy(struct pipe_winsys *winsys,
+ struct pipe_buffer *buf)
+{
+ driBOUnReference( dri_bo(buf) );
+}
+
+
+/* Pipe has no concept of pools. We choose the tex/region pool
+ * for all buffers.
+ * Grabs the hardware lock!
+ */
+static struct pipe_buffer *
+intel_buffer_create(struct pipe_winsys *winsys,
+ unsigned alignment,
+ unsigned usage,
+ unsigned size )
+{
+ struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer );
+ struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
+ unsigned flags = 0;
+
+ buffer->base.refcount = 1;
+ buffer->base.alignment = alignment;
+ buffer->base.usage = usage;
+ buffer->base.size = size;
+
+ if (usage & (PIPE_BUFFER_USAGE_VERTEX /*| IWS_BUFFER_USAGE_LOCAL*/)) {
+ flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED;
+ } else {
+ flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT;
+ }
+
+ if (usage & PIPE_BUFFER_USAGE_GPU_READ)
+ flags |= DRM_BO_FLAG_READ;
+
+ if (usage & PIPE_BUFFER_USAGE_GPU_WRITE)
+ flags |= DRM_BO_FLAG_WRITE;
+
+ /* drm complains if we don't set any read/write flags.
+ */
+ if ((flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) == 0)
+ flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
+
+#if 0
+ if (flags & IWS_BUFFER_USAGE_EXE)
+ flags |= DRM_BO_FLAG_EXE;
+
+ if (usage & IWS_BUFFER_USAGE_CACHED)
+ flags |= DRM_BO_FLAG_CACHED;
+#endif
+
+ driGenBuffers( iws->regionPool,
+ "pipe buffer", 1, &buffer->driBO, alignment, flags, 0 );
+
+ driBOData( buffer->driBO, size, NULL, 0 );
+
+ return &buffer->base;
+}
+
+
+static struct pipe_buffer *
+intel_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
+{
+ struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer );
+ struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
+
+ driGenUserBuffer( iws->regionPool,
+ "pipe user buffer", &buffer->driBO, ptr, bytes);
+
+ return &buffer->base;
+}
+
+
+/* The state tracker (should!) keep track of whether the fake
+ * frontbuffer has been touched by any rendering since the last time
+ * we copied its contents to the real frontbuffer. Our task is easy:
+ */
+static void
+intel_flush_frontbuffer( struct pipe_winsys *winsys,
+ struct pipe_surface *surf,
+ void *context_private)
+{
+ struct intel_context *intel = (struct intel_context *) context_private;
+ __DRIdrawablePrivate *dPriv = intel->driDrawable;
+
+ intelDisplaySurface(dPriv, surf, NULL);
+}
+
+
+static struct pipe_surface *
+intel_i915_surface_alloc(struct pipe_winsys *winsys)
+{
+ struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
+ if (surf) {
+ surf->refcount = 1;
+ surf->winsys = winsys;
+ }
+ return surf;
+}
+
+
+/**
+ * Round n up to next multiple.
+ */
+static INLINE unsigned
+round_up(unsigned n, unsigned multiple)
+{
+ return (n + multiple - 1) & ~(multiple - 1);
+}
+
+/**
+ * Copied from xm_winsys.c
+ */
+static int
+intel_i915_surface_alloc_storage(struct pipe_winsys *winsys,
+ struct pipe_surface *surf,
+ unsigned width, unsigned height,
+ enum pipe_format format,
+ unsigned flags)
+{
+ const unsigned alignment = 64;
+ int ret;
+
+ surf->width = width;
+ surf->height = height;
+ surf->format = format;
+ surf->cpp = pf_get_size(format);
+ surf->pitch = round_up(width, alignment / surf->cpp);
+
+ assert(!surf->buffer);
+ surf->buffer = winsys->buffer_create(winsys, alignment,
+ PIPE_BUFFER_USAGE_PIXEL,
+ surf->pitch * surf->cpp * height);
+ if(!surf->buffer)
+ return -1;
+
+ return 0;
+}
+
+
+static void
+intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
+{
+ struct pipe_surface *surf = *s;
+ surf->refcount--;
+ if (surf->refcount == 0) {
+ if (surf->buffer)
+ pipe_buffer_reference(winsys, &surf->buffer, NULL);
+ free(surf);
+ }
+ *s = NULL;
+}
+
+
+
+static void
+intel_printf( struct pipe_winsys *winsys, const char *fmtString, ... )
+{
+ va_list args;
+ va_start( args, fmtString );
+ vfprintf(stderr, fmtString, args);
+ va_end( args );
+}
+
+static const char *
+intel_get_name( struct pipe_winsys *winsys )
+{
+ return "Intel/DRI/ttm";
+}
+
+
+struct pipe_winsys *
+intel_create_pipe_winsys( int fd )
+{
+ struct intel_pipe_winsys *iws = CALLOC_STRUCT( intel_pipe_winsys );
+
+ /* Fill in this struct with callbacks that pipe will need to
+ * communicate with the window system, buffer manager, etc.
+ *
+ * Pipe would be happy with a malloc based memory manager, but
+ * the SwapBuffers implementation in this winsys driver requires
+ * that rendering be done to an appropriate _DriBufferObject.
+ */
+ iws->winsys.buffer_create = intel_buffer_create;
+ iws->winsys.user_buffer_create = intel_user_buffer_create;
+ iws->winsys.buffer_map = intel_buffer_map;
+ iws->winsys.buffer_unmap = intel_buffer_unmap;
+ iws->winsys.buffer_destroy = intel_buffer_destroy;
+ iws->winsys.flush_frontbuffer = intel_flush_frontbuffer;
+ iws->winsys.printf = intel_printf;
+ iws->winsys.get_name = intel_get_name;
+ iws->winsys.surface_alloc = intel_i915_surface_alloc;
+ iws->winsys.surface_alloc_storage = intel_i915_surface_alloc_storage;
+ iws->winsys.surface_release = intel_i915_surface_release;
+
+ if (fd)
+ iws->regionPool = driDRMPoolInit(fd);
+
+ return &iws->winsys;
+}
+
+
+void
+intel_destroy_pipe_winsys( struct pipe_winsys *winsys )
+{
+ struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
+ if (iws->regionPool) {
+ driPoolTakeDown(iws->regionPool);
+ }
+ free(iws);
+}
+
diff --git a/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c
new file mode 100644
index 00000000000..cec3437831c
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/intel_winsys_softpipe.c
@@ -0,0 +1,81 @@
+/**************************************************************************
+ *
+ * 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: Keith Whitwell <keithw-at-tungstengraphics-dot-com>
+ */
+
+#include "intel_context.h"
+#include "intel_winsys.h"
+#include "pipe/p_defines.h"
+#include "pipe/p_util.h"
+#include "pipe/p_format.h"
+#include "pipe/softpipe/sp_winsys.h"
+
+
+struct intel_softpipe_winsys {
+ struct softpipe_winsys sws;
+ struct intel_context *intel;
+};
+
+/**
+ * Return list of surface formats supported by this driver.
+ */
+static boolean
+intel_is_format_supported(struct softpipe_winsys *sws,
+ enum pipe_format format)
+{
+ switch(format) {
+ case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_R5G6B5_UNORM:
+ case PIPE_FORMAT_S8Z24_UNORM:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/**
+ * Create rendering context which uses software rendering.
+ */
+struct pipe_context *
+intel_create_softpipe( struct intel_context *intel,
+ struct pipe_winsys *winsys )
+{
+ struct intel_softpipe_winsys *isws = CALLOC_STRUCT( intel_softpipe_winsys );
+
+ /* Fill in this struct with callbacks that softpipe will need to
+ * communicate with the window system, buffer manager, etc.
+ */
+ isws->sws.is_format_supported = intel_is_format_supported;
+ isws->intel = intel;
+
+ /* Create the softpipe context:
+ */
+ return softpipe_create( winsys, &isws->sws );
+}
diff --git a/src/gallium/winsys/dri/intel/server/i830_common.h b/src/gallium/winsys/dri/intel/server/i830_common.h
new file mode 100644
index 00000000000..d4d58886ce0
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/server/i830_common.h
@@ -0,0 +1,226 @@
+/**************************************************************************
+
+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.
+
+**************************************************************************/
+
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_common.h,v 1.1 2002/09/11 00:29:32 dawes Exp $ */
+
+#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_SET_VBLANK_PIPE 0x0d
+#define DRM_I830_GET_VBLANK_PIPE 0x0e
+
+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;
+
+ /* Triple buffering */
+ drm_handle_t third_handle;
+ int third_offset;
+ int third_size;
+ unsigned int third_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 DRM_I830_VBLANK_PIPE_A 1
+#define DRM_I830_VBLANK_PIPE_B 2
+
+typedef struct {
+ int pipe;
+} drmI830VBlankPipe;
+
+#endif /* _I830_DRM_H_ */
diff --git a/src/gallium/winsys/dri/intel/server/i830_dri.h b/src/gallium/winsys/dri/intel/server/i830_dri.h
new file mode 100644
index 00000000000..c2a3af8cbf7
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/server/i830_dri.h
@@ -0,0 +1,63 @@
+/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/i810/i830_dri.h,v 1.4 2002/10/30 12:52:18 alanh Exp $ */
+
+#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 7
+#define I830_PATCHLEVEL 2
+
+#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/gallium/winsys/dri/intel/server/intel.h b/src/gallium/winsys/dri/intel/server/intel.h
new file mode 100644
index 00000000000..6ea72499c1c
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/server/intel.h
@@ -0,0 +1,331 @@
+#ifndef _INTEL_H_
+#define _INTEL_H_
+
+#include "xf86drm.h" /* drm_handle_t, etc */
+
+/* Intel */
+#ifndef PCI_CHIP_I810
+#define PCI_CHIP_I810 0x7121
+#define PCI_CHIP_I810_DC100 0x7123
+#define PCI_CHIP_I810_E 0x7125
+#define PCI_CHIP_I815 0x1132
+#define PCI_CHIP_I810_BRIDGE 0x7120
+#define PCI_CHIP_I810_DC100_BRIDGE 0x7122
+#define PCI_CHIP_I810_E_BRIDGE 0x7124
+#define PCI_CHIP_I815_BRIDGE 0x1130
+#endif
+
+#define PCI_CHIP_845_G 0x2562
+#define PCI_CHIP_I830_M 0x3577
+
+#ifndef PCI_CHIP_I855_GM
+#define PCI_CHIP_I855_GM 0x3582
+#define PCI_CHIP_I855_GM_BRIDGE 0x3580
+#endif
+
+#ifndef PCI_CHIP_I865_G
+#define PCI_CHIP_I865_G 0x2572
+#define PCI_CHIP_I865_G_BRIDGE 0x2570
+#endif
+
+#ifndef PCI_CHIP_I915_G
+#define PCI_CHIP_I915_G 0x2582
+#define PCI_CHIP_I915_G_BRIDGE 0x2580
+#endif
+
+#ifndef PCI_CHIP_I915_GM
+#define PCI_CHIP_I915_GM 0x2592
+#define PCI_CHIP_I915_GM_BRIDGE 0x2590
+#endif
+
+#ifndef PCI_CHIP_E7221_G
+#define PCI_CHIP_E7221_G 0x258A
+/* Same as I915_G_BRIDGE */
+#define PCI_CHIP_E7221_G_BRIDGE 0x2580
+#endif
+
+#ifndef PCI_CHIP_I945_G
+#define PCI_CHIP_I945_G 0x2772
+#define PCI_CHIP_I945_G_BRIDGE 0x2770
+#endif
+
+#ifndef PCI_CHIP_I945_GM
+#define PCI_CHIP_I945_GM 0x27A2
+#define PCI_CHIP_I945_GM_BRIDGE 0x27A0
+#endif
+
+#define IS_I810(pI810) (pI810->Chipset == PCI_CHIP_I810 || \
+ pI810->Chipset == PCI_CHIP_I810_DC100 || \
+ pI810->Chipset == PCI_CHIP_I810_E)
+#define IS_I815(pI810) (pI810->Chipset == PCI_CHIP_I815)
+#define IS_I830(pI810) (pI810->Chipset == PCI_CHIP_I830_M)
+#define IS_845G(pI810) (pI810->Chipset == PCI_CHIP_845_G)
+#define IS_I85X(pI810) (pI810->Chipset == PCI_CHIP_I855_GM)
+#define IS_I852(pI810) (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I852_GM || pI810->variant == I852_GME))
+#define IS_I855(pI810) (pI810->Chipset == PCI_CHIP_I855_GM && (pI810->variant == I855_GM || pI810->variant == I855_GME))
+#define IS_I865G(pI810) (pI810->Chipset == PCI_CHIP_I865_G)
+
+#define IS_I915G(pI810) (pI810->Chipset == PCI_CHIP_I915_G || pI810->Chipset == PCI_CHIP_E7221_G)
+#define IS_I915GM(pI810) (pI810->Chipset == PCI_CHIP_I915_GM)
+#define IS_I945G(pI810) (pI810->Chipset == PCI_CHIP_I945_G)
+#define IS_I945GM(pI810) (pI810->Chipset == PCI_CHIP_I945_GM)
+#define IS_I9XX(pI810) (IS_I915G(pI810) || IS_I915GM(pI810) || IS_I945G(pI810) || IS_I945GM(pI810))
+
+#define IS_MOBILE(pI810) (IS_I830(pI810) || IS_I85X(pI810) || IS_I915GM(pI810) || IS_I945GM(pI810))
+
+#define I830_GMCH_CTRL 0x52
+
+#define I830_GMCH_MEM_MASK 0x1
+#define I830_GMCH_MEM_64M 0x1
+#define I830_GMCH_MEM_128M 0
+
+#define I830_GMCH_GMS_MASK 0x70
+#define I830_GMCH_GMS_DISABLED 0x00
+#define I830_GMCH_GMS_LOCAL 0x10
+#define I830_GMCH_GMS_STOLEN_512 0x20
+#define I830_GMCH_GMS_STOLEN_1024 0x30
+#define I830_GMCH_GMS_STOLEN_8192 0x40
+
+#define I855_GMCH_GMS_MASK (0x7 << 4)
+#define I855_GMCH_GMS_DISABLED 0x00
+#define I855_GMCH_GMS_STOLEN_1M (0x1 << 4)
+#define I855_GMCH_GMS_STOLEN_4M (0x2 << 4)
+#define I855_GMCH_GMS_STOLEN_8M (0x3 << 4)
+#define I855_GMCH_GMS_STOLEN_16M (0x4 << 4)
+#define I855_GMCH_GMS_STOLEN_32M (0x5 << 4)
+#define I915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
+#define I915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
+
+typedef unsigned char Bool;
+#define TRUE 1
+#define FALSE 0
+
+#define PIPE_NONE 0<<0
+#define PIPE_CRT 1<<0
+#define PIPE_TV 1<<1
+#define PIPE_DFP 1<<2
+#define PIPE_LFP 1<<3
+#define PIPE_CRT2 1<<4
+#define PIPE_TV2 1<<5
+#define PIPE_DFP2 1<<6
+#define PIPE_LFP2 1<<7
+
+typedef struct _I830MemPool *I830MemPoolPtr;
+typedef struct _I830MemRange *I830MemRangePtr;
+typedef struct _I830MemRange {
+ long Start;
+ long End;
+ long Size;
+ unsigned long Physical;
+ unsigned long Offset; /* Offset of AGP-allocated portion */
+ unsigned long Alignment;
+ drm_handle_t Key;
+ unsigned long Pitch; // add pitch
+ I830MemPoolPtr Pool;
+} I830MemRange;
+
+typedef struct _I830MemPool {
+ I830MemRange Total;
+ I830MemRange Free;
+ I830MemRange Fixed;
+ I830MemRange Allocated;
+} I830MemPool;
+
+typedef struct {
+ int tail_mask;
+ I830MemRange mem;
+ unsigned char *virtual_start;
+ int head;
+ int tail;
+ int space;
+} I830RingBuffer;
+
+typedef struct _I830Rec {
+ unsigned char *MMIOBase;
+ unsigned char *FbBase;
+ int cpp;
+ uint32_t aper_size;
+ unsigned int bios_version;
+
+ /* These are set in PreInit and never changed. */
+ long FbMapSize;
+ long TotalVideoRam;
+ I830MemRange StolenMemory; /* pre-allocated memory */
+ long BIOSMemorySize; /* min stolen pool size */
+ int BIOSMemSizeLoc;
+
+ /* These change according to what has been allocated. */
+ long FreeMemory;
+ I830MemRange MemoryAperture;
+ I830MemPool StolenPool;
+ long allocatedMemory;
+
+ /* Regions allocated either from the above pools, or from agpgart. */
+ /* for single and dual head configurations */
+ I830MemRange FrontBuffer;
+ I830MemRange FrontBuffer2;
+ I830MemRange Scratch;
+ I830MemRange Scratch2;
+
+ I830RingBuffer *LpRing;
+
+ I830MemRange BackBuffer;
+ I830MemRange DepthBuffer;
+ I830MemRange TexMem;
+ int TexGranularity;
+ I830MemRange ContextMem;
+ int drmMinor;
+ Bool have3DWindows;
+
+ Bool NeedRingBufferLow;
+ Bool allowPageFlip;
+ Bool disableTiling;
+
+ int Chipset;
+ unsigned long LinearAddr;
+ unsigned long MMIOAddr;
+
+ drmSize registerSize; /**< \brief MMIO register map size */
+ drm_handle_t registerHandle; /**< \brief MMIO register map handle */
+ // IOADDRESS ioBase;
+ int irq; /**< \brief IRQ number */
+ int GttBound;
+
+ drm_handle_t ring_map;
+ unsigned int Fence[8];
+
+} I830Rec;
+
+/*
+ * 12288 is set as the maximum, chosen because it is enough for
+ * 1920x1440@32bpp with a 2048 pixel line pitch with some to spare.
+ */
+#define I830_MAXIMUM_VBIOS_MEM 12288
+#define I830_DEFAULT_VIDEOMEM_2D (MB(32) / 1024)
+#define I830_DEFAULT_VIDEOMEM_3D (MB(64) / 1024)
+
+/* Flags for memory allocation function */
+#define FROM_ANYWHERE 0x00000000
+#define FROM_POOL_ONLY 0x00000001
+#define FROM_NEW_ONLY 0x00000002
+#define FROM_MASK 0x0000000f
+
+#define ALLOCATE_AT_TOP 0x00000010
+#define ALLOCATE_AT_BOTTOM 0x00000020
+#define FORCE_GAPS 0x00000040
+
+#define NEED_PHYSICAL_ADDR 0x00000100
+#define ALIGN_BOTH_ENDS 0x00000200
+#define FORCE_LOW 0x00000400
+
+#define ALLOC_NO_TILING 0x00001000
+#define ALLOC_INITIAL 0x00002000
+
+#define ALLOCATE_DRY_RUN 0x80000000
+
+/* Chipset registers for VIDEO BIOS memory RW access */
+#define _855_DRAM_RW_CONTROL 0x58
+#define _845_DRAM_RW_CONTROL 0x90
+#define DRAM_WRITE 0x33330000
+
+#define KB(x) ((x) * 1024)
+#define MB(x) ((x) * KB(1024))
+
+#define GTT_PAGE_SIZE KB(4)
+#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y))
+#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y))
+#define ROUND_TO_PAGE(x) ROUND_TO((x), GTT_PAGE_SIZE)
+#define ROUND_TO_MB(x) ROUND_TO((x), MB(1))
+#define PRIMARY_RINGBUFFER_SIZE KB(128)
+
+
+/* Ring buffer registers, p277, overview p19
+ */
+#define LP_RING 0x2030
+#define HP_RING 0x2040
+
+#define RING_TAIL 0x00
+#define TAIL_ADDR 0x000FFFF8
+#define I830_TAIL_MASK 0x001FFFF8
+
+#define RING_HEAD 0x04
+#define HEAD_WRAP_COUNT 0xFFE00000
+#define HEAD_WRAP_ONE 0x00200000
+#define HEAD_ADDR 0x001FFFFC
+#define I830_HEAD_MASK 0x001FFFFC
+
+#define RING_START 0x08
+#define START_ADDR 0x03FFFFF8
+#define I830_RING_START_MASK 0xFFFFF000
+
+#define RING_LEN 0x0C
+#define RING_NR_PAGES 0x001FF000
+#define I830_RING_NR_PAGES 0x001FF000
+#define RING_REPORT_MASK 0x00000006
+#define RING_REPORT_64K 0x00000002
+#define RING_REPORT_128K 0x00000004
+#define RING_NO_REPORT 0x00000000
+#define RING_VALID_MASK 0x00000001
+#define RING_VALID 0x00000001
+#define RING_INVALID 0x00000000
+
+
+/* Fence/Tiling ranges [0..7]
+ */
+#define FENCE 0x2000
+#define FENCE_NR 8
+
+#define I915G_FENCE_START_MASK 0x0ff00000
+
+#define I830_FENCE_START_MASK 0x07f80000
+
+#define FENCE_START_MASK 0x03F80000
+#define FENCE_X_MAJOR 0x00000000
+#define FENCE_Y_MAJOR 0x00001000
+#define FENCE_SIZE_MASK 0x00000700
+#define FENCE_SIZE_512K 0x00000000
+#define FENCE_SIZE_1M 0x00000100
+#define FENCE_SIZE_2M 0x00000200
+#define FENCE_SIZE_4M 0x00000300
+#define FENCE_SIZE_8M 0x00000400
+#define FENCE_SIZE_16M 0x00000500
+#define FENCE_SIZE_32M 0x00000600
+#define FENCE_SIZE_64M 0x00000700
+#define I915G_FENCE_SIZE_1M 0x00000000
+#define I915G_FENCE_SIZE_2M 0x00000100
+#define I915G_FENCE_SIZE_4M 0x00000200
+#define I915G_FENCE_SIZE_8M 0x00000300
+#define I915G_FENCE_SIZE_16M 0x00000400
+#define I915G_FENCE_SIZE_32M 0x00000500
+#define I915G_FENCE_SIZE_64M 0x00000600
+#define I915G_FENCE_SIZE_128M 0x00000700
+#define FENCE_PITCH_1 0x00000000
+#define FENCE_PITCH_2 0x00000010
+#define FENCE_PITCH_4 0x00000020
+#define FENCE_PITCH_8 0x00000030
+#define FENCE_PITCH_16 0x00000040
+#define FENCE_PITCH_32 0x00000050
+#define FENCE_PITCH_64 0x00000060
+#define FENCE_VALID 0x00000001
+
+#include <mmio.h>
+
+# define MMIO_IN8(base, offset) \
+ *(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
+# define MMIO_IN32(base, offset) \
+ read_MMIO_LE32(base, offset)
+# define MMIO_OUT8(base, offset, val) \
+ *(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
+# define MMIO_OUT32(base, offset, val) \
+ *(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = CPU_TO_LE32(val)
+
+
+ /* Memory mapped register access macros */
+#define INREG8(addr) MMIO_IN8(MMIO, addr)
+#define INREG(addr) MMIO_IN32(MMIO, addr)
+#define OUTREG8(addr, val) MMIO_OUT8(MMIO, addr, val)
+#define OUTREG(addr, val) MMIO_OUT32(MMIO, addr, val)
+
+#define DSPABASE 0x70184
+
+#endif
diff --git a/src/gallium/winsys/dri/intel/server/intel_dri.c b/src/gallium/winsys/dri/intel/server/intel_dri.c
new file mode 100644
index 00000000000..e49c4214ad4
--- /dev/null
+++ b/src/gallium/winsys/dri/intel/server/intel_dri.c
@@ -0,0 +1,1306 @@
+/**
+ * \file server/intel_dri.c
+ * \brief File to perform the device-specific initialization tasks typically
+ * done in the X server.
+ *
+ * Here they are converted to run in the client (or perhaps a standalone
+ * process), and to work with the frame buffer device rather than the X
+ * server infrastructure.
+ *
+ * Copyright (C) 2006 Dave Airlie (airlied@linux.ie)
+
+ 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 THE COPYRIGHT HOLDERS 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.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "driver.h"
+#include "drm.h"
+
+#include "intel.h"
+#include "i830_dri.h"
+
+#include "memops.h"
+#include "pciaccess.h"
+
+static size_t drm_page_size;
+static int nextTile = 0;
+#define xf86DrvMsg(...) do {} while(0)
+
+static const int pitches[] = {
+ 128 * 8,
+ 128 * 16,
+ 128 * 32,
+ 128 * 64,
+ 0
+};
+
+static Bool I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea);
+
+static unsigned long
+GetBestTileAlignment(unsigned long size)
+{
+ unsigned long i;
+
+ for (i = KB(512); i < size; i <<= 1)
+ ;
+
+ if (i > MB(64))
+ i = MB(64);
+
+ return i;
+}
+
+static void SetFenceRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+ unsigned char *MMIO = ctx->MMIOAddress;
+
+ for (i = 0; i < 8; i++) {
+ OUTREG(FENCE + i * 4, pI830->Fence[i]);
+ // if (I810_DEBUG & DEBUG_VERBOSE_VGA)
+ fprintf(stderr,"Fence Register : %x\n", pI830->Fence[i]);
+ }
+}
+
+/* Tiled memory is good... really, really good...
+ *
+ * Need to make it less likely that we miss out on this - probably
+ * need to move the frontbuffer away from the 'guarenteed' alignment
+ * of the first memory segment, or perhaps allocate a discontigous
+ * framebuffer to get more alignment 'sweet spots'.
+ */
+static void
+SetFence(const DRIDriverContext *ctx, I830Rec *pI830,
+ int nr, unsigned int start, unsigned int pitch,
+ unsigned int size)
+{
+ unsigned int val;
+ unsigned int fence_mask = 0;
+ unsigned int fence_pitch;
+
+ if (nr < 0 || nr > 7) {
+ fprintf(stderr,
+ "SetFence: fence %d out of range\n",nr);
+ return;
+ }
+
+ pI830->Fence[nr] = 0;
+
+ if (IS_I9XX(pI830))
+ fence_mask = ~I915G_FENCE_START_MASK;
+ else
+ fence_mask = ~I830_FENCE_START_MASK;
+
+ if (start & fence_mask) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not %s aligned\n",
+ nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
+ return;
+ }
+
+ if (start % size) {
+ fprintf(stderr,
+ "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
+ nr, start, size / 1024);
+ return;
+ }
+
+ if (pitch & 127) {
+ fprintf(stderr,
+ "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
+ nr, pitch);
+ return;
+ }
+
+ val = (start | FENCE_X_MAJOR | FENCE_VALID);
+
+ if (IS_I9XX(pI830)) {
+ switch (size) {
+ case MB(1):
+ val |= I915G_FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= I915G_FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= I915G_FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= I915G_FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= I915G_FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= I915G_FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= I915G_FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ } else {
+ switch (size) {
+ case KB(512):
+ val |= FENCE_SIZE_512K;
+ break;
+ case MB(1):
+ val |= FENCE_SIZE_1M;
+ break;
+ case MB(2):
+ val |= FENCE_SIZE_2M;
+ break;
+ case MB(4):
+ val |= FENCE_SIZE_4M;
+ break;
+ case MB(8):
+ val |= FENCE_SIZE_8M;
+ break;
+ case MB(16):
+ val |= FENCE_SIZE_16M;
+ break;
+ case MB(32):
+ val |= FENCE_SIZE_32M;
+ break;
+ case MB(64):
+ val |= FENCE_SIZE_64M;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
+ return;
+ }
+ }
+
+ if (IS_I9XX(pI830))
+ fence_pitch = pitch / 512;
+ else
+ fence_pitch = pitch / 128;
+
+ switch (fence_pitch) {
+ case 1:
+ val |= FENCE_PITCH_1;
+ break;
+ case 2:
+ val |= FENCE_PITCH_2;
+ break;
+ case 4:
+ val |= FENCE_PITCH_4;
+ break;
+ case 8:
+ val |= FENCE_PITCH_8;
+ break;
+ case 16:
+ val |= FENCE_PITCH_16;
+ break;
+ case 32:
+ val |= FENCE_PITCH_32;
+ break;
+ case 64:
+ val |= FENCE_PITCH_64;
+ break;
+ default:
+ fprintf(stderr,
+ "SetFence: %d: illegal pitch (%d)\n", nr, pitch);
+ return;
+ }
+
+ pI830->Fence[nr] = val;
+}
+
+static Bool
+MakeTiles(const DRIDriverContext *ctx, I830Rec *pI830, I830MemRange *pMem)
+{
+ int pitch, ntiles, i;
+
+ pitch = pMem->Pitch * ctx->cpp;
+ /*
+ * Simply try to break the region up into at most four pieces of size
+ * equal to the alignment.
+ */
+ ntiles = ROUND_TO(pMem->Size, pMem->Alignment) / pMem->Alignment;
+ if (ntiles >= 4) {
+ return FALSE;
+ }
+
+ for (i = 0; i < ntiles; i++, nextTile++) {
+ SetFence(ctx, pI830, nextTile, pMem->Start + i * pMem->Alignment,
+ pitch, pMem->Alignment);
+ }
+ return TRUE;
+}
+
+static void I830SetupMemoryTiling(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ int i;
+
+ /* Clear out */
+ for (i = 0; i < 8; i++)
+ pI830->Fence[i] = 0;
+
+ nextTile = 0;
+
+ if (pI830->BackBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->BackBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the back buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the back buffer.\n");
+ pI830->allowPageFlip = FALSE;
+ }
+ }
+
+ if (pI830->DepthBuffer.Alignment >= KB(512)) {
+ if (MakeTiles(ctx, pI830, &(pI830->DepthBuffer))) {
+ fprintf(stderr,
+ "Activating tiled memory for the depth buffer.\n");
+ } else {
+ fprintf(stderr,
+ "MakeTiles failed for the depth buffer.\n");
+ }
+ }
+
+ return;
+}
+
+static int I830DetectMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ struct pci_device host_bridge, ig_dev;
+ uint32_t gmch_ctrl;
+ int memsize = 0;
+ int range;
+ uint32_t aper_size;
+ uint32_t membase2 = 0;
+
+ memset(&host_bridge, 0, sizeof(host_bridge));
+ memset(&ig_dev, 0, sizeof(ig_dev));
+
+ ig_dev.dev = 2;
+
+ pci_device_cfg_read_u32(&host_bridge, &gmch_ctrl, I830_GMCH_CTRL);
+
+ if (IS_I830(pI830) || IS_845G(pI830)) {
+ if ((gmch_ctrl & I830_GMCH_MEM_MASK) == I830_GMCH_MEM_128M) {
+ aper_size = 0x80000000;
+ } else {
+ aper_size = 0x40000000;
+ }
+ } else {
+ if (IS_I9XX(pI830)) {
+ int ret;
+ ret = pci_device_cfg_read_u32(&ig_dev, &membase2, 0x18);
+ if (membase2 & 0x08000000)
+ aper_size = 0x8000000;
+ else
+ aper_size = 0x10000000;
+
+ fprintf(stderr,"aper size is %08X %08x %d\n", aper_size, membase2, ret);
+ } else
+ aper_size = 0x8000000;
+ }
+
+ pI830->aper_size = aper_size;
+
+
+ /* We need to reduce the stolen size, by the GTT and the popup.
+ * The GTT varying according the the FbMapSize and the popup is 4KB */
+ range = (ctx->shared.fbSize / (1024*1024)) + 4;
+
+ if (IS_I85X(pI830) || IS_I865G(pI830) || IS_I9XX(pI830)) {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I855_GMCH_GMS_STOLEN_1M:
+ memsize = MB(1) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_4M:
+ memsize = MB(4) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_8M:
+ memsize = MB(8) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_16M:
+ memsize = MB(16) - KB(range);
+ break;
+ case I855_GMCH_GMS_STOLEN_32M:
+ memsize = MB(32) - KB(range);
+ break;
+ case I915G_GMCH_GMS_STOLEN_48M:
+ if (IS_I9XX(pI830))
+ memsize = MB(48) - KB(range);
+ break;
+ case I915G_GMCH_GMS_STOLEN_64M:
+ if (IS_I9XX(pI830))
+ memsize = MB(64) - KB(range);
+ break;
+ }
+ } else {
+ switch (gmch_ctrl & I830_GMCH_GMS_MASK) {
+ case I830_GMCH_GMS_STOLEN_512:
+ memsize = KB(512) - KB(range);
+ break;
+ case I830_GMCH_GMS_STOLEN_1024:
+ memsize = MB(1) - KB(range);
+ break;
+ case I830_GMCH_GMS_STOLEN_8192:
+ memsize = MB(8) - KB(range);
+ break;
+ case I830_GMCH_GMS_LOCAL:
+ memsize = 0;
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Local memory found, but won't be used.\n");
+ break;
+ }
+ }
+ if (memsize > 0) {
+ fprintf(stderr,
+ "detected %d kB stolen memory.\n", memsize / 1024);
+ } else {
+ fprintf(stderr,
+ "no video memory detected.\n");
+ }
+ return memsize;
+}
+
+static int AgpInit(const DRIDriverContext *ctx, I830Rec *info)
+{
+ unsigned long mode = 0x4;
+
+ if (drmAgpAcquire(ctx->drmFD) < 0) {
+ fprintf(stderr, "[gart] AGP not available\n");
+ return 0;
+ }
+
+ if (drmAgpEnable(ctx->drmFD, mode) < 0) {
+ fprintf(stderr, "[gart] AGP not enabled\n");
+ drmAgpRelease(ctx->drmFD);
+ return 0;
+ }
+ else
+ fprintf(stderr, "[gart] AGP enabled at %dx\n", ctx->agpmode);
+
+ return 1;
+}
+
+/*
+ * Allocate memory from the given pool. Grow the pool if needed and if
+ * possible.
+ */
+static unsigned long
+AllocFromPool(const DRIDriverContext *ctx, I830Rec *pI830,
+ I830MemRange *result, I830MemPool *pool,
+ long size, unsigned long alignment, int flags)
+{
+ long needed, start, end;
+
+ if (!result || !pool || !size)
+ return 0;
+
+ /* Calculate how much space is needed. */
+ if (alignment <= GTT_PAGE_SIZE)
+ needed = size;
+ else {
+ start = ROUND_TO(pool->Free.Start, alignment);
+ end = ROUND_TO(start + size, alignment);
+ needed = end - pool->Free.Start;
+ }
+ if (needed > pool->Free.Size) {
+ return 0;
+ }
+
+ result->Start = ROUND_TO(pool->Free.Start, alignment);
+ pool->Free.Start += needed;
+ result->End = pool->Free.Start;
+
+ pool->Free.Size = pool->Free.End - pool->Free.Start;
+ result->Size = result->End - result->Start;
+ result->Pool = pool;
+ result->Alignment = alignment;
+ return needed;
+}
+
+static unsigned long AllocFromAGP(const DRIDriverContext *ctx, I830Rec *pI830, long size, unsigned long alignment, I830MemRange *result)
+{
+ unsigned long start, end;
+ unsigned long newApStart, newApEnd;
+ int ret;
+ if (!result || !size)
+ return 0;
+
+ if (!alignment)
+ alignment = 4;
+
+ start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
+ end = ROUND_TO(start + size, alignment);
+ newApStart = end;
+ newApEnd = pI830->MemoryAperture.End;
+
+ ret=drmAgpAlloc(ctx->drmFD, size, 0, &(result->Physical), (drm_handle_t *)&(result->Key));
+
+ if (ret)
+ {
+ fprintf(stderr,"drmAgpAlloc failed %d\n", ret);
+ return 0;
+ }
+ pI830->allocatedMemory += size;
+ pI830->MemoryAperture.Start = newApStart;
+ pI830->MemoryAperture.End = newApEnd;
+ pI830->MemoryAperture.Size = newApEnd - newApStart;
+ // pI830->FreeMemory -= size;
+ result->Start = start;
+ result->End = start + size;
+ result->Size = size;
+ result->Offset = start;
+ result->Alignment = alignment;
+ result->Pool = NULL;
+
+ return size;
+}
+
+unsigned long
+I830AllocVidMem(const DRIDriverContext *ctx, I830Rec *pI830,
+ I830MemRange *result, I830MemPool *pool, long size,
+ unsigned long alignment, int flags)
+{
+ unsigned long ret;
+
+ if (!result)
+ return 0;
+
+ /* Make sure these are initialised. */
+ result->Size = 0;
+ result->Key = -1;
+
+ if (!size) {
+ return 0;
+ }
+
+ if (pool->Free.Size < size) {
+ ret = AllocFromAGP(ctx, pI830, size, alignment, result);
+ }
+ else {
+ ret = AllocFromPool(ctx, pI830, result, pool, size, alignment, flags);
+ if (ret == 0)
+ ret = AllocFromAGP(ctx, pI830, size, alignment, result);
+ }
+ return ret;
+}
+
+static Bool BindAgpRange(const DRIDriverContext *ctx, I830MemRange *mem)
+{
+ if (!mem)
+ return FALSE;
+
+ if (mem->Key == -1)
+ return TRUE;
+
+ return !drmAgpBind(ctx->drmFD, mem->Key, mem->Offset);
+}
+
+/* simple memory allocation routines needed */
+/* put ring buffer in low memory */
+/* need to allocate front, back, depth buffers aligned correctly,
+ allocate ring buffer,
+*/
+
+/* */
+static Bool
+I830AllocateMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ unsigned long size, ret;
+ unsigned long lines, lineSize, align;
+
+ /* allocate ring buffer */
+ memset(pI830->LpRing, 0, sizeof(I830RingBuffer));
+ pI830->LpRing->mem.Key = -1;
+
+ size = PRIMARY_RINGBUFFER_SIZE;
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->LpRing->mem, &pI830->StolenPool, size, 0x1000, 0);
+
+ if (ret != size)
+ {
+ fprintf(stderr,"unable to allocate ring buffer %ld\n", ret);
+ return FALSE;
+ }
+
+ pI830->LpRing->tail_mask = pI830->LpRing->mem.Size - 1;
+
+
+ /* allocate front buffer */
+ memset(&(pI830->FrontBuffer), 0, sizeof(pI830->FrontBuffer));
+ pI830->FrontBuffer.Key = -1;
+ pI830->FrontBuffer.Pitch = ctx->shared.virtualWidth;
+
+ align = KB(512);
+
+ lineSize = ctx->shared.virtualWidth * ctx->cpp;
+ lines = (ctx->shared.virtualHeight + 15) / 16 * 16;
+ size = lineSize * lines;
+ size = ROUND_TO_PAGE(size);
+
+ align = GetBestTileAlignment(size);
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->FrontBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
+ {
+ fprintf(stderr,"unable to allocate front buffer %ld\n", ret);
+ return FALSE;
+ }
+
+ memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
+ pI830->BackBuffer.Key = -1;
+ pI830->BackBuffer.Pitch = ctx->shared.virtualWidth;
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->BackBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
+ {
+ fprintf(stderr,"unable to allocate back buffer %ld\n", ret);
+ return FALSE;
+ }
+
+ memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
+ pI830->DepthBuffer.Key = -1;
+ pI830->DepthBuffer.Pitch = ctx->shared.virtualWidth;
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->DepthBuffer, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
+ {
+ fprintf(stderr,"unable to allocate depth buffer %ld\n", ret);
+ return FALSE;
+ }
+
+ memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
+ pI830->ContextMem.Key = -1;
+ size = KB(32);
+
+ ret = I830AllocVidMem(ctx, pI830, &pI830->ContextMem, &pI830->StolenPool, size, align, 0);
+ if (ret < size)
+ {
+ fprintf(stderr,"unable to allocate context buffer %ld\n", ret);
+ return FALSE;
+ }
+
+#if 0
+ memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
+ pI830->TexMem.Key = -1;
+
+ size = 32768 * 1024;
+ ret = AllocFromAGP(ctx, pI830, size, align, &pI830->TexMem);
+ if (ret < size)
+ {
+ fprintf(stderr,"unable to allocate texture memory %ld\n", ret);
+ return FALSE;
+ }
+#endif
+
+ return TRUE;
+}
+
+static Bool
+I830BindMemory(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ if (!BindAgpRange(ctx, &pI830->LpRing->mem))
+ return FALSE;
+ if (!BindAgpRange(ctx, &pI830->FrontBuffer))
+ return FALSE;
+ if (!BindAgpRange(ctx, &pI830->BackBuffer))
+ return FALSE;
+ if (!BindAgpRange(ctx, &pI830->DepthBuffer))
+ return FALSE;
+ if (!BindAgpRange(ctx, &pI830->ContextMem))
+ return FALSE;
+#if 0
+ if (!BindAgpRange(ctx, &pI830->TexMem))
+ return FALSE;
+#endif
+ return TRUE;
+}
+
+static void SetupDRIMM(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ unsigned long aperEnd = ROUND_DOWN_TO(pI830->aper_size, GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
+ unsigned long aperStart = ROUND_TO(pI830->aper_size - KB(32768), GTT_PAGE_SIZE) / GTT_PAGE_SIZE;
+
+ fprintf(stderr, "aper size is %08X\n", ctx->shared.fbSize);
+ if (drmMMInit(ctx->drmFD, aperStart, aperEnd - aperStart, DRM_BO_MEM_TT)) {
+ fprintf(stderr,
+ "DRM MM Initialization Failed\n");
+ } else {
+ fprintf(stderr,
+ "DRM MM Initialized at offset 0x%lx length %d page\n", aperStart, aperEnd-aperStart);
+ }
+
+}
+
+static Bool
+I830CleanupDma(const DRIDriverContext *ctx)
+{
+ drmI830Init info;
+
+ memset(&info, 0, sizeof(drmI830Init));
+ info.func = I830_CLEANUP_DMA;
+
+ if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+ &info, sizeof(drmI830Init))) {
+ fprintf(stderr, "I830 Dma Cleanup Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830InitDma(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ I830RingBuffer *ring = pI830->LpRing;
+ drmI830Init info;
+
+ memset(&info, 0, sizeof(drmI830Init));
+ info.func = I830_INIT_DMA;
+
+ info.ring_start = ring->mem.Start + pI830->LinearAddr;
+ info.ring_end = ring->mem.End + pI830->LinearAddr;
+ info.ring_size = ring->mem.Size;
+
+ info.mmio_offset = (unsigned int)ctx->MMIOStart;
+
+ info.sarea_priv_offset = sizeof(drm_sarea_t);
+
+ info.front_offset = pI830->FrontBuffer.Start;
+ info.back_offset = pI830->BackBuffer.Start;
+ info.depth_offset = pI830->DepthBuffer.Start;
+ info.w = ctx->shared.virtualWidth;
+ info.h = ctx->shared.virtualHeight;
+ info.pitch = ctx->shared.virtualWidth;
+ info.back_pitch = pI830->BackBuffer.Pitch;
+ info.depth_pitch = pI830->DepthBuffer.Pitch;
+ info.cpp = ctx->cpp;
+
+ if (drmCommandWrite(ctx->drmFD, DRM_I830_INIT,
+ &info, sizeof(drmI830Init))) {
+ fprintf(stderr,
+ "I830 Dma Initialization Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int I830CheckDRMVersion( const DRIDriverContext *ctx,
+ I830Rec *pI830 )
+{
+ drmVersionPtr version;
+
+ version = drmGetVersion(ctx->drmFD);
+
+ if (version) {
+ int req_minor, req_patch;
+
+ req_minor = 4;
+ req_patch = 0;
+
+ if (version->version_major != 1 ||
+ version->version_minor < req_minor ||
+ (version->version_minor == req_minor &&
+ version->version_patchlevel < req_patch)) {
+ /* Incompatible drm version */
+ fprintf(stderr,
+ "[dri] I830DRIScreenInit failed because of a version "
+ "mismatch.\n"
+ "[dri] i915.o kernel module version is %d.%d.%d "
+ "but version 1.%d.%d or newer is needed.\n"
+ "[dri] Disabling DRI.\n",
+ version->version_major,
+ version->version_minor,
+ version->version_patchlevel,
+ req_minor,
+ req_patch);
+ drmFreeVersion(version);
+ return 0;
+ }
+
+ pI830->drmMinor = version->version_minor;
+ drmFreeVersion(version);
+ }
+ return 1;
+}
+
+static void
+I830SetRingRegs(const DRIDriverContext *ctx, I830Rec *pI830)
+{
+ unsigned int itemp;
+ unsigned char *MMIO = ctx->MMIOAddress;
+
+ OUTREG(LP_RING + RING_LEN, 0);
+ OUTREG(LP_RING + RING_TAIL, 0);
+ OUTREG(LP_RING + RING_HEAD, 0);
+
+ if ((long)(pI830->LpRing->mem.Start & I830_RING_START_MASK) !=
+ pI830->LpRing->mem.Start) {
+ fprintf(stderr,
+ "I830SetRingRegs: Ring buffer start (%lx) violates its "
+ "mask (%x)\n", pI830->LpRing->mem.Start, I830_RING_START_MASK);
+ }
+ /* Don't care about the old value. Reserved bits must be zero anyway. */
+ itemp = pI830->LpRing->mem.Start & I830_RING_START_MASK;
+ OUTREG(LP_RING + RING_START, itemp);
+
+ if (((pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES) !=
+ pI830->LpRing->mem.Size - 4096) {
+ fprintf(stderr,
+ "I830SetRingRegs: Ring buffer size - 4096 (%lx) violates its "
+ "mask (%x)\n", pI830->LpRing->mem.Size - 4096,
+ I830_RING_NR_PAGES);
+ }
+ /* Don't care about the old value. Reserved bits must be zero anyway. */
+ itemp = (pI830->LpRing->mem.Size - 4096) & I830_RING_NR_PAGES;
+ itemp |= (RING_NO_REPORT | RING_VALID);
+ OUTREG(LP_RING + RING_LEN, itemp);
+
+ pI830->LpRing->head = INREG(LP_RING + RING_HEAD) & I830_HEAD_MASK;
+ pI830->LpRing->tail = INREG(LP_RING + RING_TAIL);
+ pI830->LpRing->space = pI830->LpRing->head - (pI830->LpRing->tail + 8);
+ if (pI830->LpRing->space < 0)
+ pI830->LpRing->space += pI830->LpRing->mem.Size;
+
+ SetFenceRegs(ctx, pI830);
+
+ /* RESET THE DISPLAY PIPE TO POINT TO THE FRONTBUFFER - hacky
+ hacky hacky */
+ OUTREG(DSPABASE, pI830->FrontBuffer.Start + pI830->LinearAddr);
+
+}
+
+static Bool
+I830SetParam(const DRIDriverContext *ctx, int param, int value)
+{
+ drmI830SetParam sp;
+
+ memset(&sp, 0, sizeof(sp));
+ sp.param = param;
+ sp.value = value;
+
+ if (drmCommandWrite(ctx->drmFD, DRM_I830_SETPARAM, &sp, sizeof(sp))) {
+ fprintf(stderr, "I830 SetParam Failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static Bool
+I830DRIMapScreenRegions(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+ fprintf(stderr,
+ "[drm] Mapping front buffer\n");
+
+ if (drmAddMap(ctx->drmFD,
+ (drm_handle_t)(sarea->front_offset + pI830->LinearAddr),
+ sarea->front_size,
+ DRM_FRAME_BUFFER, /*DRM_AGP,*/
+ 0,
+ &sarea->front_handle) < 0) {
+ fprintf(stderr,
+ "[drm] drmAddMap(front_handle) failed. Disabling DRI\n");
+ return FALSE;
+ }
+ ctx->shared.hFrameBuffer = sarea->front_handle;
+ ctx->shared.fbSize = sarea->front_size;
+ fprintf(stderr, "[drm] Front Buffer = 0x%08x\n",
+ sarea->front_handle);
+
+ if (drmAddMap(ctx->drmFD,
+ (drm_handle_t)(sarea->back_offset),
+ sarea->back_size, DRM_AGP, 0,
+ &sarea->back_handle) < 0) {
+ fprintf(stderr,
+ "[drm] drmAddMap(back_handle) failed. Disabling DRI\n");
+ return FALSE;
+ }
+ fprintf(stderr, "[drm] Back Buffer = 0x%08x\n",
+ sarea->back_handle);
+
+ if (drmAddMap(ctx->drmFD,
+ (drm_handle_t)sarea->depth_offset,
+ sarea->depth_size, DRM_AGP, 0,
+ &sarea->depth_handle) < 0) {
+ fprintf(stderr,
+ "[drm] drmAddMap(depth_handle) failed. Disabling DRI\n");
+ return FALSE;
+ }
+ fprintf(stderr, "[drm] Depth Buffer = 0x%08x\n",
+ sarea->depth_handle);
+
+#if 0
+ if (drmAddMap(ctx->drmFD,
+ (drm_handle_t)sarea->tex_offset,
+ sarea->tex_size, DRM_AGP, 0,
+ &sarea->tex_handle) < 0) {
+ fprintf(stderr,
+ "[drm] drmAddMap(tex_handle) failed. Disabling DRI\n");
+ return FALSE;
+ }
+ fprintf(stderr, "[drm] textures = 0x%08x\n",
+ sarea->tex_handle);
+#endif
+ return TRUE;
+}
+
+
+static void
+I830DRIUnmapScreenRegions(const DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+#if 1
+ if (sarea->front_handle) {
+ drmRmMap(ctx->drmFD, sarea->front_handle);
+ sarea->front_handle = 0;
+ }
+#endif
+ if (sarea->back_handle) {
+ drmRmMap(ctx->drmFD, sarea->back_handle);
+ sarea->back_handle = 0;
+ }
+ if (sarea->depth_handle) {
+ drmRmMap(ctx->drmFD, sarea->depth_handle);
+ sarea->depth_handle = 0;
+ }
+ if (sarea->tex_handle) {
+ drmRmMap(ctx->drmFD, sarea->tex_handle);
+ sarea->tex_handle = 0;
+ }
+}
+
+static Bool
+I830DRIDoMappings(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+ if (drmAddMap(ctx->drmFD,
+ (drm_handle_t)pI830->LpRing->mem.Start,
+ pI830->LpRing->mem.Size, DRM_AGP, 0,
+ &pI830->ring_map) < 0) {
+ fprintf(stderr,
+ "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+ return FALSE;
+ }
+ fprintf(stderr, "[drm] ring buffer = 0x%08x\n",
+ pI830->ring_map);
+
+ if (I830InitDma(ctx, pI830) == FALSE) {
+ return FALSE;
+ }
+
+ /* init to zero to be safe */
+
+ I830DRIMapScreenRegions(ctx, pI830, sarea);
+ SetupDRIMM(ctx, pI830);
+
+ if (ctx->pciDevice != PCI_CHIP_845_G &&
+ ctx->pciDevice != PCI_CHIP_I830_M) {
+ I830SetParam(ctx, I830_SETPARAM_USE_MI_BATCHBUFFER_START, 1 );
+ }
+
+ /* Okay now initialize the dma engine */
+ {
+ pI830->irq = drmGetInterruptFromBusID(ctx->drmFD,
+ ctx->pciBus,
+ ctx->pciDevice,
+ ctx->pciFunc);
+
+ if (drmCtlInstHandler(ctx->drmFD, pI830->irq)) {
+ fprintf(stderr,
+ "[drm] failure adding irq handler\n");
+ pI830->irq = 0;
+ return FALSE;
+ }
+ else
+ fprintf(stderr,
+ "[drm] dma control initialized, using IRQ %d\n",
+ pI830->irq);
+ }
+
+ fprintf(stderr, "[dri] visual configs initialized\n");
+
+ return TRUE;
+}
+
+static Bool
+I830ClearScreen(DRIDriverContext *ctx, I830Rec *pI830, drmI830Sarea *sarea)
+{
+ /* need to drmMap front and back buffers and zero them */
+ drmAddress map_addr;
+ int ret;
+
+ ret = drmMap(ctx->drmFD,
+ sarea->front_handle,
+ sarea->front_size,
+ &map_addr);
+
+ if (ret)
+ {
+ fprintf(stderr, "Unable to map front buffer\n");
+ return FALSE;
+ }
+
+ drimemsetio((char *)map_addr,
+ 0,
+ sarea->front_size);
+ drmUnmap(map_addr, sarea->front_size);
+
+
+ ret = drmMap(ctx->drmFD,
+ sarea->back_handle,
+ sarea->back_size,
+ &map_addr);
+
+ if (ret)
+ {
+ fprintf(stderr, "Unable to map back buffer\n");
+ return FALSE;
+ }
+
+ drimemsetio((char *)map_addr,
+ 0,
+ sarea->back_size);
+ drmUnmap(map_addr, sarea->back_size);
+
+ return TRUE;
+}
+
+static Bool
+I830ScreenInit(DRIDriverContext *ctx, I830Rec *pI830)
+
+{
+ I830DRIPtr pI830DRI;
+ drmI830Sarea *pSAREAPriv;
+ int err;
+
+ drm_page_size = getpagesize();
+
+ pI830->registerSize = ctx->MMIOSize;
+ /* This is a hack for now. We have to have more than a 4k page here
+ * because of the size of the state. However, the state should be
+ * in a per-context mapping. This will be added in the Mesa 3.5 port
+ * of the I830 driver.
+ */
+ ctx->shared.SAREASize = SAREA_MAX;
+
+ /* Note that drmOpen will try to load the kernel module, if needed. */
+ ctx->drmFD = drmOpen("i915", NULL );
+ if (ctx->drmFD < 0) {
+ fprintf(stderr, "[drm] drmOpen failed\n");
+ return 0;
+ }
+
+ if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
+ fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
+ ctx->drmFD, ctx->pciBusID, strerror(-err));
+ return 0;
+ }
+
+ if (drmAddMap( ctx->drmFD,
+ 0,
+ ctx->shared.SAREASize,
+ DRM_SHM,
+ DRM_CONTAINS_LOCK,
+ &ctx->shared.hSAREA) < 0)
+ {
+ fprintf(stderr, "[drm] drmAddMap failed\n");
+ return 0;
+ }
+
+ fprintf(stderr, "[drm] added %d byte SAREA at 0x%08x\n",
+ ctx->shared.SAREASize, ctx->shared.hSAREA);
+
+ if (drmMap( ctx->drmFD,
+ ctx->shared.hSAREA,
+ ctx->shared.SAREASize,
+ (drmAddressPtr)(&ctx->pSAREA)) < 0)
+ {
+ fprintf(stderr, "[drm] drmMap failed\n");
+ return 0;
+
+ }
+
+ memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
+ fprintf(stderr, "[drm] mapped SAREA 0x%08x to %p, size %d\n",
+ ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
+
+
+ if (drmAddMap(ctx->drmFD,
+ ctx->MMIOStart,
+ ctx->MMIOSize,
+ DRM_REGISTERS,
+ DRM_READ_ONLY,
+ &pI830->registerHandle) < 0) {
+ fprintf(stderr, "[drm] drmAddMap mmio failed\n");
+ return 0;
+ }
+ fprintf(stderr,
+ "[drm] register handle = 0x%08x\n", pI830->registerHandle);
+
+
+ if (!I830CheckDRMVersion(ctx, pI830)) {
+ return FALSE;
+ }
+
+ /* Create a 'server' context so we can grab the lock for
+ * initialization ioctls.
+ */
+ if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
+ fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
+ return 0;
+ }
+
+ DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
+
+ /* Initialize the SAREA private data structure */
+ pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
+ sizeof(drm_sarea_t));
+ memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
+
+ pI830->StolenMemory.Size = I830DetectMemory(ctx, pI830);
+ pI830->StolenMemory.Start = 0;
+ pI830->StolenMemory.End = pI830->StolenMemory.Size;
+
+ pI830->MemoryAperture.Start = pI830->StolenMemory.End;
+ pI830->MemoryAperture.End = KB(40000);
+ pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
+
+ pI830->StolenPool.Fixed = pI830->StolenMemory;
+ pI830->StolenPool.Total = pI830->StolenMemory;
+ pI830->StolenPool.Free = pI830->StolenPool.Total;
+ pI830->FreeMemory = pI830->StolenPool.Total.Size;
+
+ if (!AgpInit(ctx, pI830))
+ return FALSE;
+
+ if (I830AllocateMemory(ctx, pI830) == FALSE)
+ {
+ return FALSE;
+ }
+
+ if (I830BindMemory(ctx, pI830) == FALSE)
+ {
+ return FALSE;
+ }
+
+ pSAREAPriv->rotated_offset = -1;
+ pSAREAPriv->rotated_size = 0;
+ pSAREAPriv->rotated_pitch = ctx->shared.virtualWidth;
+
+ pSAREAPriv->front_offset = pI830->FrontBuffer.Start;
+ pSAREAPriv->front_size = pI830->FrontBuffer.Size;
+ pSAREAPriv->width = ctx->shared.virtualWidth;
+ pSAREAPriv->height = ctx->shared.virtualHeight;
+ pSAREAPriv->pitch = ctx->shared.virtualWidth;
+ pSAREAPriv->virtualX = ctx->shared.virtualWidth;
+ pSAREAPriv->virtualY = ctx->shared.virtualHeight;
+ pSAREAPriv->back_offset = pI830->BackBuffer.Start;
+ pSAREAPriv->back_size = pI830->BackBuffer.Size;
+ pSAREAPriv->depth_offset = pI830->DepthBuffer.Start;
+ pSAREAPriv->depth_size = pI830->DepthBuffer.Size;
+#if 0
+ pSAREAPriv->tex_offset = pI830->TexMem.Start;
+ pSAREAPriv->tex_size = pI830->TexMem.Size;
+#endif
+ pSAREAPriv->log_tex_granularity = pI830->TexGranularity;
+
+ ctx->driverClientMsg = malloc(sizeof(I830DRIRec));
+ ctx->driverClientMsgSize = sizeof(I830DRIRec);
+ pI830DRI = (I830DRIPtr)ctx->driverClientMsg;
+ pI830DRI->deviceID = pI830->Chipset;
+ pI830DRI->regsSize = I830_REG_SIZE;
+ pI830DRI->width = ctx->shared.virtualWidth;
+ pI830DRI->height = ctx->shared.virtualHeight;
+ pI830DRI->mem = ctx->shared.fbSize;
+ pI830DRI->cpp = ctx->cpp;
+
+ pI830DRI->bitsPerPixel = ctx->bpp;
+ pI830DRI->sarea_priv_offset = sizeof(drm_sarea_t);
+
+ err = I830DRIDoMappings(ctx, pI830, pSAREAPriv);
+ if (err == FALSE)
+ return FALSE;
+
+ I830SetupMemoryTiling(ctx, pI830);
+
+ /* Quick hack to clear the front & back buffers. Could also use
+ * the clear ioctl to do this, but would need to setup hw state
+ * first.
+ */
+ I830ClearScreen(ctx, pI830, pSAREAPriv);
+
+ I830SetRingRegs(ctx, pI830);
+
+ return TRUE;
+}
+
+
+/**
+ * \brief Validate the fbdev mode.
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Saves some registers and returns 1.
+ *
+ * \sa radeonValidateMode().
+ */
+static int i830ValidateMode( const DRIDriverContext *ctx )
+{
+ return 1;
+}
+
+/**
+ * \brief Examine mode returned by fbdev.
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Restores registers that fbdev has clobbered and returns 1.
+ *
+ * \sa i810ValidateMode().
+ */
+static int i830PostValidateMode( const DRIDriverContext *ctx )
+{
+ I830Rec *pI830 = ctx->driverPrivate;
+
+ I830SetRingRegs(ctx, pI830);
+ return 1;
+}
+
+
+/**
+ * \brief Initialize the framebuffer device mode
+ *
+ * \param ctx display handle.
+ *
+ * \return one on success, or zero on failure.
+ *
+ * Fills in \p info with some default values and some information from \p ctx
+ * and then calls I810ScreenInit() for the screen initialization.
+ *
+ * Before exiting clears the framebuffer memory accessing it directly.
+ */
+static int i830InitFBDev( DRIDriverContext *ctx )
+{
+ I830Rec *pI830 = calloc(1, sizeof(I830Rec));
+ int i;
+
+ {
+ int dummy = ctx->shared.virtualWidth;
+
+ switch (ctx->bpp / 8) {
+ case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
+ case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
+ case 3:
+ case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
+ }
+
+ ctx->shared.virtualWidth = dummy;
+ ctx->shared.Width = ctx->shared.virtualWidth;
+ }
+
+
+ for (i = 0; pitches[i] != 0; i++) {
+ if (pitches[i] >= ctx->shared.virtualWidth) {
+ ctx->shared.virtualWidth = pitches[i];
+ break;
+ }
+ }
+
+ ctx->driverPrivate = (void *)pI830;
+
+ pI830->LpRing = calloc(1, sizeof(I830RingBuffer));
+ pI830->Chipset = ctx->chipset;
+ pI830->LinearAddr = ctx->FBStart;
+
+ if (!I830ScreenInit( ctx, pI830 ))
+ return 0;
+
+
+ return 1;
+}
+
+
+/**
+ * \brief The screen is being closed, so clean up any state and free any
+ * resources used by the DRI.
+ *
+ * \param ctx display handle.
+ *
+ * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
+ * private data.
+ */
+static void i830HaltFBDev( DRIDriverContext *ctx )
+{
+ drmI830Sarea *pSAREAPriv;
+ I830Rec *pI830 = ctx->driverPrivate;
+
+ if (pI830->irq) {
+ drmCtlUninstHandler(ctx->drmFD);
+ pI830->irq = 0; }
+
+ I830CleanupDma(ctx);
+
+ pSAREAPriv = (drmI830Sarea *)(((char*)ctx->pSAREA) +
+ sizeof(drm_sarea_t));
+
+ I830DRIUnmapScreenRegions(ctx, pI830, pSAREAPriv);
+ drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
+ drmClose(ctx->drmFD);
+
+ if (ctx->driverPrivate) {
+ free(ctx->driverPrivate);
+ ctx->driverPrivate = 0;
+ }
+}
+
+
+extern void i810NotifyFocus( int );
+
+/**
+ * \brief Exported driver interface for Mini GLX.
+ *
+ * \sa DRIDriverRec.
+ */
+const struct DRIDriverRec __driDriver = {
+ i830ValidateMode,
+ i830PostValidateMode,
+ i830InitFBDev,
+ i830HaltFBDev,
+ NULL,//I830EngineShutdown,
+ NULL, //I830EngineRestore,
+#ifndef _EMBEDDED
+ 0,
+#else
+ i810NotifyFocus,
+#endif
+};