From 9ed192c692f5d334efe9f6dba4da44ed6ab048ac Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Aug 26 2008 09:04:06 +0000 Subject: - update modesetting/memory manager support --- diff --git a/radeon-modeset.patch b/radeon-modeset.patch index 76d43f4..143a50e 100644 --- a/radeon-modeset.patch +++ b/radeon-modeset.patch @@ -18,7 +18,7 @@ index b8c18a6..a7e954d 100644 save_CFLAGS="$CFLAGS" diff --git a/src/Makefile.am b/src/Makefile.am -index 97c686b..0a7d1bb 100644 +index 97c686b..d32e74a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,12 +90,13 @@ radeon_drv_ladir = @moduledir@/drivers @@ -33,7 +33,7 @@ index 97c686b..0a7d1bb 100644 $(RADEON_ATOMBIOS_SOURCES) radeon_atombios.c radeon_atomwrapper.c \ - $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c + $(RADEON_DRI_SRCS) $(RADEON_EXA_SOURCES) atombios_output.c atombios_crtc.c \ -+ drmmode_display.c radeon_bufmgr_exa.c ++ drmmode_display.c radeon_bufmgr_exa.c radeon_bufmgr_gem.c if XMODES radeon_drv_la_SOURCES += \ @@ -46,10 +46,10 @@ index 97c686b..0a7d1bb 100644 + drmmode_display.h diff --git a/src/drmmode_display.c b/src/drmmode_display.c new file mode 100644 -index 0000000..07a5349 +index 0000000..97762ce --- /dev/null +++ b/src/drmmode_display.c -@@ -0,0 +1,680 @@ +@@ -0,0 +1,681 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * @@ -634,7 +634,8 @@ index 0000000..07a5349 + int ret; + + ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, -+ scrn->bitsPerPixel, pitch, handle, &drmmode->fb_id); ++ scrn->bitsPerPixel, pitch, handle, ++ &drmmode->fb_id); + + if (ret) { + ErrorF("Failed to add fb\n"); @@ -732,7 +733,7 @@ index 0000000..07a5349 +#endif diff --git a/src/drmmode_display.h b/src/drmmode_display.h new file mode 100644 -index 0000000..03f8119 +index 0000000..691d62e --- /dev/null +++ b/src/drmmode_display.h @@ -0,0 +1,74 @@ @@ -770,7 +771,7 @@ index 0000000..03f8119 +#include "xf86drmMode.h" + +#include "radeon_probe.h" -+#include "radeon_bufmgr_exa.h" ++#include "radeon_bufmgr.h" + +typedef struct { + int fd; @@ -811,7 +812,7 @@ index 0000000..03f8119 +#endif +#endif diff --git a/src/radeon.h b/src/radeon.h -index 2348e7c..4082aac 100644 +index 2348e7c..32bfa4e 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -46,6 +46,8 @@ @@ -827,7 +828,7 @@ index 2348e7c..4082aac 100644 #include "xf86Crtc.h" #include "X11/Xatom.h" -+#include "radeon_bufmgr_exa.h" ++#include "radeon_bufmgr.h" /* Render support */ #ifdef RENDER #include "picturestr.h" @@ -939,11 +940,12 @@ index 2348e7c..4082aac 100644 } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ -@@ -1030,6 +1097,22 @@ extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode); +@@ -1030,6 +1097,23 @@ extern void RADEONUpdateHVPosition(xf86OutputPtr output, DisplayModePtr mode); extern void RADEONInitVideo(ScreenPtr pScreen); extern void RADEONResetVideo(ScrnInfoPtr pScrn); +/* radeon_memory.c */ ++extern uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem); +extern Bool radeon_bind_all_memory(ScrnInfoPtr pScrn); +extern Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn); +extern struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name, @@ -962,7 +964,7 @@ index 2348e7c..4082aac 100644 #ifdef XF86DRI # ifdef USE_XAA /* radeon_accelfuncs.c */ -@@ -1048,7 +1131,9 @@ do { \ +@@ -1048,7 +1132,9 @@ do { \ #define RADEONCP_RELEASE(pScrn, info) \ do { \ @@ -973,7 +975,7 @@ index 2348e7c..4082aac 100644 RADEON_PURGE_CACHE(); \ RADEON_WAIT_UNTIL_IDLE(); \ RADEONCPReleaseIndirect(pScrn); \ -@@ -1082,7 +1167,7 @@ do { \ +@@ -1082,7 +1168,7 @@ do { \ #define RADEONCP_REFRESH(pScrn, info) \ do { \ @@ -982,7 +984,7 @@ index 2348e7c..4082aac 100644 if (info->needCacheFlush) { \ RADEON_PURGE_CACHE(); \ RADEON_PURGE_ZCACHE(); \ -@@ -1109,6 +1194,13 @@ do { \ +@@ -1109,6 +1195,13 @@ do { \ #define RING_LOCALS uint32_t *__head = NULL; int __expected; int __count = 0 #define BEGIN_RING(n) do { \ @@ -996,7 +998,7 @@ index 2348e7c..4082aac 100644 if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\ -@@ -1121,13 +1213,6 @@ do { \ +@@ -1121,13 +1214,6 @@ do { \ } \ info->dma_debug_func = __FILE__; \ info->dma_debug_lineno = __LINE__; \ @@ -1010,15 +1012,15 @@ index 2348e7c..4082aac 100644 __expected = n; \ __head = (pointer)((char *)info->indirectBuffer->address + \ info->indirectBuffer->used); \ -@@ -1170,6 +1255,14 @@ do { \ +@@ -1170,6 +1256,14 @@ do { \ OUT_RING(val); \ } while (0) +/* TODO - VRAM is wrong in general but true for now - all EXA stuff + is in VRAM */ -+#define OUT_RING_RELOC(x) \ -+ do { \ -+ radeon_bufmgr_exa_emit_reloc(x, __head, &__count); \ ++#define OUT_RING_RELOC(x, read_domains, write_domains) \ ++ do { \ ++ radeon_bufmgr_emit_reloc(x, __head, &__count, read_domains, write_domains); \ + } while(0) + + @@ -1026,7 +1028,7 @@ index 2348e7c..4082aac 100644 do { \ if (RADEON_VERBOSE) \ diff --git a/src/radeon_accel.c b/src/radeon_accel.c -index e617fd5..0014c16 100644 +index e617fd5..09aa7f6 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -313,6 +313,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) @@ -1214,7 +1216,7 @@ index e617fd5..0014c16 100644 + info->indirectBuffer->total -= 16*4; + + if (info->bufmgr) -+ radeon_bufmgr_post_submit(info->bufmgr); ++ radeon_gem_bufmgr_post_submit(info->bufmgr); + + /* copy some state into the buffer now - we need to add 2D state to each + buffer as the kernel needs to use the blit engine to move stuff around */ @@ -1281,7 +1283,7 @@ index e617fd5..0014c16 100644 + /* for now just wait for the buffer to come around again */ + + dom_args.handle = info->mm.gem_ib_memory->kernel_bo_handle; -+ dom_args.read_domains = RADEON_GEM_DOMAIN_CPU; ++ dom_args.read_domains = RADEON_GEM_DOMAIN_GTT; + dom_args.write_domain = 0; + + drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN, @@ -1396,12 +1398,48 @@ index e617fd5..0014c16 100644 RADEONInit3DEngineCP(pScrn); } else #endif +diff --git a/src/radeon_bufmgr.h b/src/radeon_bufmgr.h +new file mode 100644 +index 0000000..a16ad9a +--- /dev/null ++++ b/src/radeon_bufmgr.h +@@ -0,0 +1,30 @@ ++/** ++ * @file intel_bufmgr.h ++ * ++ * Public definitions of Intel-specific bufmgr functions. ++ */ ++ ++#ifndef RADEON_BUFMGR_H ++#define RADEON_BUFMGR_H ++ ++#include "dri_bufmgr.h" ++ ++struct radeon_bufmgr { ++ void (*emit_reloc)(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); ++}; ++ ++dri_bufmgr *radeon_bufmgr_gem_init(int fd); ++dri_bo *radeon_bo_gem_create_from_name(dri_bufmgr *bufmgr, const char *name, ++ unsigned int handle); ++ ++void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); ++ ++dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn); ++extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo); ++extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); ++void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); ++void radeon_bufmgr_pin(dri_bo *buf); ++void radeon_bufmgr_unpin(dri_bo *buf); ++uint32_t radeon_bufmgr_get_handle(dri_bo *buf); ++void radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr); ++#endif diff --git a/src/radeon_bufmgr_exa.c b/src/radeon_bufmgr_exa.c new file mode 100644 -index 0000000..400b426 +index 0000000..64537a6 --- /dev/null +++ b/src/radeon_bufmgr_exa.c -@@ -0,0 +1,295 @@ +@@ -0,0 +1,324 @@ +/************************************************************************** + * + * Copyright © 2007-2008 Red Hat Inc. @@ -1457,7 +1495,7 @@ index 0000000..400b426 +#include "radeon_reg.h" +#include "radeon_probe.h" +#include "radeon.h" -+#include "radeon_bufmgr_exa.h" ++#include "radeon_bufmgr.h" + + +typedef struct _dri_bo_exa { @@ -1472,6 +1510,7 @@ index 0000000..400b426 + +typedef struct _dri_bufmgr_exa { + dri_bufmgr bufmgr; ++ struct radeon_bufmgr radeon_bufmgr; + ScrnInfoPtr pScrn; + struct _dri_bo_exa *reloc_head; +} dri_bufmgr_exa; @@ -1490,7 +1529,7 @@ index 0000000..400b426 + return NULL; + + exa_buf->refcount = 1; -+ exa_buf->mem = radeon_allocate_memory(bufmgr_exa->pScrn, RADEON_POOL_VRAM, ++ exa_buf->mem = radeon_allocate_memory(bufmgr_exa->pScrn, RADEON_POOL_GART, + size, alignment, 0, name, 0); + + exa_buf->bo.size = exa_buf->mem->size; @@ -1566,7 +1605,7 @@ index 0000000..400b426 + int ret; + + dom_args.handle = exa_buf->mem->kernel_bo_handle; -+ dom_args.read_domains = RADEON_GEM_DOMAIN_CPU; ++ dom_args.read_domains = RADEON_GEM_DOMAIN_GTT; + dom_args.write_domain = 0; + ret = drmCommandWriteRead(info->drmFD, DRM_RADEON_GEM_SET_DOMAIN, + &dom_args, sizeof(dom_args)); @@ -1574,6 +1613,34 @@ index 0000000..400b426 + return; +} + ++int radeon_bufmgr_subdata(dri_bo *buf, unsigned long offset, ++ unsigned long size, const void *data) ++{ ++ dri_bo_exa *exa_buf = (dri_bo_exa *)buf; ++ dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; ++ RADEONInfoPtr info = RADEONPTR(bufmgr_exa->pScrn); ++ int ret; ++ /* go to pwrite */ ++ struct drm_radeon_gem_pwrite pwrite; ++ ++ pwrite.handle = exa_buf->mem->kernel_bo_handle; ++ pwrite.offset = offset; ++ pwrite.size = size; ++ pwrite.data_ptr = (uint64_t)(uintptr_t)data; ++ ++ do { ++ ret = drmCommandWriteRead(info->drmFD, DRM_IOCTL_RADEON_GEM_PWRITE, ++ &pwrite, sizeof(pwrite)); ++ } while (ret == -1 && errno == EINTR); ++ ++ if (ret != 0) { ++ fprintf(stderr,"Pwrite %lx at %lx failed\n", size, offset); ++ return -1; ++ } ++ return 0; ++} ++ ++ +dri_bo * +radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem) +{ @@ -1597,6 +1664,35 @@ index 0000000..400b426 + return &exa_buf->bo; +} + ++static void radeon_bufmgr_exa_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) ++{ ++ dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; ++ ScrnInfoPtr pScrn = bufmgr_exa->pScrn; ++ dri_bo_exa *exa_buf = (dri_bo_exa *)buf; ++ uint32_t *__head = head; ++ uint32_t __count = *count_p; ++ dri_bo_exa *trav; ++ ++ if (exa_buf->reloc_count == 0) { ++ dri_bo_reference(buf); ++ ++ if (bufmgr_exa->reloc_head == NULL) ++ bufmgr_exa->reloc_head = exa_buf; ++ else { ++ trav = bufmgr_exa->reloc_head; ++ while (trav->next != NULL) ++ trav = trav->next; ++ trav->next = exa_buf; ++ } ++ } ++ exa_buf->reloc_count++; ++ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2)); ++ OUT_RING(exa_buf->mem->kernel_bo_handle); ++ OUT_RING(read_domains); ++ OUT_RING(write_domain); ++ *count_p = __count; ++} ++ +/** + * Initializes the EXA buffer manager, which is just a thin wrapper + * around the EXA allocator. @@ -1621,39 +1717,10 @@ index 0000000..400b426 + bufmgr_exa->bufmgr.bo_unmap = dri_exa_bo_unmap; + bufmgr_exa->bufmgr.destroy = dri_bufmgr_exa_destroy; + bufmgr_exa->bufmgr.bo_wait_rendering = radeon_bufmgr_exa_wait_rendering; -+ ++ bufmgr_exa->radeon_bufmgr.emit_reloc = radeon_bufmgr_exa_emit_reloc; + return &bufmgr_exa->bufmgr; +} + -+void radeon_bufmgr_exa_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p) -+{ -+ dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)buf->bufmgr; -+ ScrnInfoPtr pScrn = bufmgr_exa->pScrn; -+ dri_bo_exa *exa_buf = (dri_bo_exa *)buf; -+ uint32_t *__head = head; -+ uint32_t __count = *count_p; -+ dri_bo_exa *trav; -+ -+ if (exa_buf->reloc_count == 0) { -+ dri_bo_reference(buf); -+ -+ if (bufmgr_exa->reloc_head == NULL) -+ bufmgr_exa->reloc_head = exa_buf; -+ else { -+ trav = bufmgr_exa->reloc_head; -+ while (trav->next != NULL) -+ trav = trav->next; -+ trav->next = exa_buf; -+ } -+ } -+ exa_buf->reloc_count++; -+ OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2)); -+ OUT_RING(exa_buf->mem->kernel_bo_handle); -+ OUT_RING(RADEON_GEM_DOMAIN_VRAM); -+ OUT_RING(0); -+ *count_p = __count; -+} -+ +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr) +{ + dri_bufmgr_exa *bufmgr_exa = (dri_bufmgr_exa *)bufmgr; @@ -1699,7 +1766,7 @@ index 0000000..400b426 +} diff --git a/src/radeon_bufmgr_exa.h b/src/radeon_bufmgr_exa.h new file mode 100644 -index 0000000..03c9b0f +index 0000000..260322c --- /dev/null +++ b/src/radeon_bufmgr_exa.h @@ -0,0 +1,14 @@ @@ -1711,7 +1778,563 @@ index 0000000..03c9b0f +dri_bufmgr *radeon_bufmgr_exa_init(ScrnInfoPtr pScrn); +extern void radeon_bufmgr_exa_wait_rendering(dri_bo *bo); +extern dri_bo *radeon_bufmgr_exa_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); -+void radeon_bufmgr_exa_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p); ++void radeon_bufmgr_exa_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); ++void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); ++void radeon_bufmgr_pin(dri_bo *buf); ++void radeon_bufmgr_unpin(dri_bo *buf); ++uint32_t radeon_bufmgr_get_handle(dri_bo *buf); ++#endif +diff --git a/src/radeon_bufmgr_gem.c b/src/radeon_bufmgr_gem.c +new file mode 100644 +index 0000000..db28edc +--- /dev/null ++++ b/src/radeon_bufmgr_gem.c +@@ -0,0 +1,530 @@ ++/************************************************************************** ++ * ++ * Copyright © 2007-2008 Red Hat Inc. ++ * 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 ++ * Keith Whitwell ++ * Eric Anholt ++ * Dave Airlie ++ * Kristian Høgsberg ++ */ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "xf86.h" ++#include "errno.h" ++#include "dri_bufmgr.h" ++#include "string.h" ++ ++#include "radeon_reg.h" ++#include "radeon_probe.h" ++#include "radeon.h" ++#include "radeon_bufmgr.h" ++ ++#define DBG(...) do { \ ++ if (bufmgr_gem->bufmgr.debug) \ ++ fprintf(stderr, __VA_ARGS__); \ ++} while (0) ++ ++typedef struct _dri_bo_gem { ++ dri_bo bo; ++ int refcount; ++ int reloc_count; ++ int map_count; ++ /* reloc list - add to list for relocs */ ++ uint32_t gem_handle; ++ const char *name; ++ struct _dri_bo_gem *next; ++ struct _dri_bo_gem *reloc_next; ++ int in_vram; /* have we migrated this bo to VRAM ever */ ++} dri_bo_gem; ++ ++struct dri_gem_bo_bucket { ++ dri_bo_gem *head, **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 RADEON_GEM_BO_BUCKETS 16 ++ ++typedef struct _dri_bufmgr_gem { ++ dri_bufmgr bufmgr; ++ struct radeon_bufmgr radeon_bufmgr; ++ int fd; ++ struct _dri_bo_gem *reloc_head; ++ ++ /** Array of lists of cached gem objects of power-of-two sizes */ ++ struct dri_gem_bo_bucket cache_bucket[RADEON_GEM_BO_BUCKETS]; ++} dri_bufmgr_gem; ++ ++static int ++logbase2(int n) ++{ ++ int i = 1; ++ int 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 >= RADEON_GEM_BO_BUCKETS) ++ return NULL; ++ ++ return &bufmgr_gem->cache_bucket[i]; ++} ++ ++ ++static dri_bo * ++dri_gem_bo_alloc(dri_bufmgr *bufmgr, const char *name, ++ unsigned long size, unsigned int alignment) ++ ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; ++ struct drm_radeon_gem_create args; ++ int ret; ++ unsigned int page_size = getpagesize(); ++ dri_bo_gem *gem_bo; ++ struct dri_gem_bo_bucket *bucket; ++ int alloc_from_cache = 0; ++ unsigned long bo_size; ++ ++ /* Round the allocated size up to a power of two number of pages. */ ++ bo_size = 1 << logbase2(size); ++ if (bo_size < page_size) ++ bo_size = page_size; ++ bucket = dri_gem_bo_bucket_for_size(bufmgr_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_size = size; ++ if (bo_size < page_size) ++ bo_size = page_size; ++ } ++ ++ /* Get a buffer out of the cache if available */ ++ if (bucket != NULL && bucket->num_entries > 0) { ++ struct drm_radeon_gem_set_domain args; ++ ++ gem_bo = bucket->head; ++ args.handle = gem_bo->gem_handle; ++ args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM; ++ args.write_domain = 0; ++ ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_RADEON_GEM_SET_DOMAIN, &args); ++ alloc_from_cache = (ret == 0); ++ ++ if (alloc_from_cache) { ++ bucket->head = gem_bo->next; ++ if (gem_bo->next == NULL) ++ bucket->tail = &bucket->head; ++ bucket->num_entries--; ++ } ++ } ++ ++ if (!alloc_from_cache) { ++ ++ gem_bo = calloc(1, sizeof(*gem_bo)); ++ if (!gem_bo) ++ return NULL; ++ ++ gem_bo->bo.size = bo_size; ++ args.size = bo_size; ++ args.alignment = alignment; ++ args.initial_domain = RADEON_GEM_DOMAIN_CPU; ++ args.no_backing_store = 0; ++ ++ ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); ++ gem_bo->gem_handle = args.handle; ++ if (ret != 0) { ++ free(gem_bo); ++ return NULL; ++ } ++ gem_bo->bo.bufmgr = bufmgr; ++ } ++ ++ gem_bo->refcount = 1; ++ gem_bo->reloc_count = 0; ++ gem_bo->map_count = 0; ++ gem_bo->in_vram = 0; ++ gem_bo->name = name; ++ ++ DBG("bo_create: buf %d (%s) %ldb: %d\n", ++ gem_bo->gem_handle, gem_bo->name, size, alloc_from_cache); ++ ++ return &gem_bo->bo; ++} ++ ++static void ++dri_gem_bo_reference(dri_bo *bo) ++{ ++ dri_bo_gem *gem_bo = (dri_bo_gem *)bo; ++ gem_bo->refcount++; ++} ++ ++static void dri_gem_bo_free(dri_bo *bo) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)bo; ++ struct drm_gem_close args; ++ ++ if (gem_bo->map_count) ++ munmap(gem_bo->bo.virtual, gem_bo->bo.size); ++ ++ /* close object */ ++ args.handle = gem_bo->gem_handle; ++ ioctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &args); ++ free(gem_bo); ++} ++ ++static void ++dri_gem_bo_unreference(dri_bo *bo) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)bo; ++ ++ if (!bo) ++ return; ++ ++ if (--gem_bo->refcount == 0) { ++ struct dri_gem_bo_bucket *bucket; ++ ++ ++ bucket = dri_gem_bo_bucket_for_size(bufmgr_gem, bo->size); ++ /* Put the buffer into our internal cache for reuse if we can. */ ++ if ((gem_bo->in_vram == 0) && (bucket != NULL && ++ (bucket->max_entries == -1 || ++ (bucket->max_entries > 0 && ++ bucket->num_entries < bucket->max_entries)))) ++ { ++ DBG("bo_unreference final: %d (%s) 1\n", ++ gem_bo->gem_handle, gem_bo->name); ++ ++ gem_bo->name = 0; ++ ++ gem_bo->next = NULL; ++ *bucket->tail = gem_bo; ++ bucket->tail = &gem_bo->next; ++ bucket->num_entries++; ++ } else { ++ DBG("bo_unreference final: %d (%s) 0 - free %d\n", ++ gem_bo->gem_handle, gem_bo->name, gem_bo->in_vram); ++ dri_gem_bo_free(bo); ++ } ++ ++ return; ++ } ++} ++ ++static int ++dri_gem_bo_map(dri_bo *bo, int write_enable) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)bo; ++ struct drm_radeon_gem_mmap args; ++ int ret; ++ ++ if (gem_bo->map_count++ != 0) ++ return 0; ++ ++ args.handle = gem_bo->gem_handle; ++ args.offset = 0; ++ args.size = gem_bo->bo.size; ++ ++ ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_MMAP, &args, sizeof(args)); ++ if (!ret) ++ gem_bo->bo.virtual = (void *)(unsigned long)args.addr_ptr; ++ ++ return ret; ++} ++ ++static int ++dri_gem_bo_unmap(dri_bo *buf) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)buf; ++ ++ if (--gem_bo->map_count > 0) ++ return 0; ++ ++ munmap(gem_bo->bo.virtual, gem_bo->bo.size); ++ gem_bo->bo.virtual = 0; ++ return 0; ++} ++ ++static void ++dri_bufmgr_gem_destroy(dri_bufmgr *bufmgr) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; ++ int i; ++ ++ /* Free any cached buffer objects we were going to reuse */ ++ for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) { ++ struct dri_gem_bo_bucket *bucket = &bufmgr_gem->cache_bucket[i]; ++ dri_bo_gem *bo_gem; ++ ++ while ((bo_gem = bucket->head) != NULL) { ++ bucket->head = bo_gem->next; ++ if (bo_gem->next == NULL) ++ bucket->tail = &bucket->head; ++ bucket->num_entries--; ++ ++ dri_gem_bo_free(&bo_gem->bo); ++ } ++ } ++ free(bufmgr); ++} ++ ++void radeon_bufmgr_gem_wait_rendering(dri_bo *buf) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; ++ struct drm_radeon_gem_set_domain dom_args; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)buf; ++ int ret; ++ ++ dom_args.handle = gem_bo->gem_handle; ++ dom_args.read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM; ++ dom_args.write_domain = 0; ++ ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_SET_DOMAIN, ++ &dom_args, sizeof(dom_args)); ++ return; ++} ++ ++/** ++ * 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 * ++radeon_bo_gem_create_from_name(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->gem_handle = open_arg.handle; ++ ++ return &bo_gem->bo; ++} ++ ++#define BUF_OUT_RING(x) do { \ ++ __head[__count++] = (x); \ ++ } while (0) ++ ++void radeon_bufmgr_gem_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; ++ dri_bo_gem *gem_bo = (dri_bo_gem *)buf; ++ uint32_t *__head = head; ++ uint32_t __count = *count_p; ++ dri_bo_gem *trav; ++ ++ if (gem_bo->reloc_count == 0) { ++ dri_bo_reference(buf); ++ ++ if (bufmgr_gem->reloc_head == NULL) ++ bufmgr_gem->reloc_head = gem_bo; ++ else { ++ trav = bufmgr_gem->reloc_head; ++ while (trav->reloc_next != NULL) ++ trav = trav->reloc_next; ++ trav->reloc_next = gem_bo; ++ } ++ } ++ ++ if (write_domain == RADEON_GEM_DOMAIN_VRAM) { ++ if (gem_bo->in_vram == 0) ++ DBG("bo_into vram: buf %d (%s) %d %d\n", ++ gem_bo->gem_handle, gem_bo->name, read_domains, write_domain); ++ ++ gem_bo->in_vram = 1; ++ } ++ ++ gem_bo->reloc_count++; ++ BUF_OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 2)); ++ BUF_OUT_RING(gem_bo->gem_handle); ++ BUF_OUT_RING(read_domains); ++ BUF_OUT_RING(write_domain); ++ *count_p = __count; ++} ++ ++/** ++ * 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 ++radeon_bufmgr_gem_enable_reuse(dri_bufmgr *bufmgr) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; ++ int i; ++ ++ for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) { ++ bufmgr_gem->cache_bucket[i].max_entries = -1; ++ } ++} ++ ++/** ++ * Initializes the GEM buffer manager, which is just a thin wrapper ++ * around the GEM allocator. ++ * ++ * \param fd File descriptor of the opened DRM device. ++ * \param fence_type Driver-specific fence type used for fences with no flush. ++ * \param fence_type_flush Driver-specific fence type used for fences with a ++ * flush. ++ */ ++dri_bufmgr * ++radeon_bufmgr_gem_init(int fd) ++{ ++ dri_bufmgr_gem *bufmgr_gem; ++ int i; ++ ++ bufmgr_gem = calloc(1, sizeof(*bufmgr_gem)); ++ bufmgr_gem->fd = fd; ++ ++ bufmgr_gem->bufmgr.bo_alloc = dri_gem_bo_alloc; ++ 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.destroy = dri_bufmgr_gem_destroy; ++ bufmgr_gem->bufmgr.bo_wait_rendering = radeon_bufmgr_gem_wait_rendering; ++ bufmgr_gem->radeon_bufmgr.emit_reloc = radeon_bufmgr_gem_emit_reloc; ++ /* Initialize the linked lists for BO reuse cache. */ ++ for (i = 0; i < RADEON_GEM_BO_BUCKETS; i++) ++ bufmgr_gem->cache_bucket[i].tail = &bufmgr_gem->cache_bucket[i].head; ++ bufmgr_gem->bufmgr.debug = 0; ++ return &bufmgr_gem->bufmgr; ++} ++ ++ ++void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr) ++{ ++ dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; ++ struct _dri_bo_gem *trav, *prev; ++ ++ if (!bufmgr_gem->reloc_head) ++ return; ++ ++ trav = bufmgr_gem->reloc_head; ++ while (trav) { ++ prev = trav; ++ trav = trav->reloc_next; ++ ++ prev->reloc_count = 0; ++ prev->reloc_next = NULL; ++ dri_bo_unreference(&prev->bo); ++ } ++ bufmgr_gem->reloc_head = NULL; ++ ++} ++ ++void radeon_gem_bufmgr_pin(dri_bo *buf) ++{ ++} ++ ++void radeon_gem_bufmgr_unpin(dri_bo *buf) ++{ ++} ++ ++uint32_t radeon_gem_bufmgr_get_handle(dri_bo *buf) ++{ ++ dri_bo_gem *gem_bo = (dri_bo_gem *)buf; ++ ++ return gem_bo->gem_handle; ++} ++ ++void radeon_bufmgr_emit_reloc(dri_bo *buf, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain) ++{ ++ struct radeon_bufmgr *radeon_bufmgr; ++ ++ radeon_bufmgr = (struct radeon_bufmgr *)(buf->bufmgr + 1); ++ radeon_bufmgr->emit_reloc(buf, head, count_p, read_domains, write_domain); ++} +diff --git a/src/radeon_bufmgr_gem.h b/src/radeon_bufmgr_gem.h +new file mode 100644 +index 0000000..e2f1ca6 +--- /dev/null ++++ b/src/radeon_bufmgr_gem.h +@@ -0,0 +1,14 @@ ++#ifndef RADEON_BUFMGR_GEM_H ++#define RADEON_BUFMGR_GEM_H ++ ++#include "dri_bufmgr.h" ++ ++dri_bufmgr *radeon_bufmgr_gem_init(ScrnInfoPtr pScrn); ++extern void radeon_bufmgr_gem_wait_rendering(dri_bo *bo); ++extern dri_bo *radeon_bufmgr_gem_create_bo(dri_bufmgr *bufmgr, struct radeon_memory *mem); ++void radeon_bufmgr_gem_emit_reloc(dri_bo *bo, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); +void radeon_bufmgr_pin(dri_bo *buf); +void radeon_bufmgr_unpin(dri_bo *buf); @@ -1866,7 +2489,7 @@ index 13c2b9c..1e1835a 100644 FBAreaPtr fbarea; diff --git a/src/radeon_dri.c b/src/radeon_dri.c -index a192811..3783b8f 100644 +index a192811..9fa0add 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -40,6 +40,8 @@ @@ -1926,7 +2549,7 @@ index a192811..3783b8f 100644 } + -+static uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem) ++uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_gem_flink flink; @@ -2595,7 +3218,7 @@ index a192811..3783b8f 100644 + +} diff --git a/src/radeon_driver.c b/src/radeon_driver.c -index 45d2c2f..bce3cc5 100644 +index 45d2c2f..8fa32ab 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -1621,6 +1621,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) @@ -3368,7 +3991,7 @@ index 45d2c2f..bce3cc5 100644 xf86DrvMsg(scrnIndex, X_ERROR, "Static buffer allocation failed. Disabling DRI.\n"); xf86DrvMsg(scrnIndex, X_ERROR, -@@ -3421,15 +3537,38 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +@@ -3421,15 +3537,39 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } @@ -3385,8 +4008,9 @@ index 45d2c2f..bce3cc5 100644 info->directRenderingEnabled = FALSE; + } + } -+ info->bufmgr = radeon_bufmgr_exa_init(pScrn); ++ info->bufmgr = radeon_bufmgr_gem_init(info->drmFD); + drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr); ++ //radeon_bufmgr_gem_enable_reuse(info->bufmgr); + radeon_setup_kernel_mem(pScreen); + front_ptr = info->mm.front_buffer->map; + pScrn->fbOffset = info->mm.front_buffer->offset; @@ -3410,7 +4034,7 @@ index 45d2c2f..bce3cc5 100644 #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing fb layer\n"); -@@ -3453,7 +3592,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +@@ -3453,7 +3593,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, if (info->r600_shadow_fb == FALSE) { /* Init fb layer */ @@ -3419,7 +4043,7 @@ index 45d2c2f..bce3cc5 100644 pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) -@@ -3508,7 +3647,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +@@ -3508,7 +3648,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* DRI finalisation */ #ifdef XF86DRI @@ -3428,7 +4052,7 @@ index 45d2c2f..bce3cc5 100644 info->pKernelDRMVersion->version_minor >= 19) { if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_PCIGART_LOCATION, info->pciGartOffset) < 0) -@@ -3527,15 +3666,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, +@@ -3527,15 +3667,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { @@ -3454,7 +4078,7 @@ index 45d2c2f..bce3cc5 100644 } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); -@@ -5355,6 +5500,11 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) +@@ -5355,6 +5501,11 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) xf86OutputPtr output = config->output[config->compat_output]; xf86CrtcPtr crtc = output->crtc; @@ -3466,7 +4090,7 @@ index 45d2c2f..bce3cc5 100644 #ifdef XF86DRI if (info->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif -@@ -5390,67 +5540,76 @@ Bool RADEONEnterVT(int scrnIndex, int flags) +@@ -5390,67 +5541,76 @@ Bool RADEONEnterVT(int scrnIndex, int flags) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONEnterVT\n"); @@ -3589,7 +4213,7 @@ index 45d2c2f..bce3cc5 100644 } #endif /* this will get XVideo going again, but only if XVideo was initialised -@@ -5462,7 +5621,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) +@@ -5462,7 +5622,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) RADEONEngineRestore(pScrn); #ifdef XF86DRI @@ -3598,7 +4222,7 @@ index 45d2c2f..bce3cc5 100644 RADEONCP_START(pScrn, info); DRIUnlock(pScrn->pScreen); } -@@ -5485,24 +5644,26 @@ void RADEONLeaveVT(int scrnIndex, int flags) +@@ -5485,24 +5645,26 @@ void RADEONLeaveVT(int scrnIndex, int flags) "RADEONLeaveVT\n"); #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { @@ -3638,7 +4262,7 @@ index 45d2c2f..bce3cc5 100644 i = 0; -@@ -5531,10 +5692,15 @@ void RADEONLeaveVT(int scrnIndex, int flags) +@@ -5531,10 +5693,15 @@ void RADEONLeaveVT(int scrnIndex, int flags) xf86_hide_cursors (pScrn); @@ -3657,7 +4281,7 @@ index 45d2c2f..bce3cc5 100644 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Ok, leaving now...\n"); -@@ -5579,7 +5745,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) +@@ -5579,7 +5746,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif /* USE_XAA */ if (pScrn->vtSema) { @@ -3667,7 +4291,7 @@ index 45d2c2f..bce3cc5 100644 } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, -@@ -5614,6 +5781,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) +@@ -5614,6 +5782,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) info->DGAModes = NULL; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Unmapping memory\n"); @@ -3681,7 +4305,7 @@ index 45d2c2f..bce3cc5 100644 pScrn->vtSema = FALSE; diff --git a/src/radeon_exa.c b/src/radeon_exa.c -index 02fd4fc..bc489fc 100644 +index 02fd4fc..555ae16 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -47,6 +47,13 @@ @@ -3744,13 +4368,13 @@ index 02fd4fc..bc489fc 100644 + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv) { - ++ + if (driver_priv->bo) { + int ret; + + RADEONCPFlushIndirect(pScrn, 0); + -+ radeon_bufmgr_exa_wait_rendering(driver_priv->bo); ++ //radeon_bufmgr_gem_wait_rendering(driver_priv->bo); + + /* flush IB */ + ret = dri_bo_map(driver_priv->bo, 1); @@ -3762,7 +4386,7 @@ index 02fd4fc..bc489fc 100644 + pPix->devPrivate.ptr = driver_priv->bo->virtual; + } + } -+ + +#if X_BYTE_ORDER == X_BIG_ENDIAN /* Front buffer is always set with proper swappers */ if (offset == 0) @@ -3782,17 +4406,17 @@ index 02fd4fc..bc489fc 100644 + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); - ++ + if (driver_priv) { + dri_bo_unmap(driver_priv->bo); + } + pPix->devPrivate.ptr = NULL; -+ + +#if X_BYTE_ORDER == X_BIG_ENDIAN /* Front buffer is always set with proper swappers */ if (offset == 0) return; -@@ -294,13 +348,97 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index) +@@ -294,13 +348,100 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index) OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, 0); OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, 0); swapper_surfaces[index] = 0; @@ -3862,8 +4486,11 @@ index 02fd4fc..bc489fc 100644 + if (pPixData == info->mm.front_buffer->map) { + driver_priv->flags |= RADEON_PIXMAP_IS_FRONTBUFFER; + -+ driver_priv->bo = -+ radeon_bufmgr_exa_create_bo(info->bufmgr, info->mm.front_buffer); ++ if (info->new_cs) ++ driver_priv->bo = radeon_bo_gem_create_from_name(info->bufmgr, "front", ++ radeon_name_buffer(pScrn, info->mm.front_buffer)); ++ else ++ driver_priv->bo = radeon_bufmgr_exa_create_bo(info->bufmgr, info->mm.front_buffer); + + miModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, NULL); @@ -3892,7 +4519,7 @@ index 02fd4fc..bc489fc 100644 BEGIN_ACCEL(1); \ switch (info->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ -@@ -317,7 +455,7 @@ do { \ +@@ -317,7 +458,7 @@ do { \ #define RADEON_SWITCH_TO_3D() \ do { \ @@ -3901,15 +4528,15 @@ index 02fd4fc..bc489fc 100644 BEGIN_ACCEL(1); \ switch (info->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ -@@ -341,6 +479,7 @@ do { \ +@@ -341,6 +482,7 @@ do { \ #define BEGIN_ACCEL(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_ACCEL_REG(reg, val) OUTREG(reg, val) #define OUT_ACCEL_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) -+#define OUT_RELOC(x) do {} while(0) ++#define OUT_RELOC(x, read, write) do {} while(0) #define FINISH_ACCEL() #ifdef RENDER -@@ -353,6 +492,7 @@ do { \ +@@ -353,6 +495,7 @@ do { \ #undef BEGIN_ACCEL #undef OUT_ACCEL_REG #undef FINISH_ACCEL @@ -3917,15 +4544,15 @@ index 02fd4fc..bc489fc 100644 #ifdef XF86DRI -@@ -363,6 +503,7 @@ do { \ +@@ -363,6 +506,7 @@ do { \ #define BEGIN_ACCEL(n) BEGIN_RING(2*(n)) #define OUT_ACCEL_REG(reg, val) OUT_RING_REG(reg, val) #define FINISH_ACCEL() ADVANCE_RING() -+#define OUT_RELOC(x) OUT_RING_RELOC(x) ++#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) #define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) -@@ -373,6 +514,8 @@ do { \ +@@ -373,6 +517,8 @@ do { \ #endif /* XF86DRI */ @@ -3934,7 +4561,7 @@ index 02fd4fc..bc489fc 100644 /* * Once screen->off_screen_base is set, this function * allocates the remaining memory appropriately -@@ -394,125 +537,124 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) +@@ -394,125 +540,124 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) if (info->exa == NULL) return FALSE; @@ -4001,10 +4628,7 @@ index 02fd4fc..bc489fc 100644 - * when GLX is set up, but the offscreen memory manager's allocations - * don't last through VT switches, while the kernel's understanding of - * offscreen locations does. -+ if (info->drm_mm == FALSE) { -+ /* Need to adjust screen size for 16 line tiles, and then make it align to. -+ * the buffer alignment requirement. - */ +- */ - info->backPitch = pScrn->displayWidth; - next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); - if (!info->noBackBuffer && @@ -4019,7 +4643,10 @@ index 02fd4fc..bc489fc 100644 - - /* Reserve the static depth buffer, and adjust pitch and height to - * handle tiling. -- */ ++ if (info->drm_mm == FALSE) { ++ /* Need to adjust screen size for 16 line tiles, and then make it align to. ++ * the buffer alignment requirement. + */ - info->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); - depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->depthPitch * depthCpp; - next = RADEON_ALIGN(info->exa->offScreenBase, RADEON_BUFFER_ALIGN); @@ -4167,8 +4794,32 @@ index 02fd4fc..bc489fc 100644 return TRUE; } +@@ -525,10 +670,21 @@ extern void ExaOffscreenMarkUsed(PixmapPtr); + unsigned long long + RADEONTexOffsetStart(PixmapPtr pPix) + { ++ struct radeon_exa_pixmap_priv *driver_priv; ++ uint32_t offset; ++ driver_priv = exaGetPixmapDriverPrivate(pPix); ++ ++ if (driver_priv) { ++ offset = driver_priv->bo->offset; ++ ++ } else { ++ offset = exaGetPixmapOffset(pPix); ++ offset += RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation; ++ } + exaMoveInPixmap(pPix); + ExaOffscreenMarkUsed(pPix); ++ + +- return RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation + +- exaGetPixmapOffset(pPix); ++ return offset; + } + #endif diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c -index 56de23e..51b792e 100644 +index 56de23e..628d2c7 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -74,21 +74,69 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) @@ -4217,12 +4868,12 @@ index 56de23e..51b792e 100644 + + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); + if (info->new_cs) -+ OUT_RELOC(info->state_2d.dst_bo); ++ OUT_RELOC(info->state_2d.dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); + + if (has_src) { + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, info->state_2d.src_pitch_offset); + if (info->new_cs) -+ OUT_RELOC(info->state_2d.src_bo); ++ OUT_RELOC(info->state_2d.src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); + + } + FINISH_ACCEL(); @@ -4390,17 +5041,54 @@ index 56de23e..51b792e 100644 } static Bool -@@ -276,10 +352,19 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, +@@ -260,6 +336,8 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, + uint8_t *dst = info->FB + exaGetPixmapOffset(pDst); + unsigned int dst_pitch = exaGetPixmapPitch(pDst); + unsigned int bpp = pDst->drawable.bitsPerPixel; ++ int ret; ++ struct radeon_exa_pixmap_priv *driver_priv; + #ifdef ACCEL_CP + unsigned int hpass; + uint32_t buf_pitch, dst_pitch_off; +@@ -276,10 +354,47 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, if (bpp < 8) return FALSE; + if (info->new_cs) -+ dst = info->mm.front_buffer->map + exaGetPixmapOffset(pDst); ++ dst = info->mm.front_buffer->map + exaGetPixmapOffset(pDst); + #ifdef ACCEL_CP - if (info->directRenderingEnabled && - RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) { - uint8_t *buf; ++ ++ if (info->new_cs){ ++ ++ if (info->drm_mm) { ++ uint32_t offset, bo_width, bo_height = h; ++ ++ driver_priv = exaGetPixmapDriverPrivate(pDst); ++ if (!driver_priv) ++ return FALSE; ++ ++ ++ /* use pwrites - maybe require some sort of fallback */ ++ bo_width = w * (bpp / 8); ++ offset = (x * bpp / 8) + (y * dst_pitch); ++ ++ while (bo_height--) { ++ ret = dri_bo_subdata(driver_priv->bo, offset, bo_width, ++ src); ++ if (ret == -1) ++ return FALSE; ++ ++ src += src_pitch; ++ offset += dst_pitch; ++ } ++ ++ return TRUE; ++ } ++ } + if (!info->directRenderingEnabled && !info->drm_mode_setting) + goto fallback; + @@ -4413,7 +5101,7 @@ index 56de23e..51b792e 100644 int cpp = bpp / 8; ACCEL_PREAMBLE(); -@@ -294,9 +379,10 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, +@@ -294,9 +409,10 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, exaMarkSync(pDst->drawable.pScreen); return TRUE; @@ -4426,7 +5114,7 @@ index 56de23e..51b792e 100644 /* Do we need that sync here ? probably not .... */ exaWaitSync(pDst->drawable.pScreen); -@@ -388,13 +474,17 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, +@@ -388,13 +504,17 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, TRACE; @@ -4445,19 +5133,18 @@ index 56de23e..51b792e 100644 RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) && (scratch = RADEONCPGetBuffer(pScrn))) { -@@ -540,17 +630,23 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) +@@ -540,17 +660,23 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) info->exa->MarkSync = FUNC_NAME(RADEONMarkSync); info->exa->WaitMarker = FUNC_NAME(RADEONSync); -- info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); ++ + info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); - info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); - --#if X_BYTE_ORDER == X_BIG_ENDIAN + if (!info->drm_mm) { -+ info->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); + info->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); + } -+ + +-#if X_BYTE_ORDER == X_BIG_ENDIAN info->exa->PrepareAccess = RADEONPrepareAccess; info->exa->FinishAccess = RADEONFinishAccess; -#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ @@ -4474,7 +5161,7 @@ index 56de23e..51b792e 100644 #ifdef RENDER if (info->RenderAccel) { -@@ -560,7 +656,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) +@@ -560,7 +686,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) else if (IS_R300_3D || IS_R500_3D) { if ((info->ChipFamily < CHIP_FAMILY_RS400) #ifdef XF86DRI @@ -4483,7 +5170,7 @@ index 56de23e..51b792e 100644 #endif ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " -@@ -595,6 +691,16 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) +@@ -595,6 +721,16 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) } #endif @@ -4501,7 +5188,7 @@ index 56de23e..51b792e 100644 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n"); diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c -index 5d28d80..1738ca3 100644 +index 5d28d80..6426736 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -410,19 +410,22 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix, @@ -4581,7 +5268,7 @@ index 5d28d80..1738ca3 100644 + if (info->new_cs) { + uint32_t handle = 0; + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), driver_priv ? 0 : txoffset); -+ OUT_RELOC(driver_priv->bo); ++ OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset); @@ -4620,7 +5307,7 @@ index 5d28d80..1738ca3 100644 - OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0); -+ OUT_RELOC(driver_priv->bo); ++ OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); @@ -5119,14 +5806,14 @@ index 80333a4..c33632b 100644 +typedef drm_radeon_sarea_t RADEONSAREAPriv, *RADEONSAREAPrivPtr; +#endif diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c -index cfa349d..2ec4cc1 100644 +index cfa349d..ef05c72 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -85,6 +85,7 @@ static __inline__ uint32_t F_TO_DW(float val) #define BEGIN_VIDEO(n) RADEONWaitForFifo(pScrn, (n)) #define OUT_VIDEO_REG(reg, val) OUTREG(reg, val) #define OUT_VIDEO_REG_F(reg, val) OUTREG(reg, F_TO_DW(val)) -+#define OUT_RELOC(x) do {} while(0) ++#define OUT_RELOC(x, read, write) do {} while(0) #define FINISH_VIDEO() #include "radeon_textured_videofuncs.c" @@ -5142,7 +5829,7 @@ index cfa349d..2ec4cc1 100644 #define OUT_VIDEO_REG(reg, val) OUT_RING_REG(reg, val) #define FINISH_VIDEO() ADVANCE_RING() #define OUT_VIDEO_RING_F(x) OUT_RING(F_TO_DW(x)) -+#define OUT_RELOC(x) OUT_RING_RELOC(x) ++#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) #include "radeon_textured_videofuncs.c" @@ -5181,7 +5868,7 @@ index cfa349d..2ec4cc1 100644 else #endif diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c -index d39f74d..aaf54a0 100644 +index d39f74d..56d71b1 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -82,19 +82,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv @@ -5223,7 +5910,7 @@ index d39f74d..aaf54a0 100644 + + if (info->new_cs) { + OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset); -+ OUT_RELOC(info->mm.front_buffer->kernel_bo_handle); ++ OUT_RELOC(info->mm.front_buffer->kernel_bo_handle, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_VIDEO_REG(R300_TX_OFFSET_0, txoffset); @@ -5244,7 +5931,7 @@ index d39f74d..aaf54a0 100644 - OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset); + if (info->new_cs) { + OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset); -+ OUT_RELOC(info->mm.front_buffer->kernel_bo_handle); ++ OUT_RELOC(info->mm.front_buffer->kernel_bo_handle, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_VIDEO_REG(R300_RB3D_COLOROFFSET0, dst_offset); diff --git a/xorg-x11-drv-ati.spec b/xorg-x11-drv-ati.spec index e1e6d6b..71f1a1a 100644 --- a/xorg-x11-drv-ati.spec +++ b/xorg-x11-drv-ati.spec @@ -5,7 +5,7 @@ Summary: Xorg X11 ati video driver Name: xorg-x11-drv-ati Version: 6.9.0 -Release: 5%{?dist} +Release: 6%{?dist} URL: http://www.x.org License: MIT Group: User Interface/X Hardware Support @@ -22,7 +22,7 @@ ExcludeArch: s390 s390x BuildRequires: xorg-x11-server-sdk >= 1.4.99.1 BuildRequires: mesa-libGL-devel >= 6.4-4 BuildRequires: libdrm-devel >= 2.4.0-0.19 -BuildRequires: kernel-headers >= 2.6.27-0.207 +BuildRequires: kernel-headers >= 2.6.27-0.280 BuildRequires: automake autoconf libtool pkgconfig BuildRequires: xorg-x11-util-macros >= 1.1.5 @@ -67,6 +67,9 @@ rm -rf $RPM_BUILD_ROOT %{_mandir}/man4/radeon.4* %changelog +* Tue Aug 26 2008 Dave Airlie 6.9.0-6 +- update modesetting/memory manager support + * Fri Aug 15 2008 Dave Airlie 6.9.0-5 - Add a perl script to generate the radeon.xinf from the actual PCI IDs the driver supports. - not build integrated yet though