[intel] Convert drivers to using libdrm bufmgr code.

This commit is contained in:
Eric Anholt
2008-06-03 14:43:48 -07:00
parent fccc427aac
commit 4b5b008d54
35 changed files with 105 additions and 3737 deletions

View File

@@ -11,10 +11,6 @@ COMMON_SOURCES = \
../common/xmlconfig.c \
../common/drirenderbuffer.c
COMMON_BM_SOURCES = \
../common/dri_bufmgr.c
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=
WINLIB=

View File

@@ -1,171 +0,0 @@
/*
* Copyright © 2007 Intel Corporation
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Eric Anholt <eric@anholt.net>
*
*/
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include "mtypes.h"
#include "dri_bufmgr.h"
/** @file dri_bufmgr.c
*
* Convenience functions for buffer management methods.
*/
dri_bo *
dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
unsigned int alignment, uint64_t location_mask)
{
assert((location_mask & ~(DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_PRIV0 |
DRM_BO_FLAG_MEM_PRIV1 | DRM_BO_FLAG_MEM_PRIV2 |
DRM_BO_FLAG_MEM_PRIV3 | DRM_BO_FLAG_MEM_PRIV4 |
DRM_BO_FLAG_CACHED | DRM_BO_FLAG_CACHED_MAPPED)) == 0);
return bufmgr->bo_alloc(bufmgr, name, size, alignment, location_mask);
}
dri_bo *
dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name, unsigned long offset,
unsigned long size, void *virtual,
uint64_t location_mask)
{
assert((location_mask & ~(DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_PRIV0 |
DRM_BO_FLAG_MEM_PRIV1 | DRM_BO_FLAG_MEM_PRIV2 |
DRM_BO_FLAG_MEM_PRIV3 |
DRM_BO_FLAG_MEM_PRIV4)) == 0);
return bufmgr->bo_alloc_static(bufmgr, name, offset, size, virtual,
location_mask);
}
void
dri_bo_reference(dri_bo *bo)
{
bo->bufmgr->bo_reference(bo);
}
void
dri_bo_unreference(dri_bo *bo)
{
if (bo == NULL)
return;
bo->bufmgr->bo_unreference(bo);
}
int
dri_bo_map(dri_bo *buf, GLboolean write_enable)
{
return buf->bufmgr->bo_map(buf, write_enable);
}
int
dri_bo_unmap(dri_bo *buf)
{
return buf->bufmgr->bo_unmap(buf);
}
int
dri_bo_subdata(dri_bo *bo, unsigned long offset,
unsigned long size, const void *data)
{
int ret;
if (bo->bufmgr->bo_subdata)
return bo->bufmgr->bo_subdata(bo, offset, size, data);
if (size == 0 || data == NULL)
return 0;
ret = dri_bo_map(bo, GL_TRUE);
if (ret)
return ret;
memcpy((unsigned char *)bo->virtual + offset, data, size);
dri_bo_unmap(bo);
return 0;
}
int
dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
unsigned long size, void *data)
{
int ret;
if (bo->bufmgr->bo_subdata)
return bo->bufmgr->bo_get_subdata(bo, offset, size, data);
if (size == 0 || data == NULL)
return 0;
ret = dri_bo_map(bo, GL_FALSE);
if (ret)
return ret;
memcpy(data, (unsigned char *)bo->virtual + offset, size);
dri_bo_unmap(bo);
return 0;
}
void
dri_bo_wait_rendering(dri_bo *bo)
{
bo->bufmgr->bo_wait_rendering(bo);
}
void
dri_bufmgr_destroy(dri_bufmgr *bufmgr)
{
bufmgr->destroy(bufmgr);
}
int dri_emit_reloc(dri_bo *reloc_buf,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta, uint32_t offset, dri_bo *target_buf)
{
return reloc_buf->bufmgr->emit_reloc(reloc_buf, read_domains, write_domain,
delta, offset, target_buf);
}
void *dri_process_relocs(dri_bo *batch_buf)
{
return batch_buf->bufmgr->process_relocs(batch_buf);
}
void dri_post_submit(dri_bo *batch_buf)
{
batch_buf->bufmgr->post_submit(batch_buf);
}
void
dri_bufmgr_set_debug(dri_bufmgr *bufmgr, GLboolean enable_debug)
{
bufmgr->debug = enable_debug;
}
int
dri_bufmgr_check_aperture_space(dri_bo *bo)
{
return bo->bufmgr->check_aperture_space(bo);
}

View File

