⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 intel_bufmgr.c

📁 mesa-6.5-minigui源码
💻 C
字号:
/************************************************************************** *  * Copyright 2006 Tungsten Graphics, Inc., Steamboat Springs, CO. * 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. *  *  **************************************************************************/#include "intel_bufmgr.h"#include "intel_context.h"#include "intel_ioctl.h"#include "hash.h"#include "simple_list.h"#include "mm.h"#include "imports.h"#include "glthread.h"#include <sys/ioctl.h>#include <unistd.h>#include <drm.h>struct _mesa_HashTable;/* The buffer manager is really part of the gl_shared_state struct. * TODO: Organize for the bufmgr to be created/deleted with the shared * state and stored within the DriverData of that struct.  Currently * there are no mesa callbacks for this. */#define BM_MAX 16static struct bufmgr{   _glthread_Mutex mutex;	/**< for thread safety */   int driFd;   int refcount;   struct _mesa_HashTable *hash;   unsigned buf_nr;			/* for generating ids */   drmMMPool batchPool;} bufmgr_pool[BM_MAX];static int nr_bms;#define LOCK(bm) _glthread_LOCK_MUTEX(bm->mutex)#define UNLOCK(bm) _glthread_UNLOCK_MUTEX(bm->mutex)static voidbmError(int val, const char *file, const char *function, int line){   _mesa_printf("Fatal video memory manager error \"%s\".\n"		"Check kernel logs or set the LIBGL_DEBUG\n"		"environment variable to \"verbose\" for more info.\n"		"Detected in file %s, line %d, function %s.\n",		strerror(-val), file, line, function);#ifndef NDEBUG   exit(-1);#else   abort();#endif}#define BM_CKFATAL(val)					       \  do{							       \    int tstVal = (val);					       \    if (tstVal) 					       \      bmError(tstVal, __FILE__, __FUNCTION__, __LINE__);       \  } while(0);/*********************************************************************** * Public functions *//* The initialization functions are skewed in the fake implementation. * This call would be to attach to an existing manager, rather than to * create a local one. */struct bufmgr *bm_intel_Attach(struct intel_context *intel){   GLuint i;   for (i = 0; i < nr_bms; i++)      if (bufmgr_pool[i].driFd == intel->driFd) {	 bufmgr_pool[i].refcount++;	 _mesa_printf("retrieive old bufmgr for fd %d\n",		      bufmgr_pool[i].driFd);	 return &bufmgr_pool[i];      }   if (nr_bms < BM_MAX) {      struct bufmgr *bm = &bufmgr_pool[nr_bms++];      _mesa_printf("create new bufmgr for fd %d\n", intel->driFd);      bm->driFd = intel->driFd;      bm->hash = _mesa_NewHashTable();      bm->refcount = 1;      _glthread_INIT_MUTEX(bm->mutex);      drmGetLock(bm->driFd, intel->hHWContext, 0);      BM_CKFATAL(drmMMAllocBufferPool(bm->driFd, mmPoolRing, 0,				      DRM_MM_TT | DRM_MM_NO_EVICT |				      DRM_MM_READ | DRM_MM_EXE |				      BM_BATCHBUFFER, 1024 * 1024, 4096,				      &bm->batchPool));      drmUnlock(bm->driFd, intel->hHWContext);      return bm;   }   _mesa_printf("failed to create new bufmgr for fd %d\n", intel->driFd);   return NULL;}voidbmGenBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers, unsigned flags){   LOCK(bm);   {      unsigned i;      unsigned bFlags =	    (flags) ? flags : DRM_MM_TT | DRM_MM_VRAM | DRM_MM_SYSTEM;      for (i = 0; i < n; i++) {	 drmMMBuf *buf = calloc(sizeof(*buf), 1);	 BM_CKFATAL(drmMMInitBuffer(bm->driFd, bFlags, 12, buf));	 buf->client_priv = ++bm->buf_nr;	 buffers[i] = buf->client_priv;	 _mesa_HashInsert(bm->hash, buffers[i], buf);      }   }   UNLOCK(bm);}voidbmSetShared(struct bufmgr *bm, unsigned buffer, unsigned flags,	    unsigned long offset, void *virtual){   LOCK(bm);   {      drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffer);      assert(buf);      buf->flags = DRM_MM_NO_EVICT | DRM_MM_SHARED	    | DRM_MM_WRITE | DRM_MM_READ;      buf->flags |= flags & DRM_MM_MEMTYPE_MASK;      buf->offset = offset;      buf->virtual = virtual;      BM_CKFATAL(drmMMAllocBuffer(bm->driFd, 0, NULL, 0, buf));   }   UNLOCK(bm);}voidbmDeleteBuffers(struct bufmgr *bm, unsigned n, unsigned *buffers){   LOCK(bm);   {      unsigned i;      for (i = 0; i < n; i++) {	 drmMMBuf *buf = _mesa_HashLookup(bm->hash, buffers[i]);	 if (buf) {	    BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));	    _mesa_HashRemove(bm->hash, buffers[i]);	 }      }   }   UNLOCK(bm);}/* If buffer size changes, free and reallocate.  Otherwise update in * place. */voidbmBufferData(struct bufmgr *bm,	     unsigned buffer, unsigned size, const void *data, unsigned flags){   LOCK(bm);   {      drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);      DBG("bmBufferData %d sz 0x%x data: %p\n", buffer, size, data);      assert(buf);      assert(!buf->mapped);      if (buf->flags & BM_BATCHBUFFER) {	 BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));	 BM_CKFATAL(drmMMAllocBuffer		    (bm->driFd, size, &bm->batchPool, 1, buf));      } else if (!(buf->flags & DRM_MM_SHARED)) {	 if (buf->block && (buf->size < size || drmBufIsBusy(bm->driFd, buf))) {	    BM_CKFATAL(drmMMFreeBuffer(bm->driFd, buf));	 }	 if (!buf->block) {	    BM_CKFATAL(drmMMAllocBuffer(bm->driFd, size, NULL, 0, buf));	 }      }      if (data != NULL) {	 memcpy(drmMMMapBuffer(bm->driFd, buf), data, size);	 drmMMUnmapBuffer(bm->driFd, buf);      }   }   UNLOCK(bm);}/* Update the buffer in place, in whatever space it is currently resident: */voidbmBufferSubData(struct bufmgr *bm,		unsigned buffer,		unsigned offset, unsigned size, const void *data){   LOCK(bm);   {      drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);      DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);      assert(buf);      drmBufWaitBusy(bm->driFd, buf);      if (size) {	 memcpy((unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,                data, size);	 drmMMUnmapBuffer(bm->driFd, buf);      }   }   UNLOCK(bm);}/* Extract data from the buffer: */voidbmBufferGetSubData(struct bufmgr *bm,		   unsigned buffer,		   unsigned offset, unsigned size, void *data){   LOCK(bm);   {      drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);      DBG("bmBufferSubdata %d offset 0x%x sz 0x%x\n", buffer, offset, size);      assert(buf);      drmBufWaitBusy(bm->driFd, buf);      if (size) {	 memcpy(data,                (unsigned char *) drmMMMapBuffer(bm->driFd, buf) + offset,                size);	 drmMMUnmapBuffer(bm->driFd, buf);      }   }   UNLOCK(bm);}/* Return a pointer to whatever space the buffer is currently resident in: */void *bmMapBuffer(struct bufmgr *bm, unsigned buffer, unsigned flags){   void *retval;   LOCK(bm);   {      drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);      DBG("bmMapBuffer %d\n", buffer);      DBG("Map: Block is 0x%x\n", &buf->block);      assert(buf);      /* assert(!buf->mapped); */      retval = drmMMMapBuffer(bm->driFd, buf);   }   UNLOCK(bm);   return retval;}voidbmUnmapBuffer(struct bufmgr *bm, unsigned buffer){   LOCK(bm);   {      drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);      if (!buf)	 goto out;      DBG("bmUnmapBuffer %d\n", buffer);      drmMMUnmapBuffer(bm->driFd, buf);   } out:   UNLOCK(bm);}/* Build the list of buffers to validate.  Note that the buffer list * isn't a shared structure so we don't need mutexes when manipulating * it.   * * XXX: need refcounting for drmMMBuf structs so that they can't be * deleted while on these lists. */struct _drmMMBufList *bmNewBufferList(void){   return drmMMInitListHead();}intbmAddBuffer(struct bufmgr *bm,	    struct _drmMMBufList *list,	    unsigned buffer,	    unsigned flags,	    unsigned *memtype_return, unsigned long *offset_return){   drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);   assert(buf);   return drmMMBufListAdd(list, buf, 0, flags, memtype_return, offset_return);}voidbmFreeBufferList(struct _drmMMBufList *list){   drmMMFreeBufList(list);}intbmScanBufferList(struct bufmgr *bm,		 struct _drmMMBufList *list, unsigned buffer){   drmMMBuf *buf = (drmMMBuf *) _mesa_HashLookup(bm->hash, buffer);   assert(buf);   return drmMMScanBufList(list, buf);}/* To be called prior to emitting commands to hardware which reference * these buffers.  The buffer_usage list provides information on where * the buffers should be placed and whether their contents need to be * preserved on copying.  The offset and pool data elements are return * values from this function telling the driver exactly where the * buffers are currently located. */intbmValidateBufferList(struct bufmgr *bm,		     struct _drmMMBufList *list, unsigned flags){   BM_CKFATAL(drmMMValidateBuffers(bm->driFd, list));   return 0;}/* After commands are emitted but before unlocking, this must be * called so that the buffer manager can correctly age the buffers. * The buffer manager keeps track of the list of validated buffers, so * already knows what to apply the fence to. * * The buffer manager knows how to emit and test fences directly * through the drm and without callbacks or whatever into the driver. */unsignedbmFenceBufferList(struct bufmgr *bm, struct _drmMMBufList *list){   drmFence fence;   BM_CKFATAL(drmMMFenceBuffers(bm->driFd, list));   BM_CKFATAL(drmEmitFence(bm->driFd, 0, &fence));   return fence.fenceSeq;}/* This functionality is used by the buffer manager, not really sure * if we need to be exposing it in this way, probably libdrm will * offer equivalent calls. * * For now they can stay, but will likely change/move before final: */unsignedbmSetFence(struct bufmgr *bm){   drmFence dFence;   BM_CKFATAL(drmEmitFence(bm->driFd, 0, &dFence));   return dFence.fenceSeq;}intbmTestFence(struct bufmgr *bm, unsigned fence){   drmFence dFence;   int retired;   dFence.fenceType = 0;   dFence.fenceSeq = fence;   BM_CKFATAL(drmTestFence(bm->driFd, dFence, 0, &retired));   return retired;}voidbmFinishFence(struct bufmgr *bm, unsigned fence){   drmFence dFence;   dFence.fenceType = 0;   dFence.fenceSeq = fence;   BM_CKFATAL(drmWaitFence(bm->driFd, dFence));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -