From: Keith Whitwell Date: Wed, 8 Aug 2007 08:41:52 +0000 (+0100) Subject: Rename drivers/dri/i915pipe --> drivers/dri/intel_winsys. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8a475cb791a0e66fcdc3fcd12c517fcb98d75957;p=mesa.git Rename drivers/dri/i915pipe --> drivers/dri/intel_winsys. This is appropriate as this is not a "pipe driver for the i915" as the old name would suggest, but rather a dri driver that can provide "winsys" backends to softpipe/i915/i965/etc pipe drivers, running under the intel DDX, drm, etc. It also frees up the i915pipe name for something more appropriate, ie mesa/pipe/i915pipe. --- diff --git a/configs/linux-dri b/configs/linux-dri index 6a29505a6b1..63e065a40fa 100644 --- a/configs/linux-dri +++ b/configs/linux-dri @@ -66,4 +66,4 @@ WINDOW_SYSTEM=dri # gamma are missing because they have not been converted to use the new # interface. -DRI_DIRS = i915pipe +DRI_DIRS = intel_winsys diff --git a/src/mesa/drivers/dri/i915pipe/Makefile b/src/mesa/drivers/dri/i915pipe/Makefile deleted file mode 100644 index e4e9cf17b09..00000000000 --- a/src/mesa/drivers/dri/i915pipe/Makefile +++ /dev/null @@ -1,49 +0,0 @@ - -TOP = ../../../../.. -include $(TOP)/configs/current - -LIBNAME = i915tex_dri.so - -MINIGLX_SOURCES = server/intel_dri.c - -PIPE_DRIVERS = \ - $(TOP)/src/mesa/pipe/softpipe/libsoftpipe.a - -DRIVER_SOURCES = \ - intel_softpipe.c \ - intel_batchbuffer.c \ - intel_tex_layout.c \ - intel_buffers.c \ - intel_blit.c \ - intel_context.c \ - intel_ioctl.c \ - intel_screen.c \ - intel_surface.c \ - intel_fbo.c \ - intel_depthstencil.c \ - intel_batchpool.c - -OLD_TEX =\ - intel_tex_image.c \ - intel_tex_subimage.c \ - intel_tex_copy.c \ - intel_tex_validate.c \ - intel_tex_format.c \ - intel_tex.c - - -C_SOURCES = \ - $(COMMON_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/mesa/drivers/dri/i915pipe/intel_batchbuffer.c b/src/mesa/drivers/dri/i915pipe/intel_batchbuffer.c deleted file mode 100644 index 60bd8eaec29..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_batchbuffer.c +++ /dev/null @@ -1,342 +0,0 @@ -/************************************************************************** - * - * 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 "intel_batchbuffer.h" -#include "intel_ioctl.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(GLuint offset, GLuint * ptr, GLuint count) -{ - int i; - fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4); - for (i = 0; i < count / 4; i += 4) - fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", - offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]); - fprintf(stderr, "END BATCH\n\n\n"); -} - -void -intel_batchbuffer_reset(struct intel_batchbuffer *batch) -{ - - int i; - - /* - * 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); -} - -/* TODO: Push this whole function into bufmgr. - */ -static void -do_flush_locked(struct intel_batchbuffer *batch, - GLuint used, - GLboolean ignore_cliprects, GLboolean allow_unlock) -{ - GLuint *ptr; - GLuint i; - struct intel_context *intel = batch->intel; - unsigned 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 = (GLuint *) 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 (INTEL_DEBUG & DEBUG_BATCH) - intel_dump_batchbuffer(0, ptr, used); - - driBOUnmap(batch->buffer); - batch->map = NULL; - - /* Throw away non-effective packets. Won't work once we have - * hardware contexts which would preserve statechanges beyond a - * single buffer. - */ - - if (!(intel->numClipRects == 0 && !ignore_cliprects)) { - intel_batch_ioctl(batch->intel, - driBOOffset(batch->buffer), - used, ignore_cliprects, 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); - } - } - - if (intel->numClipRects == 0 && !ignore_cliprects) { - if (allow_unlock) { - UNLOCK_HARDWARE(intel); - sched_yield(); - LOCK_HARDWARE(intel); - } -// intel->vtbl.lost_hardware(intel); - } -} - - -struct _DriFenceObject * -intel_batchbuffer_flush(struct intel_batchbuffer *batch) -{ - struct intel_context *intel = batch->intel; - GLuint used = batch->ptr - batch->map; - GLboolean 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, !(batch->flags & INTEL_BATCH_CLIPRECTS), - 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); - driFenceReference(fence); - driFenceFinish(fence, 3, GL_FALSE); - driFenceUnReference(fence); -} - - -/* This is the only way buffers get added to the validate list. - */ -GLboolean -intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, - struct _DriBufferObject *buffer, - GLuint flags, GLuint mask, GLuint 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; - } - - batch->ptr += 4; - return GL_TRUE; -} - - - -void -intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags) -{ - assert((bytes & 3) == 0); - intel_batchbuffer_require_space(batch, bytes, flags); - memcpy(batch->ptr, data, bytes); - batch->ptr += bytes; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_batchbuffer.h b/src/mesa/drivers/dri/i915pipe/intel_batchbuffer.h deleted file mode 100644 index 6d4d05e0bb1..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_batchbuffer.h +++ /dev/null @@ -1,123 +0,0 @@ -#ifndef INTEL_BATCHBUFFER_H -#define INTEL_BATCHBUFFER_H - -#include "mtypes.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; - GLuint offset; - GLuint delta; /* not needed? */ -}; - -struct intel_batchbuffer -{ - struct bufmgr *bm; - struct intel_context *intel; - - struct _DriBufferObject *buffer; - struct _DriFenceObject *last_fence; - GLuint flags; - - drmBOList list; - GLuint list_count; - GLubyte *map; - GLubyte *ptr; - - struct buffer_reloc reloc[MAX_RELOCS]; - GLuint nr_relocs; - GLuint 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 multple - * intel_buffer_dword() calls. - */ -void intel_batchbuffer_data(struct intel_batchbuffer *batch, - const void *data, GLuint bytes, GLuint flags); - -void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, - GLuint bytes); - -GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, - struct _DriBufferObject *buffer, - GLuint flags, - GLuint mask, GLuint 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 GLuint -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, GLuint dword) -{ - assert(batch->map); - assert(intel_batchbuffer_space(batch) >= 4); - *(GLuint *) (batch->ptr) = dword; - batch->ptr += 4; -} - -static INLINE void -intel_batchbuffer_require_space(struct intel_batchbuffer *batch, - GLuint sz, GLuint 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/mesa/drivers/dri/i915pipe/intel_batchpool.c b/src/mesa/drivers/dri/i915pipe/intel_batchpool.c deleted file mode 100644 index 2503b8a62a1..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_batchpool.c +++ /dev/null @@ -1,418 +0,0 @@ -/************************************************************************** - * - * 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 - */ - -#include -#include -#include -#include "imports.h" -#include "glthread.h" -#include "dri_bufpool.h" -#include "dri_bufmgr.h" -#include "intel_screen.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, 0, 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/mesa/drivers/dri/i915pipe/intel_blit.c b/src/mesa/drivers/dri/i915pipe/intel_blit.c deleted file mode 100644 index 8e878f00887..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_blit.c +++ /dev/null @@ -1,394 +0,0 @@ -/************************************************************************** - * - * 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 "mtypes.h" -#include "context.h" -#include "enums.h" - -#include "intel_batchbuffer.h" -#include "intel_blit.h" -#include "intel_buffers.h" -#include "intel_context.h" -#include "intel_fbo.h" -#include "intel_reg.h" -#include "vblank.h" - -#include "pipe/p_context.h" - - -#define FILE_DEBUG_FLAG DEBUG_BLIT - -/** - * Copy the back color buffer to the front color buffer. - * Used for SwapBuffers(). - */ -void -intelCopyBuffer(__DRIdrawablePrivate * dPriv, - const drm_clip_rect_t * rect) -{ - - struct intel_context *intel; - const intelScreenPrivate *intelScreen; - - DBG("%s\n", __FUNCTION__); - - assert(dPriv); - - intel = intelScreenContext(dPriv->driScreenPriv->private); - if (!intel) - return; - - intelScreen = intel->intelScreen; - - 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; - } - 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 ((struct intel_context *)dPriv->driContextPriv->driverPrivate != intel) - DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv); - - - if (dPriv && dPriv->numClipRects) { - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - const struct pipe_region *backRegion - = intel_fb->Base._ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ? - intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) : - intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); - const int backWidth = intel_fb->Base.Width; - const int backHeight = intel_fb->Base.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 srcpitch = backRegion->pitch; - const int cpp = intelScreen->front.cpp; - int BR13, CMD; - int i; - - ASSERT(intel_fb); - ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ - ASSERT(backRegion); - ASSERT(backRegion->cpp == cpp); - - DBG("front pitch %d back pitch %d\n", - pitch, backRegion->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) - continue; - - box = *pbox; - - if (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 > backWidth) - box.x2 = backWidth + box.x1; - if (box.y2 - box.y1 > backHeight) - box.y2 = backHeight + box.y1; - - DBG("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; - - 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(backRegion->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); - - /* XXX this is bogus. The context here may not even be bound to this drawable! */ - if (intel->lastStamp != dPriv->lastStamp) { - GET_CURRENT_CONTEXT(currctx); - struct intel_context *intelcurrent = intel_context(currctx); - if (intelcurrent == intel && intelcurrent->driDrawable == dPriv) { - intelWindowMoved(intel); - intel->lastStamp = dPriv->lastStamp; - } - } - -} - - - - -void -intelEmitFillBlit(struct intel_context *intel, - GLuint cpp, - GLshort dst_pitch, - struct _DriBufferObject *dst_buffer, - GLuint dst_offset, - GLshort x, GLshort y, GLshort w, GLshort h, - GLuint value, GLuint mask) -{ - GLuint BR13, CMD; - GLboolean badMask = GL_FALSE; - BATCH_LOCALS; - - /* - printf("Emit fill blit value=0x%x mask=0x%x\n", value, mask); - */ - - dst_pitch *= cpp; - - switch (cpp) { - case 1: - case 2: - case 3: - BR13 = dst_pitch | (0xF0 << 16) | (1 << 24); - CMD = XY_COLOR_BLT_CMD; - if ((mask & 0xffff) != 0xffff) - badMask = GL_TRUE; - break; - case 4: - BR13 = dst_pitch | (0xF0 << 16) | (1 << 24) | (1 << 25); -#if 0 - CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | - XY_COLOR_BLT_WRITE_RGB); -#else - CMD = XY_COLOR_BLT_CMD; - if ((mask & 0xff000000) == 0xff000000) - CMD |= XY_COLOR_BLT_WRITE_ALPHA; - else if (mask & 0xff000000) - badMask = GL_TRUE; - if ((mask & 0x00ffffff) == 0x00ffffff) - CMD |= XY_COLOR_BLT_WRITE_RGB; - else if (mask & 0x00ffffff) - badMask = GL_TRUE; -#endif - break; - default: - return; - } - - assert(!badMask); - - DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", - __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h); - - - BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((y << 16) | x); - OUT_BATCH(((y + h) << 16) | (x + w)); - OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); - OUT_BATCH(value); - ADVANCE_BATCH(); - - intel_batchbuffer_flush(intel->batch); -} - - -static GLuint translate_raster_op(GLenum logicop) -{ - switch(logicop) { - case GL_CLEAR: return 0x00; - case GL_AND: return 0x88; - case GL_AND_REVERSE: return 0x44; - case GL_COPY: return 0xCC; - case GL_AND_INVERTED: return 0x22; - case GL_NOOP: return 0xAA; - case GL_XOR: return 0x66; - case GL_OR: return 0xEE; - case GL_NOR: return 0x11; - case GL_EQUIV: return 0x99; - case GL_INVERT: return 0x55; - case GL_OR_REVERSE: return 0xDD; - case GL_COPY_INVERTED: return 0x33; - case GL_OR_INVERTED: return 0xBB; - case GL_NAND: return 0x77; - case GL_SET: return 0xFF; - default: return 0; - } -} - - -/* Copy BitBlt - */ -void -intelEmitCopyBlit(struct intel_context *intel, - GLuint cpp, - GLshort src_pitch, - struct _DriBufferObject *src_buffer, - GLuint src_offset, - GLshort dst_pitch, - struct _DriBufferObject *dst_buffer, - GLuint dst_offset, - GLshort src_x, GLshort src_y, - GLshort dst_x, GLshort dst_y, - GLshort w, GLshort h, - GLenum logic_op) -{ - GLuint CMD, BR13; - int dst_y2 = dst_y + h; - int dst_x2 = dst_x + w; - BATCH_LOCALS; - - - DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", - __FUNCTION__, - src_buffer, src_pitch, src_offset, src_x, src_y, - dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); - - src_pitch *= cpp; - dst_pitch *= cpp; - - switch (cpp) { - case 1: - case 2: - case 3: - BR13 = (((GLint) dst_pitch) & 0xffff) | - (translate_raster_op(logic_op) << 16) | (1 << 24); - CMD = XY_SRC_COPY_BLT_CMD; - break; - case 4: - BR13 = - (((GLint) dst_pitch) & 0xffff) | - (translate_raster_op(logic_op) << 16) | (1 << 24) | (1 << 25); - CMD = - (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | - XY_SRC_COPY_BLT_WRITE_RGB); - break; - default: - return; - } - - if (dst_y2 < dst_y || dst_x2 < dst_x) { - return; - } - - /* Initial y values don't seem to work with negative pitches. If - * we adjust the offsets manually (below), it seems to work fine. - * - * On the other hand, if we always adjust, the hardware doesn't - * know which blit directions to use, so overlapping copypixels get - * the wrong result. - */ - if (dst_pitch > 0 && src_pitch > 0) { - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((dst_y << 16) | dst_x); - OUT_BATCH((dst_y2 << 16) | dst_x2); - OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); - OUT_BATCH((src_y << 16) | src_x); - OUT_BATCH(((GLint) src_pitch & 0xffff)); - OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, src_offset); - ADVANCE_BATCH(); - } - else { - BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); - OUT_BATCH(CMD); - OUT_BATCH(BR13); - OUT_BATCH((0 << 16) | dst_x); - OUT_BATCH((h << 16) | dst_x2); - OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, - DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, - dst_offset + dst_y * dst_pitch); - OUT_BATCH((0 << 16) | src_x); - OUT_BATCH(((GLint) src_pitch & 0xffff)); - OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, - DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, - src_offset + src_y * src_pitch); - ADVANCE_BATCH(); - } - - intel_batchbuffer_flush( intel->batch ); -} - - - diff --git a/src/mesa/drivers/dri/i915pipe/intel_blit.h b/src/mesa/drivers/dri/i915pipe/intel_blit.h deleted file mode 100644 index 46c25944775..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_blit.h +++ /dev/null @@ -1,62 +0,0 @@ -/************************************************************************** - * - * 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_BLIT_H -#define INTEL_BLIT_H - -#include "intel_context.h" -#include "intel_ioctl.h" -#include "dri_bufmgr.h" - -extern void intelCopyBuffer(__DRIdrawablePrivate * dpriv, - const drm_clip_rect_t * rect); - -extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask); - -extern void intelEmitCopyBlit(struct intel_context *intel, - GLuint cpp, - GLshort src_pitch, - struct _DriBufferObject *src_buffer, - GLuint src_offset, - GLshort dst_pitch, - struct _DriBufferObject *dst_buffer, - GLuint dst_offset, - GLshort srcx, GLshort srcy, - GLshort dstx, GLshort dsty, - GLshort w, GLshort h, - GLenum logicop ); - -extern void intelEmitFillBlit(struct intel_context *intel, - GLuint cpp, - GLshort dst_pitch, - struct _DriBufferObject *dst_buffer, - GLuint dst_offset, - GLshort x, GLshort y, - GLshort w, GLshort h, GLuint value, GLuint mask); - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_buffers.c b/src/mesa/drivers/dri/i915pipe/intel_buffers.c deleted file mode 100644 index fc9d60c88e5..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_buffers.c +++ /dev/null @@ -1,711 +0,0 @@ -/************************************************************************** - * - * 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_blit.h" -#include "intel_buffers.h" -#include "intel_depthstencil.h" -#include "intel_fbo.h" -#include "intel_batchbuffer.h" -#include "intel_reg.h" -#include "context.h" -#include "utils.h" -#include "drirenderbuffer.h" -#include "framebuffer.h" -#include "vblank.h" - -#include "pipe/p_context.h" - -/* This block can be removed when libdrm >= 2.3.1 is required */ - -#ifndef DRM_VBLANK_FLIP - -#define DRM_VBLANK_FLIP 0x8000000 - -typedef struct drm_i915_flip { - int pipes; -} drm_i915_flip_t; - -#undef DRM_IOCTL_I915_FLIP -#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \ - drm_i915_flip_t) - -#endif - - -/** - * XXX move this into a new dri/common/cliprects.c file. - */ -GLboolean -intel_intersect_cliprects(drm_clip_rect_t * dst, - const drm_clip_rect_t * a, - const drm_clip_rect_t * b) -{ - GLint bx = b->x1; - GLint by = b->y1; - GLint bw = b->x2 - bx; - GLint bh = b->y2 - by; - - if (bx < a->x1) - bw -= a->x1 - bx, bx = a->x1; - if (by < a->y1) - bh -= a->y1 - by, by = a->y1; - if (bx + bw > a->x2) - bw = a->x2 - bx; - if (by + bh > a->y2) - bh = a->y2 - by; - if (bw <= 0) - return GL_FALSE; - if (bh <= 0) - return GL_FALSE; - - dst->x1 = bx; - dst->y1 = by; - dst->x2 = bx + bw; - dst->y2 = by + bh; - - return GL_TRUE; -} - -/** - * Return pointer to current color drawing region, or NULL. - */ -struct pipe_region * -intel_drawbuf_region(struct intel_context *intel) -{ - struct intel_renderbuffer *irbColor = - intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]); - if (irbColor) - return irbColor->region; - else - return NULL; -} - -/** - * Return pointer to current color reading region, or NULL. - */ -struct pipe_region * -intel_readbuf_region(struct intel_context *intel) -{ - struct intel_renderbuffer *irb - = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); - if (irb) - return irb->region; - else - return NULL; -} - - - -/** - * Update the following fields for rendering: - * intel->numClipRects - * intel->pClipRects - */ -static void -intelSetRenderbufferClipRects(struct intel_context *intel) -{ - /* zero-sized buffers might be legal? */ - assert(intel->ctx.DrawBuffer->Width > 0); - assert(intel->ctx.DrawBuffer->Height > 0); - intel->fboRect.x1 = 0; - intel->fboRect.y1 = 0; - intel->fboRect.x2 = intel->ctx.DrawBuffer->Width; - intel->fboRect.y2 = intel->ctx.DrawBuffer->Height; - intel->numClipRects = 1; - intel->pClipRects = &intel->fboRect; -} - - -/** - * This will be called whenever the currently bound window is moved/resized. - * XXX: actually, it seems to NOT be called when the window is only moved (BP). - */ -void -intelWindowMoved(struct intel_context *intel) -{ - GLcontext *ctx = &intel->ctx; - __DRIdrawablePrivate *dPriv = intel->driDrawable; - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - - if (!intel->ctx.DrawBuffer) { - /* when would this happen? -BP */ - assert(0); - intel->numClipRects = 0; - } - - /* Update Mesa's notion of window size */ - driUpdateFramebufferSize(ctx, dPriv); - intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ - - { - drmI830Sarea *sarea = intel->sarea; - drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, - .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h }; - drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y, - .x2 = sarea->pipeA_x + sarea->pipeA_w, - .y2 = sarea->pipeA_y + sarea->pipeA_h }; - drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y, - .x2 = sarea->pipeB_x + sarea->pipeB_w, - .y2 = sarea->pipeB_y + sarea->pipeB_h }; - GLint areaA = driIntersectArea( drw_rect, pipeA_rect ); - GLint areaB = driIntersectArea( drw_rect, pipeB_rect ); - GLuint flags = intel_fb->vblank_flags; - GLboolean pf_active; - GLint pf_pipes; - - /* Update page flipping info - */ - pf_pipes = 0; - - if (areaA > 0) - pf_pipes |= 1; - - if (areaB > 0) - pf_pipes |= 2; - - intel_fb->pf_current_page = (intel->sarea->pf_current_page >> - (intel_fb->pf_pipes & 0x2)) & 0x3; - - intel_fb->pf_num_pages = 2 /*intel->intelScreen->third.handle ? 3 : 2*/; - - pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes; - - if (INTEL_DEBUG & DEBUG_LOCK) - if (pf_active != intel_fb->pf_active) - _mesa_printf("%s - Page flipping %sactive\n", __progname, - pf_active ? "" : "in"); - - if (pf_active) { - /* Sync pages between pipes if we're flipping on both at the same time */ - if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes && - (intel->sarea->pf_current_page & 0x3) != - (((intel->sarea->pf_current_page) >> 2) & 0x3)) { - drm_i915_flip_t flip; - - if (intel_fb->pf_current_page == - (intel->sarea->pf_current_page & 0x3)) { - /* XXX: This is ugly, but emitting two flips 'in a row' can cause - * lockups for unknown reasons. - */ - intel->sarea->pf_current_page = - intel->sarea->pf_current_page & 0x3; - intel->sarea->pf_current_page |= - ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % - intel_fb->pf_num_pages) << 2; - - flip.pipes = 0x2; - } else { - intel->sarea->pf_current_page = - intel->sarea->pf_current_page & (0x3 << 2); - intel->sarea->pf_current_page |= - (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % - intel_fb->pf_num_pages; - - flip.pipes = 0x1; - } - - drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); - } - - intel_fb->pf_pipes = pf_pipes; - } - - intel_fb->pf_active = pf_active; - intel_flip_renderbuffers(intel_fb); - intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); - - /* Update vblank info - */ - if (areaB > areaA || (areaA == areaB && areaB > 0)) { - flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY; - } else { - flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY; - } - - if (flags != intel_fb->vblank_flags && intel_fb->vblank_flags && - !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ)) { - drmVBlank vbl; - int i; - - vbl.request.type = DRM_VBLANK_ABSOLUTE; - - if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { - vbl.request.type |= DRM_VBLANK_SECONDARY; - } - - for (i = 0; i < intel_fb->pf_num_pages; i++) { - if (!intel_fb->color_rb[i] || - (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <= - (1<<23)) - continue; - - vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending; - drmWaitVBlank(intel->driFd, &vbl); - } - - intel_fb->vblank_flags = flags; - driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq); - intel_fb->vbl_waited = intel_fb->vbl_seq; - - for (i = 0; i < intel_fb->pf_num_pages; i++) { - if (intel_fb->color_rb[i]) - intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; - } - } - } - - /* This will be picked up by looking at the dirty state flags: - */ - - /* Update hardware scissor */ -// ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, -// ctx->Scissor.Width, ctx->Scissor.Height); - - /* Re-calculate viewport related state */ -// ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far ); -} - - - - - -/* Emit wait for pending flips */ -void -intel_wait_flips(struct intel_context *intel, GLuint batch_flags) -{ - struct intel_framebuffer *intel_fb = - (struct intel_framebuffer *) intel->ctx.DrawBuffer; - struct intel_renderbuffer *intel_rb = - intel_get_renderbuffer(&intel_fb->Base, - intel_fb->Base._ColorDrawBufferMask[0] == - BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : - BUFFER_BACK_LEFT); - - if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { - GLint pf_pipes = intel_fb->pf_pipes; - BATCH_LOCALS; - - /* Wait for pending flips to take effect */ - BEGIN_BATCH(2, batch_flags); - OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP) - : 0); - OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP) - : 0); - ADVANCE_BATCH(); - - intel_rb->pf_pending--; - } -} - -#if 0 -/* Flip the front & back buffers - */ -static GLboolean -intelPageFlip(const __DRIdrawablePrivate * dPriv) -{ - struct intel_context *intel; - int ret; - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - - if (INTEL_DEBUG & DEBUG_IOCTL) - fprintf(stderr, "%s\n", __FUNCTION__); - - assert(dPriv); - assert(dPriv->driContextPriv); - assert(dPriv->driContextPriv->driverPrivate); - - intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; - - if (intel->intelScreen->drmMinor < 9) - return GL_FALSE; - - intelFlush(&intel->ctx); - - ret = 0; - - LOCK_HARDWARE(intel); - - if (dPriv->numClipRects && intel_fb->pf_active) { - drm_i915_flip_t flip; - - flip.pipes = intel_fb->pf_pipes; - - ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); - } - - UNLOCK_HARDWARE(intel); - - if (ret || !intel_fb->pf_active) - return GL_FALSE; - - if (!dPriv->numClipRects) { - usleep(10000); /* throttle invisible client 10ms */ - } - - intel_fb->pf_current_page = (intel->sarea->pf_current_page >> - (intel_fb->pf_pipes & 0x2)) & 0x3; - - if (dPriv->numClipRects != 0) { - intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending = - intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending = - ++intel_fb->pf_seq; - } - - intel_flip_renderbuffers(intel_fb); - intel_draw_buffer(&intel->ctx, &intel_fb->Base); - - if (INTEL_DEBUG & DEBUG_IOCTL) - fprintf(stderr, "%s: success\n", __FUNCTION__); - - return GL_TRUE; -} -#endif - - -static GLboolean -intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target) -{ - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags); - struct intel_context *intel = - intelScreenContext(dPriv->driScreenPriv->private); - const intelScreenPrivate *intelScreen = intel->intelScreen; - unsigned int target; - drm_i915_vblank_swap_t swap; - GLboolean ret; - - if (!intel_fb->vblank_flags || - (intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) || - intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6)) - return GL_FALSE; - - swap.seqtype = DRM_VBLANK_ABSOLUTE; - - if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) { - swap.seqtype |= DRM_VBLANK_NEXTONMISS; - } else if (interval == 0) { - return GL_FALSE; - } - - swap.drawable = dPriv->hHWDrawable; - target = swap.sequence = intel_fb->vbl_seq + interval; - - if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { - swap.seqtype |= DRM_VBLANK_SECONDARY; - } - - LOCK_HARDWARE(intel); - - intel_batchbuffer_flush(intel->batch); - - if ( intel_fb->pf_active ) { - swap.seqtype |= DRM_VBLANK_FLIP; - - intel_fb->pf_current_page = (((intel->sarea->pf_current_page >> - (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) % - intel_fb->pf_num_pages; - } - - if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, - sizeof(swap))) { - intel_fb->vbl_seq = swap.sequence; - swap.sequence -= target; - *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); - - intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending = - intel_get_renderbuffer(&intel_fb->Base, - BUFFER_FRONT_LEFT)->vbl_pending = - intel_fb->vbl_seq; - - if (swap.seqtype & DRM_VBLANK_FLIP) { - intel_flip_renderbuffers(intel_fb); - intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); - } - - ret = GL_TRUE; - } else { - if (swap.seqtype & DRM_VBLANK_FLIP) { - intel_fb->pf_current_page = ((intel->sarea->pf_current_page >> - (intel_fb->pf_pipes & 0x2)) & 0x3) % - intel_fb->pf_num_pages; - } - - ret = GL_FALSE; - } - - UNLOCK_HARDWARE(intel); - - return ret; -} - -void -intelSwapBuffers(__DRIdrawablePrivate * dPriv) -{ - if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { - GET_CURRENT_CONTEXT(ctx); - struct intel_context *intel; - - if (ctx == NULL) - return; - - intel = intel_context(ctx); - - if (ctx->Visual.doubleBufferMode) { - GLboolean missed_target; - struct intel_framebuffer *intel_fb = dPriv->driverPrivate; - int64_t ust; - - _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - - if (!intelScheduleSwap(dPriv, &missed_target)) { - driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags, - &missed_target); - - intelCopyBuffer(dPriv, NULL); - } - - intel_fb->swap_count++; - (*dri_interface->getUST) (&ust); - if (missed_target) { - intel_fb->swap_missed_count++; - intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; - } - - intel_fb->swap_ust = ust; - } - } - else { - /* XXX this shouldn't be an error but we can't handle it for now */ - fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); - } -} - -void -intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) -{ - if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { - struct intel_context *intel = - (struct intel_context *) dPriv->driContextPriv->driverPrivate; - GLcontext *ctx = &intel->ctx; - - if (ctx->Visual.doubleBufferMode) { - drm_clip_rect_t rect; - /* fixup cliprect (driDrawable may have changed?) later */ - rect.x1 = x; - rect.y1 = y; - rect.x2 = w; - rect.y2 = h; - _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ - intelCopyBuffer(dPriv, &rect); - } - } - else { - /* XXX this shouldn't be an error but we can't handle it for now */ - fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); - } -} - - -/** - * Update the hardware state for drawing into a window or framebuffer object. - * - * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other - * places within the driver. - * - * Basically, this needs to be called any time the current framebuffer - * changes, the renderbuffers change, or we need to draw into different - * color buffers. - */ -void -intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) -{ - struct intel_context *intel = intel_context(ctx); - struct pipe_region *colorRegion, *depthRegion = NULL; - struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; - - if (!fb) { - /* this can happen during the initial context initialization */ - return; - } - - /* Do this here, not core Mesa, since this function is called from - * many places within the driver. - */ - if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { - /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ - _mesa_update_framebuffer(ctx); - /* this updates the DrawBuffer's Width/Height if it's a FBO */ - _mesa_update_draw_buffer_bounds(ctx); - } - - if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { - /* this may occur when we're called by glBindFrameBuffer() during - * the process of someone setting up renderbuffers, etc. - */ - /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ - return; - } - - if (fb->Name) - intel_validate_paired_depth_stencil(ctx, fb); - - /* - * How many color buffers are we drawing into? - */ - if (fb->_NumColorDrawBuffers[0] != 1) { - /* writing to 0 or 2 or 4 color buffers */ - /*_mesa_debug(ctx, "Software rendering\n");*/ - FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); - } - else { - /* draw to exactly one color buffer */ - /*_mesa_debug(ctx, "Hardware rendering\n");*/ - FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); - } - - /* - * Get the intel_renderbuffer for the colorbuffer we're drawing into. - * And set up cliprects. - */ - { - struct intel_renderbuffer *irb; - intelSetRenderbufferClipRects(intel); - irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]); - colorRegion = (irb && irb->region) ? irb->region : NULL; - } - - /* Update culling direction which changes depending on the - * orientation of the buffer: - */ - if (ctx->Driver.FrontFace) - ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); - else - ctx->NewState |= _NEW_POLYGON; - - if (!colorRegion) { - FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); - } - else { - FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); - } - - /*** - *** Get depth buffer region and check if we need a software fallback. - *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. - ***/ - if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { - irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); - if (irbDepth && irbDepth->region) { - FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); - depthRegion = irbDepth->region; - } - else { - FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); - depthRegion = NULL; - } - } - else { - /* not using depth buffer */ - FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); - depthRegion = NULL; - } - - /*** - *** Stencil buffer - *** This can only be hardware accelerated if we're using a - *** combined DEPTH_STENCIL buffer (for now anyway). - ***/ - if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { - irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); - if (irbStencil && irbStencil->region) { - ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); - /* need to re-compute stencil hw state */ -// ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); - if (!depthRegion) - depthRegion = irbStencil->region; - } - else { - FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); - } - } - else { - /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */ - FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); - /* need to re-compute stencil hw state */ -// ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); - } - - - /** - ** Release old regions, reference new regions - **/ - - // intel->vtbl.set_draw_region(intel, colorRegion, depthRegion); - - /* update viewport since it depends on window size */ -// ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, -// ctx->Viewport.Width, ctx->Viewport.Height); - - /* Update hardware scissor */ -// ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, -// ctx->Scissor.Width, ctx->Scissor.Height); -} - - -static void -intelDrawBuffer(GLcontext * ctx, GLenum mode) -{ - intel_draw_buffer(ctx, ctx->DrawBuffer); -} - - -static void -intelReadBuffer(GLcontext * ctx, GLenum mode) -{ - if (ctx->ReadBuffer == ctx->DrawBuffer) { - /* This will update FBO completeness status. - * A framebuffer will be incomplete if the GL_READ_BUFFER setting - * refers to a missing renderbuffer. Calling glReadBuffer can set - * that straight and can make the drawing buffer complete. - */ - intel_draw_buffer(ctx, ctx->DrawBuffer); - } - /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) - * reference ctx->ReadBuffer and do appropriate state checks. - */ -} - - -void -intelInitBufferFuncs(struct dd_function_table *functions) -{ - functions->DrawBuffer = intelDrawBuffer; - functions->ReadBuffer = intelReadBuffer; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_buffers.h b/src/mesa/drivers/dri/i915pipe/intel_buffers.h deleted file mode 100644 index 5834e395010..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_buffers.h +++ /dev/null @@ -1,55 +0,0 @@ -/************************************************************************** - * - * 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_BUFFERS_H -#define INTEL_BUFFERS_H - - -struct intel_context; -struct intel_framebuffer; - - -extern GLboolean -intel_intersect_cliprects(drm_clip_rect_t * dest, - const drm_clip_rect_t * a, - const drm_clip_rect_t * b); - -extern struct pipe_region *intel_readbuf_region(struct intel_context *intel); - -extern struct pipe_region *intel_drawbuf_region(struct intel_context *intel); - -extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags); - -extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); - -extern void intelWindowMoved(struct intel_context *intel); - -extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb); - -extern void intelInitBufferFuncs(struct dd_function_table *functions); - -#endif /* INTEL_BUFFERS_H */ diff --git a/src/mesa/drivers/dri/i915pipe/intel_context.c b/src/mesa/drivers/dri/i915pipe/intel_context.c deleted file mode 100644 index e6f0d4a0fa9..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_context.c +++ /dev/null @@ -1,717 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - - -#include "glheader.h" -#include "context.h" -#include "matrix.h" -#include "simple_list.h" -#include "extensions.h" -#include "framebuffer.h" -#include "imports.h" -#include "points.h" - -#include "tnl/tnl.h" - -#include "tnl/t_pipeline.h" -#include "tnl/t_vertex.h" - -#include "drivers/common/driverfuncs.h" - -#include "intel_screen.h" - -#include "i830_dri.h" - -#include "intel_buffers.h" -/*#include "intel_tex.h"*/ -#include "intel_ioctl.h" -#include "intel_batchbuffer.h" -#include "intel_blit.h" -/* -#include "intel_buffer_objects.h" -*/ -#include "intel_fbo.h" -#include "intel_tex_layout.h" - -#include "state_tracker/st_public.h" -#include "state_tracker/st_context.h" - -#include "drirenderbuffer.h" -#include "vblank.h" -#include "utils.h" -#include "xmlpool.h" /* for symbolic values of enum-type options */ - -#include "pipe/p_context.h" - - - -#ifndef INTEL_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" - - -#define DRIVER_DATE "20070731" - -_glthread_Mutex lockMutex; -static GLboolean lockMutexInit = GL_FALSE; - - -static const GLubyte * -intelGetString(GLcontext * ctx, GLenum name) -{ - const char *chipset; - static char buffer[128]; - - switch (name) { - case GL_VENDOR: - return (GLubyte *) "Tungsten Graphics, Inc"; - break; - - case GL_RENDERER: - switch (intel_context(ctx)->intelScreen->deviceID) { - case PCI_CHIP_845_G: - chipset = "Intel(R) 845G"; - break; - case PCI_CHIP_I830_M: - chipset = "Intel(R) 830M"; - break; - case PCI_CHIP_I855_GM: - chipset = "Intel(R) 852GM/855GM"; - break; - case PCI_CHIP_I865_G: - chipset = "Intel(R) 865G"; - break; - case PCI_CHIP_I915_G: - chipset = "Intel(R) 915G"; - break; - case PCI_CHIP_I915_GM: - chipset = "Intel(R) 915GM"; - break; - case PCI_CHIP_I945_G: - chipset = "Intel(R) 945G"; - break; - case PCI_CHIP_I945_GM: - chipset = "Intel(R) 945GM"; - break; - case PCI_CHIP_I945_GME: - chipset = "Intel(R) 945GME"; - break; - case PCI_CHIP_G33_G: - chipset = "Intel(R) G33"; - break; - case PCI_CHIP_Q35_G: - chipset = "Intel(R) Q35"; - break; - case PCI_CHIP_Q33_G: - chipset = "Intel(R) Q33"; - break; - default: - chipset = "Unknown Intel Chipset"; - break; - } - - (void) driGetRendererString(buffer, chipset, DRIVER_DATE, 0); - return (GLubyte *) buffer; - - default: - return NULL; - } -} - - -/** - * 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}, -#if 1 /* XXX FBO temporary? */ - {"GL_EXT_packed_depth_stencil", NULL}, -#endif - {"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} -}; - - - - -static const struct dri_debug_control debug_control[] = { - {"tex", DEBUG_TEXTURE}, - {"state", DEBUG_STATE}, - {"ioctl", DEBUG_IOCTL}, - {"blit", DEBUG_BLIT}, - {"mip", DEBUG_MIPTREE}, - {"fall", DEBUG_FALLBACKS}, - {"verb", DEBUG_VERBOSE}, - {"bat", DEBUG_BATCH}, - {"pix", DEBUG_PIXEL}, - {"buf", DEBUG_BUFMGR}, - {"reg", DEBUG_REGION}, - {"fbo", DEBUG_FBO}, - {"lock", DEBUG_LOCK}, - {NULL, 0} -}; - - -static void -intelInvalidateState(GLcontext * ctx, GLuint new_state) -{ - _vbo_InvalidateState(ctx, new_state); - _tnl_InvalidateState(ctx, new_state); - _tnl_invalidate_vertex_state(ctx, new_state); - - st_invalidate_state( ctx, new_state ); -} - - -void -intelFlush(GLcontext * ctx) -{ - struct intel_context *intel = intel_context(ctx); - - INTEL_FIREVERTICES(intel); - - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); - - /* XXX: Need to do an MI_FLUSH here. - */ -} - - -/** - * Check if we need to rotate/warp the front color buffer to the - * rotated screen. We generally need to do this when we get a glFlush - * or glFinish after drawing to the front color buffer. - * If no rotation, just copy the private fake front buffer to the real one. - */ -static void -intelCheckFrontUpdate(GLcontext * ctx) -{ - struct intel_context *intel = intel_context(ctx); - /* rely on _ColorDrawBufferMask being kept up to date by mesa - even for window-fbos. */ - /* not sure. Might need that for all masks including - BUFFER_BIT_FRONT_LEFT maybe? */ - if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == - BUFFER_BIT_FRONT_LEFT) { - __DRIdrawablePrivate *dPriv = intel->driDrawable; - intelCopyBuffer(dPriv, NULL); - } -} - - -/** - * Called via glFlush. - */ -static void -intelglFlush(GLcontext * ctx) -{ - intelFlush(ctx); - intelCheckFrontUpdate(ctx); -} - -void -intelFinish(GLcontext * ctx) -{ - struct intel_context *intel = intel_context(ctx); - intelFlush(ctx); - if (intel->batch->last_fence) { - driFenceFinish(intel->batch->last_fence, - 0, GL_FALSE); - driFenceUnReference(intel->batch->last_fence); - intel->batch->last_fence = NULL; - } - intelCheckFrontUpdate(ctx); -} - - -static void -intelInitDriverFunctions(struct dd_function_table *functions) -{ - _mesa_init_driver_functions(functions); - - functions->Flush = intelglFlush; - functions->Finish = intelFinish; - functions->GetString = intelGetString; - functions->UpdateState = intelInvalidateState; - - /* - intelInitTextureFuncs(functions); - */ - intelInitBufferFuncs(functions); - - st_init_driver_functions(functions); -} - - - -GLboolean -intelCreateContext(const __GLcontextModes * mesaVis, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate) -{ - struct dd_function_table functions; - - struct intel_context *intel = CALLOC_STRUCT(intel_context); - GLcontext *ctx = &intel->ctx; - - GLcontext *shareCtx = (GLcontext *) sharedContextPrivate; - __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; - intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; - drmI830Sarea *saPriv = intelScreen->sarea; - int fthrottle_mode; - GLboolean havePools; - - intelInitDriverFunctions(&functions); - - if (!_mesa_initialize_context(&intel->ctx, - mesaVis, shareCtx, - &functions, (void *) intel)) - return GL_FALSE; - - driContextPriv->driverPrivate = intel; - intel->intelScreen = intelScreen; - intel->driScreen = sPriv; - intel->sarea = saPriv; - - if (!lockMutexInit) { - lockMutexInit = GL_TRUE; - _glthread_INIT_MUTEX(lockMutex); - } - - driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, - intel->driScreen->myNum, "i915"); - - - /* Initialize the software rasterizer and helper modules. */ - _vbo_CreateContext(ctx); - _tnl_CreateContext(ctx); - - /* - * Pipe-related setup - */ - st_create_context( &intel->ctx, - intel_create_softpipe( intel ) ); - - /* KW: Not sure I like this - we should only be talking to the - * state_tracker. The pipe code will need some way of talking to - * us, eg for batchbuffer ioctls, and there will need to be a - * buffer manager interface. So, this is a temporary hack, right? - * BP: Yes, a temporary hack so we can make jumps between old/new code. - */ - intel->pipe = intel->ctx.st->pipe; -// intel->pipe->screen = intelScreen; -// intel->pipe->glctx = ctx; -// intel_init_region_functions(intel->pipe); - - 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: - intel->pipe->mipmap_tree_layout = i945_miptree_layout; - break; - case PCI_CHIP_I915_G: - case PCI_CHIP_I915_GM: - case PCI_CHIP_I830_M: - case PCI_CHIP_I855_GM: - case PCI_CHIP_I865_G: - intel->pipe->mipmap_tree_layout = i915_miptree_layout; - default: - assert(0); /*FIX*/ - } - - - /* - * memory pools - */ - DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext); - havePools = intelCreatePools(intelScreen); - 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; - - TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; - - - - fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode"); - intel->iw.irq_seq = -1; - intel->irqsEmitted = 0; - - /* Disable imaging extension until convolution is working in - * teximage paths: - */ - driInitExtensions(ctx, card_extensions, -/* GL_TRUE, */ - GL_FALSE); - - - intel->batch = intel_batchbuffer_alloc(intel); - intel->last_swap_fence = NULL; - intel->first_swap_fence = NULL; - - intel_fbo_init(intel); - - if (intel->ctx.Mesa_DXTn) { - _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); - _mesa_enable_extension(ctx, "GL_S3_s3tc"); - } - else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) { - _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); - } - -#if DO_DEBUG - INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); -#endif - - - return GL_TRUE; -} - -void -intelDestroyContext(__DRIcontextPrivate * driContextPriv) -{ - struct intel_context *intel = - (struct intel_context *) driContextPriv->driverPrivate; - - assert(intel); /* should never be null */ - if (intel) { - GLboolean release_texture_heaps; - - INTEL_FIREVERTICES(intel); - - //intel->vtbl.destroy(intel); - - release_texture_heaps = (intel->ctx.Shared->RefCount == 1); - _tnl_DestroyContext(&intel->ctx); - _vbo_DestroyContext(&intel->ctx); - - 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 (release_texture_heaps) { - /* This share group is about to go away, free our private - * texture object data. - */ - if (INTEL_DEBUG & DEBUG_TEXTURE) - fprintf(stderr, "do something to free texture heaps\n"); - } - - /* free the Mesa context */ - _mesa_free_context_data(&intel->ctx); - } -} - -GLboolean -intelUnbindContext(__DRIcontextPrivate * driContextPriv) -{ - struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; - /* XXX UnbindContext is called AFTER the new context is made current. - Hopefully shouldn't be a problem ? */ - FLUSH_VERTICES((&intel->ctx), 0); - intelFlush(&intel->ctx); - return GL_TRUE; -} - -GLboolean -intelMakeCurrent(__DRIcontextPrivate * driContextPriv, - __DRIdrawablePrivate * driDrawPriv, - __DRIdrawablePrivate * driReadPriv) -{ - -#if 0 - if (driDrawPriv) { - fprintf(stderr, "x %d, y %d, width %d, height %d\n", - driDrawPriv->x, driDrawPriv->y, driDrawPriv->w, driDrawPriv->h); - } -#endif - - if (driContextPriv) { - struct intel_context *intel = - (struct intel_context *) driContextPriv->driverPrivate; - struct intel_framebuffer *intel_fb = - (struct intel_framebuffer *) driDrawPriv->driverPrivate; - GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; - - /* this is a hack so we have a valid context when the region allocation - is done. Need a per-screen context? */ - intel->intelScreen->dummyctxptr = intel; - - /* update GLframebuffer size to match window if needed */ - driUpdateFramebufferSize(&intel->ctx, driDrawPriv); - - if (driReadPriv != driDrawPriv) { - driUpdateFramebufferSize(&intel->ctx, driReadPriv); - } - - _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb); - - /* The drawbuffer won't always be updated by _mesa_make_current: - */ - if (intel->ctx.DrawBuffer == &intel_fb->Base) { - - if (intel->driDrawable != driDrawPriv) { - if (driDrawPriv->pdraw->swap_interval == (unsigned)-1) { - int i; - - intel_fb->vblank_flags = driGetDefaultVBlankFlags(&intel->optionCache); - - (*dri_interface->getUST) (&intel_fb->swap_ust); - driDrawableInitVBlank(driDrawPriv, intel_fb->vblank_flags, - &intel_fb->vbl_seq); - intel_fb->vbl_waited = intel_fb->vbl_seq; - - for (i = 0; i < 2; i++) { - if (intel_fb->color_rb[i]) - intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_seq; - } - } - } - } - - if ((intel->driDrawable != driDrawPriv) || - (intel->lastStamp != driDrawPriv->lastStamp)) { - intel->driDrawable = driDrawPriv; - intelWindowMoved(intel); - intel->lastStamp = driDrawPriv->lastStamp; - } - - } - else { - _mesa_make_current(NULL, NULL, NULL); - } - - return GL_TRUE; -} - -static void -intelContendedLock(struct intel_context *intel, GLuint flags) -{ - __DRIdrawablePrivate *dPriv = intel->driDrawable; - __DRIscreenPrivate *sPriv = intel->driScreen; - intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; - drmI830Sarea *sarea = intel->sarea; - - drmGetLock(intel->driFd, intel->hHWContext, flags); - - if (INTEL_DEBUG & DEBUG_LOCK) - _mesa_printf("%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); - } - -#if 0 - if (sarea->width != intel->width || - sarea->height != intel->height || - sarea->rotation != intel->current_rotation) { - int numClipRects = intel->numClipRects; - - /* - * FIXME: Really only need to do this when drawing to a - * common back- or front buffer. - */ - - /* - * This will essentially drop the outstanding batchbuffer on the floor. - */ - intel->numClipRects = 0; - - INTEL_FIREVERTICES(intel); - - if (intel->batch->map != intel->batch->ptr) - intel_batchbuffer_flush(intel->batch); - - intel->numClipRects = numClipRects; - - /* force window update */ - intel->lastStamp = 0; - - intel->width = sarea->width; - intel->height = sarea->height; - intel->current_rotation = sarea->rotation; - } -#endif -} - - -/* Lock the hardware and validate our state. - */ -void LOCK_HARDWARE( struct intel_context *intel ) -{ - char __ret=0; - struct intel_framebuffer *intel_fb = NULL; - struct intel_renderbuffer *intel_rb = NULL; - _glthread_LOCK_MUTEX(lockMutex); - assert(!intel->locked); - - if (intel->driDrawable) { - intel_fb = intel->driDrawable->driverPrivate; - - if (intel_fb) - intel_rb = - intel_get_renderbuffer(&intel_fb->Base, - intel_fb->Base._ColorDrawBufferMask[0] == - BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : - BUFFER_BACK_LEFT); - } - - if (intel_rb && intel_fb->vblank_flags && - !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) && - (intel_fb->vbl_waited - intel_rb->vbl_pending) > (1<<23)) { - drmVBlank vbl; - - vbl.request.type = DRM_VBLANK_ABSOLUTE; - - if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { - vbl.request.type |= DRM_VBLANK_SECONDARY; - } - - vbl.request.sequence = intel_rb->vbl_pending; - drmWaitVBlank(intel->driFd, &vbl); - intel_fb->vbl_waited = vbl.reply.sequence; - } - - DRM_CAS(intel->driHwLock, intel->hHWContext, - (DRM_LOCK_HELD|intel->hHWContext), __ret); - - if (__ret) - intelContendedLock( intel, 0 ); - - if (INTEL_DEBUG & DEBUG_LOCK) - _mesa_printf("%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); - - if (INTEL_DEBUG & DEBUG_LOCK) - _mesa_printf("%s - unlocked\n", __progname); -} - diff --git a/src/mesa/drivers/dri/i915pipe/intel_context.h b/src/mesa/drivers/dri/i915pipe/intel_context.h deleted file mode 100644 index 1a4e7ca1cd4..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_context.h +++ /dev/null @@ -1,225 +0,0 @@ -/************************************************************************** - * - * 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 INTELCONTEXT_INC -#define INTELCONTEXT_INC - - - -#include "mtypes.h" -#include "drm.h" -#include "mm.h" -#include "texmem.h" - -#include "intel_screen.h" -#include "i915_drm.h" -#include "i830_common.h" - - -#define DV_PF_555 (1<<8) -#define DV_PF_565 (2<<8) -#define DV_PF_8888 (3<<8) - -struct pipe_context; -struct pipe_region; -struct intel_context; -struct _DriBufferObject; - - -#define INTEL_WRITE_PART 0x1 -#define INTEL_WRITE_FULL 0x2 -#define INTEL_READ 0x4 - - - -#define INTEL_MAX_FIXUP 64 - -struct intel_context -{ - GLcontext ctx; /* the parent class */ - - struct pipe_context *pipe; - - GLint refcount; - - struct _DriFenceObject *last_swap_fence; - struct _DriFenceObject *first_swap_fence; - - struct intel_batchbuffer *batch; - - - GLboolean locked; - char *prevLockFile; - int prevLockLine; - - GLuint ClearColor565; - GLuint ClearColor8888; - - - /* These refer to the current drawing buffer: - */ - GLuint numClipRects; /**< cliprects for drawing */ - drm_clip_rect_t *pClipRects; - drm_clip_rect_t fboRect; /**< cliprect for rendering */ - - GLuint irqsEmitted; - drm_i915_irq_wait_t iw; - - drm_context_t hHWContext; - drmLock *driHwLock; - int driFd; - - __DRIdrawablePrivate *driDrawable; - __DRIscreenPrivate *driScreen; - intelScreenPrivate *intelScreen; - drmI830Sarea *sarea; - - GLuint lastStamp; - - /** - * Configuration cache - */ - driOptionCache optionCache; -}; - -/* These are functions now: - */ -void LOCK_HARDWARE( struct intel_context *intel ); -void UNLOCK_HARDWARE( struct intel_context *intel ); - -extern char *__progname; - -/* Will become a call into state_tracker: - */ -#define INTEL_FIREVERTICES(intel) - -/* ================================================================ - * Color packing: - */ - -#define INTEL_PACKCOLOR4444(r,g,b,a) \ - ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) - -#define INTEL_PACKCOLOR1555(r,g,b,a) \ - ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ - ((a) ? 0x8000 : 0)) - -#define INTEL_PACKCOLOR565(r,g,b) \ - ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) - -#define INTEL_PACKCOLOR8888(r,g,b,a) \ - ((a<<24) | (r<<16) | (g<<8) | b) - - - - -/* ================================================================ - * Debugging: - */ -#define DO_DEBUG 0 -#if DO_DEBUG -extern int INTEL_DEBUG; -#else -#define INTEL_DEBUG 0 -#endif - -#define DEBUG_TEXTURE 0x1 -#define DEBUG_STATE 0x2 -#define DEBUG_IOCTL 0x4 -#define DEBUG_BLIT 0x8 -#define DEBUG_MIPTREE 0x10 -#define DEBUG_FALLBACKS 0x20 -#define DEBUG_VERBOSE 0x40 -#define DEBUG_BATCH 0x80 -#define DEBUG_PIXEL 0x100 -#define DEBUG_BUFMGR 0x200 -#define DEBUG_REGION 0x400 -#define DEBUG_FBO 0x800 -#define DEBUG_LOCK 0x1000 - -#define DBG(...) do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0) - - -#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 - - -/* ================================================================ - * intel_context.c: - */ - -extern GLboolean intelInitContext(struct intel_context *intel, - const __GLcontextModes * mesaVis, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate, - struct dd_function_table *functions); - -extern void intelGetLock(struct intel_context *intel, GLuint flags); - -extern void intelFinish(GLcontext * ctx); -extern void intelFlush(GLcontext * ctx); - - -/* ================================================================ - * intel_softpipe.c: - */ - -struct pipe_context * -intel_create_softpipe( struct intel_context *intel ); - - -#define MI_BATCH_BUFFER_END (0xA<<23) - -#define FALLBACK( ctx, bit, mode ) - -/*====================================================================== - * Inline conversion functions. - * These are better-typed than the macros used previously: - */ -static INLINE struct intel_context * -intel_context(GLcontext * ctx) -{ - return (struct intel_context *) ctx; -} - -extern struct intel_renderbuffer *intel_renderbuffer(struct gl_renderbuffer - *rb); - -extern void intel_init_region_functions(struct pipe_context *pipe); - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_depthstencil.c b/src/mesa/drivers/dri/i915pipe/intel_depthstencil.c deleted file mode 100644 index 81e09698cc5..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_depthstencil.c +++ /dev/null @@ -1,282 +0,0 @@ -/************************************************************************** - * - * 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 "glheader.h" -#include "imports.h" -#include "context.h" -#include "depthstencil.h" -#include "fbobject.h" -#include "framebuffer.h" -#include "hash.h" -#include "mtypes.h" -#include "renderbuffer.h" - -#include "intel_context.h" -#include "intel_fbo.h" -#include "intel_depthstencil.h" - -#include "pipe/p_context.h" - -/** - * The GL_EXT_framebuffer_object allows the user to create their own - * framebuffer objects consisting of color renderbuffers (0 or more), - * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1). - * - * The spec considers depth and stencil renderbuffers to be totally independent - * buffers. In reality, most graphics hardware today uses a combined - * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil). - * - * This causes difficulty because the user may create some number of depth - * renderbuffers and some number of stencil renderbuffers and bind them - * together in framebuffers in any combination. - * - * This code manages all that. - * - * 1. Depth renderbuffers are always allocated in hardware as 32bpp - * GL_DEPTH24_STENCIL8 buffers. - * - * 2. Stencil renderbuffers are initially allocated in software as 8bpp - * GL_STENCIL_INDEX8 buffers. - * - * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth - * fields (respectively) to indicate if the buffer's currently paired - * with another stencil or depth buffer (respectively). - * - * 4. When a depth and stencil buffer are initially both attached to the - * current framebuffer, we merge the stencil buffer values into the - * depth buffer (really a depth+stencil buffer). The then hardware uses - * the combined buffer. - * - * 5. Whenever a depth or stencil buffer is reallocated (with - * glRenderbufferStorage) we undo the pairing and copy the stencil values - * from the combined depth/stencil buffer back to the stencil-only buffer. - * - * 6. We also undo the pairing when we find a change in buffer bindings. - * - * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we - * just use the combined depth/stencil buffer and ignore the stencil values. - * - * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have - * to promote the 8bpp software stencil buffer to a 32bpp hardware - * depth+stencil buffer. - * - */ - - - -static void -map_regions(GLcontext * ctx, - struct intel_renderbuffer *depthRb, - struct intel_renderbuffer *stencilRb) -{ - struct intel_context *intel = intel_context(ctx); - if (depthRb && depthRb->region) { - intel->pipe->region_map(intel->pipe, depthRb->region); - depthRb->pfMap = depthRb->region->map; - depthRb->pfPitch = depthRb->region->pitch; - } - if (stencilRb && stencilRb->region) { - intel->pipe->region_map(intel->pipe, stencilRb->region); - stencilRb->pfMap = stencilRb->region->map; - stencilRb->pfPitch = stencilRb->region->pitch; - } -} - -static void -unmap_regions(GLcontext * ctx, - struct intel_renderbuffer *depthRb, - struct intel_renderbuffer *stencilRb) -{ - struct intel_context *intel = intel_context(ctx); - if (depthRb && depthRb->region) { - intel->pipe->region_unmap(intel->pipe, depthRb->region); - depthRb->pfMap = NULL; - depthRb->pfPitch = 0; - } - if (stencilRb && stencilRb->region) { - intel->pipe->region_unmap(intel->pipe, stencilRb->region); - stencilRb->pfMap = NULL; - stencilRb->pfPitch = 0; - } -} - - - -/** - * Undo the pairing/interleaving between depth and stencil buffers. - * irb should be a depth/stencil or stencil renderbuffer. - */ -void -intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb) -{ - if (irb->PairedStencil) { - /* irb is a depth/stencil buffer */ - struct gl_renderbuffer *stencilRb; - struct intel_renderbuffer *stencilIrb; - - ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - - stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil); - stencilIrb = intel_renderbuffer(stencilRb); - if (stencilIrb) { - /* need to extract stencil values from the depth buffer */ - ASSERT(stencilIrb->PairedDepth == irb->Base.Name); - map_regions(ctx, irb, stencilIrb); - _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base); - unmap_regions(ctx, irb, stencilIrb); - stencilIrb->PairedDepth = 0; - } - irb->PairedStencil = 0; - } - else if (irb->PairedDepth) { - /* irb is a stencil buffer */ - struct gl_renderbuffer *depthRb; - struct intel_renderbuffer *depthIrb; - - ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || - irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - - depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth); - depthIrb = intel_renderbuffer(depthRb); - if (depthIrb) { - /* need to extract stencil values from the depth buffer */ - ASSERT(depthIrb->PairedStencil == irb->Base.Name); - map_regions(ctx, depthIrb, irb); - _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base); - unmap_regions(ctx, depthIrb, irb); - depthIrb->PairedStencil = 0; - } - irb->PairedDepth = 0; - } - else { - _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing"); - } - - ASSERT(irb->PairedStencil == 0); - ASSERT(irb->PairedDepth == 0); -} - - -/** - * Examine the depth and stencil renderbuffers which are attached to the - * framebuffer. If both depth and stencil are attached, make sure that the - * renderbuffers are 'paired' (combined). If only depth or only stencil is - * attached, undo any previous pairing. - * - * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments - * change, for example). - */ -void -intel_validate_paired_depth_stencil(GLcontext * ctx, - struct gl_framebuffer *fb) -{ - struct intel_renderbuffer *depthRb, *stencilRb; - - depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL); - - if (depthRb && stencilRb) { - if (depthRb == stencilRb) { - /* Using a user-created combined depth/stencil buffer. - * Nothing to do. - */ - ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT); - ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - } - else { - /* Separate depth/stencil buffers, need to interleave now */ - ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT); - ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX); - /* may need to interleave depth/stencil now */ - if (depthRb->PairedStencil == stencilRb->Base.Name) { - /* OK, the depth and stencil buffers are already interleaved */ - ASSERT(stencilRb->PairedDepth == depthRb->Base.Name); - } - else { - /* need to setup new pairing/interleaving */ - if (depthRb->PairedStencil) { - intel_unpair_depth_stencil(ctx, depthRb); - } - if (stencilRb->PairedDepth) { - intel_unpair_depth_stencil(ctx, stencilRb); - } - - ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || - stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - - /* establish new pairing: interleave stencil into depth buffer */ - map_regions(ctx, depthRb, stencilRb); - _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base); - unmap_regions(ctx, depthRb, stencilRb); - depthRb->PairedStencil = stencilRb->Base.Name; - stencilRb->PairedDepth = depthRb->Base.Name; - } - - } - } - else if (depthRb) { - /* Depth buffer but no stencil buffer. - * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits. - */ - /* can't assert this until storage is allocated: - ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - */ - /* intel_undo any previous pairing */ - if (depthRb->PairedStencil) { - intel_unpair_depth_stencil(ctx, depthRb); - } - } - else if (stencilRb) { - /* Stencil buffer but no depth buffer. - * Since h/w doesn't typically support just 8bpp stencil w/out Z, - * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits. - */ - /* undo any previous pairing */ - if (stencilRb->PairedDepth) { - intel_unpair_depth_stencil(ctx, stencilRb); - } - if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) { - /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */ - _mesa_promote_stencil(ctx, &stencilRb->Base); - ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); - } - } - - /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */ - _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); - if (depthRb && depthRb->PairedStencil) - _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH); - else - _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); - - - /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer - * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer - * if present. - */ -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_depthstencil.h b/src/mesa/drivers/dri/i915pipe/intel_depthstencil.h deleted file mode 100644 index 2d3fc48b3a3..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_depthstencil.h +++ /dev/null @@ -1,14 +0,0 @@ - -#ifndef INTEL_DEPTH_STENCIL_H -#define INTEL_DEPTH_STENCIL_H - - -extern void -intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb); - -extern void -intel_validate_paired_depth_stencil(GLcontext * ctx, - struct gl_framebuffer *fb); - - -#endif /* INTEL_DEPTH_STENCIL_H */ diff --git a/src/mesa/drivers/dri/i915pipe/intel_fbo.c b/src/mesa/drivers/dri/i915pipe/intel_fbo.c deleted file mode 100644 index 0b6c6a94ee5..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_fbo.c +++ /dev/null @@ -1,629 +0,0 @@ -/************************************************************************** - * - * 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 "imports.h" -#include "mtypes.h" -#include "fbobject.h" -#include "framebuffer.h" -#include "renderbuffer.h" -#include "context.h" -#include "texformat.h" -#include "texrender.h" - -#include "intel_context.h" -#include "intel_buffers.h" -#include "intel_depthstencil.h" -#include "intel_fbo.h" -#include "state_tracker/st_mipmap_tree.h" -/*#include "intel_tex.h"*/ - -#include "pipe/p_context.h" - -#define FILE_DEBUG_FLAG DEBUG_FBO - -#define INTEL_RB_CLASS 0x12345678 - - -/* XXX FBO: move this to intel_context.h (inlined) */ -/** - * Return a gl_renderbuffer ptr casted to intel_renderbuffer. - * NULL will be returned if the rb isn't really an intel_renderbuffer. - * This is determiend by checking the ClassID. - */ -struct intel_renderbuffer * -intel_renderbuffer(struct gl_renderbuffer *rb) -{ - struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; - if (irb && irb->Base.ClassID == INTEL_RB_CLASS) { - /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ - return irb; - } - else - return NULL; -} - - -struct intel_renderbuffer * -intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) -{ - return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); -} - - -void -intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) -{ - int current_page = intel_fb->pf_current_page; - int next_page = (current_page + 1) % intel_fb->pf_num_pages; - struct gl_renderbuffer *tmp_rb; - - /* Exchange renderbuffers if necessary but make sure their reference counts - * are preserved. - */ - if (intel_fb->color_rb[current_page] && - intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != - &intel_fb->color_rb[current_page]->Base) { - tmp_rb = NULL; - _mesa_reference_renderbuffer(&tmp_rb, - intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); - tmp_rb = &intel_fb->color_rb[current_page]->Base; - _mesa_reference_renderbuffer( - &intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb); - _mesa_reference_renderbuffer(&tmp_rb, NULL); - } - - if (intel_fb->color_rb[next_page] && - intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != - &intel_fb->color_rb[next_page]->Base) { - tmp_rb = NULL; - _mesa_reference_renderbuffer(&tmp_rb, - intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); - tmp_rb = &intel_fb->color_rb[next_page]->Base; - _mesa_reference_renderbuffer( - &intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb); - _mesa_reference_renderbuffer(&tmp_rb, NULL); - } -} - - -struct pipe_region * -intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) -{ - struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); - - if (irb) - return irb->region; - else - return NULL; -} - - - -/** - * Create a new framebuffer object. - */ -static struct gl_framebuffer * -intel_new_framebuffer(GLcontext * ctx, GLuint name) -{ - /* Only drawable state in intel_framebuffer at this time, just use Mesa's - * class - */ - return _mesa_new_framebuffer(ctx, name); -} - - -static void -intel_delete_renderbuffer(struct gl_renderbuffer *rb) -{ - GET_CURRENT_CONTEXT(ctx); - struct intel_context *intel = intel_context(ctx); - struct intel_renderbuffer *irb = intel_renderbuffer(rb); - - ASSERT(irb); - - DBG("freeing renderbuffer\n"); - - if (irb->PairedStencil || irb->PairedDepth) { - intel_unpair_depth_stencil(ctx, irb); - } - - if (intel && irb->region) { - intel->pipe->region_release(intel->pipe, &irb->region); - } - - _mesa_free(irb); -} - - - -/** - * Return a pointer to a specific pixel in a renderbuffer. - */ -static void * -intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, - GLint x, GLint y) -{ - /* By returning NULL we force all software rendering to go through - * the span routines. - */ - return NULL; -} - - - -/** - * Called via glRenderbufferStorageEXT() to set the format and allocate - * storage for a user-created (or priv buffer) renderbuffer. - */ -static GLboolean -intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, - GLenum internalFormat, - GLuint width, GLuint height) -{ - struct intel_context *intel = intel_context(ctx); - struct intel_renderbuffer *irb = intel_renderbuffer(rb); - GLboolean softwareBuffer = GL_FALSE; - int cpp; - - switch (internalFormat) { - case GL_R3_G3_B2: - case GL_RGB4: - case GL_RGB5: - rb->_ActualFormat = GL_RGB5; - rb->DataType = GL_UNSIGNED_BYTE; - rb->RedBits = 5; - rb->GreenBits = 6; - rb->BlueBits = 5; - cpp = 2; - break; - case GL_RGB: - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - case GL_RGBA: - case GL_RGBA2: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - rb->_ActualFormat = GL_RGBA8; - rb->DataType = GL_UNSIGNED_BYTE; - rb->RedBits = 8; - rb->GreenBits = 8; - rb->BlueBits = 8; - rb->AlphaBits = 8; - cpp = 4; - break; - case GL_STENCIL_INDEX: - case GL_STENCIL_INDEX1_EXT: - case GL_STENCIL_INDEX4_EXT: - case GL_STENCIL_INDEX8_EXT: - case GL_STENCIL_INDEX16_EXT: - /* alloc a depth+stencil buffer */ - rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; - rb->DataType = GL_UNSIGNED_INT_24_8_EXT; - rb->StencilBits = 8; - cpp = 4; - break; - case GL_DEPTH_COMPONENT16: - rb->_ActualFormat = GL_DEPTH_COMPONENT16; - rb->DataType = GL_UNSIGNED_SHORT; - rb->DepthBits = 16; - cpp = 2; - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; - rb->DataType = GL_UNSIGNED_INT_24_8_EXT; - rb->DepthBits = 24; - cpp = 4; - break; - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; - rb->DataType = GL_UNSIGNED_INT_24_8_EXT; - rb->DepthBits = 24; - rb->StencilBits = 8; - cpp = 4; - break; - default: - _mesa_problem(ctx, - "Unexpected format (%x) in intel_alloc_renderbuffer_storage", internalFormat); - return GL_FALSE; - } - - intelFlush(ctx); - - /* free old region */ - if (irb->region) { - intel->pipe->region_release(intel->pipe, &irb->region); - } - - /* allocate new memory region/renderbuffer */ - if (softwareBuffer) { - return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, - width, height); - } - else { - /* Choose a pitch to match hardware requirements: - */ - GLuint pitch = ((cpp * width + 63) & ~63) / cpp; - - /* alloc hardware renderbuffer */ - DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, - height, pitch); - - irb->region = intel->pipe->region_alloc(intel->pipe, cpp, pitch, height); - if (!irb->region) - return GL_FALSE; /* out of memory? */ - - ASSERT(irb->region->buffer); - - rb->Width = width; - rb->Height = height; - - /* update the surface's size too */ - rb->surface->width = width; - rb->surface->height = height; - rb->surface->region = irb->region; - - /* This sets the Get/PutRow/Value functions */ - // intel_set_span_functions(&irb->Base); - - return GL_TRUE; - } -} - - -static void -intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb, - GLuint width, GLuint height) -{ - struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; - int i; - - _mesa_resize_framebuffer(ctx, fb, width, height); - - fb->Initialized = GL_TRUE; /* XXX remove someday */ - - if (fb->Name != 0) { - return; - } - - /* Make sure all window system renderbuffers are up to date */ - for (i = 0; i < 3; i++) { - struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base; - - /* only resize if size is changing */ - if (rb && (rb->Width != width || rb->Height != height)) { - rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); - } - } -} - -static GLboolean -intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, - GLenum internalFormat, GLuint width, GLuint height) -{ - _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); - return GL_FALSE; -} - - - -struct intel_renderbuffer * -intel_new_renderbuffer_fb(GLuint intFormat) -{ - struct intel_renderbuffer *irb; - - irb = CALLOC_STRUCT(intel_renderbuffer); - if (!irb) { - _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); - return NULL; - } - - _mesa_init_renderbuffer(&irb->Base, 0); - irb->Base.ClassID = INTEL_RB_CLASS; - irb->Base.InternalFormat = intFormat; - - switch (intFormat) { - case GL_RGB5: - case GL_RGBA8: - irb->Base._BaseFormat = GL_RGBA; - break; - case GL_DEPTH_COMPONENT16: - irb->Base._BaseFormat = GL_DEPTH_COMPONENT; - break; - case GL_DEPTH24_STENCIL8_EXT: - irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; - break; - default: - _mesa_problem(NULL, - "Unexpected intFormat in intel_create_renderbuffer"); - return NULL; - } - - /* intel-specific methods */ - irb->Base.Delete = intel_delete_renderbuffer; - irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; - irb->Base.GetPointer = intel_get_pointer; - /* span routines set in alloc_storage function */ - - irb->Base.surface = intel_new_surface(intFormat); - irb->Base.surface->rb = irb; - - return irb; -} - -/** - * Create a new renderbuffer object. - * Typically called via glBindRenderbufferEXT(). - */ -static struct gl_renderbuffer * -intel_new_renderbuffer(GLcontext * ctx, GLuint name) -{ - /*struct intel_context *intel = intel_context(ctx); */ - struct intel_renderbuffer *irb; - - irb = CALLOC_STRUCT(intel_renderbuffer); - if (!irb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); - return NULL; - } - - _mesa_init_renderbuffer(&irb->Base, name); - irb->Base.ClassID = INTEL_RB_CLASS; - - /* intel-specific methods */ - irb->Base.Delete = intel_delete_renderbuffer; - irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; - irb->Base.GetPointer = intel_get_pointer; - /* span routines set in alloc_storage function */ - - irb->Base.surface = intel_new_surface(0 /*unknown format*/); - irb->Base.surface->rb = irb; - - return &irb->Base; -} - - -/** - * Called via glBindFramebufferEXT(). - */ -static void -intel_bind_framebuffer(GLcontext * ctx, GLenum target, - struct gl_framebuffer *fb, struct gl_framebuffer *fbread) -{ - if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { - intel_draw_buffer(ctx, fb); - /* Integer depth range depends on depth buffer bits */ - /* XXX - */ -// ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); - } - else { - /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ - } -} - - -/** - * Called via glFramebufferRenderbufferEXT(). - */ -static void -intel_framebuffer_renderbuffer(GLcontext * ctx, - struct gl_framebuffer *fb, - GLenum attachment, struct gl_renderbuffer *rb) -{ - DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); - - intelFlush(ctx); - - _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); - intel_draw_buffer(ctx, fb); -} - - -/** - * When glFramebufferTexture[123]D is called this function sets up the - * gl_renderbuffer wrapper around the texture image. - * This will have the region info needed for hardware rendering. - */ -static struct intel_renderbuffer * -intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage) -{ - const GLuint name = ~0; /* not significant, but distinct for debugging */ - struct intel_renderbuffer *irb; - - /* make an intel_renderbuffer to wrap the texture image */ - irb = CALLOC_STRUCT(intel_renderbuffer); - if (!irb) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); - return NULL; - } - - _mesa_init_renderbuffer(&irb->Base, name); - irb->Base.ClassID = INTEL_RB_CLASS; - - if (texImage->TexFormat == &_mesa_texformat_argb8888) { - irb->Base._ActualFormat = GL_RGBA8; - irb->Base._BaseFormat = GL_RGBA; - DBG("Render to RGBA8 texture OK\n"); - } - else if (texImage->TexFormat == &_mesa_texformat_rgb565) { - irb->Base._ActualFormat = GL_RGB5; - irb->Base._BaseFormat = GL_RGB; - DBG("Render to RGB5 texture OK\n"); - } - else if (texImage->TexFormat == &_mesa_texformat_z16) { - irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; - irb->Base._BaseFormat = GL_DEPTH_COMPONENT; - DBG("Render to DEPTH16 texture OK\n"); - } - else { - DBG("Render to texture BAD FORMAT %d\n", - texImage->TexFormat->MesaFormat); - _mesa_free(irb); - return NULL; - } - - irb->Base.InternalFormat = irb->Base._ActualFormat; - irb->Base.Width = texImage->Width; - irb->Base.Height = texImage->Height; - irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */ - irb->Base.RedBits = texImage->TexFormat->RedBits; - irb->Base.GreenBits = texImage->TexFormat->GreenBits; - irb->Base.BlueBits = texImage->TexFormat->BlueBits; - irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; - irb->Base.DepthBits = texImage->TexFormat->DepthBits; - - irb->Base.Delete = intel_delete_renderbuffer; - irb->Base.AllocStorage = intel_nop_alloc_storage; - -// intel_set_span_functions(&irb->Base); - - irb->RenderToTexture = GL_TRUE; - - return irb; -} - - -/** - * Called by glFramebufferTexture[123]DEXT() (and other places) to - * prepare for rendering into texture memory. This might be called - * many times to choose different texture levels, cube faces, etc - * before intel_finish_render_texture() is ever called. - */ -static void -intel_render_texture(GLcontext * ctx, - struct gl_framebuffer *fb, - struct gl_renderbuffer_attachment *att) -{ -#if 0 - struct intel_context *intel = intel_context(ctx); - struct gl_texture_image *newImage - = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; - struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); - struct st_texture_image *st_image; - GLuint imageOffset; - - (void) fb; - - ASSERT(newImage); - - if (!irb) { - irb = intel_wrap_texture(ctx, newImage); - if (irb) { - /* bind the wrapper to the attachment point */ - _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); - } - else { - /* fallback to software rendering */ - _mesa_render_texture(ctx, fb, att); - return; - } - } - - DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", - _glthread_GetID(), - att->Texture->Name, newImage->Width, newImage->Height, - irb->Base.RefCount); - - /* point the renderbufer's region to the texture image region */ - st_image = st_texture_image(newImage); - if (irb->region != st_image->mt->region) { - if (irb->region) - intel->pipe->region_release(intel->pipe, &irb->region); - pipe_region_reference(&irb->region, st_image->mt->region); - } - - /* compute offset of the particular 2D image within the texture region */ - imageOffset = st_miptree_image_offset(st_image->mt, - att->CubeMapFace, - att->TextureLevel); - - if (att->Texture->Target == GL_TEXTURE_3D) { - const GLuint *offsets = st_miptree_depth_offsets(st_image->mt, - att->TextureLevel); - imageOffset += offsets[att->Zoffset]; - } - - /* store that offset in the region */ -#if 0 - st_image->mt->region->draw_offset = imageOffset; -#endif - - /* update drawing region, etc */ - intel_draw_buffer(ctx, fb); -#endif -} - - -/** - * Called by Mesa when rendering to a texture is done. - */ -static void -intel_finish_render_texture(GLcontext * ctx, - struct gl_renderbuffer_attachment *att) -{ - struct intel_context *intel = intel_context(ctx); - struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); - - DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name); - - if (irb) { - /* just release the region */ - intel->pipe->region_release(intel->pipe, &irb->region); - } - else if (att->Renderbuffer) { - /* software fallback */ - _mesa_finish_render_texture(ctx, att); - /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ - } -} - - -/** - * Do one-time context initializations related to GL_EXT_framebuffer_object. - * Hook in device driver functions. - */ -void -intel_fbo_init(struct intel_context *intel) -{ - intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; - intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; - intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; - intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; - intel->ctx.Driver.RenderTexture = intel_render_texture; - intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; - intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_fbo.h b/src/mesa/drivers/dri/i915pipe/intel_fbo.h deleted file mode 100644 index 0f99a3e98db..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_fbo.h +++ /dev/null @@ -1,127 +0,0 @@ -/************************************************************************** - * - * 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_FBO_H -#define INTEL_FBO_H - - -#include "pipe/p_state.h" -#include "pipe/softpipe/sp_surface.h" - - -struct intel_context; -struct pipe_region; - - -/** - * Intel framebuffer, derived from gl_framebuffer. - */ -struct intel_framebuffer -{ - struct gl_framebuffer Base; - - struct intel_renderbuffer *color_rb[3]; - - /* Drawable page flipping state */ - GLboolean pf_active; - GLuint pf_seq; - GLint pf_pipes; - GLint pf_current_page; - GLint pf_num_pages; - - /* VBI - */ - GLuint vbl_seq; - GLuint vblank_flags; - GLuint vbl_waited; - - int64_t swap_ust; - int64_t swap_missed_ust; - - GLuint swap_count; - GLuint swap_missed_count; -}; - - -/** - * Intel renderbuffer, derived from gl_renderbuffer. - * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs, - * not pointers because in some circumstances a deleted renderbuffer could - * result in a dangling pointer here. - */ -struct intel_renderbuffer -{ - struct gl_renderbuffer Base; - struct pipe_region *region; - void *pfMap; /* possibly paged flipped map pointer */ - GLuint pfPitch; /* possibly paged flipped pitch */ - GLboolean RenderToTexture; /* RTT? */ - - GLuint PairedDepth; /**< only used if this is a depth renderbuffer */ - GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ - - GLuint pf_pending; /**< sequence number of pending flip */ - - GLuint vbl_pending; /**< vblank sequence number of pending flip */ - - struct intel_surface *surface; -}; - -#if 0 -extern struct intel_renderbuffer *intel_create_renderbuffer(GLenum intFormat, - GLsizei width, - GLsizei height, - int offset, - int pitch, - int cpp, - void *map); -#endif - -extern struct intel_renderbuffer *intel_new_renderbuffer_fb(GLuint intFormat); - -extern void intel_fbo_init(struct intel_context *intel); - - -/* XXX make inline or macro */ -extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer - *fb, - GLuint attIndex); - -extern void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb); - - -/* XXX make inline or macro */ -extern struct pipe_region *intel_get_rb_region(struct gl_framebuffer *fb, - GLuint attIndex); - - - -extern struct pipe_surface * -intel_new_surface(GLuint intFormat); - - -#endif /* INTEL_FBO_H */ diff --git a/src/mesa/drivers/dri/i915pipe/intel_ioctl.c b/src/mesa/drivers/dri/i915pipe/intel_ioctl.c deleted file mode 100644 index 154a3e289f5..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_ioctl.c +++ /dev/null @@ -1,135 +0,0 @@ -/************************************************************************** - * - * 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 -#include -#include -#include - -#include "mtypes.h" -#include "context.h" - -#include "intel_context.h" -#include "intel_ioctl.h" -#include "intel_batchbuffer.h" -#include "intel_blit.h" -#include "drm.h" - -#define FILE_DEBUG_FLAG DEBUG_IOCTL - -int -intelEmitIrqLocked(struct intel_context *intel) -{ - drmI830IrqEmit ie; - int ret, seq; - - assert(((*(int *) intel->driHwLock) & ~DRM_LOCK_CONT) == - (DRM_LOCK_HELD | intel->hHWContext)); - - ie.irq_seq = &seq; - - ret = drmCommandWriteRead(intel->driFd, DRM_I830_IRQ_EMIT, - &ie, sizeof(ie)); - if (ret) { - fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret); - exit(1); - } - - DBG("%s --> %d\n", __FUNCTION__, seq); - - return seq; -} - -void -intelWaitIrq(struct intel_context *intel, int seq) -{ - int ret; - - DBG("%s %d\n", __FUNCTION__, seq); - - intel->iw.irq_seq = seq; - - do { - ret = - drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, - sizeof(intel->iw)); - } while (ret == -EAGAIN || ret == -EINTR); - - if (ret) { - fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret); - exit(1); - } -} - - -void -intel_batch_ioctl(struct intel_context *intel, - GLuint start_offset, - GLuint used, - GLboolean ignore_cliprects, GLboolean allow_unlock) -{ - drmI830BatchBuffer batch; - - assert(intel->locked); - assert(used); - - DBG("%s used %d offset %x..%x ignore_cliprects %d\n", - __FUNCTION__, - used, start_offset, start_offset + used, ignore_cliprects); - - /* Throw away non-effective packets. Won't work once we have - * hardware contexts which would preserve statechanges beyond a - * single buffer. - */ - - - - batch.start = start_offset; - batch.used = used; - batch.cliprects = intel->pClipRects; - batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; - batch.DR1 = 0; - batch.DR4 = 0; /* still need this ? */ - - DBG("%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))) { - fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno); - UNLOCK_HARDWARE(intel); - exit(1); - } - - /* FIXME: use hardware contexts to avoid 'losing' hardware after - * each buffer flush. - */ - //intel->vtbl.lost_hardware(intel); -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_ioctl.h b/src/mesa/drivers/dri/i915pipe/intel_ioctl.h deleted file mode 100644 index e8d07de893e..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_ioctl.h +++ /dev/null @@ -1,40 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#ifndef INTEL_IOCTL_H -#define INTEL_IOCTL_H - -#include "intel_context.h" - -void intelWaitIrq(struct intel_context *intel, int seq); -int intelEmitIrqLocked(struct intel_context *intel); - -void intel_batch_ioctl(struct intel_context *intel, - GLuint start_offset, - GLuint used, - GLboolean ignore_cliprects, GLboolean allow_unlock); -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c deleted file mode 100644 index 1a9aa101157..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.c +++ /dev/null @@ -1,293 +0,0 @@ -/************************************************************************** - * - * 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 "intel_mipmap_tree.h" -#include "enums.h" - -#include "pipe/p_state.h" -#include "pipe/p_context.h" - - -#define DBG if(0) printf - -static GLenum -target_to_target(GLenum target) -{ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - return GL_TEXTURE_CUBE_MAP_ARB; - default: - return target; - } -} - -struct pipe_mipmap_tree * -st_miptree_create(struct pipe_context *pipe, - GLenum target, - GLenum internal_format, - GLuint first_level, - GLuint last_level, - GLuint width0, - GLuint height0, - GLuint depth0, GLuint cpp, GLuint compress_byte) -{ - GLboolean ok; - struct pipe_mipmap_tree *mt = calloc(sizeof(*mt), 1); - - DBG("%s target %s format %s level %d..%d\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(target), - _mesa_lookup_enum_by_nr(internal_format), first_level, last_level); - - mt->target = target_to_target(target); - mt->internal_format = internal_format; - mt->first_level = first_level; - mt->last_level = last_level; - mt->width0 = width0; - mt->height0 = height0; - mt->depth0 = depth0; - mt->cpp = compress_byte ? compress_byte : cpp; - mt->compressed = compress_byte ? 1 : 0; - mt->refcount = 1; - - ok = pipe->mipmap_tree_layout(pipe, mt); - if (ok) - mt->region = pipe->region_alloc(pipe, - mt->cpp, mt->pitch, mt->total_height); - - if (!mt->region) { - free(mt); - return NULL; - } - - return mt; -} - - -void -st_miptree_reference(struct pipe_mipmap_tree **dst, - struct pipe_mipmap_tree *src) -{ - src->refcount++; - *dst = src; - DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount); -} - -void -st_miptree_release(struct pipe_context *pipe, - struct pipe_mipmap_tree **mt) -{ - if (!*mt) - return; - - DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1); - if (--(*mt)->refcount <= 0) { - GLuint i; - - DBG("%s deleting %p\n", __FUNCTION__, *mt); - - pipe->region_release(pipe, &((*mt)->region)); - - for (i = 0; i < MAX_TEXTURE_LEVELS; i++) - if ((*mt)->level[i].image_offset) - free((*mt)->level[i].image_offset); - - free(*mt); - } - *mt = NULL; -} - - - - -/* Can the image be pulled into a unified mipmap tree. This mirrors - * the completeness test in a lot of ways. - * - * Not sure whether I want to pass gl_texture_image here. - */ -GLboolean -st_miptree_match_image(struct pipe_mipmap_tree *mt, - struct gl_texture_image *image, - GLuint face, GLuint level) -{ - /* Images with borders are never pulled into mipmap trees. - */ - if (image->Border) - return GL_FALSE; - - if (image->InternalFormat != mt->internal_format || - image->IsCompressed != mt->compressed) - return GL_FALSE; - - /* Test image dimensions against the base level image adjusted for - * minification. This will also catch images not present in the - * tree, changed targets, etc. - */ - if (image->Width != mt->level[level].width || - image->Height != mt->level[level].height || - image->Depth != mt->level[level].depth) - return GL_FALSE; - - return GL_TRUE; -} - - -/* Although we use the image_offset[] array to store relative offsets - * to cube faces, Mesa doesn't know anything about this and expects - * each cube face to be treated as a separate image. - * - * These functions present that view to mesa: - */ -const GLuint * -st_miptree_depth_offsets(struct pipe_mipmap_tree *mt, GLuint level) -{ - static const GLuint zero = 0; - - if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1) - return &zero; - else - return mt->level[level].image_offset; -} - - -GLuint -st_miptree_image_offset(struct pipe_mipmap_tree * mt, - GLuint face, GLuint level) -{ - if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) - return (mt->level[level].level_offset + - mt->level[level].image_offset[face] * mt->cpp); - else - return mt->level[level].level_offset; -} - - - -/** - * Map a teximage in a mipmap tree. - * \param row_stride returns row stride in bytes - * \param image_stride returns image stride in bytes (for 3D textures). - * \return address of mapping - */ -GLubyte * -st_miptree_image_map(struct pipe_context *pipe, - struct pipe_mipmap_tree * mt, - GLuint face, - GLuint level, - GLuint * row_stride, GLuint * image_offsets) -{ - GLubyte *ptr; - DBG("%s \n", __FUNCTION__); - - if (row_stride) - *row_stride = mt->pitch * mt->cpp; - - if (image_offsets) - memcpy(image_offsets, mt->level[level].image_offset, - mt->level[level].depth * sizeof(GLuint)); - - ptr = pipe->region_map(pipe, mt->region); - - return ptr + st_miptree_image_offset(mt, face, level); -} - -void -st_miptree_image_unmap(struct pipe_context *pipe, - struct pipe_mipmap_tree *mt) -{ - DBG("%s\n", __FUNCTION__); - pipe->region_unmap(pipe, mt->region); -} - - - -/* Upload data for a particular image. - */ -void -st_miptree_image_data(struct pipe_context *pipe, - struct pipe_mipmap_tree *dst, - GLuint face, - GLuint level, - void *src, - GLuint src_row_pitch, GLuint src_image_pitch) -{ - GLuint depth = dst->level[level].depth; - GLuint dst_offset = st_miptree_image_offset(dst, face, level); - const GLuint *dst_depth_offset = st_miptree_depth_offsets(dst, level); - GLuint i; - GLuint height = 0; - - DBG("%s\n", __FUNCTION__); - for (i = 0; i < depth; i++) { - height = dst->level[level].height; - if(dst->compressed) - height /= 4; - pipe->region_data(pipe, dst->region, - dst_offset + dst_depth_offset[i], /* dst_offset */ - 0, 0, /* dstx, dsty */ - src, - src_row_pitch, - 0, 0, /* source x, y */ - dst->level[level].width, height); /* width, height */ - - src += src_image_pitch * dst->cpp; - } -} - -/* Copy mipmap image between trees - */ -void -st_miptree_image_copy(struct pipe_context *pipe, - struct pipe_mipmap_tree *dst, - GLuint face, GLuint level, - struct pipe_mipmap_tree *src) -{ - GLuint width = src->level[level].width; - GLuint height = src->level[level].height; - GLuint depth = src->level[level].depth; - GLuint dst_offset = st_miptree_image_offset(dst, face, level); - GLuint src_offset = st_miptree_image_offset(src, face, level); - const GLuint *dst_depth_offset = st_miptree_depth_offsets(dst, level); - const GLuint *src_depth_offset = st_miptree_depth_offsets(src, level); - GLuint i; - - if (dst->compressed) - height /= 4; - for (i = 0; i < depth; i++) { - pipe->region_copy(pipe, - dst->region, dst_offset + dst_depth_offset[i], - 0, - 0, - src->region, src_offset + src_depth_offset[i], - 0, 0, width, height); - } - -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h b/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h deleted file mode 100644 index eafe47c0291..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_mipmap_tree.h +++ /dev/null @@ -1,105 +0,0 @@ -/************************************************************************** - * - * 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_MIPMAP_TREE_H -#define INTEL_MIPMAP_TREE_H - - -#include "main/mtypes.h" - -struct pipe_context; -struct pipe_mipmap_tree; -struct pipe_region; - - -struct pipe_mipmap_tree *st_miptree_create(struct pipe_context *pipe, - GLenum target, - GLenum internal_format, - GLuint first_level, - GLuint last_level, - GLuint width0, - GLuint height0, - GLuint depth0, - GLuint cpp, - GLuint compress_byte); - -void st_miptree_reference(struct pipe_mipmap_tree **dst, - struct pipe_mipmap_tree *src); - -void st_miptree_release(struct pipe_context *pipe, - struct pipe_mipmap_tree **mt); - -/* Check if an image fits an existing mipmap tree layout - */ -GLboolean st_miptree_match_image(struct pipe_mipmap_tree *mt, - struct gl_texture_image *image, - GLuint face, GLuint level); - -/* Return a pointer to an image within a tree. Return image stride as - * well. - */ -GLubyte *st_miptree_image_map(struct pipe_context *pipe, - struct pipe_mipmap_tree *mt, - GLuint face, - GLuint level, - GLuint * row_stride, GLuint * image_stride); - -void st_miptree_image_unmap(struct pipe_context *pipe, - struct pipe_mipmap_tree *mt); - - -/* Return the linear offset of an image relative to the start of the - * tree: - */ -GLuint st_miptree_image_offset(struct pipe_mipmap_tree *mt, - GLuint face, GLuint level); - -/* Return pointers to each 2d slice within an image. Indexed by depth - * value. - */ -const GLuint *st_miptree_depth_offsets(struct pipe_mipmap_tree *mt, - GLuint level); - - -/* Upload an image into a tree - */ -void st_miptree_image_data(struct pipe_context *pipe, - struct pipe_mipmap_tree *dst, - GLuint face, - GLuint level, - void *src, - GLuint src_row_pitch, GLuint src_image_pitch); - -/* Copy an image between two trees - */ -void st_miptree_image_copy(struct pipe_context *pipe, - struct pipe_mipmap_tree *dst, - GLuint face, GLuint level, - struct pipe_mipmap_tree *src); - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_reg.h b/src/mesa/drivers/dri/i915pipe/intel_reg.h deleted file mode 100644 index 7828ba6ad39..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_reg.h +++ /dev/null @@ -1,88 +0,0 @@ -/************************************************************************** - * - * 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 CMD_3D (0x3<<29) - - -#define _3DPRIMITIVE ((0x3<<29)|(0x1f<<24)) -#define PRIM_INDIRECT (1<<23) -#define PRIM_INLINE (0<<23) -#define PRIM_INDIRECT_SEQUENTIAL (0<<17) -#define PRIM_INDIRECT_ELTS (1<<17) - -#define PRIM3D_TRILIST (0x0<<18) -#define PRIM3D_TRISTRIP (0x1<<18) -#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) -#define PRIM3D_TRIFAN (0x3<<18) -#define PRIM3D_POLY (0x4<<18) -#define PRIM3D_LINELIST (0x5<<18) -#define PRIM3D_LINESTRIP (0x6<<18) -#define PRIM3D_RECTLIST (0x7<<18) -#define PRIM3D_POINTLIST (0x8<<18) -#define PRIM3D_DIB (0x9<<18) -#define PRIM3D_MASK (0x1f<<18) - -#define I915PACKCOLOR4444(r,g,b,a) \ - ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) - -#define I915PACKCOLOR1555(r,g,b,a) \ - ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ - ((a) ? 0x8000 : 0)) - -#define I915PACKCOLOR565(r,g,b) \ - ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) - -#define I915PACKCOLOR8888(r,g,b,a) \ - ((a<<24) | (r<<16) | (g<<8) | b) - - - - -#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) - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_screen.c b/src/mesa/drivers/dri/i915pipe/intel_screen.c deleted file mode 100644 index 81ab435f42e..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_screen.c +++ /dev/null @@ -1,597 +0,0 @@ -/************************************************************************** - * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - **************************************************************************/ - -#include "glheader.h" -#include "context.h" -#include "framebuffer.h" -#include "matrix.h" -#include "renderbuffer.h" -#include "simple_list.h" -#include "utils.h" -#include "vblank.h" -#include "xmlpool.h" - -#include "intel_screen.h" -#include "intel_batchbuffer.h" -#include "intel_buffers.h" -/*#include "intel_tex.h"*/ -#include "intel_ioctl.h" -#include "intel_fbo.h" - -#include "i830_dri.h" -#include "dri_bufpool.h" - -#include "pipe/p_context.h" - - - -PUBLIC const char __driConfigOptions[] = - DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE - DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) - DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) - DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY - DRI_CONF_FORCE_S3TC_ENABLE(false) - DRI_CONF_ALLOW_LARGE_TEXTURES(1) - DRI_CONF_SECTION_END DRI_CONF_END; - const GLuint __driNConfigOptions = 4; - -#ifdef USE_NEW_INTERFACE - static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; -#endif /*USE_NEW_INTERFACE */ - - extern const struct dri_extension card_extensions[]; - - - - - -static void -intelPrintDRIInfo(intelScreenPrivate * intelScreen, - __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv) -{ - fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", - intelScreen->front.size, intelScreen->front.offset, - intelScreen->front.pitch); - fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); -} - - -static void -intelPrintSAREA(const drmI830Sarea * sarea) -{ - fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, - sarea->height); - fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); - fprintf(stderr, - "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->front_offset, sarea->front_size, - (unsigned) sarea->front_handle); - fprintf(stderr, - "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->back_offset, sarea->back_size, - (unsigned) sarea->back_handle); - fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->depth_offset, sarea->depth_size, - (unsigned) sarea->depth_handle); - fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", - sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); - fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); - fprintf(stderr, - "SAREA: rotated offset: 0x%08x size: 0x%x\n", - sarea->rotated_offset, sarea->rotated_size); - fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); -} - - - -/** - * 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) -{ - intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; - - 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) { - _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); - 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); - } -} - - - -GLboolean -intelCreatePools(intelScreenPrivate *intelScreen) -{ - unsigned batchPoolSize = 1024*1024; - __DRIscreenPrivate * sPriv = intelScreen->driScrnPriv; - - if (intelScreen->havePools) - return GL_TRUE; - - batchPoolSize /= BATCH_SZ; - intelScreen->regionPool = driDRMPoolInit(sPriv->fd); - - if (!intelScreen->regionPool) - return GL_FALSE; - - intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd); - - if (!intelScreen->staticPool) - return GL_FALSE; - - intelScreen->texPool = intelScreen->regionPool; - - 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 GLboolean -intelInitDriver(__DRIscreenPrivate * sPriv) -{ - intelScreenPrivate *intelScreen; - I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; - - PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = - (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface-> - getProcAddress("glxEnableExtension")); - void *const psc = sPriv->psc->screenConfigs; - - if (sPriv->devPrivSize != sizeof(I830DRIRec)) { - fprintf(stderr, - "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); - return GL_FALSE; - } - - /* Allocate the private area */ - intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); - if (!intelScreen) - return GL_FALSE; - - /* parse information in __driConfigOptions */ - driParseOptionInfo(&intelScreen->optionCache, - __driConfigOptions, __driNConfigOptions); - - intelScreen->driScrnPriv = sPriv; - 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"); - } - - return GL_TRUE; -} - - -static void -intelDestroyScreen(__DRIscreenPrivate * sPriv) -{ - intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; - -// intelUnmapScreenRegions(intelScreen); - - if (intelScreen->havePools) { - driPoolTakeDown(intelScreen->regionPool); - 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 GLboolean -intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, - __DRIdrawablePrivate * driDrawPriv, - const __GLcontextModes * mesaVis, GLboolean isPixmap) -{ - if (isPixmap) { - return GL_FALSE; /* not implemented */ - } - else { - GLboolean swStencil = (mesaVis->stencilBits > 0 && - mesaVis->depthBits != 24); - GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); - - struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); - - if (!intel_fb) - return GL_FALSE; - - _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); - - { - /* fake frontbuffer */ - /* XXX allocation should only happen in the unusual case - it's actually needed */ - intel_fb->color_rb[0] - = intel_new_renderbuffer_fb(rgbFormat); - _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, - &intel_fb->color_rb[0]->Base); - } - - if (mesaVis->doubleBufferMode) { - intel_fb->color_rb[1] - = intel_new_renderbuffer_fb(rgbFormat); - _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, - &intel_fb->color_rb[1]->Base); - } - - if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { - /* combined depth/stencil buffer */ - struct intel_renderbuffer *depthStencilRb - = intel_new_renderbuffer_fb(GL_DEPTH24_STENCIL8_EXT); - /* note: bind RB to two attachment points */ - _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, - &depthStencilRb->Base); - _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, - &depthStencilRb->Base); - } - else if (mesaVis->depthBits == 16) { - /* just 16-bit depth buffer, no hw stencil */ - struct intel_renderbuffer *depthRb - = intel_new_renderbuffer_fb(GL_DEPTH_COMPONENT16); - _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); - } - - - /* now add any/all software-based renderbuffers we may need */ - _mesa_add_soft_renderbuffers(&intel_fb->Base, - GL_FALSE, /* never sw color */ - GL_FALSE, /* never sw depth */ - swStencil, mesaVis->accumRedBits > 0, - GL_FALSE, /* never sw alpha */ - GL_FALSE /* never sw aux */ ); - driDrawPriv->driverPrivate = (void *) intel_fb; - - return GL_TRUE; - } -} - -static void -intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) -{ - _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); -} - - -/** - * Get information about previous buffer swaps. - */ -static int -intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) -{ - struct intel_framebuffer *intel_fb; - - if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) - || (sInfo == NULL)) { - return -1; - } - - intel_fb = dPriv->driverPrivate; - sInfo->swap_count = intel_fb->swap_count; - sInfo->swap_ust = intel_fb->swap_ust; - sInfo->swap_missed_count = intel_fb->swap_missed_count; - - sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) - ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) - : 0.0; - - return 0; -} - - -static void -intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, - unsigned long long offset, GLint depth, GLuint 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->mt) - st_miptree_release(intel->pipe, &stObj->mt); - - 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, GLboolean have_back_buffer) -{ - __GLcontextModes *modes; - __GLcontextModes *m; - unsigned num_modes; - unsigned depth_buffer_factor; - unsigned back_buffer_factor; - GLenum fb_format; - GLenum fb_type; - - /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't - * support pageflipping at all. - */ - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML - }; - - 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; -} - -struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) -{ - /* - * This should probably change to have the screen allocate a dummy - * context at screen creation. For now just use the current context. - */ - - GET_CURRENT_CONTEXT(ctx); - if (ctx == NULL) { -/* _mesa_problem(NULL, "No current context in intelScreenContext\n"); - return NULL; */ - /* need a context for the first time makecurrent is called (for hw lock - when allocating priv buffers) */ - if (intelScreen->dummyctxptr == NULL) { - _mesa_problem(NULL, "No current context in intelScreenContext\n"); - return NULL; - } - return intelScreen->dummyctxptr; - } - return intel_context(ctx); - -} - diff --git a/src/mesa/drivers/dri/i915pipe/intel_screen.h b/src/mesa/drivers/dri/i915pipe/intel_screen.h deleted file mode 100644 index 549587a6f2b..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_screen.h +++ /dev/null @@ -1,111 +0,0 @@ -/************************************************************************** - * - * 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" - - -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; - - __DRIscreenPrivate *driScrnPriv; - drmI830Sarea *sarea; - - - /** - * Configuration cache with default values for all contexts - */ - driOptionCache optionCache; - struct _DriBufferPool *batchPool; - struct _DriBufferPool *texPool; - struct _DriBufferPool *regionPool; - struct _DriBufferPool *staticPool; - GLboolean havePools; - - struct intel_context *dummyctxptr; -}; - -typedef struct intel_screen intelScreenPrivate; - -extern void -intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea); - - -extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv); - -extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv); - -extern GLboolean -intelMakeCurrent(__DRIcontextPrivate * driContextPriv, - __DRIdrawablePrivate * driDrawPriv, - __DRIdrawablePrivate * driReadPriv); - -extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); - -extern void -intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h); - -extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags, - unsigned long bufSize, - unsigned numBufs, - unsigned checkDelayed); - -extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen); - -extern GLboolean -intelCreatePools(intelScreenPrivate *intelScreen); - -extern GLboolean -intelCreateContext(const __GLcontextModes * mesaVis, - __DRIcontextPrivate * driContextPriv, - void *sharedContextPrivate); - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_softpipe.c b/src/mesa/drivers/dri/i915pipe/intel_softpipe.c deleted file mode 100644 index ef477443586..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_softpipe.c +++ /dev/null @@ -1,184 +0,0 @@ -/************************************************************************** - * - * 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 - */ - -#include -#include -#include "dri_bufpool.h" -#include "dri_bufmgr.h" - -/* #include "errno.h" */ -/* #include "string.h" */ -/* #include "imports.h" */ - -#include "intel_context.h" - -#include "pipe/softpipe/sp_winsys.h" - - -struct intel_softpipe_winsys { - struct softpipe_winsys sws; - struct intel_context *intel; -}; - - - -/* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque - * buffer pointer... - */ -static inline struct _DriBufferObject * -dri_bo( struct pipe_buffer_handle *bo ) -{ - return (struct _DriBufferObject *)bo; -} - -static inline struct pipe_buffer_handle * -pipe_bo( struct _DriBufferObject *bo ) -{ - return (struct pipe_buffer_handle *)bo; -} - -/* Turn a softpipe winsys into an intel/softpipe winsys: - */ -static inline struct intel_softpipe_winsys * -intel_softpipe_winsys( struct softpipe_winsys *sws ) -{ - return (struct intel_softpipe_winsys *)sws; -} - - -/* Most callbacks map direcly onto dri_bufmgr operations: - */ -static void *intel_buffer_map(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf ) -{ - return driBOMap( dri_bo(buf), - DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0 ); -} - -static void intel_buffer_unmap(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf) -{ - driBOUnmap( dri_bo(buf) ); -} - - -static struct pipe_buffer_handle * -intel_buffer_reference(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf) -{ - return pipe_bo( driBOReference( dri_bo(buf) ) ); -} - -static void intel_buffer_unreference(struct softpipe_winsys *sws, - struct pipe_buffer_handle **buf) -{ - if (*buf) { - driBOUnReference( dri_bo(*buf) ); - *buf = NULL; - } -} - -/* Grabs the hardware lock! - */ -static void intel_buffer_data(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf, - unsigned size, const void *data ) -{ - struct intel_context *intel = intel_softpipe_winsys(sws)->intel; - - LOCK_HARDWARE( intel ); - driBOData( dri_bo(buf), size, data, 0 ); - UNLOCK_HARDWARE( intel ); -} - -static void intel_buffer_subdata(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf, - unsigned long offset, - unsigned long size, - const void *data) -{ - driBOSubData( dri_bo(buf), offset, size, data ); -} - -static void intel_buffer_get_subdata(struct softpipe_winsys *sws, - struct pipe_buffer_handle *buf, - unsigned long offset, - unsigned long size, - void *data) -{ - driBOGetSubData( dri_bo(buf), offset, size, data ); -} - -/* Softpipe has no concept of pools. We choose the tex/region pool - * for all buffers. - */ -static struct pipe_buffer_handle * -intel_create_buffer(struct softpipe_winsys *sws, - unsigned alignment) -{ - struct intel_context *intel = intel_softpipe_winsys(sws)->intel; - struct _DriBufferObject *buffer; - - LOCK_HARDWARE( intel ); - driGenBuffers( intel->intelScreen->regionPool, - "softpipe buffer", 1, &buffer, alignment, 0, 0 ); - UNLOCK_HARDWARE( intel ); - - return pipe_bo(buffer); -} - - -struct pipe_context * -intel_create_softpipe( struct intel_context *intel ) -{ - 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. - * - * Softpipe 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. - */ - isws->sws.create_buffer = intel_create_buffer; - isws->sws.buffer_map = intel_buffer_map; - isws->sws.buffer_unmap = intel_buffer_unmap; - isws->sws.buffer_reference = intel_buffer_reference; - isws->sws.buffer_unreference = intel_buffer_unreference; - isws->sws.buffer_data = intel_buffer_data; - isws->sws.buffer_subdata = intel_buffer_subdata; - isws->sws.buffer_get_subdata = intel_buffer_get_subdata; - isws->intel = intel; - - /* Create the softpipe context: - */ - return softpipe_create( &isws->sws ); -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_surface.c b/src/mesa/drivers/dri/i915pipe/intel_surface.c deleted file mode 100644 index 3fa40271c83..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_surface.c +++ /dev/null @@ -1,196 +0,0 @@ -#include "glheader.h" -#include "context.h" -#include "framebuffer.h" -#include "renderbuffer.h" -#include "utils.h" -#include "main/macros.h" - - -#include "intel_screen.h" - -#include "intel_context.h" -#include "intel_buffers.h" -#include "intel_fbo.h" - -#include "pipe/p_state.h" -#include "pipe/p_context.h" -#include "pipe/p_defines.h" -#include "pipe/softpipe/sp_surface.h" - - -/* - * XXX a lof of this is a temporary kludge - */ - -/** - * Note: the arithmetic/addressing in these functions is a little - * tricky since we need to invert the Y axis. - */ - - -static void -read_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y, - GLfloat (*rrrr)[QUAD_SIZE]) -{ - const GLint bytesPerRow = sps->surface.region->pitch * sps->surface.region->cpp; - const GLint invY = sps->surface.height - y - 1; - const GLubyte *src = sps->surface.region->map + invY * bytesPerRow + x * sps->surface.region->cpp; - GLfloat *dst = (GLfloat *) rrrr; - GLubyte temp[16]; - GLuint j; - - assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8); - - memcpy(temp + 8, src, 8); - memcpy(temp + 0, src + bytesPerRow, 8); - - for (j = 0; j < 4; j++) { - dst[0 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 2]); /*R*/ - dst[1 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 1]); /*G*/ - dst[2 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 0]); /*B*/ - dst[3 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 3]); /*A*/ - } -} - - -static void -write_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y, - GLfloat (*rrrr)[QUAD_SIZE]) -{ - const GLfloat *src = (const GLfloat *) rrrr; - const GLint bytesPerRow = sps->surface.region->pitch * sps->surface.region->cpp; - const GLint invY = sps->surface.height - y - 1; - GLubyte *dst = sps->surface.region->map + invY * bytesPerRow + x * sps->surface.region->cpp; - GLubyte temp[16]; - GLuint j; - - assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8); - - for (j = 0; j < 4; j++) { - UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 2], src[0 * 4 + j]); /*R*/ - UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 1], src[1 * 4 + j]); /*G*/ - UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 0], src[2 * 4 + j]); /*B*/ - UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 3], src[3 * 4 + j]); /*A*/ - } - - memcpy(dst, temp + 8, 8); - memcpy(dst + bytesPerRow, temp + 0, 8); -} - - - -static void -read_quad_z24(struct softpipe_surface *sps, - GLint x, GLint y, GLuint zzzz[QUAD_SIZE]) -{ - static const GLuint mask = 0xffffff; - const GLint invY = sps->surface.height - y - 1; - const GLuint *src - = (GLuint *) (sps->surface.region->map - + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); - - assert(sps->surface.format == PIPE_FORMAT_S8_Z24); - - /* extract lower three bytes */ - zzzz[0] = src[0] & mask; - zzzz[1] = src[1] & mask; - zzzz[2] = src[-sps->surface.region->pitch] & mask; - zzzz[3] = src[-sps->surface.region->pitch + 1] & mask; -} - -static void -write_quad_z24(struct softpipe_surface *sps, - GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]) -{ - static const GLuint mask = 0xff000000; - const GLint invY = sps->surface.height - y - 1; - GLuint *dst - = (GLuint *) (sps->surface.region->map - + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); - - assert(sps->surface.format == PIPE_FORMAT_S8_Z24); - - /* write lower three bytes */ - dst[0] = (dst[0] & mask) | zzzz[0]; - dst[1] = (dst[1] & mask) | zzzz[1]; - dst -= sps->surface.region->pitch; - dst[0] = (dst[0] & mask) | zzzz[2]; - dst[1] = (dst[1] & mask) | zzzz[3]; -} - - -static void -read_quad_stencil(struct softpipe_surface *sps, - GLint x, GLint y, GLubyte ssss[QUAD_SIZE]) -{ - const GLint invY = sps->surface.height - y - 1; - const GLuint *src = (const GLuint *) (sps->surface.region->map - + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); - - assert(sps->surface.format == PIPE_FORMAT_S8_Z24); - - /* extract high byte */ - ssss[0] = src[0] >> 24; - ssss[1] = src[1] >> 24; - src -= sps->surface.region->pitch; - ssss[2] = src[0] >> 24; - ssss[3] = src[1] >> 24; -} - -static void -write_quad_stencil(struct softpipe_surface *sps, - GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]) -{ - static const GLuint mask = 0x00ffffff; - const GLint invY = sps->surface.height - y - 1; - GLuint *dst = (GLuint *) (sps->surface.region->map - + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); - - assert(sps->surface.format == PIPE_FORMAT_S8_Z24); - - /* write high byte */ - dst[0] = (dst[0] & mask) | (ssss[0] << 24); - dst[1] = (dst[1] & mask) | (ssss[1] << 24); - dst -= sps->surface.region->pitch; - dst[0] = (dst[0] & mask) | (ssss[2] << 24); - dst[1] = (dst[1] & mask) | (ssss[3] << 24); -} - - -struct pipe_surface * -intel_new_surface(GLuint intFormat) -{ - struct softpipe_surface *sps = CALLOC_STRUCT(softpipe_surface); - if (!sps) - return NULL; - - sps->surface.width = 0; /* set in intel_alloc_renderbuffer_storage() */ - sps->surface.height = 0; - - if (intFormat == GL_RGBA8) { - sps->surface.format = PIPE_FORMAT_U_A8_R8_G8_B8; - sps->read_quad_f_swz = read_quad_f_swz; - sps->write_quad_f_swz = write_quad_f_swz; - } - else if (intFormat == GL_RGB5) { - sps->surface.format = PIPE_FORMAT_U_R5_G6_B5; - - } - else if (intFormat == GL_DEPTH_COMPONENT16) { - sps->surface.format = PIPE_FORMAT_U_Z16; - - } - else if (intFormat == GL_DEPTH24_STENCIL8_EXT) { - sps->surface.format = PIPE_FORMAT_S8_Z24; - sps->read_quad_z = read_quad_z24; - sps->write_quad_z = write_quad_z24; - sps->read_quad_stencil = read_quad_stencil; - sps->write_quad_stencil = write_quad_stencil; - } - else { - /* TBD / unknown */ - - } - - return &sps->surface; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex.c b/src/mesa/drivers/dri/i915pipe/intel_tex.c deleted file mode 100644 index 5270094cc51..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex.c +++ /dev/null @@ -1,184 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - -#include "main/texobj.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_mipmap_tree.h" -#include "intel_tex.h" - -#define FILE_DEBUG_FLAG DEBUG_TEXTURE - -static GLboolean -intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj) -{ -#if 0 - struct intel_context *intel = intel_context(ctx); - struct st_texture_object *stObj = st_texture_object(texObj); - - return - stObj->mt && - stObj->mt->region && - intel_is_region_resident(intel, stObj->mt->region); -#endif - return 1; -} - - - -static struct gl_texture_image * -intelNewTextureImage(GLcontext * ctx) -{ - DBG("%s\n", __FUNCTION__); - (void) ctx; - return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image); -} - - -static struct gl_texture_object * -intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target) -{ - struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object); - - DBG("%s\n", __FUNCTION__); - _mesa_initialize_texture_object(&obj->base, name, target); - - return &obj->base; -} - -static void -intelDeleteTextureObject(GLcontext *ctx, - struct gl_texture_object *texObj) -{ - struct pipe_context *pipe = ctx->st->pipe; - struct st_texture_object *stObj = st_texture_object(texObj); - - if (stObj->mt) - st_miptree_release(pipe, &stObj->mt); - - _mesa_delete_texture_object(ctx, texObj); -} - - -static void -intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) -{ - struct pipe_context *pipe = ctx->st->pipe; - struct st_texture_image *stImage = st_texture_image(texImage); - - DBG("%s\n", __FUNCTION__); - - if (stImage->mt) { - st_miptree_release(pipe, &stImage->mt); - } - - if (texImage->Data) { - free(texImage->Data); - texImage->Data = NULL; - } -} - - - - -/* ================================================================ - * From linux kernel i386 header files, copes with odd sizes better - * than COPY_DWORDS would: - * XXX Put this in src/mesa/main/imports.h ??? - */ -#if defined(i386) || defined(__i386__) -static INLINE void * -__memcpy(void *to, const void *from, size_t n) -{ - int d0, d1, d2; - __asm__ __volatile__("rep ; movsl\n\t" - "testb $2,%b4\n\t" - "je 1f\n\t" - "movsw\n" - "1:\ttestb $1,%b4\n\t" - "je 2f\n\t" - "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2) - :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from) - :"memory"); - return (to); -} -#else -#define __memcpy(a,b,c) memcpy(a,b,c) -#endif - - -/* The system memcpy (at least on ubuntu 5.10) has problems copying - * to agp (writecombined) memory from a source which isn't 64-byte - * aligned - there is a 4x performance falloff. - * - * The x86 __memcpy is immune to this but is slightly slower - * (10%-ish) than the system memcpy. - * - * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but - * isn't much faster than x86_memcpy for agp copies. - * - * TODO: switch dynamically. - */ -static void * -do_memcpy(void *dest, const void *src, size_t n) -{ - if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) { - return __memcpy(dest, src, n); - } - else - return memcpy(dest, src, n); -} - - -void -intelInitTextureFuncs(struct dd_function_table *functions) -{ - functions->ChooseTextureFormat = intelChooseTextureFormat; - functions->TexImage1D = intelTexImage1D; - functions->TexImage2D = intelTexImage2D; - functions->TexImage3D = intelTexImage3D; - functions->TexSubImage1D = intelTexSubImage1D; - functions->TexSubImage2D = intelTexSubImage2D; - functions->TexSubImage3D = intelTexSubImage3D; - functions->CopyTexImage1D = intelCopyTexImage1D; - functions->CopyTexImage2D = intelCopyTexImage2D; - functions->CopyTexSubImage1D = intelCopyTexSubImage1D; - functions->CopyTexSubImage2D = intelCopyTexSubImage2D; - functions->GetTexImage = intelGetTexImage; - - /* compressed texture functions */ - functions->CompressedTexImage2D = intelCompressedTexImage2D; - functions->GetCompressedTexImage = intelGetCompressedTexImage; - - functions->NewTextureObject = intelNewTextureObject; - functions->NewTextureImage = intelNewTextureImage; - functions->DeleteTexture = intelDeleteTextureObject; - functions->FreeTexImageData = intelFreeTextureImageData; - functions->UpdateTexturePalette = 0; - functions->IsTextureResident = intelIsTextureResident; - - functions->TextureMemCpy = do_memcpy; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex.h b/src/mesa/drivers/dri/i915pipe/intel_tex.h deleted file mode 100644 index 7a1cc919749..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex.h +++ /dev/null @@ -1,212 +0,0 @@ -/************************************************************************** - * - * 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 INTELTEX_INC -#define INTELTEX_INC - -#include "mtypes.h" -#include "intel_context.h" -#include "texmem.h" - -struct st_texture_object -{ - struct gl_texture_object base; /* The "parent" object */ - - /* The mipmap tree must include at least these levels once - * validated: - */ - GLuint firstLevel; - GLuint lastLevel; - - /* Offset for firstLevel image: - */ - GLuint textureOffset; - - /* On validation any active images held in main memory or in other - * regions will be copied to this region and the old storage freed. - */ - struct pipe_mipmap_tree *mt; - - GLboolean imageOverride; - GLint depthOverride; - GLuint pitchOverride; -}; - - - -struct st_texture_image -{ - struct gl_texture_image base; - - /* These aren't stored in gl_texture_image - */ - GLuint level; - GLuint face; - - /* If stImage->mt != NULL, image data is stored here. - * Else if stImage->base.Data != NULL, image is stored there. - * Else there is no image data. - */ - struct pipe_mipmap_tree *mt; -}; - - -void intelInitTextureFuncs(struct dd_function_table *functions); - -const struct gl_texture_format *intelChooseTextureFormat(GLcontext * ctx, - GLint internalFormat, - GLenum format, - GLenum type); - - -void intelTexImage3D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelTexSubImage3D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelTexImage2D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelTexSubImage2D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelTexImage1D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelTexSubImage1D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLint border); - -void intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border); - -void intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width); - -void intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height); - -void intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage); - -void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ); - -void intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, - GLvoid *pixels, - const struct gl_texture_object *texObj, - const struct gl_texture_image *texImage); - -void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, - unsigned long long offset, GLint depth, GLuint pitch); - -GLuint intel_finalize_mipmap_tree(GLcontext *ctx, - struct pipe_context *pipe, GLuint unit, - GLboolean *needFlush); - - -#if 0 -void intel_tex_map_images(struct pipe_context *pipe, - struct st_texture_object *stObj); - -void intel_tex_unmap_images(struct pipe_context *pipe, - struct st_texture_object *stObj); -#endif - -int intel_compressed_num_bytes(GLuint mesaFormat); - - -static INLINE struct st_texture_object * -st_texture_object(struct gl_texture_object *obj) -{ - return (struct st_texture_object *) obj; -} - -static INLINE struct st_texture_image * -st_texture_image(struct gl_texture_image *img) -{ - return (struct st_texture_image *) img; -} - - -#endif diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_copy.c b/src/mesa/drivers/dri/i915pipe/intel_tex_copy.c deleted file mode 100644 index d2cf6f4669c..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_copy.c +++ /dev/null @@ -1,315 +0,0 @@ -/************************************************************************** - * - * 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/mtypes.h" -#include "main/enums.h" -#include "main/image.h" -#include "main/teximage.h" - -#include "state_tracker/st_mipmap_tree.h" - -#if 0 -#include "intel_screen.h" -#include "intel_context.h" -#include "intel_batchbuffer.h" -#include "intel_buffers.h" -#include "intel_fbo.h" -#include "intel_blit.h" -#endif -#include "intel_tex.h" - - -#define FILE_DEBUG_FLAG DEBUG_TEXTURE - -/** - * Get the pipe_region which is the source for any glCopyTex[Sub]Image call. - * - * Do the best we can using the blitter. A future project is to use - * the texture engine and fragment programs for these copies. - */ -static const struct pipe_region * -get_teximage_source(struct intel_context *intel, GLenum internalFormat) -{ -#if 00 - struct intel_renderbuffer *irb; - - DBG("%s %s\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(internalFormat)); - - switch (internalFormat) { - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16_ARB: - irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); - if (irb && irb->region && irb->region->cpp == 2) - return irb->region; - return NULL; - case GL_DEPTH24_STENCIL8_EXT: - case GL_DEPTH_STENCIL_EXT: - irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); - if (irb && irb->region && irb->region->cpp == 4) - return irb->region; - return NULL; - case GL_RGBA: - case GL_RGBA8: - return intel_readbuf_region(intel); - case GL_RGB: - if (intel->intelScreen->front.cpp == 2) - return intel_readbuf_region(intel); - return NULL; - default: - return NULL; - } -#else - return NULL; -#endif -} - - -static GLboolean -do_copy_texsubimage(GLcontext *ctx, - struct st_texture_image *intelImage, - GLenum internalFormat, - GLint dstx, GLint dsty, - GLint x, GLint y, GLsizei width, GLsizei height) -{ - struct intel_context *intel = intel_context(ctx); - const struct pipe_region *src = - get_teximage_source(intel, internalFormat); - - if (!intelImage->mt || !src) { - DBG("%s fail %p %p\n", __FUNCTION__, intelImage->mt, src); - return GL_FALSE; - } - -#if 00 /* XXX FIX flush/locking */ - intelFlush(ctx); - /* XXX still need the lock ? */ - LOCK_HARDWARE(intel); -#endif - - { - GLuint image_offset = st_miptree_image_offset(intelImage->mt, - intelImage->face, - intelImage->level); - const GLint orig_x = x; - const GLint orig_y = y; - const struct gl_framebuffer *fb = ctx->DrawBuffer; - - if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, - &x, &y, &width, &height)) { - /* Update dst for clipped src. Need to also clip the source rect. - */ - dstx += x - orig_x; - dsty += y - orig_y; - - if (!(ctx->ReadBuffer->Name == 0)) { - /* XXX this looks bogus ? */ - /* FBO: invert Y */ - y = ctx->ReadBuffer->Height - y - 1; - } - - /* A bit of fiddling to get the blitter to work with -ve - * pitches. But we get a nice inverted blit this way, so it's - * worth it: - */ -#if 0 - intelEmitCopyBlit(intel, - intelImage->mt->cpp, - -src->pitch, - src->buffer, - src->height * src->pitch * src->cpp, - intelImage->mt->pitch, - intelImage->mt->region->buffer, - image_offset, - x, y + height, dstx, dsty, width, height, - GL_COPY); /* ? */ - intel_batchbuffer_flush(intel->batch); -#else - /* XXX use pipe->region_copy() ??? */ - (void) image_offset; -#endif - } - } - -#if 0 - UNLOCK_HARDWARE(intel); -#endif - -#if 0 - /* GL_SGIS_generate_mipmap -- this can be accelerated now. - * XXX Add a ctx->Driver.GenerateMipmaps() function? - */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - intel_generate_mipmap(ctx, target, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } -#endif - - return GL_TRUE; -} - - - - - -void -intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLint border) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - - if (border) - goto fail; - - /* Setup or redefine the texture object, mipmap tree and texture - * image. Don't populate yet. - */ - ctx->Driver.TexImage1D(ctx, target, level, internalFormat, - width, border, - GL_RGBA, CHAN_TYPE, NULL, - &ctx->DefaultPacking, texObj, texImage); - - if (!do_copy_texsubimage(ctx, - st_texture_image(texImage), - internalFormat, 0, 0, x, y, width, 1)) - goto fail; - - return; - - fail: -#if 0 - _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y, - width, border); -#endif - ; -} - -void -intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, - GLenum internalFormat, - GLint x, GLint y, GLsizei width, GLsizei height, - GLint border) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - - if (border) - goto fail; - - /* Setup or redefine the texture object, mipmap tree and texture - * image. Don't populate yet. - */ - ctx->Driver.TexImage2D(ctx, target, level, internalFormat, - width, height, border, - GL_RGBA, CHAN_TYPE, NULL, - &ctx->DefaultPacking, texObj, texImage); - - - if (!do_copy_texsubimage(ctx, - st_texture_image(texImage), - internalFormat, 0, 0, x, y, width, height)) - goto fail; - - return; - - fail: -#if 0 - _swrast_copy_teximage2d(ctx, target, level, internalFormat, x, y, - width, height, border); -#endif - assert(0); -} - - -void -intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint x, GLint y, GLsizei width) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - GLenum internalFormat = texImage->InternalFormat; - - /* XXX need to check as in above function? */ - - /* Need to check texture is compatible with source format. - */ - - if (!do_copy_texsubimage(ctx, - st_texture_image(texImage), - internalFormat, xoffset, 0, x, y, width, 1)) { -#if 0 - _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width); -#endif - assert(0); - } -} - - - -void -intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, - GLint xoffset, GLint yoffset, - GLint x, GLint y, GLsizei width, GLsizei height) -{ - struct gl_texture_unit *texUnit = - &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; - struct gl_texture_object *texObj = - _mesa_select_tex_object(ctx, texUnit, target); - struct gl_texture_image *texImage = - _mesa_select_tex_image(ctx, texObj, target, level); - GLenum internalFormat = texImage->InternalFormat; - - - /* Need to check texture is compatible with source format. - */ - - if (!do_copy_texsubimage(ctx, - st_texture_image(texImage), - internalFormat, - xoffset, yoffset, x, y, width, height)) { -#if 0 - _swrast_copy_texsubimage2d(ctx, target, level, - xoffset, yoffset, x, y, width, height); -#endif - assert(0); - } -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_format.c b/src/mesa/drivers/dri/i915pipe/intel_tex_format.c deleted file mode 100644 index a11718bb075..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_format.c +++ /dev/null @@ -1,172 +0,0 @@ -#include "intel_context.h" -#include "intel_tex.h" -#include "texformat.h" -#include "enums.h" - -/* It works out that this function is fine for all the supported - * hardware. However, there is still a need to map the formats onto - * hardware descriptors. - */ -/* Note that the i915 can actually support many more formats than - * these if we take the step of simply swizzling the colors - * immediately after sampling... - */ -const struct gl_texture_format * -intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat, - GLenum format, GLenum type) -{ - struct intel_context *intel = intel_context(ctx); - const GLboolean do32bpt = (intel->intelScreen->front.cpp == 4); - - switch (internalFormat) { - case 4: - case GL_RGBA: - case GL_COMPRESSED_RGBA: - if (format == GL_BGRA) { - if (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) { - return &_mesa_texformat_argb8888; - } - else if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { - return &_mesa_texformat_argb4444; - } - else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { - return &_mesa_texformat_argb1555; - } - } - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; - - case 3: - case GL_RGB: - case GL_COMPRESSED_RGB: - if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) { - return &_mesa_texformat_rgb565; - } - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; - - case GL_RGBA8: - case GL_RGB10_A2: - case GL_RGBA12: - case GL_RGBA16: - return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; - - case GL_RGBA4: - case GL_RGBA2: - return &_mesa_texformat_argb4444; - - case GL_RGB5_A1: - return &_mesa_texformat_argb1555; - - case GL_RGB8: - case GL_RGB10: - case GL_RGB12: - case GL_RGB16: - return &_mesa_texformat_argb8888; - - case GL_RGB5: - case GL_RGB4: - case GL_R3_G3_B2: - return &_mesa_texformat_rgb565; - - case GL_ALPHA: - case GL_ALPHA4: - case GL_ALPHA8: - case GL_ALPHA12: - case GL_ALPHA16: - case GL_COMPRESSED_ALPHA: - return &_mesa_texformat_a8; - - case 1: - case GL_LUMINANCE: - case GL_LUMINANCE4: - case GL_LUMINANCE8: - case GL_LUMINANCE12: - case GL_LUMINANCE16: - case GL_COMPRESSED_LUMINANCE: - return &_mesa_texformat_l8; - - case 2: - case GL_LUMINANCE_ALPHA: - case GL_LUMINANCE4_ALPHA4: - case GL_LUMINANCE6_ALPHA2: - case GL_LUMINANCE8_ALPHA8: - case GL_LUMINANCE12_ALPHA4: - case GL_LUMINANCE12_ALPHA12: - case GL_LUMINANCE16_ALPHA16: - case GL_COMPRESSED_LUMINANCE_ALPHA: - return &_mesa_texformat_al88; - - case GL_INTENSITY: - case GL_INTENSITY4: - case GL_INTENSITY8: - case GL_INTENSITY12: - case GL_INTENSITY16: - case GL_COMPRESSED_INTENSITY: - return &_mesa_texformat_i8; - - case GL_YCBCR_MESA: - if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE) - return &_mesa_texformat_ycbcr; - else - return &_mesa_texformat_ycbcr_rev; - - case GL_COMPRESSED_RGB_FXT1_3DFX: - return &_mesa_texformat_rgb_fxt1; - case GL_COMPRESSED_RGBA_FXT1_3DFX: - return &_mesa_texformat_rgba_fxt1; - - case GL_RGB_S3TC: - case GL_RGB4_S3TC: - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - return &_mesa_texformat_rgb_dxt1; - - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return &_mesa_texformat_rgba_dxt1; - - case GL_RGBA_S3TC: - case GL_RGBA4_S3TC: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - return &_mesa_texformat_rgba_dxt3; - - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: - return &_mesa_texformat_rgba_dxt5; - - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT24: - case GL_DEPTH_COMPONENT32: - return &_mesa_texformat_z16; - - case GL_DEPTH_STENCIL_EXT: - case GL_DEPTH24_STENCIL8_EXT: - return &_mesa_texformat_z24_s8; - - default: - fprintf(stderr, "unexpected texture format %s in %s\n", - _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__); - return NULL; - } - - return NULL; /* never get here */ -} - -int intel_compressed_num_bytes(GLuint mesaFormat) -{ - int bytes = 0; - switch(mesaFormat) { - - case MESA_FORMAT_RGB_FXT1: - case MESA_FORMAT_RGBA_FXT1: - case MESA_FORMAT_RGB_DXT1: - case MESA_FORMAT_RGBA_DXT1: - bytes = 2; - break; - - case MESA_FORMAT_RGBA_DXT3: - case MESA_FORMAT_RGBA_DXT5: - bytes = 4; - default: - break; - } - - return bytes; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_image.c b/src/mesa/drivers/dri/i915pipe/intel_tex_image.c deleted file mode 100644 index 93a59b68960..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_image.c +++ /dev/null @@ -1,695 +0,0 @@ -/************************************************************************** - * - * 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. - * - **************************************************************************/ - - -#include "glheader.h" -#include "macros.h" -#include "mtypes.h" -#include "enums.h" -#include "colortab.h" -#include "convolve.h" -#include "context.h" -#include "simple_list.h" -#include "texcompress.h" -#include "texformat.h" -#include "texobj.h" -#include "texstore.h" - -#include "pipe/p_context.h" -#include "state_tracker/st_mipmap_tree.h" - -#include "intel_tex.h" - - - -#define FILE_DEBUG_FLAG DEBUG_TEXTURE - -/* Functions to store texture images. Where possible, mipmap_tree's - * will be created or further instantiated with image data, otherwise - * images will be stored in malloc'd memory. A validation step is - * required to pull those images into a mipmap tree, or otherwise - * decide a fallback is required. - */ - - -static int -logbase2(int n) -{ - GLint i = 1; - GLint log2 = 0; - - while (n > i) { - i *= 2; - log2++; - } - - return log2; -} - - -/* Otherwise, store it in memory if (Border != 0) or (any dimension == - * 1). - * - * Otherwise, if max_level >= level >= min_level, create tree with - * space for textures from min_level down to max_level. - * - * Otherwise, create tree with space for textures from (level - * 0)..(1x1). Consider pruning this tree at a validation if the - * saving is worth it. - */ -static void -guess_and_alloc_mipmap_tree(struct pipe_context *pipe, - struct st_texture_object *intelObj, - struct st_texture_image *intelImage) -{ - GLuint firstLevel; - GLuint lastLevel; - GLuint width = intelImage->base.Width; - GLuint height = intelImage->base.Height; - GLuint depth = intelImage->base.Depth; - GLuint l2width, l2height, l2depth; - GLuint i, comp_byte = 0; - - DBG("%s\n", __FUNCTION__); - - if (intelImage->base.Border) - return; - - if (intelImage->level > intelObj->base.BaseLevel && - (intelImage->base.Width == 1 || - (intelObj->base.Target != GL_TEXTURE_1D && - intelImage->base.Height == 1) || - (intelObj->base.Target == GL_TEXTURE_3D && - intelImage->base.Depth == 1))) - return; - - /* If this image disrespects BaseLevel, allocate from level zero. - * Usually BaseLevel == 0, so it's unlikely to happen. - */ - if (intelImage->level < intelObj->base.BaseLevel) - firstLevel = 0; - else - firstLevel = intelObj->base.BaseLevel; - - - /* Figure out image dimensions at start level. - */ - for (i = intelImage->level; i > firstLevel; i--) { - width <<= 1; - if (height != 1) - height <<= 1; - if (depth != 1) - depth <<= 1; - } - - /* Guess a reasonable value for lastLevel. This is probably going - * to be wrong fairly often and might mean that we have to look at - * resizable buffers, or require that buffers implement lazy - * pagetable arrangements. - */ - if ((intelObj->base.MinFilter == GL_NEAREST || - intelObj->base.MinFilter == GL_LINEAR) && - intelImage->level == firstLevel) { - lastLevel = firstLevel; - } - else { - l2width = logbase2(width); - l2height = logbase2(height); - l2depth = logbase2(depth); - lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); - } - - assert(!intelObj->mt); - if (intelImage->base.IsCompressed) - comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat->MesaFormat); - intelObj->mt = st_miptree_create(pipe, - intelObj->base.Target, - intelImage->base.InternalFormat, - firstLevel, - lastLevel, - width, - height, - depth, - intelImage->base.TexFormat->TexelBytes, - comp_byte); - - DBG("%s - success\n", __FUNCTION__); -} - - - - -static GLuint -target_to_face(GLenum target) -{ - switch (target) { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: - return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); - default: - return 0; - } -} - - - -/* There are actually quite a few combinations this will work for, - * more than what I've listed here. - */ -static GLboolean -check_pbo_format(GLint internalFormat, - GLenum format, GLenum type, - const struct gl_texture_format *mesa_format) -{ - switch (internalFormat) { - case 4: - case GL_RGBA: - return (format == GL_BGRA && - (type == GL_UNSIGNED_BYTE || - type == GL_UNSIGNED_INT_8_8_8_8_REV) && - mesa_format == &_mesa_texformat_argb8888); - case 3: - case GL_RGB: - return (format == GL_RGB && - type == GL_UNSIGNED_SHORT_5_6_5 && - mesa_format == &_mesa_texformat_rgb565); - case GL_YCBCR_MESA: - return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE); - default: - return GL_FALSE; - } -} - - -/* XXX: Do this for TexSubImage also: - */ -static GLboolean -try_pbo_upload(struct intel_context *intel, - struct st_texture_image *intelImage, - const struct gl_pixelstore_attrib *unpack, - GLint internalFormat, - GLint width, GLint height, - GLenum format, GLenum type, const void *pixels) -{ - return GL_FALSE; /* XXX fix flushing/locking/blitting below */ -#if 000 - struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); - GLuint src_offset, src_stride; - GLuint dst_offset, dst_stride; - - if (!pbo || - intel->ctx._ImageTransferState || - unpack->SkipPixels || unpack->SkipRows) { - _mesa_printf("%s: failure 1\n", __FUNCTION__); - return GL_FALSE; - } - - src_offset = (GLuint) pixels; - - if (unpack->RowLength > 0) - src_stride = unpack->RowLength; - else - src_stride = width; - - dst_offset = st_miptree_image_offset(intelImage->mt, - intelImage->face, - intelImage->level); - - dst_stride = intelImage->mt->pitch; - - intelFlush(&intel->ctx); - LOCK_HARDWARE(intel); - { - struct _DriBufferObject *src_buffer = - intel_bufferobj_buffer(intel, pbo, INTEL_READ); - - /* Temporary hack: cast to _DriBufferObject: - */ - struct _DriBufferObject *dst_buffer = - (struct _DriBufferObject *)intelImage->mt->region->buffer; - - - intelEmitCopyBlit(intel, - intelImage->mt->cpp, - src_stride, src_buffer, src_offset, - dst_stride, dst_buffer, dst_offset, - 0, 0, 0, 0, width, height, - GL_COPY); - - intel_batchbuffer_flush(intel->batch); - } - UNLOCK_HARDWARE(intel); - - return GL_TRUE; -#endif -} - - - -static GLboolean -try_pbo_zcopy(struct intel_context *intel, - struct st_texture_image *intelImage, - const struct gl_pixelstore_attrib *unpack, - GLint internalFormat, - GLint width, GLint height, - GLenum format, GLenum type, const void *pixels) -{ - return GL_FALSE; -} - - - - - - -static void -intelTexImage(GLcontext * ctx, - GLint dims, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, GLsizei imageSize, int compressed) -{ - struct intel_context *intel = intel_context(ctx); - struct st_texture_object *intelObj = st_texture_object(texObj); - struct st_texture_image *intelImage = st_texture_image(texImage); - GLint postConvWidth = width; - GLint postConvHeight = height; - GLint texelBytes, sizeInBytes; - GLuint dstRowStride; - - - DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); - - intelFlush(ctx); - - intelImage->face = target_to_face(target); - intelImage->level = level; - - if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { - _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, - &postConvHeight); - } - - /* choose the texture format */ - texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat, - format, type); - - _mesa_set_fetch_functions(texImage, dims); - - if (texImage->TexFormat->TexelBytes == 0) { - /* must be a compressed format */ - texelBytes = 0; - texImage->IsCompressed = GL_TRUE; - texImage->CompressedSize = - ctx->Driver.CompressedTextureSize(ctx, texImage->Width, - texImage->Height, texImage->Depth, - texImage->TexFormat->MesaFormat); - } else { - texelBytes = texImage->TexFormat->TexelBytes; - - /* Minimum pitch of 32 bytes */ - if (postConvWidth * texelBytes < 32) { - postConvWidth = 32 / texelBytes; - texImage->RowStride = postConvWidth; - } - - assert(texImage->RowStride == postConvWidth); - } - - /* Release the reference to a potentially orphaned buffer. - * Release any old malloced memory. - */ - if (intelImage->mt) { - st_miptree_release(intel->pipe, &intelImage->mt); - assert(!texImage->Data); - } - else if (texImage->Data) { - _mesa_align_free(texImage->Data); - } - - /* If this is the only texture image in the tree, could call - * bmBufferData with NULL data to free the old block and avoid - * waiting on any outstanding fences. - */ - if (intelObj->mt && - intelObj->mt->first_level == level && - intelObj->mt->last_level == level && - intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB && - !st_miptree_match_image(intelObj->mt, &intelImage->base, - intelImage->face, intelImage->level)) { - - DBG("release it\n"); - st_miptree_release(intel->pipe, &intelObj->mt); - assert(!intelObj->mt); - } - - if (!intelObj->mt) { - guess_and_alloc_mipmap_tree(intel->pipe, intelObj, intelImage); - if (!intelObj->mt) { - DBG("guess_and_alloc_mipmap_tree: failed\n"); - } - } - - assert(!intelImage->mt); - - if (intelObj->mt && - st_miptree_match_image(intelObj->mt, &intelImage->base, - intelImage->face, intelImage->level)) { - - st_miptree_reference(&intelImage->mt, intelObj->mt); - assert(intelImage->mt); - } - - if (!intelImage->mt) - DBG("XXX: Image did not fit into tree - storing in local memory!\n"); - -#if 0 /* XXX FIX when st_buffer_objects are in place */ - /* PBO fastpaths: - */ - if (dims <= 2 && - intelImage->mt && - intel_buffer_object(unpack->BufferObj) && - check_pbo_format(internalFormat, format, - type, intelImage->base.TexFormat)) { - - DBG("trying pbo upload\n"); - - /* Attempt to texture directly from PBO data (zero copy upload). - * - * Currently disable as it can lead to worse as well as better - * performance (in particular when pipe_region_cow() is - * required). - */ - if (intelObj->mt == intelImage->mt && - intelObj->mt->first_level == level && - intelObj->mt->last_level == level) { - - if (try_pbo_zcopy(intel, intelImage, unpack, - internalFormat, - width, height, format, type, pixels)) { - - DBG("pbo zcopy upload succeeded\n"); - return; - } - } - - - /* Otherwise, attempt to use the blitter for PBO image uploads. - */ - if (try_pbo_upload(intel, intelImage, unpack, - internalFormat, - width, height, format, type, pixels)) { - DBG("pbo upload succeeded\n"); - return; - } - - DBG("pbo upload failed\n"); - } -#else - (void) try_pbo_upload; - (void) check_pbo_format; - (void) try_pbo_zcopy; -#endif - - - /* intelCopyTexImage calls this function with pixels == NULL, with - * the expectation that the mipmap tree will be set up but nothing - * more will be done. This is where those calls return: - */ - if (compressed) { - pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, - unpack, - "glCompressedTexImage"); - } else { - pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, - format, type, - pixels, unpack, "glTexImage"); - } - if (!pixels) - return; - - - if (intelImage->mt) - intel->pipe->region_idle(intel->pipe, intelImage->mt->region); - - LOCK_HARDWARE(intel); - - if (intelImage->mt) { - texImage->Data = st_miptree_image_map(intel->pipe, - intelImage->mt, - intelImage->face, - intelImage->level, - &dstRowStride, - intelImage->base.ImageOffsets); - } - else { - /* Allocate regular memory and store the image there temporarily. */ - if (texImage->IsCompressed) { - sizeInBytes = texImage->CompressedSize; - dstRowStride = - _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); - assert(dims != 3); - } - else { - dstRowStride = postConvWidth * texelBytes; - sizeInBytes = depth * dstRowStride * postConvHeight; - } - - texImage->Data = malloc(sizeInBytes); - } - - DBG("Upload image %dx%dx%d row_len %x " - "pitch %x\n", - width, height, depth, width * texelBytes, dstRowStride); - - /* Copy data. Would like to know when it's ok for us to eg. use - * the blitter to copy. Or, use the hardware to do the format - * conversion and copy: - */ - if (compressed) { - memcpy(texImage->Data, pixels, imageSize); - } else if (!texImage->TexFormat->StoreImage(ctx, dims, - texImage->_BaseFormat, - texImage->TexFormat, - texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */ - dstRowStride, - texImage->ImageOffsets, - width, height, depth, - format, type, pixels, unpack)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); - } - - _mesa_unmap_teximage_pbo(ctx, unpack); - - if (intelImage->mt) { - st_miptree_image_unmap(intel->pipe, intelImage->mt); - texImage->Data = NULL; - } - - UNLOCK_HARDWARE(intel); - -#if 0 - /* GL_SGIS_generate_mipmap -- this can be accelerated now. - */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - intel_generate_mipmap(ctx, target, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } -#endif -} - -void -intelTexImage3D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint depth, - GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - intelTexImage(ctx, 3, target, level, - internalFormat, width, height, depth, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); -} - - -void -intelTexImage2D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - intelTexImage(ctx, 2, target, level, - internalFormat, width, height, 1, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); -} - -void -intelTexImage1D(GLcontext * ctx, - GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint border, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *unpack, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - intelTexImage(ctx, 1, target, level, - internalFormat, width, 1, 1, border, - format, type, pixels, unpack, texObj, texImage, 0, 0); -} - -void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, - GLint internalFormat, - GLint width, GLint height, GLint border, - GLsizei imageSize, const GLvoid *data, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage ) -{ - intelTexImage(ctx, 2, target, level, - internalFormat, width, height, 1, border, - 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1); -} - -/** - * Need to map texture image into memory before copying image data, - * then unmap it. - */ -static void -intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage, int compressed) -{ - struct intel_context *intel = intel_context(ctx); - struct st_texture_image *intelImage = st_texture_image(texImage); - - /* Map */ - if (intelImage->mt) { - /* Image is stored in hardware format in a buffer managed by the - * kernel. Need to explicitly map and unmap it. - */ - intelImage->base.Data = - st_miptree_image_map(intel->pipe, - intelImage->mt, - intelImage->face, - intelImage->level, - &intelImage->base.RowStride, - intelImage->base.ImageOffsets); - intelImage->base.RowStride /= intelImage->mt->cpp; - } - else { - /* Otherwise, the image should actually be stored in - * intelImage->base.Data. This is pretty confusing for - * everybody, I'd much prefer to separate the two functions of - * texImage->Data - storage for texture images in main memory - * and access (ie mappings) of images. In other words, we'd - * create a new texImage->Map field and leave Data simply for - * storage. - */ - assert(intelImage->base.Data); - } - - - if (compressed) { - _mesa_get_compressed_teximage(ctx, target, level, pixels, - texObj, texImage); - } else { - _mesa_get_teximage(ctx, target, level, format, type, pixels, - texObj, texImage); - } - - - /* Unmap */ - if (intelImage->mt) { - st_miptree_image_unmap(intel->pipe, intelImage->mt); - intelImage->base.Data = NULL; - } -} - -void -intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, - GLenum format, GLenum type, GLvoid * pixels, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - intel_get_tex_image(ctx, target, level, format, type, pixels, - texObj, texImage, 0); - - -} - -void -intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, - GLvoid *pixels, - const struct gl_texture_object *texObj, - const struct gl_texture_image *texImage) -{ - intel_get_tex_image(ctx, target, level, 0, 0, pixels, - texObj, texImage, 1); - -} - -void -intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, - unsigned long long offset, GLint depth, GLuint pitch) -{ - 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->mt) - st_miptree_release(intel->pipe, &stObj->mt); - - stObj->imageOverride = GL_TRUE; - stObj->depthOverride = depth; - stObj->pitchOverride = pitch; - - if (offset) - stObj->textureOffset = offset; -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_layout.c b/src/mesa/drivers/dri/i915pipe/intel_tex_layout.c deleted file mode 120000 index fe61b441945..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_layout.c +++ /dev/null @@ -1 +0,0 @@ -../intel/intel_tex_layout.c \ No newline at end of file diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_subimage.c b/src/mesa/drivers/dri/i915pipe/intel_tex_subimage.c deleted file mode 100644 index 0937114c7fe..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_subimage.c +++ /dev/null @@ -1,192 +0,0 @@ - -/************************************************************************** - * - * 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 "mtypes.h" -#include "texobj.h" -#include "texstore.h" -#include "enums.h" - -/* -#include "intel_context.h" -*/ -#include "intel_tex.h" -#include "state_tracker/st_context.h" -#include "state_tracker/st_mipmap_tree.h" - -#include "pipe/p_context.h" - - -#define FILE_DEBUG_FLAG DEBUG_TEXTURE - -static void -intelTexSubimage(GLcontext * ctx, - GLint dims, - GLenum target, GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLint width, GLint height, GLint depth, - GLenum format, GLenum type, const void *pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - struct pipe_context *pipe = ctx->st->pipe; - struct st_texture_image *intelImage = st_texture_image(texImage); - GLuint dstRowStride; - - DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, - _mesa_lookup_enum_by_nr(target), - level, xoffset, yoffset, width, height); - - intelFlush(ctx); - - pixels = - _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, - type, pixels, packing, "glTexSubImage2D"); - if (!pixels) - return; - - if (intelImage->mt) - pipe->region_idle(pipe, intelImage->mt->region); - -#if 0 - LOCK_HARDWARE(intel); -#endif - - /* Map buffer if necessary. Need to lock to prevent other contexts - * from uploading the buffer under us. - */ - if (intelImage->mt) - texImage->Data = st_miptree_image_map(pipe, - intelImage->mt, - intelImage->face, - intelImage->level, - &dstRowStride, - texImage->ImageOffsets); - - assert(dstRowStride); - - if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, - texImage->TexFormat, - texImage->Data, - xoffset, yoffset, zoffset, - dstRowStride, - texImage->ImageOffsets, - width, height, depth, - format, type, pixels, packing)) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); - } - -#if 0 - /* GL_SGIS_generate_mipmap */ - if (level == texObj->BaseLevel && texObj->GenerateMipmap) { - _mesa_generate_mipmap(ctx, target, - &ctx->Texture.Unit[ctx->Texture.CurrentUnit], - texObj); - } -#endif - - _mesa_unmap_teximage_pbo(ctx, packing); - - if (intelImage->mt) { - st_miptree_image_unmap(pipe, intelImage->mt); - texImage->Data = NULL; - } - -#if 0 - UNLOCK_HARDWARE(intel); -#endif -} - - - - - -void -intelTexSubImage3D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, GLint zoffset, - GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - - intelTexSubimage(ctx, 3, - target, level, - xoffset, yoffset, zoffset, - width, height, depth, - format, type, pixels, packing, texObj, texImage); - -} - - - -void -intelTexSubImage2D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - - intelTexSubimage(ctx, 2, - target, level, - xoffset, yoffset, 0, - width, height, 1, - format, type, pixels, packing, texObj, texImage); - -} - - -void -intelTexSubImage1D(GLcontext * ctx, - GLenum target, - GLint level, - GLint xoffset, - GLsizei width, - GLenum format, GLenum type, - const GLvoid * pixels, - const struct gl_pixelstore_attrib *packing, - struct gl_texture_object *texObj, - struct gl_texture_image *texImage) -{ - intelTexSubimage(ctx, 1, - target, level, - xoffset, 0, 0, - width, 1, 1, - format, type, pixels, packing, texObj, texImage); - -} diff --git a/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c b/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c deleted file mode 100644 index d0631a88f19..00000000000 --- a/src/mesa/drivers/dri/i915pipe/intel_tex_validate.c +++ /dev/null @@ -1,277 +0,0 @@ -#include "mtypes.h" -#include "macros.h" - -#include "state_tracker/st_mipmap_tree.h" -#include "intel_tex.h" - -#include "pipe/p_state.h" - -#define FILE_DEBUG_FLAG DEBUG_TEXTURE - -/** - * Compute which mipmap levels that really need to be sent to the hardware. - * This depends on the base image size, GL_TEXTURE_MIN_LOD, - * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. - */ -static void -intel_calculate_first_last_level(struct st_texture_object *intelObj) -{ - struct gl_texture_object *tObj = &intelObj->base; - const struct gl_texture_image *const baseImage = - tObj->Image[0][tObj->BaseLevel]; - - /* These must be signed values. MinLod and MaxLod can be negative numbers, - * and having firstLevel and lastLevel as signed prevents the need for - * extra sign checks. - */ - int firstLevel; - int lastLevel; - - /* Yes, this looks overly complicated, but it's all needed. - */ - switch (tObj->Target) { - case GL_TEXTURE_1D: - case GL_TEXTURE_2D: - case GL_TEXTURE_3D: - case GL_TEXTURE_CUBE_MAP: - if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { - /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. - */ - firstLevel = lastLevel = tObj->BaseLevel; - } - else { - firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); - firstLevel = MAX2(firstLevel, tObj->BaseLevel); - lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); - lastLevel = MAX2(lastLevel, tObj->BaseLevel); - lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); - lastLevel = MIN2(lastLevel, tObj->MaxLevel); - lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ - } - break; - case GL_TEXTURE_RECTANGLE_NV: - case GL_TEXTURE_4D_SGIS: - firstLevel = lastLevel = 0; - break; - default: - return; - } - - /* save these values */ - intelObj->firstLevel = firstLevel; - intelObj->lastLevel = lastLevel; -} - -static void -copy_image_data_to_tree(struct pipe_context *pipe, - struct st_texture_object *intelObj, - struct st_texture_image *intelImage) -{ - if (intelImage->mt) { - /* Copy potentially with the blitter: - */ - st_miptree_image_copy(pipe, - intelObj->mt, - intelImage->face, - intelImage->level, intelImage->mt); - - st_miptree_release(pipe, &intelImage->mt); - } - else { - assert(intelImage->base.Data != NULL); - - /* More straightforward upload. - */ - st_miptree_image_data(pipe, - intelObj->mt, - intelImage->face, - intelImage->level, - intelImage->base.Data, - intelImage->base.RowStride, - intelImage->base.RowStride * - intelImage->base.Height); - _mesa_align_free(intelImage->base.Data); - intelImage->base.Data = NULL; - } - - st_miptree_reference(&intelImage->mt, intelObj->mt); -} - - -/* - */ -GLuint -intel_finalize_mipmap_tree(GLcontext *ctx, - struct pipe_context *pipe, GLuint unit, - GLboolean *needFlush) -{ - struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; - struct st_texture_object *intelObj = st_texture_object(tObj); - int comp_byte = 0; - int cpp; - - GLuint face, i; - GLuint nr_faces = 0; - struct st_texture_image *firstImage; - - *needFlush = GL_FALSE; - - /* We know/require this is true by now: - */ - assert(intelObj->base._Complete); - - /* What levels must the tree include at a minimum? - */ - intel_calculate_first_last_level(intelObj); - firstImage = - st_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); - - /* Fallback case: - */ - if (firstImage->base.Border) { - if (intelObj->mt) { - st_miptree_release(pipe, &intelObj->mt); - } - return GL_FALSE; - } - - - /* If both firstImage and intelObj have a tree which can contain - * all active images, favour firstImage. Note that because of the - * completeness requirement, we know that the image dimensions - * will match. - */ - if (firstImage->mt && - firstImage->mt != intelObj->mt && - firstImage->mt->first_level <= intelObj->firstLevel && - firstImage->mt->last_level >= intelObj->lastLevel) { - - if (intelObj->mt) - st_miptree_release(pipe, &intelObj->mt); - - st_miptree_reference(&intelObj->mt, firstImage->mt); - } - - if (firstImage->base.IsCompressed) { - comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); - cpp = comp_byte; - } - else cpp = firstImage->base.TexFormat->TexelBytes; - - /* Check tree can hold all active levels. Check tree matches - * target, imageFormat, etc. - * - * XXX: For some layouts (eg i945?), the test might have to be - * first_level == firstLevel, as the tree isn't valid except at the - * original start level. Hope to get around this by - * programming minLod, maxLod, baseLevel into the hardware and - * leaving the tree alone. - */ - if (intelObj->mt && - (intelObj->mt->target != intelObj->base.Target || - intelObj->mt->internal_format != firstImage->base.InternalFormat || - intelObj->mt->first_level != intelObj->firstLevel || - intelObj->mt->last_level != intelObj->lastLevel || - intelObj->mt->width0 != firstImage->base.Width || - intelObj->mt->height0 != firstImage->base.Height || - intelObj->mt->depth0 != firstImage->base.Depth || - intelObj->mt->cpp != cpp || - intelObj->mt->compressed != firstImage->base.IsCompressed)) { - st_miptree_release(pipe, &intelObj->mt); - } - - - /* May need to create a new tree: - */ - if (!intelObj->mt) { - intelObj->mt = st_miptree_create(pipe, - intelObj->base.Target, - firstImage->base.InternalFormat, - intelObj->firstLevel, - intelObj->lastLevel, - firstImage->base.Width, - firstImage->base.Height, - firstImage->base.Depth, - cpp, - comp_byte); - } - - /* Pull in any images not in the object's tree: - */ - nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - for (face = 0; face < nr_faces; face++) { - for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { - struct st_texture_image *intelImage = - st_texture_image(intelObj->base.Image[face][i]); - - /* Need to import images in main memory or held in other trees. - */ - if (intelObj->mt != intelImage->mt) { - copy_image_data_to_tree(pipe, intelObj, intelImage); - *needFlush = GL_TRUE; - } - } - } - - /** - if (need_flush) - intel_batchbuffer_flush(intel->batch); - **/ - - return GL_TRUE; -} - - -#if 0 /* unused? */ -void -intel_tex_map_images(struct pipe_context *pipe, - struct st_texture_object *intelObj) -{ - GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLuint face, i; - - DBG("%s\n", __FUNCTION__); - - for (face = 0; face < nr_faces; face++) { - for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { - struct st_texture_image *intelImage = - st_texture_image(intelObj->base.Image[face][i]); - - if (intelImage->mt) { - intelImage->base.Data = - st_miptree_image_map(pipe, - intelImage->mt, - intelImage->face, - intelImage->level, - &intelImage->base.RowStride, - intelImage->base.ImageOffsets); - /* convert stride to texels, not bytes */ - intelImage->base.RowStride /= intelImage->mt->cpp; -/* intelImage->base.ImageStride /= intelImage->mt->cpp; */ - } - } - } -} - - - -void -intel_tex_unmap_images(struct pipe_context *pipe, - struct st_texture_object *intelObj) -{ - GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; - GLuint face, i; - - for (face = 0; face < nr_faces; face++) { - for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { - struct st_texture_image *intelImage = - st_texture_image(intelObj->base.Image[face][i]); - - if (intelImage->mt) { - st_miptree_image_unmap(pipe, intelImage->mt); - intelImage->base.Data = NULL; - } - } - } -} -#endif diff --git a/src/mesa/drivers/dri/i915pipe/server/i830_common.h b/src/mesa/drivers/dri/i915pipe/server/i830_common.h deleted file mode 100644 index d4d58886ce0..00000000000 --- a/src/mesa/drivers/dri/i915pipe/server/i830_common.h +++ /dev/null @@ -1,226 +0,0 @@ -/************************************************************************** - -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/mesa/drivers/dri/i915pipe/server/i830_dri.h b/src/mesa/drivers/dri/i915pipe/server/i830_dri.h deleted file mode 100644 index c2a3af8cbf7..00000000000 --- a/src/mesa/drivers/dri/i915pipe/server/i830_dri.h +++ /dev/null @@ -1,63 +0,0 @@ -/* $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/mesa/drivers/dri/i915pipe/server/intel.h b/src/mesa/drivers/dri/i915pipe/server/intel.h deleted file mode 100644 index 6ea72499c1c..00000000000 --- a/src/mesa/drivers/dri/i915pipe/server/intel.h +++ /dev/null @@ -1,331 +0,0 @@ -#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 - -# 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/mesa/drivers/dri/i915pipe/server/intel_dri.c b/src/mesa/drivers/dri/i915pipe/server/intel_dri.c deleted file mode 100644 index e49c4214ad4..00000000000 --- a/src/mesa/drivers/dri/i915pipe/server/intel_dri.c +++ /dev/null @@ -1,1306 +0,0 @@ -/** - * \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 -#include -#include -#include -#include - -#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 -}; diff --git a/src/mesa/drivers/dri/intel_winsys/Makefile b/src/mesa/drivers/dri/intel_winsys/Makefile new file mode 100644 index 00000000000..e4e9cf17b09 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/Makefile @@ -0,0 +1,49 @@ + +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = i915tex_dri.so + +MINIGLX_SOURCES = server/intel_dri.c + +PIPE_DRIVERS = \ + $(TOP)/src/mesa/pipe/softpipe/libsoftpipe.a + +DRIVER_SOURCES = \ + intel_softpipe.c \ + intel_batchbuffer.c \ + intel_tex_layout.c \ + intel_buffers.c \ + intel_blit.c \ + intel_context.c \ + intel_ioctl.c \ + intel_screen.c \ + intel_surface.c \ + intel_fbo.c \ + intel_depthstencil.c \ + intel_batchpool.c + +OLD_TEX =\ + intel_tex_image.c \ + intel_tex_subimage.c \ + intel_tex_copy.c \ + intel_tex_validate.c \ + intel_tex_format.c \ + intel_tex.c + + +C_SOURCES = \ + $(COMMON_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/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c new file mode 100644 index 00000000000..60bd8eaec29 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.c @@ -0,0 +1,342 @@ +/************************************************************************** + * + * 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 "intel_batchbuffer.h" +#include "intel_ioctl.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(GLuint offset, GLuint * ptr, GLuint count) +{ + int i; + fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4); + for (i = 0; i < count / 4; i += 4) + fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n", + offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]); + fprintf(stderr, "END BATCH\n\n\n"); +} + +void +intel_batchbuffer_reset(struct intel_batchbuffer *batch) +{ + + int i; + + /* + * 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); +} + +/* TODO: Push this whole function into bufmgr. + */ +static void +do_flush_locked(struct intel_batchbuffer *batch, + GLuint used, + GLboolean ignore_cliprects, GLboolean allow_unlock) +{ + GLuint *ptr; + GLuint i; + struct intel_context *intel = batch->intel; + unsigned 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 = (GLuint *) 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 (INTEL_DEBUG & DEBUG_BATCH) + intel_dump_batchbuffer(0, ptr, used); + + driBOUnmap(batch->buffer); + batch->map = NULL; + + /* Throw away non-effective packets. Won't work once we have + * hardware contexts which would preserve statechanges beyond a + * single buffer. + */ + + if (!(intel->numClipRects == 0 && !ignore_cliprects)) { + intel_batch_ioctl(batch->intel, + driBOOffset(batch->buffer), + used, ignore_cliprects, 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); + } + } + + if (intel->numClipRects == 0 && !ignore_cliprects) { + if (allow_unlock) { + UNLOCK_HARDWARE(intel); + sched_yield(); + LOCK_HARDWARE(intel); + } +// intel->vtbl.lost_hardware(intel); + } +} + + +struct _DriFenceObject * +intel_batchbuffer_flush(struct intel_batchbuffer *batch) +{ + struct intel_context *intel = batch->intel; + GLuint used = batch->ptr - batch->map; + GLboolean 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, !(batch->flags & INTEL_BATCH_CLIPRECTS), + 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); + driFenceReference(fence); + driFenceFinish(fence, 3, GL_FALSE); + driFenceUnReference(fence); +} + + +/* This is the only way buffers get added to the validate list. + */ +GLboolean +intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, + struct _DriBufferObject *buffer, + GLuint flags, GLuint mask, GLuint 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; + } + + batch->ptr += 4; + return GL_TRUE; +} + + + +void +intel_batchbuffer_data(struct intel_batchbuffer *batch, + const void *data, GLuint bytes, GLuint flags) +{ + assert((bytes & 3) == 0); + intel_batchbuffer_require_space(batch, bytes, flags); + memcpy(batch->ptr, data, bytes); + batch->ptr += bytes; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h new file mode 100644 index 00000000000..6d4d05e0bb1 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_batchbuffer.h @@ -0,0 +1,123 @@ +#ifndef INTEL_BATCHBUFFER_H +#define INTEL_BATCHBUFFER_H + +#include "mtypes.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; + GLuint offset; + GLuint delta; /* not needed? */ +}; + +struct intel_batchbuffer +{ + struct bufmgr *bm; + struct intel_context *intel; + + struct _DriBufferObject *buffer; + struct _DriFenceObject *last_fence; + GLuint flags; + + drmBOList list; + GLuint list_count; + GLubyte *map; + GLubyte *ptr; + + struct buffer_reloc reloc[MAX_RELOCS]; + GLuint nr_relocs; + GLuint 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 multple + * intel_buffer_dword() calls. + */ +void intel_batchbuffer_data(struct intel_batchbuffer *batch, + const void *data, GLuint bytes, GLuint flags); + +void intel_batchbuffer_release_space(struct intel_batchbuffer *batch, + GLuint bytes); + +GLboolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch, + struct _DriBufferObject *buffer, + GLuint flags, + GLuint mask, GLuint 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 GLuint +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, GLuint dword) +{ + assert(batch->map); + assert(intel_batchbuffer_space(batch) >= 4); + *(GLuint *) (batch->ptr) = dword; + batch->ptr += 4; +} + +static INLINE void +intel_batchbuffer_require_space(struct intel_batchbuffer *batch, + GLuint sz, GLuint 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/mesa/drivers/dri/intel_winsys/intel_batchpool.c b/src/mesa/drivers/dri/intel_winsys/intel_batchpool.c new file mode 100644 index 00000000000..2503b8a62a1 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_batchpool.c @@ -0,0 +1,418 @@ +/************************************************************************** + * + * 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 + */ + +#include +#include +#include +#include "imports.h" +#include "glthread.h" +#include "dri_bufpool.h" +#include "dri_bufmgr.h" +#include "intel_screen.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, 0, 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/mesa/drivers/dri/intel_winsys/intel_blit.c b/src/mesa/drivers/dri/intel_winsys/intel_blit.c new file mode 100644 index 00000000000..8e878f00887 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_blit.c @@ -0,0 +1,394 @@ +/************************************************************************** + * + * 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 "mtypes.h" +#include "context.h" +#include "enums.h" + +#include "intel_batchbuffer.h" +#include "intel_blit.h" +#include "intel_buffers.h" +#include "intel_context.h" +#include "intel_fbo.h" +#include "intel_reg.h" +#include "vblank.h" + +#include "pipe/p_context.h" + + +#define FILE_DEBUG_FLAG DEBUG_BLIT + +/** + * Copy the back color buffer to the front color buffer. + * Used for SwapBuffers(). + */ +void +intelCopyBuffer(__DRIdrawablePrivate * dPriv, + const drm_clip_rect_t * rect) +{ + + struct intel_context *intel; + const intelScreenPrivate *intelScreen; + + DBG("%s\n", __FUNCTION__); + + assert(dPriv); + + intel = intelScreenContext(dPriv->driScreenPriv->private); + if (!intel) + return; + + intelScreen = intel->intelScreen; + + 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; + } + 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 ((struct intel_context *)dPriv->driContextPriv->driverPrivate != intel) + DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv); + + + if (dPriv && dPriv->numClipRects) { + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + const struct pipe_region *backRegion + = intel_fb->Base._ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT ? + intel_get_rb_region(&intel_fb->Base, BUFFER_FRONT_LEFT) : + intel_get_rb_region(&intel_fb->Base, BUFFER_BACK_LEFT); + const int backWidth = intel_fb->Base.Width; + const int backHeight = intel_fb->Base.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 srcpitch = backRegion->pitch; + const int cpp = intelScreen->front.cpp; + int BR13, CMD; + int i; + + ASSERT(intel_fb); + ASSERT(intel_fb->Base.Name == 0); /* Not a user-created FBO */ + ASSERT(backRegion); + ASSERT(backRegion->cpp == cpp); + + DBG("front pitch %d back pitch %d\n", + pitch, backRegion->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) + continue; + + box = *pbox; + + if (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 > backWidth) + box.x2 = backWidth + box.x1; + if (box.y2 - box.y1 > backHeight) + box.y2 = backHeight + box.y1; + + DBG("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; + + 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(backRegion->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); + + /* XXX this is bogus. The context here may not even be bound to this drawable! */ + if (intel->lastStamp != dPriv->lastStamp) { + GET_CURRENT_CONTEXT(currctx); + struct intel_context *intelcurrent = intel_context(currctx); + if (intelcurrent == intel && intelcurrent->driDrawable == dPriv) { + intelWindowMoved(intel); + intel->lastStamp = dPriv->lastStamp; + } + } + +} + + + + +void +intelEmitFillBlit(struct intel_context *intel, + GLuint cpp, + GLshort dst_pitch, + struct _DriBufferObject *dst_buffer, + GLuint dst_offset, + GLshort x, GLshort y, GLshort w, GLshort h, + GLuint value, GLuint mask) +{ + GLuint BR13, CMD; + GLboolean badMask = GL_FALSE; + BATCH_LOCALS; + + /* + printf("Emit fill blit value=0x%x mask=0x%x\n", value, mask); + */ + + dst_pitch *= cpp; + + switch (cpp) { + case 1: + case 2: + case 3: + BR13 = dst_pitch | (0xF0 << 16) | (1 << 24); + CMD = XY_COLOR_BLT_CMD; + if ((mask & 0xffff) != 0xffff) + badMask = GL_TRUE; + break; + case 4: + BR13 = dst_pitch | (0xF0 << 16) | (1 << 24) | (1 << 25); +#if 0 + CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA | + XY_COLOR_BLT_WRITE_RGB); +#else + CMD = XY_COLOR_BLT_CMD; + if ((mask & 0xff000000) == 0xff000000) + CMD |= XY_COLOR_BLT_WRITE_ALPHA; + else if (mask & 0xff000000) + badMask = GL_TRUE; + if ((mask & 0x00ffffff) == 0x00ffffff) + CMD |= XY_COLOR_BLT_WRITE_RGB; + else if (mask & 0x00ffffff) + badMask = GL_TRUE; +#endif + break; + default: + return; + } + + assert(!badMask); + + DBG("%s dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", + __FUNCTION__, dst_buffer, dst_pitch, dst_offset, x, y, w, h); + + + BEGIN_BATCH(6, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH(CMD); + OUT_BATCH(BR13); + OUT_BATCH((y << 16) | x); + OUT_BATCH(((y + h) << 16) | (x + w)); + OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); + OUT_BATCH(value); + ADVANCE_BATCH(); + + intel_batchbuffer_flush(intel->batch); +} + + +static GLuint translate_raster_op(GLenum logicop) +{ + switch(logicop) { + case GL_CLEAR: return 0x00; + case GL_AND: return 0x88; + case GL_AND_REVERSE: return 0x44; + case GL_COPY: return 0xCC; + case GL_AND_INVERTED: return 0x22; + case GL_NOOP: return 0xAA; + case GL_XOR: return 0x66; + case GL_OR: return 0xEE; + case GL_NOR: return 0x11; + case GL_EQUIV: return 0x99; + case GL_INVERT: return 0x55; + case GL_OR_REVERSE: return 0xDD; + case GL_COPY_INVERTED: return 0x33; + case GL_OR_INVERTED: return 0xBB; + case GL_NAND: return 0x77; + case GL_SET: return 0xFF; + default: return 0; + } +} + + +/* Copy BitBlt + */ +void +intelEmitCopyBlit(struct intel_context *intel, + GLuint cpp, + GLshort src_pitch, + struct _DriBufferObject *src_buffer, + GLuint src_offset, + GLshort dst_pitch, + struct _DriBufferObject *dst_buffer, + GLuint dst_offset, + GLshort src_x, GLshort src_y, + GLshort dst_x, GLshort dst_y, + GLshort w, GLshort h, + GLenum logic_op) +{ + GLuint CMD, BR13; + int dst_y2 = dst_y + h; + int dst_x2 = dst_x + w; + BATCH_LOCALS; + + + DBG("%s src:buf(%p)/%d+%d %d,%d dst:buf(%p)/%d+%d %d,%d sz:%dx%d\n", + __FUNCTION__, + src_buffer, src_pitch, src_offset, src_x, src_y, + dst_buffer, dst_pitch, dst_offset, dst_x, dst_y, w, h); + + src_pitch *= cpp; + dst_pitch *= cpp; + + switch (cpp) { + case 1: + case 2: + case 3: + BR13 = (((GLint) dst_pitch) & 0xffff) | + (translate_raster_op(logic_op) << 16) | (1 << 24); + CMD = XY_SRC_COPY_BLT_CMD; + break; + case 4: + BR13 = + (((GLint) dst_pitch) & 0xffff) | + (translate_raster_op(logic_op) << 16) | (1 << 24) | (1 << 25); + CMD = + (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB); + break; + default: + return; + } + + if (dst_y2 < dst_y || dst_x2 < dst_x) { + return; + } + + /* Initial y values don't seem to work with negative pitches. If + * we adjust the offsets manually (below), it seems to work fine. + * + * On the other hand, if we always adjust, the hardware doesn't + * know which blit directions to use, so overlapping copypixels get + * the wrong result. + */ + if (dst_pitch > 0 && src_pitch > 0) { + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH(CMD); + OUT_BATCH(BR13); + OUT_BATCH((dst_y << 16) | dst_x); + OUT_BATCH((dst_y2 << 16) | dst_x2); + OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, dst_offset); + OUT_BATCH((src_y << 16) | src_x); + OUT_BATCH(((GLint) src_pitch & 0xffff)); + OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, src_offset); + ADVANCE_BATCH(); + } + else { + BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS); + OUT_BATCH(CMD); + OUT_BATCH(BR13); + OUT_BATCH((0 << 16) | dst_x); + OUT_BATCH((h << 16) | dst_x2); + OUT_RELOC(dst_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE, + DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, + dst_offset + dst_y * dst_pitch); + OUT_BATCH((0 << 16) | src_x); + OUT_BATCH(((GLint) src_pitch & 0xffff)); + OUT_RELOC(src_buffer, DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ, + DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, + src_offset + src_y * src_pitch); + ADVANCE_BATCH(); + } + + intel_batchbuffer_flush( intel->batch ); +} + + + diff --git a/src/mesa/drivers/dri/intel_winsys/intel_blit.h b/src/mesa/drivers/dri/intel_winsys/intel_blit.h new file mode 100644 index 00000000000..46c25944775 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_blit.h @@ -0,0 +1,62 @@ +/************************************************************************** + * + * 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_BLIT_H +#define INTEL_BLIT_H + +#include "intel_context.h" +#include "intel_ioctl.h" +#include "dri_bufmgr.h" + +extern void intelCopyBuffer(__DRIdrawablePrivate * dpriv, + const drm_clip_rect_t * rect); + +extern void intelClearWithBlit(GLcontext * ctx, GLbitfield mask); + +extern void intelEmitCopyBlit(struct intel_context *intel, + GLuint cpp, + GLshort src_pitch, + struct _DriBufferObject *src_buffer, + GLuint src_offset, + GLshort dst_pitch, + struct _DriBufferObject *dst_buffer, + GLuint dst_offset, + GLshort srcx, GLshort srcy, + GLshort dstx, GLshort dsty, + GLshort w, GLshort h, + GLenum logicop ); + +extern void intelEmitFillBlit(struct intel_context *intel, + GLuint cpp, + GLshort dst_pitch, + struct _DriBufferObject *dst_buffer, + GLuint dst_offset, + GLshort x, GLshort y, + GLshort w, GLshort h, GLuint value, GLuint mask); + + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_buffers.c b/src/mesa/drivers/dri/intel_winsys/intel_buffers.c new file mode 100644 index 00000000000..fc9d60c88e5 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_buffers.c @@ -0,0 +1,711 @@ +/************************************************************************** + * + * 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_blit.h" +#include "intel_buffers.h" +#include "intel_depthstencil.h" +#include "intel_fbo.h" +#include "intel_batchbuffer.h" +#include "intel_reg.h" +#include "context.h" +#include "utils.h" +#include "drirenderbuffer.h" +#include "framebuffer.h" +#include "vblank.h" + +#include "pipe/p_context.h" + +/* This block can be removed when libdrm >= 2.3.1 is required */ + +#ifndef DRM_VBLANK_FLIP + +#define DRM_VBLANK_FLIP 0x8000000 + +typedef struct drm_i915_flip { + int pipes; +} drm_i915_flip_t; + +#undef DRM_IOCTL_I915_FLIP +#define DRM_IOCTL_I915_FLIP DRM_IOW(DRM_COMMAND_BASE + DRM_I915_FLIP, \ + drm_i915_flip_t) + +#endif + + +/** + * XXX move this into a new dri/common/cliprects.c file. + */ +GLboolean +intel_intersect_cliprects(drm_clip_rect_t * dst, + const drm_clip_rect_t * a, + const drm_clip_rect_t * b) +{ + GLint bx = b->x1; + GLint by = b->y1; + GLint bw = b->x2 - bx; + GLint bh = b->y2 - by; + + if (bx < a->x1) + bw -= a->x1 - bx, bx = a->x1; + if (by < a->y1) + bh -= a->y1 - by, by = a->y1; + if (bx + bw > a->x2) + bw = a->x2 - bx; + if (by + bh > a->y2) + bh = a->y2 - by; + if (bw <= 0) + return GL_FALSE; + if (bh <= 0) + return GL_FALSE; + + dst->x1 = bx; + dst->y1 = by; + dst->x2 = bx + bw; + dst->y2 = by + bh; + + return GL_TRUE; +} + +/** + * Return pointer to current color drawing region, or NULL. + */ +struct pipe_region * +intel_drawbuf_region(struct intel_context *intel) +{ + struct intel_renderbuffer *irbColor = + intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0][0]); + if (irbColor) + return irbColor->region; + else + return NULL; +} + +/** + * Return pointer to current color reading region, or NULL. + */ +struct pipe_region * +intel_readbuf_region(struct intel_context *intel) +{ + struct intel_renderbuffer *irb + = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); + if (irb) + return irb->region; + else + return NULL; +} + + + +/** + * Update the following fields for rendering: + * intel->numClipRects + * intel->pClipRects + */ +static void +intelSetRenderbufferClipRects(struct intel_context *intel) +{ + /* zero-sized buffers might be legal? */ + assert(intel->ctx.DrawBuffer->Width > 0); + assert(intel->ctx.DrawBuffer->Height > 0); + intel->fboRect.x1 = 0; + intel->fboRect.y1 = 0; + intel->fboRect.x2 = intel->ctx.DrawBuffer->Width; + intel->fboRect.y2 = intel->ctx.DrawBuffer->Height; + intel->numClipRects = 1; + intel->pClipRects = &intel->fboRect; +} + + +/** + * This will be called whenever the currently bound window is moved/resized. + * XXX: actually, it seems to NOT be called when the window is only moved (BP). + */ +void +intelWindowMoved(struct intel_context *intel) +{ + GLcontext *ctx = &intel->ctx; + __DRIdrawablePrivate *dPriv = intel->driDrawable; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + + if (!intel->ctx.DrawBuffer) { + /* when would this happen? -BP */ + assert(0); + intel->numClipRects = 0; + } + + /* Update Mesa's notion of window size */ + driUpdateFramebufferSize(ctx, dPriv); + intel_fb->Base.Initialized = GL_TRUE; /* XXX remove someday */ + + { + drmI830Sarea *sarea = intel->sarea; + drm_clip_rect_t drw_rect = { .x1 = dPriv->x, .x2 = dPriv->x + dPriv->w, + .y1 = dPriv->y, .y2 = dPriv->y + dPriv->h }; + drm_clip_rect_t pipeA_rect = { .x1 = sarea->pipeA_x, .y1 = sarea->pipeA_y, + .x2 = sarea->pipeA_x + sarea->pipeA_w, + .y2 = sarea->pipeA_y + sarea->pipeA_h }; + drm_clip_rect_t pipeB_rect = { .x1 = sarea->pipeB_x, .y1 = sarea->pipeB_y, + .x2 = sarea->pipeB_x + sarea->pipeB_w, + .y2 = sarea->pipeB_y + sarea->pipeB_h }; + GLint areaA = driIntersectArea( drw_rect, pipeA_rect ); + GLint areaB = driIntersectArea( drw_rect, pipeB_rect ); + GLuint flags = intel_fb->vblank_flags; + GLboolean pf_active; + GLint pf_pipes; + + /* Update page flipping info + */ + pf_pipes = 0; + + if (areaA > 0) + pf_pipes |= 1; + + if (areaB > 0) + pf_pipes |= 2; + + intel_fb->pf_current_page = (intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3; + + intel_fb->pf_num_pages = 2 /*intel->intelScreen->third.handle ? 3 : 2*/; + + pf_active = pf_pipes && (pf_pipes & intel->sarea->pf_active) == pf_pipes; + + if (INTEL_DEBUG & DEBUG_LOCK) + if (pf_active != intel_fb->pf_active) + _mesa_printf("%s - Page flipping %sactive\n", __progname, + pf_active ? "" : "in"); + + if (pf_active) { + /* Sync pages between pipes if we're flipping on both at the same time */ + if (pf_pipes == 0x3 && pf_pipes != intel_fb->pf_pipes && + (intel->sarea->pf_current_page & 0x3) != + (((intel->sarea->pf_current_page) >> 2) & 0x3)) { + drm_i915_flip_t flip; + + if (intel_fb->pf_current_page == + (intel->sarea->pf_current_page & 0x3)) { + /* XXX: This is ugly, but emitting two flips 'in a row' can cause + * lockups for unknown reasons. + */ + intel->sarea->pf_current_page = + intel->sarea->pf_current_page & 0x3; + intel->sarea->pf_current_page |= + ((intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % + intel_fb->pf_num_pages) << 2; + + flip.pipes = 0x2; + } else { + intel->sarea->pf_current_page = + intel->sarea->pf_current_page & (0x3 << 2); + intel->sarea->pf_current_page |= + (intel_fb->pf_current_page + intel_fb->pf_num_pages - 1) % + intel_fb->pf_num_pages; + + flip.pipes = 0x1; + } + + drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); + } + + intel_fb->pf_pipes = pf_pipes; + } + + intel_fb->pf_active = pf_active; + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + + /* Update vblank info + */ + if (areaB > areaA || (areaA == areaB && areaB > 0)) { + flags = intel_fb->vblank_flags | VBLANK_FLAG_SECONDARY; + } else { + flags = intel_fb->vblank_flags & ~VBLANK_FLAG_SECONDARY; + } + + if (flags != intel_fb->vblank_flags && intel_fb->vblank_flags && + !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ)) { + drmVBlank vbl; + int i; + + vbl.request.type = DRM_VBLANK_ABSOLUTE; + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { + vbl.request.type |= DRM_VBLANK_SECONDARY; + } + + for (i = 0; i < intel_fb->pf_num_pages; i++) { + if (!intel_fb->color_rb[i] || + (intel_fb->vbl_waited - intel_fb->color_rb[i]->vbl_pending) <= + (1<<23)) + continue; + + vbl.request.sequence = intel_fb->color_rb[i]->vbl_pending; + drmWaitVBlank(intel->driFd, &vbl); + } + + intel_fb->vblank_flags = flags; + driGetCurrentVBlank(dPriv, intel_fb->vblank_flags, &intel_fb->vbl_seq); + intel_fb->vbl_waited = intel_fb->vbl_seq; + + for (i = 0; i < intel_fb->pf_num_pages; i++) { + if (intel_fb->color_rb[i]) + intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_waited; + } + } + } + + /* This will be picked up by looking at the dirty state flags: + */ + + /* Update hardware scissor */ +// ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, +// ctx->Scissor.Width, ctx->Scissor.Height); + + /* Re-calculate viewport related state */ +// ctx->Driver.DepthRange( ctx, ctx->Viewport.Near, ctx->Viewport.Far ); +} + + + + + +/* Emit wait for pending flips */ +void +intel_wait_flips(struct intel_context *intel, GLuint batch_flags) +{ + struct intel_framebuffer *intel_fb = + (struct intel_framebuffer *) intel->ctx.DrawBuffer; + struct intel_renderbuffer *intel_rb = + intel_get_renderbuffer(&intel_fb->Base, + intel_fb->Base._ColorDrawBufferMask[0] == + BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : + BUFFER_BACK_LEFT); + + if (intel_fb->Base.Name == 0 && intel_rb->pf_pending == intel_fb->pf_seq) { + GLint pf_pipes = intel_fb->pf_pipes; + BATCH_LOCALS; + + /* Wait for pending flips to take effect */ + BEGIN_BATCH(2, batch_flags); + OUT_BATCH(pf_pipes & 0x1 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP) + : 0); + OUT_BATCH(pf_pipes & 0x2 ? (MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_B_FLIP) + : 0); + ADVANCE_BATCH(); + + intel_rb->pf_pending--; + } +} + +#if 0 +/* Flip the front & back buffers + */ +static GLboolean +intelPageFlip(const __DRIdrawablePrivate * dPriv) +{ + struct intel_context *intel; + int ret; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s\n", __FUNCTION__); + + assert(dPriv); + assert(dPriv->driContextPriv); + assert(dPriv->driContextPriv->driverPrivate); + + intel = (struct intel_context *) dPriv->driContextPriv->driverPrivate; + + if (intel->intelScreen->drmMinor < 9) + return GL_FALSE; + + intelFlush(&intel->ctx); + + ret = 0; + + LOCK_HARDWARE(intel); + + if (dPriv->numClipRects && intel_fb->pf_active) { + drm_i915_flip_t flip; + + flip.pipes = intel_fb->pf_pipes; + + ret = drmCommandWrite(intel->driFd, DRM_I915_FLIP, &flip, sizeof(flip)); + } + + UNLOCK_HARDWARE(intel); + + if (ret || !intel_fb->pf_active) + return GL_FALSE; + + if (!dPriv->numClipRects) { + usleep(10000); /* throttle invisible client 10ms */ + } + + intel_fb->pf_current_page = (intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3; + + if (dPriv->numClipRects != 0) { + intel_get_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT)->pf_pending = + intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->pf_pending = + ++intel_fb->pf_seq; + } + + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, &intel_fb->Base); + + if (INTEL_DEBUG & DEBUG_IOCTL) + fprintf(stderr, "%s: success\n", __FUNCTION__); + + return GL_TRUE; +} +#endif + + +static GLboolean +intelScheduleSwap(const __DRIdrawablePrivate * dPriv, GLboolean *missed_target) +{ + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + unsigned int interval = driGetVBlankInterval(dPriv, intel_fb->vblank_flags); + struct intel_context *intel = + intelScreenContext(dPriv->driScreenPriv->private); + const intelScreenPrivate *intelScreen = intel->intelScreen; + unsigned int target; + drm_i915_vblank_swap_t swap; + GLboolean ret; + + if (!intel_fb->vblank_flags || + (intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) || + intelScreen->drmMinor < (intel_fb->pf_active ? 9 : 6)) + return GL_FALSE; + + swap.seqtype = DRM_VBLANK_ABSOLUTE; + + if (intel_fb->vblank_flags & VBLANK_FLAG_SYNC) { + swap.seqtype |= DRM_VBLANK_NEXTONMISS; + } else if (interval == 0) { + return GL_FALSE; + } + + swap.drawable = dPriv->hHWDrawable; + target = swap.sequence = intel_fb->vbl_seq + interval; + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { + swap.seqtype |= DRM_VBLANK_SECONDARY; + } + + LOCK_HARDWARE(intel); + + intel_batchbuffer_flush(intel->batch); + + if ( intel_fb->pf_active ) { + swap.seqtype |= DRM_VBLANK_FLIP; + + intel_fb->pf_current_page = (((intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3) + 1) % + intel_fb->pf_num_pages; + } + + if (!drmCommandWriteRead(intel->driFd, DRM_I915_VBLANK_SWAP, &swap, + sizeof(swap))) { + intel_fb->vbl_seq = swap.sequence; + swap.sequence -= target; + *missed_target = swap.sequence > 0 && swap.sequence <= (1 << 23); + + intel_get_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT)->vbl_pending = + intel_get_renderbuffer(&intel_fb->Base, + BUFFER_FRONT_LEFT)->vbl_pending = + intel_fb->vbl_seq; + + if (swap.seqtype & DRM_VBLANK_FLIP) { + intel_flip_renderbuffers(intel_fb); + intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer); + } + + ret = GL_TRUE; + } else { + if (swap.seqtype & DRM_VBLANK_FLIP) { + intel_fb->pf_current_page = ((intel->sarea->pf_current_page >> + (intel_fb->pf_pipes & 0x2)) & 0x3) % + intel_fb->pf_num_pages; + } + + ret = GL_FALSE; + } + + UNLOCK_HARDWARE(intel); + + return ret; +} + +void +intelSwapBuffers(__DRIdrawablePrivate * dPriv) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + GET_CURRENT_CONTEXT(ctx); + struct intel_context *intel; + + if (ctx == NULL) + return; + + intel = intel_context(ctx); + + if (ctx->Visual.doubleBufferMode) { + GLboolean missed_target; + struct intel_framebuffer *intel_fb = dPriv->driverPrivate; + int64_t ust; + + _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ + + if (!intelScheduleSwap(dPriv, &missed_target)) { + driWaitForVBlank(dPriv, &intel_fb->vbl_seq, intel_fb->vblank_flags, + &missed_target); + + intelCopyBuffer(dPriv, NULL); + } + + intel_fb->swap_count++; + (*dri_interface->getUST) (&ust); + if (missed_target) { + intel_fb->swap_missed_count++; + intel_fb->swap_missed_ust = ust - intel_fb->swap_ust; + } + + intel_fb->swap_ust = ust; + } + } + else { + /* XXX this shouldn't be an error but we can't handle it for now */ + fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); + } +} + +void +intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) +{ + if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) { + struct intel_context *intel = + (struct intel_context *) dPriv->driContextPriv->driverPrivate; + GLcontext *ctx = &intel->ctx; + + if (ctx->Visual.doubleBufferMode) { + drm_clip_rect_t rect; + /* fixup cliprect (driDrawable may have changed?) later */ + rect.x1 = x; + rect.y1 = y; + rect.x2 = w; + rect.y2 = h; + _mesa_notifySwapBuffers(ctx); /* flush pending rendering comands */ + intelCopyBuffer(dPriv, &rect); + } + } + else { + /* XXX this shouldn't be an error but we can't handle it for now */ + fprintf(stderr, "%s: drawable has no context!\n", __FUNCTION__); + } +} + + +/** + * Update the hardware state for drawing into a window or framebuffer object. + * + * Called by glDrawBuffer, glBindFramebufferEXT, MakeCurrent, and other + * places within the driver. + * + * Basically, this needs to be called any time the current framebuffer + * changes, the renderbuffers change, or we need to draw into different + * color buffers. + */ +void +intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb) +{ + struct intel_context *intel = intel_context(ctx); + struct pipe_region *colorRegion, *depthRegion = NULL; + struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; + + if (!fb) { + /* this can happen during the initial context initialization */ + return; + } + + /* Do this here, not core Mesa, since this function is called from + * many places within the driver. + */ + if (ctx->NewState & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { + /* this updates the DrawBuffer->_NumColorDrawBuffers fields, etc */ + _mesa_update_framebuffer(ctx); + /* this updates the DrawBuffer's Width/Height if it's a FBO */ + _mesa_update_draw_buffer_bounds(ctx); + } + + if (fb->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { + /* this may occur when we're called by glBindFrameBuffer() during + * the process of someone setting up renderbuffers, etc. + */ + /*_mesa_debug(ctx, "DrawBuffer: incomplete user FBO\n");*/ + return; + } + + if (fb->Name) + intel_validate_paired_depth_stencil(ctx, fb); + + /* + * How many color buffers are we drawing into? + */ + if (fb->_NumColorDrawBuffers[0] != 1) { + /* writing to 0 or 2 or 4 color buffers */ + /*_mesa_debug(ctx, "Software rendering\n");*/ + FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); + } + else { + /* draw to exactly one color buffer */ + /*_mesa_debug(ctx, "Hardware rendering\n");*/ + FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); + } + + /* + * Get the intel_renderbuffer for the colorbuffer we're drawing into. + * And set up cliprects. + */ + { + struct intel_renderbuffer *irb; + intelSetRenderbufferClipRects(intel); + irb = intel_renderbuffer(fb->_ColorDrawBuffers[0][0]); + colorRegion = (irb && irb->region) ? irb->region : NULL; + } + + /* Update culling direction which changes depending on the + * orientation of the buffer: + */ + if (ctx->Driver.FrontFace) + ctx->Driver.FrontFace(ctx, ctx->Polygon.FrontFace); + else + ctx->NewState |= _NEW_POLYGON; + + if (!colorRegion) { + FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE); + } + else { + FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE); + } + + /*** + *** Get depth buffer region and check if we need a software fallback. + *** Note that the depth buffer is usually a DEPTH_STENCIL buffer. + ***/ + if (fb->_DepthBuffer && fb->_DepthBuffer->Wrapped) { + irbDepth = intel_renderbuffer(fb->_DepthBuffer->Wrapped); + if (irbDepth && irbDepth->region) { + FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); + depthRegion = irbDepth->region; + } + else { + FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_TRUE); + depthRegion = NULL; + } + } + else { + /* not using depth buffer */ + FALLBACK(intel, INTEL_FALLBACK_DEPTH_BUFFER, GL_FALSE); + depthRegion = NULL; + } + + /*** + *** Stencil buffer + *** This can only be hardware accelerated if we're using a + *** combined DEPTH_STENCIL buffer (for now anyway). + ***/ + if (fb->_StencilBuffer && fb->_StencilBuffer->Wrapped) { + irbStencil = intel_renderbuffer(fb->_StencilBuffer->Wrapped); + if (irbStencil && irbStencil->region) { + ASSERT(irbStencil->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); + /* need to re-compute stencil hw state */ +// ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); + if (!depthRegion) + depthRegion = irbStencil->region; + } + else { + FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_TRUE); + } + } + else { + /* XXX FBO: instead of FALSE, pass ctx->Stencil.Enabled ??? */ + FALLBACK(intel, INTEL_FALLBACK_STENCIL_BUFFER, GL_FALSE); + /* need to re-compute stencil hw state */ +// ctx->Driver.Enable(ctx, GL_STENCIL_TEST, ctx->Stencil.Enabled); + } + + + /** + ** Release old regions, reference new regions + **/ + + // intel->vtbl.set_draw_region(intel, colorRegion, depthRegion); + + /* update viewport since it depends on window size */ +// ctx->Driver.Viewport(ctx, ctx->Viewport.X, ctx->Viewport.Y, +// ctx->Viewport.Width, ctx->Viewport.Height); + + /* Update hardware scissor */ +// ctx->Driver.Scissor(ctx, ctx->Scissor.X, ctx->Scissor.Y, +// ctx->Scissor.Width, ctx->Scissor.Height); +} + + +static void +intelDrawBuffer(GLcontext * ctx, GLenum mode) +{ + intel_draw_buffer(ctx, ctx->DrawBuffer); +} + + +static void +intelReadBuffer(GLcontext * ctx, GLenum mode) +{ + if (ctx->ReadBuffer == ctx->DrawBuffer) { + /* This will update FBO completeness status. + * A framebuffer will be incomplete if the GL_READ_BUFFER setting + * refers to a missing renderbuffer. Calling glReadBuffer can set + * that straight and can make the drawing buffer complete. + */ + intel_draw_buffer(ctx, ctx->DrawBuffer); + } + /* Generally, functions which read pixels (glReadPixels, glCopyPixels, etc) + * reference ctx->ReadBuffer and do appropriate state checks. + */ +} + + +void +intelInitBufferFuncs(struct dd_function_table *functions) +{ + functions->DrawBuffer = intelDrawBuffer; + functions->ReadBuffer = intelReadBuffer; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_buffers.h b/src/mesa/drivers/dri/intel_winsys/intel_buffers.h new file mode 100644 index 00000000000..5834e395010 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_buffers.h @@ -0,0 +1,55 @@ +/************************************************************************** + * + * 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_BUFFERS_H +#define INTEL_BUFFERS_H + + +struct intel_context; +struct intel_framebuffer; + + +extern GLboolean +intel_intersect_cliprects(drm_clip_rect_t * dest, + const drm_clip_rect_t * a, + const drm_clip_rect_t * b); + +extern struct pipe_region *intel_readbuf_region(struct intel_context *intel); + +extern struct pipe_region *intel_drawbuf_region(struct intel_context *intel); + +extern void intel_wait_flips(struct intel_context *intel, GLuint batch_flags); + +extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); + +extern void intelWindowMoved(struct intel_context *intel); + +extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb); + +extern void intelInitBufferFuncs(struct dd_function_table *functions); + +#endif /* INTEL_BUFFERS_H */ diff --git a/src/mesa/drivers/dri/intel_winsys/intel_context.c b/src/mesa/drivers/dri/intel_winsys/intel_context.c new file mode 100644 index 00000000000..e6f0d4a0fa9 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_context.c @@ -0,0 +1,717 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "glheader.h" +#include "context.h" +#include "matrix.h" +#include "simple_list.h" +#include "extensions.h" +#include "framebuffer.h" +#include "imports.h" +#include "points.h" + +#include "tnl/tnl.h" + +#include "tnl/t_pipeline.h" +#include "tnl/t_vertex.h" + +#include "drivers/common/driverfuncs.h" + +#include "intel_screen.h" + +#include "i830_dri.h" + +#include "intel_buffers.h" +/*#include "intel_tex.h"*/ +#include "intel_ioctl.h" +#include "intel_batchbuffer.h" +#include "intel_blit.h" +/* +#include "intel_buffer_objects.h" +*/ +#include "intel_fbo.h" +#include "intel_tex_layout.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" + +#include "drirenderbuffer.h" +#include "vblank.h" +#include "utils.h" +#include "xmlpool.h" /* for symbolic values of enum-type options */ + +#include "pipe/p_context.h" + + + +#ifndef INTEL_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" + + +#define DRIVER_DATE "20070731" + +_glthread_Mutex lockMutex; +static GLboolean lockMutexInit = GL_FALSE; + + +static const GLubyte * +intelGetString(GLcontext * ctx, GLenum name) +{ + const char *chipset; + static char buffer[128]; + + switch (name) { + case GL_VENDOR: + return (GLubyte *) "Tungsten Graphics, Inc"; + break; + + case GL_RENDERER: + switch (intel_context(ctx)->intelScreen->deviceID) { + case PCI_CHIP_845_G: + chipset = "Intel(R) 845G"; + break; + case PCI_CHIP_I830_M: + chipset = "Intel(R) 830M"; + break; + case PCI_CHIP_I855_GM: + chipset = "Intel(R) 852GM/855GM"; + break; + case PCI_CHIP_I865_G: + chipset = "Intel(R) 865G"; + break; + case PCI_CHIP_I915_G: + chipset = "Intel(R) 915G"; + break; + case PCI_CHIP_I915_GM: + chipset = "Intel(R) 915GM"; + break; + case PCI_CHIP_I945_G: + chipset = "Intel(R) 945G"; + break; + case PCI_CHIP_I945_GM: + chipset = "Intel(R) 945GM"; + break; + case PCI_CHIP_I945_GME: + chipset = "Intel(R) 945GME"; + break; + case PCI_CHIP_G33_G: + chipset = "Intel(R) G33"; + break; + case PCI_CHIP_Q35_G: + chipset = "Intel(R) Q35"; + break; + case PCI_CHIP_Q33_G: + chipset = "Intel(R) Q33"; + break; + default: + chipset = "Unknown Intel Chipset"; + break; + } + + (void) driGetRendererString(buffer, chipset, DRIVER_DATE, 0); + return (GLubyte *) buffer; + + default: + return NULL; + } +} + + +/** + * 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}, +#if 1 /* XXX FBO temporary? */ + {"GL_EXT_packed_depth_stencil", NULL}, +#endif + {"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} +}; + + + + +static const struct dri_debug_control debug_control[] = { + {"tex", DEBUG_TEXTURE}, + {"state", DEBUG_STATE}, + {"ioctl", DEBUG_IOCTL}, + {"blit", DEBUG_BLIT}, + {"mip", DEBUG_MIPTREE}, + {"fall", DEBUG_FALLBACKS}, + {"verb", DEBUG_VERBOSE}, + {"bat", DEBUG_BATCH}, + {"pix", DEBUG_PIXEL}, + {"buf", DEBUG_BUFMGR}, + {"reg", DEBUG_REGION}, + {"fbo", DEBUG_FBO}, + {"lock", DEBUG_LOCK}, + {NULL, 0} +}; + + +static void +intelInvalidateState(GLcontext * ctx, GLuint new_state) +{ + _vbo_InvalidateState(ctx, new_state); + _tnl_InvalidateState(ctx, new_state); + _tnl_invalidate_vertex_state(ctx, new_state); + + st_invalidate_state( ctx, new_state ); +} + + +void +intelFlush(GLcontext * ctx) +{ + struct intel_context *intel = intel_context(ctx); + + INTEL_FIREVERTICES(intel); + + if (intel->batch->map != intel->batch->ptr) + intel_batchbuffer_flush(intel->batch); + + /* XXX: Need to do an MI_FLUSH here. + */ +} + + +/** + * Check if we need to rotate/warp the front color buffer to the + * rotated screen. We generally need to do this when we get a glFlush + * or glFinish after drawing to the front color buffer. + * If no rotation, just copy the private fake front buffer to the real one. + */ +static void +intelCheckFrontUpdate(GLcontext * ctx) +{ + struct intel_context *intel = intel_context(ctx); + /* rely on _ColorDrawBufferMask being kept up to date by mesa + even for window-fbos. */ + /* not sure. Might need that for all masks including + BUFFER_BIT_FRONT_LEFT maybe? */ + if (intel->ctx.DrawBuffer->_ColorDrawBufferMask[0] == + BUFFER_BIT_FRONT_LEFT) { + __DRIdrawablePrivate *dPriv = intel->driDrawable; + intelCopyBuffer(dPriv, NULL); + } +} + + +/** + * Called via glFlush. + */ +static void +intelglFlush(GLcontext * ctx) +{ + intelFlush(ctx); + intelCheckFrontUpdate(ctx); +} + +void +intelFinish(GLcontext * ctx) +{ + struct intel_context *intel = intel_context(ctx); + intelFlush(ctx); + if (intel->batch->last_fence) { + driFenceFinish(intel->batch->last_fence, + 0, GL_FALSE); + driFenceUnReference(intel->batch->last_fence); + intel->batch->last_fence = NULL; + } + intelCheckFrontUpdate(ctx); +} + + +static void +intelInitDriverFunctions(struct dd_function_table *functions) +{ + _mesa_init_driver_functions(functions); + + functions->Flush = intelglFlush; + functions->Finish = intelFinish; + functions->GetString = intelGetString; + functions->UpdateState = intelInvalidateState; + + /* + intelInitTextureFuncs(functions); + */ + intelInitBufferFuncs(functions); + + st_init_driver_functions(functions); +} + + + +GLboolean +intelCreateContext(const __GLcontextModes * mesaVis, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate) +{ + struct dd_function_table functions; + + struct intel_context *intel = CALLOC_STRUCT(intel_context); + GLcontext *ctx = &intel->ctx; + + GLcontext *shareCtx = (GLcontext *) sharedContextPrivate; + __DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv; + intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; + drmI830Sarea *saPriv = intelScreen->sarea; + int fthrottle_mode; + GLboolean havePools; + + intelInitDriverFunctions(&functions); + + if (!_mesa_initialize_context(&intel->ctx, + mesaVis, shareCtx, + &functions, (void *) intel)) + return GL_FALSE; + + driContextPriv->driverPrivate = intel; + intel->intelScreen = intelScreen; + intel->driScreen = sPriv; + intel->sarea = saPriv; + + if (!lockMutexInit) { + lockMutexInit = GL_TRUE; + _glthread_INIT_MUTEX(lockMutex); + } + + driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache, + intel->driScreen->myNum, "i915"); + + + /* Initialize the software rasterizer and helper modules. */ + _vbo_CreateContext(ctx); + _tnl_CreateContext(ctx); + + /* + * Pipe-related setup + */ + st_create_context( &intel->ctx, + intel_create_softpipe( intel ) ); + + /* KW: Not sure I like this - we should only be talking to the + * state_tracker. The pipe code will need some way of talking to + * us, eg for batchbuffer ioctls, and there will need to be a + * buffer manager interface. So, this is a temporary hack, right? + * BP: Yes, a temporary hack so we can make jumps between old/new code. + */ + intel->pipe = intel->ctx.st->pipe; +// intel->pipe->screen = intelScreen; +// intel->pipe->glctx = ctx; +// intel_init_region_functions(intel->pipe); + + 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: + intel->pipe->mipmap_tree_layout = i945_miptree_layout; + break; + case PCI_CHIP_I915_G: + case PCI_CHIP_I915_GM: + case PCI_CHIP_I830_M: + case PCI_CHIP_I855_GM: + case PCI_CHIP_I865_G: + intel->pipe->mipmap_tree_layout = i915_miptree_layout; + default: + assert(0); /*FIX*/ + } + + + /* + * memory pools + */ + DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext); + havePools = intelCreatePools(intelScreen); + 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; + + TNL_CONTEXT(ctx)->Driver.RunPipeline = _tnl_run_pipeline; + + + + fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode"); + intel->iw.irq_seq = -1; + intel->irqsEmitted = 0; + + /* Disable imaging extension until convolution is working in + * teximage paths: + */ + driInitExtensions(ctx, card_extensions, +/* GL_TRUE, */ + GL_FALSE); + + + intel->batch = intel_batchbuffer_alloc(intel); + intel->last_swap_fence = NULL; + intel->first_swap_fence = NULL; + + intel_fbo_init(intel); + + if (intel->ctx.Mesa_DXTn) { + _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); + _mesa_enable_extension(ctx, "GL_S3_s3tc"); + } + else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) { + _mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc"); + } + +#if DO_DEBUG + INTEL_DEBUG = driParseDebugString(getenv("INTEL_DEBUG"), debug_control); +#endif + + + return GL_TRUE; +} + +void +intelDestroyContext(__DRIcontextPrivate * driContextPriv) +{ + struct intel_context *intel = + (struct intel_context *) driContextPriv->driverPrivate; + + assert(intel); /* should never be null */ + if (intel) { + GLboolean release_texture_heaps; + + INTEL_FIREVERTICES(intel); + + //intel->vtbl.destroy(intel); + + release_texture_heaps = (intel->ctx.Shared->RefCount == 1); + _tnl_DestroyContext(&intel->ctx); + _vbo_DestroyContext(&intel->ctx); + + 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 (release_texture_heaps) { + /* This share group is about to go away, free our private + * texture object data. + */ + if (INTEL_DEBUG & DEBUG_TEXTURE) + fprintf(stderr, "do something to free texture heaps\n"); + } + + /* free the Mesa context */ + _mesa_free_context_data(&intel->ctx); + } +} + +GLboolean +intelUnbindContext(__DRIcontextPrivate * driContextPriv) +{ + struct intel_context *intel = (struct intel_context *) driContextPriv->driverPrivate; + /* XXX UnbindContext is called AFTER the new context is made current. + Hopefully shouldn't be a problem ? */ + FLUSH_VERTICES((&intel->ctx), 0); + intelFlush(&intel->ctx); + return GL_TRUE; +} + +GLboolean +intelMakeCurrent(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv) +{ + +#if 0 + if (driDrawPriv) { + fprintf(stderr, "x %d, y %d, width %d, height %d\n", + driDrawPriv->x, driDrawPriv->y, driDrawPriv->w, driDrawPriv->h); + } +#endif + + if (driContextPriv) { + struct intel_context *intel = + (struct intel_context *) driContextPriv->driverPrivate; + struct intel_framebuffer *intel_fb = + (struct intel_framebuffer *) driDrawPriv->driverPrivate; + GLframebuffer *readFb = (GLframebuffer *) driReadPriv->driverPrivate; + + /* this is a hack so we have a valid context when the region allocation + is done. Need a per-screen context? */ + intel->intelScreen->dummyctxptr = intel; + + /* update GLframebuffer size to match window if needed */ + driUpdateFramebufferSize(&intel->ctx, driDrawPriv); + + if (driReadPriv != driDrawPriv) { + driUpdateFramebufferSize(&intel->ctx, driReadPriv); + } + + _mesa_make_current(&intel->ctx, &intel_fb->Base, readFb); + + /* The drawbuffer won't always be updated by _mesa_make_current: + */ + if (intel->ctx.DrawBuffer == &intel_fb->Base) { + + if (intel->driDrawable != driDrawPriv) { + if (driDrawPriv->pdraw->swap_interval == (unsigned)-1) { + int i; + + intel_fb->vblank_flags = driGetDefaultVBlankFlags(&intel->optionCache); + + (*dri_interface->getUST) (&intel_fb->swap_ust); + driDrawableInitVBlank(driDrawPriv, intel_fb->vblank_flags, + &intel_fb->vbl_seq); + intel_fb->vbl_waited = intel_fb->vbl_seq; + + for (i = 0; i < 2; i++) { + if (intel_fb->color_rb[i]) + intel_fb->color_rb[i]->vbl_pending = intel_fb->vbl_seq; + } + } + } + } + + if ((intel->driDrawable != driDrawPriv) || + (intel->lastStamp != driDrawPriv->lastStamp)) { + intel->driDrawable = driDrawPriv; + intelWindowMoved(intel); + intel->lastStamp = driDrawPriv->lastStamp; + } + + } + else { + _mesa_make_current(NULL, NULL, NULL); + } + + return GL_TRUE; +} + +static void +intelContendedLock(struct intel_context *intel, GLuint flags) +{ + __DRIdrawablePrivate *dPriv = intel->driDrawable; + __DRIscreenPrivate *sPriv = intel->driScreen; + intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; + drmI830Sarea *sarea = intel->sarea; + + drmGetLock(intel->driFd, intel->hHWContext, flags); + + if (INTEL_DEBUG & DEBUG_LOCK) + _mesa_printf("%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); + } + +#if 0 + if (sarea->width != intel->width || + sarea->height != intel->height || + sarea->rotation != intel->current_rotation) { + int numClipRects = intel->numClipRects; + + /* + * FIXME: Really only need to do this when drawing to a + * common back- or front buffer. + */ + + /* + * This will essentially drop the outstanding batchbuffer on the floor. + */ + intel->numClipRects = 0; + + INTEL_FIREVERTICES(intel); + + if (intel->batch->map != intel->batch->ptr) + intel_batchbuffer_flush(intel->batch); + + intel->numClipRects = numClipRects; + + /* force window update */ + intel->lastStamp = 0; + + intel->width = sarea->width; + intel->height = sarea->height; + intel->current_rotation = sarea->rotation; + } +#endif +} + + +/* Lock the hardware and validate our state. + */ +void LOCK_HARDWARE( struct intel_context *intel ) +{ + char __ret=0; + struct intel_framebuffer *intel_fb = NULL; + struct intel_renderbuffer *intel_rb = NULL; + _glthread_LOCK_MUTEX(lockMutex); + assert(!intel->locked); + + if (intel->driDrawable) { + intel_fb = intel->driDrawable->driverPrivate; + + if (intel_fb) + intel_rb = + intel_get_renderbuffer(&intel_fb->Base, + intel_fb->Base._ColorDrawBufferMask[0] == + BUFFER_BIT_FRONT_LEFT ? BUFFER_FRONT_LEFT : + BUFFER_BACK_LEFT); + } + + if (intel_rb && intel_fb->vblank_flags && + !(intel_fb->vblank_flags & VBLANK_FLAG_NO_IRQ) && + (intel_fb->vbl_waited - intel_rb->vbl_pending) > (1<<23)) { + drmVBlank vbl; + + vbl.request.type = DRM_VBLANK_ABSOLUTE; + + if ( intel_fb->vblank_flags & VBLANK_FLAG_SECONDARY ) { + vbl.request.type |= DRM_VBLANK_SECONDARY; + } + + vbl.request.sequence = intel_rb->vbl_pending; + drmWaitVBlank(intel->driFd, &vbl); + intel_fb->vbl_waited = vbl.reply.sequence; + } + + DRM_CAS(intel->driHwLock, intel->hHWContext, + (DRM_LOCK_HELD|intel->hHWContext), __ret); + + if (__ret) + intelContendedLock( intel, 0 ); + + if (INTEL_DEBUG & DEBUG_LOCK) + _mesa_printf("%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); + + if (INTEL_DEBUG & DEBUG_LOCK) + _mesa_printf("%s - unlocked\n", __progname); +} + diff --git a/src/mesa/drivers/dri/intel_winsys/intel_context.h b/src/mesa/drivers/dri/intel_winsys/intel_context.h new file mode 100644 index 00000000000..1a4e7ca1cd4 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_context.h @@ -0,0 +1,225 @@ +/************************************************************************** + * + * 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 INTELCONTEXT_INC +#define INTELCONTEXT_INC + + + +#include "mtypes.h" +#include "drm.h" +#include "mm.h" +#include "texmem.h" + +#include "intel_screen.h" +#include "i915_drm.h" +#include "i830_common.h" + + +#define DV_PF_555 (1<<8) +#define DV_PF_565 (2<<8) +#define DV_PF_8888 (3<<8) + +struct pipe_context; +struct pipe_region; +struct intel_context; +struct _DriBufferObject; + + +#define INTEL_WRITE_PART 0x1 +#define INTEL_WRITE_FULL 0x2 +#define INTEL_READ 0x4 + + + +#define INTEL_MAX_FIXUP 64 + +struct intel_context +{ + GLcontext ctx; /* the parent class */ + + struct pipe_context *pipe; + + GLint refcount; + + struct _DriFenceObject *last_swap_fence; + struct _DriFenceObject *first_swap_fence; + + struct intel_batchbuffer *batch; + + + GLboolean locked; + char *prevLockFile; + int prevLockLine; + + GLuint ClearColor565; + GLuint ClearColor8888; + + + /* These refer to the current drawing buffer: + */ + GLuint numClipRects; /**< cliprects for drawing */ + drm_clip_rect_t *pClipRects; + drm_clip_rect_t fboRect; /**< cliprect for rendering */ + + GLuint irqsEmitted; + drm_i915_irq_wait_t iw; + + drm_context_t hHWContext; + drmLock *driHwLock; + int driFd; + + __DRIdrawablePrivate *driDrawable; + __DRIscreenPrivate *driScreen; + intelScreenPrivate *intelScreen; + drmI830Sarea *sarea; + + GLuint lastStamp; + + /** + * Configuration cache + */ + driOptionCache optionCache; +}; + +/* These are functions now: + */ +void LOCK_HARDWARE( struct intel_context *intel ); +void UNLOCK_HARDWARE( struct intel_context *intel ); + +extern char *__progname; + +/* Will become a call into state_tracker: + */ +#define INTEL_FIREVERTICES(intel) + +/* ================================================================ + * Color packing: + */ + +#define INTEL_PACKCOLOR4444(r,g,b,a) \ + ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) + +#define INTEL_PACKCOLOR1555(r,g,b,a) \ + ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define INTEL_PACKCOLOR565(r,g,b) \ + ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) + +#define INTEL_PACKCOLOR8888(r,g,b,a) \ + ((a<<24) | (r<<16) | (g<<8) | b) + + + + +/* ================================================================ + * Debugging: + */ +#define DO_DEBUG 0 +#if DO_DEBUG +extern int INTEL_DEBUG; +#else +#define INTEL_DEBUG 0 +#endif + +#define DEBUG_TEXTURE 0x1 +#define DEBUG_STATE 0x2 +#define DEBUG_IOCTL 0x4 +#define DEBUG_BLIT 0x8 +#define DEBUG_MIPTREE 0x10 +#define DEBUG_FALLBACKS 0x20 +#define DEBUG_VERBOSE 0x40 +#define DEBUG_BATCH 0x80 +#define DEBUG_PIXEL 0x100 +#define DEBUG_BUFMGR 0x200 +#define DEBUG_REGION 0x400 +#define DEBUG_FBO 0x800 +#define DEBUG_LOCK 0x1000 + +#define DBG(...) do { if (INTEL_DEBUG & FILE_DEBUG_FLAG) _mesa_printf(__VA_ARGS__); } while(0) + + +#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 + + +/* ================================================================ + * intel_context.c: + */ + +extern GLboolean intelInitContext(struct intel_context *intel, + const __GLcontextModes * mesaVis, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate, + struct dd_function_table *functions); + +extern void intelGetLock(struct intel_context *intel, GLuint flags); + +extern void intelFinish(GLcontext * ctx); +extern void intelFlush(GLcontext * ctx); + + +/* ================================================================ + * intel_softpipe.c: + */ + +struct pipe_context * +intel_create_softpipe( struct intel_context *intel ); + + +#define MI_BATCH_BUFFER_END (0xA<<23) + +#define FALLBACK( ctx, bit, mode ) + +/*====================================================================== + * Inline conversion functions. + * These are better-typed than the macros used previously: + */ +static INLINE struct intel_context * +intel_context(GLcontext * ctx) +{ + return (struct intel_context *) ctx; +} + +extern struct intel_renderbuffer *intel_renderbuffer(struct gl_renderbuffer + *rb); + +extern void intel_init_region_functions(struct pipe_context *pipe); + + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.c b/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.c new file mode 100644 index 00000000000..81e09698cc5 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.c @@ -0,0 +1,282 @@ +/************************************************************************** + * + * 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 "glheader.h" +#include "imports.h" +#include "context.h" +#include "depthstencil.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "hash.h" +#include "mtypes.h" +#include "renderbuffer.h" + +#include "intel_context.h" +#include "intel_fbo.h" +#include "intel_depthstencil.h" + +#include "pipe/p_context.h" + +/** + * The GL_EXT_framebuffer_object allows the user to create their own + * framebuffer objects consisting of color renderbuffers (0 or more), + * depth renderbuffers (0 or 1) and stencil renderbuffers (0 or 1). + * + * The spec considers depth and stencil renderbuffers to be totally independent + * buffers. In reality, most graphics hardware today uses a combined + * depth+stencil buffer (one 32-bit pixel = 24 bits of Z + 8 bits of stencil). + * + * This causes difficulty because the user may create some number of depth + * renderbuffers and some number of stencil renderbuffers and bind them + * together in framebuffers in any combination. + * + * This code manages all that. + * + * 1. Depth renderbuffers are always allocated in hardware as 32bpp + * GL_DEPTH24_STENCIL8 buffers. + * + * 2. Stencil renderbuffers are initially allocated in software as 8bpp + * GL_STENCIL_INDEX8 buffers. + * + * 3. Depth and Stencil renderbuffers use the PairedStencil and PairedDepth + * fields (respectively) to indicate if the buffer's currently paired + * with another stencil or depth buffer (respectively). + * + * 4. When a depth and stencil buffer are initially both attached to the + * current framebuffer, we merge the stencil buffer values into the + * depth buffer (really a depth+stencil buffer). The then hardware uses + * the combined buffer. + * + * 5. Whenever a depth or stencil buffer is reallocated (with + * glRenderbufferStorage) we undo the pairing and copy the stencil values + * from the combined depth/stencil buffer back to the stencil-only buffer. + * + * 6. We also undo the pairing when we find a change in buffer bindings. + * + * 7. If a framebuffer is only using a depth renderbuffer (no stencil), we + * just use the combined depth/stencil buffer and ignore the stencil values. + * + * 8. If a framebuffer is only using a stencil renderbuffer (no depth) we have + * to promote the 8bpp software stencil buffer to a 32bpp hardware + * depth+stencil buffer. + * + */ + + + +static void +map_regions(GLcontext * ctx, + struct intel_renderbuffer *depthRb, + struct intel_renderbuffer *stencilRb) +{ + struct intel_context *intel = intel_context(ctx); + if (depthRb && depthRb->region) { + intel->pipe->region_map(intel->pipe, depthRb->region); + depthRb->pfMap = depthRb->region->map; + depthRb->pfPitch = depthRb->region->pitch; + } + if (stencilRb && stencilRb->region) { + intel->pipe->region_map(intel->pipe, stencilRb->region); + stencilRb->pfMap = stencilRb->region->map; + stencilRb->pfPitch = stencilRb->region->pitch; + } +} + +static void +unmap_regions(GLcontext * ctx, + struct intel_renderbuffer *depthRb, + struct intel_renderbuffer *stencilRb) +{ + struct intel_context *intel = intel_context(ctx); + if (depthRb && depthRb->region) { + intel->pipe->region_unmap(intel->pipe, depthRb->region); + depthRb->pfMap = NULL; + depthRb->pfPitch = 0; + } + if (stencilRb && stencilRb->region) { + intel->pipe->region_unmap(intel->pipe, stencilRb->region); + stencilRb->pfMap = NULL; + stencilRb->pfPitch = 0; + } +} + + + +/** + * Undo the pairing/interleaving between depth and stencil buffers. + * irb should be a depth/stencil or stencil renderbuffer. + */ +void +intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb) +{ + if (irb->PairedStencil) { + /* irb is a depth/stencil buffer */ + struct gl_renderbuffer *stencilRb; + struct intel_renderbuffer *stencilIrb; + + ASSERT(irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + + stencilRb = _mesa_lookup_renderbuffer(ctx, irb->PairedStencil); + stencilIrb = intel_renderbuffer(stencilRb); + if (stencilIrb) { + /* need to extract stencil values from the depth buffer */ + ASSERT(stencilIrb->PairedDepth == irb->Base.Name); + map_regions(ctx, irb, stencilIrb); + _mesa_extract_stencil(ctx, &irb->Base, &stencilIrb->Base); + unmap_regions(ctx, irb, stencilIrb); + stencilIrb->PairedDepth = 0; + } + irb->PairedStencil = 0; + } + else if (irb->PairedDepth) { + /* irb is a stencil buffer */ + struct gl_renderbuffer *depthRb; + struct intel_renderbuffer *depthIrb; + + ASSERT(irb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || + irb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + + depthRb = _mesa_lookup_renderbuffer(ctx, irb->PairedDepth); + depthIrb = intel_renderbuffer(depthRb); + if (depthIrb) { + /* need to extract stencil values from the depth buffer */ + ASSERT(depthIrb->PairedStencil == irb->Base.Name); + map_regions(ctx, depthIrb, irb); + _mesa_extract_stencil(ctx, &depthIrb->Base, &irb->Base); + unmap_regions(ctx, depthIrb, irb); + depthIrb->PairedStencil = 0; + } + irb->PairedDepth = 0; + } + else { + _mesa_problem(ctx, "Problem in undo_depth_stencil_pairing"); + } + + ASSERT(irb->PairedStencil == 0); + ASSERT(irb->PairedDepth == 0); +} + + +/** + * Examine the depth and stencil renderbuffers which are attached to the + * framebuffer. If both depth and stencil are attached, make sure that the + * renderbuffers are 'paired' (combined). If only depth or only stencil is + * attached, undo any previous pairing. + * + * Must be called if NewState & _NEW_BUFFER (when renderbuffer attachments + * change, for example). + */ +void +intel_validate_paired_depth_stencil(GLcontext * ctx, + struct gl_framebuffer *fb) +{ + struct intel_renderbuffer *depthRb, *stencilRb; + + depthRb = intel_get_renderbuffer(fb, BUFFER_DEPTH); + stencilRb = intel_get_renderbuffer(fb, BUFFER_STENCIL); + + if (depthRb && stencilRb) { + if (depthRb == stencilRb) { + /* Using a user-created combined depth/stencil buffer. + * Nothing to do. + */ + ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_STENCIL_EXT); + ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + } + else { + /* Separate depth/stencil buffers, need to interleave now */ + ASSERT(depthRb->Base._BaseFormat == GL_DEPTH_COMPONENT); + ASSERT(stencilRb->Base._BaseFormat == GL_STENCIL_INDEX); + /* may need to interleave depth/stencil now */ + if (depthRb->PairedStencil == stencilRb->Base.Name) { + /* OK, the depth and stencil buffers are already interleaved */ + ASSERT(stencilRb->PairedDepth == depthRb->Base.Name); + } + else { + /* need to setup new pairing/interleaving */ + if (depthRb->PairedStencil) { + intel_unpair_depth_stencil(ctx, depthRb); + } + if (stencilRb->PairedDepth) { + intel_unpair_depth_stencil(ctx, stencilRb); + } + + ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + ASSERT(stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT || + stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + + /* establish new pairing: interleave stencil into depth buffer */ + map_regions(ctx, depthRb, stencilRb); + _mesa_insert_stencil(ctx, &depthRb->Base, &stencilRb->Base); + unmap_regions(ctx, depthRb, stencilRb); + depthRb->PairedStencil = stencilRb->Base.Name; + stencilRb->PairedDepth = depthRb->Base.Name; + } + + } + } + else if (depthRb) { + /* Depth buffer but no stencil buffer. + * We'll use a GL_DEPTH24_STENCIL8 buffer and ignore the stencil bits. + */ + /* can't assert this until storage is allocated: + ASSERT(depthRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + */ + /* intel_undo any previous pairing */ + if (depthRb->PairedStencil) { + intel_unpair_depth_stencil(ctx, depthRb); + } + } + else if (stencilRb) { + /* Stencil buffer but no depth buffer. + * Since h/w doesn't typically support just 8bpp stencil w/out Z, + * we'll use a GL_DEPTH24_STENCIL8 buffer and ignore the depth bits. + */ + /* undo any previous pairing */ + if (stencilRb->PairedDepth) { + intel_unpair_depth_stencil(ctx, stencilRb); + } + if (stencilRb->Base._ActualFormat == GL_STENCIL_INDEX8_EXT) { + /* promote buffer to GL_DEPTH24_STENCIL8 for hw rendering */ + _mesa_promote_stencil(ctx, &stencilRb->Base); + ASSERT(stencilRb->Base._ActualFormat == GL_DEPTH24_STENCIL8_EXT); + } + } + + /* Finally, update the fb->_DepthBuffer and fb->_StencilBuffer fields */ + _mesa_update_depth_buffer(ctx, fb, BUFFER_DEPTH); + if (depthRb && depthRb->PairedStencil) + _mesa_update_stencil_buffer(ctx, fb, BUFFER_DEPTH); + else + _mesa_update_stencil_buffer(ctx, fb, BUFFER_STENCIL); + + + /* The hardware should use fb->Attachment[BUFFER_DEPTH].Renderbuffer + * first, if present, then fb->Attachment[BUFFER_STENCIL].Renderbuffer + * if present. + */ +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.h b/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.h new file mode 100644 index 00000000000..2d3fc48b3a3 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_depthstencil.h @@ -0,0 +1,14 @@ + +#ifndef INTEL_DEPTH_STENCIL_H +#define INTEL_DEPTH_STENCIL_H + + +extern void +intel_unpair_depth_stencil(GLcontext * ctx, struct intel_renderbuffer *irb); + +extern void +intel_validate_paired_depth_stencil(GLcontext * ctx, + struct gl_framebuffer *fb); + + +#endif /* INTEL_DEPTH_STENCIL_H */ diff --git a/src/mesa/drivers/dri/intel_winsys/intel_fbo.c b/src/mesa/drivers/dri/intel_winsys/intel_fbo.c new file mode 100644 index 00000000000..0b6c6a94ee5 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_fbo.c @@ -0,0 +1,629 @@ +/************************************************************************** + * + * 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 "imports.h" +#include "mtypes.h" +#include "fbobject.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "context.h" +#include "texformat.h" +#include "texrender.h" + +#include "intel_context.h" +#include "intel_buffers.h" +#include "intel_depthstencil.h" +#include "intel_fbo.h" +#include "state_tracker/st_mipmap_tree.h" +/*#include "intel_tex.h"*/ + +#include "pipe/p_context.h" + +#define FILE_DEBUG_FLAG DEBUG_FBO + +#define INTEL_RB_CLASS 0x12345678 + + +/* XXX FBO: move this to intel_context.h (inlined) */ +/** + * Return a gl_renderbuffer ptr casted to intel_renderbuffer. + * NULL will be returned if the rb isn't really an intel_renderbuffer. + * This is determiend by checking the ClassID. + */ +struct intel_renderbuffer * +intel_renderbuffer(struct gl_renderbuffer *rb) +{ + struct intel_renderbuffer *irb = (struct intel_renderbuffer *) rb; + if (irb && irb->Base.ClassID == INTEL_RB_CLASS) { + /*_mesa_warning(NULL, "Returning non-intel Rb\n");*/ + return irb; + } + else + return NULL; +} + + +struct intel_renderbuffer * +intel_get_renderbuffer(struct gl_framebuffer *fb, GLuint attIndex) +{ + return intel_renderbuffer(fb->Attachment[attIndex].Renderbuffer); +} + + +void +intel_flip_renderbuffers(struct intel_framebuffer *intel_fb) +{ + int current_page = intel_fb->pf_current_page; + int next_page = (current_page + 1) % intel_fb->pf_num_pages; + struct gl_renderbuffer *tmp_rb; + + /* Exchange renderbuffers if necessary but make sure their reference counts + * are preserved. + */ + if (intel_fb->color_rb[current_page] && + intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer != + &intel_fb->color_rb[current_page]->Base) { + tmp_rb = NULL; + _mesa_reference_renderbuffer(&tmp_rb, + intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer); + tmp_rb = &intel_fb->color_rb[current_page]->Base; + _mesa_reference_renderbuffer( + &intel_fb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer, tmp_rb); + _mesa_reference_renderbuffer(&tmp_rb, NULL); + } + + if (intel_fb->color_rb[next_page] && + intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer != + &intel_fb->color_rb[next_page]->Base) { + tmp_rb = NULL; + _mesa_reference_renderbuffer(&tmp_rb, + intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer); + tmp_rb = &intel_fb->color_rb[next_page]->Base; + _mesa_reference_renderbuffer( + &intel_fb->Base.Attachment[BUFFER_BACK_LEFT].Renderbuffer, tmp_rb); + _mesa_reference_renderbuffer(&tmp_rb, NULL); + } +} + + +struct pipe_region * +intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) +{ + struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); + + if (irb) + return irb->region; + else + return NULL; +} + + + +/** + * Create a new framebuffer object. + */ +static struct gl_framebuffer * +intel_new_framebuffer(GLcontext * ctx, GLuint name) +{ + /* Only drawable state in intel_framebuffer at this time, just use Mesa's + * class + */ + return _mesa_new_framebuffer(ctx, name); +} + + +static void +intel_delete_renderbuffer(struct gl_renderbuffer *rb) +{ + GET_CURRENT_CONTEXT(ctx); + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + + ASSERT(irb); + + DBG("freeing renderbuffer\n"); + + if (irb->PairedStencil || irb->PairedDepth) { + intel_unpair_depth_stencil(ctx, irb); + } + + if (intel && irb->region) { + intel->pipe->region_release(intel->pipe, &irb->region); + } + + _mesa_free(irb); +} + + + +/** + * Return a pointer to a specific pixel in a renderbuffer. + */ +static void * +intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, + GLint x, GLint y) +{ + /* By returning NULL we force all software rendering to go through + * the span routines. + */ + return NULL; +} + + + +/** + * Called via glRenderbufferStorageEXT() to set the format and allocate + * storage for a user-created (or priv buffer) renderbuffer. + */ +static GLboolean +intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, + GLuint width, GLuint height) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + GLboolean softwareBuffer = GL_FALSE; + int cpp; + + switch (internalFormat) { + case GL_R3_G3_B2: + case GL_RGB4: + case GL_RGB5: + rb->_ActualFormat = GL_RGB5; + rb->DataType = GL_UNSIGNED_BYTE; + rb->RedBits = 5; + rb->GreenBits = 6; + rb->BlueBits = 5; + cpp = 2; + break; + case GL_RGB: + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + case GL_RGBA: + case GL_RGBA2: + case GL_RGBA4: + case GL_RGB5_A1: + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + rb->_ActualFormat = GL_RGBA8; + rb->DataType = GL_UNSIGNED_BYTE; + rb->RedBits = 8; + rb->GreenBits = 8; + rb->BlueBits = 8; + rb->AlphaBits = 8; + cpp = 4; + break; + case GL_STENCIL_INDEX: + case GL_STENCIL_INDEX1_EXT: + case GL_STENCIL_INDEX4_EXT: + case GL_STENCIL_INDEX8_EXT: + case GL_STENCIL_INDEX16_EXT: + /* alloc a depth+stencil buffer */ + rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; + rb->DataType = GL_UNSIGNED_INT_24_8_EXT; + rb->StencilBits = 8; + cpp = 4; + break; + case GL_DEPTH_COMPONENT16: + rb->_ActualFormat = GL_DEPTH_COMPONENT16; + rb->DataType = GL_UNSIGNED_SHORT; + rb->DepthBits = 16; + cpp = 2; + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; + rb->DataType = GL_UNSIGNED_INT_24_8_EXT; + rb->DepthBits = 24; + cpp = 4; + break; + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; + rb->DataType = GL_UNSIGNED_INT_24_8_EXT; + rb->DepthBits = 24; + rb->StencilBits = 8; + cpp = 4; + break; + default: + _mesa_problem(ctx, + "Unexpected format (%x) in intel_alloc_renderbuffer_storage", internalFormat); + return GL_FALSE; + } + + intelFlush(ctx); + + /* free old region */ + if (irb->region) { + intel->pipe->region_release(intel->pipe, &irb->region); + } + + /* allocate new memory region/renderbuffer */ + if (softwareBuffer) { + return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, + width, height); + } + else { + /* Choose a pitch to match hardware requirements: + */ + GLuint pitch = ((cpp * width + 63) & ~63) / cpp; + + /* alloc hardware renderbuffer */ + DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, + height, pitch); + + irb->region = intel->pipe->region_alloc(intel->pipe, cpp, pitch, height); + if (!irb->region) + return GL_FALSE; /* out of memory? */ + + ASSERT(irb->region->buffer); + + rb->Width = width; + rb->Height = height; + + /* update the surface's size too */ + rb->surface->width = width; + rb->surface->height = height; + rb->surface->region = irb->region; + + /* This sets the Get/PutRow/Value functions */ + // intel_set_span_functions(&irb->Base); + + return GL_TRUE; + } +} + + +static void +intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb, + GLuint width, GLuint height) +{ + struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; + int i; + + _mesa_resize_framebuffer(ctx, fb, width, height); + + fb->Initialized = GL_TRUE; /* XXX remove someday */ + + if (fb->Name != 0) { + return; + } + + /* Make sure all window system renderbuffers are up to date */ + for (i = 0; i < 3; i++) { + struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base; + + /* only resize if size is changing */ + if (rb && (rb->Width != width || rb->Height != height)) { + rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); + } + } +} + +static GLboolean +intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, + GLenum internalFormat, GLuint width, GLuint height) +{ + _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); + return GL_FALSE; +} + + + +struct intel_renderbuffer * +intel_new_renderbuffer_fb(GLuint intFormat) +{ + struct intel_renderbuffer *irb; + + irb = CALLOC_STRUCT(intel_renderbuffer); + if (!irb) { + _mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(&irb->Base, 0); + irb->Base.ClassID = INTEL_RB_CLASS; + irb->Base.InternalFormat = intFormat; + + switch (intFormat) { + case GL_RGB5: + case GL_RGBA8: + irb->Base._BaseFormat = GL_RGBA; + break; + case GL_DEPTH_COMPONENT16: + irb->Base._BaseFormat = GL_DEPTH_COMPONENT; + break; + case GL_DEPTH24_STENCIL8_EXT: + irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; + break; + default: + _mesa_problem(NULL, + "Unexpected intFormat in intel_create_renderbuffer"); + return NULL; + } + + /* intel-specific methods */ + irb->Base.Delete = intel_delete_renderbuffer; + irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; + irb->Base.GetPointer = intel_get_pointer; + /* span routines set in alloc_storage function */ + + irb->Base.surface = intel_new_surface(intFormat); + irb->Base.surface->rb = irb; + + return irb; +} + +/** + * Create a new renderbuffer object. + * Typically called via glBindRenderbufferEXT(). + */ +static struct gl_renderbuffer * +intel_new_renderbuffer(GLcontext * ctx, GLuint name) +{ + /*struct intel_context *intel = intel_context(ctx); */ + struct intel_renderbuffer *irb; + + irb = CALLOC_STRUCT(intel_renderbuffer); + if (!irb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); + return NULL; + } + + _mesa_init_renderbuffer(&irb->Base, name); + irb->Base.ClassID = INTEL_RB_CLASS; + + /* intel-specific methods */ + irb->Base.Delete = intel_delete_renderbuffer; + irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; + irb->Base.GetPointer = intel_get_pointer; + /* span routines set in alloc_storage function */ + + irb->Base.surface = intel_new_surface(0 /*unknown format*/); + irb->Base.surface->rb = irb; + + return &irb->Base; +} + + +/** + * Called via glBindFramebufferEXT(). + */ +static void +intel_bind_framebuffer(GLcontext * ctx, GLenum target, + struct gl_framebuffer *fb, struct gl_framebuffer *fbread) +{ + if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { + intel_draw_buffer(ctx, fb); + /* Integer depth range depends on depth buffer bits */ + /* XXX + */ +// ctx->Driver.DepthRange(ctx, ctx->Viewport.Near, ctx->Viewport.Far); + } + else { + /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ + } +} + + +/** + * Called via glFramebufferRenderbufferEXT(). + */ +static void +intel_framebuffer_renderbuffer(GLcontext * ctx, + struct gl_framebuffer *fb, + GLenum attachment, struct gl_renderbuffer *rb) +{ + DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); + + intelFlush(ctx); + + _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); + intel_draw_buffer(ctx, fb); +} + + +/** + * When glFramebufferTexture[123]D is called this function sets up the + * gl_renderbuffer wrapper around the texture image. + * This will have the region info needed for hardware rendering. + */ +static struct intel_renderbuffer * +intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage) +{ + const GLuint name = ~0; /* not significant, but distinct for debugging */ + struct intel_renderbuffer *irb; + + /* make an intel_renderbuffer to wrap the texture image */ + irb = CALLOC_STRUCT(intel_renderbuffer); + if (!irb) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); + return NULL; + } + + _mesa_init_renderbuffer(&irb->Base, name); + irb->Base.ClassID = INTEL_RB_CLASS; + + if (texImage->TexFormat == &_mesa_texformat_argb8888) { + irb->Base._ActualFormat = GL_RGBA8; + irb->Base._BaseFormat = GL_RGBA; + DBG("Render to RGBA8 texture OK\n"); + } + else if (texImage->TexFormat == &_mesa_texformat_rgb565) { + irb->Base._ActualFormat = GL_RGB5; + irb->Base._BaseFormat = GL_RGB; + DBG("Render to RGB5 texture OK\n"); + } + else if (texImage->TexFormat == &_mesa_texformat_z16) { + irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; + irb->Base._BaseFormat = GL_DEPTH_COMPONENT; + DBG("Render to DEPTH16 texture OK\n"); + } + else { + DBG("Render to texture BAD FORMAT %d\n", + texImage->TexFormat->MesaFormat); + _mesa_free(irb); + return NULL; + } + + irb->Base.InternalFormat = irb->Base._ActualFormat; + irb->Base.Width = texImage->Width; + irb->Base.Height = texImage->Height; + irb->Base.DataType = GL_UNSIGNED_BYTE; /* FBO XXX fix */ + irb->Base.RedBits = texImage->TexFormat->RedBits; + irb->Base.GreenBits = texImage->TexFormat->GreenBits; + irb->Base.BlueBits = texImage->TexFormat->BlueBits; + irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; + irb->Base.DepthBits = texImage->TexFormat->DepthBits; + + irb->Base.Delete = intel_delete_renderbuffer; + irb->Base.AllocStorage = intel_nop_alloc_storage; + +// intel_set_span_functions(&irb->Base); + + irb->RenderToTexture = GL_TRUE; + + return irb; +} + + +/** + * Called by glFramebufferTexture[123]DEXT() (and other places) to + * prepare for rendering into texture memory. This might be called + * many times to choose different texture levels, cube faces, etc + * before intel_finish_render_texture() is ever called. + */ +static void +intel_render_texture(GLcontext * ctx, + struct gl_framebuffer *fb, + struct gl_renderbuffer_attachment *att) +{ +#if 0 + struct intel_context *intel = intel_context(ctx); + struct gl_texture_image *newImage + = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; + struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); + struct st_texture_image *st_image; + GLuint imageOffset; + + (void) fb; + + ASSERT(newImage); + + if (!irb) { + irb = intel_wrap_texture(ctx, newImage); + if (irb) { + /* bind the wrapper to the attachment point */ + _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); + } + else { + /* fallback to software rendering */ + _mesa_render_texture(ctx, fb, att); + return; + } + } + + DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", + _glthread_GetID(), + att->Texture->Name, newImage->Width, newImage->Height, + irb->Base.RefCount); + + /* point the renderbufer's region to the texture image region */ + st_image = st_texture_image(newImage); + if (irb->region != st_image->mt->region) { + if (irb->region) + intel->pipe->region_release(intel->pipe, &irb->region); + pipe_region_reference(&irb->region, st_image->mt->region); + } + + /* compute offset of the particular 2D image within the texture region */ + imageOffset = st_miptree_image_offset(st_image->mt, + att->CubeMapFace, + att->TextureLevel); + + if (att->Texture->Target == GL_TEXTURE_3D) { + const GLuint *offsets = st_miptree_depth_offsets(st_image->mt, + att->TextureLevel); + imageOffset += offsets[att->Zoffset]; + } + + /* store that offset in the region */ +#if 0 + st_image->mt->region->draw_offset = imageOffset; +#endif + + /* update drawing region, etc */ + intel_draw_buffer(ctx, fb); +#endif +} + + +/** + * Called by Mesa when rendering to a texture is done. + */ +static void +intel_finish_render_texture(GLcontext * ctx, + struct gl_renderbuffer_attachment *att) +{ + struct intel_context *intel = intel_context(ctx); + struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); + + DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name); + + if (irb) { + /* just release the region */ + intel->pipe->region_release(intel->pipe, &irb->region); + } + else if (att->Renderbuffer) { + /* software fallback */ + _mesa_finish_render_texture(ctx, att); + /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ + } +} + + +/** + * Do one-time context initializations related to GL_EXT_framebuffer_object. + * Hook in device driver functions. + */ +void +intel_fbo_init(struct intel_context *intel) +{ + intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; + intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; + intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; + intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; + intel->ctx.Driver.RenderTexture = intel_render_texture; + intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; + intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_fbo.h b/src/mesa/drivers/dri/intel_winsys/intel_fbo.h new file mode 100644 index 00000000000..0f99a3e98db --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_fbo.h @@ -0,0 +1,127 @@ +/************************************************************************** + * + * 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_FBO_H +#define INTEL_FBO_H + + +#include "pipe/p_state.h" +#include "pipe/softpipe/sp_surface.h" + + +struct intel_context; +struct pipe_region; + + +/** + * Intel framebuffer, derived from gl_framebuffer. + */ +struct intel_framebuffer +{ + struct gl_framebuffer Base; + + struct intel_renderbuffer *color_rb[3]; + + /* Drawable page flipping state */ + GLboolean pf_active; + GLuint pf_seq; + GLint pf_pipes; + GLint pf_current_page; + GLint pf_num_pages; + + /* VBI + */ + GLuint vbl_seq; + GLuint vblank_flags; + GLuint vbl_waited; + + int64_t swap_ust; + int64_t swap_missed_ust; + + GLuint swap_count; + GLuint swap_missed_count; +}; + + +/** + * Intel renderbuffer, derived from gl_renderbuffer. + * Note: The PairedDepth and PairedStencil fields use renderbuffer IDs, + * not pointers because in some circumstances a deleted renderbuffer could + * result in a dangling pointer here. + */ +struct intel_renderbuffer +{ + struct gl_renderbuffer Base; + struct pipe_region *region; + void *pfMap; /* possibly paged flipped map pointer */ + GLuint pfPitch; /* possibly paged flipped pitch */ + GLboolean RenderToTexture; /* RTT? */ + + GLuint PairedDepth; /**< only used if this is a depth renderbuffer */ + GLuint PairedStencil; /**< only used if this is a stencil renderbuffer */ + + GLuint pf_pending; /**< sequence number of pending flip */ + + GLuint vbl_pending; /**< vblank sequence number of pending flip */ + + struct intel_surface *surface; +}; + +#if 0 +extern struct intel_renderbuffer *intel_create_renderbuffer(GLenum intFormat, + GLsizei width, + GLsizei height, + int offset, + int pitch, + int cpp, + void *map); +#endif + +extern struct intel_renderbuffer *intel_new_renderbuffer_fb(GLuint intFormat); + +extern void intel_fbo_init(struct intel_context *intel); + + +/* XXX make inline or macro */ +extern struct intel_renderbuffer *intel_get_renderbuffer(struct gl_framebuffer + *fb, + GLuint attIndex); + +extern void intel_flip_renderbuffers(struct intel_framebuffer *intel_fb); + + +/* XXX make inline or macro */ +extern struct pipe_region *intel_get_rb_region(struct gl_framebuffer *fb, + GLuint attIndex); + + + +extern struct pipe_surface * +intel_new_surface(GLuint intFormat); + + +#endif /* INTEL_FBO_H */ diff --git a/src/mesa/drivers/dri/intel_winsys/intel_ioctl.c b/src/mesa/drivers/dri/intel_winsys/intel_ioctl.c new file mode 100644 index 00000000000..154a3e289f5 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_ioctl.c @@ -0,0 +1,135 @@ +/************************************************************************** + * + * 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 +#include +#include +#include + +#include "mtypes.h" +#include "context.h" + +#include "intel_context.h" +#include "intel_ioctl.h" +#include "intel_batchbuffer.h" +#include "intel_blit.h" +#include "drm.h" + +#define FILE_DEBUG_FLAG DEBUG_IOCTL + +int +intelEmitIrqLocked(struct intel_context *intel) +{ + drmI830IrqEmit ie; + int ret, seq; + + assert(((*(int *) intel->driHwLock) & ~DRM_LOCK_CONT) == + (DRM_LOCK_HELD | intel->hHWContext)); + + ie.irq_seq = &seq; + + ret = drmCommandWriteRead(intel->driFd, DRM_I830_IRQ_EMIT, + &ie, sizeof(ie)); + if (ret) { + fprintf(stderr, "%s: drmI830IrqEmit: %d\n", __FUNCTION__, ret); + exit(1); + } + + DBG("%s --> %d\n", __FUNCTION__, seq); + + return seq; +} + +void +intelWaitIrq(struct intel_context *intel, int seq) +{ + int ret; + + DBG("%s %d\n", __FUNCTION__, seq); + + intel->iw.irq_seq = seq; + + do { + ret = + drmCommandWrite(intel->driFd, DRM_I830_IRQ_WAIT, &intel->iw, + sizeof(intel->iw)); + } while (ret == -EAGAIN || ret == -EINTR); + + if (ret) { + fprintf(stderr, "%s: drmI830IrqWait: %d\n", __FUNCTION__, ret); + exit(1); + } +} + + +void +intel_batch_ioctl(struct intel_context *intel, + GLuint start_offset, + GLuint used, + GLboolean ignore_cliprects, GLboolean allow_unlock) +{ + drmI830BatchBuffer batch; + + assert(intel->locked); + assert(used); + + DBG("%s used %d offset %x..%x ignore_cliprects %d\n", + __FUNCTION__, + used, start_offset, start_offset + used, ignore_cliprects); + + /* Throw away non-effective packets. Won't work once we have + * hardware contexts which would preserve statechanges beyond a + * single buffer. + */ + + + + batch.start = start_offset; + batch.used = used; + batch.cliprects = intel->pClipRects; + batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects; + batch.DR1 = 0; + batch.DR4 = 0; /* still need this ? */ + + DBG("%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))) { + fprintf(stderr, "DRM_I830_BATCHBUFFER: %d\n", -errno); + UNLOCK_HARDWARE(intel); + exit(1); + } + + /* FIXME: use hardware contexts to avoid 'losing' hardware after + * each buffer flush. + */ + //intel->vtbl.lost_hardware(intel); +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_ioctl.h b/src/mesa/drivers/dri/intel_winsys/intel_ioctl.h new file mode 100644 index 00000000000..e8d07de893e --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_ioctl.h @@ -0,0 +1,40 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef INTEL_IOCTL_H +#define INTEL_IOCTL_H + +#include "intel_context.h" + +void intelWaitIrq(struct intel_context *intel, int seq); +int intelEmitIrqLocked(struct intel_context *intel); + +void intel_batch_ioctl(struct intel_context *intel, + GLuint start_offset, + GLuint used, + GLboolean ignore_cliprects, GLboolean allow_unlock); +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.c new file mode 100644 index 00000000000..1a9aa101157 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.c @@ -0,0 +1,293 @@ +/************************************************************************** + * + * 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 "intel_mipmap_tree.h" +#include "enums.h" + +#include "pipe/p_state.h" +#include "pipe/p_context.h" + + +#define DBG if(0) printf + +static GLenum +target_to_target(GLenum target) +{ + switch (target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + return GL_TEXTURE_CUBE_MAP_ARB; + default: + return target; + } +} + +struct pipe_mipmap_tree * +st_miptree_create(struct pipe_context *pipe, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + GLuint width0, + GLuint height0, + GLuint depth0, GLuint cpp, GLuint compress_byte) +{ + GLboolean ok; + struct pipe_mipmap_tree *mt = calloc(sizeof(*mt), 1); + + DBG("%s target %s format %s level %d..%d\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(target), + _mesa_lookup_enum_by_nr(internal_format), first_level, last_level); + + mt->target = target_to_target(target); + mt->internal_format = internal_format; + mt->first_level = first_level; + mt->last_level = last_level; + mt->width0 = width0; + mt->height0 = height0; + mt->depth0 = depth0; + mt->cpp = compress_byte ? compress_byte : cpp; + mt->compressed = compress_byte ? 1 : 0; + mt->refcount = 1; + + ok = pipe->mipmap_tree_layout(pipe, mt); + if (ok) + mt->region = pipe->region_alloc(pipe, + mt->cpp, mt->pitch, mt->total_height); + + if (!mt->region) { + free(mt); + return NULL; + } + + return mt; +} + + +void +st_miptree_reference(struct pipe_mipmap_tree **dst, + struct pipe_mipmap_tree *src) +{ + src->refcount++; + *dst = src; + DBG("%s %p refcount now %d\n", __FUNCTION__, src, src->refcount); +} + +void +st_miptree_release(struct pipe_context *pipe, + struct pipe_mipmap_tree **mt) +{ + if (!*mt) + return; + + DBG("%s %p refcount will be %d\n", __FUNCTION__, *mt, (*mt)->refcount - 1); + if (--(*mt)->refcount <= 0) { + GLuint i; + + DBG("%s deleting %p\n", __FUNCTION__, *mt); + + pipe->region_release(pipe, &((*mt)->region)); + + for (i = 0; i < MAX_TEXTURE_LEVELS; i++) + if ((*mt)->level[i].image_offset) + free((*mt)->level[i].image_offset); + + free(*mt); + } + *mt = NULL; +} + + + + +/* Can the image be pulled into a unified mipmap tree. This mirrors + * the completeness test in a lot of ways. + * + * Not sure whether I want to pass gl_texture_image here. + */ +GLboolean +st_miptree_match_image(struct pipe_mipmap_tree *mt, + struct gl_texture_image *image, + GLuint face, GLuint level) +{ + /* Images with borders are never pulled into mipmap trees. + */ + if (image->Border) + return GL_FALSE; + + if (image->InternalFormat != mt->internal_format || + image->IsCompressed != mt->compressed) + return GL_FALSE; + + /* Test image dimensions against the base level image adjusted for + * minification. This will also catch images not present in the + * tree, changed targets, etc. + */ + if (image->Width != mt->level[level].width || + image->Height != mt->level[level].height || + image->Depth != mt->level[level].depth) + return GL_FALSE; + + return GL_TRUE; +} + + +/* Although we use the image_offset[] array to store relative offsets + * to cube faces, Mesa doesn't know anything about this and expects + * each cube face to be treated as a separate image. + * + * These functions present that view to mesa: + */ +const GLuint * +st_miptree_depth_offsets(struct pipe_mipmap_tree *mt, GLuint level) +{ + static const GLuint zero = 0; + + if (mt->target != GL_TEXTURE_3D || mt->level[level].nr_images == 1) + return &zero; + else + return mt->level[level].image_offset; +} + + +GLuint +st_miptree_image_offset(struct pipe_mipmap_tree * mt, + GLuint face, GLuint level) +{ + if (mt->target == GL_TEXTURE_CUBE_MAP_ARB) + return (mt->level[level].level_offset + + mt->level[level].image_offset[face] * mt->cpp); + else + return mt->level[level].level_offset; +} + + + +/** + * Map a teximage in a mipmap tree. + * \param row_stride returns row stride in bytes + * \param image_stride returns image stride in bytes (for 3D textures). + * \return address of mapping + */ +GLubyte * +st_miptree_image_map(struct pipe_context *pipe, + struct pipe_mipmap_tree * mt, + GLuint face, + GLuint level, + GLuint * row_stride, GLuint * image_offsets) +{ + GLubyte *ptr; + DBG("%s \n", __FUNCTION__); + + if (row_stride) + *row_stride = mt->pitch * mt->cpp; + + if (image_offsets) + memcpy(image_offsets, mt->level[level].image_offset, + mt->level[level].depth * sizeof(GLuint)); + + ptr = pipe->region_map(pipe, mt->region); + + return ptr + st_miptree_image_offset(mt, face, level); +} + +void +st_miptree_image_unmap(struct pipe_context *pipe, + struct pipe_mipmap_tree *mt) +{ + DBG("%s\n", __FUNCTION__); + pipe->region_unmap(pipe, mt->region); +} + + + +/* Upload data for a particular image. + */ +void +st_miptree_image_data(struct pipe_context *pipe, + struct pipe_mipmap_tree *dst, + GLuint face, + GLuint level, + void *src, + GLuint src_row_pitch, GLuint src_image_pitch) +{ + GLuint depth = dst->level[level].depth; + GLuint dst_offset = st_miptree_image_offset(dst, face, level); + const GLuint *dst_depth_offset = st_miptree_depth_offsets(dst, level); + GLuint i; + GLuint height = 0; + + DBG("%s\n", __FUNCTION__); + for (i = 0; i < depth; i++) { + height = dst->level[level].height; + if(dst->compressed) + height /= 4; + pipe->region_data(pipe, dst->region, + dst_offset + dst_depth_offset[i], /* dst_offset */ + 0, 0, /* dstx, dsty */ + src, + src_row_pitch, + 0, 0, /* source x, y */ + dst->level[level].width, height); /* width, height */ + + src += src_image_pitch * dst->cpp; + } +} + +/* Copy mipmap image between trees + */ +void +st_miptree_image_copy(struct pipe_context *pipe, + struct pipe_mipmap_tree *dst, + GLuint face, GLuint level, + struct pipe_mipmap_tree *src) +{ + GLuint width = src->level[level].width; + GLuint height = src->level[level].height; + GLuint depth = src->level[level].depth; + GLuint dst_offset = st_miptree_image_offset(dst, face, level); + GLuint src_offset = st_miptree_image_offset(src, face, level); + const GLuint *dst_depth_offset = st_miptree_depth_offsets(dst, level); + const GLuint *src_depth_offset = st_miptree_depth_offsets(src, level); + GLuint i; + + if (dst->compressed) + height /= 4; + for (i = 0; i < depth; i++) { + pipe->region_copy(pipe, + dst->region, dst_offset + dst_depth_offset[i], + 0, + 0, + src->region, src_offset + src_depth_offset[i], + 0, 0, width, height); + } + +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.h new file mode 100644 index 00000000000..eafe47c0291 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_mipmap_tree.h @@ -0,0 +1,105 @@ +/************************************************************************** + * + * 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_MIPMAP_TREE_H +#define INTEL_MIPMAP_TREE_H + + +#include "main/mtypes.h" + +struct pipe_context; +struct pipe_mipmap_tree; +struct pipe_region; + + +struct pipe_mipmap_tree *st_miptree_create(struct pipe_context *pipe, + GLenum target, + GLenum internal_format, + GLuint first_level, + GLuint last_level, + GLuint width0, + GLuint height0, + GLuint depth0, + GLuint cpp, + GLuint compress_byte); + +void st_miptree_reference(struct pipe_mipmap_tree **dst, + struct pipe_mipmap_tree *src); + +void st_miptree_release(struct pipe_context *pipe, + struct pipe_mipmap_tree **mt); + +/* Check if an image fits an existing mipmap tree layout + */ +GLboolean st_miptree_match_image(struct pipe_mipmap_tree *mt, + struct gl_texture_image *image, + GLuint face, GLuint level); + +/* Return a pointer to an image within a tree. Return image stride as + * well. + */ +GLubyte *st_miptree_image_map(struct pipe_context *pipe, + struct pipe_mipmap_tree *mt, + GLuint face, + GLuint level, + GLuint * row_stride, GLuint * image_stride); + +void st_miptree_image_unmap(struct pipe_context *pipe, + struct pipe_mipmap_tree *mt); + + +/* Return the linear offset of an image relative to the start of the + * tree: + */ +GLuint st_miptree_image_offset(struct pipe_mipmap_tree *mt, + GLuint face, GLuint level); + +/* Return pointers to each 2d slice within an image. Indexed by depth + * value. + */ +const GLuint *st_miptree_depth_offsets(struct pipe_mipmap_tree *mt, + GLuint level); + + +/* Upload an image into a tree + */ +void st_miptree_image_data(struct pipe_context *pipe, + struct pipe_mipmap_tree *dst, + GLuint face, + GLuint level, + void *src, + GLuint src_row_pitch, GLuint src_image_pitch); + +/* Copy an image between two trees + */ +void st_miptree_image_copy(struct pipe_context *pipe, + struct pipe_mipmap_tree *dst, + GLuint face, GLuint level, + struct pipe_mipmap_tree *src); + + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_reg.h b/src/mesa/drivers/dri/intel_winsys/intel_reg.h new file mode 100644 index 00000000000..7828ba6ad39 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_reg.h @@ -0,0 +1,88 @@ +/************************************************************************** + * + * 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 CMD_3D (0x3<<29) + + +#define _3DPRIMITIVE ((0x3<<29)|(0x1f<<24)) +#define PRIM_INDIRECT (1<<23) +#define PRIM_INLINE (0<<23) +#define PRIM_INDIRECT_SEQUENTIAL (0<<17) +#define PRIM_INDIRECT_ELTS (1<<17) + +#define PRIM3D_TRILIST (0x0<<18) +#define PRIM3D_TRISTRIP (0x1<<18) +#define PRIM3D_TRISTRIP_RVRSE (0x2<<18) +#define PRIM3D_TRIFAN (0x3<<18) +#define PRIM3D_POLY (0x4<<18) +#define PRIM3D_LINELIST (0x5<<18) +#define PRIM3D_LINESTRIP (0x6<<18) +#define PRIM3D_RECTLIST (0x7<<18) +#define PRIM3D_POINTLIST (0x8<<18) +#define PRIM3D_DIB (0x9<<18) +#define PRIM3D_MASK (0x1f<<18) + +#define I915PACKCOLOR4444(r,g,b,a) \ + ((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4)) + +#define I915PACKCOLOR1555(r,g,b,a) \ + ((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \ + ((a) ? 0x8000 : 0)) + +#define I915PACKCOLOR565(r,g,b) \ + ((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3)) + +#define I915PACKCOLOR8888(r,g,b,a) \ + ((a<<24) | (r<<16) | (g<<8) | b) + + + + +#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) + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_screen.c b/src/mesa/drivers/dri/intel_winsys/intel_screen.c new file mode 100644 index 00000000000..81ab435f42e --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_screen.c @@ -0,0 +1,597 @@ +/************************************************************************** + * + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "glheader.h" +#include "context.h" +#include "framebuffer.h" +#include "matrix.h" +#include "renderbuffer.h" +#include "simple_list.h" +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + +#include "intel_screen.h" +#include "intel_batchbuffer.h" +#include "intel_buffers.h" +/*#include "intel_tex.h"*/ +#include "intel_ioctl.h" +#include "intel_fbo.h" + +#include "i830_dri.h" +#include "dri_bufpool.h" + +#include "pipe/p_context.h" + + + +PUBLIC const char __driConfigOptions[] = + DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY + DRI_CONF_FORCE_S3TC_ENABLE(false) + DRI_CONF_ALLOW_LARGE_TEXTURES(1) + DRI_CONF_SECTION_END DRI_CONF_END; + const GLuint __driNConfigOptions = 4; + +#ifdef USE_NEW_INTERFACE + static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; +#endif /*USE_NEW_INTERFACE */ + + extern const struct dri_extension card_extensions[]; + + + + + +static void +intelPrintDRIInfo(intelScreenPrivate * intelScreen, + __DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv) +{ + fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n", + intelScreen->front.size, intelScreen->front.offset, + intelScreen->front.pitch); + fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem); +} + + +static void +intelPrintSAREA(const drmI830Sarea * sarea) +{ + fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width, + sarea->height); + fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch); + fprintf(stderr, + "SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->front_offset, sarea->front_size, + (unsigned) sarea->front_handle); + fprintf(stderr, + "SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->back_offset, sarea->back_size, + (unsigned) sarea->back_handle); + fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->depth_offset, sarea->depth_size, + (unsigned) sarea->depth_handle); + fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n", + sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle); + fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation); + fprintf(stderr, + "SAREA: rotated offset: 0x%08x size: 0x%x\n", + sarea->rotated_offset, sarea->rotated_size); + fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch); +} + + + +/** + * 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) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; + + 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) { + _mesa_problem(NULL, "drmMap(frontbuffer) failed!"); + 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); + } +} + + + +GLboolean +intelCreatePools(intelScreenPrivate *intelScreen) +{ + unsigned batchPoolSize = 1024*1024; + __DRIscreenPrivate * sPriv = intelScreen->driScrnPriv; + + if (intelScreen->havePools) + return GL_TRUE; + + batchPoolSize /= BATCH_SZ; + intelScreen->regionPool = driDRMPoolInit(sPriv->fd); + + if (!intelScreen->regionPool) + return GL_FALSE; + + intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd); + + if (!intelScreen->staticPool) + return GL_FALSE; + + intelScreen->texPool = intelScreen->regionPool; + + 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 GLboolean +intelInitDriver(__DRIscreenPrivate * sPriv) +{ + intelScreenPrivate *intelScreen; + I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv; + + PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension = + (PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface-> + getProcAddress("glxEnableExtension")); + void *const psc = sPriv->psc->screenConfigs; + + if (sPriv->devPrivSize != sizeof(I830DRIRec)) { + fprintf(stderr, + "\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n"); + return GL_FALSE; + } + + /* Allocate the private area */ + intelScreen = (intelScreenPrivate *) CALLOC(sizeof(intelScreenPrivate)); + if (!intelScreen) + return GL_FALSE; + + /* parse information in __driConfigOptions */ + driParseOptionInfo(&intelScreen->optionCache, + __driConfigOptions, __driNConfigOptions); + + intelScreen->driScrnPriv = sPriv; + 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"); + } + + return GL_TRUE; +} + + +static void +intelDestroyScreen(__DRIscreenPrivate * sPriv) +{ + intelScreenPrivate *intelScreen = (intelScreenPrivate *) sPriv->private; + +// intelUnmapScreenRegions(intelScreen); + + if (intelScreen->havePools) { + driPoolTakeDown(intelScreen->regionPool); + 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 GLboolean +intelCreateBuffer(__DRIscreenPrivate * driScrnPriv, + __DRIdrawablePrivate * driDrawPriv, + const __GLcontextModes * mesaVis, GLboolean isPixmap) +{ + if (isPixmap) { + return GL_FALSE; /* not implemented */ + } + else { + GLboolean swStencil = (mesaVis->stencilBits > 0 && + mesaVis->depthBits != 24); + GLenum rgbFormat = (mesaVis->redBits == 5 ? GL_RGB5 : GL_RGBA8); + + struct intel_framebuffer *intel_fb = CALLOC_STRUCT(intel_framebuffer); + + if (!intel_fb) + return GL_FALSE; + + _mesa_initialize_framebuffer(&intel_fb->Base, mesaVis); + + { + /* fake frontbuffer */ + /* XXX allocation should only happen in the unusual case + it's actually needed */ + intel_fb->color_rb[0] + = intel_new_renderbuffer_fb(rgbFormat); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_FRONT_LEFT, + &intel_fb->color_rb[0]->Base); + } + + if (mesaVis->doubleBufferMode) { + intel_fb->color_rb[1] + = intel_new_renderbuffer_fb(rgbFormat); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_BACK_LEFT, + &intel_fb->color_rb[1]->Base); + } + + if (mesaVis->depthBits == 24 && mesaVis->stencilBits == 8) { + /* combined depth/stencil buffer */ + struct intel_renderbuffer *depthStencilRb + = intel_new_renderbuffer_fb(GL_DEPTH24_STENCIL8_EXT); + /* note: bind RB to two attachment points */ + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, + &depthStencilRb->Base); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_STENCIL, + &depthStencilRb->Base); + } + else if (mesaVis->depthBits == 16) { + /* just 16-bit depth buffer, no hw stencil */ + struct intel_renderbuffer *depthRb + = intel_new_renderbuffer_fb(GL_DEPTH_COMPONENT16); + _mesa_add_renderbuffer(&intel_fb->Base, BUFFER_DEPTH, &depthRb->Base); + } + + + /* now add any/all software-based renderbuffers we may need */ + _mesa_add_soft_renderbuffers(&intel_fb->Base, + GL_FALSE, /* never sw color */ + GL_FALSE, /* never sw depth */ + swStencil, mesaVis->accumRedBits > 0, + GL_FALSE, /* never sw alpha */ + GL_FALSE /* never sw aux */ ); + driDrawPriv->driverPrivate = (void *) intel_fb; + + return GL_TRUE; + } +} + +static void +intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv) +{ + _mesa_unreference_framebuffer((GLframebuffer **)(&(driDrawPriv->driverPrivate))); +} + + +/** + * Get information about previous buffer swaps. + */ +static int +intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo) +{ + struct intel_framebuffer *intel_fb; + + if ((dPriv == NULL) || (dPriv->driverPrivate == NULL) + || (sInfo == NULL)) { + return -1; + } + + intel_fb = dPriv->driverPrivate; + sInfo->swap_count = intel_fb->swap_count; + sInfo->swap_ust = intel_fb->swap_ust; + sInfo->swap_missed_count = intel_fb->swap_missed_count; + + sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0) + ? driCalculateSwapUsage(dPriv, 0, intel_fb->swap_missed_ust) + : 0.0; + + return 0; +} + + +static void +intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint 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->mt) + st_miptree_release(intel->pipe, &stObj->mt); + + 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, GLboolean have_back_buffer) +{ + __GLcontextModes *modes; + __GLcontextModes *m; + unsigned num_modes; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + + /* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't + * support pageflipping at all. + */ + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + 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; +} + +struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen) +{ + /* + * This should probably change to have the screen allocate a dummy + * context at screen creation. For now just use the current context. + */ + + GET_CURRENT_CONTEXT(ctx); + if (ctx == NULL) { +/* _mesa_problem(NULL, "No current context in intelScreenContext\n"); + return NULL; */ + /* need a context for the first time makecurrent is called (for hw lock + when allocating priv buffers) */ + if (intelScreen->dummyctxptr == NULL) { + _mesa_problem(NULL, "No current context in intelScreenContext\n"); + return NULL; + } + return intelScreen->dummyctxptr; + } + return intel_context(ctx); + +} + diff --git a/src/mesa/drivers/dri/intel_winsys/intel_screen.h b/src/mesa/drivers/dri/intel_winsys/intel_screen.h new file mode 100644 index 00000000000..549587a6f2b --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_screen.h @@ -0,0 +1,111 @@ +/************************************************************************** + * + * 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" + + +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; + + __DRIscreenPrivate *driScrnPriv; + drmI830Sarea *sarea; + + + /** + * Configuration cache with default values for all contexts + */ + driOptionCache optionCache; + struct _DriBufferPool *batchPool; + struct _DriBufferPool *texPool; + struct _DriBufferPool *regionPool; + struct _DriBufferPool *staticPool; + GLboolean havePools; + + struct intel_context *dummyctxptr; +}; + +typedef struct intel_screen intelScreenPrivate; + +extern void +intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea); + + +extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv); + +extern GLboolean intelUnbindContext(__DRIcontextPrivate * driContextPriv); + +extern GLboolean +intelMakeCurrent(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv); + +extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv); + +extern void +intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h); + +extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags, + unsigned long bufSize, + unsigned numBufs, + unsigned checkDelayed); + +extern struct intel_context *intelScreenContext(intelScreenPrivate *intelScreen); + +extern GLboolean +intelCreatePools(intelScreenPrivate *intelScreen); + +extern GLboolean +intelCreateContext(const __GLcontextModes * mesaVis, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); + + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_softpipe.c b/src/mesa/drivers/dri/intel_winsys/intel_softpipe.c new file mode 100644 index 00000000000..ef477443586 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_softpipe.c @@ -0,0 +1,184 @@ +/************************************************************************** + * + * 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 + */ + +#include +#include +#include "dri_bufpool.h" +#include "dri_bufmgr.h" + +/* #include "errno.h" */ +/* #include "string.h" */ +/* #include "imports.h" */ + +#include "intel_context.h" + +#include "pipe/softpipe/sp_winsys.h" + + +struct intel_softpipe_winsys { + struct softpipe_winsys sws; + struct intel_context *intel; +}; + + + +/* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque + * buffer pointer... + */ +static inline struct _DriBufferObject * +dri_bo( struct pipe_buffer_handle *bo ) +{ + return (struct _DriBufferObject *)bo; +} + +static inline struct pipe_buffer_handle * +pipe_bo( struct _DriBufferObject *bo ) +{ + return (struct pipe_buffer_handle *)bo; +} + +/* Turn a softpipe winsys into an intel/softpipe winsys: + */ +static inline struct intel_softpipe_winsys * +intel_softpipe_winsys( struct softpipe_winsys *sws ) +{ + return (struct intel_softpipe_winsys *)sws; +} + + +/* Most callbacks map direcly onto dri_bufmgr operations: + */ +static void *intel_buffer_map(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf ) +{ + return driBOMap( dri_bo(buf), + DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0 ); +} + +static void intel_buffer_unmap(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf) +{ + driBOUnmap( dri_bo(buf) ); +} + + +static struct pipe_buffer_handle * +intel_buffer_reference(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf) +{ + return pipe_bo( driBOReference( dri_bo(buf) ) ); +} + +static void intel_buffer_unreference(struct softpipe_winsys *sws, + struct pipe_buffer_handle **buf) +{ + if (*buf) { + driBOUnReference( dri_bo(*buf) ); + *buf = NULL; + } +} + +/* Grabs the hardware lock! + */ +static void intel_buffer_data(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf, + unsigned size, const void *data ) +{ + struct intel_context *intel = intel_softpipe_winsys(sws)->intel; + + LOCK_HARDWARE( intel ); + driBOData( dri_bo(buf), size, data, 0 ); + UNLOCK_HARDWARE( intel ); +} + +static void intel_buffer_subdata(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + const void *data) +{ + driBOSubData( dri_bo(buf), offset, size, data ); +} + +static void intel_buffer_get_subdata(struct softpipe_winsys *sws, + struct pipe_buffer_handle *buf, + unsigned long offset, + unsigned long size, + void *data) +{ + driBOGetSubData( dri_bo(buf), offset, size, data ); +} + +/* Softpipe has no concept of pools. We choose the tex/region pool + * for all buffers. + */ +static struct pipe_buffer_handle * +intel_create_buffer(struct softpipe_winsys *sws, + unsigned alignment) +{ + struct intel_context *intel = intel_softpipe_winsys(sws)->intel; + struct _DriBufferObject *buffer; + + LOCK_HARDWARE( intel ); + driGenBuffers( intel->intelScreen->regionPool, + "softpipe buffer", 1, &buffer, alignment, 0, 0 ); + UNLOCK_HARDWARE( intel ); + + return pipe_bo(buffer); +} + + +struct pipe_context * +intel_create_softpipe( struct intel_context *intel ) +{ + 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. + * + * Softpipe 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. + */ + isws->sws.create_buffer = intel_create_buffer; + isws->sws.buffer_map = intel_buffer_map; + isws->sws.buffer_unmap = intel_buffer_unmap; + isws->sws.buffer_reference = intel_buffer_reference; + isws->sws.buffer_unreference = intel_buffer_unreference; + isws->sws.buffer_data = intel_buffer_data; + isws->sws.buffer_subdata = intel_buffer_subdata; + isws->sws.buffer_get_subdata = intel_buffer_get_subdata; + isws->intel = intel; + + /* Create the softpipe context: + */ + return softpipe_create( &isws->sws ); +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_surface.c b/src/mesa/drivers/dri/intel_winsys/intel_surface.c new file mode 100644 index 00000000000..3fa40271c83 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_surface.c @@ -0,0 +1,196 @@ +#include "glheader.h" +#include "context.h" +#include "framebuffer.h" +#include "renderbuffer.h" +#include "utils.h" +#include "main/macros.h" + + +#include "intel_screen.h" + +#include "intel_context.h" +#include "intel_buffers.h" +#include "intel_fbo.h" + +#include "pipe/p_state.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/softpipe/sp_surface.h" + + +/* + * XXX a lof of this is a temporary kludge + */ + +/** + * Note: the arithmetic/addressing in these functions is a little + * tricky since we need to invert the Y axis. + */ + + +static void +read_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE]) +{ + const GLint bytesPerRow = sps->surface.region->pitch * sps->surface.region->cpp; + const GLint invY = sps->surface.height - y - 1; + const GLubyte *src = sps->surface.region->map + invY * bytesPerRow + x * sps->surface.region->cpp; + GLfloat *dst = (GLfloat *) rrrr; + GLubyte temp[16]; + GLuint j; + + assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8); + + memcpy(temp + 8, src, 8); + memcpy(temp + 0, src + bytesPerRow, 8); + + for (j = 0; j < 4; j++) { + dst[0 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 2]); /*R*/ + dst[1 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 1]); /*G*/ + dst[2 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 0]); /*B*/ + dst[3 * 4 + j] = UBYTE_TO_FLOAT(temp[j * 4 + 3]); /*A*/ + } +} + + +static void +write_quad_f_swz(struct softpipe_surface *sps, GLint x, GLint y, + GLfloat (*rrrr)[QUAD_SIZE]) +{ + const GLfloat *src = (const GLfloat *) rrrr; + const GLint bytesPerRow = sps->surface.region->pitch * sps->surface.region->cpp; + const GLint invY = sps->surface.height - y - 1; + GLubyte *dst = sps->surface.region->map + invY * bytesPerRow + x * sps->surface.region->cpp; + GLubyte temp[16]; + GLuint j; + + assert(sps->surface.format == PIPE_FORMAT_U_A8_R8_G8_B8); + + for (j = 0; j < 4; j++) { + UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 2], src[0 * 4 + j]); /*R*/ + UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 1], src[1 * 4 + j]); /*G*/ + UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 0], src[2 * 4 + j]); /*B*/ + UNCLAMPED_FLOAT_TO_UBYTE(temp[j * 4 + 3], src[3 * 4 + j]); /*A*/ + } + + memcpy(dst, temp + 8, 8); + memcpy(dst + bytesPerRow, temp + 0, 8); +} + + + +static void +read_quad_z24(struct softpipe_surface *sps, + GLint x, GLint y, GLuint zzzz[QUAD_SIZE]) +{ + static const GLuint mask = 0xffffff; + const GLint invY = sps->surface.height - y - 1; + const GLuint *src + = (GLuint *) (sps->surface.region->map + + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); + + assert(sps->surface.format == PIPE_FORMAT_S8_Z24); + + /* extract lower three bytes */ + zzzz[0] = src[0] & mask; + zzzz[1] = src[1] & mask; + zzzz[2] = src[-sps->surface.region->pitch] & mask; + zzzz[3] = src[-sps->surface.region->pitch + 1] & mask; +} + +static void +write_quad_z24(struct softpipe_surface *sps, + GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]) +{ + static const GLuint mask = 0xff000000; + const GLint invY = sps->surface.height - y - 1; + GLuint *dst + = (GLuint *) (sps->surface.region->map + + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); + + assert(sps->surface.format == PIPE_FORMAT_S8_Z24); + + /* write lower three bytes */ + dst[0] = (dst[0] & mask) | zzzz[0]; + dst[1] = (dst[1] & mask) | zzzz[1]; + dst -= sps->surface.region->pitch; + dst[0] = (dst[0] & mask) | zzzz[2]; + dst[1] = (dst[1] & mask) | zzzz[3]; +} + + +static void +read_quad_stencil(struct softpipe_surface *sps, + GLint x, GLint y, GLubyte ssss[QUAD_SIZE]) +{ + const GLint invY = sps->surface.height - y - 1; + const GLuint *src = (const GLuint *) (sps->surface.region->map + + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); + + assert(sps->surface.format == PIPE_FORMAT_S8_Z24); + + /* extract high byte */ + ssss[0] = src[0] >> 24; + ssss[1] = src[1] >> 24; + src -= sps->surface.region->pitch; + ssss[2] = src[0] >> 24; + ssss[3] = src[1] >> 24; +} + +static void +write_quad_stencil(struct softpipe_surface *sps, + GLint x, GLint y, const GLubyte ssss[QUAD_SIZE]) +{ + static const GLuint mask = 0x00ffffff; + const GLint invY = sps->surface.height - y - 1; + GLuint *dst = (GLuint *) (sps->surface.region->map + + (invY * sps->surface.region->pitch + x) * sps->surface.region->cpp); + + assert(sps->surface.format == PIPE_FORMAT_S8_Z24); + + /* write high byte */ + dst[0] = (dst[0] & mask) | (ssss[0] << 24); + dst[1] = (dst[1] & mask) | (ssss[1] << 24); + dst -= sps->surface.region->pitch; + dst[0] = (dst[0] & mask) | (ssss[2] << 24); + dst[1] = (dst[1] & mask) | (ssss[3] << 24); +} + + +struct pipe_surface * +intel_new_surface(GLuint intFormat) +{ + struct softpipe_surface *sps = CALLOC_STRUCT(softpipe_surface); + if (!sps) + return NULL; + + sps->surface.width = 0; /* set in intel_alloc_renderbuffer_storage() */ + sps->surface.height = 0; + + if (intFormat == GL_RGBA8) { + sps->surface.format = PIPE_FORMAT_U_A8_R8_G8_B8; + sps->read_quad_f_swz = read_quad_f_swz; + sps->write_quad_f_swz = write_quad_f_swz; + } + else if (intFormat == GL_RGB5) { + sps->surface.format = PIPE_FORMAT_U_R5_G6_B5; + + } + else if (intFormat == GL_DEPTH_COMPONENT16) { + sps->surface.format = PIPE_FORMAT_U_Z16; + + } + else if (intFormat == GL_DEPTH24_STENCIL8_EXT) { + sps->surface.format = PIPE_FORMAT_S8_Z24; + sps->read_quad_z = read_quad_z24; + sps->write_quad_z = write_quad_z24; + sps->read_quad_stencil = read_quad_stencil; + sps->write_quad_stencil = write_quad_stencil; + } + else { + /* TBD / unknown */ + + } + + return &sps->surface; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex.c b/src/mesa/drivers/dri/intel_winsys/intel_tex.c new file mode 100644 index 00000000000..5270094cc51 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex.c @@ -0,0 +1,184 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + +#include "main/texobj.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_mipmap_tree.h" +#include "intel_tex.h" + +#define FILE_DEBUG_FLAG DEBUG_TEXTURE + +static GLboolean +intelIsTextureResident(GLcontext * ctx, struct gl_texture_object *texObj) +{ +#if 0 + struct intel_context *intel = intel_context(ctx); + struct st_texture_object *stObj = st_texture_object(texObj); + + return + stObj->mt && + stObj->mt->region && + intel_is_region_resident(intel, stObj->mt->region); +#endif + return 1; +} + + + +static struct gl_texture_image * +intelNewTextureImage(GLcontext * ctx) +{ + DBG("%s\n", __FUNCTION__); + (void) ctx; + return (struct gl_texture_image *) CALLOC_STRUCT(st_texture_image); +} + + +static struct gl_texture_object * +intelNewTextureObject(GLcontext * ctx, GLuint name, GLenum target) +{ + struct st_texture_object *obj = CALLOC_STRUCT(st_texture_object); + + DBG("%s\n", __FUNCTION__); + _mesa_initialize_texture_object(&obj->base, name, target); + + return &obj->base; +} + +static void +intelDeleteTextureObject(GLcontext *ctx, + struct gl_texture_object *texObj) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct st_texture_object *stObj = st_texture_object(texObj); + + if (stObj->mt) + st_miptree_release(pipe, &stObj->mt); + + _mesa_delete_texture_object(ctx, texObj); +} + + +static void +intelFreeTextureImageData(GLcontext * ctx, struct gl_texture_image *texImage) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct st_texture_image *stImage = st_texture_image(texImage); + + DBG("%s\n", __FUNCTION__); + + if (stImage->mt) { + st_miptree_release(pipe, &stImage->mt); + } + + if (texImage->Data) { + free(texImage->Data); + texImage->Data = NULL; + } +} + + + + +/* ================================================================ + * From linux kernel i386 header files, copes with odd sizes better + * than COPY_DWORDS would: + * XXX Put this in src/mesa/main/imports.h ??? + */ +#if defined(i386) || defined(__i386__) +static INLINE void * +__memcpy(void *to, const void *from, size_t n) +{ + int d0, d1, d2; + __asm__ __volatile__("rep ; movsl\n\t" + "testb $2,%b4\n\t" + "je 1f\n\t" + "movsw\n" + "1:\ttestb $1,%b4\n\t" + "je 2f\n\t" + "movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2) + :"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from) + :"memory"); + return (to); +} +#else +#define __memcpy(a,b,c) memcpy(a,b,c) +#endif + + +/* The system memcpy (at least on ubuntu 5.10) has problems copying + * to agp (writecombined) memory from a source which isn't 64-byte + * aligned - there is a 4x performance falloff. + * + * The x86 __memcpy is immune to this but is slightly slower + * (10%-ish) than the system memcpy. + * + * The sse_memcpy seems to have a slight cliff at 64/32 bytes, but + * isn't much faster than x86_memcpy for agp copies. + * + * TODO: switch dynamically. + */ +static void * +do_memcpy(void *dest, const void *src, size_t n) +{ + if ((((unsigned) src) & 63) || (((unsigned) dest) & 63)) { + return __memcpy(dest, src, n); + } + else + return memcpy(dest, src, n); +} + + +void +intelInitTextureFuncs(struct dd_function_table *functions) +{ + functions->ChooseTextureFormat = intelChooseTextureFormat; + functions->TexImage1D = intelTexImage1D; + functions->TexImage2D = intelTexImage2D; + functions->TexImage3D = intelTexImage3D; + functions->TexSubImage1D = intelTexSubImage1D; + functions->TexSubImage2D = intelTexSubImage2D; + functions->TexSubImage3D = intelTexSubImage3D; + functions->CopyTexImage1D = intelCopyTexImage1D; + functions->CopyTexImage2D = intelCopyTexImage2D; + functions->CopyTexSubImage1D = intelCopyTexSubImage1D; + functions->CopyTexSubImage2D = intelCopyTexSubImage2D; + functions->GetTexImage = intelGetTexImage; + + /* compressed texture functions */ + functions->CompressedTexImage2D = intelCompressedTexImage2D; + functions->GetCompressedTexImage = intelGetCompressedTexImage; + + functions->NewTextureObject = intelNewTextureObject; + functions->NewTextureImage = intelNewTextureImage; + functions->DeleteTexture = intelDeleteTextureObject; + functions->FreeTexImageData = intelFreeTextureImageData; + functions->UpdateTexturePalette = 0; + functions->IsTextureResident = intelIsTextureResident; + + functions->TextureMemCpy = do_memcpy; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex.h b/src/mesa/drivers/dri/intel_winsys/intel_tex.h new file mode 100644 index 00000000000..7a1cc919749 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex.h @@ -0,0 +1,212 @@ +/************************************************************************** + * + * 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 INTELTEX_INC +#define INTELTEX_INC + +#include "mtypes.h" +#include "intel_context.h" +#include "texmem.h" + +struct st_texture_object +{ + struct gl_texture_object base; /* The "parent" object */ + + /* The mipmap tree must include at least these levels once + * validated: + */ + GLuint firstLevel; + GLuint lastLevel; + + /* Offset for firstLevel image: + */ + GLuint textureOffset; + + /* On validation any active images held in main memory or in other + * regions will be copied to this region and the old storage freed. + */ + struct pipe_mipmap_tree *mt; + + GLboolean imageOverride; + GLint depthOverride; + GLuint pitchOverride; +}; + + + +struct st_texture_image +{ + struct gl_texture_image base; + + /* These aren't stored in gl_texture_image + */ + GLuint level; + GLuint face; + + /* If stImage->mt != NULL, image data is stored here. + * Else if stImage->base.Data != NULL, image is stored there. + * Else there is no image data. + */ + struct pipe_mipmap_tree *mt; +}; + + +void intelInitTextureFuncs(struct dd_function_table *functions); + +const struct gl_texture_format *intelChooseTextureFormat(GLcontext * ctx, + GLint internalFormat, + GLenum format, + GLenum type); + + +void intelTexImage3D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexSubImage3D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexImage2D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexSubImage2D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexImage1D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelTexSubImage1D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLint border); + +void intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border); + +void intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width); + +void intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height); + +void intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage); + +void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ); + +void intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage); + +void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch); + +GLuint intel_finalize_mipmap_tree(GLcontext *ctx, + struct pipe_context *pipe, GLuint unit, + GLboolean *needFlush); + + +#if 0 +void intel_tex_map_images(struct pipe_context *pipe, + struct st_texture_object *stObj); + +void intel_tex_unmap_images(struct pipe_context *pipe, + struct st_texture_object *stObj); +#endif + +int intel_compressed_num_bytes(GLuint mesaFormat); + + +static INLINE struct st_texture_object * +st_texture_object(struct gl_texture_object *obj) +{ + return (struct st_texture_object *) obj; +} + +static INLINE struct st_texture_image * +st_texture_image(struct gl_texture_image *img) +{ + return (struct st_texture_image *) img; +} + + +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_copy.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_copy.c new file mode 100644 index 00000000000..d2cf6f4669c --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_copy.c @@ -0,0 +1,315 @@ +/************************************************************************** + * + * 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/mtypes.h" +#include "main/enums.h" +#include "main/image.h" +#include "main/teximage.h" + +#include "state_tracker/st_mipmap_tree.h" + +#if 0 +#include "intel_screen.h" +#include "intel_context.h" +#include "intel_batchbuffer.h" +#include "intel_buffers.h" +#include "intel_fbo.h" +#include "intel_blit.h" +#endif +#include "intel_tex.h" + + +#define FILE_DEBUG_FLAG DEBUG_TEXTURE + +/** + * Get the pipe_region which is the source for any glCopyTex[Sub]Image call. + * + * Do the best we can using the blitter. A future project is to use + * the texture engine and fragment programs for these copies. + */ +static const struct pipe_region * +get_teximage_source(struct intel_context *intel, GLenum internalFormat) +{ +#if 00 + struct intel_renderbuffer *irb; + + DBG("%s %s\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(internalFormat)); + + switch (internalFormat) { + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16_ARB: + irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); + if (irb && irb->region && irb->region->cpp == 2) + return irb->region; + return NULL; + case GL_DEPTH24_STENCIL8_EXT: + case GL_DEPTH_STENCIL_EXT: + irb = intel_get_renderbuffer(intel->ctx.ReadBuffer, BUFFER_DEPTH); + if (irb && irb->region && irb->region->cpp == 4) + return irb->region; + return NULL; + case GL_RGBA: + case GL_RGBA8: + return intel_readbuf_region(intel); + case GL_RGB: + if (intel->intelScreen->front.cpp == 2) + return intel_readbuf_region(intel); + return NULL; + default: + return NULL; + } +#else + return NULL; +#endif +} + + +static GLboolean +do_copy_texsubimage(GLcontext *ctx, + struct st_texture_image *intelImage, + GLenum internalFormat, + GLint dstx, GLint dsty, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + struct intel_context *intel = intel_context(ctx); + const struct pipe_region *src = + get_teximage_source(intel, internalFormat); + + if (!intelImage->mt || !src) { + DBG("%s fail %p %p\n", __FUNCTION__, intelImage->mt, src); + return GL_FALSE; + } + +#if 00 /* XXX FIX flush/locking */ + intelFlush(ctx); + /* XXX still need the lock ? */ + LOCK_HARDWARE(intel); +#endif + + { + GLuint image_offset = st_miptree_image_offset(intelImage->mt, + intelImage->face, + intelImage->level); + const GLint orig_x = x; + const GLint orig_y = y; + const struct gl_framebuffer *fb = ctx->DrawBuffer; + + if (_mesa_clip_to_region(fb->_Xmin, fb->_Ymin, fb->_Xmax, fb->_Ymax, + &x, &y, &width, &height)) { + /* Update dst for clipped src. Need to also clip the source rect. + */ + dstx += x - orig_x; + dsty += y - orig_y; + + if (!(ctx->ReadBuffer->Name == 0)) { + /* XXX this looks bogus ? */ + /* FBO: invert Y */ + y = ctx->ReadBuffer->Height - y - 1; + } + + /* A bit of fiddling to get the blitter to work with -ve + * pitches. But we get a nice inverted blit this way, so it's + * worth it: + */ +#if 0 + intelEmitCopyBlit(intel, + intelImage->mt->cpp, + -src->pitch, + src->buffer, + src->height * src->pitch * src->cpp, + intelImage->mt->pitch, + intelImage->mt->region->buffer, + image_offset, + x, y + height, dstx, dsty, width, height, + GL_COPY); /* ? */ + intel_batchbuffer_flush(intel->batch); +#else + /* XXX use pipe->region_copy() ??? */ + (void) image_offset; +#endif + } + } + +#if 0 + UNLOCK_HARDWARE(intel); +#endif + +#if 0 + /* GL_SGIS_generate_mipmap -- this can be accelerated now. + * XXX Add a ctx->Driver.GenerateMipmaps() function? + */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + intel_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } +#endif + + return GL_TRUE; +} + + + + + +void +intelCopyTexImage1D(GLcontext * ctx, GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLint border) +{ + struct gl_texture_unit *texUnit = + &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = + _mesa_select_tex_object(ctx, texUnit, target); + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, level); + + if (border) + goto fail; + + /* Setup or redefine the texture object, mipmap tree and texture + * image. Don't populate yet. + */ + ctx->Driver.TexImage1D(ctx, target, level, internalFormat, + width, border, + GL_RGBA, CHAN_TYPE, NULL, + &ctx->DefaultPacking, texObj, texImage); + + if (!do_copy_texsubimage(ctx, + st_texture_image(texImage), + internalFormat, 0, 0, x, y, width, 1)) + goto fail; + + return; + + fail: +#if 0 + _swrast_copy_teximage1d(ctx, target, level, internalFormat, x, y, + width, border); +#endif + ; +} + +void +intelCopyTexImage2D(GLcontext * ctx, GLenum target, GLint level, + GLenum internalFormat, + GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + struct gl_texture_unit *texUnit = + &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = + _mesa_select_tex_object(ctx, texUnit, target); + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, level); + + if (border) + goto fail; + + /* Setup or redefine the texture object, mipmap tree and texture + * image. Don't populate yet. + */ + ctx->Driver.TexImage2D(ctx, target, level, internalFormat, + width, height, border, + GL_RGBA, CHAN_TYPE, NULL, + &ctx->DefaultPacking, texObj, texImage); + + + if (!do_copy_texsubimage(ctx, + st_texture_image(texImage), + internalFormat, 0, 0, x, y, width, height)) + goto fail; + + return; + + fail: +#if 0 + _swrast_copy_teximage2d(ctx, target, level, internalFormat, x, y, + width, height, border); +#endif + assert(0); +} + + +void +intelCopyTexSubImage1D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint x, GLint y, GLsizei width) +{ + struct gl_texture_unit *texUnit = + &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = + _mesa_select_tex_object(ctx, texUnit, target); + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, level); + GLenum internalFormat = texImage->InternalFormat; + + /* XXX need to check as in above function? */ + + /* Need to check texture is compatible with source format. + */ + + if (!do_copy_texsubimage(ctx, + st_texture_image(texImage), + internalFormat, xoffset, 0, x, y, width, 1)) { +#if 0 + _swrast_copy_texsubimage1d(ctx, target, level, xoffset, x, y, width); +#endif + assert(0); + } +} + + + +void +intelCopyTexSubImage2D(GLcontext * ctx, GLenum target, GLint level, + GLint xoffset, GLint yoffset, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + struct gl_texture_unit *texUnit = + &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; + struct gl_texture_object *texObj = + _mesa_select_tex_object(ctx, texUnit, target); + struct gl_texture_image *texImage = + _mesa_select_tex_image(ctx, texObj, target, level); + GLenum internalFormat = texImage->InternalFormat; + + + /* Need to check texture is compatible with source format. + */ + + if (!do_copy_texsubimage(ctx, + st_texture_image(texImage), + internalFormat, + xoffset, yoffset, x, y, width, height)) { +#if 0 + _swrast_copy_texsubimage2d(ctx, target, level, + xoffset, yoffset, x, y, width, height); +#endif + assert(0); + } +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_format.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_format.c new file mode 100644 index 00000000000..a11718bb075 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_format.c @@ -0,0 +1,172 @@ +#include "intel_context.h" +#include "intel_tex.h" +#include "texformat.h" +#include "enums.h" + +/* It works out that this function is fine for all the supported + * hardware. However, there is still a need to map the formats onto + * hardware descriptors. + */ +/* Note that the i915 can actually support many more formats than + * these if we take the step of simply swizzling the colors + * immediately after sampling... + */ +const struct gl_texture_format * +intelChooseTextureFormat(GLcontext * ctx, GLint internalFormat, + GLenum format, GLenum type) +{ + struct intel_context *intel = intel_context(ctx); + const GLboolean do32bpt = (intel->intelScreen->front.cpp == 4); + + switch (internalFormat) { + case 4: + case GL_RGBA: + case GL_COMPRESSED_RGBA: + if (format == GL_BGRA) { + if (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_INT_8_8_8_8_REV) { + return &_mesa_texformat_argb8888; + } + else if (type == GL_UNSIGNED_SHORT_4_4_4_4_REV) { + return &_mesa_texformat_argb4444; + } + else if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV) { + return &_mesa_texformat_argb1555; + } + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case 3: + case GL_RGB: + case GL_COMPRESSED_RGB: + if (format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5) { + return &_mesa_texformat_rgb565; + } + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_rgb565; + + case GL_RGBA8: + case GL_RGB10_A2: + case GL_RGBA12: + case GL_RGBA16: + return do32bpt ? &_mesa_texformat_argb8888 : &_mesa_texformat_argb4444; + + case GL_RGBA4: + case GL_RGBA2: + return &_mesa_texformat_argb4444; + + case GL_RGB5_A1: + return &_mesa_texformat_argb1555; + + case GL_RGB8: + case GL_RGB10: + case GL_RGB12: + case GL_RGB16: + return &_mesa_texformat_argb8888; + + case GL_RGB5: + case GL_RGB4: + case GL_R3_G3_B2: + return &_mesa_texformat_rgb565; + + case GL_ALPHA: + case GL_ALPHA4: + case GL_ALPHA8: + case GL_ALPHA12: + case GL_ALPHA16: + case GL_COMPRESSED_ALPHA: + return &_mesa_texformat_a8; + + case 1: + case GL_LUMINANCE: + case GL_LUMINANCE4: + case GL_LUMINANCE8: + case GL_LUMINANCE12: + case GL_LUMINANCE16: + case GL_COMPRESSED_LUMINANCE: + return &_mesa_texformat_l8; + + case 2: + case GL_LUMINANCE_ALPHA: + case GL_LUMINANCE4_ALPHA4: + case GL_LUMINANCE6_ALPHA2: + case GL_LUMINANCE8_ALPHA8: + case GL_LUMINANCE12_ALPHA4: + case GL_LUMINANCE12_ALPHA12: + case GL_LUMINANCE16_ALPHA16: + case GL_COMPRESSED_LUMINANCE_ALPHA: + return &_mesa_texformat_al88; + + case GL_INTENSITY: + case GL_INTENSITY4: + case GL_INTENSITY8: + case GL_INTENSITY12: + case GL_INTENSITY16: + case GL_COMPRESSED_INTENSITY: + return &_mesa_texformat_i8; + + case GL_YCBCR_MESA: + if (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE) + return &_mesa_texformat_ycbcr; + else + return &_mesa_texformat_ycbcr_rev; + + case GL_COMPRESSED_RGB_FXT1_3DFX: + return &_mesa_texformat_rgb_fxt1; + case GL_COMPRESSED_RGBA_FXT1_3DFX: + return &_mesa_texformat_rgba_fxt1; + + case GL_RGB_S3TC: + case GL_RGB4_S3TC: + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + return &_mesa_texformat_rgb_dxt1; + + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + return &_mesa_texformat_rgba_dxt1; + + case GL_RGBA_S3TC: + case GL_RGBA4_S3TC: + case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: + return &_mesa_texformat_rgba_dxt3; + + case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: + return &_mesa_texformat_rgba_dxt5; + + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT24: + case GL_DEPTH_COMPONENT32: + return &_mesa_texformat_z16; + + case GL_DEPTH_STENCIL_EXT: + case GL_DEPTH24_STENCIL8_EXT: + return &_mesa_texformat_z24_s8; + + default: + fprintf(stderr, "unexpected texture format %s in %s\n", + _mesa_lookup_enum_by_nr(internalFormat), __FUNCTION__); + return NULL; + } + + return NULL; /* never get here */ +} + +int intel_compressed_num_bytes(GLuint mesaFormat) +{ + int bytes = 0; + switch(mesaFormat) { + + case MESA_FORMAT_RGB_FXT1: + case MESA_FORMAT_RGBA_FXT1: + case MESA_FORMAT_RGB_DXT1: + case MESA_FORMAT_RGBA_DXT1: + bytes = 2; + break; + + case MESA_FORMAT_RGBA_DXT3: + case MESA_FORMAT_RGBA_DXT5: + bytes = 4; + default: + break; + } + + return bytes; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_image.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_image.c new file mode 100644 index 00000000000..93a59b68960 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_image.c @@ -0,0 +1,695 @@ +/************************************************************************** + * + * 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. + * + **************************************************************************/ + + +#include "glheader.h" +#include "macros.h" +#include "mtypes.h" +#include "enums.h" +#include "colortab.h" +#include "convolve.h" +#include "context.h" +#include "simple_list.h" +#include "texcompress.h" +#include "texformat.h" +#include "texobj.h" +#include "texstore.h" + +#include "pipe/p_context.h" +#include "state_tracker/st_mipmap_tree.h" + +#include "intel_tex.h" + + + +#define FILE_DEBUG_FLAG DEBUG_TEXTURE + +/* Functions to store texture images. Where possible, mipmap_tree's + * will be created or further instantiated with image data, otherwise + * images will be stored in malloc'd memory. A validation step is + * required to pull those images into a mipmap tree, or otherwise + * decide a fallback is required. + */ + + +static int +logbase2(int n) +{ + GLint i = 1; + GLint log2 = 0; + + while (n > i) { + i *= 2; + log2++; + } + + return log2; +} + + +/* Otherwise, store it in memory if (Border != 0) or (any dimension == + * 1). + * + * Otherwise, if max_level >= level >= min_level, create tree with + * space for textures from min_level down to max_level. + * + * Otherwise, create tree with space for textures from (level + * 0)..(1x1). Consider pruning this tree at a validation if the + * saving is worth it. + */ +static void +guess_and_alloc_mipmap_tree(struct pipe_context *pipe, + struct st_texture_object *intelObj, + struct st_texture_image *intelImage) +{ + GLuint firstLevel; + GLuint lastLevel; + GLuint width = intelImage->base.Width; + GLuint height = intelImage->base.Height; + GLuint depth = intelImage->base.Depth; + GLuint l2width, l2height, l2depth; + GLuint i, comp_byte = 0; + + DBG("%s\n", __FUNCTION__); + + if (intelImage->base.Border) + return; + + if (intelImage->level > intelObj->base.BaseLevel && + (intelImage->base.Width == 1 || + (intelObj->base.Target != GL_TEXTURE_1D && + intelImage->base.Height == 1) || + (intelObj->base.Target == GL_TEXTURE_3D && + intelImage->base.Depth == 1))) + return; + + /* If this image disrespects BaseLevel, allocate from level zero. + * Usually BaseLevel == 0, so it's unlikely to happen. + */ + if (intelImage->level < intelObj->base.BaseLevel) + firstLevel = 0; + else + firstLevel = intelObj->base.BaseLevel; + + + /* Figure out image dimensions at start level. + */ + for (i = intelImage->level; i > firstLevel; i--) { + width <<= 1; + if (height != 1) + height <<= 1; + if (depth != 1) + depth <<= 1; + } + + /* Guess a reasonable value for lastLevel. This is probably going + * to be wrong fairly often and might mean that we have to look at + * resizable buffers, or require that buffers implement lazy + * pagetable arrangements. + */ + if ((intelObj->base.MinFilter == GL_NEAREST || + intelObj->base.MinFilter == GL_LINEAR) && + intelImage->level == firstLevel) { + lastLevel = firstLevel; + } + else { + l2width = logbase2(width); + l2height = logbase2(height); + l2depth = logbase2(depth); + lastLevel = firstLevel + MAX2(MAX2(l2width, l2height), l2depth); + } + + assert(!intelObj->mt); + if (intelImage->base.IsCompressed) + comp_byte = intel_compressed_num_bytes(intelImage->base.TexFormat->MesaFormat); + intelObj->mt = st_miptree_create(pipe, + intelObj->base.Target, + intelImage->base.InternalFormat, + firstLevel, + lastLevel, + width, + height, + depth, + intelImage->base.TexFormat->TexelBytes, + comp_byte); + + DBG("%s - success\n", __FUNCTION__); +} + + + + +static GLuint +target_to_face(GLenum target) +{ + switch (target) { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: + return ((GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); + default: + return 0; + } +} + + + +/* There are actually quite a few combinations this will work for, + * more than what I've listed here. + */ +static GLboolean +check_pbo_format(GLint internalFormat, + GLenum format, GLenum type, + const struct gl_texture_format *mesa_format) +{ + switch (internalFormat) { + case 4: + case GL_RGBA: + return (format == GL_BGRA && + (type == GL_UNSIGNED_BYTE || + type == GL_UNSIGNED_INT_8_8_8_8_REV) && + mesa_format == &_mesa_texformat_argb8888); + case 3: + case GL_RGB: + return (format == GL_RGB && + type == GL_UNSIGNED_SHORT_5_6_5 && + mesa_format == &_mesa_texformat_rgb565); + case GL_YCBCR_MESA: + return (type == GL_UNSIGNED_SHORT_8_8_MESA || type == GL_UNSIGNED_BYTE); + default: + return GL_FALSE; + } +} + + +/* XXX: Do this for TexSubImage also: + */ +static GLboolean +try_pbo_upload(struct intel_context *intel, + struct st_texture_image *intelImage, + const struct gl_pixelstore_attrib *unpack, + GLint internalFormat, + GLint width, GLint height, + GLenum format, GLenum type, const void *pixels) +{ + return GL_FALSE; /* XXX fix flushing/locking/blitting below */ +#if 000 + struct intel_buffer_object *pbo = intel_buffer_object(unpack->BufferObj); + GLuint src_offset, src_stride; + GLuint dst_offset, dst_stride; + + if (!pbo || + intel->ctx._ImageTransferState || + unpack->SkipPixels || unpack->SkipRows) { + _mesa_printf("%s: failure 1\n", __FUNCTION__); + return GL_FALSE; + } + + src_offset = (GLuint) pixels; + + if (unpack->RowLength > 0) + src_stride = unpack->RowLength; + else + src_stride = width; + + dst_offset = st_miptree_image_offset(intelImage->mt, + intelImage->face, + intelImage->level); + + dst_stride = intelImage->mt->pitch; + + intelFlush(&intel->ctx); + LOCK_HARDWARE(intel); + { + struct _DriBufferObject *src_buffer = + intel_bufferobj_buffer(intel, pbo, INTEL_READ); + + /* Temporary hack: cast to _DriBufferObject: + */ + struct _DriBufferObject *dst_buffer = + (struct _DriBufferObject *)intelImage->mt->region->buffer; + + + intelEmitCopyBlit(intel, + intelImage->mt->cpp, + src_stride, src_buffer, src_offset, + dst_stride, dst_buffer, dst_offset, + 0, 0, 0, 0, width, height, + GL_COPY); + + intel_batchbuffer_flush(intel->batch); + } + UNLOCK_HARDWARE(intel); + + return GL_TRUE; +#endif +} + + + +static GLboolean +try_pbo_zcopy(struct intel_context *intel, + struct st_texture_image *intelImage, + const struct gl_pixelstore_attrib *unpack, + GLint internalFormat, + GLint width, GLint height, + GLenum format, GLenum type, const void *pixels) +{ + return GL_FALSE; +} + + + + + + +static void +intelTexImage(GLcontext * ctx, + GLint dims, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *unpack, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, GLsizei imageSize, int compressed) +{ + struct intel_context *intel = intel_context(ctx); + struct st_texture_object *intelObj = st_texture_object(texObj); + struct st_texture_image *intelImage = st_texture_image(texImage); + GLint postConvWidth = width; + GLint postConvHeight = height; + GLint texelBytes, sizeInBytes; + GLuint dstRowStride; + + + DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(target), level, width, height, depth, border); + + intelFlush(ctx); + + intelImage->face = target_to_face(target); + intelImage->level = level; + + if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) { + _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth, + &postConvHeight); + } + + /* choose the texture format */ + texImage->TexFormat = intelChooseTextureFormat(ctx, internalFormat, + format, type); + + _mesa_set_fetch_functions(texImage, dims); + + if (texImage->TexFormat->TexelBytes == 0) { + /* must be a compressed format */ + texelBytes = 0; + texImage->IsCompressed = GL_TRUE; + texImage->CompressedSize = + ctx->Driver.CompressedTextureSize(ctx, texImage->Width, + texImage->Height, texImage->Depth, + texImage->TexFormat->MesaFormat); + } else { + texelBytes = texImage->TexFormat->TexelBytes; + + /* Minimum pitch of 32 bytes */ + if (postConvWidth * texelBytes < 32) { + postConvWidth = 32 / texelBytes; + texImage->RowStride = postConvWidth; + } + + assert(texImage->RowStride == postConvWidth); + } + + /* Release the reference to a potentially orphaned buffer. + * Release any old malloced memory. + */ + if (intelImage->mt) { + st_miptree_release(intel->pipe, &intelImage->mt); + assert(!texImage->Data); + } + else if (texImage->Data) { + _mesa_align_free(texImage->Data); + } + + /* If this is the only texture image in the tree, could call + * bmBufferData with NULL data to free the old block and avoid + * waiting on any outstanding fences. + */ + if (intelObj->mt && + intelObj->mt->first_level == level && + intelObj->mt->last_level == level && + intelObj->mt->target != GL_TEXTURE_CUBE_MAP_ARB && + !st_miptree_match_image(intelObj->mt, &intelImage->base, + intelImage->face, intelImage->level)) { + + DBG("release it\n"); + st_miptree_release(intel->pipe, &intelObj->mt); + assert(!intelObj->mt); + } + + if (!intelObj->mt) { + guess_and_alloc_mipmap_tree(intel->pipe, intelObj, intelImage); + if (!intelObj->mt) { + DBG("guess_and_alloc_mipmap_tree: failed\n"); + } + } + + assert(!intelImage->mt); + + if (intelObj->mt && + st_miptree_match_image(intelObj->mt, &intelImage->base, + intelImage->face, intelImage->level)) { + + st_miptree_reference(&intelImage->mt, intelObj->mt); + assert(intelImage->mt); + } + + if (!intelImage->mt) + DBG("XXX: Image did not fit into tree - storing in local memory!\n"); + +#if 0 /* XXX FIX when st_buffer_objects are in place */ + /* PBO fastpaths: + */ + if (dims <= 2 && + intelImage->mt && + intel_buffer_object(unpack->BufferObj) && + check_pbo_format(internalFormat, format, + type, intelImage->base.TexFormat)) { + + DBG("trying pbo upload\n"); + + /* Attempt to texture directly from PBO data (zero copy upload). + * + * Currently disable as it can lead to worse as well as better + * performance (in particular when pipe_region_cow() is + * required). + */ + if (intelObj->mt == intelImage->mt && + intelObj->mt->first_level == level && + intelObj->mt->last_level == level) { + + if (try_pbo_zcopy(intel, intelImage, unpack, + internalFormat, + width, height, format, type, pixels)) { + + DBG("pbo zcopy upload succeeded\n"); + return; + } + } + + + /* Otherwise, attempt to use the blitter for PBO image uploads. + */ + if (try_pbo_upload(intel, intelImage, unpack, + internalFormat, + width, height, format, type, pixels)) { + DBG("pbo upload succeeded\n"); + return; + } + + DBG("pbo upload failed\n"); + } +#else + (void) try_pbo_upload; + (void) check_pbo_format; + (void) try_pbo_zcopy; +#endif + + + /* intelCopyTexImage calls this function with pixels == NULL, with + * the expectation that the mipmap tree will be set up but nothing + * more will be done. This is where those calls return: + */ + if (compressed) { + pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels, + unpack, + "glCompressedTexImage"); + } else { + pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1, + format, type, + pixels, unpack, "glTexImage"); + } + if (!pixels) + return; + + + if (intelImage->mt) + intel->pipe->region_idle(intel->pipe, intelImage->mt->region); + + LOCK_HARDWARE(intel); + + if (intelImage->mt) { + texImage->Data = st_miptree_image_map(intel->pipe, + intelImage->mt, + intelImage->face, + intelImage->level, + &dstRowStride, + intelImage->base.ImageOffsets); + } + else { + /* Allocate regular memory and store the image there temporarily. */ + if (texImage->IsCompressed) { + sizeInBytes = texImage->CompressedSize; + dstRowStride = + _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width); + assert(dims != 3); + } + else { + dstRowStride = postConvWidth * texelBytes; + sizeInBytes = depth * dstRowStride * postConvHeight; + } + + texImage->Data = malloc(sizeInBytes); + } + + DBG("Upload image %dx%dx%d row_len %x " + "pitch %x\n", + width, height, depth, width * texelBytes, dstRowStride); + + /* Copy data. Would like to know when it's ok for us to eg. use + * the blitter to copy. Or, use the hardware to do the format + * conversion and copy: + */ + if (compressed) { + memcpy(texImage->Data, pixels, imageSize); + } else if (!texImage->TexFormat->StoreImage(ctx, dims, + texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, 0, 0, 0, /* dstX/Y/Zoffset */ + dstRowStride, + texImage->ImageOffsets, + width, height, depth, + format, type, pixels, unpack)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage"); + } + + _mesa_unmap_teximage_pbo(ctx, unpack); + + if (intelImage->mt) { + st_miptree_image_unmap(intel->pipe, intelImage->mt); + texImage->Data = NULL; + } + + UNLOCK_HARDWARE(intel); + +#if 0 + /* GL_SGIS_generate_mipmap -- this can be accelerated now. + */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + intel_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } +#endif +} + +void +intelTexImage3D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint depth, + GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *unpack, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexImage(ctx, 3, target, level, + internalFormat, width, height, depth, border, + format, type, pixels, unpack, texObj, texImage, 0, 0); +} + + +void +intelTexImage2D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *unpack, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexImage(ctx, 2, target, level, + internalFormat, width, height, 1, border, + format, type, pixels, unpack, texObj, texImage, 0, 0); +} + +void +intelTexImage1D(GLcontext * ctx, + GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint border, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *unpack, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexImage(ctx, 1, target, level, + internalFormat, width, 1, 1, border, + format, type, pixels, unpack, texObj, texImage, 0, 0); +} + +void intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, + GLint width, GLint height, GLint border, + GLsizei imageSize, const GLvoid *data, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage ) +{ + intelTexImage(ctx, 2, target, level, + internalFormat, width, height, 1, border, + 0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, 1); +} + +/** + * Need to map texture image into memory before copying image data, + * then unmap it. + */ +static void +intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage, int compressed) +{ + struct intel_context *intel = intel_context(ctx); + struct st_texture_image *intelImage = st_texture_image(texImage); + + /* Map */ + if (intelImage->mt) { + /* Image is stored in hardware format in a buffer managed by the + * kernel. Need to explicitly map and unmap it. + */ + intelImage->base.Data = + st_miptree_image_map(intel->pipe, + intelImage->mt, + intelImage->face, + intelImage->level, + &intelImage->base.RowStride, + intelImage->base.ImageOffsets); + intelImage->base.RowStride /= intelImage->mt->cpp; + } + else { + /* Otherwise, the image should actually be stored in + * intelImage->base.Data. This is pretty confusing for + * everybody, I'd much prefer to separate the two functions of + * texImage->Data - storage for texture images in main memory + * and access (ie mappings) of images. In other words, we'd + * create a new texImage->Map field and leave Data simply for + * storage. + */ + assert(intelImage->base.Data); + } + + + if (compressed) { + _mesa_get_compressed_teximage(ctx, target, level, pixels, + texObj, texImage); + } else { + _mesa_get_teximage(ctx, target, level, format, type, pixels, + texObj, texImage); + } + + + /* Unmap */ + if (intelImage->mt) { + st_miptree_image_unmap(intel->pipe, intelImage->mt); + intelImage->base.Data = NULL; + } +} + +void +intelGetTexImage(GLcontext * ctx, GLenum target, GLint level, + GLenum format, GLenum type, GLvoid * pixels, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intel_get_tex_image(ctx, target, level, format, type, pixels, + texObj, texImage, 0); + + +} + +void +intelGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level, + GLvoid *pixels, + const struct gl_texture_object *texObj, + const struct gl_texture_image *texImage) +{ + intel_get_tex_image(ctx, target, level, 0, 0, pixels, + texObj, texImage, 1); + +} + +void +intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname, + unsigned long long offset, GLint depth, GLuint pitch) +{ + 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->mt) + st_miptree_release(intel->pipe, &stObj->mt); + + stObj->imageOverride = GL_TRUE; + stObj->depthOverride = depth; + stObj->pitchOverride = pitch; + + if (offset) + stObj->textureOffset = offset; +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_layout.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_layout.c new file mode 120000 index 00000000000..fe61b441945 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_layout.c @@ -0,0 +1 @@ +../intel/intel_tex_layout.c \ No newline at end of file diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_subimage.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_subimage.c new file mode 100644 index 00000000000..0937114c7fe --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_subimage.c @@ -0,0 +1,192 @@ + +/************************************************************************** + * + * 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 "mtypes.h" +#include "texobj.h" +#include "texstore.h" +#include "enums.h" + +/* +#include "intel_context.h" +*/ +#include "intel_tex.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_mipmap_tree.h" + +#include "pipe/p_context.h" + + +#define FILE_DEBUG_FLAG DEBUG_TEXTURE + +static void +intelTexSubimage(GLcontext * ctx, + GLint dims, + GLenum target, GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLint width, GLint height, GLint depth, + GLenum format, GLenum type, const void *pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + struct pipe_context *pipe = ctx->st->pipe; + struct st_texture_image *intelImage = st_texture_image(texImage); + GLuint dstRowStride; + + DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__, + _mesa_lookup_enum_by_nr(target), + level, xoffset, yoffset, width, height); + + intelFlush(ctx); + + pixels = + _mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format, + type, pixels, packing, "glTexSubImage2D"); + if (!pixels) + return; + + if (intelImage->mt) + pipe->region_idle(pipe, intelImage->mt->region); + +#if 0 + LOCK_HARDWARE(intel); +#endif + + /* Map buffer if necessary. Need to lock to prevent other contexts + * from uploading the buffer under us. + */ + if (intelImage->mt) + texImage->Data = st_miptree_image_map(pipe, + intelImage->mt, + intelImage->face, + intelImage->level, + &dstRowStride, + texImage->ImageOffsets); + + assert(dstRowStride); + + if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat, + texImage->TexFormat, + texImage->Data, + xoffset, yoffset, zoffset, + dstRowStride, + texImage->ImageOffsets, + width, height, depth, + format, type, pixels, packing)) { + _mesa_error(ctx, GL_OUT_OF_MEMORY, "intelTexSubImage"); + } + +#if 0 + /* GL_SGIS_generate_mipmap */ + if (level == texObj->BaseLevel && texObj->GenerateMipmap) { + _mesa_generate_mipmap(ctx, target, + &ctx->Texture.Unit[ctx->Texture.CurrentUnit], + texObj); + } +#endif + + _mesa_unmap_teximage_pbo(ctx, packing); + + if (intelImage->mt) { + st_miptree_image_unmap(pipe, intelImage->mt); + texImage->Data = NULL; + } + +#if 0 + UNLOCK_HARDWARE(intel); +#endif +} + + + + + +void +intelTexSubImage3D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + + intelTexSubimage(ctx, 3, + target, level, + xoffset, yoffset, zoffset, + width, height, depth, + format, type, pixels, packing, texObj, texImage); + +} + + + +void +intelTexSubImage2D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + + intelTexSubimage(ctx, 2, + target, level, + xoffset, yoffset, 0, + width, height, 1, + format, type, pixels, packing, texObj, texImage); + +} + + +void +intelTexSubImage1D(GLcontext * ctx, + GLenum target, + GLint level, + GLint xoffset, + GLsizei width, + GLenum format, GLenum type, + const GLvoid * pixels, + const struct gl_pixelstore_attrib *packing, + struct gl_texture_object *texObj, + struct gl_texture_image *texImage) +{ + intelTexSubimage(ctx, 1, + target, level, + xoffset, 0, 0, + width, 1, 1, + format, type, pixels, packing, texObj, texImage); + +} diff --git a/src/mesa/drivers/dri/intel_winsys/intel_tex_validate.c b/src/mesa/drivers/dri/intel_winsys/intel_tex_validate.c new file mode 100644 index 00000000000..d0631a88f19 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/intel_tex_validate.c @@ -0,0 +1,277 @@ +#include "mtypes.h" +#include "macros.h" + +#include "state_tracker/st_mipmap_tree.h" +#include "intel_tex.h" + +#include "pipe/p_state.h" + +#define FILE_DEBUG_FLAG DEBUG_TEXTURE + +/** + * Compute which mipmap levels that really need to be sent to the hardware. + * This depends on the base image size, GL_TEXTURE_MIN_LOD, + * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. + */ +static void +intel_calculate_first_last_level(struct st_texture_object *intelObj) +{ + struct gl_texture_object *tObj = &intelObj->base; + const struct gl_texture_image *const baseImage = + tObj->Image[0][tObj->BaseLevel]; + + /* These must be signed values. MinLod and MaxLod can be negative numbers, + * and having firstLevel and lastLevel as signed prevents the need for + * extra sign checks. + */ + int firstLevel; + int lastLevel; + + /* Yes, this looks overly complicated, but it's all needed. + */ + switch (tObj->Target) { + case GL_TEXTURE_1D: + case GL_TEXTURE_2D: + case GL_TEXTURE_3D: + case GL_TEXTURE_CUBE_MAP: + if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { + /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. + */ + firstLevel = lastLevel = tObj->BaseLevel; + } + else { + firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); + firstLevel = MAX2(firstLevel, tObj->BaseLevel); + lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); + lastLevel = MAX2(lastLevel, tObj->BaseLevel); + lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); + lastLevel = MIN2(lastLevel, tObj->MaxLevel); + lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ + } + break; + case GL_TEXTURE_RECTANGLE_NV: + case GL_TEXTURE_4D_SGIS: + firstLevel = lastLevel = 0; + break; + default: + return; + } + + /* save these values */ + intelObj->firstLevel = firstLevel; + intelObj->lastLevel = lastLevel; +} + +static void +copy_image_data_to_tree(struct pipe_context *pipe, + struct st_texture_object *intelObj, + struct st_texture_image *intelImage) +{ + if (intelImage->mt) { + /* Copy potentially with the blitter: + */ + st_miptree_image_copy(pipe, + intelObj->mt, + intelImage->face, + intelImage->level, intelImage->mt); + + st_miptree_release(pipe, &intelImage->mt); + } + else { + assert(intelImage->base.Data != NULL); + + /* More straightforward upload. + */ + st_miptree_image_data(pipe, + intelObj->mt, + intelImage->face, + intelImage->level, + intelImage->base.Data, + intelImage->base.RowStride, + intelImage->base.RowStride * + intelImage->base.Height); + _mesa_align_free(intelImage->base.Data); + intelImage->base.Data = NULL; + } + + st_miptree_reference(&intelImage->mt, intelObj->mt); +} + + +/* + */ +GLuint +intel_finalize_mipmap_tree(GLcontext *ctx, + struct pipe_context *pipe, GLuint unit, + GLboolean *needFlush) +{ + struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; + struct st_texture_object *intelObj = st_texture_object(tObj); + int comp_byte = 0; + int cpp; + + GLuint face, i; + GLuint nr_faces = 0; + struct st_texture_image *firstImage; + + *needFlush = GL_FALSE; + + /* We know/require this is true by now: + */ + assert(intelObj->base._Complete); + + /* What levels must the tree include at a minimum? + */ + intel_calculate_first_last_level(intelObj); + firstImage = + st_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); + + /* Fallback case: + */ + if (firstImage->base.Border) { + if (intelObj->mt) { + st_miptree_release(pipe, &intelObj->mt); + } + return GL_FALSE; + } + + + /* If both firstImage and intelObj have a tree which can contain + * all active images, favour firstImage. Note that because of the + * completeness requirement, we know that the image dimensions + * will match. + */ + if (firstImage->mt && + firstImage->mt != intelObj->mt && + firstImage->mt->first_level <= intelObj->firstLevel && + firstImage->mt->last_level >= intelObj->lastLevel) { + + if (intelObj->mt) + st_miptree_release(pipe, &intelObj->mt); + + st_miptree_reference(&intelObj->mt, firstImage->mt); + } + + if (firstImage->base.IsCompressed) { + comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); + cpp = comp_byte; + } + else cpp = firstImage->base.TexFormat->TexelBytes; + + /* Check tree can hold all active levels. Check tree matches + * target, imageFormat, etc. + * + * XXX: For some layouts (eg i945?), the test might have to be + * first_level == firstLevel, as the tree isn't valid except at the + * original start level. Hope to get around this by + * programming minLod, maxLod, baseLevel into the hardware and + * leaving the tree alone. + */ + if (intelObj->mt && + (intelObj->mt->target != intelObj->base.Target || + intelObj->mt->internal_format != firstImage->base.InternalFormat || + intelObj->mt->first_level != intelObj->firstLevel || + intelObj->mt->last_level != intelObj->lastLevel || + intelObj->mt->width0 != firstImage->base.Width || + intelObj->mt->height0 != firstImage->base.Height || + intelObj->mt->depth0 != firstImage->base.Depth || + intelObj->mt->cpp != cpp || + intelObj->mt->compressed != firstImage->base.IsCompressed)) { + st_miptree_release(pipe, &intelObj->mt); + } + + + /* May need to create a new tree: + */ + if (!intelObj->mt) { + intelObj->mt = st_miptree_create(pipe, + intelObj->base.Target, + firstImage->base.InternalFormat, + intelObj->firstLevel, + intelObj->lastLevel, + firstImage->base.Width, + firstImage->base.Height, + firstImage->base.Depth, + cpp, + comp_byte); + } + + /* Pull in any images not in the object's tree: + */ + nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + for (face = 0; face < nr_faces; face++) { + for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { + struct st_texture_image *intelImage = + st_texture_image(intelObj->base.Image[face][i]); + + /* Need to import images in main memory or held in other trees. + */ + if (intelObj->mt != intelImage->mt) { + copy_image_data_to_tree(pipe, intelObj, intelImage); + *needFlush = GL_TRUE; + } + } + } + + /** + if (need_flush) + intel_batchbuffer_flush(intel->batch); + **/ + + return GL_TRUE; +} + + +#if 0 /* unused? */ +void +intel_tex_map_images(struct pipe_context *pipe, + struct st_texture_object *intelObj) +{ + GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + GLuint face, i; + + DBG("%s\n", __FUNCTION__); + + for (face = 0; face < nr_faces; face++) { + for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { + struct st_texture_image *intelImage = + st_texture_image(intelObj->base.Image[face][i]); + + if (intelImage->mt) { + intelImage->base.Data = + st_miptree_image_map(pipe, + intelImage->mt, + intelImage->face, + intelImage->level, + &intelImage->base.RowStride, + intelImage->base.ImageOffsets); + /* convert stride to texels, not bytes */ + intelImage->base.RowStride /= intelImage->mt->cpp; +/* intelImage->base.ImageStride /= intelImage->mt->cpp; */ + } + } + } +} + + + +void +intel_tex_unmap_images(struct pipe_context *pipe, + struct st_texture_object *intelObj) +{ + GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + GLuint face, i; + + for (face = 0; face < nr_faces; face++) { + for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { + struct st_texture_image *intelImage = + st_texture_image(intelObj->base.Image[face][i]); + + if (intelImage->mt) { + st_miptree_image_unmap(pipe, intelImage->mt); + intelImage->base.Data = NULL; + } + } + } +} +#endif diff --git a/src/mesa/drivers/dri/intel_winsys/server/i830_common.h b/src/mesa/drivers/dri/intel_winsys/server/i830_common.h new file mode 100644 index 00000000000..d4d58886ce0 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/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/mesa/drivers/dri/intel_winsys/server/i830_dri.h b/src/mesa/drivers/dri/intel_winsys/server/i830_dri.h new file mode 100644 index 00000000000..c2a3af8cbf7 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/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/mesa/drivers/dri/intel_winsys/server/intel.h b/src/mesa/drivers/dri/intel_winsys/server/intel.h new file mode 100644 index 00000000000..6ea72499c1c --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/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 + +# 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/mesa/drivers/dri/intel_winsys/server/intel_dri.c b/src/mesa/drivers/dri/intel_winsys/server/intel_dri.c new file mode 100644 index 00000000000..e49c4214ad4 --- /dev/null +++ b/src/mesa/drivers/dri/intel_winsys/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 +#include +#include +#include +#include + +#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 +};