@@ -1,216 +0,0 @@
/**************************************************************************
*
* Copyright <20> 2007 Intel Corporation
* 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<74>m <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
* Eric Anholt <eric@anholt.net>
*/
#ifndef _DRI_BUFMGR_H_
#define _DRI_BUFMGR_H_
#include <xf86drm.h>
typedef struct _dri_bufmgr dri_bufmgr;
typedef struct _dri_bo dri_bo;
struct _dri_bo {
/**
* Size in bytes of the buffer object.
*
* The size may be larger than the size originally requested for the
* allocation, such as being aligned to page size.
*/
unsigned long size;
/**
* Card virtual address (offset from the beginning of the aperture) for the
* object. Only valid while validated.
*/
unsigned long offset;
/**
* Virtual address for accessing the buffer data. Only valid while mapped.
*/
void *virtual;
/** Buffer manager context associated with this buffer object */
dri_bufmgr *bufmgr;
};
/**
* Context for a buffer manager instance.
*
* Contains public methods followed by private storage for the buffer manager.
*/
struct _dri_bufmgr {
/**
* Allocate a buffer object.
*
* Buffer objects are not necessarily initially mapped into CPU virtual
* address space or graphics device aperture. They must be mapped using
* bo_map() to be used by the CPU, and validated for use using bo_validate()
* to be used from the graphics device.
*/
dri_bo *(*bo_alloc)(dri_bufmgr *bufmgr_ctx, const char *name,
unsigned long size, unsigned int alignment,
uint64_t location_mask);
/**
* Allocates a buffer object for a static allocation.
*
* Static allocations are ones such as the front buffer that are offered by
* the X Server, which are never evicted and never moved.
*/
dri_bo *(*bo_alloc_static)(dri_bufmgr *bufmgr_ctx, const char *name,
unsigned long offset, unsigned long size,
void *virtual, uint64_t location_mask);
/** Takes a reference on a buffer object */
void (*bo_reference)(dri_bo *bo);
/**
* Releases a reference on a buffer object, freeing the data if
* rerefences remain.
*/
void (*bo_unreference)(dri_bo *bo);
/**
* Maps the buffer into userspace.
*
* This function will block waiting for any existing execution on the
* buffer to complete, first. The resulting mapping is available at
* buf->virtual.
*/
int (*bo_map)(dri_bo *buf, GLboolean write_enable);
/** Reduces the refcount on the userspace mapping of the buffer object. */
int (*bo_unmap)(dri_bo *buf);
/**
* Write data into an object.
*
* This is an optional function, if missing,
* dri_bo will map/memcpy/unmap.
*/
int (*bo_subdata) (dri_bo *buf, unsigned long offset,
unsigned long size, const void *data);
/**
* Read data from an object
*
* This is an optional function, if missing,
* dri_bo will map/memcpy/unmap.
*/
int (*bo_get_subdata) (dri_bo *bo, unsigned long offset,
unsigned long size, void *data);
/**
* Waits for rendering to an object by the GPU to have completed.
*
* This is not required for any access to the BO by bo_map, bo_subdata, etc.
* It is merely a way for the driver to implement glFinish.
*/
void (*bo_wait_rendering) (dri_bo *bo);
/**
* Tears down the buffer manager instance.
*/
void (*destroy)(dri_bufmgr *bufmgr);
/**
* Add relocation entry in reloc_buf, which will be updated with the
* target buffer's real offset on on command submission.
*
* Relocations remain in place for the lifetime of the buffer object.
*
* \param reloc_buf Buffer to write the relocation into.
* \param flags BO flags to be used in validating the target buffer.
* Applicable flags include:
* - DRM_BO_FLAG_READ: The buffer will be read in the process of
* command execution.
* - DRM_BO_FLAG_WRITE: The buffer will be written in the process of
* command execution.
* - DRM_BO_FLAG_MEM_TT: The buffer should be validated in TT memory.
* - DRM_BO_FLAG_MEM_VRAM: The buffer should be validated in video
* memory.
* \param delta Constant value to be added to the relocation target's offset.
* \param offset Byte offset within batch_buf of the relocated pointer.
* \param target Buffer whose offset should be written into the relocation
* entry.
*/
int (*emit_reloc)(dri_bo *reloc_buf,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta, uint32_t offset, dri_bo *target);
/**
* Processes the relocations, either in userland or by converting the list
* for use in batchbuffer submission.
*
* Kernel-based implementations will return a pointer to the arguments
* to be handed with batchbuffer submission to the kernel. The userland
* implementation performs the buffer validation and emits relocations
* into them the appopriate order.
*
* \param batch_buf buffer at the root of the tree of relocations
* \return argument to be completed and passed to the execbuffers ioctl
* (if any).
*/
void *(*process_relocs)(dri_bo *batch_buf);
void (*post_submit)(dri_bo *batch_buf);
int (*check_aperture_space)(dri_bo *bo);
GLboolean debug; /**< Enables verbose debugging printouts */
};
dri_bo *dri_bo_alloc(dri_bufmgr *bufmgr, const char *name, unsigned long size,
unsigned int alignment, uint64_t location_mask);
dri_bo *dri_bo_alloc_static(dri_bufmgr *bufmgr, const char *name,
unsigned long offset, unsigned long size,
void *virtual, uint64_t location_mask);
void dri_bo_reference(dri_bo *bo);
void dri_bo_unreference(dri_bo *bo);
int dri_bo_map(dri_bo *buf, GLboolean write_enable);
int dri_bo_unmap(dri_bo *buf);
int dri_bo_subdata(dri_bo *bo, unsigned long offset,
unsigned long size, const void *data);
int dri_bo_get_subdata(dri_bo *bo, unsigned long offset,
unsigned long size, void *data);
void dri_bo_wait_rendering(dri_bo *bo);
void dri_bufmgr_set_debug(dri_bufmgr *bufmgr, GLboolean enable_debug);
void dri_bufmgr_destroy(dri_bufmgr *bufmgr);
int dri_emit_reloc(dri_bo *reloc_buf,
uint32_t read_domains, uint32_t write_domain,
uint32_t delta, uint32_t offset, dri_bo *target_buf);
void *dri_process_relocs(dri_bo *batch_buf);
void dri_post_process_relocs(dri_bo *batch_buf);
void dri_post_submit(dri_bo *batch_buf);
int dri_bufmgr_check_aperture_space(dri_bo *bo);
#endif

View File

@@ -53,13 +53,10 @@ DRIVER_SOURCES = \
intel_state.c \
intel_tris.c \
intel_fbo.c \
intel_depthstencil.c \
intel_bufmgr_fake.c \
intel_bufmgr_gem.c
intel_depthstencil.c
C_SOURCES = \
$(COMMON_SOURCES) \
$(COMMON_BM_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_fake.c

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_gem.c

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_ttm.c

View File

@@ -9,8 +9,6 @@ DRIVER_SOURCES = \
intel_blit.c \
intel_buffer_objects.c \
intel_buffers.c \
intel_bufmgr_fake.c \
intel_bufmgr_gem.c \
intel_context.c \
intel_decode.c \
intel_depthstencil.c \
@@ -85,7 +83,6 @@ DRIVER_SOURCES = \
C_SOURCES = \
$(COMMON_SOURCES) \
$(COMMON_BM_SOURCES) \
$(MINIGLX_SOURCES) \
$(DRIVER_SOURCES)

View File

@@ -256,7 +256,7 @@ cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
NULL, NULL);
/* Emit CC viewport relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION,
0,
0,

View File

@@ -119,7 +119,7 @@ clip_unit_create_from_key(struct brw_context *brw,
/* Emit clip program relocation */
assert(brw->clip.prog_bo);
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION,
0,
clip.thread0.grf_reg_count << 1,

View File

