commit 912a135fa66d50174ed925676ebcbaeae7bd8556 Author: Dave Airlie Date: Fri Nov 14 15:56:16 2008 +1000 radeon: make space accounting a lot smarter commit 1163200d644744bbfc72c205f47bf00a92446c68 Author: Dave Airlie Date: Fri Nov 14 15:55:12 2008 +1000 radeon: retry on CS2 EAGAIN commit 9f16d36104d242385e2a14916a66cdc95fca96ca Author: Dave Airlie Date: Fri Nov 14 15:20:59 2008 +1000 radeon: add src/mask/dest to fallbacks commit 38b1f12d268f5a3213380e3b4fbd730d17ba073c Author: Dave Airlie Date: Fri Nov 14 15:20:37 2008 +1000 radeon_memory: align all allocations commit 40804bd0927833048fd92ec7a1332f10f9d6a850 Author: Dave Airlie Date: Fri Nov 14 11:03:34 2008 +1000 radeon: force gtt for mmap after fallbacks commit a9bd6835e8f41a1ceb2a62bd1c4a8f92051cb620 Author: Dave Airlie Date: Mon Nov 10 14:18:17 2008 +1000 radeon: add more buffer info + fix read objects too big fallback commit 115015f904e21c9118982b4b8be6e420a72fb334 Author: Dave Airlie Date: Mon Nov 10 11:47:02 2008 +1000 radeon: remove old exa bufmgr not used anymore code commit 8883244a965896052de172aec3c4aea97adb6731 Author: Dave Airlie Date: Mon Nov 10 11:18:27 2008 +1000 radeon: fix crtc dpms need to find a better way to switch displays off commit d36e1bf4d64ed9e2c63d2d7aa985857af51e1281 Author: Dave Airlie Date: Mon Nov 10 11:18:02 2008 +1000 radeon: fix textured video corruption at least workaround it commit e62421656dcf49633380fa698d5c94394069403f Author: Dave Airlie Date: Sat Nov 8 14:48:29 2008 +1000 radeon: add DPMS support for connectors commit 7bdeb2bfbe91bfd5e5f3b1e11b3f4a717526f0b0 Author: Dave Airlie Date: Fri Nov 7 16:20:09 2008 +1000 radeon: fix rotation of right-of heads commit b4dd210c7186ea5660b902357862c59a856d3993 Author: Dave Airlie Date: Mon Nov 3 14:51:43 2008 +1000 radeon: respect fb tex percent + trust kernel values commit 1261865fa2a4f8174d31fefbf6e134d8c719ee5b Author: Dave Airlie Date: Fri Oct 31 15:05:14 2008 +1000 radeon: remove workaround hack since kernel is hopefully fixed commit 03cfb265dada3233262f40715a9a542ae889f5bc Author: Dave Airlie Date: Fri Oct 31 15:04:31 2008 +1000 radeon: workaround use after free commit e3b394a58329df2efe1b57f369cefe6803b5f853 Author: Dave Airlie Date: Thu Oct 30 13:53:02 2008 +1000 radeon: setup accel dfs for PCIE cards only if drm_mm commit 2a85b00b38da8f5419837a9b4504aa1ba69b2a32 Author: Dave Airlie Date: Thu Oct 30 10:00:10 2008 +1000 radeon: fixup name handling for bufmgr commit b57a389fa222ecb832bb72b30f2602bf086db892 Author: Dave Airlie Date: Thu Oct 30 09:59:11 2008 +1000 radeon: fix memory leak in CS2 code commit ffde9b0fa3157e956e6bc0580f10d21f191be327 Author: Dave Airlie Date: Tue Oct 28 20:35:19 2008 +1000 return on empty IBs, flush happen in the kernel commit 1714b8e5443da01d838e9804166b67fcb3a6ec45 Author: Dave Airlie Date: Tue Oct 28 10:16:09 2008 +1000 radeon: remove some debugging commit 17b7b76a702640462a3878ae745fd1f5ddd32f19 Author: Dave Airlie Date: Tue Oct 28 06:40:31 2008 +1000 radeon: enable gem wait rendering. commit 2171a9d834be69e002a93fe440450ff532758e93 Author: Dave Airlie Date: Mon Oct 27 16:51:00 2008 +1000 radeon: add new CS submission scheme commit 3a29ac76d724c9a0ed6f4c2b832178594db94a0a Author: Dave Airlie Date: Thu Oct 23 17:05:12 2008 +1000 radeon: really rough effort at vram limit setting commit dddb524ded5b4b3b663cf332a97899b24134974e Author: Dave Airlie Date: Thu Oct 23 17:04:51 2008 +1000 radeon: this shouldn't fail but it did once while debugging so patch up commit fe706004af67894eb7cf661ebd42305a754f3381 Author: Dave Airlie Date: Thu Oct 23 10:43:09 2008 +1000 radeon: fixup some memory allocation issues hopefully since the alignment got fixed this doesn't break anything commit 4e24123007f8dd8bb2aee5398778bf36d920521e Author: Dave Airlie Date: Tue Oct 21 15:50:31 2008 +1000 radeon: avoid unnecessary emits commit e207eb6181692d8afe893fcd3b39f38bd3cf202b Author: Dave Airlie Date: Tue Oct 21 15:50:17 2008 +1000 radeon: cleanup reserved space calcs commit 21d9f5b0d9507404e6a2c55955420747bee2cbfb Author: Dave Airlie Date: Tue Oct 21 15:49:48 2008 +1000 radeon: fixup Owen's optimisation - this fixes corruption I haven't a good explaination why mapping the buffer twice in a row seems to cause this failure. but I probably don't have time to track it down before release. commit dab489dc784bb14ef4a64b3ecec1c46568210c22 Author: Dave Airlie Date: Sun Oct 19 18:27:53 2008 +1000 radeon: fixup tex offset for no modeset commit 6b66d506a63c49abf781c390261c460f2183cd84 Author: Dave Airlie Date: Wed Oct 15 17:01:34 2008 +1000 radeon: add DFS support for CS commit f4f95f0a15308d4a8cb38c1ed73a0edb2e8b906a Author: airlied Date: Wed Oct 15 23:55:13 2008 +1000 radeon: add r100/r200 support for EXA render commit d8cbb2f90b4d399c1ce3ac4cfdf79894bae8d06a Author: Dave Airlie Date: Mon Oct 13 16:59:02 2008 +1000 radeon: fix switch mode path so nexuiz starts commit 65488679e8443cbebbd4ff9585ac34b1ae42da55 Author: Dave Airlie Date: Fri Oct 10 15:29:24 2008 +1000 remove gem buf caching useless on radeon commit db1d00f76acdc9868546694d4f3ab3a869ad2396 Author: Dave Airlie Date: Fri Oct 10 15:18:41 2008 +1000 radeon: drmmode make names same as for non-kms drivers commit b1a87b4b67cae5a31c87f884f40f7116ac8ecdf2 Author: Dave Airlie Date: Fri Oct 10 15:10:28 2008 +1000 radeon: fix rotation under kms commit 1eb523e28c7a1f69a9fe7b247b7828399d7e6a75 Author: Dave Airlie Date: Fri Oct 10 14:44:39 2008 +1000 radeon: remove testing fallback commit ab876f2a090a5aabb0712aa5388f224e651c83e7 Author: Kristian Høgsberg Date: Fri Oct 10 10:57:47 2008 +1100 radeon: add copy fb contents patch commit 3bd7fcef66e093ecf2d5c2badf60b8f5bb3bdd4b Author: Dave Airlie Date: Fri Oct 10 10:57:20 2008 +1100 bufmgr: turn off debug commit 44fb767aa95e5f0725386106b89d0782fd53b768 Author: Dave Airlie Date: Fri Oct 10 10:38:38 2008 +1100 radeon: fixup modesetting code after rebasing to master commit fc5d27b1b7da64fbb4ba0b4156454291a3a243c5 Author: Dave Airlie Date: Thu Oct 9 16:34:52 2008 +1100 radeon: misc cleanups in exa commit c7c2e6f7b2b12c55d0153d9c64fcf39eda5e843e Author: Dave Airlie Date: Thu Oct 9 16:34:23 2008 +1100 radeon: fix UTS for non-modesetting commit 62fd7f4335474e7a3f47c6d9aaf6c162ebddc8a5 Author: Dave Airlie Date: Thu Oct 9 16:33:59 2008 +1100 radeon: fix exa limits problem - shouldn't have been resetting scissor commit 10602f918013e3799ef41284e71307863aae1aa6 Author: Dave Airlie Date: Wed Oct 1 11:21:53 2008 +1000 radeon: fixup for latest libdrm changes commit 088cad33ef83802f42dce1a5684eb813b9bfe251 Author: Owen Taylor Date: Fri Sep 26 16:17:49 2008 -0400 Don't flush when mapping a newly created pixmap into system ram If we have a pixmap that has never been mapped into vram (and thus never written to by the GPU), there is no need to flush the graphics pipeline and wait for idle before starting to write to it. commit ec7a5b4b701da283e84a899bcfaf35b202043f7b Author: Dave Airlie Date: Mon Sep 29 16:32:51 2008 +1000 radeon: hopefully fix textured xv commit eac0d78d462e49ce0ee178a87c06d0eb697ed8b8 Author: Dave Airlie Date: Fri Sep 26 11:38:36 2008 +1000 radeon: fix the offset checks for command submission since we are relocating in the kernel we don't need these commit 8ad885b0f044bda60d38664a62c65f9d7a4f5c47 Author: Dave Airlie Date: Fri Sep 26 10:46:20 2008 +1000 radeon: fixup after mertge commit f3efa0c398d131458945b0b1a89c3fc7887e51f6 Author: Dave Airlie Date: Fri Sep 26 10:34:41 2008 +1000 radeon: fix issues with emitting DST PIPE on cards that don't use it commit ae03476547568e426c9448b0c13fa25ef3a6a2dd Author: Dave Airlie Date: Wed Sep 24 17:12:19 2008 +1000 modesetting: fixup bits of drmmode_display.c commit 5140bc984f98661ba6bc8e70025a9f43024a7551 Author: Dave Airlie Date: Wed Sep 24 15:42:01 2008 +1000 r600: fixup for kms commit bb0cfe3035c03d3703aa0a960790b6e5365759b4 Author: Dave Airlie Date: Sun Sep 7 08:01:56 2008 +1000 modeset: fix AddFB for current tree commit b90e88b455e250a2386320005385f3d70b2150f7 Author: Dave Airlie Date: Thu Aug 14 10:52:52 2008 +1000 radeon: disable overlay for modesetting for now commit 5c5736604e6a1bc280821bd92f3714e0c9e7d7d3 Author: Dave Airlie Date: Thu Aug 14 10:52:42 2008 +1000 radeon: no need for this anymore commit aa09c6d7bb28ce5fe3efbe23cf5aa9ce55275fc6 Author: Dave Airlie Date: Fri Sep 5 16:32:01 2008 +1000 radeon: fix up for suspend/resume - uses new API commit 3bf412b019c03e3e8d392a896e79d9fd9cf75a51 Author: Dave Airlie Date: Wed Aug 27 13:09:55 2008 +1000 radeon: update to proper domain this should fix 3d again for now at least commit 7e30990b969c5789d61bd61ec8d2d9955c5b9f86 Author: Dave Airlie Date: Tue Aug 26 18:29:23 2008 +1000 ddx: move to using new gem interface add a GEM bufmgr backend along the lines of Intels one. The buffer reuse is disabled and I'll probably rip it out for radeon as we can't just re-use buffers that might have ended up in VRAM etc. Probably need some sort of in-kernel re-use. commit fbb7f9cf4820bac91ad7a7684fcc8812dd8bc525 Author: Dave Airlie Date: Mon Aug 25 11:37:48 2008 +1000 radeon: add an initial GEM bufmgr commit f66550984636e426ff05d3f9109c55c36cf4ab42 Author: Dave Airlie Date: Mon Aug 25 11:37:20 2008 +1000 radeon: implement simple UTS commit 8e22a14716ba852e3945a6588df9b6b77ba10a4c Author: Dave Airlie Date: Fri Aug 22 15:34:58 2008 +1000 radeon: add read/write domains properly commit 6a5952e34df4c4d38404e6b88043cc749aeeba6a Author: Dave Airlie Date: Fri Aug 15 11:25:31 2008 +1000 radeon: fix some rotate bugs commit 22d4ea4b1b831f50fe2d2f9c90bd2a529a1f01cd Author: Dave Airlie Date: Fri Aug 15 11:16:18 2008 +1000 radeon: when create fake bos, they are already mapped commit 216cd29e2d7354181b8b32dde374bf0ad11dc90d Author: Dave Airlie Date: Fri Aug 15 11:15:58 2008 +1000 exa: remove wrong assert commit b3ac04aef5148856ecb7df2f83cb858fd1d8df29 Author: Dave Airlie Date: Tue Aug 12 19:27:44 2008 +1000 radeon: start to work on rotate pixmap support commit 043dd60d8ddcbc00367839be5d0cecf89533bfdf Author: Dave Airlie Date: Tue Aug 12 18:28:23 2008 +1000 radeon: port simple exa bufmgr exa pixmaps work now but they are slow commit 5b713057af6362d78c125a90f0cda727e9f511d1 Author: Dave Airlie Date: Thu Aug 7 17:52:04 2008 +1000 further pixmaps on EXA commit 9e245b41674e25c23dbefda37a3e13611206c05f Author: Dave Airlie Date: Thu Aug 7 11:22:46 2008 +1000 initial exa on gem hackx Conflicts: src/radeon_exa.c src/radeon_memory.c commit 0569311ee032498ac73f176baebd716146b07342 Author: Dave Airlie Date: Tue Aug 12 15:31:03 2008 +1000 radeon: initial rotate pixmap This doesn't work, we really need EXA pixmaps for this stuff commit 9054524b3bdc8de3588f838401f56c49d1528757 Author: Dave Airlie Date: Tue Aug 12 14:40:18 2008 +1000 radeon: use buffer names commit eb6b80595c9dd731d001058ff997f5e5c35710e0 Author: Dave Airlie Date: Tue Aug 12 14:38:56 2008 +1000 ati: fix do adjust mode commit e44e62cde9c1e19811bd0f9a77068d8f0927e837 Author: Dave Airlie Date: Tue Aug 12 09:38:48 2008 +1000 FEDORA: update offsets in DRI private commit 0e27902438773facffc304e2f6bf43d6a926ab81 Author: Dave Airlie Date: Tue Aug 12 09:10:18 2008 +1000 radeon: add vt bind flag commit 648360f17f285bc5cd0498161dcb0cb61eae39cd Author: Dave Airlie Date: Wed Aug 6 13:30:54 2008 +1000 radeon: warning cleanups commit d425be2a405ffd1af684d50260b16c6877fdda56 Author: Dave Airlie Date: Wed Aug 6 13:18:52 2008 +1000 radeon: remove debugging commit fe75573b5cc05590430b7ffb8b7e10666547a438 Author: Dave Airlie Date: Wed Aug 6 13:17:31 2008 +1000 radeon: add code to set memory map and not futz with mappings commit 9e586c9e941d69bd5751647f4c891c43a893ac19 Author: Dave Airlie Date: Wed Aug 6 13:16:56 2008 +1000 drm: don't futz with framebuffer when no drm_mm commit 20e17c8f386fa25418ea5fa5265785d9e52ca97f Author: Dave Airlie Date: Tue Aug 5 16:47:21 2008 +1000 radeon: undef OUT_RELOC commit dc14747b1d7446fafe3bc0a639ee964c3944f310 Author: Dave Airlie Date: Tue Aug 5 16:37:52 2008 +1000 radeon: add stdint/lib to check for modesetting commit 5ad05af2c23e5cb267234d077c43bafb87c35a5c Author: Dave Airlie Date: Tue Aug 5 16:07:31 2008 +1000 fix whitespace commit 97bb89257ec8a5bac629b8e74435ab40389665df Author: Dave Airlie Date: Tue Aug 5 16:07:07 2008 +1000 radeon: fix build issue commit ccc8673d3e0c37e3ff8f8627d215086e607d0a60 Author: Dave Airlie Date: Mon Aug 4 16:27:55 2008 +1000 radeon: free all pinned memory on server shutdown commit 894aaf6ec6a8ba851d836358adc28cd122b5270a Author: Dave Airlie Date: Mon Aug 4 16:11:30 2008 +1000 radeon: get textured video working on the memory manager commit 2c9a7762718ef0560a383f2729ecf72baecb669b Author: Dave Airlie Date: Mon Aug 4 16:11:18 2008 +1000 radeon: convert bus addr to void pointer commit 32f376d062dea6eabb8eca23a23ec9f2967b2073 Author: Dave Airlie Date: Mon Aug 4 15:11:13 2008 +1000 radeon: avoid z cache flushes if not needed commit bbd6b19554096bd4880405aa9dfd378cbef8471e Author: Dave Airlie Date: Wed Jul 30 17:04:22 2008 +1000 radeon: update DRI support, so mappings get added We only add fake frontbuffer mapping as DRI clients expect one. commit b419e9c91730c2c9bc94f9df8fba4310d0c4f554 Author: Dave Airlie Date: Tue Jul 29 16:50:03 2008 +1000 radeon: exa through the handle relocation function commit 0c2b073855ead62eca8757c4a52b3c7838d6ec3d Author: Dave Airlie Date: Tue Jul 29 14:58:22 2008 +1000 radeon: keep track of 2D state This lets the kernel use the 2D blit engine in theory commit bb18f9fb7232ab2182fb40d2aa79fb4afb1fc19b Author: Dave Airlie Date: Mon Jul 28 17:48:59 2008 +1000 new command submission attempt commit aca38e9562a307f7a668b3aeffc849bd3658eaab Author: Dave Airlie Date: Mon Jul 28 17:48:08 2008 +1000 radeon: fixup over fluishing problem commit 06494b222640cb4315231c31fa172a0345fb3497 Author: Dave Airlie Date: Mon Jul 28 17:44:51 2008 +1000 hack for now: divide texture size by 2 commit 7e2f6d6a14a7736151db128348b9578faeb3e134 Author: Dave Airlie Date: Fri Jul 25 17:07:20 2008 +1000 radeon: fix dri message commit 28d65fc64b1195aa3f3592979d9ed15d0b26847b Author: Dave Airlie Date: Fri Jul 25 15:11:58 2008 +1000 radeon: fix pool which caused memory corruption commit 2bb5310123a8fc4838ab17d6aa6fc0b30ec91d8a Author: Dave Airlie Date: Fri Jul 25 14:59:07 2008 +1000 radeon: get DRI to attempt to start up commit aa657a2e9698ae25e9ad985b205e9bf051338e3b Author: Dave Airlie Date: Fri Jul 25 14:58:23 2008 +1000 radeon: call the right sync function commit 02ff76a1adcfd1ea11798c545256a1021fbba1ce Author: Dave Airlie Date: Fri Jul 25 14:57:21 2008 +1000 radeon: unmap memory from objects commit cbb97ec98e1d67cab9fc10e4bb8e12a01972a041 Author: Dave Airlie Date: Wed Jul 23 10:59:16 2008 +1000 use CP for 3D engine with modeset commit a479fcf9c158e232cf2c97de007616a9854e455d Author: Dave Airlie Date: Wed Jul 23 10:59:04 2008 +1000 radeon: fix DFS commit 7b39d83234e7c87f59817e6bdc9f4ae8eae4df15 Author: Dave Airlie Date: Wed Jul 23 10:48:45 2008 +1000 radeon: get the fb location right commit 72dc11e13790d24e8da308231dc0643ce072771e Author: Dave Airlie Date: Tue Jul 22 18:08:25 2008 +1000 radeon: make at least the EXA stipple work.. commit 95b985e65164788ac76ef5c59e6b9b9cb8f931a1 Author: Dave Airlie Date: Tue Jul 22 18:07:15 2008 +1000 radeon: disable debugging for now commit 695387eaecb3c626d81ee4f326f49fb5093d65fe Author: Dave Airlie Date: Mon Jul 21 18:40:14 2008 +1000 radeon: initial indirect buffer use. Move EXA and front allocation into one big buffer to workaround EXA issues - need to move to driver pixmap hooks. Add new indirect GEM to take indirect buffers. doesn't work think the offsets are all wrong. commit cf3caa7ca957fff69a9f11624e61017c30068f95 Author: Dave Airlie Date: Fri Jul 18 13:46:41 2008 +1000 modesetting step 1: have X and a cursor commit 409e8b3d156e16dd2300a11ae99f4d552dd84e20 Author: Dave Airlie Date: Thu Jul 17 09:59:19 2008 +1000 radeon: add radeon_memory.c commit ee9f68d728aae8fff4f4194d8e6d6d70f6168ce2 Author: Dave Airlie Date: Tue Jul 8 16:55:27 2008 +1000 remove mappings of some buffers. use drm gart code if available commit 8e4a09253d52e9c097871b06c522f1c7ef2b9b14 Author: Dave Airlie Date: Mon Jul 7 16:54:35 2008 +1000 add initial support for a kernel memory manager This just pins all the current allocations via the kernel memory manager instead of trying to do them all in userspace. useful steps towards getting kernel modesetting commit 12e71eaf7999520d23d50cfbcfc0299b2bdf7a9d Author: Dave Airlie Date: Fri Jul 4 10:39:34 2008 +1000 port to using drm header files diff --git a/configure.ac b/configure.ac index b8c18a6..8b126b5 100644 --- a/configure.ac +++ b/configure.ac @@ -115,6 +115,15 @@ if test "$DRI" = yes; then if test "$have_damage_h" = yes; then AC_DEFINE(DAMAGE,1,[Use Damage extension]) fi + + save_CFLAGS="$CFLAGS" + CFLAGS="$XORG_CFLAGS $DRI_CFLAGS" + AC_CHECK_HEADER(xf86drmMode.h,[DRM_MODE=yes],[DRM_MODE=no],[#include +#include ]) + if test "x$DRM_MODE" = xyes; then + AC_DEFINE(XF86DRM_MODE,1,[DRM kernel modesetting]) + fi + CFLAGS="$save_CFLAGS" fi save_CFLAGS="$CFLAGS" diff --git a/src/Makefile.am b/src/Makefile.am index d65a3e4..1be325a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -90,12 +90,13 @@ radeon_drv_ladir = @moduledir@/drivers radeon_drv_la_SOURCES = \ radeon_accel.c radeon_cursor.c radeon_dga.c radeon_legacy_memory.c \ radeon_driver.c radeon_video.c radeon_bios.c radeon_mm_i2c.c \ - radeon_vip.c radeon_misc.c radeon_probe.c \ + radeon_vip.c radeon_misc.c radeon_probe.c radeon_memory.c \ legacy_crtc.c legacy_output.c \ radeon_textured_video.c \ radeon_crtc.c radeon_output.c radeon_modes.c radeon_tv.c \ $(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_gem.c radeon_dri_bufmgr.c if XMODES radeon_drv_la_SOURCES += \ @@ -159,4 +160,6 @@ EXTRA_DIST = \ radeon_pci_device_match_gen.h \ pcidb/ati_pciids.csv \ pcidb/parse_pci_ids.pl \ - radeon_atombios.h + radeon_atombios.h \ + drmmode_display.h \ + radeon_dri_bufmgr.h diff --git a/src/drmmode_display.c b/src/drmmode_display.c new file mode 100644 index 0000000..3cb2fb9 --- /dev/null +++ b/src/drmmode_display.c @@ -0,0 +1,864 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * + * 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: + * Dave Airlie + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef XF86DRM_MODE +#include "radeon.h" +#include "radeon_reg.h" +#include "radeon_drm.h" +#include "sarea.h" + +/* DPMS */ +#define DPMS_SERVER +#include + +static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height); + +static Bool +drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + Bool ret; + + ErrorF("resize called %d %d\n", width, height); + ret = drmmode_resize_fb(scrn, drmmode, width, height); + scrn->virtualX = width; + scrn->virtualY = height; + return TRUE; +} + +static void +drmmode_ConvertFromKMode(ScrnInfoPtr scrn, + struct drm_mode_modeinfo *kmode, + DisplayModePtr mode) +{ + memset(mode, 0, sizeof(DisplayModeRec)); + mode->status = MODE_OK; + + mode->Clock = kmode->clock; + + mode->HDisplay = kmode->hdisplay; + mode->HSyncStart = kmode->hsync_start; + mode->HSyncEnd = kmode->hsync_end; + mode->HTotal = kmode->htotal; + mode->HSkew = kmode->hskew; + + mode->VDisplay = kmode->vdisplay; + mode->VSyncStart = kmode->vsync_start; + mode->VSyncEnd = kmode->vsync_end; + mode->VTotal = kmode->vtotal; + mode->VScan = kmode->vscan; + + mode->Flags = kmode->flags; //& FLAG_BITS; + mode->name = strdup(kmode->name); + + if (kmode->type & DRM_MODE_TYPE_DRIVER) + mode->type = M_T_DRIVER; + if (kmode->type & DRM_MODE_TYPE_PREFERRED) + mode->type |= M_T_PREFERRED; + xf86SetModeCrtc (mode, scrn->adjustFlags); +} + +static void +drmmode_ConvertToKMode(ScrnInfoPtr scrn, + struct drm_mode_modeinfo *kmode, + DisplayModePtr mode) +{ + memset(kmode, 0, sizeof(*kmode)); + + kmode->clock = mode->Clock; + kmode->hdisplay = mode->HDisplay; + kmode->hsync_start = mode->HSyncStart; + kmode->hsync_end = mode->HSyncEnd; + kmode->htotal = mode->HTotal; + kmode->hskew = mode->HSkew; + + kmode->vdisplay = mode->VDisplay; + kmode->vsync_start = mode->VSyncStart; + kmode->vsync_end = mode->VSyncEnd; + kmode->vtotal = mode->VTotal; + kmode->vscan = mode->VScan; + + kmode->flags = mode->Flags; //& FLAG_BITS; + if (mode->name) + strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN); + kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0; + +} + +static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { + drmmode_xf86crtc_resize +}; + +static void +drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */ + if (mode == DPMSModeOff) { +// drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, +// 0, 0, 0, NULL, 0, NULL); + } +} + +static PixmapPtr +create_pixmap_for_fb(drmmode_ptr drmmode, ScrnInfoPtr pScrn, drmModeFBPtr fb) +{ + ScreenPtr pScreen = pScrn->pScreen; + PixmapPtr pPixmap; + struct radeon_exa_pixmap_priv *driver_priv; + dri_bo *bo; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, fb->depth, 0); + driver_priv = exaGetPixmapDriverPrivate(pPixmap); + if (!driver_priv) { + (*pScreen->DestroyPixmap)(pPixmap); + return NULL; + } + + miModifyPixmapHeader(pPixmap, fb->width, fb->height, fb->depth, + pScrn->bitsPerPixel, fb->pitch, NULL); + + bo = radeon_bo_gem_create_from_handle(drmmode->bufmgr, + fb->handle, + fb->pitch * fb->height); + driver_priv->bo = bo; + if (bo == NULL) { + (*pScreen->DestroyPixmap)(pPixmap); + return NULL; + } + + return pPixmap; +} + +static void +copy_fb_contents (drmmode_ptr drmmode, + ScrnInfoPtr pScrn, + unsigned int dest_id, int x, int y, unsigned int src_id) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + drmModeFBPtr dest_fb, src_fb; + dri_bo *dest_bo, *src_bo; + PixmapPtr src_pixmap, dest_pixmap; + ScreenPtr pScreen = pScrn->pScreen; + + dest_fb = drmModeGetFB(drmmode->fd, dest_id); + src_fb = drmModeGetFB(drmmode->fd, src_id); + if (src_fb == NULL || dest_fb == NULL) { + ErrorF("failed to get old fb, id %d\n", src_id); + return; + } + + dest_pixmap = create_pixmap_for_fb(drmmode, pScrn, dest_fb); + src_pixmap = create_pixmap_for_fb(drmmode, pScrn, src_fb); + + info->accel_state->exa->PrepareCopy (src_pixmap, dest_pixmap, + 0, 0, GXcopy, 0xffffff); + info->accel_state->exa->Copy (dest_pixmap, 0, 0, x, y, + src_fb->width, src_fb->height); + info->accel_state->exa->DoneCopy (dest_pixmap); + RADEONCPFlushIndirect(pScrn, 0); + + (*pScreen->DestroyPixmap)(dest_pixmap); + (*pScreen->DestroyPixmap)(src_pixmap); + + drmFree(dest_fb); + drmFree(src_fb); +} + +static Bool +drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, + Rotation rotation, int x, int y) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int saved_x, saved_y; + Rotation saved_rotation; + DisplayModeRec saved_mode; + uint32_t *output_ids; + int output_count = 0; + Bool ret = TRUE; + int i; + int fb_id; + struct drm_mode_modeinfo kmode; + + saved_mode = crtc->mode; + saved_x = crtc->x; + saved_y = crtc->y; + saved_rotation = crtc->rotation; + + if (mode) { + crtc->mode = *mode; + crtc->x = x; + crtc->y = y; + crtc->rotation = rotation; + } + + output_ids = xcalloc(sizeof(uint32_t), xf86_config->num_output); + if (!output_ids) { + ret = FALSE; + goto done; + } + + if (mode) { + for (i = 0; i < xf86_config->num_output; i++) { + xf86OutputPtr output = xf86_config->output[i]; + drmmode_output_private_ptr drmmode_output; + + if (output->crtc != crtc) + continue; + + drmmode_output = output->driver_private; + output_ids[output_count] = drmmode_output->mode_output->connector_id; + output_count++; + } + + if (!xf86CrtcRotate(crtc, mode, rotation)) { + goto done; + } + + drmmode_ConvertToKMode(crtc->scrn, &kmode, mode); + + fb_id = drmmode->fb_id; + if (drmmode_crtc->rotate_fb_id) { + fb_id = drmmode_crtc->rotate_fb_id; + x = y = 0; + } + else if (fb_id != drmmode_crtc->mode_crtc->buffer_id) + copy_fb_contents (drmmode, crtc->scrn, fb_id, x, y, + drmmode_crtc->mode_crtc->buffer_id); + + drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + fb_id, x, y, output_ids, output_count, &kmode); + + if (crtc->scrn->pScreen) + xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen); + } + + + + +done: + if (!ret) { + crtc->x = saved_x; + crtc->y = saved_y; + crtc->rotation = saved_rotation; + crtc->mode = saved_mode; + } + return ret; +} + +static void +drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg) +{ + +} + +static void +drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); +} + +static void +drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + void *ptr; + + /* cursor should be mapped already */ + ptr = drmmode_crtc->cursor_map; + + memcpy (ptr, image, 64 * 64 * 4); + + return; +} + + +static void +drmmode_hide_cursor (xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64); + +} + +static void +drmmode_show_cursor (xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, drmmode_crtc->cursor_handle, 64, 64); +} + +static void * +drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + int size; + unsigned long rotate_pitch; + dri_bo *rotate_bo; + int ret; + rotate_pitch = crtc->scrn->displayWidth * drmmode->cpp; + size = rotate_pitch * height; + + rotate_bo = dri_bo_alloc(drmmode->bufmgr, "rotate", size, 0, 0); + if (rotate_bo == NULL) + return NULL; + + dri_bo_pin(rotate_bo, RADEON_GEM_DOMAIN_VRAM); + dri_bo_map(rotate_bo, 1); + + ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth, + crtc->scrn->bitsPerPixel, rotate_pitch, dri_bo_get_handle(rotate_bo), + &drmmode_crtc->rotate_fb_id); + if (ret) { + ErrorF("failed to add rotate fb\n"); + } + + drmmode_crtc->rotate_bo = rotate_bo; + return drmmode_crtc->rotate_bo->virtual; +} + +static PixmapPtr +drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height) +{ + ScrnInfoPtr pScrn = crtc->scrn; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + unsigned long rotate_pitch; + PixmapPtr rotate_pixmap; + + if (!data) + data = drmmode_crtc_shadow_allocate (crtc, width, height); + + rotate_pitch = pScrn->displayWidth * drmmode->cpp; + + rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen, + width, height, + pScrn->depth, + pScrn->bitsPerPixel, + rotate_pitch, + data); + + if (rotate_pixmap == NULL) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't allocate shadow pixmap for rotated CRTC\n"); + } + return rotate_pixmap; + +} + +static void +drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *data) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + + if (rotate_pixmap) + FreeScratchPixmapHeader(rotate_pixmap); + + if (data) { + drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id); + drmmode_crtc->rotate_fb_id = 0; + dri_bo_unreference(drmmode_crtc->rotate_bo); + drmmode_crtc->rotate_bo = NULL; + } + +} + +static const xf86CrtcFuncsRec drmmode_crtc_funcs = { + .dpms = drmmode_crtc_dpms, + .set_mode_major = drmmode_set_mode_major, + .set_cursor_colors = drmmode_set_cursor_colors, + .set_cursor_position = drmmode_set_cursor_position, + .show_cursor = drmmode_show_cursor, + .hide_cursor = drmmode_hide_cursor, + .load_cursor_argb = drmmode_load_cursor_argb, + + .shadow_create = drmmode_crtc_shadow_create, + .shadow_allocate = drmmode_crtc_shadow_allocate, + .shadow_destroy = drmmode_crtc_shadow_destroy, +#if 0 + .gamma_set = i830_crtc_gamma_set, +#endif + .destroy = NULL, /* XXX */ +}; + + +static void +drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) +{ + xf86CrtcPtr crtc; + drmmode_crtc_private_ptr drmmode_crtc; + + crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); + if (crtc == NULL) + return; + + drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); + drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]); + drmmode_crtc->drmmode = drmmode; + crtc->driver_private = drmmode_crtc; + + return; +} + +static xf86OutputStatus +drmmode_output_detect(xf86OutputPtr output) +{ + /* go to the hw and retrieve a new output struct */ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmmode_ptr drmmode = drmmode_output->drmmode; + xf86OutputStatus status; + drmModeFreeConnector(drmmode_output->mode_output); + + drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id); + + switch (drmmode_output->mode_output->connection) { + case DRM_MODE_CONNECTED: + status = XF86OutputStatusConnected; + break; + case DRM_MODE_DISCONNECTED: + status = XF86OutputStatusDisconnected; + break; + default: + case DRM_MODE_UNKNOWNCONNECTION: + status = XF86OutputStatusUnknown; + break; + } + return status; +} + +static Bool +drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) +{ + return MODE_OK; +} + +static DisplayModePtr +drmmode_output_get_modes(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + int i; + DisplayModePtr Modes = NULL, Mode; + drmModePropertyPtr props; + + /* look for an EDID property */ + for (i = 0; i < koutput->count_props; i++) { + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (props && (props->flags & DRM_MODE_PROP_BLOB)) { + if (!strcmp(props->name, "EDID")) { + if (drmmode_output->edid_blob) + drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + } + + if (drmmode_output->edid_blob) + xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, drmmode_output->edid_blob->data)); + else + xf86OutputSetEDID(output, xf86InterpretEDID(output->scrn->scrnIndex, NULL)); + + /* modes should already be available */ + for (i = 0; i < koutput->count_modes; i++) { + Mode = xnfalloc(sizeof(DisplayModeRec)); + + drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode); + Modes = xf86ModesAdd(Modes, Mode); + + } + return Modes; +} + +static void +drmmode_output_destroy(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + + if (drmmode_output->edid_blob) + drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmModeFreeConnector(drmmode_output->mode_output); + xfree(drmmode_output); + output->driver_private = NULL; +} + +static void +drmmode_output_dpms(xf86OutputPtr output, int mode) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + drmmode_ptr drmmode = drmmode_output->drmmode; + + drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id, + drmmode_output->dpms_enum_id, mode); + return; +} + +static const xf86OutputFuncsRec drmmode_output_funcs = { + .dpms = drmmode_output_dpms, +#if 0 + + .save = drmmode_crt_save, + .restore = drmmode_crt_restore, + .mode_fixup = drmmode_crt_mode_fixup, + .prepare = drmmode_output_prepare, + .mode_set = drmmode_crt_mode_set, + .commit = drmmode_output_commit, +#endif + .detect = drmmode_output_detect, + .mode_valid = drmmode_output_mode_valid, + + .get_modes = drmmode_output_get_modes, + .destroy = drmmode_output_destroy +}; + +static int subpixel_conv_table[7] = { 0, SubPixelUnknown, + SubPixelHorizontalRGB, + SubPixelHorizontalBGR, + SubPixelVerticalRGB, + SubPixelVerticalBGR, + SubPixelNone }; + +const char *output_names[] = { "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", +}; + + +static void +drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num) +{ + xf86OutputPtr output; + drmModeConnectorPtr koutput; + drmModeEncoderPtr kencoder; + drmmode_output_private_ptr drmmode_output; + drmModePropertyPtr props; + char name[32]; + int i; + + koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]); + if (!koutput) + return; + + kencoder = drmModeGetEncoder(drmmode->fd, koutput->encoders[0]); + if (!kencoder) { + drmModeFreeConnector(koutput); + return; + } + + /* need to do smart conversion here for compat with non-kms ATI driver */ + if (koutput->connector_type_id == 1) { + switch(koutput->connector_type) { + case DRM_MODE_CONNECTOR_VGA: + case DRM_MODE_CONNECTOR_DVII: + case DRM_MODE_CONNECTOR_DVID: + case DRM_MODE_CONNECTOR_DVIA: + case DRM_MODE_CONNECTOR_HDMIA: + case DRM_MODE_CONNECTOR_HDMIB: + snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); + break; + default: + snprintf(name, 32, "%s", output_names[koutput->connector_type]); + break; + } + } else { + snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1); + } + + output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name); + if (!output) { + drmModeFreeEncoder(kencoder); + drmModeFreeConnector(koutput); + return; + } + + drmmode_output = xcalloc(sizeof(drmmode_output_private_rec), 1); + if (!drmmode_output) { + xf86OutputDestroy(output); + drmModeFreeConnector(koutput); + drmModeFreeEncoder(kencoder); + return; + } + + drmmode_output->output_id = drmmode->mode_res->connectors[num]; + drmmode_output->mode_output = koutput; + drmmode_output->mode_encoder = kencoder; + drmmode_output->drmmode = drmmode; + output->mm_width = koutput->mmWidth; + output->mm_height = koutput->mmHeight; + + output->subpixel_order = subpixel_conv_table[koutput->subpixel]; + output->driver_private = drmmode_output; + + output->possible_crtcs = kencoder->possible_crtcs; + output->possible_clones = kencoder->possible_clones; + + for (i = 0; i < koutput->count_props; i++) { + props = drmModeGetProperty(drmmode->fd, koutput->props[i]); + if (props && (props->flags && DRM_MODE_PROP_ENUM)) { + if (!strcmp(props->name, "DPMS")) { + drmmode_output->dpms_enum_id = koutput->props[i]; + drmModeFreeProperty(props); + break; + } + drmModeFreeProperty(props); + } + } + + return; +} + +Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp) +{ + xf86CrtcConfigPtr xf86_config; + int i; + Bool ret; + + /* Create a bus Id */ + /* Low level DRM open */ + ret = DRIOpenDRMMaster(pScrn, SAREA_MAX, busId, driver_name); + if (!ret) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[dri] DRIGetVersion failed to open the DRM\n" + "[dri] Disabling DRI.\n"); + return FALSE; + } + + drmmode->fd = DRIMasterFD(pScrn); + + xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + drmmode->cpp = cpp; + drmmode->mode_res = drmModeGetResources(drmmode->fd); + if (!drmmode->mode_res) + return FALSE; + + xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height); + for (i = 0; i < drmmode->mode_res->count_crtcs; i++) + drmmode_crtc_init(pScrn, drmmode, i); + + for (i = 0; i < drmmode->mode_res->count_connectors; i++) + drmmode_output_init(pScrn, drmmode, i); + + xf86InitialConfiguration(pScrn, FALSE); + + return TRUE; +} + +Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr) +{ + drmmode->bufmgr = bufmgr; + return TRUE; +} + +void drmmode_set_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height, int pitch, uint32_t handle) +{ + int ret; + + ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth, + scrn->bitsPerPixel, pitch, handle, + &drmmode->fb_id); + + if (ret) { + ErrorF("Failed to add fb\n"); + } + + drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id); + if (!drmmode->mode_fb) + return; + + + ErrorF("Add fb id %d %d %d\n", drmmode->fb_id, width, height); +} + +void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); + xf86CrtcPtr crtc = xf86_config->crtc[id]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + + drmmode_crtc->cursor_handle = handle; + drmmode_crtc->cursor_map = ptr; +} + +Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR (pScrn); + int i; + + if (pPixData == NULL) + return FALSE; + + for (i = 0; i < config->num_crtc; i++) { + xf86CrtcPtr crtc = config->crtc[i]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (!drmmode_crtc->rotate_bo) + continue; + + if (drmmode_crtc->rotate_bo->virtual == pPixData) { + *bo = drmmode_crtc->rotate_bo; + return TRUE; + } + } + return FALSE; + +} + +static Bool drmmode_resize_fb(ScrnInfoPtr scrn, drmmode_ptr drmmode, int width, int height) +{ + uint32_t handle; + int pitch; + int ret; + + return FALSE; + + if (drmmode->mode_fb->width == width && drmmode->mode_fb->height == height) + return TRUE; + + if (!drmmode->create_new_fb) + return FALSE; + + handle = drmmode->create_new_fb(scrn, width, height, &pitch); + if (handle == 0) + return FALSE; + + ret = drmModeReplaceFB(drmmode->fd, drmmode->fb_id, + width, height, + scrn->depth, scrn->bitsPerPixel, pitch, + handle); + + if (ret) + return FALSE; + + drmModeFreeFB(drmmode->mode_fb); + drmmode->mode_fb = drmModeGetFB(drmmode->fd, drmmode->fb_id); + if (!drmmode->mode_fb) + return FALSE; + + return TRUE; +} + +void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + xf86OutputPtr output = config->output[config->compat_output]; + xf86CrtcPtr crtc = output->crtc; + + if (crtc && crtc->enabled) { + drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, + x, y); + } +} + +Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + int c, o; + + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + xf86OutputPtr output = NULL; + int o; + + /* Skip disabled CRTCs */ + if (!crtc->enabled) { + drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, + 0, 0, 0, NULL, 0, NULL); + continue; + } + + if (config->output[config->compat_output]->crtc == crtc) + output = config->output[config->compat_output]; + else + { + for (o = 0; o < config->num_output; o++) + if (config->output[o]->crtc == crtc) + { + output = config->output[o]; + break; + } + } + /* paranoia */ + if (!output) + continue; + + /* Mark that we'll need to re-set the mode for sure */ + memset(&crtc->mode, 0, sizeof(crtc->mode)); + if (!crtc->desiredMode.CrtcHDisplay) + { + DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); + + if (!mode) + return FALSE; + crtc->desiredMode = *mode; + crtc->desiredRotation = RR_Rotate_0; + crtc->desiredX = 0; + crtc->desiredY = 0; + } + + if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation, + crtc->desiredX, crtc->desiredY)) + return FALSE; + } + return TRUE; +} +#endif diff --git a/src/drmmode_display.h b/src/drmmode_display.h new file mode 100644 index 0000000..dbb6412 --- /dev/null +++ b/src/drmmode_display.h @@ -0,0 +1,76 @@ +/* + * Copyright © 2007 Red Hat, Inc. + * + * 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: + * Dave Airlie + * + */ +#ifndef DRMMODE_DISPLAY_H +#define DRMMODE_DISPLAY_H + +#ifdef XF86DRM_MODE + +#include "xf86drmMode.h" + +#include "radeon_probe.h" +#include "radeon_bufmgr.h" + +typedef struct { + int fd; + int fb_id; + drmModeResPtr mode_res; + drmModeFBPtr mode_fb; + int cpp; + dri_bufmgr *bufmgr; + + uint32_t (*create_new_fb)(ScrnInfoPtr pScrn, int width, int height, int *pitch); +} drmmode_rec, *drmmode_ptr; + +typedef struct { + + drmmode_ptr drmmode; + drmModeCrtcPtr mode_crtc; + uint32_t cursor_handle; + void *cursor_map; + dri_bo *rotate_bo; + int rotate_fb_id; +} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; + +typedef struct { + drmmode_ptr drmmode; + int output_id; + drmModeConnectorPtr mode_output; + drmModeEncoderPtr mode_encoder; + drmModePropertyBlobPtr edid_blob; + int dpms_enum_id; +} drmmode_output_private_rec, *drmmode_output_private_ptr; + + +extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, char *busId, char *driver_name, int cpp); +extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, dri_bufmgr *bufmgr); +extern void drmmode_set_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int width, int height, int pitch, uint32_t handle); +extern Bool drmmode_is_rotate_pixmap(ScrnInfoPtr pScrn, pointer pPixData, dri_bo **bo); +extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, void *ptr, uint32_t handle); +void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags); +extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode); +#endif +#endif diff --git a/src/radeon.h b/src/radeon.h index f7ae1a8..a437b55 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -46,6 +46,8 @@ #include "compiler.h" #include "xf86fbman.h" +#include "drmmode_display.h" + /* PCI support */ #include "xf86Pci.h" @@ -85,6 +87,7 @@ #include "xf86Crtc.h" #include "X11/Xatom.h" +#include "radeon_bufmgr.h" /* Render support */ #ifdef RENDER #include "picturestr.h" @@ -404,6 +407,14 @@ typedef enum { typedef struct _atomBiosHandle *atomBiosHandlePtr; +#define RADEON_POOL_GART 0 +#define RADEON_POOL_VRAM 1 + +struct radeon_exa_pixmap_priv { + dri_bo *bo; + int flags; +}; + typedef struct { uint32_t pci_device_id; RADEONChipFamily chip_family; @@ -414,7 +425,27 @@ typedef struct { int singledac; } RADEONCardInfo; +#define RADEON_2D_EXA_COPY 1 +#define RADEON_2D_EXA_SOLID 2 + +struct radeon_2d_state { + int op; // + uint32_t dst_pitch_offset; + uint32_t src_pitch_offset; + uint32_t dp_gui_master_cntl; + uint32_t dp_cntl; + uint32_t dp_write_mask; + uint32_t dp_brush_frgd_clr; + uint32_t dp_brush_bkgd_clr; + uint32_t dp_src_frgd_clr; + uint32_t dp_src_bkgd_clr; + uint32_t default_sc_bottom_right; + dri_bo *dst_bo; + dri_bo *src_bo; +}; + #ifdef XF86DRI + struct radeon_cp { Bool CPRuns; /* CP is running */ Bool CPInUse; /* CP has been used by X server */ @@ -428,6 +459,10 @@ struct radeon_cp { drmBufPtr indirectBuffer; int indirectStart; + drmBuf ib_gem_fake; + void *ib_ptr; + + struct radeon_relocs_info relocs; /* Debugging info for BEGIN_RING/ADVANCE_RING pairs. */ int dma_begin_count; char *dma_debug_func; @@ -494,13 +529,13 @@ struct radeon_dri { drm_handle_t ringHandle; /* Handle from drmAddMap */ drmSize ringMapSize; /* Size of map */ int ringSize; /* Size of ring (in MB) */ - drmAddress ring; /* Map */ + // drmAddress ring; /* Map */ int ringSizeLog2QW; unsigned long ringReadOffset; /* Offset into GART space */ drm_handle_t ringReadPtrHandle; /* Handle from drmAddMap */ drmSize ringReadMapSize; /* Size of map */ - drmAddress ringReadPtr; /* Map */ + // drmAddress ringReadPtr; /* Map */ /* CP vertex/indirect buffer data */ unsigned long bufStart; /* Offset into GART space */ @@ -519,7 +554,6 @@ struct radeon_dri { drmAddress gartTex; /* Map */ int log2GARTTexGran; - /* DRI screen private data */ int fbX; int fbY; int backX; @@ -836,6 +870,44 @@ typedef struct { Bool r600_shadow_fb; void *fb_shadow; + Bool new_cs; // new command submission routine + struct radeon_2d_state state_2d; + void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB + Bool cs_used_depth; + Bool drm_mm; // the drm memory manager exists and is initialised + struct { + uint64_t vram_start; + uint64_t vram_size; + uint64_t gart_start; + uint64_t gart_size; + + struct radeon_memory *bo_list[2]; + struct radeon_memory *front_buffer; + struct radeon_memory *back_buffer; + struct radeon_memory *depth_buffer; + +#if 0 + struct radeon_memory *exa_buffer; +#endif + struct radeon_memory *texture_buffer; + + struct radeon_memory *dma_buffer; + struct radeon_memory *gart_texture_buffer; + struct radeon_memory *rotate_buffer; + struct radeon_memory *cursor[2]; + + /* indirect buffer for accel */ + struct radeon_memory *gem_ib_memory; + + } mm; + + drm_handle_t fb_map_handle; + Bool drm_mode_setting; +#ifdef XF86DRM_MODE + drmmode_rec drmmode; +#endif + + dri_bufmgr *bufmgr; } RADEONInfoRec, *RADEONInfoPtr; #define RADEONWaitForFifo(pScrn, entries) \ @@ -1078,6 +1150,23 @@ extern void radeon_legacy_free_memory(ScrnInfoPtr pScrn, void *mem_struct); +/* 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, + int need_bind); +uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch); +int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +Bool radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem); +Bool radeon_free_all_memory(ScrnInfoPtr pScrn); +Bool radeon_setup_kernel_mem(ScreenPtr pScreen); +Bool RADEONDRIDoMappings(ScreenPtr pScreen); +Bool radeon_update_dri_buffers(ScreenPtr pScreen); +Bool radeon_setup_gart_mem(ScreenPtr pScreen); + #ifdef XF86DRI # ifdef USE_XAA /* radeon_accelfuncs.c */ @@ -1096,7 +1185,9 @@ do { \ #define RADEONCP_RELEASE(pScrn, info) \ do { \ - if (info->cp->CPInUse) { \ + if (info->new_cs) { \ + RADEONCPReleaseIndirect(pScrn); \ + } else if (info->cp->CPInUse) { \ RADEON_PURGE_CACHE(); \ RADEON_WAIT_UNTIL_IDLE(); \ RADEONCPReleaseIndirect(pScrn); \ @@ -1130,7 +1221,7 @@ do { \ #define RADEONCP_REFRESH(pScrn, info) \ do { \ - if (!info->cp->CPInUse) { \ + if (!info->cp->CPInUse && !info->new_cs) { \ if (info->cp->needCacheFlush) { \ RADEON_PURGE_CACHE(); \ RADEON_PURGE_ZCACHE(); \ @@ -1157,6 +1248,13 @@ do { \ #define RING_LOCALS uint32_t *__head = NULL; int __expected; int __count = 0 #define BEGIN_RING(n) do { \ + if (!info->cp->indirectBuffer) { \ + info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn); \ + info->cp->indirectStart = 0; \ + } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) > \ + info->cp->indirectBuffer->total) { \ + RADEONCPFlushIndirect(pScrn, 1); \ + } \ if (RADEON_VERBOSE) { \ xf86DrvMsg(pScrn->scrnIndex, X_INFO, \ "BEGIN_RING(%d) in %s\n", (unsigned int)n, __FUNCTION__);\ @@ -1169,13 +1267,6 @@ do { \ } \ info->cp->dma_debug_func = __FILE__; \ info->cp->dma_debug_lineno = __LINE__; \ - if (!info->cp->indirectBuffer) { \ - info->cp->indirectBuffer = RADEONCPGetBuffer(pScrn); \ - info->cp->indirectStart = 0; \ - } else if (info->cp->indirectBuffer->used + (n) * (int)sizeof(uint32_t) > \ - info->cp->indirectBuffer->total) { \ - RADEONCPFlushIndirect(pScrn, 1); \ - } \ __expected = n; \ __head = (pointer)((char *)info->cp->indirectBuffer->address + \ info->cp->indirectBuffer->used); \ @@ -1218,6 +1309,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, read_domains, write_domains) \ + do { \ + radeon_bufmgr_emit_reloc(x, &info->cp->relocs, __head, &__count, read_domains, write_domains); \ + } while(0) + + #define FLUSH_RING() \ do { \ if (RADEON_VERBOSE) \ diff --git a/src/radeon_accel.c b/src/radeon_accel.c index a6e332d..d40da24 100644 --- a/src/radeon_accel.c +++ b/src/radeon_accel.c @@ -311,6 +311,9 @@ void RADEONEngineRestore(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR(pScrn); unsigned char *RADEONMMIO = info->MMIO; + if (info->drm_mode_setting) + return; + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "EngineRestore (%d/%d)\n", info->CurrentLayout.pixel_code, @@ -370,8 +373,8 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) info->CurrentLayout.bitsPerPixel); #ifdef XF86DRI - if (info->directRenderingEnabled && (IS_R300_3D || IS_R500_3D)) { - drm_radeon_getparam_t np; + if ((info->directRenderingEnabled || info->drm_mode_setting) && (IS_R300_3D || IS_R500_3D)) { + drm_radeon_getparam_t np; int num_pipes; memset(&np, 0, sizeof(np)); @@ -390,59 +393,62 @@ void RADEONEngineInit(ScrnInfoPtr pScrn) } #endif - if ((info->ChipFamily == CHIP_FAMILY_RV410) || - (info->ChipFamily == CHIP_FAMILY_R420) || - (info->ChipFamily == CHIP_FAMILY_RS600) || - (info->ChipFamily == CHIP_FAMILY_RS690) || - (info->ChipFamily == CHIP_FAMILY_RS740) || - (info->ChipFamily == CHIP_FAMILY_RS400) || - (info->ChipFamily == CHIP_FAMILY_RS480) || - IS_R500_3D) { - if (info->accel_state->num_gb_pipes == 0) { - uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT); - - info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; - if (IS_R500_3D) - OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); - } - } else { - if (info->accel_state->num_gb_pipes == 0) { - if ((info->ChipFamily == CHIP_FAMILY_R300) || - (info->ChipFamily == CHIP_FAMILY_R350)) { - /* R3xx chips */ - info->accel_state->num_gb_pipes = 2; - } else { - /* RV3xx chips */ - info->accel_state->num_gb_pipes = 1; + if (!info->drm_mode_setting) { + if ((info->ChipFamily == CHIP_FAMILY_RV410) || + (info->ChipFamily == CHIP_FAMILY_R420) || + (info->ChipFamily == CHIP_FAMILY_RS600) || + (info->ChipFamily == CHIP_FAMILY_RS690) || + (info->ChipFamily == CHIP_FAMILY_RS740) || + (info->ChipFamily == CHIP_FAMILY_RS400) || + (info->ChipFamily == CHIP_FAMILY_RS480) || + IS_R500_3D) { + if (info->accel_state->num_gb_pipes == 0) { + uint32_t gb_pipe_sel = INREG(R400_GB_PIPE_SELECT); + + info->accel_state->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; + if (IS_R500_3D) + OUTPLL(pScrn, R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); + } + } else { + if (info->accel_state->num_gb_pipes == 0) { + if ((info->ChipFamily == CHIP_FAMILY_R300) || + (info->ChipFamily == CHIP_FAMILY_R350)) { + /* R3xx chips */ + info->accel_state->num_gb_pipes = 2; + } else { + /* RV3xx chips */ + info->accel_state->num_gb_pipes = 1; + } } - } - } - - if (IS_R300_3D || IS_R500_3D) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "num quad-pipes is %d\n", info->accel_state->num_gb_pipes); - - if (IS_R300_3D || IS_R500_3D) { - uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); - - switch(info->accel_state->num_gb_pipes) { - case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; - case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; - case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; - default: - case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; } - OUTREG(R300_GB_TILE_CONFIG, gb_tile_config); - OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); - OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) | - R300_DC_AUTOFLUSH_ENABLE | - R300_DC_DC_DISABLE_IGNORE_PE)); - } else - OUTREG(RADEON_RB3D_CNTL, 0); + if (IS_R300_3D || IS_R500_3D) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "num quad-pipes is %d\n", info->accel_state->num_gb_pipes); + + if (IS_R300_3D || IS_R500_3D) { + uint32_t gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); + + switch(info->accel_state->num_gb_pipes) { + case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; + case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; + case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; + default: + case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; + } - RADEONEngineReset(pScrn); + OUTREG(R300_GB_TILE_CONFIG, gb_tile_config); + OUTREG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); + if (info->ChipFamily >= CHIP_FAMILY_R420) + OUTREG(R300_DST_PIPE_CONFIG, INREG(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); + OUTREG(R300_RB2D_DSTCACHE_MODE, (INREG(R300_RB2D_DSTCACHE_MODE) | + R300_DC_AUTOFLUSH_ENABLE | + R300_DC_DC_DISABLE_IGNORE_PE)); + } else + OUTREG(RADEON_RB3D_CNTL, 0); + + RADEONEngineReset(pScrn); + } switch (info->CurrentLayout.pixel_code) { case 8: datatype = 2; break; @@ -550,6 +556,153 @@ int RADEONCPStop(ScrnInfoPtr pScrn, RADEONInfoPtr info) } } +#define RADEON_IB_RESERVE (16 * sizeof(uint32_t)) +drmBufPtr RADEONCSGetBuffer(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->cp->relocs.size = getpagesize(); + info->cp->relocs.num_reloc = 0; + info->cp->relocs.buf = xcalloc(1, info->cp->relocs.size); + if (!info->cp->relocs.buf) + return NULL; + info->cp->ib_gem_fake.address = xcalloc(1, RADEON_BUFFER_SIZE); + if (!info->cp->ib_gem_fake.address) { + xfree(info->cp->relocs.buf); + return NULL; + } + + + info->cp->ib_gem_fake.used = 0; + info->cp->ib_gem_fake.total = RADEON_BUFFER_SIZE - RADEON_IB_RESERVE; // reserve 16 dwords + return &info->cp->ib_gem_fake; +} + +#ifdef DRM_RADEON_CS2 +void RADEONCSFlushIndirect(ScrnInfoPtr pScrn, int discard) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_cs2 args; + struct drm_radeon_cs_chunk chunk[2]; + uint64_t chunk_array[2]; + int retry = 0; + int ret; + RING_LOCALS; + + if (info->cp->indirectBuffer->used == 0) + return; + + /* always add the cache flushes to the end of the IB */ + info->cp->indirectBuffer->total += RADEON_IB_RESERVE; + + /* end of IB purge caches */ + if (info->cs_used_depth) { + RADEON_PURGE_ZCACHE(); + info->cs_used_depth = 0; + } + + chunk[0].chunk_data = (unsigned long)info->cp->ib_gem_fake.address; + chunk[0].length_dw = info->cp->indirectBuffer->used / sizeof(uint32_t); + chunk[0].chunk_id = RADEON_CHUNK_ID_IB; + + chunk[1].chunk_data = (unsigned long)info->cp->relocs.buf; + chunk[1].length_dw = info->cp->relocs.num_reloc * RADEON_RELOC_SIZE; + chunk[1].chunk_id = RADEON_CHUNK_ID_RELOCS; + + chunk_array[0] = (uint64_t)(unsigned long)&chunk[0]; + chunk_array[1] = (uint64_t)(unsigned long)&chunk[1]; + + args.num_chunks = 2; + args.chunks = (uint64_t)(unsigned long)chunk_array; + + do { + ret = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_CS2, + &args, sizeof(args)); + if (ret) + ErrorF("DRM Command submission failure %d\n", ret); + retry++; + } while (ret == -EAGAIN && retry < 1000); + if (ret) { + FatalError("DRM Command submission failure %d\n", ret); + return; + } + + + info->cp->indirectStart = 0; + info->cp->indirectBuffer->used = 0; + info->cp->indirectBuffer->total -= RADEON_IB_RESERVE; + + if (info->bufmgr) + radeon_gem_bufmgr_post_submit(info->bufmgr, &info->cp->relocs); + + info->cp->relocs.num_reloc = 0; + /* 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 */ + if (info->reemit_current2d) + info->reemit_current2d(pScrn, 0); +} +#else +void RADEONCSFlushIndirect(ScrnInfoPtr pScrn, int discard) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_cs args; + int ret; + RING_LOCALS; + + /* always add the cache flushes to the end of the IB */ + info->cp->indirectBuffer->total += RADEON_IB_RESERVE; + + /* end of IB purge caches */ + if (info->cs_used_depth) { + RADEON_PURGE_ZCACHE(); + info->cs_used_depth = 0; + } + + RADEON_PURGE_CACHE(); + RADEON_WAIT_UNTIL_IDLE(); + + args.packets = (unsigned long)info->cp->ib_gem_fake.address; + args.dwords = info->cp->indirectBuffer->used / sizeof(uint32_t); + + ret = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_CS, + &args, sizeof(args)); + + if (ret) { + FatalError("DRM Command submission failure %d\n", ret); + return; + } + + + info->cp->indirectStart = 0; + info->cp->indirectBuffer->used = 0; + info->cp->indirectBuffer->total -= RADEON_IB_RESERVE; + + if (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 */ + if (info->reemit_current2d) + info->reemit_current2d(pScrn, 0); +} +#endif + +void RADEONCSReleaseIndirect(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (!info->cp->indirectBuffer) return; + RADEONCSFlushIndirect(pScrn, 0); + xfree(info->cp->relocs.buf); + info->cp->relocs.buf = 0; + info->cp->relocs.size = 0; + info->cp->relocs.num_reloc = 0; + xfree(info->cp->ib_gem_fake.address); + info->cp->ib_gem_fake.address = NULL; + info->cp->indirectBuffer = NULL; + +} + /* Get an indirect buffer for the CP 2D acceleration commands */ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) { @@ -560,6 +713,9 @@ drmBufPtr RADEONCPGetBuffer(ScrnInfoPtr pScrn) int size = 0; int i = 0; int ret; + + if (info->new_cs) + return RADEONCSGetBuffer(pScrn); #if 0 /* FIXME: pScrn->pScreen has not been initialized when this is first @@ -625,6 +781,11 @@ void RADEONCPFlushIndirect(ScrnInfoPtr pScrn, int discard) if (!buffer) return; if (start == buffer->used && !discard) return; + if (info->new_cs) { + RADEONCSFlushIndirect(pScrn, discard); + return; + } + if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Flushing buffer %d\n", buffer->idx); @@ -659,10 +820,16 @@ void RADEONCPReleaseIndirect(ScrnInfoPtr pScrn) int start = info->cp->indirectStart; drm_radeon_indirect_t indirect; + if (info->new_cs) { + RADEONCSReleaseIndirect(pScrn); + return; + } + info->cp->indirectBuffer = NULL; info->cp->indirectStart = 0; if (!buffer) return; + if (RADEON_VERBOSE) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Releasing buffer %d\n", @@ -789,6 +956,7 @@ RADEONHostDataBlit( ret = ( uint8_t* )&__head[__count]; __count += dwords; + ADVANCE_RING(); *y += *hpass; @@ -926,7 +1094,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen) #ifdef USE_EXA if (info->useEXA) { # ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled || info->drm_mode_setting) { if (!RADEONDrawInitCP(pScreen)) return FALSE; } else @@ -947,7 +1115,7 @@ Bool RADEONAccelInit(ScreenPtr pScreen) } #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingEnabled || info->drm_mode_setting) RADEONAccelInitCP(pScreen, a); else #endif /* XF86DRI */ @@ -969,11 +1137,13 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn) RADEONInfoPtr info = RADEONPTR (pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { - drm_radeon_sarea_t *pSAREAPriv; + if (info->directRenderingEnabled || info->drm_mode_setting) { + if (info->directRenderingEnabled) { + drm_radeon_sarea_t *pSAREAPriv; - pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); - pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen); + pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen); + pSAREAPriv->ctx_owner = DRIGetContext(pScrn->pScreen); + } RADEONInit3DEngineCP(pScrn); } else #endif @@ -981,7 +1151,7 @@ void RADEONInit3DEngine(ScrnInfoPtr pScrn) info->accel_state->XInited3D = TRUE; } - + #ifdef USE_XAA #ifdef XF86DRI Bool diff --git a/src/radeon_bufmgr.h b/src/radeon_bufmgr.h new file mode 100644 index 0000000..481c5cf --- /dev/null +++ b/src/radeon_bufmgr.h @@ -0,0 +1,25 @@ +/** + * @file intel_bufmgr.h + * + * Public definitions of Intel-specific bufmgr functions. + */ + +#ifndef RADEON_BUFMGR_H +#define RADEON_BUFMGR_H + +#include "radeon_dri_bufmgr.h" + +struct radeon_bufmgr { + void (*emit_reloc)(dri_bo *buf, struct radeon_relocs_info *relocs, 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); +dri_bo *radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr, + uint32_t handle, unsigned long size); + +void radeon_bufmgr_emit_reloc(dri_bo *buf, struct radeon_relocs_info *relocs, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); + +void radeon_bufmgr_post_submit(dri_bufmgr *bufmgr); +#endif diff --git a/src/radeon_bufmgr_gem.c b/src/radeon_bufmgr_gem.c new file mode 100644 index 0000000..92fbaa8 --- /dev/null +++ b/src/radeon_bufmgr_gem.c @@ -0,0 +1,600 @@ +/************************************************************************** + * + * 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 "string.h" + +#include "radeon_reg.h" +#include "radeon_probe.h" +#include "radeon.h" +#include "radeon_bufmgr.h" +#include "radeon_drm.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; + int in_vram; /* have we migrated this bo to VRAM ever */ + int force_gtt; + int pinned; + int touched; + uint32_t space_accounted; +} dri_bo_gem; + +typedef struct _dri_bufmgr_gem { + dri_bufmgr bufmgr; + struct radeon_bufmgr radeon_bufmgr; + int fd; + uint32_t vram_limit, gart_limit; + uint32_t vram_write_used, gart_write_used; + uint32_t read_used; + + struct _dri_bo_gem *bo_list; +} dri_bufmgr_gem; + +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; + struct drm_radeon_gem_create args; + int ret; + unsigned int page_size = getpagesize(); + dri_bo_gem *gem_bo; + + gem_bo = calloc(1, sizeof(*gem_bo)); + if (!gem_bo) + return NULL; + + gem_bo->bo.size = size; + args.size = 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 = strdup(name); + gem_bo->touched = 0; + + gem_bo->next = bufmgr_gem->bo_list; + bufmgr_gem->bo_list = gem_bo; + + DBG("bo_create: buf %d (%s) %ldb\n", + gem_bo->gem_handle, gem_bo->name, size); + + 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, *trav, *prev; + 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); + + if (gem_bo == bufmgr_gem->bo_list) + bufmgr_gem->bo_list = gem_bo->next; + else { + prev = trav = bufmgr_gem->bo_list; + while (trav) { + if (trav == gem_bo) { + if (prev) + prev->next = trav->next; + break; + } + prev = trav; + trav = trav->next; + } + } + free(gem_bo->name); + 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) { + 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(bufmgr); +} + +void radeon_bufmgr_gem_wait_rendering(dri_bo *buf) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)buf->bufmgr; + struct drm_radeon_gem_wait_rendering args; + struct drm_radeon_gem_set_domain sd_args; + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + int ret; + + /* do a set domain */ + if (gem_bo->force_gtt) { + sd_args.handle = gem_bo->gem_handle; + sd_args.read_domains = RADEON_GEM_DOMAIN_GTT; + sd_args.write_domain = 0; + + ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_SET_DOMAIN, + &sd_args, sizeof(sd_args)); + + } else { + args.handle = gem_bo->gem_handle; + + do { + ret = drmCommandWriteRead(bufmgr_gem->fd, DRM_RADEON_GEM_WAIT_RENDERING, + &args, sizeof(args)); + } while (ret == -EAGAIN); + } + return; +} + +dri_bo * +radeon_bo_gem_create_from_handle(dri_bufmgr *bufmgr, + uint32_t handle, unsigned long size) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + dri_bo_gem *bo_gem; + char name[32]; + + sprintf(name, "handle:%8x", handle); + bo_gem = calloc(1, sizeof(*bo_gem)); + if (!bo_gem) + return NULL; + + bo_gem->bo.size = size; + bo_gem->bo.offset = 0; + bo_gem->bo.virtual = NULL; + bo_gem->bo.bufmgr = bufmgr; + bo_gem->name = strdup(name); + bo_gem->refcount = 1; + bo_gem->pinned = 1; + bo_gem->gem_handle = handle; + + bo_gem->next = bufmgr_gem->bo_list; + bufmgr_gem->bo_list = bo_gem; + return &bo_gem->bo; +} + +/** + * 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; + int ret; + struct drm_gem_open open_arg; + + 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)); + return NULL; + } + + return radeon_bo_gem_create_from_handle(bufmgr, + open_arg.handle, open_arg.size); +} + +#define BUF_OUT_RING(x) do { \ + __head[__count++] = (x); \ + } while (0) + +void radeon_bufmgr_gem_emit_reloc(dri_bo *buf, struct radeon_relocs_info *reloc_info, 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; + int i; + int index; + int have_reloc = -1; + + for (i = 0; i < reloc_info->num_reloc; i++) { + if (reloc_info->buf[i * 4] == gem_bo->gem_handle) { + have_reloc = i; + break; + } + } + + if (gem_bo->force_gtt && (read_domains & RADEON_GEM_DOMAIN_VRAM)) + read_domains = RADEON_GEM_DOMAIN_GTT; + + if (have_reloc != -1) { + uint32_t old_write, old_read; + + index = have_reloc * 4; + old_read = reloc_info->buf[index + 1]; + old_write = reloc_info->buf[index + 2]; + + /* error up for now - work out new domains - if we have a write */ + if (write_domain && (old_read & write_domain)) { + reloc_info->buf[index + 1] = 0; + reloc_info->buf[index + 2] = write_domain; + } else if (read_domains & old_write) { + reloc_info->buf[index + 1] = 0; + } else { + /* rewrite the domains */ + if (write_domain != old_write) + ErrorF("WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, write_domain, old_write); + if (read_domains != old_read) + ErrorF("READ DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, read_domains, old_read); + } + reloc_info->buf[index + 3]++; + + } else { + + if ((reloc_info->num_reloc + 1) * RADEON_RELOC_SIZE > reloc_info->size) { + /* resize the buffer */ + reloc_info->size += getpagesize(); + reloc_info->buf = xrealloc(reloc_info->buf, reloc_info->size); + if (!reloc_info->buf) + FatalError("failed to increase reloc buffer size\n"); + } + + dri_bo_reference(buf); + gem_bo->touched = 1; + + index = reloc_info->num_reloc * 4; + reloc_info->buf[index] = gem_bo->gem_handle; + reloc_info->buf[index + 1] = read_domains; + reloc_info->buf[index + 2] = write_domain; + reloc_info->buf[index + 3] = 1; + reloc_info->num_reloc++; + } + + 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; + } + + BUF_OUT_RING(CP_PACKET3(RADEON_CP_PACKET3_NOP, 0)); + BUF_OUT_RING(index); + *count_p = __count; +} + +static int radeon_gem_bufmgr_pin(dri_bo *bo, int domain) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + struct drm_radeon_gem_pin pin; + int ret; + + pin.pin_domain = domain; + pin.handle = gem_bo->gem_handle; + pin.alignment = 0; + + ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_RADEON_GEM_PIN, &pin); + if (ret != 0) + return -1; + + gem_bo->pinned = 1; + return 0; +} + +static void radeon_gem_bufmgr_unpin(dri_bo *bo) +{ + + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bo->bufmgr; + dri_bo_gem *gem_bo = (dri_bo_gem *)bo; + struct drm_radeon_gem_unpin unpin; + + unpin.handle = gem_bo->gem_handle; + ioctl(bufmgr_gem->fd, DRM_IOCTL_RADEON_GEM_UNPIN, &unpin); + gem_bo->pinned = 0; +} + + +static uint32_t radeon_gem_bufmgr_get_handle(dri_bo *buf) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + return gem_bo->gem_handle; +} + +static int radeon_gem_bufmgr_check_aperture_space(dri_bo *buf, 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; + int old_accounted = 0; + + if (gem_bo->pinned) + return 0; + + if (write_domain && (write_domain == gem_bo->space_accounted)) + return 0; + + if (read_domains && ((read_domains << 16) == gem_bo->space_accounted)) + return 0; + + old_accounted = gem_bo->space_accounted; + + if (gem_bo->space_accounted == 0) { + gem_bo->space_accounted = (read_domains << 16) | write_domain; + if (write_domain == RADEON_GEM_DOMAIN_VRAM) { + bufmgr_gem->vram_write_used += buf->size; + } else { + bufmgr_gem->read_used += buf->size; + } + } else { + uint16_t old_read, old_write; + + old_read = gem_bo->space_accounted >> 16; + old_write = gem_bo->space_accounted & 0xffff; + + if (write_domain && (old_read & write_domain)) { + gem_bo->space_accounted = write_domain; + /* moving from read to a write domain */ + if (write_domain == RADEON_GEM_DOMAIN_VRAM) { + bufmgr_gem->read_used -= buf->size; + bufmgr_gem->vram_write_used += buf->size; + } + } else if (read_domains & old_write) { + gem_bo->space_accounted &= 0xffff; + } else { + /* rewrite the domains */ + if (write_domain != old_write) + ErrorF("WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, write_domain, old_write); + if (read_domains != old_read) + ErrorF("READ DOMAIN RELOC FAILURE 0x%x %d %d\n", gem_bo->gem_handle, read_domains, old_read); + } + } + + if (bufmgr_gem->vram_write_used > bufmgr_gem->vram_limit) { + bufmgr_gem->vram_write_used = 0; + bufmgr_gem->read_used = 0; + gem_bo->space_accounted = old_accounted; + return -1; + } + + if (bufmgr_gem->read_used > bufmgr_gem->gart_limit) { + bufmgr_gem->vram_write_used = 0; + bufmgr_gem->read_used = 0; + gem_bo->space_accounted = old_accounted; + return -1; + } + + return 0; +} + +/** + * 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.pin = radeon_gem_bufmgr_pin; + bufmgr_gem->bufmgr.unpin = radeon_gem_bufmgr_unpin; + //bufmgr_gem->bufmgr.bo_wait_rendering = radeon_bufmgr_gem_wait_rendering; + bufmgr_gem->radeon_bufmgr.emit_reloc = radeon_bufmgr_gem_emit_reloc; + bufmgr_gem->bufmgr.get_handle = radeon_gem_bufmgr_get_handle; + bufmgr_gem->bufmgr.check_aperture_space = radeon_gem_bufmgr_check_aperture_space; + bufmgr_gem->bufmgr.debug = 0; + return &bufmgr_gem->bufmgr; +} + + +void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr, struct radeon_relocs_info *reloc_info) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + struct _dri_bo_gem *trav, *prev; + int i; + + if (!bufmgr_gem->bo_list) + return; + + for (i = 0; i < reloc_info->num_reloc; i++) { + trav = bufmgr_gem->bo_list; + while (trav) { + prev = trav; + trav = trav->next; + + if (prev->gem_handle == reloc_info->buf[i * 4]) { + prev->space_accounted = 0; + dri_bo_unreference(&prev->bo); + } + } + } + + bufmgr_gem->read_used = 0; + bufmgr_gem->vram_write_used = 0; + +} + + + +void radeon_bufmgr_emit_reloc(dri_bo *buf, struct radeon_relocs_info *relocs, 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, relocs, head, count_p, read_domains, write_domain); +} + +/* if the buffer is references by the current IB we need to flush the IB */ +int radeon_bufmgr_gem_has_references(dri_bo *buf) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + return gem_bo->touched; +} + +void radeon_bufmgr_gem_set_limit(dri_bufmgr *bufmgr, uint32_t domain, uint32_t limit) +{ + dri_bufmgr_gem *bufmgr_gem = (dri_bufmgr_gem *)bufmgr; + + if (domain == RADEON_GEM_DOMAIN_VRAM) + bufmgr_gem->vram_limit = limit; + else + bufmgr_gem->gart_limit = limit; + +} + +void radeon_bufmgr_gem_force_gtt(dri_bo *buf) +{ + dri_bo_gem *gem_bo = (dri_bo_gem *)buf; + + gem_bo->force_gtt = 1; +} diff --git a/src/radeon_bufmgr_gem.h b/src/radeon_bufmgr_gem.h new file mode 100644 index 0000000..b13a642 --- /dev/null +++ b/src/radeon_bufmgr_gem.h @@ -0,0 +1,18 @@ +#ifndef RADEON_BUFMGR_GEM_H +#define RADEON_BUFMGR_GEM_H + +#include "radeon_dri_bufmgr.h" + +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, struct radeon_relocs_info *reloc_info, uint32_t *head, uint32_t *count_p, uint32_t read_domains, uint32_t write_domain); +void radeon_gem_bufmgr_post_submit(dri_bufmgr *bufmgr, struct radeon_relocs_info *reloc_info); +void radeon_bufmgr_pin(dri_bo *buf); +void radeon_bufmgr_unpin(dri_bo *buf); +uint32_t radeon_bufmgr_get_handle(dri_bo *buf); +int radeon_bufmgr_gem_has_references(dri_bo *buf); +int radeon_bufmgr_gem_force_gtt(dri_bo *buf); +void radeon_bufmgr_gem_set_limit(dri_bufmgr *bufmgr, uint32_t domain, uint32_t limit); + + +#endif diff --git a/src/radeon_commonfuncs.c b/src/radeon_commonfuncs.c index dba197e..10d146e 100644 --- a/src/radeon_commonfuncs.c +++ b/src/radeon_commonfuncs.c @@ -62,12 +62,15 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) info->accel_state->texW[1] = info->accel_state->texH[1] = 1; if (IS_R300_3D || IS_R500_3D) { + int size; - BEGIN_ACCEL(3); - OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D); - OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE); - OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - FINISH_ACCEL(); + if (!info->new_cs) { + BEGIN_ACCEL(3); + OUT_ACCEL_REG(R300_RB3D_DSTCACHE_CTLSTAT, R300_DC_FLUSH_3D | R300_DC_FREE_3D); + OUT_ACCEL_REG(R300_RB3D_ZCACHE_CTLSTAT, R300_ZC_FLUSH | R300_ZC_FREE); + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); + FINISH_ACCEL(); + } gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 | R300_SUBPIXEL_1_16); @@ -79,10 +82,12 @@ static void FUNC_NAME(RADEONInit3DEngine)(ScrnInfoPtr pScrn) case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; } - BEGIN_ACCEL(5); + size = (info->ChipFamily >= CHIP_FAMILY_R420) ? 5 : 4; + BEGIN_ACCEL(size); OUT_ACCEL_REG(R300_GB_TILE_CONFIG, gb_tile_config); OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); - OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG); + if (info->ChipFamily >= CHIP_FAMILY_R420) + OUT_ACCEL_REG(R300_DST_PIPE_CONFIG, R300_PIPE_AUTO_CONFIG); OUT_ACCEL_REG(R300_GB_SELECT, 0); OUT_ACCEL_REG(R300_GB_ENABLE, 0); FINISH_ACCEL(); @@ -687,7 +692,7 @@ void FUNC_NAME(RADEONWaitForIdle)(ScrnInfoPtr pScrn) #ifdef ACCEL_CP /* Make sure the CP is idle first */ - if (info->cp->CPStarted) { + if (info->cp->CPStarted || info->drm_mode_setting) { int ret; FLUSH_RING(); diff --git a/src/radeon_cursor.c b/src/radeon_cursor.c index 08bfddf..53dcb8a 100644 --- a/src/radeon_cursor.c +++ b/src/radeon_cursor.c @@ -96,12 +96,19 @@ avivo_setup_cursor(xf86CrtcPtr crtc, Bool enable) RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; RADEONInfoPtr info = RADEONPTR(crtc->scrn); unsigned char *RADEONMMIO = info->MMIO; - + uint32_t location; + OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, 0); if (enable) { + + if (info->drm_mm) + location = info->fbLocation + radeon_crtc->cursor->offset; + else + location = info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset; + OUTREG(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, - info->fbLocation + radeon_crtc->cursor_offset + pScrn->fbOffset); + location); OUTREG(AVIVO_D1CUR_SIZE + radeon_crtc->crtc_offset, ((CURSOR_WIDTH - 1) << 16) | (CURSOR_HEIGHT - 1)); OUTREG(AVIVO_D1CUR_CONTROL + radeon_crtc->crtc_offset, @@ -203,6 +210,7 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) int xorigin = 0, yorigin = 0; int stride = 256; DisplayModePtr mode = &crtc->mode; + uint32_t offset; if (x < 0) xorigin = -x+1; if (y < 0) yorigin = -y+1; @@ -235,8 +243,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) | (yorigin ? 0 : y))); RADEONCTRACE(("cursor_offset: 0x%x, yorigin: %d, stride: %d, temp %08X\n", radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); + if (info->drm_mm) + offset = radeon_crtc->cursor->offset; + else + offset = radeon_crtc->cursor_offset + pScrn->fbOffset; OUTREG(RADEON_CUR_OFFSET, - radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); + offset + yorigin * stride); } else if (crtc_id == 1) { OUTREG(RADEON_CUR2_HORZ_VERT_OFF, (RADEON_CUR2_LOCK | (xorigin << 16) @@ -246,8 +258,12 @@ radeon_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y) | (yorigin ? 0 : y))); RADEONCTRACE(("cursor_offset2: 0x%x, yorigin: %d, stride: %d, temp %08X\n", radeon_crtc->cursor_offset + pScrn->fbOffset, yorigin, stride, temp)); + if (info->drm_mm) + offset = radeon_crtc->cursor->offset; + else + offset = radeon_crtc->cursor_offset + pScrn->fbOffset; OUTREG(RADEON_CUR2_OFFSET, - radeon_crtc->cursor_offset + pScrn->fbOffset + yorigin * stride); + offset + yorigin * stride); } } } @@ -301,10 +317,15 @@ radeon_crtc_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; RADEONInfoPtr info = RADEONPTR(pScrn); CURSOR_SWAPPING_DECL_MMIO - uint32_t *d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); + uint32_t *d; RADEONCTRACE(("RADEONLoadCursorARGB\n")); + if (info->drm_mm) + d = (uint32_t *)radeon_crtc->cursor->map; + else + d = (uint32_t *)(pointer)(info->FB + radeon_crtc->cursor_offset); + info->cursor_argb = TRUE; CURSOR_SWAPPING_START(); @@ -335,7 +356,7 @@ Bool RADEONCursorInit(ScreenPtr pScreen) height = ((size_bytes * xf86_config->num_crtc) + width_bytes - 1) / width_bytes; int align = IS_AVIVO_VARIANT ? 4096 : 256; - if (!info->useEXA) { + if (!info->useEXA && !info->drm_mm) { for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr crtc = xf86_config->crtc[c]; RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; diff --git a/src/radeon_dri.c b/src/radeon_dri.c index 5542d2b..a4e8dea 100644 --- a/src/radeon_dri.c +++ b/src/radeon_dri.c @@ -40,6 +40,8 @@ #include #include +#include +#include /* Driver data structures */ #include "radeon.h" @@ -50,6 +52,8 @@ #include "radeon_dri.h" #include "radeon_version.h" +#include "radeon_drm.h" + /* X and server generic header files */ #include "xf86.h" #include "xf86PciInfo.h" @@ -67,16 +71,31 @@ static size_t radeon_drm_page_size; extern void GlxSetVisualConfigs(int nconfigs, __GLXvisualConfig *configs, void **configprivs); +#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +#define DRI_SUPPORTS_CLIP_NOTIFY 1 +#else +#define DRI_SUPPORTS_CLIP_NOTIFY 0 +#endif + +#if (DRIINFO_MAJOR_VERSION > 5 || \ + (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 4)) +#define DRI_DRIVER_FRAMEBUFFER_MAP 1 +#else +#define DRI_DRIVER_FRAMEBUFFER_MAP 0 +#endif + static void RADEONDRITransitionTo2d(ScreenPtr pScreen); static void RADEONDRITransitionTo3d(ScreenPtr pScreen); static void RADEONDRITransitionMultiToSingle3d(ScreenPtr pScreen); static void RADEONDRITransitionSingleToMulti3d(ScreenPtr pScreen); +static Bool radeon_dri_gart_init(ScreenPtr pScreen); + #ifdef DAMAGE static void RADEONDRIRefreshArea(ScrnInfoPtr pScrn, RegionPtr pReg); -#if (DRIINFO_MAJOR_VERSION > 5 || \ - (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)) +#if DRI_SUPPORTS_CLIP_NOTIFY static void RADEONDRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num); #endif #endif @@ -349,6 +368,126 @@ static void RADEONDestroyContext(ScreenPtr pScreen, drm_context_t hwContext, #endif } + +uint32_t radeon_name_buffer(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_gem_flink flink; + int ret; + + if (mem && mem->kernel_bo_handle) { + if (!mem->kernel_name) { + flink.handle = mem->kernel_bo_handle; + ret = ioctl(info->dri->drmFD, DRM_IOCTL_GEM_FLINK, &flink); + if (ret != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "[drm] failed to name buffer %d\n", -errno); + return -1; + } + mem->kernel_name = flink.name; + } + return mem->kernel_name; + } + return -1; +} + +static void radeon_update_sarea(ScrnInfoPtr pScrn, drm_radeon_sarea_t * sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + sarea->front_handle = -1; + sarea->back_handle = -1; + sarea->depth_handle = -1; + + if (info->drm_mm){ + /* get handles and use them */ + sarea->front_handle = radeon_name_buffer(pScrn, info->mm.front_buffer); + + sarea->front_pitch = info->dri->frontPitch * cpp; + sarea->back_pitch = info->dri->backPitch * cpp; + sarea->depth_pitch = info->dri->depthPitch * cpp; + ErrorF("front handle is %x\n", sarea->front_handle); + sarea->back_handle = radeon_name_buffer(pScrn, info->mm.back_buffer); + sarea->depth_handle = radeon_name_buffer(pScrn, info->mm.depth_buffer); + + } +} + +/* so we need to add a frontbuffer map no matter what */ +#define ROUND_TO(x, y) (((x) + (y) - 1) / (y) * (y)) +#define ROUND_TO_PAGE(x) ROUND_TO((x), radeon_drm_page_size) + +static void +radeon_update_screen_private(ScrnInfoPtr pScrn, drm_radeon_sarea_t * sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + RADEONDRIPtr pRADEONDRI; + + pRADEONDRI = (RADEONDRIPtr)info->dri->pDRIInfo->devPrivate; + info->dri->pDRIInfo->frameBufferPhysicalAddress = (char *) info->LinearAddr; + info->dri->pDRIInfo->frameBufferStride = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; + info->dri->pDRIInfo->frameBufferSize = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes); +#if DRI_DRIVER_FRAMEBUFFER_MAP + info->dri->pDRIInfo->hFrameBuffer = info->fb_map_handle; +#endif + /* overload these */ + pRADEONDRI->gartTexHandle = radeon_name_buffer(pScrn, info->mm.gart_texture_buffer); + pRADEONDRI->textureOffset = radeon_name_buffer(pScrn, info->mm.texture_buffer); + pRADEONDRI->frontOffset = radeon_name_buffer(pScrn, info->mm.front_buffer); + pRADEONDRI->backOffset = radeon_name_buffer(pScrn, info->mm.back_buffer); + pRADEONDRI->depthOffset = radeon_name_buffer(pScrn, info->mm.depth_buffer); +} + +static Bool +radeon_update_dri_mappings(ScrnInfoPtr pScrn, drm_radeon_sarea_t * sarea) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + uint32_t fb_addr, fb_size; + int ret; + + if (!info->drm_mm) + return TRUE; + + + fb_addr = info->mm.front_buffer->offset + info->LinearAddr; + fb_size = ROUND_TO_PAGE(pScrn->displayWidth * pScrn->virtualY * info->CurrentLayout.pixel_bytes); + + if (info->fb_map_handle) { + drmRmMap(info->dri->drmFD, info->fb_map_handle); + info->fb_map_handle = 0; + } + + ret = drmAddMap(info->dri->drmFD, fb_addr, fb_size, DRM_FRAME_BUFFER, 0, + &info->fb_map_handle); + + ErrorF("adding fb map from %x for %x ret %d %x\n", fb_addr, fb_size, ret, info->fb_map_handle); + + if (ret < 0) + return FALSE; + + return TRUE; +} + +Bool radeon_update_dri_buffers(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + Bool success; + drm_radeon_sarea_t * sarea = DRIGetSAREAPrivate(pScreen); + + if (info->ChipFamily >= CHIP_FAMILY_R600) + return TRUE; + + success = radeon_update_dri_mappings(pScrn, sarea); + + if (!success) + return FALSE; + + radeon_update_sarea(pScrn, sarea); + radeon_update_screen_private(pScrn, sarea); + return TRUE; +} + /* Called when the X server is woken up to allow the last client's * context to be saved and the X server's context to be loaded. This is * not necessary for the Radeon since the client detects when it's @@ -698,25 +837,35 @@ static void RADEONDRIInitGARTValues(RADEONInfoPtr info) info->dri->gartOffset = 0; - /* Initialize the CP ring buffer data */ - info->dri->ringStart = info->dri->gartOffset; - info->dri->ringMapSize = info->dri->ringSize*1024*1024 + radeon_drm_page_size; - info->dri->ringSizeLog2QW = RADEONMinBits(info->dri->ringSize*1024*1024/8)-1; - - info->dri->ringReadOffset = info->dri->ringStart + info->dri->ringMapSize; - info->dri->ringReadMapSize = radeon_drm_page_size; - - /* Reserve space for vertex/indirect buffers */ - info->dri->bufStart = info->dri->ringReadOffset + info->dri->ringReadMapSize; - info->dri->bufMapSize = info->dri->bufSize*1024*1024; - - /* Reserve the rest for GART textures */ - info->dri->gartTexStart = info->dri->bufStart + info->dri->bufMapSize; - s = (info->dri->gartSize*1024*1024 - info->dri->gartTexStart); - l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - info->dri->gartTexMapSize = (s >> l) << l; - info->dri->log2GARTTexGran = l; + if (!info->drm_mm) { + /* Initialize the CP ring buffer data */ + info->dri->ringStart = info->dri->gartOffset; + info->dri->ringMapSize = info->dri->ringSize*1024*1024 + radeon_drm_page_size; + info->dri->ringSizeLog2QW = RADEONMinBits(info->dri->ringSize*1024*1024/8)-1; + + info->dri->ringReadOffset = info->dri->ringStart + info->dri->ringMapSize; + info->dri->ringReadMapSize = radeon_drm_page_size; + + /* Reserve space for vertex/indirect buffers */ + info->dri->bufStart = info->dri->ringReadOffset + info->dri->ringReadMapSize; + info->dri->bufMapSize = info->dri->bufSize*1024*1024; + + /* Reserve the rest for GART textures */ + info->dri->gartTexStart = info->dri->bufStart + info->dri->bufMapSize; + s = (info->dri->gartSize*1024*1024 - info->dri->gartTexStart); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->dri->gartTexMapSize = (s >> l) << l; + info->dri->log2GARTTexGran = l; + } else { + s = (8*1024*1024); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->dri->gartTexMapSize = (s >> l) << l; + info->dri->log2GARTTexGran = l; + } + } /* Set AGP transfer mode according to requests and constraints */ @@ -888,6 +1037,8 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] ring handle = 0x%08x\n", info->dri->ringHandle); + +#if 0 if (drmMap(info->dri->drmFD, info->dri->ringHandle, info->dri->ringMapSize, &info->dri->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not map ring\n"); @@ -896,9 +1047,10 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring mapped at 0x%08lx\n", (unsigned long)info->dri->ring); - +#endif if (drmAddMap(info->dri->drmFD, info->dri->ringReadOffset, info->dri->ringReadMapSize, DRM_AGP, DRM_READ_ONLY, &info->dri->ringReadPtrHandle) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[agp] Could not add ring read ptr mapping\n"); return FALSE; @@ -907,6 +1059,8 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) "[agp] ring read ptr handle = 0x%08x\n", info->dri->ringReadPtrHandle); + +#if 0 if (drmMap(info->dri->drmFD, info->dri->ringReadPtrHandle, info->dri->ringReadMapSize, &info->dri->ringReadPtr) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, @@ -916,6 +1070,7 @@ static Bool RADEONDRIAgpInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[agp] Ring read ptr mapped at 0x%08lx\n", (unsigned long)info->dri->ringReadPtr); +#endif if (drmAddMap(info->dri->drmFD, info->dri->bufStart, info->dri->bufMapSize, DRM_AGP, 0, &info->dri->bufHandle) < 0) { @@ -991,6 +1146,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] ring handle = 0x%08x\n", info->dri->ringHandle); +#if 0 if (drmMap(info->dri->drmFD, info->dri->ringHandle, info->dri->ringMapSize, &info->dri->ring) < 0) { xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring\n"); @@ -1002,6 +1158,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring contents 0x%08lx\n", *(unsigned long *)(pointer)info->dri->ring); +#endif if (drmAddMap(info->dri->drmFD, info->dri->ringReadOffset, info->dri->ringReadMapSize, DRM_SCATTER_GATHER, flags, &info->dri->ringReadPtrHandle) < 0) { @@ -1013,8 +1170,10 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) "[pci] ring read ptr handle = 0x%08x\n", info->dri->ringReadPtrHandle); +#if 0 if (drmMap(info->dri->drmFD, info->dri->ringReadPtrHandle, info->dri->ringReadMapSize, &info->dri->ringReadPtr) < 0) { + xf86DrvMsg(pScreen->myNum, X_ERROR, "[pci] Could not map ring read ptr\n"); return FALSE; @@ -1025,6 +1184,7 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) xf86DrvMsg(pScreen->myNum, X_INFO, "[pci] Ring read ptr contents 0x%08lx\n", *(unsigned long *)(pointer)info->dri->ringReadPtr); +#endif if (drmAddMap(info->dri->drmFD, info->dri->bufStart, info->dri->bufMapSize, DRM_SCATTER_GATHER, 0, &info->dri->bufHandle) < 0) { @@ -1077,6 +1237,9 @@ static Bool RADEONDRIPciInit(RADEONInfoPtr info, ScreenPtr pScreen) */ static Bool RADEONDRIMapInit(RADEONInfoPtr info, ScreenPtr pScreen) { + + if (info->drm_mm) + return TRUE; /* Map registers */ info->dri->registerSize = info->MMIOSize; if (drmAddMap(info->dri->drmFD, info->MMIOAddr, info->dri->registerSize, @@ -1115,20 +1278,23 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) drmInfo.fb_bpp = info->CurrentLayout.pixel_code; drmInfo.depth_bpp = (info->dri->depthBits - 8) * 2; - drmInfo.front_offset = info->dri->frontOffset; - drmInfo.front_pitch = info->dri->frontPitch * cpp; - drmInfo.back_offset = info->dri->backOffset; - drmInfo.back_pitch = info->dri->backPitch * cpp; - drmInfo.depth_offset = info->dri->depthOffset; - drmInfo.depth_pitch = info->dri->depthPitch * drmInfo.depth_bpp / 8; - - drmInfo.fb_offset = info->dri->fbHandle; - drmInfo.mmio_offset = info->dri->registerHandle; - drmInfo.ring_offset = info->dri->ringHandle; - drmInfo.ring_rptr_offset = info->dri->ringReadPtrHandle; - drmInfo.buffers_offset = info->dri->bufHandle; - drmInfo.gart_textures_offset= info->dri->gartTexHandle; - + if (!info->drm_mm) { + drmInfo.front_offset = info->dri->frontOffset; + drmInfo.front_pitch = info->dri->frontPitch * cpp; + drmInfo.back_offset = info->dri->backOffset; + drmInfo.back_pitch = info->dri->backPitch * cpp; + drmInfo.depth_offset = info->dri->depthOffset; + drmInfo.depth_pitch = info->dri->depthPitch * drmInfo.depth_bpp / 8; + + drmInfo.fb_offset = info->dri->fbHandle; + drmInfo.mmio_offset = info->dri->registerHandle; + drmInfo.ring_offset = info->dri->ringHandle; + drmInfo.ring_rptr_offset = info->dri->ringReadPtrHandle; + drmInfo.buffers_offset = info->dri->bufHandle; + drmInfo.gart_textures_offset= info->dri->gartTexHandle; + } else { + } + if (drmCommandWrite(info->dri->drmFD, DRM_RADEON_CP_INIT, &drmInfo, sizeof(drm_radeon_init_t)) < 0) return FALSE; @@ -1137,7 +1303,8 @@ static int RADEONDRIKernelInit(RADEONInfoPtr info, ScreenPtr pScreen) * registers back to their default values, so we need to restore * those engine register here. */ - RADEONEngineRestore(pScrn); + if (!info->drm_mm) + RADEONEngineRestore(pScrn); return TRUE; } @@ -1333,12 +1500,11 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) /* Get DRM version & close DRM */ info->dri->pKernelDRMVersion = drmGetVersion(fd); - drmClose(fd); if (info->dri->pKernelDRMVersion == NULL) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] RADEONDRIGetVersion failed to get the DRM version\n" "[dri] Disabling DRI.\n"); - return FALSE; + goto fail; } /* Now check if we qualify */ @@ -1372,10 +1538,29 @@ Bool RADEONDRIGetVersion(ScrnInfoPtr pScrn) req_patch); drmFreeVersion(info->dri->pKernelDRMVersion); info->dri->pKernelDRMVersion = NULL; - return FALSE; + goto fail; } + if (info->dri->pKernelDRMVersion->version_minor >= 30) { + struct drm_radeon_gem_info mminfo; + + if (!drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) + { + info->drm_mm = TRUE; + info->mm.vram_start = mminfo.vram_start; + info->mm.vram_size = mminfo.vram_size; + info->mm.gart_start = mminfo.vram_start; + info->mm.gart_size = mminfo.gart_size; + ErrorF("initing %llx %llx %llx %llx\n", mminfo.gart_start, + mminfo.gart_size, mminfo.vram_start, mminfo.vram_size); + } + } + + drmClose(fd); return TRUE; +fail: + drmClose(fd); + return FALSE; } Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) @@ -1384,6 +1569,9 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int value = 0; + if (info->drm_mode_setting) + return TRUE; + if (!info->want_vblank_interrupts) on = FALSE; @@ -1403,6 +1591,48 @@ Bool RADEONDRISetVBlankInterrupt(ScrnInfoPtr pScrn, Bool on) return TRUE; } +Bool RADEONDRIDoMappings(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + drm_radeon_sarea_t * pSAREAPriv = DRIGetSAREAPrivate(pScreen); + /* DRIScreenInit doesn't add all the + * common mappings. Add additional + * mappings here. + */ + + if (info->ChipFamily >= CHIP_FAMILY_R600) + return TRUE; + + if (!RADEONDRIMapInit(info, pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } + + radeon_update_sarea(pScrn, pSAREAPriv); + + /* DRIScreenInit adds the frame buffer + map, but we need it as well */ + { + void *scratch_ptr; + int scratch_int; + + DRIGetDeviceInfo(pScreen, &info->dri->fbHandle, + &scratch_int, &scratch_int, + &scratch_int, &scratch_int, + &scratch_ptr); + } + + /* FIXME: When are these mappings unmapped? */ + + if (!RADEONInitVisualConfigs(pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); + return TRUE; + +} /* Initialize the screen-specific data structures for the DRI and the * Radeon. This is the main entry point to the device-specific @@ -1466,10 +1696,22 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->ddxDriverMajorVersion = info->allowColorTiling ? 5 : 4; pDRIInfo->ddxDriverMinorVersion = 3; pDRIInfo->ddxDriverPatchVersion = 0; - pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset; - pDRIInfo->frameBufferSize = info->FbMapSize - info->FbSecureSize; - pDRIInfo->frameBufferStride = (pScrn->displayWidth * - info->CurrentLayout.pixel_bytes); + +#if DRI_DRIVER_FRAMEBUFFER_MAP + if (info->drm_mm) { + pDRIInfo->frameBufferPhysicalAddress = 0; + pDRIInfo->frameBufferSize = 0; + pDRIInfo->frameBufferStride = 0; + pDRIInfo->dontMapFrameBuffer = TRUE; + } else +#endif + { + pDRIInfo->frameBufferPhysicalAddress = (void *)info->LinearAddr + info->dri->frontOffset; + pDRIInfo->frameBufferSize = info->FbMapSize - info->FbSecureSize; + pDRIInfo->frameBufferStride = (pScrn->displayWidth * + info->CurrentLayout.pixel_bytes); + } + pDRIInfo->ddxDrawableTableEntry = RADEON_MAX_DRAWABLES; pDRIInfo->maxDrawableTableEntry = (SAREA_MAX_DRAWABLES < RADEON_MAX_DRAWABLES @@ -1522,9 +1764,7 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo->TransitionTo3d = RADEONDRITransitionTo3d; pDRIInfo->TransitionSingleToMulti3D = RADEONDRITransitionSingleToMulti3d; pDRIInfo->TransitionMultiToSingle3D = RADEONDRITransitionMultiToSingle3d; -#if defined(DAMAGE) && (DRIINFO_MAJOR_VERSION > 5 || \ - (DRIINFO_MAJOR_VERSION == 5 && \ - DRIINFO_MINOR_VERSION >= 1)) +#if DRI_SUPPORT_CLIP_NOTIFY pDRIInfo->ClipNotify = RADEONDRIClipNotify; #endif @@ -1556,57 +1796,60 @@ Bool RADEONDRIScreenInit(ScreenPtr pScreen) pDRIInfo = NULL; return FALSE; } - /* Initialize AGP */ - if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[agp] AGP failed to initialize. Disabling the DRI.\n" ); - xf86DrvMsg(pScreen->myNum, X_INFO, - "[agp] You may want to make sure the agpgart kernel " - "module\nis loaded before the radeon kernel module.\n"); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - - /* Initialize PCI */ - if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "[pci] PCI failed to initialize. Disabling the DRI.\n" ); - RADEONDRICloseScreen(pScreen); - return FALSE; - } - - /* DRIScreenInit doesn't add all the - * common mappings. Add additional - * mappings here. - */ - if (!RADEONDRIMapInit(info, pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; - } - /* DRIScreenInit adds the frame buffer - map, but we need it as well */ - { - void *scratch_ptr; - int scratch_int; + /* Now, nuke dri.c's dummy frontbuffer map setup if we did that. */ + if (pDRIInfo->frameBufferSize != 0 && info->drm_mm) { + int tmp; + drm_handle_t fb_handle; + void *ptmp; - DRIGetDeviceInfo(pScreen, &info->dri->fbHandle, - &scratch_int, &scratch_int, - &scratch_int, &scratch_int, - &scratch_ptr); - } - - /* FIXME: When are these mappings unmapped? */ - - if (!RADEONInitVisualConfigs(pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; + /* With the compat method, it will continue to report + * the wrong map out of GetDeviceInfo, which will break AIGLX. + */ + DRIGetDeviceInfo(pScreen, &fb_handle, &tmp, &tmp, &tmp, &tmp, &ptmp); + drmRmMap(info->dri->drmFD, fb_handle); + + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Removed DRI frontbuffer mapping in compatibility mode.\n"); + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "DRIGetDeviceInfo will report incorrect frontbuffer " + "handle.\n"); + } + + if (info->drm_mm) { + int ret; + ret = radeon_dri_gart_init(pScreen); + if (!ret) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[gart] GART failed to initialize. Disabling the DRI.\n" ); + RADEONDRICloseScreen(pScreen); + return FALSE; + } + } else { + if (info->cardType==CARD_AGP && !RADEONDRIAgpInit(info, pScreen)) { + /* Initialize AGP */ + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[agp] AGP failed to initialize. Disabling the DRI.\n" ); + xf86DrvMsg(pScreen->myNum, X_INFO, + "[agp] You may want to make sure the agpgart kernel " + "module\nis loaded before the radeon kernel module.\n"); + RADEONDRICloseScreen(pScreen); + return FALSE; + } + + /* Initialize PCI */ + if ((info->cardType!=CARD_AGP) && !RADEONDRIPciInit(info, pScreen)) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "[pci] PCI failed to initialize. Disabling the DRI.\n" ); + RADEONDRICloseScreen(pScreen); + return FALSE; + } } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Visual configs initialized\n"); return TRUE; } + static Bool RADEONDRIDoCloseScreen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; @@ -1648,14 +1891,18 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) return FALSE; } - /* Initialize the vertex buffers list */ - if (!RADEONDRIBufInit(info, pScreen)) { - RADEONDRICloseScreen(pScreen); - return FALSE; + if (!info->drm_mm) { + /* Initialize the vertex buffers list */ + if (!RADEONDRIBufInit(info, pScreen)) { + RADEONDRICloseScreen(pScreen); + return FALSE; + } } - /* Initialize IRQ */ - RADEONDRIIrqInit(info, pScreen); + if (!info->drm_mode_setting) { + /* Initialize IRQ */ + RADEONDRIIrqInit(info, pScreen); + } /* Initialize kernel GART memory manager */ RADEONDRIGartHeapInit(info, pScreen); @@ -1667,6 +1914,10 @@ Bool RADEONDRIFinishScreenInit(ScreenPtr pScreen) pSAREAPriv = (drm_radeon_sarea_t*)DRIGetSAREAPrivate(pScreen); memset(pSAREAPriv, 0, sizeof(*pSAREAPriv)); + if (info->drm_mm) { + /* init the handles into the sarea */ + + } pRADEONDRI = (RADEONDRIPtr)info->dri->pDRIInfo->devPrivate; pRADEONDRI->deviceID = info->Chipset; @@ -1823,6 +2074,8 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmUnmap(info->dri->buf, info->dri->bufMapSize); info->dri->buf = NULL; } + +#if 0 if (info->dri->ringReadPtr) { drmUnmap(info->dri->ringReadPtr, info->dri->ringReadMapSize); info->dri->ringReadPtr = NULL; @@ -1831,6 +2084,7 @@ void RADEONDRICloseScreen(ScreenPtr pScreen) drmUnmap(info->dri->ring, info->dri->ringMapSize); info->dri->ring = NULL; } +#endif if (info->dri->agpMemHandle != DRM_AGP_NO_HANDLE) { drmAgpUnbind(info->dri->drmFD, info->dri->agpMemHandle); drmAgpFree(info->dri->drmFD, info->dri->agpMemHandle); @@ -2237,3 +2491,16 @@ int RADEONDRISetParam(ScrnInfoPtr pScrn, unsigned int param, int64_t value) &radeonsetparam, sizeof(drm_radeon_setparam_t)); return ret; } + +static Bool radeon_dri_gart_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + RADEONDRIInitGARTValues(info); + + /* so we want to allocate the buffers/gart texmap */ + /* ignore ring stuff */ + return radeon_setup_gart_mem(pScreen); + +} diff --git a/src/radeon_dri_bufmgr.c b/src/radeon_dri_bufmgr.c new file mode 100644 index 0000000..12263c3 --- /dev/null +++ b/src/radeon_dri_bufmgr.c @@ -0,0 +1,174 @@ +/* + * 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 + * + */ + +#include +#include +#include +#include "radeon_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) +{ + 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) +{ + 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, int write_enable) +{ + return buf->bufmgr->bo_map(buf, write_enable); +} + +int +dri_bo_unmap(dri_bo *buf) +{ + return buf->bufmgr->bo_unmap(buf); +} + +void +dri_fence_wait(dri_fence *fence) +{ + fence->bufmgr->fence_wait(fence); +} + +void +dri_fence_reference(dri_fence *fence) +{ + fence->bufmgr->fence_reference(fence); +} + +void +dri_fence_unreference(dri_fence *fence) +{ + if (fence == NULL) + return; + + fence->bufmgr->fence_unreference(fence); +} + +void +dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data) +{ + if (size == 0 || data == NULL) + return; + + dri_bo_map(bo, 1); + memcpy((unsigned char *)bo->virtual + offset, data, size); + dri_bo_unmap(bo); +} + +void +dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data) +{ + if (size == 0 || data == NULL) + return; + + dri_bo_map(bo, 0); + memcpy(data, (unsigned char *)bo->virtual + offset, size); + dri_bo_unmap(bo); +} + +void +dri_bufmgr_destroy(dri_bufmgr *bufmgr) +{ + bufmgr->destroy(bufmgr); +} + + +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta, + uint32_t offset, dri_bo *target_buf) +{ + return reloc_buf->bufmgr->emit_reloc(reloc_buf, flags, delta, offset, target_buf); +} + +void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count) +{ + return batch_buf->bufmgr->process_relocs(batch_buf, count); +} + +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence) +{ + batch_buf->bufmgr->post_submit(batch_buf, last_fence); +} + +void +dri_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug) +{ + bufmgr->debug = enable_debug; +} + +int +dri_bufmgr_check_aperture_space(dri_bo *bo, uint32_t read_domains, uint32_t write_domain) +{ + return bo->bufmgr->check_aperture_space(bo, read_domains, write_domain); +} + +int dri_bo_pin(dri_bo *bo, int domain) +{ + return bo->bufmgr->pin(bo, domain); +} + +void dri_bo_unpin(dri_bo *bo) +{ + bo->bufmgr->unpin(bo); +} + +uint32_t dri_bo_get_handle(dri_bo *bo) +{ + return bo->bufmgr->get_handle(bo); +} diff --git a/src/radeon_dri_bufmgr.h b/src/radeon_dri_bufmgr.h new file mode 100644 index 0000000..041671f --- /dev/null +++ b/src/radeon_dri_bufmgr.h @@ -0,0 +1,279 @@ +/************************************************************************** + * + * 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 + */ + +#ifndef _DRI_BUFMGR_H_ +#define _DRI_BUFMGR_H_ +#include + +typedef struct _dri_bufmgr dri_bufmgr; +typedef struct _dri_bo dri_bo; +typedef struct _dri_fence dri_fence; + +/* reloc format */ +/* gem handle, read_domains, write_domain, reloc_count */ +#define RADEON_RELOC_SIZE 4 +struct radeon_relocs_info { + uint32_t *buf; + int size; + int num_reloc; +}; + +struct _dri_bo { + /** Size in bytes of the buffer object. */ + 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; +}; + +struct _dri_fence { + /** + * This is an ORed mask of DRM_BO_FLAG_READ, DRM_BO_FLAG_WRITE, and + * DRM_FLAG_EXE indicating the operations associated with this fence. + * + * It is constant for the life of the fence object. + */ + unsigned int type; + /** Buffer manager context associated with this fence */ + 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 fence on the buffer to + * clear, first. The resulting mapping is available at buf->virtual. +\ */ + int (*bo_map)(dri_bo *buf, int write_enable); + + /** Reduces the refcount on the userspace mapping of the buffer object. */ + int (*bo_unmap)(dri_bo *buf); + + /** Takes a reference on a fence object */ + void (*fence_reference)(dri_fence *fence); + + /** + * Releases a reference on a fence object, freeing the data if + * rerefences remain. + */ + void (*fence_unreference)(dri_fence *fence); + + /** + * Blocks until the given fence is signaled. + */ + void (*fence_wait)(dri_fence *fence); + + /** + * 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, uint64_t flags, 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 + * \param count returns the number of buffers validated. + * \return relocation record for use in command submission. + * */ + void *(*process_relocs)(dri_bo *batch_buf, uint32_t *count); + + void (*post_submit)(dri_bo *batch_buf, dri_fence **fence); + + int (*check_aperture_space)(dri_bo *bo, uint32_t read_domains, uint32_t write_domain); + + int (*pin)(dri_bo *bo, int domain); + void (*unpin)(dri_bo *bo); + + uint32_t (*get_handle)(dri_bo *bo); + int 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, int write_enable); +int dri_bo_unmap(dri_bo *buf); +void dri_fence_wait(dri_fence *fence); +void dri_fence_reference(dri_fence *fence); +void dri_fence_unreference(dri_fence *fence); + +void dri_bo_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, const void *data); +void dri_bo_get_subdata(dri_bo *bo, unsigned long offset, + unsigned long size, void *data); + +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_bufmgr_set_debug(dri_bufmgr *bufmgr, int enable_debug); +void dri_bo_fake_disable_backing_store(dri_bo *bo, + void (*invalidate_cb)(dri_bo *bo, + void *ptr), + void *ptr); +void dri_bufmgr_destroy(dri_bufmgr *bufmgr); + +int dri_emit_reloc(dri_bo *reloc_buf, uint64_t flags, uint32_t delta, + uint32_t offset, dri_bo *target_buf); +void *dri_process_relocs(dri_bo *batch_buf, uint32_t *count); +void dri_post_process_relocs(dri_bo *batch_buf); +void dri_post_submit(dri_bo *batch_buf, dri_fence **last_fence); +int dri_bufmgr_check_aperture_space(dri_bo *bo, uint32_t read_domains, uint32_t write_domain); + +int dri_bo_pin(dri_bo *bo, int domain); +void dri_bo_unpin(dri_bo *bo); + +uint32_t dri_bo_get_handle(dri_bo *bo); + +#ifndef TTM_API +/* reuse some TTM API */ + +#define DRM_BO_MEM_LOCAL 0 +#define DRM_BO_MEM_TT 1 +#define DRM_BO_MEM_VRAM 2 +#define DRM_BO_MEM_PRIV0 3 +#define DRM_BO_MEM_PRIV1 4 +#define DRM_BO_MEM_PRIV2 5 +#define DRM_BO_MEM_PRIV3 6 +#define DRM_BO_MEM_PRIV4 7 + +#define DRM_BO_FLAG_READ (1ULL << 0) +#define DRM_BO_FLAG_WRITE (1ULL << 1) +#define DRM_BO_FLAG_EXE (1ULL << 2) +#define DRM_BO_MASK_ACCESS (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE | DRM_BO_FLAG_EXE) +#define DRM_BO_FLAG_NO_EVICT (1ULL << 4) + +#define DRM_BO_FLAG_MAPPABLE (1ULL << 5) +#define DRM_BO_FLAG_SHAREABLE (1ULL << 6) + +#define DRM_BO_FLAG_CACHED (1ULL << 7) + +#define DRM_BO_FLAG_NO_MOVE (1ULL << 8) +#define DRM_BO_FLAG_CACHED_MAPPED (1ULL << 19) +#define DRM_BO_FLAG_FORCE_CACHING (1ULL << 13) +#define DRM_BO_FLAG_FORCE_MAPPABLE (1ULL << 14) +#define DRM_BO_FLAG_TILE (1ULL << 15) + +#define DRM_BO_FLAG_MEM_LOCAL (1ULL << 24) +#define DRM_BO_FLAG_MEM_TT (1ULL << 25) +#define DRM_BO_FLAG_MEM_VRAM (1ULL << 26) + +#define DRM_BO_MASK_MEM 0x00000000FF000000ULL + +#define DRM_FENCE_TYPE_EXE 0x00000001 +#endif + +#endif diff --git a/src/radeon_driver.c b/src/radeon_driver.c index c759bd6..54cc804 100644 --- a/src/radeon_driver.c +++ b/src/radeon_driver.c @@ -224,7 +224,10 @@ radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; *size = stride; - return ((uint8_t *)info->FB + row * stride + offset); + if (info->drm_mm) + return ((uint8_t *)info->mm.front_buffer->map + row * stride + offset); + else + return ((uint8_t *)info->FB + row * stride + offset); } static Bool RADEONCreateScreenResources (ScreenPtr pScreen) @@ -1620,6 +1623,7 @@ static Bool RADEONPreInitVRAM(ScrnInfoPtr pScrn) } pScrn->videoRam &= ~1023; + info->FbMapSize = pScrn->videoRam * 1024; /* if the card is PCI Express reserve the last 32k for the gart table */ @@ -1747,56 +1751,62 @@ static Bool RADEONPreInitChipType(ScrnInfoPtr pScrn) from = X_PROBED; info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL; pScrn->memPhysBase = info->LinearAddr; - if (dev->MemBase) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Linear address override, using 0x%016lx instead of 0x%016lx\n", - dev->MemBase, - info->LinearAddr); - info->LinearAddr = dev->MemBase; - from = X_CONFIG; - } else if (!info->LinearAddr) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "No valid linear framebuffer address\n"); - return FALSE; - } - xf86DrvMsg(pScrn->scrnIndex, from, - "Linear framebuffer at 0x%016lx\n", info->LinearAddr); -#ifndef XSERVER_LIBPCIACCESS - /* BIOS */ - from = X_PROBED; - info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; - if (dev->BiosBase) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "BIOS address override, using 0x%08lx instead of 0x%08lx\n", - dev->BiosBase, - info->BIOSAddr); - info->BIOSAddr = dev->BiosBase; - from = X_CONFIG; - } - if (info->BIOSAddr) { + if (!info->drm_mode_setting) { + from = X_PROBED; + info->LinearAddr = PCI_REGION_BASE(info->PciInfo, 0, REGION_MEM) & ~0x1ffffffUL; + pScrn->memPhysBase = info->LinearAddr; + if (dev->MemBase) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Linear address override, using 0x%016lx instead of 0x%016lx\n", + dev->MemBase, + info->LinearAddr); + info->LinearAddr = dev->MemBase; + from = X_CONFIG; + } else if (!info->LinearAddr) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No valid linear framebuffer address\n"); + return FALSE; + } xf86DrvMsg(pScrn->scrnIndex, from, - "BIOS at 0x%08lx\n", info->BIOSAddr); - } + "Linear framebuffer at 0x%016lx\n", info->LinearAddr); + +#ifndef XSERVER_LIBPCIACCESS + /* BIOS */ + from = X_PROBED; + info->BIOSAddr = info->PciInfo->biosBase & 0xfffe0000; + if (dev->BiosBase) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "BIOS address override, using 0x%08lx instead of 0x%08lx\n", + dev->BiosBase, + info->BIOSAddr); + info->BIOSAddr = dev->BiosBase; + from = X_CONFIG; + } + if (info->BIOSAddr) { + xf86DrvMsg(pScrn->scrnIndex, from, + "BIOS at 0x%08lx\n", info->BIOSAddr); + } #endif - /* Read registers used to determine options */ - /* Check chip errata */ - info->ChipErrata = 0; + /* Read registers used to determine options */ + /* Check chip errata */ + info->ChipErrata = 0; - if (info->ChipFamily == CHIP_FAMILY_R300 && - (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) - == RADEON_CFG_ATI_REV_A11) + if (info->ChipFamily == CHIP_FAMILY_R300 && + (INREG(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) + == RADEON_CFG_ATI_REV_A11) info->ChipErrata |= CHIP_ERRATA_R300_CG; - - if (info->ChipFamily == CHIP_FAMILY_RV200 || - info->ChipFamily == CHIP_FAMILY_RS200) + + if (info->ChipFamily == CHIP_FAMILY_RV200 || + info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DUMMYREADS; - - if (info->ChipFamily == CHIP_FAMILY_RV100 || - info->ChipFamily == CHIP_FAMILY_RS100 || - info->ChipFamily == CHIP_FAMILY_RS200) + + if (info->ChipFamily == CHIP_FAMILY_RV100 || + info->ChipFamily == CHIP_FAMILY_RS100 || + info->ChipFamily == CHIP_FAMILY_RS200) info->ChipErrata |= CHIP_ERRATA_PLL_DELAY; + } #ifdef XF86DRI /* AGP/PCI */ @@ -1989,6 +1999,9 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) if (!xf86ReturnOptValBool(info->Options, OPTION_NOACCEL, FALSE)) { int errmaj = 0, errmin = 0; +#if defined(USE_EXA) + info->useEXA = TRUE; +#endif from = X_DEFAULT; #if defined(USE_EXA) #if defined(USE_XAA) @@ -1999,6 +2012,7 @@ static Bool RADEONPreInitAccel(ScrnInfoPtr pScrn) info->useEXA = TRUE; } else if (xf86NameCmp(optstr, "XAA") == 0) { from = X_CONFIG; + info->useEXA = FALSE; } } #else /* USE_XAA */ @@ -2102,15 +2116,9 @@ static Bool RADEONPreInitInt10(ScrnInfoPtr pScrn, xf86Int10InfoPtr *ppInt10) return TRUE; } -#ifdef XF86DRI -static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) +static Bool radeon_alloc_dri(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - MessageType from; - char *reason; - - info->directRenderingEnabled = FALSE; - info->directRenderingInited = FALSE; if (!(info->dri = xcalloc(1, sizeof(struct radeon_dri)))) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate dri rec!\n"); @@ -2121,6 +2129,22 @@ static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) xf86DrvMsg(pScrn->scrnIndex, X_ERROR,"Unable to allocate cp rec!\n"); return FALSE; } + return TRUE; +} + +#ifdef XF86DRI +static Bool RADEONPreInitDRI(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + MessageType from; + char *reason; + + info->directRenderingEnabled = FALSE; + info->directRenderingInited = FALSE; + + if (!radeon_alloc_dri(pScrn)) + return FALSE; + info->cp->CPInUse = FALSE; info->cp->CPStarted = FALSE; info->cp->CPusecTimeout = RADEON_DEFAULT_CP_TIMEOUT; @@ -2685,6 +2709,37 @@ static const xf86CrtcConfigFuncsRec RADEONCRTCResizeFuncs = { RADEONCRTCResize }; +#ifdef XF86DRM_MODE +static Bool radeon_kernel_mode_enabled(ScrnInfoPtr pScrn) +{ +#if XSERVER_LIBPCIACCESS + struct pci_device *PciInfo; +#else + pciVideoPtr PciInfo; +#endif + EntityInfoPtr pEnt; + char *busIdString; + int ret; + + pEnt = xf86GetEntityInfo(pScrn->entityList[0]); + PciInfo = xf86GetPciInfoForEntity(pEnt->index); + + if (!xf86LoaderCheckSymbol("DRICreatePCIBusID")) + return FALSE; + + busIdString = DRICreatePCIBusID(PciInfo); + ret = drmCheckModesettingSupported(busIdString); + xfree(busIdString); + if (ret) + return FALSE; + + return TRUE; +} +#else +#define radeon_kernel_mode_enabled(x) FALSE +#endif + + Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) { xf86CrtcConfigPtr xf86_config; @@ -2705,6 +2760,8 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) info = RADEONPTR(pScrn); info->MMIO = NULL; + info->drm_mode_setting = radeon_kernel_mode_enabled(pScrn); + info->IsSecondary = FALSE; info->IsPrimary = FALSE; @@ -2739,59 +2796,63 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) } info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); - info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), - PCI_DEV_DEV(info->PciInfo), - PCI_DEV_FUNC(info->PciInfo)); - info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffUL; - info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2); - if (info->pEnt->device->IOBase) { - xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, - "MMIO address override, using 0x%08lx instead of 0x%08lx\n", - info->pEnt->device->IOBase, - info->MMIOAddr); - info->MMIOAddr = info->pEnt->device->IOBase; - } else if (!info->MMIOAddr) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); - goto fail1; - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "MMIO registers at 0x%016lx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024); - if(!RADEONMapMMIO(pScrn)) { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Memory map the MMIO region failed\n"); - goto fail1; - } + if (!info->drm_mode_setting) { + info->PciTag = pciTag(PCI_DEV_BUS(info->PciInfo), + PCI_DEV_DEV(info->PciInfo), + PCI_DEV_FUNC(info->PciInfo)); + info->MMIOAddr = PCI_REGION_BASE(info->PciInfo, 2, REGION_MEM) & ~0xffUL; + info->MMIOSize = PCI_REGION_SIZE(info->PciInfo, 2); + if (info->pEnt->device->IOBase) { + xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, + "MMIO address override, using 0x%08lx instead of 0x%08lx\n", + info->pEnt->device->IOBase, + info->MMIOAddr); + info->MMIOAddr = info->pEnt->device->IOBase; + } else if (!info->MMIOAddr) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid MMIO address\n"); + goto fail1; + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "MMIO registers at 0x%016lx: size %ldKB\n", info->MMIOAddr, info->MMIOSize / 1024); + + if(!RADEONMapMMIO(pScrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Memory map the MMIO region failed\n"); + goto fail1; + } + #if !defined(__alpha__) - if ( + if ( #ifndef XSERVER_LIBPCIACCESS - xf86GetPciDomain(info->PciTag) || + xf86GetPciDomain(info->PciTag) || #endif - !xf86IsPrimaryPci(info->PciInfo)) - RADEONPreInt10Save(pScrn, &int10_save); + !xf86IsPrimaryPci(info->PciInfo)) + RADEONPreInt10Save(pScrn, &int10_save); #else - /* [Alpha] On the primary, the console already ran the BIOS and we're - * going to run it again - so make sure to "fix up" the card - * so that (1) we can read the BIOS ROM and (2) the BIOS will - * get the memory config right. - */ - RADEONPreInt10Save(pScrn, &int10_save); + /* [Alpha] On the primary, the console already ran the BIOS and we're + * going to run it again - so make sure to "fix up" the card + * so that (1) we can read the BIOS ROM and (2) the BIOS will + * get the memory config right. + */ + RADEONPreInt10Save(pScrn, &int10_save); #endif - - if (flags & PROBE_DETECT) { - RADEONProbeDDC(pScrn, info->pEnt->index); - RADEONPostInt10Check(pScrn, int10_save); - if(info->MMIO) RADEONUnmapMMIO(pScrn); - return TRUE; - } + + if (flags & PROBE_DETECT) { + RADEONProbeDDC(pScrn, info->pEnt->index); + RADEONPostInt10Check(pScrn, int10_save); + if(info->MMIO) RADEONUnmapMMIO(pScrn); + return TRUE; + } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "PCI bus %d card %d func %d\n", - PCI_DEV_BUS(info->PciInfo), - PCI_DEV_DEV(info->PciInfo), - PCI_DEV_FUNC(info->PciInfo)); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "PCI bus %d card %d func %d\n", + PCI_DEV_BUS(info->PciInfo), + PCI_DEV_DEV(info->PciInfo), + PCI_DEV_FUNC(info->PciInfo)); + } if (xf86RegisterResources(info->pEnt->index, 0, ResExclusive)) goto fail; @@ -2801,10 +2862,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR; pScrn->monitor = pScrn->confScreen->monitor; - /* Allocate an xf86CrtcConfig */ - xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); - xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - + if (!info->drm_mode_setting) { + /* Allocate an xf86CrtcConfig */ + xf86CrtcConfigInit (pScrn, &RADEONCRTCResizeFuncs); + xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + + } if (!RADEONPreInitVisual(pScrn)) goto fail; @@ -2818,136 +2881,197 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) memcpy(info->Options, RADEONOptions, sizeof(RADEONOptions)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); - /* By default, don't do VGA IOs on ppc/sparc */ + if (!info->drm_mode_setting) { + /* By default, don't do VGA IOs on ppc/sparc */ #if defined(__powerpc__) || defined(__sparc__) || !defined(WITH_VGAHW) - info->VGAAccess = FALSE; + info->VGAAccess = FALSE; #else - info->VGAAccess = TRUE; + info->VGAAccess = TRUE; #endif - + #ifdef WITH_VGAHW - xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); - if (info->VGAAccess) { - if (!xf86LoadSubModule(pScrn, "vgahw")) - info->VGAAccess = FALSE; - else { - if (!vgaHWGetHWRec(pScrn)) - info->VGAAccess = FALSE; - } - if (!info->VGAAccess) - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," - " trying to run without it\n"); - } else - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," - " VGA module load skipped\n"); - if (info->VGAAccess) - vgaHWGetIOBase(VGAHWPTR(pScrn)); + xf86GetOptValBool(info->Options, OPTION_VGA_ACCESS, &info->VGAAccess); + if (info->VGAAccess) { + if (!xf86LoadSubModule(pScrn, "vgahw")) + info->VGAAccess = FALSE; + else { + if (!vgaHWGetHWRec(pScrn)) + info->VGAAccess = FALSE; + } + if (!info->VGAAccess) + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Loading VGA module failed," + " trying to run without it\n"); + } else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VGAAccess option set to FALSE," + " VGA module load skipped\n"); + if (info->VGAAccess) + vgaHWGetIOBase(VGAHWPTR(pScrn)); #endif - - + + } + if (!RADEONPreInitWeight(pScrn)) goto fail; - info->DispPriority = 1; - if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { - if (strcmp(s, "AUTO") == 0) { - info->DispPriority = 1; - } else if (strcmp(s, "BIOS") == 0) { - info->DispPriority = 0; - } else if (strcmp(s, "HIGH") == 0) { - info->DispPriority = 2; - } else - info->DispPriority = 1; - } - if (!RADEONPreInitChipType(pScrn)) - goto fail; - - if (!RADEONPreInitInt10(pScrn, &pInt10)) - goto fail; - - RADEONPostInt10Check(pScrn, int10_save); - - if (!RADEONPreInitBIOS(pScrn, pInt10)) - goto fail; + goto fail; + + if (!info->drm_mode_setting) { + info->DispPriority = 1; + if ((s = xf86GetOptValString(info->Options, OPTION_DISP_PRIORITY))) { + if (strcmp(s, "AUTO") == 0) { + info->DispPriority = 1; + } else if (strcmp(s, "BIOS") == 0) { + info->DispPriority = 0; + } else if (strcmp(s, "HIGH") == 0) { + info->DispPriority = 2; + } else + info->DispPriority = 1; + } + + + if (!RADEONPreInitInt10(pScrn, &pInt10)) + goto fail; + + RADEONPostInt10Check(pScrn, int10_save); + if (!RADEONPreInitBIOS(pScrn, pInt10)) + goto fail; #ifdef XF86DRI - /* PreInit DRI first of all since we need that for getting a proper - * memory map - */ - info->directRenderingEnabled = RADEONPreInitDRI(pScrn); + /* PreInit DRI first of all since we need that for getting a proper + * memory map + */ + info->directRenderingEnabled = RADEONPreInitDRI(pScrn); #endif - if (!RADEONPreInitVRAM(pScrn)) - goto fail; - - RADEONPreInitColorTiling(pScrn); - - /* we really need an FB manager... */ - if (pScrn->display->virtualX) { - crtc_max_X = pScrn->display->virtualX; - crtc_max_Y = pScrn->display->virtualY; - if (info->allowColorTiling) { - if (crtc_max_X > info->MaxSurfaceWidth || - crtc_max_Y > info->MaxLines) { - info->allowColorTiling = FALSE; - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n"); + + if (!RADEONPreInitVRAM(pScrn)) + goto fail; + + RADEONPreInitColorTiling(pScrn); + + /* we really need an FB manager... */ + if (pScrn->display->virtualX) { + crtc_max_X = pScrn->display->virtualX; + crtc_max_Y = pScrn->display->virtualY; + if (info->allowColorTiling) { + if (crtc_max_X > info->MaxSurfaceWidth || + crtc_max_Y > info->MaxLines) { + info->allowColorTiling = FALSE; + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Requested desktop size exceeds surface limts for tiling, ColorTiling disabled\n"); + } } - } - if (crtc_max_X > 8192) - crtc_max_X = 8192; - if (crtc_max_Y > 8192) - crtc_max_Y = 8192; - } else { - /* - * note that these aren't really the CRTC limits, they're just - * heuristics until we have a better memory manager. - */ - if (pScrn->videoRam <= 16384) { - crtc_max_X = 1600; - crtc_max_Y = 1200; - } else if (IS_R300_VARIANT) { - crtc_max_X = 2560; - crtc_max_Y = 1200; - } else if (IS_AVIVO_VARIANT) { - crtc_max_X = 2560; - crtc_max_Y = 1600; + if (crtc_max_X > 8192) + crtc_max_X = 8192; + if (crtc_max_Y > 8192) + crtc_max_Y = 8192; } else { - crtc_max_X = 2048; - crtc_max_Y = 1200; + /* + * note that these aren't really the CRTC limits, they're just + * heuristics until we have a better memory manager. + */ + if (pScrn->videoRam <= 16384) { + crtc_max_X = 1600; + crtc_max_Y = 1200; + } else if (IS_R300_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 1200; + } else if (IS_AVIVO_VARIANT) { + crtc_max_X = 2560; + crtc_max_Y = 1600; + } else { + crtc_max_X = 2048; + crtc_max_Y = 1200; } - } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", - crtc_max_X, crtc_max_Y); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "If you are having trouble with 3D, " - "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n"); - + } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Max desktop size set to %dx%d\n", + crtc_max_X, crtc_max_Y); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "For a larger or smaller max desktop size, add a Virtual line to your xorg.conf\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "If you are having trouble with 3D, " + "reduce the desktop size by adjusting the Virtual line to your xorg.conf\n"); + /*xf86CrtcSetSizeRange (pScrn, 320, 200, info->MaxSurfaceWidth, info->MaxLines);*/ - xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + xf86CrtcSetSizeRange (pScrn, 320, 200, crtc_max_X, crtc_max_Y); + + RADEONPreInitDDC(pScrn); - RADEONPreInitDDC(pScrn); + if (!RADEONPreInitControllers(pScrn)) + goto fail; - if (!RADEONPreInitControllers(pScrn)) - goto fail; + ErrorF("before xf86InitialConfiguration\n"); + + if (!xf86InitialConfiguration (pScrn, FALSE)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); + goto fail; + } + + ErrorF("after xf86InitialConfiguration\n"); - ErrorF("before xf86InitialConfiguration\n"); + } else { +#ifdef XF86DRM_MODE + char *bus_id; + if (!radeon_alloc_dri(pScrn)) + return FALSE; - if (!xf86InitialConfiguration (pScrn, FALSE)) - { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n"); - goto fail; - } + bus_id = DRICreatePCIBusID(info->PciInfo); + if (drmmode_pre_init(pScrn, &info->drmmode, bus_id, "radeon", pScrn->bitsPerPixel / 8) == FALSE) { + xfree(bus_id); + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); + goto fail; + } - ErrorF("after xf86InitialConfiguration\n"); + info->drmmode.create_new_fb = radeon_create_new_fb; + info->dri->drmFD = info->drmmode.fd; + xfree(bus_id); + + { + struct drm_radeon_gem_info mminfo; + + if (!drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_INFO, &mminfo, sizeof(mminfo))) + { + info->mm.vram_start = mminfo.vram_start; + info->mm.vram_size = mminfo.vram_visible; + info->mm.gart_start = mminfo.gart_start; + info->mm.gart_size = mminfo.gart_size; + ErrorF("initing %llx %llx %llx %llx %llx\n", mminfo.gart_start, + mminfo.gart_size, mminfo.vram_start, mminfo.vram_size, mminfo.vram_visible); + } + { + struct drm_radeon_getparam gp; + int value; + + memset(&gp, 0, sizeof(gp)); + gp.param = RADEON_PARAM_FB_LOCATION; + gp.value = &value; + + if (drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GETPARAM, &gp, + sizeof(gp)) < 0) { + goto fail; + } + if (info->ChipFamily >= CHIP_FAMILY_R600) + info->fbLocation = (value & 0xffff) << 24; + else + info->fbLocation = (value & 0xffff) << 16; + } + } + if (info->ChipFamily < CHIP_FAMILY_R600) { + info->useEXA = TRUE; + info->directRenderingEnabled = TRUE; + } + info->new_cs = TRUE; + info->drm_mm = TRUE; + // info->directRenderingDisabled = FALSE; +#endif + } RADEONSetPitch(pScrn); - /* Set display resolution */ - xf86SetDpi(pScrn, 0, 0); + /* Set display resolution */ + xf86SetDpi(pScrn, 0, 0); /* Get ScreenInit function */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; @@ -2962,10 +3086,12 @@ Bool RADEONPreInit(ScrnInfoPtr pScrn, int flags) if (!RADEONPreInitXv(pScrn)) goto fail; } - if (!xf86RandR12PreInit (pScrn)) - { - xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); - goto fail; + if (!info->drm_mode_setting) { + if (!xf86RandR12PreInit (pScrn)) + { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RandR initialization failure\n"); + goto fail; + } } if (pScrn->modes == NULL) { @@ -3206,7 +3332,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, int subPixelOrder = SubPixelUnknown; char* s; #endif - + void *front_ptr; info->accelOn = FALSE; #ifdef USE_XAA @@ -3226,52 +3352,55 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, "RADEONScreenInit %lx %ld\n", pScrn->memPhysBase, pScrn->fbOffset); #endif - if (!RADEONMapMem(pScrn)) return FALSE; + + if (!info->drm_mode_setting) { + if (!RADEONMapMem(pScrn)) return FALSE; #ifdef XF86DRI - info->dri->fbX = 0; - info->dri->fbY = 0; + info->dri->fbX = 0; + info->dri->fbY = 0; #endif + + info->PaletteSavedOnVT = FALSE; - info->PaletteSavedOnVT = FALSE; + info->crtc_on = FALSE; + info->crtc2_on = FALSE; - info->crtc_on = FALSE; - info->crtc2_on = FALSE; + RADEONSave(pScrn); - RADEONSave(pScrn); + /* set initial bios scratch reg state */ + RADEONInitBIOSRegisters(pScrn); - /* set initial bios scratch reg state */ - RADEONInitBIOSRegisters(pScrn); + /* blank the outputs/crtcs */ + RADEONBlank(pScrn); - /* blank the outputs/crtcs */ - RADEONBlank(pScrn); + if (info->IsMobility && !IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); + } else { + RADEONSetDynamicClock(pScrn, 0); + } + } else if (IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + atombios_static_pwrmgt_setup(pScrn, 1); + atombios_dyn_clk_setup(pScrn, 1); + } + } + + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); + if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", + info->MaxSurfaceWidth); + info->allowColorTiling = FALSE; } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); + if (info->allowColorTiling) { + info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; } + } - - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); - - if (info->allowColorTiling && (pScrn->virtualX > info->MaxSurfaceWidth)) { - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Color tiling not supported with virtual x resolutions larger than %d, disabling\n", - info->MaxSurfaceWidth); - info->allowColorTiling = FALSE; - } - if (info->allowColorTiling) { - info->tilingEnabled = (pScrn->currentMode->Flags & (V_DBLSCAN | V_INTERLACE)) ? FALSE : TRUE; - } - /* Visual setup */ miClearVisualTypes(); if (!miSetVisualTypes(pScrn->depth, @@ -3305,19 +3434,21 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, hasDRI = info->directRenderingEnabled; #endif /* XF86DRI */ - /* Initialize the memory map, this basically calculates the values - * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION - */ - RADEONInitMemoryMap(pScrn); - - /* empty the surfaces */ - if (info->ChipFamily < CHIP_FAMILY_R600) { - unsigned char *RADEONMMIO = info->MMIO; - unsigned int j; - for (j = 0; j < 8; j++) { - OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); - OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); - OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); + if (!info->drm_mode_setting) { + /* Initialize the memory map, this basically calculates the values + * we'll use later on for MC_FB_LOCATION & MC_AGP_LOCATION + */ + RADEONInitMemoryMap(pScrn); + + /* empty the surfaces */ + if (info->ChipFamily < CHIP_FAMILY_R600) { + unsigned char *RADEONMMIO = info->MMIO; + unsigned int j; + for (j = 0; j < 8; j++) { + OUTREG(RADEON_SURFACE0_INFO + 16 * j, 0); + OUTREG(RADEON_SURFACE0_LOWER_BOUND + 16 * j, 0); + OUTREG(RADEON_SURFACE0_UPPER_BOUND + 16 * j, 0); + } } } @@ -3357,11 +3488,15 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, if (hasDRI) { info->accelDFS = info->cardType != CARD_AGP; + if (info->cardType != CARD_PCIE && info->drm_mm) + info->accelDFS = FALSE; + if (xf86GetOptValInteger(info->Options, OPTION_ACCEL_DFS, &info->accelDFS)) { from = X_CONFIG; } + /* Reserve approx. half of offscreen memory for local textures by * default, can be overridden with Option "FBTexPercent". * Round down to a whole number of texture regions. @@ -3390,7 +3525,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif #if defined(XF86DRI) && defined(USE_XAA) - if (!info->useEXA && hasDRI) { + if (!info->useEXA && hasDRI && !info->drm_mm) { info->dri->textureSize = -1; if (xf86GetOptValInteger(info->Options, OPTION_FBTEX_PERCENT, &(info->dri->textureSize))) { @@ -3408,7 +3543,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, #endif #ifdef USE_XAA - if (!info->useEXA && !hasDRI && !RADEONSetupMemXAA(scrnIndex, pScreen)) + if (!info->useEXA && !hasDRI && !info->drm_mm && !RADEONSetupMemXAA(scrnIndex, pScreen)) return FALSE; #endif @@ -3429,7 +3564,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->CurrentLayout.pixel_bytes); int maxy = info->FbMapSize / width_bytes; - if (maxy <= pScrn->virtualY * 3) { + if (maxy <= pScrn->virtualY * 3 && !info->drm_mm) { xf86DrvMsg(scrnIndex, X_ERROR, "Static buffer allocation failed. Disabling DRI.\n"); xf86DrvMsg(scrnIndex, X_ERROR, @@ -3443,15 +3578,41 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, } } - /* Tell DRI about new memory map */ - if (info->directRenderingEnabled && info->dri->newMemoryMap) { - if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { + front_ptr = info->FB; + if (info->drm_mm) { + if (info->directRenderingEnabled && info->dri->newMemoryMap) { + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "[drm] failed to enable new memory map\n"); + RADEONDRICloseScreen(pScreen); + info->directRenderingEnabled = FALSE; + } + } + info->bufmgr = radeon_bufmgr_gem_init(info->dri->drmFD); + drmmode_set_bufmgr(pScrn, &info->drmmode, info->bufmgr); + //radeon_bufmgr_gem_enable_reuse(info->bufmgr); + radeon_bufmgr_gem_set_limit(info->bufmgr, RADEON_GEM_DOMAIN_GTT, info->mm.gart_size - info->dri->gartTexMapSize); + + radeon_setup_kernel_mem(pScreen); + front_ptr = info->mm.front_buffer->map; + pScrn->fbOffset = info->mm.front_buffer->offset; + info->accel_state->dst_pitch_offset = (((pScrn->displayWidth * info->CurrentLayout.pixel_bytes / 64) + << 22) | ((info->fbLocation + pScrn->fbOffset) >> 10)); + } else { + + /* Tell DRI about new memory map */ + if (info->directRenderingEnabled && info->dri->newMemoryMap) { + if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_NEW_MEMMAP, 1) < 0) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "[drm] failed to enable new memory map\n"); RADEONDRICloseScreen(pScreen); info->directRenderingEnabled = FALSE; + } } } + + RADEONDRIDoMappings(pScreen); + #endif xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing fb layer\n"); @@ -3475,7 +3636,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, if (info->r600_shadow_fb == FALSE) { /* Init fb layer */ - if (!fbScreenInit(pScreen, info->FB, + if (!fbScreenInit(pScreen, front_ptr, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel)) @@ -3517,8 +3678,10 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* restore the memory map here otherwise we may get a hang when * initializing the drm below */ - RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); - RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); + if (!info->drm_mode_setting) { + RADEONInitMemMapRegisters(pScrn, info->ModeReg, info); + RADEONRestoreMemMapRegisters(pScrn, info->ModeReg); + } /* Backing store setup */ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -3528,7 +3691,7 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, /* DRI finalisation */ #ifdef XF86DRI - if (info->directRenderingEnabled && info->cardType==CARD_PCIE && + if (!info->drm_mm && info->directRenderingEnabled && info->cardType==CARD_PCIE && info->dri->pKernelDRMVersion->version_minor >= 19) { if (RADEONDRISetParam(pScrn, RADEON_SETPARAM_PCIGART_LOCATION, info->dri->pciGartOffset) < 0) @@ -3547,11 +3710,17 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, info->directRenderingEnabled = RADEONDRIFinishScreenInit(pScreen); } if (info->directRenderingEnabled) { + + if (info->drm_mm) + radeon_update_dri_buffers(pScreen); + /* DRI final init might have changed the memory map, we need to adjust * our local image to make sure we restore them properly on mode * changes or VT switches */ - RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + if (!info->drm_mode_setting) { + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n"); @@ -3649,10 +3818,16 @@ Bool RADEONScreenInit(int scrnIndex, ScreenPtr pScreen, return FALSE; } } + pScrn->pScreen = pScreen; /* set the modes with desired rotation, etc. */ - if (!xf86SetDesiredModes (pScrn)) + if (info->drm_mode_setting) { + if (!drmmode_set_desired_modes(pScrn, &info->drmmode)) return FALSE; + } else { + if (!xf86SetDesiredModes (pScrn)) + return FALSE; + } /* Provide SaveScreen & wrap BlockHandler and CloseScreen */ /* Wrap CloseScreen */ @@ -5133,7 +5308,7 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #ifdef XF86DRI Bool CPStarted = info->cp->CPStarted; - if (CPStarted) { + if (CPStarted && !info->drm_mode_setting) { DRILock(pScrn->pScreen, 0); RADEONCP_STOP(pScrn, info); } @@ -5156,8 +5331,10 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) #endif } - if (info->accelOn) - RADEON_SYNC(info, pScrn); + if (!info->drm_mode_setting) { + if (info->accelOn) + RADEON_SYNC(info, pScrn); + } ret = xf86SetSingleMode (pScrn, mode, RR_Rotate_0); @@ -5169,15 +5346,18 @@ Bool RADEONSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) /* xf86SetRootClip would do, but can't access that here */ } - if (info->accelOn) { - RADEON_SYNC(info, pScrn); - RADEONEngineRestore(pScrn); - } + if (!info->drm_mode_setting) + if (info->accelOn) { + RADEON_SYNC(info, pScrn); + RADEONEngineRestore(pScrn); + } #ifdef XF86DRI - if (CPStarted) { - RADEONCP_START(pScrn, info); - DRIUnlock(pScrn->pScreen); + if (!info->drm_mode_setting) { + if (CPStarted) { + RADEONCP_START(pScrn, info); + DRIUnlock(pScrn->pScreen); + } } #endif @@ -5375,6 +5555,11 @@ void RADEONAdjustFrame(int scrnIndex, int x, int y, int flags) xf86OutputPtr output = config->output[config->compat_output]; xf86CrtcPtr crtc = output->crtc; + if (info->drm_mode_setting) { + drmmode_adjust_frame(pScrn, &info->drmmode, x, y, flags); + return; + } + #ifdef XF86DRI if (info->cp->CPStarted && pScrn->pScreen) DRILock(pScrn->pScreen, 0); #endif @@ -5410,67 +5595,84 @@ Bool RADEONEnterVT(int scrnIndex, int flags) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONEnterVT\n"); - if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */ - if (info->IsAtomBios) { - rhdAtomASICInit(info->atomBIOS); - } else { - xf86Int10InfoPtr pInt; + if (!info->drm_mode_setting) { + if (!radeon_card_posted(pScrn)) { /* Softboot V_BIOS */ + if (info->IsAtomBios) { + rhdAtomASICInit(info->atomBIOS); + } else { + xf86Int10InfoPtr pInt; + + pInt = xf86InitInt10 (info->pEnt->index); + if (pInt) { + pInt->num = 0xe6; + xf86ExecX86int10 (pInt); + xf86FreeInt10 (pInt); + } else { + RADEONGetBIOSInitTableOffsets(pScrn); + RADEONPostCardFromBIOSTables(pScrn); + } + } + } + /* Makes sure the engine is idle before doing anything */ + RADEONWaitForIdleMMIO(pScrn); - pInt = xf86InitInt10 (info->pEnt->index); - if (pInt) { - pInt->num = 0xe6; - xf86ExecX86int10 (pInt); - xf86FreeInt10 (pInt); + if (info->IsMobility && !IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + RADEONSetDynamicClock(pScrn, 1); } else { - RADEONGetBIOSInitTableOffsets(pScrn); - RADEONPostCardFromBIOSTables(pScrn); + RADEONSetDynamicClock(pScrn, 0); + } + } else if (IS_AVIVO_VARIANT) { + if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { + atombios_static_pwrmgt_setup(pScrn, 1); + atombios_dyn_clk_setup(pScrn, 1); } } - } - - /* Makes sure the engine is idle before doing anything */ - RADEONWaitForIdleMMIO(pScrn); + + if (IS_R300_VARIANT || IS_RV100_VARIANT) + RADEONForceSomeClocks(pScrn); - if (info->IsMobility && !IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - RADEONSetDynamicClock(pScrn, 1); - } else { - RADEONSetDynamicClock(pScrn, 0); - } - } else if (IS_AVIVO_VARIANT) { - if (xf86ReturnOptValBool(info->Options, OPTION_DYNAMIC_CLOCKS, FALSE)) { - atombios_static_pwrmgt_setup(pScrn, 1); - atombios_dyn_clk_setup(pScrn, 1); - } } - if (IS_R300_VARIANT || IS_RV100_VARIANT) - RADEONForceSomeClocks(pScrn); + if (info->drm_mm) { + radeon_bind_all_memory(pScrn); + info->accel_state->XInited3D = FALSE; + info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; + } - for (i = 0; i < config->num_crtc; i++) - radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); + radeon_update_dri_buffers(pScrn->pScreen); pScrn->vtSema = TRUE; - if (!xf86SetDesiredModes(pScrn)) + if (!info->drm_mode_setting) + for (i = 0; i < config->num_crtc; i++) + radeon_crtc_modeset_ioctl(config->crtc[i], TRUE); + + if (info->drm_mode_setting) { + if (!drmmode_set_desired_modes(pScrn, &info->drmmode)) + return FALSE; + } else { + if (!xf86SetDesiredModes(pScrn)) return FALSE; + } - if (info->ChipFamily < CHIP_FAMILY_R600) - RADEONRestoreSurfaces(pScrn, info->ModeReg); + if (!info->drm_mode_setting) { + if (info->ChipFamily < CHIP_FAMILY_R600) + RADEONRestoreSurfaces(pScrn, info->ModeReg); #ifdef XF86DRI - if (info->directRenderingEnabled) { - if (info->cardType == CARD_PCIE && - info->dri->pKernelDRMVersion->version_minor >= 19 && - info->FbSecureSize) { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->FB + info->dri->pciGartOffset, info->dri->pciGartBackup, info->dri->pciGartSize); - } - - /* get the DRI back into shape after resume */ - RADEONDRISetVBlankInterrupt (pScrn, TRUE); - RADEONDRIResume(pScrn->pScreen); - RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + if (info->directRenderingEnabled) { + if (info->cardType == CARD_PCIE && + info->dri->pKernelDRMVersion->version_minor >= 19 && + info->FbSecureSize) { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->FB + info->dri->pciGartOffset, info->dri->pciGartBackup, info->dri->pciGartSize); + } + /* get the DRI back into shape after resume */ + RADEONDRISetVBlankInterrupt (pScrn, TRUE); + RADEONDRIResume(pScrn->pScreen); + RADEONAdjustMemMapRegisters(pScrn, info->ModeReg); + } } #endif /* this will get XVideo going again, but only if XVideo was initialised @@ -5482,7 +5684,7 @@ Bool RADEONEnterVT(int scrnIndex, int flags) RADEONEngineRestore(pScrn); #ifdef XF86DRI - if (info->directRenderingEnabled) { + if (info->directRenderingEnabled && !info->drm_mode_setting) { RADEONCP_START(pScrn, info); DRIUnlock(pScrn->pScreen); } @@ -5505,17 +5707,18 @@ void RADEONLeaveVT(int scrnIndex, int flags) "RADEONLeaveVT\n"); #ifdef XF86DRI if (RADEONPTR(pScrn)->directRenderingInited) { - - RADEONDRISetVBlankInterrupt (pScrn, FALSE); - DRILock(pScrn->pScreen, 0); - RADEONCP_STOP(pScrn, info); - - if (info->cardType == CARD_PCIE && - info->dri->pKernelDRMVersion->version_minor >= 19 && - info->FbSecureSize) { - /* we need to backup the PCIE GART TABLE from fb memory */ - memcpy(info->dri->pciGartBackup, (info->FB + info->dri->pciGartOffset), info->dri->pciGartSize); - } + if (!info->drm_mode_setting) { + RADEONDRISetVBlankInterrupt (pScrn, FALSE); + DRILock(pScrn->pScreen, 0); + RADEONCP_STOP(pScrn, info); + + if (info->cardType == CARD_PCIE && + info->dri->pKernelDRMVersion->version_minor >= 19 && + info->FbSecureSize) { + /* we need to backup the PCIE GART TABLE from fb memory */ + memcpy(info->dri->pciGartBackup, (info->FB + info->dri->pciGartOffset), info->dri->pciGartSize); + } + } /* Make sure 3D clients will re-upload textures to video RAM */ if (info->dri->textureSize) { @@ -5551,10 +5754,15 @@ void RADEONLeaveVT(int scrnIndex, int flags) xf86_hide_cursors (pScrn); - RADEONRestore(pScrn); + if (info->drm_mm) + radeon_unbind_all_memory(pScrn); + + if (!info->drm_mode_setting) { + RADEONRestore(pScrn); - for (i = 0; i < config->num_crtc; i++) - radeon_crtc_modeset_ioctl(config->crtc[i], FALSE); + for (i = 0; i < config->num_crtc; i++) + radeon_crtc_modeset_ioctl(config->crtc[i], FALSE); + } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Ok, leaving now...\n"); @@ -5599,7 +5807,8 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) #endif /* USE_XAA */ if (pScrn->vtSema) { - RADEONRestore(pScrn); + if (!info->drm_mode_setting) + RADEONRestore(pScrn); } xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, @@ -5634,6 +5843,12 @@ static Bool RADEONCloseScreen(int scrnIndex, ScreenPtr pScreen) info->DGAModes = NULL; xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Unmapping memory\n"); + + if (info->drm_mm) { + radeon_unbind_all_memory(pScrn); + radeon_free_all_memory(pScrn); + } + RADEONUnmapMem(pScrn); pScrn->vtSema = FALSE; diff --git a/src/radeon_drm.h b/src/radeon_drm.h index 66cefb7..af7d382 100644 --- a/src/radeon_drm.h +++ b/src/radeon_drm.h @@ -303,7 +303,6 @@ typedef union { #define RADEON_INDEX_PRIM_OFFSET 20 #define RADEON_SCRATCH_REG_OFFSET 32 -#define R600_SCRATCH_REG_OFFSET 256 #define RADEON_NR_SAREA_CLIPRECTS 12 @@ -454,6 +453,15 @@ typedef struct { int pfCurrentPage; /* which buffer is being displayed? */ int crtc2_base; /* CRTC2 frame offset */ int tiling_enabled; /* set by drm, read by 2d + 3d clients */ + + unsigned int last_fence; + + uint32_t front_handle; + uint32_t back_handle; + uint32_t depth_handle; + uint32_t front_pitch; + uint32_t back_pitch; + uint32_t depth_pitch; } drm_radeon_sarea_t; /* WARNING: If you change any of these defines, make sure to change the @@ -494,6 +502,19 @@ typedef struct { #define DRM_RADEON_SURF_ALLOC 0x1a #define DRM_RADEON_SURF_FREE 0x1b +#define DRM_RADEON_GEM_INFO 0x1c +#define DRM_RADEON_GEM_CREATE 0x1d +#define DRM_RADEON_GEM_MMAP 0x1e +#define DRM_RADEON_GEM_PIN 0x1f +#define DRM_RADEON_GEM_UNPIN 0x20 +#define DRM_RADEON_GEM_PREAD 0x21 +#define DRM_RADEON_GEM_PWRITE 0x22 +#define DRM_RADEON_GEM_SET_DOMAIN 0x23 +#define DRM_RADEON_GEM_WAIT_RENDERING 0x24 + +#define DRM_RADEON_CS 0x25 +#define DRM_RADEON_CS2 0x26 + #define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t) #define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START) #define DRM_IOCTL_RADEON_CP_STOP DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_STOP, drm_radeon_cp_stop_t) @@ -522,16 +543,28 @@ typedef struct { #define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t) #define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t) +#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info) +#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create) +#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap) +#define DRM_IOCTL_RADEON_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PIN, struct drm_radeon_gem_pin) +#define DRM_IOCTL_RADEON_GEM_UNPIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_UNPIN, struct drm_radeon_gem_unpin) +#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread) +#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite) +#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain) +#define DRM_IOCTL_RADEON_GEM_WAIT_RENDERING DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_RENDERING, struct drm_radeon_gem_wait_rendering) +#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs) +#define DRM_IOCTL_RADEON_CS2 DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS2, struct drm_radeon_cs2) + + typedef struct drm_radeon_init { enum { RADEON_INIT_CP = 0x01, RADEON_CLEANUP_CP = 0x02, RADEON_INIT_R200_CP = 0x03, - RADEON_INIT_R300_CP = 0x04, - RADEON_INIT_R600_CP = 0x05, + RADEON_INIT_R300_CP = 0x04 } func; unsigned long sarea_priv_offset; - int is_pci; /* for overriding only */ + int is_pci; int cp_mode; int gart_size; int ring_size; @@ -543,9 +576,8 @@ typedef struct drm_radeon_init { unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; - /* DEPRECATED commented out below to allow for -Werror build */ - unsigned long fb_offset /*DEPRECATED*/; /* deprecated, driver asks hardware */ - unsigned long mmio_offset /*DEPRECATED*/; /* deprecated, driver asks hardware */ + unsigned long fb_offset; + unsigned long mmio_offset; unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; @@ -581,7 +613,7 @@ typedef struct drm_radeon_clear { unsigned int clear_depth; unsigned int color_mask; unsigned int depth_mask; /* misnamed field: should be stencil */ - drm_radeon_clear_rect_t __user *depth_boxes; + drm_radeon_clear_rect_t *depth_boxes; } drm_radeon_clear_t; typedef struct drm_radeon_vertex { @@ -607,9 +639,9 @@ typedef struct drm_radeon_vertex2 { int idx; /* Index of vertex buffer */ int discard; /* Client finished with buffer? */ int nr_states; - drm_radeon_state_t __user *state; + drm_radeon_state_t *state; int nr_prims; - drm_radeon_prim_t __user *prim; + drm_radeon_prim_t *prim; } drm_radeon_vertex2_t; /* v1.3 - obsoletes drm_radeon_vertex2 @@ -624,15 +656,15 @@ typedef struct drm_radeon_vertex2 { */ typedef struct drm_radeon_cmd_buffer { int bufsz; - char __user *buf; + char *buf; int nbox; - struct drm_clip_rect __user *boxes; + struct drm_clip_rect *boxes; } drm_radeon_cmd_buffer_t; typedef struct drm_radeon_tex_image { unsigned int x, y; /* Blit coordinates */ unsigned int width, height; - const void __user *data; + const void *data; } drm_radeon_tex_image_t; typedef struct drm_radeon_texture { @@ -641,11 +673,11 @@ typedef struct drm_radeon_texture { int format; int width; /* Texture image coordinates */ int height; - drm_radeon_tex_image_t __user *image; + drm_radeon_tex_image_t *image; } drm_radeon_texture_t; typedef struct drm_radeon_stipple { - unsigned int __user *mask; + unsigned int *mask; } drm_radeon_stipple_t; typedef struct drm_radeon_indirect { @@ -655,9 +687,6 @@ typedef struct drm_radeon_indirect { int discard; } drm_radeon_indirect_t; -#define RADEON_INDIRECT_DISCARD (1 << 0) -#define RADEON_INDIRECT_NOFLUSH (1 << 1) - /* enum for card type parameters */ #define RADEON_CARD_PCI 0 #define RADEON_CARD_AGP 1 @@ -683,10 +712,11 @@ typedef struct drm_radeon_indirect { #define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */ #define RADEON_PARAM_FB_LOCATION 14 /* FB location */ #define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */ +#define RADEON_PARAM_KERNEL_MM 16 typedef struct drm_radeon_getparam { int param; - void __user *value; + void *value; } drm_radeon_getparam_t; /* 1.6: Set up a memory manager for regions of shared memory: @@ -698,7 +728,7 @@ typedef struct drm_radeon_mem_alloc { int region; int alignment; int size; - int __user *region_offset; /* offset from start of fb or GART */ + int *region_offset; /* offset from start of fb or GART */ } drm_radeon_mem_alloc_t; typedef struct drm_radeon_mem_free { @@ -715,7 +745,7 @@ typedef struct drm_radeon_mem_init_heap { /* 1.6: Userspace can request & wait on irq's: */ typedef struct drm_radeon_irq_emit { - int __user *irq_seq; + int *irq_seq; } drm_radeon_irq_emit_t; typedef struct drm_radeon_irq_wait { @@ -734,10 +764,10 @@ typedef struct drm_radeon_setparam { #define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */ #define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */ #define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */ - #define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */ #define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */ #define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */ +#define RADEON_SETPARAM_MM_INIT 7 /* DDX wants memory manager but has no modesetting */ /* 1.14: Clients can allocate/free a surface */ typedef struct drm_radeon_surface_alloc { @@ -753,4 +783,114 @@ typedef struct drm_radeon_surface_free { #define DRM_RADEON_VBLANK_CRTC1 1 #define DRM_RADEON_VBLANK_CRTC2 2 +#define RADEON_GEM_DOMAIN_CPU 0x1 // Cached CPU domain +#define RADEON_GEM_DOMAIN_GTT 0x2 // GTT or cache flushed +#define RADEON_GEM_DOMAIN_VRAM 0x4 // VRAM domain + +/* return to userspace start/size of gtt and vram apertures */ +struct drm_radeon_gem_info { + uint64_t gart_start; + uint64_t gart_size; + uint64_t vram_start; + uint64_t vram_size; + uint64_t vram_visible; +}; + +struct drm_radeon_gem_create { + uint64_t size; + uint64_t alignment; + uint32_t handle; + uint32_t initial_domain; // to allow VRAM to be created + uint32_t no_backing_store; // for VRAM objects - select whether they need backing store + // pretty much front/back/depth don't need it - other things do +}; + +struct drm_radeon_gem_mmap { + uint32_t handle; + uint32_t pad; + uint64_t offset; + uint64_t size; + uint64_t addr_ptr; +}; + +struct drm_radeon_gem_set_domain { + uint32_t handle; + uint32_t read_domains; + uint32_t write_domain; +}; + +struct drm_radeon_gem_wait_rendering { + uint32_t handle; +}; + +struct drm_radeon_gem_pin { + uint32_t handle; + uint32_t pin_domain; + uint64_t alignment; + uint64_t offset; +}; + +struct drm_radeon_gem_unpin { + uint32_t handle; + uint32_t pad; +}; + +struct drm_radeon_gem_busy { + uint32_t handle; + uint32_t busy; +}; + +struct drm_radeon_gem_pread { + /** Handle for the object being read. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to read from */ + uint64_t offset; + /** Length of data to read */ + uint64_t size; + /** Pointer to write the data into. */ + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ +}; + +struct drm_radeon_gem_pwrite { + /** Handle for the object being written to. */ + uint32_t handle; + uint32_t pad; + /** Offset into the object to write to */ + uint64_t offset; + /** Length of data to write */ + uint64_t size; + /** Pointer to read the data from. */ + uint64_t data_ptr; /* void *, but pointers are not 32/64 compatible */ +}; + + +/* New interface which obsolete all previous interface. + */ + + +struct drm_radeon_cs { + uint32_t dwords; + uint32_t cs_id; + uint64_t packets; +}; + +#define RADEON_CHUNK_ID_RELOCS 0x01 +#define RADEON_CHUNK_ID_IB 0x02 +#define RADEON_CHUNK_ID_OLD 0xff + +struct drm_radeon_cs_chunk { + uint32_t chunk_id; + uint32_t length_dw; + uint64_t chunk_data; +}; + +struct drm_radeon_cs2 { + uint32_t num_chunks; + uint32_t cs_id; + uint64_t chunks; /* this points to uint64_t * which point to + cs chunks */ +}; + + #endif diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 0f86fdd..f0d1f48 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -43,7 +43,11 @@ #include "radeon_version.h" #include "xf86.h" +#include "radeon_bufmgr_gem.h" +#define RADEON_PIXMAP_IS_FRONTBUFFER 1 + +/* quick hacks lolz */ /***********************************************************************/ #define RINFO_FROM_SCREEN(pScr) ScrnInfoPtr pScrn = xf86Screens[pScr->myNum]; \ @@ -181,14 +185,23 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) RINFO_FROM_SCREEN(pPix->drawable.pScreen); uint32_t pitch, offset; int bpp; + struct radeon_exa_pixmap_priv *driver_priv; bpp = pPix->drawable.bitsPerPixel; if (bpp == 24) bpp = 8; - offset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; - pitch = exaGetPixmapPitch(pPix); + /* validate the pixmap somewhere */ + if (info->new_cs) + offset = 0; + else { + + offset = exaGetPixmapOffset(pPix); + + offset += info->fbLocation + pScrn->fbOffset; + } + pitch = exaGetPixmapPitch(pPix); return RADEONGetOffsetPitch(pPix, bpp, pitch_offset, offset, pitch); } @@ -196,6 +209,8 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) static unsigned long swapper_surfaces[3]; +#endif + static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) { RINFO_FROM_SCREEN(pPix->drawable.pScreen); @@ -203,7 +218,31 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) uint32_t offset = exaGetPixmapOffset(pPix); int bpp, soff; uint32_t size, flags; + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv) { + + if (driver_priv->bo) { + int ret; + + if (radeon_bufmgr_gem_has_references(driver_priv->bo)) + RADEONCPFlushIndirect(pScrn, 0); + + radeon_bufmgr_gem_wait_rendering(driver_priv->bo); + + /* flush IB */ + ret = dri_bo_map(driver_priv->bo, 1); + if (ret) { + FatalError("failed to map pixmap %d\n", ret); + return FALSE; + } + + 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) return TRUE; @@ -259,6 +298,7 @@ static Bool RADEONPrepareAccess(PixmapPtr pPix, int index) OUTREG(RADEON_SURFACE0_LOWER_BOUND + soff, offset); OUTREG(RADEON_SURFACE0_UPPER_BOUND + soff, offset + size - 1); swapper_surfaces[index] = offset; +#endif return TRUE; } @@ -268,7 +308,17 @@ static void RADEONFinishAccess(PixmapPtr pPix, int index) unsigned char *RADEONMMIO = info->MMIO; uint32_t offset = exaGetPixmapOffset(pPix); int soff; + 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; @@ -291,14 +341,97 @@ 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; +#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ } -#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ +void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *new_priv; + + new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv)); + if (!new_priv) + return NULL; + + if (size == 0) + return new_priv; + + new_priv->bo = dri_bo_alloc(info->bufmgr, "exa pixmap", size, + align, 0); + if (!new_priv->bo) { + xfree(new_priv); + ErrorF("Failed to alloc memory\n"); + return NULL; + } + + return new_priv; + +} + +static void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *driver_priv = driverPriv; + int ret; + + dri_bo_unreference(driver_priv->bo); + xfree(driverPriv); +} + +static Bool RADEONEXAModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, + int depth, int bitsPerPixel, int devKind, + pointer pPixData) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPixmap); + if (!driver_priv) + return FALSE; + + + if (info->drm_mode_setting && drmmode_is_rotate_pixmap(pScrn, pPixData, &driver_priv->bo)){ + dri_bo_unmap(driver_priv->bo); + dri_bo_reference(driver_priv->bo); + miModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, NULL); + + return TRUE; + } + + if (pPixData == info->mm.front_buffer->map) { + driver_priv->flags |= RADEON_PIXMAP_IS_FRONTBUFFER; + + driver_priv->bo = radeon_bo_gem_create_from_name(info->bufmgr, "front", + radeon_name_buffer(pScrn, info->mm.front_buffer)); + + miModifyPixmapHeader(pPixmap, width, height, depth, + bitsPerPixel, devKind, NULL); + return TRUE; + } + return FALSE; +} + +static Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix) +{ + struct radeon_exa_pixmap_priv *driver_priv; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + + if (!driver_priv) + return FALSE; + if (driver_priv->bo) + return TRUE; + return FALSE; +} #define RADEON_SWITCH_TO_2D() \ do { \ - uint32_t wait_until = 0; \ - BEGIN_ACCEL(1); \ + uint32_t wait_until = 0; \ switch (info->accel_state->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ wait_until |= RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_2D_IDLECLEAN; \ @@ -307,15 +440,17 @@ do { \ case EXA_ENGINEMODE_2D: \ break; \ } \ - OUT_ACCEL_REG(RADEON_WAIT_UNTIL, wait_until); \ - FINISH_ACCEL(); \ + if (wait_until) { \ + BEGIN_ACCEL(1); \ + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, wait_until); \ + FINISH_ACCEL(); \ + } \ info->accel_state->engineMode = EXA_ENGINEMODE_2D; \ } while (0); #define RADEON_SWITCH_TO_3D() \ do { \ - uint32_t wait_until = 0; \ - BEGIN_ACCEL(1); \ + uint32_t wait_until = 0; \ switch (info->accel_state->engineMode) { \ case EXA_ENGINEMODE_UNKNOWN: \ wait_until |= RADEON_WAIT_HOST_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN; \ @@ -324,8 +459,11 @@ do { \ case EXA_ENGINEMODE_3D: \ break; \ } \ - OUT_ACCEL_REG(RADEON_WAIT_UNTIL, wait_until); \ - FINISH_ACCEL(); \ + if (wait_until) { \ + BEGIN_ACCEL(1); \ + OUT_ACCEL_REG(RADEON_WAIT_UNTIL, wait_until); \ + FINISH_ACCEL(); \ + } \ info->accel_state->engineMode = EXA_ENGINEMODE_3D; \ } while (0); @@ -338,6 +476,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, read, write) do {} while(0) #define FINISH_ACCEL() #ifdef RENDER @@ -351,6 +490,7 @@ do { \ #undef OUT_ACCEL_REG #undef OUT_ACCEL_REG_F #undef FINISH_ACCEL +#undef OUT_RELOC #ifdef XF86DRI @@ -361,6 +501,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, read, write) OUT_RING_RELOC(x, read, write) #define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) @@ -378,6 +519,8 @@ do { \ #endif /* XF86DRI */ + + /* * Once screen->off_screen_base is set, this function * allocates the remaining memory appropriately @@ -399,122 +542,126 @@ Bool RADEONSetupMemEXA (ScreenPtr pScreen) if (info->accel_state->exa == NULL) return FALSE; - /* Need to adjust screen size for 16 line tiles, and then make it align to. - * the buffer alignment requirement. - */ - if (info->allowColorTiling) - screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; - else - screen_size = pScrn->virtualY * byteStride; - - info->accel_state->exa->memoryBase = info->FB; - info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; - info->accel_state->exa->offScreenBase = screen_size; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", - info->accel_state->exa->memorySize / 1024); - - /* Reserve static area for hardware cursor */ - if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { - int cursor_size = 64 * 4 * 64; - int align = IS_AVIVO_VARIANT ? 4096 : 256; - int c; - - for (c = 0; c < xf86_config->num_crtc; c++) { - xf86CrtcPtr crtc = xf86_config->crtc[c]; - RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; - - radeon_crtc->cursor_offset = - RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); - info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for hardware cursor %d at offset 0x%08x\n", - (cursor_size * xf86_config->num_crtc) / 1024, - c, - (unsigned int)radeon_crtc->cursor_offset); - } - } - -#if defined(XF86DRI) - if (info->directRenderingEnabled) { - int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; - - info->dri->frontOffset = 0; - info->dri->frontPitch = pScrn->displayWidth; - - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for front buffer at offset 0x%08x\n", - screen_size / 1024, info->dri->frontOffset); - RADEONDRIAllocatePCIGARTTable(pScreen); - - if (info->cardType==CARD_PCIE) - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for PCI GART at offset 0x%08x\n", - info->dri->pciGartSize / 1024, - (int)info->dri->pciGartOffset); - - /* Reserve a static area for the back buffer the same size as the - * visible screen. XXX: This would be better initialized in ati_dri.c - * 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->dri->backPitch = pScrn->displayWidth; - next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN); - if (!info->dri->noBackBuffer && - next + screen_size <= info->accel_state->exa->memorySize) - { - info->dri->backOffset = next; - info->accel_state->exa->offScreenBase = next + screen_size; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for back buffer at offset 0x%08x\n", - screen_size / 1024, info->dri->backOffset); + if (info->allowColorTiling) + screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * byteStride; + else + screen_size = pScrn->virtualY * byteStride; + + info->accel_state->exa->memoryBase = info->FB; + info->accel_state->exa->memorySize = info->FbMapSize - info->FbSecureSize; + info->accel_state->exa->offScreenBase = screen_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Allocating from a screen of %ld kb\n", + info->accel_state->exa->memorySize / 1024); + + /* Reserve static area for hardware cursor */ + if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { + int cursor_size = 64 * 4 * 64; + int align = IS_AVIVO_VARIANT ? 4096 : 256; + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + + radeon_crtc->cursor_offset = + RADEON_ALIGN(info->accel_state->exa->offScreenBase, align); + info->accel_state->exa->offScreenBase = radeon_crtc->cursor_offset + cursor_size; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for hardware cursor %d at offset 0x%08x\n", + (cursor_size * xf86_config->num_crtc) / 1024, + c, + (unsigned int)radeon_crtc->cursor_offset); + } } - /* Reserve the static depth buffer, and adjust pitch and height to - * handle tiling. - */ - info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); - depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; - next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN); - if (next + depth_size <= info->accel_state->exa->memorySize) - { - info->dri->depthOffset = next; - info->accel_state->exa->offScreenBase = next + depth_size; +#if defined(XF86DRI) + if (info->directRenderingEnabled) { + int depthCpp = (info->dri->depthBits - 8) / 4, l, next, depth_size; + + info->dri->frontOffset = 0; + info->dri->frontPitch = pScrn->displayWidth; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for depth buffer at offset 0x%08x\n", - depth_size / 1024, info->dri->depthOffset); - } + "Will use %d kb for front buffer at offset 0x%08x\n", + screen_size / 1024, info->dri->frontOffset); + RADEONDRIAllocatePCIGARTTable(pScreen); + + if (info->cardType==CARD_PCIE) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for PCI GART at offset 0x%08x\n", + info->dri->pciGartSize / 1024, + (int)info->dri->pciGartOffset); + + /* Reserve a static area for the back buffer the same size as the + * visible screen. XXX: This would be better initialized in ati_dri.c + * 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. + */ + info->dri->backPitch = pScrn->displayWidth; + next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN); + if (!info->dri->noBackBuffer && + next + screen_size <= info->accel_state->exa->memorySize) + { + info->dri->backOffset = next; + info->accel_state->exa->offScreenBase = next + screen_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for back buffer at offset 0x%08x\n", + screen_size / 1024, info->dri->backOffset); + } + + /* Reserve the static depth buffer, and adjust pitch and height to + * handle tiling. + */ + info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); + depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; + next = RADEON_ALIGN(info->accel_state->exa->offScreenBase, RADEON_BUFFER_ALIGN); + if (next + depth_size <= info->accel_state->exa->memorySize) + { + info->dri->depthOffset = next; + info->accel_state->exa->offScreenBase = next + depth_size; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for depth buffer at offset 0x%08x\n", + depth_size / 1024, info->dri->depthOffset); + } - info->dri->textureSize *= (info->accel_state->exa->memorySize - - info->accel_state->exa->offScreenBase) / 100; - - l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) - l = RADEON_LOG_TEX_GRANULARITY; - info->dri->textureSize = (info->dri->textureSize >> l) << l; - if (info->dri->textureSize >= 512 * 1024) { - info->dri->textureOffset = info->accel_state->exa->offScreenBase; - info->accel_state->exa->offScreenBase += info->dri->textureSize; - xf86DrvMsg(pScrn->scrnIndex, X_INFO, - "Will use %d kb for textures at offset 0x%08x\n", - info->dri->textureSize / 1024, info->dri->textureOffset); - } else { - /* Minimum texture size is for 2 256x256x32bpp textures */ - info->dri->textureSize = 0; - } - } else + info->dri->textureSize *= (info->accel_state->exa->memorySize - + info->accel_state->exa->offScreenBase) / 100; + + l = RADEONLog2(info->dri->textureSize / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) + l = RADEON_LOG_TEX_GRANULARITY; + info->dri->textureSize = (info->dri->textureSize >> l) << l; + if (info->dri->textureSize >= 512 * 1024) { + info->dri->textureOffset = info->accel_state->exa->offScreenBase; + info->accel_state->exa->offScreenBase += info->dri->textureSize; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "Will use %d kb for textures at offset 0x%08x\n", + info->dri->textureSize / 1024, info->dri->textureOffset); + } else { + /* Minimum texture size is for 2 256x256x32bpp textures */ + info->dri->textureSize = 0; + } + } else #endif /* XF86DRI */ - xf86DrvMsg(pScrn->scrnIndex, X_INFO, + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use %d kb for front buffer at offset 0x%08x\n", screen_size / 1024, 0); - + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Will use %ld kb for X Server offscreen at offset 0x%08lx\n", (info->accel_state->exa->memorySize - info->accel_state->exa->offScreenBase) / 1024, info->accel_state->exa->offScreenBase); + } + return TRUE; } @@ -527,10 +674,21 @@ extern void ExaOffscreenMarkUsed(PixmapPtr); unsigned long long RADEONTexOffsetStart(PixmapPtr pPix) { - exaMoveInPixmap(pPix); + struct radeon_exa_pixmap_priv *driver_priv; + uint32_t offset; + driver_priv = exaGetPixmapDriverPrivate(pPix); + + if (driver_priv) { + //offset = dri_bo_get_handle(driver_priv->bo); + offset = driver_priv->bo->offset; + + } else { + exaMoveInPixmap(pPix); + offset = exaGetPixmapOffset(pPix); + offset += RADEONPTR(xf86Screens[pPix->drawable.pScreen->myNum])->fbLocation; + } 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 62224d0..17b90dc 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -74,21 +74,71 @@ FUNC_NAME(RADEONSync)(ScreenPtr pScreen, int marker) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->new_cs) + return; + TRACE; if (info->accel_state->exaMarkerSynced != marker) { - FUNC_NAME(RADEONWaitForIdle)(pScrn); + FUNC_NAME(RADEONWaitForIdle)(pScrn); info->accel_state->exaMarkerSynced = marker; } RADEONPTR(pScrn)->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; } +static void FUNC_NAME(Emit2DState)(ScrnInfoPtr pScrn, int op) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + uint32_t qwords; + int has_src; + ACCEL_PREAMBLE(); + + /* don't emit if no operation in progress */ + if (info->state_2d.op == 0 && op == 0) + return; + + has_src = info->state_2d.src_pitch_offset || (info->new_cs && info->state_2d.src_bo); + + qwords = info->new_cs ? 10 : 9; + qwords += (has_src ? (info->new_cs ? 2 : 1) : 0); + + BEGIN_ACCEL(qwords); + OUT_ACCEL_REG(RADEON_DEFAULT_SC_BOTTOM_RIGHT, info->state_2d.default_sc_bottom_right); + OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, info->state_2d.dp_gui_master_cntl); + OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, info->state_2d.dp_brush_frgd_clr); + OUT_ACCEL_REG(RADEON_DP_BRUSH_BKGD_CLR, info->state_2d.dp_brush_bkgd_clr); + OUT_ACCEL_REG(RADEON_DP_SRC_FRGD_CLR, info->state_2d.dp_src_frgd_clr); + OUT_ACCEL_REG(RADEON_DP_SRC_BKGD_CLR, info->state_2d.dp_src_bkgd_clr); + OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, info->state_2d.dp_write_mask); + OUT_ACCEL_REG(RADEON_DP_CNTL, info->state_2d.dp_cntl); + + OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, info->state_2d.dst_pitch_offset); + if (info->new_cs) + 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, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); + + } + FINISH_ACCEL(); + + if (op) + info->state_2d.op = op; + if (info->new_cs) + info->reemit_current2d = FUNC_NAME(Emit2DState); +} + static Bool FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) { RINFO_FROM_SCREEN(pPix->drawable.pScreen); uint32_t datatype, dst_pitch_offset; + struct radeon_exa_pixmap_priv *driver_priv; + int ret; + int retry_count = 0; ACCEL_PREAMBLE(); TRACE; @@ -97,25 +147,49 @@ FUNC_NAME(RADEONPrepareSolid)(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) RADEON_FALLBACK(("24bpp unsupported\n")); if (!RADEONGetDatatypeBpp(pPix->drawable.bitsPerPixel, &datatype)) RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pPix, &dst_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch failed\n")); + + + if (info->new_cs) { + retry: + driver_priv = exaGetPixmapDriverPrivate(pPix); + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for dst\n")); + goto retry; + } + } RADEON_SWITCH_TO_2D(); - BEGIN_ACCEL(5); - OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (datatype << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP[alu].pattern | - RADEON_GMC_CLR_CMP_CNTL_DIS); - OUT_ACCEL_REG(RADEON_DP_BRUSH_FRGD_CLR, fg); - OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, pm); - OUT_ACCEL_REG(RADEON_DP_CNTL, - (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM)); - OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); - FINISH_ACCEL(); + info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX | + RADEON_DEFAULT_SC_BOTTOM_MAX); + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_SOLID_COLOR | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[alu].pattern | + RADEON_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_brush_frgd_clr = fg; + info->state_2d.dp_cntl = (RADEON_DST_X_LEFT_TO_RIGHT | RADEON_DST_Y_TOP_TO_BOTTOM); + info->state_2d.dp_write_mask = pm; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = 0; + info->state_2d.src_bo = NULL; + + driver_priv = exaGetPixmapDriverPrivate(pPix); + if (driver_priv) + info->state_2d.dst_bo = driver_priv->bo; + + FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_SOLID); return TRUE; } @@ -148,8 +222,10 @@ FUNC_NAME(RADEONDoneSolid)(PixmapPtr pPix) OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); FINISH_ACCEL(); + info->state_2d.op = 0; } + void FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, uint32_t dst_pitch_offset, uint32_t datatype, int rop, @@ -160,23 +236,28 @@ FUNC_NAME(RADEONDoPrepareCopy)(ScrnInfoPtr pScrn, uint32_t src_pitch_offset, RADEON_SWITCH_TO_2D(); - BEGIN_ACCEL(5); - OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (datatype << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP[rop].rop | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS); - OUT_ACCEL_REG(RADEON_DP_WRITE_MASK, planemask); - OUT_ACCEL_REG(RADEON_DP_CNTL, - ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | - (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0))); - OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); - OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); - FINISH_ACCEL(); + /* setup 2D state */ + info->state_2d.dp_gui_master_cntl = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_SRC_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (datatype << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP[rop].rop | + RADEON_DP_SRC_SOURCE_MEMORY | + RADEON_GMC_CLR_CMP_CNTL_DIS); + info->state_2d.dp_cntl = ((info->accel_state->xdir >= 0 ? RADEON_DST_X_LEFT_TO_RIGHT : 0) | + (info->accel_state->ydir >= 0 ? RADEON_DST_Y_TOP_TO_BOTTOM : 0)); + info->state_2d.dp_brush_frgd_clr = 0xffffffff; + info->state_2d.dp_brush_bkgd_clr = 0x00000000; + info->state_2d.dp_src_frgd_clr = 0xffffffff; + info->state_2d.dp_src_bkgd_clr = 0x00000000; + info->state_2d.dp_write_mask = planemask; + info->state_2d.dst_pitch_offset = dst_pitch_offset; + info->state_2d.src_pitch_offset = src_pitch_offset; + info->state_2d.default_sc_bottom_right = (RADEON_DEFAULT_SC_RIGHT_MAX + | RADEON_DEFAULT_SC_BOTTOM_MAX); + + FUNC_NAME(Emit2DState)(pScrn, RADEON_2D_EXA_COPY); } static Bool @@ -187,7 +268,9 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, { RINFO_FROM_SCREEN(pDst->drawable.pScreen); uint32_t datatype, src_pitch_offset, dst_pitch_offset; - + struct radeon_exa_pixmap_priv *driver_priv; + int ret; + int retry_count = 0; TRACE; info->accel_state->xdir = xdir; @@ -197,10 +280,40 @@ FUNC_NAME(RADEONPrepareCopy)(PixmapPtr pSrc, PixmapPtr pDst, RADEON_FALLBACK(("24bpp unsupported")); if (!RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype)) RADEON_FALLBACK(("RADEONGetDatatypeBpp failed\n")); + if (!RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch source failed\n")); if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset)) - RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); + RADEON_FALLBACK(("RADEONGetPixmapOffsetPitch dest failed\n")); + + retry: + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pSrc); + if (driver_priv) { + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for src\n")); + goto retry; + } + info->state_2d.src_bo = driver_priv->bo; + + driver_priv = exaGetPixmapDriverPrivate(pDst); + if (driver_priv) { + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for dst\n")); + goto retry; + } + info->state_2d.dst_bo = driver_priv->bo; + } + } + } FUNC_NAME(RADEONDoPrepareCopy)(pScrn, src_pitch_offset, dst_pitch_offset, datatype, rop, planemask); @@ -250,6 +363,8 @@ FUNC_NAME(RADEONDoneCopy)(PixmapPtr pDst) OUT_ACCEL_REG(RADEON_WAIT_UNTIL, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); FINISH_ACCEL(); + + info->state_2d.op = 0; } static Bool @@ -260,6 +375,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 +393,45 @@ 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); + #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--) { + dri_bo_subdata(driver_priv->bo, offset, bo_width, + src); + + src += src_pitch; + offset += dst_pitch; + } + + return TRUE; + } + } + if (!info->directRenderingEnabled && !info->drm_mode_setting) + goto fallback; + + if (!RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_off)) + goto fallback; + + if (!info->new_cs) + { + uint8_t *buf; int cpp = bpp / 8; ACCEL_PREAMBLE(); @@ -294,9 +446,10 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, exaMarkSync(pDst->drawable.pScreen); return TRUE; - } -#endif + } + fallback: +#endif /* Do we need that sync here ? probably not .... */ exaWaitSync(pDst->drawable.pScreen); @@ -335,14 +488,20 @@ FUNC_NAME(RADEONUploadToScreen)(PixmapPtr pDst, int x, int y, int w, int h, #ifdef ACCEL_CP /* Emit blit with arbitrary source and destination offsets and pitches */ static void -RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset, +RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, dri_bo *src_bo, dri_bo *dst_bo, + uint32_t src_pitch_offset, uint32_t dst_pitch_offset, int srcX, int srcY, int dstX, int dstY, int w, int h) { RADEONInfoPtr info = RADEONPTR(pScrn); + uint32_t qwords; ACCEL_PREAMBLE(); - BEGIN_ACCEL(6); + qwords = 6; + if (src_bo && dst_bo) + qwords += 2; + + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(RADEON_DP_GUI_MASTER_CNTL, RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_SRC_PITCH_OFFSET_CNTL | @@ -353,8 +512,14 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset, RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); + OUT_ACCEL_REG(RADEON_SRC_PITCH_OFFSET, src_pitch_offset); + if (src_bo) + OUT_RELOC(src_bo, RADEON_GEM_DOMAIN_GTT|RADEON_GEM_DOMAIN_VRAM, 0); OUT_ACCEL_REG(RADEON_DST_PITCH_OFFSET, dst_pitch_offset); + if (dst_bo) + OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_GTT); + OUT_ACCEL_REG(RADEON_SRC_Y_X, (srcY << 16) | srcX); OUT_ACCEL_REG(RADEON_DST_Y_X, (dstY << 16) | dstX); OUT_ACCEL_REG(RADEON_DST_HEIGHT_WIDTH, (h << 16) | w); @@ -365,6 +530,107 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, uint32_t datatype, uint32_t src_pitch_offset, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_DMA_GUI_IDLE); FINISH_ACCEL(); } + +static Bool +RADEON_DFS_CS(PixmapPtr pSrc, int x, int y, int w, int h, + char *dst, int dst_pitch) +{ + RINFO_FROM_SCREEN(pSrc->drawable.pScreen); + struct radeon_exa_pixmap_priv *driver_priv; + dri_bo *scratch_bo[2]; + int i, ret; + uint32_t scratch_size = RADEON_BUFFER_SIZE / 2; + int bpp = pSrc->drawable.bitsPerPixel; + uint32_t scratch_pitch = (w * bpp/8 + 63) & ~63, scratch_off = 0; + uint32_t datatype; + int src_pitch = exaGetPixmapPitch(pSrc); + dri_bo *cur_scratch; + uint32_t src_pitch_offset; + + if (!info->accelDFS) + return FALSE; + + driver_priv = exaGetPixmapDriverPrivate(pSrc); + + RADEONGetDatatypeBpp(bpp, &datatype); + scratch_bo[0] = scratch_bo[1] = NULL; + for (i = 0; i < 2; i++) { + scratch_bo[i] = dri_bo_alloc(info->bufmgr, "DFS scratch", scratch_size, 0, 0); + if (!scratch_bo[i]) + goto fail; + } + + + /* we want to blit from the BO to the scratch and memcpy out of the scratch */ + { + int wpass = wpass = w * bpp / 8; + int hpass = min(h, scratch_size / scratch_pitch); + uint32_t pitch_offset = scratch_pitch << 16; + + RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); + + ACCEL_PREAMBLE(); + RADEON_SWITCH_TO_2D(); + + cur_scratch = scratch_bo[0]; + RADEONBlitChunk(pScrn, datatype, driver_priv->bo, cur_scratch, src_pitch_offset, + pitch_offset, + x, y, 0, 0, w, hpass); + + FLUSH_RING(); + + while (h) { + int swap = RADEON_HOST_DATA_SWAP_NONE; + int oldhpass = hpass, i = 0; + dri_bo *old_scratch; + uint8_t *src; + + old_scratch = cur_scratch; + y += oldhpass; + h -= oldhpass; + hpass = min(h, scratch_size / scratch_pitch); + if (hpass) { + if (cur_scratch == scratch_bo[0]) + cur_scratch = scratch_bo[1]; + else + cur_scratch = scratch_bo[0]; + + RADEONBlitChunk(pScrn, datatype, driver_priv->bo, cur_scratch, src_pitch_offset, + pitch_offset, + x, y, 0, 0, w, hpass); + } + + ret = dri_bo_map(old_scratch, 0); + + if (hpass) + FLUSH_RING(); + + src = old_scratch->virtual; + + if (wpass == scratch_pitch && wpass == dst_pitch) { + RADEONCopySwap((uint8_t*)dst, src, wpass * oldhpass, swap); + dst += dst_pitch * oldhpass; + } else while (oldhpass--) { + RADEONCopySwap((uint8_t*)dst, src, wpass, swap); + src += scratch_pitch; + dst += dst_pitch; + } + dri_bo_unmap(old_scratch); + } + + dri_bo_unreference(scratch_bo[0]); + dri_bo_unreference(scratch_bo[1]); + return TRUE; + } + + + fail: + if (scratch_bo[0]) + dri_bo_unreference(scratch_bo[0]); + if (scratch_bo[1]) + dri_bo_unreference(scratch_bo[1]); + return FALSE; +} #endif static Bool @@ -389,12 +655,16 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, TRACE; #ifdef ACCEL_CP + + if (info->new_cs) + return RADEON_DFS_CS(pSrc, x, y, w, h, dst, dst_pitch); /* * Try to accelerate download. Use an indirect buffer as scratch space, * blitting the bits to one half while copying them out of the other one and * then swapping the halves. */ - if (info->accelDFS && bpp != 24 && RADEONGetDatatypeBpp(bpp, &datatype) && + if (!info->drm_mm && info->accelDFS && bpp != 24 && + RADEONGetDatatypeBpp(bpp, &datatype) && RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset) && (scratch = RADEONCPGetBuffer(pScrn))) { @@ -409,7 +679,8 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, RADEON_SWITCH_TO_2D(); /* Kick the first blit as early as possible */ - RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset, + RADEONBlitChunk(pScrn, datatype, NULL, NULL, + src_pitch_offset, scratch_pitch_offset, x, y, 0, 0, w, hpass); FLUSH_RING(); @@ -436,7 +707,8 @@ FUNC_NAME(RADEONDownloadFromScreen)(PixmapPtr pSrc, int x, int y, int w, int h, /* Prepare next blit if anything's left */ if (hpass) { scratch_off = scratch->total/2 - scratch_off; - RADEONBlitChunk(pScrn, datatype, src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10), + RADEONBlitChunk(pScrn, datatype, NULL, NULL, + src_pitch_offset, scratch_pitch_offset + (scratch_off >> 10), x, y, 0, 0, w, hpass); } @@ -543,14 +815,17 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) info->accel_state->exa->UploadToScreen = FUNC_NAME(RADEONUploadToScreen); info->accel_state->exa->DownloadFromScreen = FUNC_NAME(RADEONDownloadFromScreen); -#if X_BYTE_ORDER == X_BIG_ENDIAN info->accel_state->exa->PrepareAccess = RADEONPrepareAccess; info->accel_state->exa->FinishAccess = RADEONFinishAccess; -#endif /* X_BYTE_ORDER == X_BIG_ENDIAN */ info->accel_state->exa->flags = EXA_OFFSCREEN_PIXMAPS; - info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; info->accel_state->exa->pixmapPitchAlign = 64; + info->accel_state->exa->pixmapOffsetAlign = RADEON_BUFFER_ALIGN + 1; + + if (info->drm_mm) { + info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS; + } else { + } #ifdef RENDER if (info->RenderAccel) { @@ -560,7 +835,7 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) else if (IS_R300_3D || IS_R500_3D) { if ((info->ChipFamily < CHIP_FAMILY_RS400) #ifdef XF86DRI - || (info->directRenderingEnabled) + || (info->directRenderingEnabled || info->drm_mode_setting) #endif ) { xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Render acceleration " @@ -595,6 +870,16 @@ Bool FUNC_NAME(RADEONDrawInit)(ScreenPtr pScreen) } #endif +#if (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 4) + if (info->drm_mm) { + info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; + info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; + info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; + info->accel_state->exa->ModifyPixmapHeader = RADEONEXAModifyPixmapHeader; + } +#endif + + #if EXA_VERSION_MAJOR > 2 || (EXA_VERSION_MAJOR == 2 && EXA_VERSION_MINOR >= 3) xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Setting EXA maxPitchBytes\n"); diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index 97199ae..0de7666 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -355,12 +355,14 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix, Bool repeat = pPict->repeat && !(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y)); int i; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); txpitch = exaGetPixmapPitch(pPix); - txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; + txoffset = exaGetPixmapOffset(pPix); - if ((txoffset & 0x1f) != 0) + if (!info->new_cs && ((txoffset & 0x1f) != 0)) RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); if ((txpitch & 0x1f) != 0) RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); @@ -402,23 +404,43 @@ static Bool FUNC_NAME(R100TextureSetup)(PicturePtr pPict, PixmapPtr pPix, if (repeat) txfilter |= RADEON_CLAMP_S_WRAP | RADEON_CLAMP_T_WRAP; - BEGIN_ACCEL(5); + qwords = info->new_cs ? 6 : 5; + BEGIN_ACCEL(qwords); if (unit == 0) { OUT_ACCEL_REG(RADEON_PP_TXFILTER_0, txfilter); OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat); - OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset); OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_0, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_0, txpitch - 32); + + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pPix); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, 0); + OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, txoffset); + } + /* emit a texture relocation */ } else { OUT_ACCEL_REG(RADEON_PP_TXFILTER_1, txfilter); OUT_ACCEL_REG(RADEON_PP_TXFORMAT_1, txformat); - OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset); + OUT_ACCEL_REG(RADEON_PP_TEX_SIZE_1, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(RADEON_PP_TEX_PITCH_1, txpitch - 32); + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pPix); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, 0); + OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_1, txoffset); + } + + /* emit a texture relocation */ } FINISH_ACCEL(); @@ -523,6 +545,8 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op, uint32_t dst_format, dst_offset, dst_pitch, colorpitch; uint32_t pp_cntl, blendcntl, cblend, ablend; int pixel_shift; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); TRACE; @@ -540,15 +564,13 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op, pixel_shift = pDst->drawable.bitsPerPixel >> 4; - dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; + dst_offset = exaGetPixmapOffset(pDst); dst_pitch = exaGetPixmapPitch(pDst); colorpitch = dst_pitch >> pixel_shift; if (RADEONPixmapIsColortiled(pDst)) colorpitch |= RADEON_COLOR_TILE_ENABLE; - dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; - dst_pitch = exaGetPixmapPitch(pDst); - if ((dst_offset & 0x0f) != 0) + if (!info->new_cs && (dst_offset & 0x0f) != 0) RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); if (((dst_pitch >> pixel_shift) & 0x7) != 0) RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); @@ -569,11 +591,19 @@ static Bool FUNC_NAME(R100PrepareComposite)(int op, } RADEON_SWITCH_TO_3D(); - - BEGIN_ACCEL(8); + + qwords = info->new_cs ? 9 : 8; + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl); OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pDst); + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, 0); + OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + } OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch); /* IN operator: Multiply src by mask components or mask alpha. @@ -669,13 +699,17 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, Bool repeat = pPict->repeat && !(unit == 0 && (info->accel_state->need_src_tile_x || info->accel_state->need_src_tile_y)); int i; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); txpitch = exaGetPixmapPitch(pPix); - txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; + txoffset = exaGetPixmapOffset(pPix); - if ((txoffset & 0x1f) != 0) - RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if (!info->new_cs) { + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + } if ((txpitch & 0x1f) != 0) RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); @@ -718,7 +752,8 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, if (repeat) txfilter |= R200_CLAMP_S_WRAP | R200_CLAMP_T_WRAP; - BEGIN_ACCEL(6); + qwords = info->new_cs ? 7 : 6; + BEGIN_ACCEL(qwords); if (unit == 0) { OUT_ACCEL_REG(R200_PP_TXFILTER_0, txfilter); OUT_ACCEL_REG(R200_PP_TXFORMAT_0, txformat); @@ -726,7 +761,15 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, OUT_ACCEL_REG(R200_PP_TXSIZE_0, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(R200_PP_TXPITCH_0, txpitch - 32); - OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset); + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pPix); + + OUT_ACCEL_REG(R200_PP_TXOFFSET_0, driver_priv ? 0 : txoffset); + OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R200_PP_TXOFFSET_0, txoffset); + } } else { OUT_ACCEL_REG(R200_PP_TXFILTER_1, txfilter); OUT_ACCEL_REG(R200_PP_TXFORMAT_1, txformat); @@ -734,7 +777,17 @@ static Bool FUNC_NAME(R200TextureSetup)(PicturePtr pPict, PixmapPtr pPix, OUT_ACCEL_REG(R200_PP_TXSIZE_1, (pPix->drawable.width - 1) | ((pPix->drawable.height - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(R200_PP_TXPITCH_1, txpitch - 32); - OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset); + if (info->new_cs) { + uint32_t handle = 0; + driver_priv = exaGetPixmapDriverPrivate(pPix); + + OUT_ACCEL_REG(R200_PP_TXOFFSET_1, driver_priv ? 0 : txoffset); + OUT_RELOC(driver_priv->bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R200_PP_TXOFFSET_1, txoffset); + } + /* emit a texture relocation */ } FINISH_ACCEL(); @@ -823,6 +876,8 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, uint32_t dst_format, dst_offset, dst_pitch; uint32_t pp_cntl, blendcntl, cblend, ablend, colorpitch; int pixel_shift; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); TRACE; @@ -840,13 +895,13 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, pixel_shift = pDst->drawable.bitsPerPixel >> 4; - dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; + dst_offset = exaGetPixmapOffset(pDst); dst_pitch = exaGetPixmapPitch(pDst); colorpitch = dst_pitch >> pixel_shift; if (RADEONPixmapIsColortiled(pDst)) colorpitch |= RADEON_COLOR_TILE_ENABLE; - if ((dst_offset & 0x0f) != 0) + if (!info->new_cs && (dst_offset & 0x0f) != 0) RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); if (((dst_pitch >> pixel_shift) & 0x7) != 0) RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); @@ -868,11 +923,22 @@ static Bool FUNC_NAME(R200PrepareComposite)(int op, PicturePtr pSrcPicture, RADEON_SWITCH_TO_3D(); - BEGIN_ACCEL(11); + qwords = info->new_cs ? 12 : 11; + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(RADEON_PP_CNTL, pp_cntl); OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); - OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pDst); + assert(driver_priv); + + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, 0); + OUT_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); + } OUT_ACCEL_REG(R200_SE_VTX_FMT_0, R200_VTX_XY); if (pMask) @@ -941,6 +1007,10 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict, int unit, Bool is_r500) { + ScreenPtr pScreen = pDstPict->pDrawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + int w = pPict->pDrawable->width; int h = pPict->pDrawable->height; int i; @@ -966,8 +1036,17 @@ static Bool R300CheckCompositeTexture(PicturePtr pPict, RADEON_FALLBACK(("Unsupported picture format 0x%x\n", (int)pPict->format)); - if (!RADEONCheckTexturePOT(pPict, unit == 0)) + if (!RADEONCheckTexturePOT(pPict, unit == 0)) { + if (info->new_cs) { + struct radeon_exa_pixmap_priv *driver_priv; + PixmapPtr pPix; + + pPix = RADEONGetDrawablePixmap(pPict->pDrawable); + driver_priv = exaGetPixmapDriverPrivate(pPix); + radeon_bufmgr_gem_force_gtt(driver_priv->bo); + } return FALSE; + } if (pPict->filter != PictFilterNearest && pPict->filter != PictFilterBilinear) @@ -999,15 +1078,19 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix, int w = pPict->pDrawable->width; int h = pPict->pDrawable->height; int i, pixel_shift; + struct radeon_exa_pixmap_priv *driver_priv; + int qwords; ACCEL_PREAMBLE(); TRACE; txpitch = exaGetPixmapPitch(pPix); - txoffset = exaGetPixmapOffset(pPix) + info->fbLocation + pScrn->fbOffset; + txoffset = exaGetPixmapOffset(pPix); - if ((txoffset & 0x1f) != 0) - RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + if (!info->new_cs) { + if ((txoffset & 0x1f) != 0) + RADEON_FALLBACK(("Bad texture offset 0x%x\n", (int)txoffset)); + } if ((txpitch & 0x1f) != 0) RADEON_FALLBACK(("Bad texture pitch 0x%x\n", (int)txpitch)); @@ -1068,13 +1151,26 @@ static Bool FUNC_NAME(R300TextureSetup)(PicturePtr pPict, PixmapPtr pPix, RADEON_FALLBACK(("Bad filter 0x%x\n", pPict->filter)); } - BEGIN_ACCEL(pPict->repeat ? 6 : 7); + qwords = pPict->repeat ? 6 : 7; + qwords += info->new_cs ? 1 : 0; + + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(R300_TX_FILTER0_0 + (unit * 4), txfilter); OUT_ACCEL_REG(R300_TX_FILTER1_0 + (unit * 4), 0); OUT_ACCEL_REG(R300_TX_FORMAT0_0 + (unit * 4), txformat0); OUT_ACCEL_REG(R300_TX_FORMAT1_0 + (unit * 4), txformat1); OUT_ACCEL_REG(R300_TX_FORMAT2_0 + (unit * 4), txpitch); - OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), txoffset); + + if (info->new_cs) { + uint32_t handle = 0; + driver_priv = exaGetPixmapDriverPrivate(pPix); + + OUT_ACCEL_REG(R300_TX_OFFSET_0 + (unit * 4), driver_priv ? 0 : txoffset); + 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); + } if (!pPict->repeat) OUT_ACCEL_REG(R300_TX_BORDER_COLOR_0 + (unit * 4), 0); FINISH_ACCEL(); @@ -1173,6 +1269,7 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP return TRUE; } + #endif /* ONLY_ONCE */ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, @@ -1184,10 +1281,52 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, uint32_t txenable, colorpitch; uint32_t blendcntl; int pixel_shift; + int qwords, ret; + int retry_count = 0; + struct radeon_exa_pixmap_priv *driver_priv; ACCEL_PREAMBLE(); TRACE; + retry: + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pSrc); + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for src\n")); + goto retry; + } + + if (pMask) { + driver_priv = exaGetPixmapDriverPrivate(pMask); + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for mask\n")); + goto retry; + } + } + + driver_priv = exaGetPixmapDriverPrivate(pDst); + if (driver_priv) { + ret = dri_bufmgr_check_aperture_space(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + if (ret) { + RADEONCPFlushIndirect(pScrn, 1); + retry_count++; + if (retry_count == 2) + RADEON_FALLBACK(("Not enough Video RAM for dst\n")); + goto retry; + } + } + } + + + if (!info->accel_state->XInited3D) RADEONInit3DEngine(pScrn); @@ -1201,7 +1340,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, pixel_shift = pDst->drawable.bitsPerPixel >> 4; - dst_offset = exaGetPixmapOffset(pDst) + info->fbLocation + pScrn->fbOffset; + dst_offset = exaGetPixmapOffset(pDst); dst_pitch = exaGetPixmapPitch(pDst); colorpitch = dst_pitch >> pixel_shift; @@ -1210,7 +1349,7 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, colorpitch |= dst_format; - if ((dst_offset & 0x0f) != 0) + if (!info->new_cs && ((dst_offset & 0x0f) != 0)) RADEON_FALLBACK(("Bad destination offset 0x%x\n", (int)dst_offset)); if (((dst_pitch >> pixel_shift) & 0x7) != 0) RADEON_FALLBACK(("Bad destination pitch 0x%x\n", (int)dst_pitch)); @@ -1829,9 +1968,18 @@ static Bool FUNC_NAME(R300PrepareComposite)(int op, PicturePtr pSrcPicture, FINISH_ACCEL(); } - BEGIN_ACCEL(3); + qwords = info->new_cs ? 4 : 3; + BEGIN_ACCEL(qwords); + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pDst); + assert(driver_priv); - OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0); + 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); + } OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch); blendcntl = RADEONGetBlendCntl(op, pMaskPicture, pDstPicture->format); diff --git a/src/radeon_legacy_memory.c b/src/radeon_legacy_memory.c index 2a9ee94..0423571 100644 --- a/src/radeon_legacy_memory.c +++ b/src/radeon_legacy_memory.c @@ -21,6 +21,19 @@ radeon_legacy_allocate_memory(ScrnInfoPtr pScrn, RADEONInfoPtr info = RADEONPTR(pScrn); uint32_t offset = 0; + if (info->new_cs) { + dri_bo *video_bo; + + video_bo = dri_bo_alloc(info->bufmgr, "xv pixmap", size, 4096, 0); + + *mem_struct = video_bo; + + if (!video_bo) + return 0; + + return (uint32_t)-1; + + } #ifdef USE_EXA if (info->useEXA) { ExaOffscreenArea *area = *mem_struct; @@ -96,6 +109,11 @@ radeon_legacy_free_memory(ScrnInfoPtr pScrn, ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; RADEONInfoPtr info = RADEONPTR(pScrn); + if (info->new_cs) { + dri_bo *bo = mem_struct; + dri_bo_unreference(bo); + return; + } #ifdef USE_EXA if (info->useEXA) { ExaOffscreenArea *area = mem_struct; diff --git a/src/radeon_memory.c b/src/radeon_memory.c new file mode 100644 index 0000000..c613ade --- /dev/null +++ b/src/radeon_memory.c @@ -0,0 +1,415 @@ + +#include +#include +#include +#include "radeon.h" +#include "radeon_drm.h" +#include "radeon_bufmgr_gem.h" + +Bool +radeon_bind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (mem == NULL || mem->bound) + return TRUE; + + if (!info->drm_mm) + return FALSE; + + if (mem->kernel_bo_handle) { + struct drm_radeon_gem_pin pin; + + int ret; + + if (mem->pool == RADEON_POOL_VRAM) + pin.pin_domain = RADEON_GEM_DOMAIN_VRAM; + else + pin.pin_domain = RADEON_GEM_DOMAIN_GTT; + pin.handle = mem->kernel_bo_handle; + pin.alignment = mem->alignment; + + ret = ioctl(info->dri->drmFD, DRM_IOCTL_RADEON_GEM_PIN, &pin); + if (ret != 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Failed to pin %s: %s\n", mem->name, strerror(errno)); + return FALSE; + } + + mem->bound = TRUE; + mem->offset = pin.offset; + // ErrorF("pin returned 0x%llx\n", pin.offset); + mem->end = mem->offset + mem->size; + return TRUE; + } + return FALSE; +} + +static Bool +radeon_unbind_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + int ret; + + if (mem == NULL || !mem->bound) + return TRUE; + + if (!info->drm_mm) + return FALSE; + + + if (mem->kernel_bo_handle) { + struct drm_radeon_gem_unpin unpin; + + unpin.handle = mem->kernel_bo_handle; + ret = ioctl(info->dri->drmFD, DRM_IOCTL_RADEON_GEM_UNPIN, &unpin); + + if (ret == 0) { + mem->bound = FALSE; + mem->offset = -1; + mem->end = -1; + return TRUE; + } else { + return FALSE; + } + } + return FALSE; +} + +void radeon_free_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + + if (mem == NULL) + return; + + if (mem->map) + radeon_unmap_memory(pScrn, mem); + + radeon_unbind_memory(pScrn, mem); + + if (mem->kernel_bo_handle) { + struct drm_gem_close close; + + close.handle = mem->kernel_bo_handle; + ioctl(info->dri->drmFD, DRM_IOCTL_GEM_CLOSE, &close); + } + + if (info->mm.bo_list[mem->pool] == mem) { + info->mm.bo_list[mem->pool] = mem->next; + if (mem->next) + mem->next->prev = NULL; + } else { + if (mem->prev) + mem->prev->next = mem->next; + if (mem->next) + mem->next->prev = mem->prev; + } + xfree(mem->name); + xfree(mem); + return; +} + +struct radeon_memory *radeon_allocate_memory(ScrnInfoPtr pScrn, int pool, int size, int alignment, Bool no_backing_store, char *name, + int static_alloc) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct drm_radeon_gem_create args; + struct radeon_memory *mem; + int ret; + + mem = xcalloc(1, sizeof(*mem)); + if (!mem) + return NULL; + + mem->name = xstrdup(name); + if (!mem->name) { + xfree(mem); + return NULL; + } + + mem->size = size; + mem->pool = pool; + mem->next = mem->prev = NULL; + mem->vt_bind = static_alloc; + args.size = size; + args.alignment = alignment; + if (pool == RADEON_POOL_VRAM) + args.initial_domain = RADEON_GEM_DOMAIN_VRAM; + else + args.initial_domain = RADEON_GEM_DOMAIN_GTT; + args.no_backing_store = no_backing_store; + + ret = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_CREATE, &args, sizeof(args)); + if (ret) { + ErrorF("Failed to allocate %s\n", mem->name); + xfree(mem); + return NULL; + } + + mem->kernel_bo_handle = args.handle; + // xf86DrvMsg(pScrn->scrnIndex, X_INFO, + // "%s allocated %d with handle %x\n", mem->name, mem->size, mem->kernel_bo_handle); + + /* add to VRAM linked list for now */ + + mem->prev = NULL; + mem->next = info->mm.bo_list[pool]; + if (info->mm.bo_list[pool] != NULL) + info->mm.bo_list[pool]->prev = mem; + info->mm.bo_list[pool] = mem; + return mem; +} + +Bool radeon_bind_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem; + int i; + + for (i = 0; i < 2; i++) { + for (mem = info->mm.bo_list[i]; mem != NULL; + mem = mem->next) { + if (mem->vt_bind) + if (!radeon_bind_memory(pScrn, mem)) { + FatalError("Couldn't bind %s\n", mem->name); + } + } + } + return TRUE; +} + +Bool radeon_unbind_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem; + int i; + + for (i = 0; i < 2; i++) { + for (mem = info->mm.bo_list[i]; mem != NULL; + mem = mem->next) { + if (mem->vt_bind) + radeon_unbind_memory(pScrn, mem); + } + } + return TRUE; +} + +Bool radeon_free_all_memory(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_memory *mem, *tmp; + int i; + + for (i = 0; i < 2; i++) { + + for (mem = info->mm.bo_list[i]; mem != NULL; ) { + tmp = mem->next; + radeon_free_memory(pScrn, mem); + mem = tmp; + } + } + return TRUE; +} + +int radeon_map_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + struct drm_radeon_gem_mmap args; + RADEONInfoPtr info = RADEONPTR(pScrn); + int ret; + + assert(!mem->map); + + + args.handle = mem->kernel_bo_handle; + args.size = mem->size; + ret = drmCommandWriteRead(info->dri->drmFD, DRM_RADEON_GEM_MMAP, &args, sizeof(args)); + + if (!ret) + mem->map = (void *)(unsigned long)args.addr_ptr; + // ErrorF("Mapped %s size %ld at %x %p\n", mem->name, mem->size, mem->offset, mem->map); + return ret; +} + +void radeon_unmap_memory(ScrnInfoPtr pScrn, struct radeon_memory *mem) +{ + assert(mem->map); + if (mem->map) { + munmap(mem->map, mem->size); + mem->map = NULL; + } +} + +/* Okay radeon + 2D allocations + - Front buffer + - cursors + - EXA space + + 3D related: + - Backbuffer + - Depth buffer + - textures +*/ + + +Bool radeon_setup_kernel_mem(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int cpp = info->CurrentLayout.pixel_bytes; + int screen_size; + int stride = pScrn->displayWidth * cpp; + int total_size_bytes = 0, remain_size_bytes; + int fb_size_bytes; + int pagesize = 4096; + + screen_size = RADEON_ALIGN(pScrn->virtualY, 16) * stride; + + ErrorF("%d x %d x %d = %dK\n", pScrn->displayWidth, pScrn->virtualY, cpp, screen_size / 1024); + + { + int cursor_size = 64 * 4 * 64; + int c; + + cursor_size = RADEON_ALIGN(cursor_size, pagesize); + for (c = 0; c < xf86_config->num_crtc; c++) { + /* cursor objects */ + info->mm.cursor[c] = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, cursor_size, 0, 1, "Cursor", 1); + if (!info->mm.cursor[c]) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.cursor[c]); + + if (radeon_map_memory(pScrn, info->mm.cursor[c])) { + ErrorF("Failed to map front buffer memory\n"); + } + + if (!info->drm_mode_setting) { + xf86CrtcPtr crtc = xf86_config->crtc[c]; + RADEONCrtcPrivatePtr radeon_crtc = crtc->driver_private; + radeon_crtc->cursor = info->mm.cursor[c]; + } else { + drmmode_set_cursor(pScrn, &info->drmmode, c, (void *)info->mm.cursor[c]->map, info->mm.cursor[c]->kernel_bo_handle); + } + total_size_bytes += cursor_size; + } + } + + screen_size = RADEON_ALIGN(screen_size, pagesize); + /* keep area front front buffer - but don't allocate it yet */ + total_size_bytes += screen_size; + + if (info->directRenderingEnabled) { + info->dri->backPitch = pScrn->displayWidth; + info->mm.back_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, screen_size, 0, 1, "Back Buffer", 1); + if (!info->mm.back_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.back_buffer); + total_size_bytes += screen_size; + + info->dri->depthPitch = RADEON_ALIGN(pScrn->displayWidth, 32); + { + int depthCpp = (info->dri->depthBits - 8) / 4; + int depth_size = RADEON_ALIGN(pScrn->virtualY, 16) * info->dri->depthPitch * depthCpp; + depth_size = RADEON_ALIGN(depth_size, pagesize); + info->mm.depth_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, depth_size, 0, 1, "Depth Buffer", 1); + if (!info->mm.depth_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.depth_buffer); + total_size_bytes += depth_size; + } + } + + /* work out from the mm size what the exa / tex sizes need to be */ + remain_size_bytes = info->mm.vram_size - total_size_bytes; + + if (info->dri->textureSize > 0) + info->dri->textureSize = (remain_size_bytes / 100) * info->dri->textureSize; + else + info->dri->textureSize = remain_size_bytes / 2; + + info->dri->textureSize = RADEON_ALIGN(info->dri->textureSize, pagesize); + + remain_size_bytes -= info->dri->textureSize; + + ErrorF("texture size is %dK, exa is %dK\n", info->dri->textureSize / 1024, remain_size_bytes/1024); + + fb_size_bytes = screen_size; + + ErrorF("fb size is %dK %dK\n", fb_size_bytes / 1024, total_size_bytes / 1024); + + info->mm.front_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, fb_size_bytes, 0, 1, "Front Buffer + EXA", 1); + if (!info->mm.front_buffer) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.front_buffer); + if (radeon_map_memory(pScrn, info->mm.front_buffer)) { + ErrorF("Failed to map front buffer memory\n"); + } + info->dri->frontPitch = pScrn->displayWidth; + + if (info->directRenderingEnabled) { + info->mm.texture_buffer = radeon_allocate_memory(pScrn, RADEON_POOL_VRAM, info->dri->textureSize, 0, 1, "Texture Buffer", 1); + if (!info->mm.texture_buffer) { + return FALSE; + } + radeon_bind_memory(pScrn, info->mm.texture_buffer); + } + + if (info->drm_mode_setting) { + drmmode_set_fb(pScrn, &info->drmmode, pScrn->virtualX, RADEON_ALIGN(pScrn->virtualY, 16), stride, info->mm.front_buffer->kernel_bo_handle); + } + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK at 0x%08x\n", info->mm.front_buffer->size/1024, info->mm.front_buffer->offset); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Back buffer size: %dK at 0x%08x\n", info->mm.back_buffer->size/1024, info->mm.back_buffer->offset); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Depth buffer size: %dK at 0x%08x\n", info->mm.depth_buffer->size/1024, info->mm.depth_buffer->offset); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Texture size: %dK at 0x%08x\n", info->mm.texture_buffer->size/1024, info->mm.texture_buffer->offset); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024); + + radeon_bufmgr_gem_set_limit(info->bufmgr, RADEON_GEM_DOMAIN_VRAM, remain_size_bytes); + return TRUE; +} + +Bool radeon_setup_gart_mem(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + + + info->mm.gart_texture_buffer = + radeon_allocate_memory(pScrn, RADEON_POOL_GART, + info->dri->gartTexMapSize, + 0, 1, "GART texture buffers", 1); + + if (!info->mm.gart_texture_buffer) { + return FALSE; + } + + radeon_bind_memory(pScrn, info->mm.gart_texture_buffer); + + return TRUE; +} + +uint32_t radeon_create_new_fb(ScrnInfoPtr pScrn, int width, int height, int *pitch) +{ + return 0; +} + + +dri_bo *radeon_create_rotate_bo(ScrnInfoPtr pScrn, int size) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + dri_bo *bo; + + bo = dri_bo_alloc(info->bufmgr, "rotate", size, 0, 0); + + dri_bo_pin(bo, RADEON_GEM_DOMAIN_VRAM); + return bo; +} + diff --git a/src/radeon_probe.h b/src/radeon_probe.h index c14241e..8ef7381 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -184,6 +184,27 @@ typedef struct Bool hw_capable; } RADEONI2CBusRec, *RADEONI2CBusPtr; +struct radeon_memory { + int pool; // memory is VRAM vs GART + unsigned long offset; + unsigned long end; + + unsigned long size; + unsigned long allocated_size; + void *map; + int key; + + Bool bound; + unsigned long agp_offset; + unsigned int pitch; + char *name; + struct radeon_memory *next, *prev; + uint32_t alignment; + uint32_t kernel_bo_handle; + uint32_t kernel_name; + Bool vt_bind; +}; + typedef struct _RADEONCrtcPrivateRec { void *crtc_rotate_mem; void *cursor_mem; @@ -196,6 +217,8 @@ typedef struct _RADEONCrtcPrivateRec { uint32_t crtc_offset; int can_tile; Bool enabled; + struct radeon_memory *cursor; + } RADEONCrtcPrivateRec, *RADEONCrtcPrivatePtr; typedef struct { diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c index c185b46..1ff5a7f 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -39,6 +39,7 @@ #include "radeon_macros.h" #include "radeon_probe.h" #include "radeon_video.h" +#include "radeon_drm.h" #include #include "fourcc.h" @@ -85,6 +86,7 @@ static __inline__ uint32_t F_TO_DW(float val) #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, read, write) do {} while(0) #define FINISH_ACCEL() #include "radeon_textured_videofuncs.c" @@ -94,6 +96,7 @@ static __inline__ uint32_t F_TO_DW(float val) #undef BEGIN_ACCEL #undef OUT_ACCEL_REG #undef OUT_ACCEL_REG_F +#undef OUT_RELOC #undef FINISH_ACCEL #ifdef XF86DRI @@ -107,6 +110,7 @@ static __inline__ uint32_t F_TO_DW(float val) #define OUT_ACCEL_REG_F(reg, val) OUT_ACCEL_REG(reg, F_TO_DW(val)) #define FINISH_ACCEL() ADVANCE_RING() #define OUT_RING_F(x) OUT_RING(F_TO_DW(x)) +#define OUT_RELOC(x, read, write) OUT_RING_RELOC(x, read, write) #include "radeon_textured_videofuncs.c" @@ -188,13 +192,8 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, break; } -#ifdef XF86DRI - if (info->directRenderingEnabled && info->DMAForXv) - /* The upload blit only supports multiples of 64 bytes */ - dstPitch = (dstPitch + 63) & ~63; - else -#endif - dstPitch = (dstPitch + 15) & ~15; + /* always align to 64 bytes - fixes issue with non-CP code */ + dstPitch = (dstPitch + 63) & ~63; if (pPriv->video_memory != NULL && size != pPriv->size) { radeon_legacy_free_memory(pScrn, pPriv->video_memory); @@ -207,6 +206,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, size * 2, 64); if (pPriv->video_offset == 0) return BadAlloc; + + if (info->new_cs) + pPriv->src_bo = pPriv->video_memory; } /* Bicubic filter loading */ @@ -219,6 +221,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, pPriv->bicubic_src_offset = pPriv->bicubic_offset + info->fbLocation + pScrn->fbOffset; if (pPriv->bicubic_offset == 0) pPriv->bicubic_enabled = FALSE; + + if (info->new_cs) + pPriv->bicubic_bo = pPriv->bicubic_memory; } if (pDraw->type == DRAWABLE_WINDOW) @@ -248,8 +253,19 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, left = (x1 >> 16) & ~1; npixels = ((((x2 + 0xffff) >> 16) + 1) & ~1) - left; - pPriv->src_offset = pPriv->video_offset + info->fbLocation + pScrn->fbOffset; - pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); + pPriv->src_offset = pPriv->video_offset; + if (info->new_cs) { + int ret; + ret = dri_bo_map(pPriv->src_bo, 1); + if (ret) + return BadAlloc; + + pPriv->src_addr = pPriv->src_bo->virtual; + } else if (info->drm_mm) { + pPriv->src_addr = (uint8_t *)(info->mm.front_buffer->map + pPriv->video_offset + (top * dstPitch)); + } else { + pPriv->src_addr = (uint8_t *)(info->FB + pPriv->video_offset + (top * dstPitch)); + } pPriv->src_pitch = dstPitch; pPriv->size = size; pPriv->pDraw = pDraw; @@ -290,8 +306,24 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, } /* Upload bicubic filter tex */ - if (pPriv->bicubic_enabled) - RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, (uint8_t *)(info->FB + pPriv->bicubic_offset), 1024, 1024, 1, 512, 2); + if (pPriv->bicubic_enabled) { + uint8_t *bicubic_addr; + int ret; + + if (info->new_cs) { + ret = dri_bo_map(pPriv->bicubic_bo, 1); + if (ret) + return BadAlloc; + + bicubic_addr = pPriv->bicubic_bo->virtual; + } else + bicubic_addr = (uint8_t *)(info->FB + pPriv->bicubic_offset); + + RADEONCopyData(pScrn, (uint8_t *)bicubic_tex_512, bicubic_addr, 1024, 1024, 1, 512, 2); + + if (info->new_cs) + dri_bo_unmap(pPriv->bicubic_bo); + } /* update cliplist */ if (!REGION_EQUAL(pScrn->pScreen, &pPriv->clip, clipBoxes)) { @@ -308,8 +340,10 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, pPriv->w = width; pPriv->h = height; + if (info->new_cs) + dri_bo_unmap(pPriv->src_bo); #ifdef XF86DRI - if (info->directRenderingEnabled) + if (info->directRenderingEnabled || info->drm_mode_setting) RADEONDisplayTexturedVideoCP(pScrn, pPriv); else #endif diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index c5ad0e1..61fecc8 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -95,6 +95,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv { RADEONInfoPtr info = RADEONPTR(pScrn); PixmapPtr pPixmap = pPriv->pPixmap; + struct radeon_exa_pixmap_priv *driver_priv; + dri_bo *dst_bo; uint32_t txformat; uint32_t txfilter, txformat0, txformat1, txoffset, txpitch; uint32_t dst_offset, dst_pitch, dst_format; @@ -103,19 +105,25 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv int dstxoff, dstyoff, pixel_shift, vtx_count; BoxPtr pBox = REGION_RECTS(&pPriv->clip); int nBox = REGION_NUM_RECTS(&pPriv->clip); + int qwords; ACCEL_PREAMBLE(); pixel_shift = pPixmap->drawable.bitsPerPixel >> 4; #ifdef USE_EXA if (info->useEXA) { - dst_offset = exaGetPixmapOffset(pPixmap) + info->fbLocation + pScrn->fbOffset; + if (info->new_cs) { + driver_priv = exaGetPixmapDriverPrivate(pPixmap); + if (driver_priv) + dst_bo = driver_priv->bo; + } else { + dst_offset = exaGetPixmapOffset(pPixmap); + } dst_pitch = exaGetPixmapPitch(pPixmap); } else #endif { - dst_offset = (pPixmap->devPrivate.ptr - info->FB) + - info->fbLocation + pScrn->fbOffset; + dst_offset = (pPixmap->devPrivate.ptr - info->FB); dst_pitch = pPixmap->devKind; } @@ -210,13 +218,20 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv txoffset = pPriv->src_offset; - BEGIN_ACCEL(6); + qwords = info->new_cs ? 7 : 6; + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(R300_TX_FILTER0_0, txfilter); OUT_ACCEL_REG(R300_TX_FILTER1_0, 0); OUT_ACCEL_REG(R300_TX_FORMAT0_0, txformat0); OUT_ACCEL_REG(R300_TX_FORMAT1_0, txformat1); OUT_ACCEL_REG(R300_TX_FORMAT2_0, txpitch); - OUT_ACCEL_REG(R300_TX_OFFSET_0, txoffset); + if (info->new_cs) { + OUT_ACCEL_REG(R300_TX_OFFSET_0, 0); + OUT_RELOC(pPriv->src_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + txoffset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_TX_OFFSET_0, txoffset); + } FINISH_ACCEL(); txenable = R300_TEX_0_ENABLE; @@ -237,13 +252,19 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv R300_TX_MAG_FILTER_NEAREST | (1 << R300_TX_ID_SHIFT)); - BEGIN_ACCEL(6); + qwords = info->new_cs ? 7 : 6; + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(R300_TX_FILTER0_1, txfilter); OUT_ACCEL_REG(R300_TX_FILTER1_1, 0); OUT_ACCEL_REG(R300_TX_FORMAT0_1, txformat0); OUT_ACCEL_REG(R300_TX_FORMAT1_1, txformat1); OUT_ACCEL_REG(R300_TX_FORMAT2_1, txpitch); - OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset); + if (info->new_cs) { + OUT_ACCEL_REG(R300_TX_OFFSET_1, 0); + OUT_RELOC(pPriv->bicubic_bo, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, 0); + } else { + OUT_ACCEL_REG(R300_TX_OFFSET_1, pPriv->bicubic_src_offset); + } FINISH_ACCEL(); /* Enable tex 1 */ @@ -980,11 +1001,18 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv } } - BEGIN_ACCEL(6); + qwords = info->new_cs ? 7 : 6; + BEGIN_ACCEL(qwords); OUT_ACCEL_REG(R300_TX_INVALTAGS, 0); OUT_ACCEL_REG(R300_TX_ENABLE, txenable); - OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + if (info->new_cs) { + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, 0); + OUT_RELOC(dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); + } else { + dst_offset += info->fbLocation + pScrn->fbOffset; + OUT_ACCEL_REG(R300_RB3D_COLOROFFSET0, dst_offset); + } OUT_ACCEL_REG(R300_RB3D_COLORPITCH0, colorpitch); blendcntl = RADEON_SRC_BLEND_GL_ONE | RADEON_DST_BLEND_GL_ZERO; @@ -1029,6 +1057,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE); OUT_ACCEL_REG(RADEON_RB3D_CNTL, dst_format | RADEON_ALPHA_BLEND_ENABLE); + + dst_offset += info->fbLocation + pScrn->fbOffset; OUT_ACCEL_REG(RADEON_RB3D_COLOROFFSET, dst_offset); OUT_ACCEL_REG(RADEON_RB3D_COLORPITCH, colorpitch); @@ -1066,7 +1096,8 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv ((pPriv->h - 1) << RADEON_TEX_VSIZE_SHIFT)); OUT_ACCEL_REG(R200_PP_TXPITCH_0, pPriv->src_pitch - 32); - OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset); + OUT_ACCEL_REG(R200_PP_TXOFFSET_0, pPriv->src_offset + + info->fbLocation + pScrn->fbOffset); OUT_ACCEL_REG(R200_PP_TXCBLEND_0, R200_TXC_ARG_A_ZERO | @@ -1099,8 +1130,10 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv RADEON_CLAMP_S_CLAMP_LAST | RADEON_CLAMP_T_CLAMP_LAST | RADEON_YUV_TO_RGB); + OUT_ACCEL_REG(RADEON_PP_TXFORMAT_0, txformat); - OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset); + OUT_ACCEL_REG(RADEON_PP_TXOFFSET_0, pPriv->src_offset + + info->fbLocation + pScrn->fbOffset); OUT_ACCEL_REG(RADEON_PP_TXCBLEND_0, RADEON_COLOR_ARG_A_ZERO | RADEON_COLOR_ARG_B_ZERO | diff --git a/src/radeon_video.c b/src/radeon_video.c index 6249cea..5874335 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -257,7 +257,7 @@ void RADEONInitVideo(ScreenPtr pScreen) memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); adaptors = newAdaptors; - if (!IS_AVIVO_VARIANT) { + if (!IS_AVIVO_VARIANT && !info->drm_mode_setting) { overlayAdaptor = RADEONSetupImageVideo(pScreen); if (overlayAdaptor != NULL) { adaptors[num_adaptors++] = overlayAdaptor; @@ -270,7 +270,7 @@ void RADEONInitVideo(ScreenPtr pScreen) if (info->ChipFamily != CHIP_FAMILY_RV250) { if ((info->ChipFamily < CHIP_FAMILY_RS400) #ifdef XF86DRI - || (info->directRenderingEnabled) + || (info->directRenderingEnabled || info->drm_mode_setting) #endif ) { texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen); @@ -2173,7 +2173,7 @@ RADEONCopyData( #ifdef XF86DRI - if ( info->directRenderingEnabled && info->DMAForXv ) + if ( info->directRenderingEnabled && info->DMAForXv && !info->new_cs ) { uint8_t *buf; uint32_t bufPitch, dstPitchOff; diff --git a/src/radeon_video.h b/src/radeon_video.h index 11b8029..a1bd20c 100644 --- a/src/radeon_video.h +++ b/src/radeon_video.h @@ -111,6 +111,9 @@ typedef struct { int src_w, src_h, dst_w, dst_h; int w, h; int drw_x, drw_y; + + dri_bo *src_bo; + dri_bo *bicubic_bo; } RADEONPortPrivRec, *RADEONPortPrivPtr; void RADEONInitI2C(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv);