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

📄 dri_bufmgr_fake.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/************************************************************************** *  * 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. *  **************************************************************************//* Originally a fake version of the buffer manager so that we can * prototype the changes in a driver fairly quickly, has been fleshed * out to a fully functional interim solution. * * Basically wraps the old style memory management in the new * programming interface, but is more expressive and avoids many of * the bugs in the old texture manager. */#include "mtypes.h"#include "dri_bufmgr.h"#include "drm.h"#include "simple_list.h"#include "mm.h"#include "imports.h"#define DBG(...) do {					\   if (bufmgr_fake->bufmgr.debug)			\      _mesa_printf(__VA_ARGS__);			\} while (0)/* Internal flags: */#define BM_NO_BACKING_STORE			0x00000001#define BM_NO_FENCE_SUBDATA			0x00000002#define BM_PINNED				0x00000004/* Wrapper around mm.c's mem_block, which understands that you must * wait for fences to expire before memory can be freed.  This is * specific to our use of memcpy for uploads - an upload that was * processed through the command queue wouldn't need to care about * fences. */#define MAX_RELOCS 4096struct fake_buffer_reloc{   /** Buffer object that the relocation points at. */   dri_bo *target_buf;   /** Offset of the relocation entry within reloc_buf. */   GLuint offset;   /** Cached value of the offset when we last performed this relocation. */   GLuint last_target_offset;   /** Value added to target_buf's offset to get the relocation entry. */   GLuint delta;   /** Flags to validate the target buffer under. */   uint64_t validate_flags;};struct block {   struct block *next, *prev;   struct mem_block *mem;	/* BM_MEM_AGP */   /**    * Marks that the block is currently in the aperture and has yet to be    * fenced.    */   unsigned on_hardware:1;   /**    * Marks that the block is currently fenced (being used by rendering) and    * can't be freed until @fence is passed.    */   unsigned fenced:1;   /** Fence cookie for the block. */   unsigned fence; /* Split to read_fence, write_fence */   dri_bo *bo;   void *virtual;};typedef struct _bufmgr_fake {   dri_bufmgr bufmgr;   unsigned long low_offset;   unsigned long size;   void *virtual;   struct mem_block *heap;   struct block lru;		/* only allocated, non-fence-pending blocks here */   unsigned buf_nr;		/* for generating ids */   struct block on_hardware;	/* after bmValidateBuffers */   struct block fenced;		/* after bmFenceBuffers (mi_flush, emit irq, write dword) */                                /* then to bufmgr->lru or free() */   unsigned int last_fence;   unsigned fail:1;   unsigned need_fence:1;   GLboolean thrashing;   /**    * Driver callback to emit a fence, returning the cookie.    *    * Currently, this also requires that a write flush be emitted before    * emitting the fence, but this should change.    */   unsigned int (*fence_emit)(void *private);   /** Driver callback to wait for a fence cookie to have passed. */   int (*fence_wait)(void *private, unsigned int fence_cookie);   /** Driver-supplied argument to driver callbacks */   void *driver_priv;   GLboolean debug;   GLboolean performed_rendering;   /* keep track of the current total size of objects we have relocs for */   unsigned long current_total_size;} dri_bufmgr_fake;typedef struct _dri_bo_fake {   dri_bo bo;   unsigned id;			/* debug only */   const char *name;   unsigned dirty:1;   unsigned size_accounted:1; /*this buffers size has been accounted against the aperture */   unsigned card_dirty:1; /* has the card written to this buffer - we make need to copy it back */   unsigned int refcount;   /* Flags may consist of any of the DRM_BO flags, plus    * DRM_BO_NO_BACKING_STORE and BM_NO_FENCE_SUBDATA, which are the first two    * driver private flags.    */   uint64_t flags;   unsigned int alignment;   GLboolean is_static, validated;   unsigned int map_count;   /* Flags for the buffer to be validated with in command submission */   uint64_t validate_flags;   /** relocation list */   struct fake_buffer_reloc *relocs;   GLuint nr_relocs;   struct block *block;   void *backing_store;   void (*invalidate_cb)(dri_bo *bo, void *ptr);   void *invalidate_ptr;} dri_bo_fake;typedef struct _dri_fence_fake {   dri_fence fence;   const char *name;   unsigned int refcount;   unsigned int fence_cookie;   GLboolean flushed;} dri_fence_fake;static int clear_fenced(dri_bufmgr_fake *bufmgr_fake,			unsigned int fence_cookie);static int dri_fake_check_aperture_space(dri_bo *bo);#define MAXFENCE 0x7fffffffstatic GLboolean FENCE_LTE( unsigned a, unsigned b ){   if (a == b)      return GL_TRUE;   if (a < b && b - a < (1<<24))      return GL_TRUE;   if (a > b && MAXFENCE - a + b < (1<<24))      return GL_TRUE;   return GL_FALSE;}static unsigned int_fence_emit_internal(dri_bufmgr_fake *bufmgr_fake){   bufmgr_fake->last_fence = bufmgr_fake->fence_emit(bufmgr_fake->driver_priv);   return bufmgr_fake->last_fence;}static void_fence_wait_internal(dri_bufmgr_fake *bufmgr_fake, unsigned int cookie){   int ret;   ret = bufmgr_fake->fence_wait(bufmgr_fake->driver_priv, cookie);   if (ret != 0) {      _mesa_printf("%s:%d: Error %d waiting for fence.\n",		   __FILE__, __LINE__);      abort();   }   clear_fenced(bufmgr_fake, cookie);}static GLboolean_fence_test(dri_bufmgr_fake *bufmgr_fake, unsigned fence){   /* Slight problem with wrap-around:    */   return fence == 0 || FENCE_LTE(fence, bufmgr_fake->last_fence);}/** * Allocate a memory manager block for the buffer. */static GLbooleanalloc_block(dri_bo *bo){   dri_bo_fake *bo_fake = (dri_bo_fake *)bo;   dri_bufmgr_fake *bufmgr_fake= (dri_bufmgr_fake *)bo->bufmgr;   struct block *block = (struct block *)calloc(sizeof *block, 1);   unsigned int align_log2 = _mesa_ffs(bo_fake->alignment) - 1;   GLuint sz;   if (!block)      return GL_FALSE;   sz = (bo->size + bo_fake->alignment - 1) & ~(bo_fake->alignment - 1);   block->mem = mmAllocMem(bufmgr_fake->heap, sz, align_log2, 0);   if (!block->mem) {      free(block);      return GL_FALSE;   }   make_empty_list(block);   /* Insert at head or at tail???       */   insert_at_tail(&bufmgr_fake->lru, block);   block->virtual = bufmgr_fake->virtual +      block->mem->ofs - bufmgr_fake->low_offset;   block->bo = bo;   bo_fake->block = block;   return GL_TRUE;}/* Release the card storage associated with buf: */static void free_block(dri_bufmgr_fake *bufmgr_fake, struct block *block){   dri_bo_fake *bo_fake;   DBG("free block %p %08x %d %d\n", block, block->mem->ofs, block->on_hardware, block->fenced);   if (!block)      return;   bo_fake = (dri_bo_fake *)block->bo;   if (!(bo_fake->flags & BM_NO_BACKING_STORE) && (bo_fake->card_dirty == 1)) {     memcpy(bo_fake->backing_store, block->virtual, block->bo->size);     bo_fake->card_dirty = 1;     bo_fake->dirty = 1;   }   if (block->on_hardware) {      block->bo = NULL;   }   else if (block->fenced) {      block->bo = NULL;   }   else {      DBG("    - free immediately\n");      remove_from_list(block);      mmFreeMem(block->mem);      free(block);   }}static voidalloc_backing_store(dri_bo *bo){   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;   dri_bo_fake *bo_fake = (dri_bo_fake *)bo;   assert(!bo_fake->backing_store);   assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE)));   bo_fake->backing_store = ALIGN_MALLOC(bo->size, 64);   DBG("alloc_backing - buf %d %p %d\n", bo_fake->id, bo_fake->backing_store, bo->size);   assert(bo_fake->backing_store);}static voidfree_backing_store(dri_bo *bo){   dri_bo_fake *bo_fake = (dri_bo_fake *)bo;   if (bo_fake->backing_store) {      assert(!(bo_fake->flags & (BM_PINNED|BM_NO_BACKING_STORE)));      ALIGN_FREE(bo_fake->backing_store);      bo_fake->backing_store = NULL;   }}static voidset_dirty(dri_bo *bo){   dri_bufmgr_fake *bufmgr_fake = (dri_bufmgr_fake *)bo->bufmgr;   dri_bo_fake *bo_fake = (dri_bo_fake *)bo;   if (bo_fake->flags & BM_NO_BACKING_STORE && bo_fake->invalidate_cb != NULL)      bo_fake->invalidate_cb(bo, bo_fake->invalidate_ptr);   assert(!(bo_fake->flags & BM_PINNED));   DBG("set_dirty - buf %d\n", bo_fake->id);   bo_fake->dirty = 1;}static GLbooleanevict_lru(dri_bufmgr_fake *bufmgr_fake, GLuint max_fence){   struct block *block, *tmp;   DBG("%s\n", __FUNCTION__);   foreach_s(block, tmp, &bufmgr_fake->lru) {      dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo;      if (bo_fake != NULL && (bo_fake->flags & BM_NO_FENCE_SUBDATA))	 continue;      if (block->fence && max_fence && !FENCE_LTE(block->fence, max_fence))	 return 0;      set_dirty(&bo_fake->bo);      bo_fake->block = NULL;      free_block(bufmgr_fake, block);      return GL_TRUE;   }   return GL_FALSE;}#define foreach_s_rev(ptr, t, list)   \        for(ptr=(list)->prev,t=(ptr)->prev; list != ptr; ptr=t, t=(t)->prev)static GLbooleanevict_mru(dri_bufmgr_fake *bufmgr_fake){   struct block *block, *tmp;   DBG("%s\n", __FUNCTION__);   foreach_s_rev(block, tmp, &bufmgr_fake->lru) {      dri_bo_fake *bo_fake = (dri_bo_fake *)block->bo;      if (bo_fake && (bo_fake->flags & BM_NO_FENCE_SUBDATA))	 continue;      set_dirty(&bo_fake->bo);      bo_fake->block = NULL;      free_block(bufmgr_fake, block);      return GL_TRUE;   }   return GL_FALSE;}/** * Removes all objects from the fenced list older than the given fence. */static int clear_fenced(dri_bufmgr_fake *bufmgr_fake,			unsigned int fence_cookie){   struct block *block, *tmp;   int ret = 0;   foreach_s(block, tmp, &bufmgr_fake->fenced) {      assert(block->fenced);      if (_fence_test(bufmgr_fake, block->fence)) {	 block->fenced = 0;	 if (!block->bo) {	    DBG("delayed free: offset %x sz %x\n",		block->mem->ofs, block->mem->size);	    remove_from_list(block);	    mmFreeMem(block->mem);	    free(block);

⌨️ 快捷键说明

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