@@ -306,10 +306,7 @@ static int prepare_constant_buffer(struct brw_context *brw)
* They're generally around 64b.
*/
brw->curbe.curbe_bo = dri_bo_alloc(brw->intel.bufmgr, "CURBE",
4096, 1 << 6,
DRM_BO_FLAG_MEM_LOCAL |
DRM_BO_FLAG_CACHED |
DRM_BO_FLAG_CACHED_MAPPED);
4096, 1 << 6);
brw->curbe.curbe_next_offset = 0;
}

View File

@@ -247,10 +247,7 @@ static void wrap_buffers( struct brw_context *brw,
if (brw->vb.upload.bo != NULL)
dri_bo_unreference(brw->vb.upload.bo);
brw->vb.upload.bo = dri_bo_alloc(brw->intel.bufmgr, "temporary VBO",
size, 1,
DRM_BO_FLAG_MEM_LOCAL |
DRM_BO_FLAG_CACHED |
DRM_BO_FLAG_CACHED_MAPPED);
size, 1);
/* Set the internal VBO\ to no-backing-store. We only use them as a
* temporary within a brw_try_draw_prims while the lock is held.

View File

@@ -106,7 +106,7 @@ gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key)
if (key->prog_active) {
/* Emit GS program relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
gs.thread0.grf_reg_count << 1,
offsetof(struct brw_gs_unit_state, thread0),

View File

@@ -253,14 +253,14 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
NULL, NULL);
/* Emit SF program relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
sf.thread0.grf_reg_count << 1,
offsetof(struct brw_sf_unit_state, thread0),
brw->sf.prog_bo);
/* Emit SF viewport relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
sf.sf5.front_winding | (sf.sf5.viewport_transform << 1),
offsetof(struct brw_sf_unit_state, sf5),

View File

@@ -214,10 +214,7 @@ brw_upload_cache( struct brw_cache *cache,
/* Create the buffer object to contain the data */
bo = dri_bo_alloc(cache->brw->intel.bufmgr,
cache->name[cache_id], data_size, 1 << 6,
DRM_BO_FLAG_MEM_LOCAL |
DRM_BO_FLAG_CACHED |
DRM_BO_FLAG_CACHED_MAPPED);
cache->name[cache_id], data_size, 1 << 6);
/* Set up the memory containing the key, aux_data, and reloc_bufs */

View File

@@ -115,7 +115,7 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key)
NULL, NULL);
/* Emit VS program relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
vs.thread0.grf_reg_count << 1,
offsetof(struct brw_vs_unit_state, thread0),

View File

@@ -305,7 +305,7 @@ static int upload_wm_samplers( struct brw_context *brw )
continue;
ret |= dri_bufmgr_check_aperture_space(brw->wm.sdc_bo[i]);
dri_emit_reloc(brw->wm.sampler_bo,
intel_bo_emit_reloc(brw->wm.sampler_bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
0,
i * sizeof(struct brw_sampler_state) +

View File

@@ -199,7 +199,7 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
NULL, NULL);
/* Emit WM program relocation */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
wm.thread0.grf_reg_count << 1,
offsetof(struct brw_wm_unit_state, thread0),
@@ -207,7 +207,7 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
/* Emit scratch space relocation */
if (key->total_scratch != 0) {
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
0, 0,
wm.thread2.per_thread_scratch_space,
offsetof(struct brw_wm_unit_state, thread2),
@@ -216,7 +216,7 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
/* Emit sampler state relocation */
if (key->sampler_count != 0) {
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
offsetof(struct brw_wm_unit_state, wm4),
@@ -251,7 +251,7 @@ static int upload_wm_unit( struct brw_context *brw )
brw->wm.scratch_buffer = dri_bo_alloc(intel->bufmgr,
"wm scratch",
total,
4096, DRM_BO_FLAG_MEM_TT);
4096);
}
}

View File

@@ -203,7 +203,7 @@ brw_create_texture_surface( struct brw_context *brw,
NULL, NULL);
/* Emit relocation to surface contents */
dri_emit_reloc(bo,
intel_bo_emit_reloc(bo,
DRM_GEM_DOMAIN_I915_SAMPLER, 0,
0,
offsetof(struct brw_surface_state, ss1),
@@ -341,7 +341,7 @@ brw_update_region_surface(struct brw_context *brw, struct intel_region *region,
* them both. We might be able to figure out from other state
* a more restrictive relocation to emit.
*/
dri_emit_reloc(brw->wm.surf_bo[unit],
intel_bo_emit_reloc(brw->wm.surf_bo[unit],
DRM_GEM_DOMAIN_I915_RENDER |
DRM_GEM_DOMAIN_I915_SAMPLER,
DRM_GEM_DOMAIN_I915_RENDER,
@@ -391,7 +391,7 @@ brw_wm_get_binding_table(struct brw_context *brw)
/* Emit binding table relocations to surface state */
for (i = 0; i < BRW_WM_MAX_SURF; i++) {
if (brw->wm.surf_bo[i] != NULL) {
dri_emit_reloc(bind_bo,
intel_bo_emit_reloc(bind_bo,
DRM_GEM_DOMAIN_I915_INSTRUCTION, 0,
0,
i * sizeof(GLuint),

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_fake.c

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_gem.c

View File

@@ -1 +0,0 @@
../intel/intel_bufmgr_ttm.c

View File

@@ -29,6 +29,7 @@
#include "intel_ioctl.h"
#include "intel_decode.h"
#include "intel_reg.h"
#include "intel_bufmgr.h"
/* Relocations in kernel space:
* - pass dma buffer seperately
@@ -82,8 +83,7 @@ intel_batchbuffer_reset(struct intel_batchbuffer *batch)
batch->buffer = malloc (intel->maxBatchSize);
batch->buf = dri_bo_alloc(intel->bufmgr, "batchbuffer",
intel->maxBatchSize, 4096,
DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | DRM_BO_FLAG_CACHED_MAPPED);
intel->maxBatchSize, 4096);
if (batch->buffer)
batch->map = batch->buffer;
else {
@@ -290,7 +290,7 @@ intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
if (batch->ptr - batch->map > batch->buf->size)
_mesa_printf ("bad relocation ptr %p map %p offset %d size %d\n",
batch->ptr, batch->map, batch->ptr - batch->map, batch->buf->size);
ret = dri_emit_reloc(batch->buf, read_domains, write_domain,
ret = intel_bo_emit_reloc(batch->buf, read_domains, write_domain,
delta, batch->ptr - batch->map, buffer);
/*

View File

@@ -45,8 +45,7 @@ intel_bufferobj_alloc_buffer(struct intel_context *intel,
struct intel_buffer_object *intel_obj)
{
intel_obj->buffer = dri_bo_alloc(intel->bufmgr, "bufferobj",
intel_obj->Base.Size, 64,
DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED | DRM_BO_FLAG_CACHED_MAPPED);
intel_obj->Base.Size, 64);
}
/**

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +0,0 @@
/**************************************************************************
*
* Copyright © 2007 Intel Corporation
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
/*
* Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
* Eric Anholt <eric@anholt.net>
*/
#ifndef _INTEL_BUFMGR_FAKE_H_
#define _INTEL_BUFMGR_FAKE_H_
void dri_bufmgr_fake_contended_lock_take(dri_bufmgr *bufmgr);
dri_bufmgr *dri_bufmgr_fake_init(unsigned long low_offset, void *low_virtual,
unsigned long size,
unsigned int (*fence_emit)(void *private),
int (*fence_wait)(void *private,
unsigned int cookie),
void *driver_priv);
void dri_bo_fake_disable_backing_store(dri_bo *bo,
void (*invalidate_cb)(dri_bo *bo,
void *ptr),
void *ptr);
#endif /* _INTEL_BUFMGR_FAKE_H_ */

View File

@@ -1,847 +0,0 @@
/**************************************************************************
*
* Copyright <20> 2007 Red Hat Inc.
* Copyright <20> 2007 Intel Corporation
* 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<74>m <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
* Eric Anholt <eric@anholt.net>
* Dave Airlie <airlied@linux.ie>
*/
#include <xf86drm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include "errno.h"
#include "mtypes.h"
#include "dri_bufmgr.h"
#include "string.h"
#include "imports.h"
#include "i915_drm.h"
#include "intel_bufmgr_gem.h"
#define DBG(...) do { \
if (bufmgr_gem->bufmgr.debug) \
fprintf(stderr, __VA_ARGS__); \
} while (0)
struct intel_validate_entry {
dri_bo *bo;
struct drm_i915_op_arg bo_arg;
};
struct dri_gem_bo_bucket_entry {
uint32_t gem_handle;
uint32_t last_offset;
struct dri_gem_bo_bucket_entry *next;
};
struct dri_gem_bo_bucket {
struct dri_gem_bo_bucket_entry *head;
struct dri_gem_bo_bucket_entry **tail;
/**
* Limit on the number of entries in this bucket.
*
* 0 means that this caching at this bucket size is disabled.
* -1 means that there is no limit to caching at this size.
*/
int max_entries;
int num_entries;
};
/* Arbitrarily chosen, 16 means that the maximum size we'll cache for reuse
* is 1 << 16 pages, or 256MB.
*/
#define INTEL_GEM_BO_BUCKETS 16
typedef struct _dri_bufmgr_gem {
dri_bufmgr bufmgr;
int fd;
uint32_t max_relocs;
struct drm_i915_gem_exec_object *exec_objects;
dri_bo **exec_bos;
int exec_size;
int exec_count;
/** Array of lists of cached gem objects of power-of-two sizes */
struct dri_gem_bo_bucket cache_bucket[INTEL_GEM_BO_BUCKETS];
struct drm_i915_gem_execbuffer exec_arg;
} dri_bufmgr_gem;
typedef struct _dri_bo_gem {
dri_bo bo;
int refcount;
GLboolean mapped;
uint32_t gem_handle;
const char *name;
/**
* Index of the buffer within the validation list while preparing a
* batchbuffer execution.
*/
int validate_index;
/**
* Tracks whether set_domain to CPU is current
* Set when set_domain has been called
* Cleared when a batch has been submitted
*/
GLboolean cpu_domain_set;
/** Array passed to the DRM containing relocation information. */
struct drm_i915_gem_relocation_entry *relocs;
/** Array of bos corresponding to relocs[i].target_handle */
dri_bo **reloc_target_bo;
/** Number of entries in relocs */
int reloc_count;
/** Mapped address for the buffer */
void *virtual;
} dri_bo_gem;
static int
logbase2(int n)
{
GLint i = 1;
GLint log2 = 0;
while (n > i) {
i *= 2;
log2++;
}
return log2;
}
static struct dri_gem_bo_bucket *
dri_gem_bo_bucket_for_size(dri_bufmgr_gem *bufmgr_gem, unsigned long size)
{
int i;
/* We only do buckets in power of two increments */
if ((size & (size - 1)) != 0)
return NULL;
/* We should only see sizes rounded to pages. */
assert((size % 4096) == 0);
/* We always allocate in units of pages */
i = ffs(size / 4096) - 1;
if (i >= INTEL_GEM_BO_BUCKETS)
return NULL;
return &bufmgr_gem->cache_bucket[i];
}
static void dri_gem_dump_validation_list(dri_bufmgr_gem *bufmgr_gem)
{
int i, j;
for (i = 0; i < bufmgr_gem->exec_count; i++) {
dri_bo *bo = bufmgr_gem->exec_bos[i];
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
if (bo_gem->relocs == NULL) {
DBG("%2d: %d (%s)\n", i, bo_gem->gem_handle, bo_gem->name);
continue;
}
for (j = 0; j < bo_gem->reloc_count; j++) {
dri_bo *target_bo = bo_gem->reloc_target_bo[j];
dri_bo_gem *target_gem = (dri_bo_gem *)target_bo;
DBG("%2d: %d (%s)@0x%08llx -> %d (%s)@0x%08lx + 0x%08x\n",
i,
bo_gem->gem_handle, bo_gem->name, bo_gem->relocs[j].offset,
target_gem->gem_handle, target_gem->name, target_bo->offset,
bo_gem->relocs[j].delta);
}
}
}
/**
* Adds the given buffer to the list of buffers to be validated (moved into the
* appropriate memory type) with the next batch submission.
*
* If a buffer is validated multiple times in a batch submission, it ends up
* with the intersection of the memory type flags and the union of the
* access flags.
*/
static void
intel_add_validate_buffer(dri_bo *bo)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
int index;
if (bo_gem->validate_index != -1)
return;
/* Extend the array of validation entries as necessary. */
if (bufmgr_gem->exec_count == bufmgr_gem->exec_size) {
int new_size = bufmgr_gem->exec_size * 2;
if (new_size == 0)
new_size = 5;
bufmgr_gem->exec_objects =
realloc(bufmgr_gem->exec_objects,
sizeof(*bufmgr_gem->exec_objects) * new_size);
bufmgr_gem->exec_bos =
realloc(bufmgr_gem->exec_bos,
sizeof(*bufmgr_gem->exec_bos) * new_size);
bufmgr_gem->exec_size = new_size;
}
index = bufmgr_gem->exec_count;
bo_gem->validate_index = index;
/* Fill in array entry */
bufmgr_gem->exec_objects[index].handle = bo_gem->gem_handle;
bufmgr_gem->exec_objects[index].relocation_count = bo_gem->reloc_count;
bufmgr_gem->exec_objects[index].relocs_ptr = (uintptr_t)bo_gem->relocs;
bufmgr_gem->exec_objects[index].alignment = 0;
bufmgr_gem->exec_objects[index].offset = 0;
bufmgr_gem->exec_bos[index] = bo;
dri_bo_reference(bo);
bufmgr_gem->exec_count++;
}
#define RELOC_BUF_SIZE(x) ((I915_RELOC_HEADER + x * I915_RELOC0_STRIDE) * \
sizeof(uint32_t))
static int
intel_setup_reloc_list(dri_bo *bo)
{
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
bo_gem->relocs = malloc(bufmgr_gem->max_relocs *
sizeof(struct drm_i915_gem_relocation_entry));
bo_gem->reloc_target_bo = malloc(bufmgr_gem->max_relocs * sizeof(dri_bo *));
return 0;
}
static dri_bo *
dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name,
unsigned long size, unsigned int alignment,
uint64_t location_mask)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
dri_bo_gem *bo_gem;
unsigned int page_size = getpagesize();
int ret;
struct dri_gem_bo_bucket *bucket;
GLboolean alloc_from_cache = GL_FALSE;
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
return NULL;
/* Round the allocated size up to a power of two number of pages. */
bo_gem->bo.size = 1 << logbase2(size);
if (bo_gem->bo.size < page_size)
bo_gem->bo.size = page_size;
bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo_gem->bo.size);
/* If we don't have caching at this size, don't actually round the
* allocation up.
*/
if (bucket == NULL || bucket->max_entries == 0) {
bo_gem->bo.size = size;
if (bo_gem->bo.size < page_size)
bo_gem->bo.size = page_size;
}
/* Get a buffer out of the cache if available */
if (bucket != NULL && bucket->num_entries > 0) {
struct dri_gem_bo_bucket_entry *entry = bucket->head;
struct drm_i915_gem_busy busy;
busy.handle = entry->gem_handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
alloc_from_cache = (ret == 0 && busy.busy == 0);
if (alloc_from_cache) {
bucket->head = entry->next;
if (entry->next == NULL)
bucket->tail = &bucket->head;
bucket->num_entries--;
bo_gem->gem_handle = entry->gem_handle;
bo_gem->bo.offset = entry->last_offset;
free(entry);
}
}
if (!alloc_from_cache) {
struct drm_gem_create create;
memset(&create, 0, sizeof(create));
create.size = bo_gem->bo.size;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CREATE, &create);
bo_gem->gem_handle = create.handle;
if (ret != 0) {
free(bo_gem);
return NULL;
}
}
bo_gem->bo.virtual = NULL;
bo_gem->bo.bufmgr = bufmgr;
bo_gem->name = name;
bo_gem->refcount = 1;
bo_gem->validate_index = -1;
DBG("bo_create: buf %d (%s) %ldb\n",
bo_gem->gem_handle, bo_gem->name, size);
return &bo_gem->bo;
}
/* Our GEM backend doesn't allow creation of static buffers, as that requires
* privelege for the non-fake case, and the lock in the fake case where we were
* working around the X Server not creating buffers and passing handles to us.
*/
static dri_bo *
dri_gem_bo_alloc_static(dri_bufmgr *bufmgr, const char *name,
unsigned long offset, unsigned long size, void *virtual,
uint64_t location_mask)
{
return NULL;
}
/**
* Returns a dri_bo wrapping the given buffer object handle.
*
* This can be used when one application needs to pass a buffer object
* to another.
*/
dri_bo *
intel_gem_bo_create_from_handle(dri_bufmgr *bufmgr, const char *name,
unsigned int handle)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
dri_bo_gem *bo_gem;
int ret;
struct drm_gem_open open_arg;
bo_gem = calloc(1, sizeof(*bo_gem));
if (!bo_gem)
return NULL;
memset(&open_arg, 0, sizeof(open_arg));
open_arg.name = handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_OPEN, &open_arg);
if (ret != 0) {
fprintf(stderr, "Couldn't reference %s handle 0x%08x: %s\n",
name, handle, strerror(-ret));
free(bo_gem);
return NULL;
}
bo_gem->bo.size = open_arg.size;
bo_gem->bo.offset = 0;
bo_gem->bo.virtual = NULL;
bo_gem->bo.bufmgr = bufmgr;
bo_gem->name = name;
bo_gem->refcount = 1;
bo_gem->validate_index = -1;
bo_gem->gem_handle = open_arg.handle;
DBG("bo_create_from_handle: %d (%s)\n", handle, bo_gem->name);
return &bo_gem->bo;
}
static void
dri_gem_bo_reference(dri_bo *bo)
{
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
bo_gem->refcount++;
}
static void
dri_gem_bo_unreference(dri_bo *bo)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
if (!bo)
return;
if (--bo_gem->refcount == 0) {
struct dri_gem_bo_bucket *bucket;
int ret;
if (bo_gem->mapped)
munmap (bo_gem->virtual, bo->size);
if (bo_gem->relocs != NULL) {
int i;
/* Unreference all the target buffers */
for (i = 0; i < bo_gem->reloc_count; i++)
dri_bo_unreference(bo_gem->reloc_target_bo[i]);
free(bo_gem->reloc_target_bo);
free(bo_gem->relocs);
}
bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size);
/* Put the buffer into our internal cache for reuse if we can. */
if (bucket != NULL &&
(bucket->max_entries == -1 ||
(bucket->max_entries > 0 &&
bucket->num_entries < bucket->max_entries)))
{
struct dri_gem_bo_bucket_entry *entry;
entry = calloc(1, sizeof(*entry));
entry->gem_handle = bo_gem->gem_handle;
entry->last_offset = bo->offset;
entry->next = NULL;
*bucket->tail = entry;
bucket->tail = &entry->next;
bucket->num_entries++;
} else {
struct drm_gem_close close;
/* Close this object */
close.handle = bo_gem->gem_handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
if (ret != 0) {
fprintf(stderr,
"DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
bo_gem->gem_handle, bo_gem->name, strerror(-ret));
}
}
DBG("bo_unreference final: %d (%s)\n",
bo_gem->gem_handle, bo_gem->name);
free(bo);
return;
}
}
static int
dri_gem_bo_map(dri_bo *bo, GLboolean write_enable)
{
dri_bufmgr_gem *bufmgr_gem;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
struct drm_gem_set_domain set_domain;
int ret;
bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
/* Allow recursive mapping. Mesa may recursively map buffers with
* nested display loops.
*/
if (!bo_gem->mapped) {
assert(bo->virtual == NULL);
DBG("bo_map: %d (%s)\n", bo_gem->gem_handle, bo_gem->name);
if (bo_gem->virtual == NULL) {
struct drm_gem_mmap mmap_arg;
memset(&mmap_arg, 0, sizeof(mmap_arg));
mmap_arg.handle = bo_gem->gem_handle;
mmap_arg.offset = 0;
mmap_arg.size = bo->size;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_MMAP, &mmap_arg);
if (ret != 0) {
fprintf(stderr, "%s:%d: Error mapping buffer %d (%s): %s .\n",
__FILE__, __LINE__,
bo_gem->gem_handle, bo_gem->name, strerror(errno));
}
bo_gem->virtual = (void *)(uintptr_t)mmap_arg.addr_ptr;
}
bo->virtual = bo_gem->virtual;
bo_gem->mapped = GL_TRUE;
DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name, bo_gem->virtual);
}
if (!bo_gem->cpu_domain_set) {
set_domain.handle = bo_gem->gem_handle;
set_domain.read_domains = DRM_GEM_DOMAIN_CPU;
set_domain.write_domain = write_enable ? DRM_GEM_DOMAIN_CPU : 0;
ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_GEM_SET_DOMAIN, &set_domain);
if (ret != 0) {
fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
__FILE__, __LINE__,
bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
strerror (errno));
}
bo_gem->cpu_domain_set = GL_TRUE;
}
return 0;
}
static int
dri_gem_bo_unmap(dri_bo *bo)
{
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
if (bo == NULL)
return 0;
assert(bo_gem->mapped);
return 0;
}
static int
dri_gem_bo_subdata (dri_bo *bo, unsigned long offset,
unsigned long size, const void *data)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
struct drm_gem_pwrite pwrite;
int ret;
memset (&pwrite, 0, sizeof (pwrite));
pwrite.handle = bo_gem->gem_handle;
pwrite.offset = offset;
pwrite.size = size;
pwrite.data_ptr = (uint64_t) (uintptr_t) data;
ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_GEM_PWRITE, &pwrite);
if (ret != 0) {
fprintf (stderr, "%s:%d: Error writing data to buffer %d: (%d %d) %s .\n",
__FILE__, __LINE__,
bo_gem->gem_handle, (int) offset, (int) size,
strerror (errno));
}
return 0;
}
static int
dri_gem_bo_get_subdata (dri_bo *bo, unsigned long offset,
unsigned long size, void *data)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
struct drm_gem_pread pread;
int ret;
memset (&pread, 0, sizeof (pread));
pread.handle = bo_gem->gem_handle;
pread.offset = offset;
pread.size = size;
pread.data_ptr = (uint64_t) (uintptr_t) data;
ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_GEM_PREAD, &pread);
if (ret != 0) {
fprintf (stderr, "%s:%d: Error reading data from buffer %d: (%d %d) %s .\n",
__FILE__, __LINE__,
bo_gem->gem_handle, (int) offset, (int) size,
strerror (errno));
}
return 0;
}
static void
dri_gem_bo_wait_rendering(dri_bo *bo)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
struct drm_gem_set_domain set_domain;
int ret;
set_domain.handle = bo_gem->gem_handle;
set_domain.read_domains = DRM_GEM_DOMAIN_CPU;
set_domain.write_domain = 0;
ret = ioctl (bufmgr_gem->fd, DRM_IOCTL_GEM_SET_DOMAIN, &set_domain);
if (ret != 0) {
fprintf (stderr, "%s:%d: Error setting memory domains %d (%08x %08x): %s .\n",
__FILE__, __LINE__,
bo_gem->gem_handle, set_domain.read_domains, set_domain.write_domain,
strerror (errno));
}
}
static void
dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
int i;
free(bufmgr_gem->exec_objects);
free(bufmgr_gem->exec_bos);
/* Free any cached buffer objects we were going to reuse */
for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i];
struct dri_gem_bo_bucket_entry *entry;
while ((entry = bucket->head) != NULL) {
struct drm_gem_close close;
int ret;
bucket->head = entry->next;
if (entry->next == NULL)
bucket->tail = &bucket->head;
bucket->num_entries--;
/* Close this object */
close.handle = entry->gem_handle;
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
if (ret != 0) {
fprintf(stderr, "DRM_IOCTL_GEM_CLOSE failed: %s\n",
strerror(-ret));
}
free(entry);
}
}
free(bufmgr);
}
/**
* Adds the target buffer to the validation list and adds the relocation
* to the reloc_buffer's relocation list.
*
* The relocation entry at the given offset must already contain the
* precomputed relocation value, because the kernel will optimize out
* the relocation entry write when the buffer hasn't moved from the
* last known offset in target_bo.
*/
static int
dri_gem_emit_reloc(dri_bo *bo, uint32_t read_domains, uint32_t write_domain,
uint32_t delta, uint32_t offset, dri_bo *target_bo)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr;
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
dri_bo_gem *target_bo_gem = (dri_bo_gem *)target_bo;
/* Create a new relocation list if needed */
if (bo_gem->relocs == NULL)
intel_setup_reloc_list(bo);
/* Check overflow */
assert(bo_gem->reloc_count < bufmgr_gem->max_relocs);
/* Check args */
assert (offset <= bo->size - 4);
assert ((write_domain & (write_domain-1)) == 0);
bo_gem->relocs[bo_gem->reloc_count].offset = offset;
bo_gem->relocs[bo_gem->reloc_count].delta = delta;
bo_gem->relocs[bo_gem->reloc_count].target_handle =
target_bo_gem->gem_handle;
bo_gem->relocs[bo_gem->reloc_count].read_domains = read_domains;
bo_gem->relocs[bo_gem->reloc_count].write_domain = write_domain;
bo_gem->relocs[bo_gem->reloc_count].presumed_offset = target_bo->offset;
bo_gem->reloc_target_bo[bo_gem->reloc_count] = target_bo;
dri_bo_reference(target_bo);
bo_gem->reloc_count++;
return 0;
}
/**
* Walk the tree of relocations rooted at BO and accumulate the list of
* validations to be performed and update the relocation buffers with
* index values into the validation list.
*/
static void
dri_gem_bo_process_reloc(dri_bo *bo)
{
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
int i;
if (bo_gem->relocs == NULL)
return;
for (i = 0; i < bo_gem->reloc_count; i++) {
dri_bo *target_bo = bo_gem->reloc_target_bo[i];
/* Continue walking the tree depth-first. */
dri_gem_bo_process_reloc(target_bo);
/* Add the target to the validate list */
intel_add_validate_buffer(target_bo);
}
}
static void *
dri_gem_process_reloc(dri_bo *batch_buf)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *) batch_buf->bufmgr;
/* Update indices and set up the validate list. */
dri_gem_bo_process_reloc(batch_buf);
/* Add the batch buffer to the validation list. There are no relocations
* pointing to it.
*/
intel_add_validate_buffer(batch_buf);
bufmgr_gem->exec_arg.buffers_ptr = (uintptr_t)bufmgr_gem->exec_objects;
bufmgr_gem->exec_arg.buffer_count = bufmgr_gem->exec_count;
bufmgr_gem->exec_arg.batch_start_offset = 0;
bufmgr_gem->exec_arg.batch_len = 0; /* written in intel_exec_ioctl */
return &bufmgr_gem->exec_arg;
}
static void
intel_update_buffer_offsets (dri_bufmgr_gem *bufmgr_gem)
{
int i;
for (i = 0; i < bufmgr_gem->exec_count; i++) {
dri_bo *bo = bufmgr_gem->exec_bos[i];
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
/* Update the buffer offset */
if (bufmgr_gem->exec_objects[i].offset != bo->offset) {
DBG("BO %d (%s) migrated: 0x%08lx -> 0x%08llx\n",
bo_gem->gem_handle, bo_gem->name, bo->offset,
bufmgr_gem->exec_objects[i].offset);
bo->offset = bufmgr_gem->exec_objects[i].offset;
}
}
}
static void
dri_gem_post_submit(dri_bo *batch_buf)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)batch_buf->bufmgr;
int i;
intel_update_buffer_offsets (bufmgr_gem);
if (bufmgr_gem->bufmgr.debug)
dri_gem_dump_validation_list(bufmgr_gem);
for (i = 0; i < bufmgr_gem->exec_count; i++) {
dri_bo *bo = bufmgr_gem->exec_bos[i];
dri_bo_gem *bo_gem = (dri_bo_gem *)bo;
/* Need to call set_domain on next bo_map */
bo_gem->cpu_domain_set = GL_FALSE;
/* Disconnect the buffer from the validate list */
bo_gem->validate_index = -1;
dri_bo_unreference(bo);
bufmgr_gem->exec_bos[i] = NULL;
}
bufmgr_gem->exec_count = 0;
}
/**
* Enables unlimited caching of buffer objects for reuse.
*
* This is potentially very memory expensive, as the cache at each bucket
* size is only bounded by how many buffers of that size we've managed to have
* in flight at once.
*/
void
intel_gem_enable_bo_reuse(dri_bufmgr *bufmgr)
{
dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr;
int i;
for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++) {
bufmgr_gem->cache_bucket[i].max_entries = -1;
}
}
/*
*
*/
static int
dri_gem_check_aperture_space(dri_bo *bo)
{
return 0;
}
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.
*
* \param fd File descriptor of the opened DRM device.
*/
dri_bufmgr *
intel_bufmgr_gem_init(int fd, int batch_size)
{
dri_bufmgr_gem *bufmgr_gem;
int i;
bufmgr_gem = calloc(1, sizeof(*bufmgr_gem));
bufmgr_gem->fd = fd;
/* Let's go with one relocation per every 2 dwords (but round down a bit
* since a power of two will mean an extra page allocation for the reloc
* buffer).
*
* Every 4 was too few for the blender benchmark.
*/
bufmgr_gem->max_relocs = batch_size / sizeof(uint32_t) / 2 - 2;
bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc;
bufmgr_gem->bufmgr.bo_alloc_static = dri_gem_bo_alloc_static;
bufmgr_gem->bufmgr.bo_reference = dri_gem_bo_reference;
bufmgr_gem->bufmgr.bo_unreference = dri_gem_bo_unreference;
bufmgr_gem->bufmgr.bo_map = dri_gem_bo_map;
bufmgr_gem->bufmgr.bo_unmap = dri_gem_bo_unmap;
bufmgr_gem->bufmgr.bo_subdata = dri_gem_bo_subdata;
bufmgr_gem->bufmgr.bo_get_subdata = dri_gem_bo_get_subdata;
bufmgr_gem->bufmgr.bo_wait_rendering = dri_gem_bo_wait_rendering;
bufmgr_gem->bufmgr.destroy = dri_bufmgr_gem_destroy;
bufmgr_gem->bufmgr.emit_reloc = dri_gem_emit_reloc;
bufmgr_gem->bufmgr.process_relocs = dri_gem_process_reloc;
bufmgr_gem->bufmgr.post_submit = dri_gem_post_submit;
bufmgr_gem->bufmgr.debug = GL_FALSE;
bufmgr_gem->bufmgr.check_aperture_space = dri_gem_check_aperture_space;
/* Initialize the linked lists for BO reuse cache. */
for (i = 0; i < INTEL_GEM_BO_BUCKETS; i++)
bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head;
return &bufmgr_gem->bufmgr;
}

View File

@@ -1,16 +0,0 @@
#ifndef INTEL_BUFMGR_GEM_H
#define INTEL_BUFMGR_GEM_H
#include "dri_bufmgr.h"
extern dri_bo *intel_gem_bo_create_from_handle(dri_bufmgr *bufmgr,
const char *name,
unsigned int handle);
dri_bufmgr *intel_bufmgr_gem_init(int fd, int batch_size);
void
intel_gem_enable_bo_reuse(dri_bufmgr *bufmgr);
#endif /* INTEL_BUFMGR_GEM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
#ifndef INTEL_BUFMGR_TTM_H
#define INTEL_BUFMGR_TTM_H
#include "dri_bufmgr.h"
extern dri_bo *intel_ttm_bo_create_from_handle(dri_bufmgr *bufmgr, const char *name,
unsigned int handle);
dri_fence *intel_ttm_fence_create_from_arg(dri_bufmgr *bufmgr, const char *name,
drm_fence_arg_t *arg);
dri_bufmgr *intel_bufmgr_ttm_init(int fd, unsigned int fence_type,
unsigned int fence_type_flush, int batch_size);
void
intel_ttm_enable_bo_reuse(dri_bufmgr *bufmgr);
#endif

View File

@@ -59,8 +59,7 @@
#include "intel_buffer_objects.h"
#include "intel_fbo.h"
#include "intel_decode.h"
#include "intel_bufmgr_fake.h"
#include "intel_bufmgr_gem.h"
#include "intel_bufmgr.h"
#include "drirenderbuffer.h"
#include "vblank.h"
@@ -474,7 +473,7 @@ intel_init_bufmgr(struct intel_context *intel)
case DRI_CONF_BO_REUSE_DISABLED:
break;
case DRI_CONF_BO_REUSE_ALL:
intel_gem_enable_bo_reuse(intel->bufmgr);
intel_bufmgr_gem_enable_reuse(intel->bufmgr);
break;
}
}
@@ -493,7 +492,7 @@ intel_init_bufmgr(struct intel_context *intel)
return GL_FALSE;
}
intel->bufmgr = dri_bufmgr_fake_init(intelScreen->tex.offset,
intel->bufmgr = intel_bufmgr_fake_init(intelScreen->tex.offset,
intelScreen->tex.map,
intelScreen->tex.size,
intel_fence_emit,
@@ -873,7 +872,7 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
*/
if (!intel->ttm && sarea->texAge != intel->hHWContext) {
sarea->texAge = intel->hHWContext;
dri_bufmgr_fake_contended_lock_take(intel->bufmgr);
intel_bufmgr_fake_contended_lock_take(intel->bufmgr);
if (INTEL_DEBUG & DEBUG_BATCH)
intel_decode_context_reset();
if (INTEL_DEBUG & DEBUG_BUFMGR)

View File

@@ -35,6 +35,7 @@
#include "mm.h"
#include "texmem.h"
#include "dri_bufmgr.h"
#include "intel_bufmgr.h"
#include "intel_screen.h"
#include "intel_tex_obj.h"

View File

@@ -45,7 +45,7 @@
#include "drm.h"
#include "i915_drm.h"
#include "intel_bufmgr_gem.h"
#include "intel_bufmgr.h"
#define FILE_DEBUG_FLAG DEBUG_IOCTL

View File

@@ -44,7 +44,7 @@
#include "intel_blit.h"
#include "intel_buffer_objects.h"
#include "dri_bufmgr.h"
#include "intel_bufmgr_gem.h"
#include "intel_bufmgr.h"
#include "intel_batchbuffer.h"
#define FILE_DEBUG_FLAG DEBUG_REGION
@@ -106,10 +106,7 @@ intel_region_alloc(struct intel_context *intel,
dri_bo *buffer;
buffer = dri_bo_alloc(intel->bufmgr, "region",
pitch * cpp * height, 64,
DRM_BO_FLAG_MEM_LOCAL |
DRM_BO_FLAG_CACHED |
DRM_BO_FLAG_CACHED_MAPPED);
pitch * cpp * height, 64);
return intel_region_alloc_internal(intel, cpp, pitch, height, 0, buffer);
}
@@ -121,7 +118,7 @@ intel_region_alloc_for_handle(struct intel_context *intel,
{
dri_bo *buffer;
buffer = intel_gem_bo_create_from_handle(intel->bufmgr, "region", handle);
buffer = intel_bo_gem_create_from_name(intel->bufmgr, "region", handle);
return intel_region_alloc_internal(intel,
cpp, pitch, height, tiled, buffer);
@@ -355,10 +352,7 @@ intel_region_release_pbo(struct intel_context *intel,
region->buffer = dri_bo_alloc(intel->bufmgr, "region",
region->pitch * region->cpp * region->height,
64,
DRM_BO_FLAG_MEM_LOCAL |
DRM_BO_FLAG_CACHED |
DRM_BO_FLAG_CACHED_MAPPED);
64);
}
/* Break the COW tie to the pbo. Both the pbo and the region end up
@@ -440,17 +434,16 @@ intel_recreate_static(struct intel_context *intel,
if (intel->ttm) {
assert(region_desc->bo_handle != -1);
region->buffer = intel_gem_bo_create_from_handle(intel->bufmgr,
region->buffer = intel_bo_gem_create_from_name(intel->bufmgr,
name,
region_desc->bo_handle);
} else {
region->buffer = dri_bo_alloc_static(intel->bufmgr,
region->buffer = intel_bo_fake_alloc_static(intel->bufmgr,
name,
region_desc->offset,
intelScreen->pitch *
intelScreen->height,
region_desc->map,
DRM_BO_FLAG_MEM_TT);
region_desc->map);
}
assert(region->buffer != NULL);

View File

@@ -49,7 +49,7 @@
#include "i830_dri.h"
#include "intel_regions.h"
#include "intel_batchbuffer.h"
#include "intel_bufmgr_gem.h"
#include "intel_bufmgr.h"
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN