diff options
-rw-r--r-- | .gitignore | 84 | ||||
-rw-r--r-- | Makefile.am | 10 | ||||
-rw-r--r-- | configure.ac | 13 | ||||
-rw-r--r-- | man/radeon.man | 8 | ||||
-rw-r--r-- | src/.gitignore | 3 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/atombios_output.c | 40 | ||||
-rw-r--r-- | src/drmmode_display.c | 32 | ||||
-rw-r--r-- | src/r600_exa.c | 269 | ||||
-rw-r--r-- | src/r600_state.h | 4 | ||||
-rw-r--r-- | src/r600_textured_videofuncs.c | 76 | ||||
-rw-r--r-- | src/r6xx_accel.c | 206 | ||||
-rw-r--r-- | src/radeon.h | 33 | ||||
-rw-r--r-- | src/radeon_atombios.c | 32 | ||||
-rw-r--r-- | src/radeon_dri2.c | 46 | ||||
-rw-r--r-- | src/radeon_dri2.h | 2 | ||||
-rw-r--r-- | src/radeon_exa.c | 18 | ||||
-rw-r--r-- | src/radeon_exa_render.c | 9 | ||||
-rw-r--r-- | src/radeon_kms.c | 72 | ||||
-rw-r--r-- | src/radeon_modes.c | 2 | ||||
-rw-r--r-- | src/radeon_output.c | 2 | ||||
-rw-r--r-- | src/radeon_textured_video.c | 2 | ||||
-rw-r--r-- | src/radeon_textured_videofuncs.c | 45 | ||||
-rw-r--r-- | src/radeon_vbo.c | 206 | ||||
-rw-r--r-- | src/radeon_vbo.h | 62 | ||||
-rw-r--r-- | src/simple_list.h | 202 |
26 files changed, 997 insertions, 483 deletions
@@ -1,36 +1,80 @@ -*~ -*.la -*.lo -.#* -.deps -.libs -Makefile -Makefile.in +# +# X.Org module default exclusion patterns +# The next section if for module specific patterns +# +# Do not edit the following section +# GNU Build System (Autotools) aclocal.m4 -ati.4 -ati.4x -autom4te.cache +autom4te.cache/ +autoscan.log +ChangeLog compile config.guess config.h config.h.in config.log +config-ml.in +config.py config.status +config.status.lineno config.sub configure -configure.lineno -cscope.files -cscope.out +configure.scan depcomp +.deps/ +INSTALL install-sh +.libs/ libtool +libtool.m4 ltmain.sh +lt~obsolete.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +Makefile +Makefile.in +mdate-sh missing -r128.4 -r128.4x -radeon.4 -radeon.4x -stamp-h1 -*cscope* +mkinstalldirs +*.pc +py-compile +stamp-h? +symlink-tree +texinfo.tex +ylwrap + +# Do not edit the following section +# Edit Compile Debug Document Distribute +*~ +*.[0-9] +*.[0-9]x +*.bak +*.bin +core +*.dll +*.exe +*-ISO*.bdf +*-JIS*.bdf +*-KOI8*.bdf +*.kld +*.ko +*.ko.cmd +*.lai +*.l[oa] +*.[oa] +*.obj +*.patch +*.so +*.pcf.gz +*.pdb +*.tar.bz2 +*.tar.gz +# +# Add & Override patterns for xf86-video-ati +# +# Edit the following section as needed +# For example, !report.pc overrides *.pc. See 'man gitignore' +# shave shave-libtool diff --git a/Makefile.am b/Makefile.am index e76bf118..4c278ba7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,15 +18,15 @@ # 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. -AUTOMAKE_OPTIONS = foreign SUBDIRS = src man +MAINTAINERCLEANFILES = ChangeLog INSTALL -EXTRA_DIST = ChangeLog -CLEANFILES = ChangeLog +.PHONY: ChangeLog INSTALL -.PHONY: ChangeLog +INSTALL: + $(INSTALL_CMD) ChangeLog: $(CHANGELOG_CMD) -dist-hook: ChangeLog +dist-hook: ChangeLog INSTALL diff --git a/configure.ac b/configure.ac index 162c8394..6b3c4c6c 100644 --- a/configure.ac +++ b/configure.ac @@ -29,13 +29,15 @@ AC_INIT([xf86-video-ati], AC_CONFIG_SRCDIR([Makefile.am]) AM_CONFIG_HEADER([config.h]) -# Require xorg-macros: XORG_RELEASE_VERSION XORG_CHANGELOG -m4_ifndef([XORG_MACROS_VERSION], [AC_FATAL([must install xorg-macros 1.2 or later before running autoconf/autogen])]) -XORG_MACROS_VERSION(1.2) +# Require xorg-macros: XORG_DEFAULT_OPTIONS +m4_ifndef([XORG_MACROS_VERSION], + [m4_fatal([must install xorg-macros 1.3 or later before running autoconf/autogen])]) +XORG_MACROS_VERSION(1.3) +XORG_DEFAULT_OPTIONS AC_CONFIG_AUX_DIR(.) -AM_INIT_AUTOMAKE([dist-bzip2]) +AM_INIT_AUTOMAKE([foreign dist-bzip2]) AC_SYS_LARGEFILE AM_MAINTAINER_MODE @@ -363,10 +365,7 @@ AC_SUBST([moduledir]) DRIVER_NAME=ati AC_SUBST([DRIVER_NAME]) -XORG_MANPAGE_SECTIONS -XORG_RELEASE_VERSION XORG_CHECK_LINUXDOC -XORG_CHANGELOG AC_MSG_NOTICE( [The atimisc sub-driver has been split out to xf86-video-mach64:] diff --git a/man/radeon.man b/man/radeon.man index 47fa9f5e..0ea866fe 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -606,6 +606,14 @@ The default is This option enables modesetting on R/RV4xx chips using atombios. The default is .B off. +.TP +.BI "Option \*qEXAPixmaps\*q \*q" boolean \*q +(KMS Only) Under kernel modesetting to avoid thrashing pixmaps in/out +of VRAM on low memory cards, we use a heuristic based on VRAM amount, +to determine whether to allow EXA to use VRAM for non-essential pixmaps. +This option allows us to override the heurisitc. +The default is +.B on with > 32MB VRAM, off with < 32MB. .SH TEXTURED VIDEO ATTRIBUTES The driver supports the following X11 Xv attributes for Textured Video. diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 00000000..9147dc10 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,3 @@ +# Add & Override for this directory and it's subdirectories +modes +parser diff --git a/src/Makefile.am b/src/Makefile.am index 93f237cb..a431d2e5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -66,7 +66,7 @@ XMODE_SRCS=\ modes/xf86DiDGA.c if XF86DRM_MODE -RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c +RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c endif if USE_EXA diff --git a/src/atombios_output.c b/src/atombios_output.c index eb643ce4..8047b534 100644 --- a/src/atombios_output.c +++ b/src/atombios_output.c @@ -1316,21 +1316,29 @@ atombios_output_dpms(xf86OutputPtr output, int mode) break; case ENCODER_OBJECT_ID_INTERNAL_DAC1: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1: - if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) - index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); - else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) - index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); - else + if (IS_DCE32_VARIANT) index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); + else { + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC1OutputControl); + } break; case ENCODER_OBJECT_ID_INTERNAL_DAC2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2: - if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) - index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); - else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) - index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); - else + if (IS_DCE32_VARIANT) index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); + else { + if (radeon_output->active_device & (ATOM_DEVICE_TV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, TV1OutputControl); + else if (radeon_output->active_device & (ATOM_DEVICE_CV_SUPPORT)) + index = GetIndexIntoMasterTable(COMMAND, CV1OutputControl); + else + index = GetIndexIntoMasterTable(COMMAND, DAC2OutputControl); + } break; } @@ -1556,6 +1564,18 @@ atombios_apply_output_quirks(xf86OutputPtr output, DisplayModePtr mode) if (IS_AVIVO_VARIANT && (mode->Flags & V_INTERLACE)) OUTREG(AVIVO_D1MODE_DATA_FORMAT + radeon_crtc->crtc_offset, AVIVO_D1MODE_INTERLEAVE_EN); } + + if (IS_DCE32_VARIANT && (radeon_output->active_device & (ATOM_DEVICE_DFP_SUPPORT))) { + radeon_encoder_ptr radeon_encoder = radeon_get_encoder(output); + if (radeon_encoder == NULL) + return; + /* XXX: need to sort out why transmitter control table sometimes sets this to a + * different golden value. + */ + if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_UNIPHY2) { + OUTREG(0x7ec4, 0x00824002); + } + } } void diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 29c3ff17..38f73735 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -204,6 +204,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) int crtc_id = 0; int i; int pitch = pScrn->displayWidth * info->CurrentLayout.pixel_bytes; + Bool ret; if (info->accelOn == FALSE) return; @@ -228,8 +229,10 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode) if (!dst) goto out_free_src; - info->accel_state->exa->PrepareCopy (src, dst, - -1, -1, GXcopy, FB_ALLONES); + ret = info->accel_state->exa->PrepareCopy (src, dst, + -1, -1, GXcopy, FB_ALLONES); + if (!ret) + goto out_free_src; info->accel_state->exa->Copy (dst, 0, 0, 0, 0, pScrn->virtualX, pScrn->virtualY); info->accel_state->exa->DoneCopy (dst); @@ -1017,11 +1020,13 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) int cpp = info->CurrentLayout.pixel_bytes; struct radeon_bo *front_bo; uint32_t tiling_flags = 0; + PixmapPtr ppix = screen->GetScreenPixmap(screen); + void *fb_shadow; if (scrn->virtualX == width && scrn->virtualY == height) return TRUE; - front_bo = radeon_get_pixmap_bo(screen->GetScreenPixmap(screen)); + front_bo = info->front_bo; radeon_cs_flush_indirect(scrn); if (front_bo) @@ -1073,9 +1078,23 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (ret) goto fail; - radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->front_bo); - screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), - width, height, -1, -1, pitch * cpp, NULL); + if (!info->r600_shadow_fb) { + radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), info->front_bo); + screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), + width, height, -1, -1, pitch * cpp, NULL); + } else { + if (radeon_bo_map(info->front_bo, 1)) + goto fail; + fb_shadow = xcalloc(1, screen_size); + if (fb_shadow == NULL) + goto fail; + xfree(info->fb_shadow); + info->fb_shadow = fb_shadow; + screen->ModifyPixmapHeader(screen->GetScreenPixmap(screen), + width, height, -1, -1, pitch * cpp, + info->fb_shadow); + } + scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr; // xf86DrvMsg(scrn->scrnIndex, X_INFO, "New front buffer at 0x%lx\n", // info->front_bo-); @@ -1095,6 +1114,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) if (old_front) radeon_bo_unref(old_front); + radeon_kms_update_vram_limit(scrn, screen_size); return TRUE; fail: diff --git a/src/r600_exa.c b/src/r600_exa.c index ca1a1fae..634e6cac 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -38,7 +38,7 @@ #include "r600_shader.h" #include "r600_reg.h" #include "r600_state.h" - +#include "radeon_vbo.h" #define RADEON_TRACE_FALL 0 #define RADEON_TRACE_DRAW 0 @@ -217,15 +217,9 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) pPix->drawable.bitsPerPixel, exaGetPixmapPitch(pPix)); #endif + radeon_vbo_check(pScrn, 16); r600_cp_start(pScrn); - /* Init */ -#if defined(XF86DRM_MODE) - if (info->cs) - accel_state->XInited3D = FALSE; -#endif - start_3d(pScrn, accel_state->ib); - set_default_state(pScrn, accel_state->ib); set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPix->drawable.width, pPix->drawable.height); @@ -367,16 +361,9 @@ static void R600Solid(PixmapPtr pPix, int x1, int y1, int x2, int y2) { ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; float *vb; - if (((accel_state->vb_index + 3) * 8) > accel_state->vb_total) { - R600DoneSolid(pPix); - r600_cp_start(pScrn); - } - - vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*8); + vb = radeon_vbo_space(pScrn, 8); vb[0] = (float)x1; vb[1] = (float)y1; @@ -387,70 +374,15 @@ R600Solid(PixmapPtr pPix, int x1, int y1, int x2, int y2) vb[4] = (float)x2; vb[5] = (float)y2; - accel_state->vb_index += 3; - + radeon_vbo_commit(pScrn); } static void R600DoneSolid(PixmapPtr pPix) { ScrnInfoPtr pScrn = xf86Screens[pPix->drawable.pScreen->myNum]; - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; - draw_config_t draw_conf; - vtx_resource_t vtx_res; - CLEAR (draw_conf); - CLEAR (vtx_res); - - if (accel_state->vb_index == 0) { - R600IBDiscard(pScrn, accel_state->ib); - r600_vb_discard(pScrn); - return; - } - - accel_state->vb_size = accel_state->vb_index * 8; - - /* flush vertex cache */ - if ((info->ChipFamily == CHIP_FAMILY_RV610) || - (info->ChipFamily == CHIP_FAMILY_RV620) || - (info->ChipFamily == CHIP_FAMILY_RS780) || - (info->ChipFamily == CHIP_FAMILY_RS880) || - (info->ChipFamily == CHIP_FAMILY_RV710)) - cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - else - cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - - /* Vertex buffer setup */ - vtx_res.id = SQ_VTX_RESOURCE_vs; - vtx_res.vtx_size_dw = 8 / 4; - vtx_res.vtx_num_entries = accel_state->vb_size / 4; - vtx_res.mem_req_size = 1; - vtx_res.vb_addr = accel_state->vb_mc_addr; - vtx_res.bo = accel_state->vb_bo; - set_vtx_resource (pScrn, accel_state->ib, &vtx_res); - - /* Draw */ - draw_conf.prim_type = DI_PT_RECTLIST; - draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX; - draw_conf.num_instances = 1; - draw_conf.num_indices = vtx_res.vtx_num_entries / vtx_res.vtx_size_dw; - draw_conf.index_type = DI_INDEX_SIZE_16_BIT; - - draw_auto(pScrn, accel_state->ib, &draw_conf); - - wait_3d_idle_clean(pScrn, accel_state->ib); - - /* sync dst surface */ - cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit), - accel_state->dst_size, accel_state->dst_mc_addr, - accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0); - - R600CPFlushIndirect(pScrn, accel_state->ib); + r600_finish_op(pScrn, 8); } static void @@ -491,15 +423,9 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn, accel_state->dst_bpp = dst_bpp; accel_state->dst_bo = dst_bo; + radeon_vbo_check(pScrn, 16); r600_cp_start(pScrn); - /* Init */ -#if defined(XF86DRM_MODE) - if (info->cs) - accel_state->XInited3D = FALSE; -#endif - start_3d(pScrn, accel_state->ib); - set_default_state(pScrn, accel_state->ib); set_generic_scissor(pScrn, accel_state->ib, 0, 0, dst_width, dst_height); @@ -651,66 +577,13 @@ R600DoPrepareCopy(ScrnInfoPtr pScrn, SEL_CENTROID_bit)); EREG(accel_state->ib, SPI_INTERP_CONTROL_0, 0); END_BATCH(); + } static void R600DoCopy(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; - draw_config_t draw_conf; - vtx_resource_t vtx_res; - - CLEAR (draw_conf); - CLEAR (vtx_res); - - if (accel_state->vb_index == 0) { - R600IBDiscard(pScrn, accel_state->ib); - r600_vb_discard(pScrn); - return; - } - - accel_state->vb_size = accel_state->vb_index * 16; - - /* flush vertex cache */ - if ((info->ChipFamily == CHIP_FAMILY_RV610) || - (info->ChipFamily == CHIP_FAMILY_RV620) || - (info->ChipFamily == CHIP_FAMILY_RS780) || - (info->ChipFamily == CHIP_FAMILY_RS880) || - (info->ChipFamily == CHIP_FAMILY_RV710)) - cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - else - cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - - /* Vertex buffer setup */ - vtx_res.id = SQ_VTX_RESOURCE_vs; - vtx_res.vtx_size_dw = 16 / 4; - vtx_res.vtx_num_entries = accel_state->vb_size / 4; - vtx_res.mem_req_size = 1; - vtx_res.vb_addr = accel_state->vb_mc_addr; - vtx_res.bo = accel_state->vb_bo; - set_vtx_resource (pScrn, accel_state->ib, &vtx_res); - - draw_conf.prim_type = DI_PT_RECTLIST; - draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX; - draw_conf.num_instances = 1; - draw_conf.num_indices = vtx_res.vtx_num_entries / vtx_res.vtx_size_dw; - draw_conf.index_type = DI_INDEX_SIZE_16_BIT; - - draw_auto(pScrn, accel_state->ib, &draw_conf); - - wait_3d_idle_clean(pScrn, accel_state->ib); - - /* sync dst surface */ - cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit), - accel_state->dst_size, accel_state->dst_mc_addr, - accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0); - - R600CPFlushIndirect(pScrn, accel_state->ib); + r600_finish_op(pScrn, 16); } static void @@ -719,16 +592,9 @@ R600AppendCopyVertex(ScrnInfoPtr pScrn, int dstX, int dstY, int w, int h) { - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; float *vb; - if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) { - R600DoCopy(pScrn); - r600_cp_start(pScrn); - } - - vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16); + vb = radeon_vbo_space(pScrn, 16); vb[0] = (float)dstX; vb[1] = (float)dstY; @@ -745,7 +611,7 @@ R600AppendCopyVertex(ScrnInfoPtr pScrn, vb[10] = (float)(srcX + w); vb[11] = (float)(srcY + h); - accel_state->vb_index += 3; + radeon_vbo_commit(pScrn); } static Bool @@ -757,7 +623,6 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; - int ret; if (!R600CheckBPP(pSrc->drawable.bitsPerPixel)) RADEON_FALLBACK(("R600CheckDatatype src failed\n")); @@ -809,6 +674,8 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, #if defined(XF86DRM_MODE) if (info->cs) { + int ret; + radeon_cs_space_reset_bos(info->cs); radeon_cs_space_add_persistent_bo(info->cs, accel_state->shaders_bo, RADEON_GEM_DOMAIN_VRAM, 0); @@ -845,7 +712,6 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, RADEON_GEM_DOMAIN_VRAM, 0); if (accel_state->copy_area_bo == NULL) { - R600IBDiscard(pScrn, accel_state->ib); return FALSE; } radeon_cs_space_add_persistent_bo(info->cs, accel_state->copy_area_bo, @@ -853,7 +719,6 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, if (radeon_cs_space_check(info->cs)) { radeon_bo_unref(accel_state->copy_area_bo); accel_state->copy_area_bo = NULL; - R600IBDiscard(pScrn, accel_state->ib); return FALSE; } accel_state->copy_area = (void*)accel_state->copy_area_bo; @@ -1654,7 +1519,6 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, uint32_t blendcntl, dst_format; cb_config_t cb_conf; shader_config_t vs_conf, ps_conf; - int ret; /* return FALSE; */ @@ -1681,6 +1545,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, #if defined(XF86DRM_MODE) if (info->cs) { + int ret; + accel_state->dst_mc_addr = 0; accel_state->dst_bo = radeon_get_pixmap_bo(pDst); accel_state->src_bo[0] = radeon_get_pixmap_bo(pSrc); @@ -1717,14 +1583,12 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, CLEAR (vs_conf); CLEAR (ps_conf); - r600_cp_start(pScrn); + if (pMask) + radeon_vbo_check(pScrn, 24); + else + radeon_vbo_check(pScrn, 16); - /* Init */ -#if defined(XF86DRM_MODE) - if (info->cs) - accel_state->XInited3D = FALSE; -#endif - start_3d(pScrn, accel_state->ib); + r600_cp_start(pScrn); set_default_state(pScrn, accel_state->ib); @@ -1906,12 +1770,8 @@ static void R600Composite(PixmapPtr pDst, srcX, srcY, maskX, maskY,dstX, dstY, w, h); */ if (accel_state->msk_pic) { - if (((accel_state->vb_index + 3) * 24) > accel_state->vb_total) { - R600DoneComposite(pDst); - r600_cp_start(pScrn); - } - vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*24); + vb = radeon_vbo_space(pScrn, 24); vb[0] = (float)dstX; vb[1] = (float)dstY; @@ -1934,13 +1794,11 @@ static void R600Composite(PixmapPtr pDst, vb[16] = (float)(maskX + w); vb[17] = (float)(maskY + h); + radeon_vbo_commit(pScrn); + } else { - if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) { - R600DoneComposite(pDst); - r600_cp_start(pScrn); - } - vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16); + vb = radeon_vbo_space(pScrn, 16); vb[0] = (float)dstX; vb[1] = (float)dstY; @@ -1956,9 +1814,10 @@ static void R600Composite(PixmapPtr pDst, vb[9] = (float)(dstY + h); vb[10] = (float)(srcX + w); vb[11] = (float)(srcY + h); + + radeon_vbo_commit(pScrn); } - accel_state->vb_index += 3; } @@ -1967,68 +1826,11 @@ static void R600DoneComposite(PixmapPtr pDst) ScrnInfoPtr pScrn = xf86Screens[pDst->drawable.pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; - draw_config_t draw_conf; - vtx_resource_t vtx_res; - - CLEAR (draw_conf); - CLEAR (vtx_res); - - if (accel_state->vb_index == 0) { - R600IBDiscard(pScrn, accel_state->ib); - r600_vb_discard(pScrn); - return; - } - - /* Vertex buffer setup */ - if (accel_state->msk_pic) { - accel_state->vb_size = accel_state->vb_index * 24; - vtx_res.id = SQ_VTX_RESOURCE_vs; - vtx_res.vtx_size_dw = 24 / 4; - vtx_res.vtx_num_entries = accel_state->vb_size / 4; - vtx_res.mem_req_size = 1; - vtx_res.vb_addr = accel_state->vb_mc_addr; - vtx_res.bo = accel_state->vb_bo; - } else { - accel_state->vb_size = accel_state->vb_index * 16; - vtx_res.id = SQ_VTX_RESOURCE_vs; - vtx_res.vtx_size_dw = 16 / 4; - vtx_res.vtx_num_entries = accel_state->vb_size / 4; - vtx_res.mem_req_size = 1; - vtx_res.vb_addr = accel_state->vb_mc_addr; - vtx_res.bo = accel_state->vb_bo; - } - /* flush vertex cache */ - if ((info->ChipFamily == CHIP_FAMILY_RV610) || - (info->ChipFamily == CHIP_FAMILY_RV620) || - (info->ChipFamily == CHIP_FAMILY_RS780) || - (info->ChipFamily == CHIP_FAMILY_RS880) || - (info->ChipFamily == CHIP_FAMILY_RV710)) - cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - else - cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - - set_vtx_resource(pScrn, accel_state->ib, &vtx_res); - - draw_conf.prim_type = DI_PT_RECTLIST; - draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX; - draw_conf.num_instances = 1; - draw_conf.num_indices = vtx_res.vtx_num_entries / vtx_res.vtx_size_dw; - draw_conf.index_type = DI_INDEX_SIZE_16_BIT; + int vtx_size; - draw_auto(pScrn, accel_state->ib, &draw_conf); - - wait_3d_idle_clean(pScrn, accel_state->ib); - - cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit), - accel_state->dst_size, accel_state->dst_mc_addr, - accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0); - - R600CPFlushIndirect(pScrn, accel_state->ib); + vtx_size = accel_state->msk_pic ? 24 : 16; + r600_finish_op(pScrn, vtx_size); } Bool @@ -2336,6 +2138,9 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, 3, 0xffffffff); R600AppendCopyVertex(pScrn, x, y, 0, 0, w, h); R600DoCopy(pScrn); + + if (info->cs) + radeon_cs_flush_indirect(pScrn); r = radeon_bo_map(scratch, 0); if (r) { @@ -2575,9 +2380,9 @@ R600DrawInit(ScreenPtr pScreen) #ifdef EXA_HANDLES_PIXMAPS if (info->cs) { info->accel_state->exa->flags |= EXA_HANDLES_PIXMAPS; -//#ifdef EXA_MIXED_PIXMAPS -// info->accel_state->exa->flags |= EXA_MIXED_PIXMAPS; -//#endif +#ifdef EXA_MIXED_PIXMAPS + info->accel_state->exa->flags |= EXA_MIXED_PIXMAPS; +#endif } #endif #endif @@ -2621,7 +2426,11 @@ R600DrawInit(ScreenPtr pScreen) info->accel_state->src_bo[1] = NULL; info->accel_state->dst_bo = NULL; info->accel_state->copy_area_bo = NULL; - info->accel_state->vb_bo = NULL; + info->accel_state->vb_start_op = -1; + +#ifdef XF86DRM_MODE + radeon_vbo_init_lists(pScrn); +#endif if (!R600AllocShaders(pScrn, pScreen)) return FALSE; diff --git a/src/r600_state.h b/src/r600_state.h index 46c18f9d..0ee480bc 100644 --- a/src/r600_state.h +++ b/src/r600_state.h @@ -206,7 +206,7 @@ do { \ } \ } while (0) #else -#define BEGIN_BATCH(n) do {} while(0) +#define BEGIN_BATCH(n) do {(void)info;} while(0) #define END_BATCH() do {} while(0) #define RELOC_BATCH(bo, wd, rd) do {} while(0) #define E32(ib, dword) \ @@ -326,6 +326,7 @@ void r600_vb_discard(ScrnInfoPtr pScrn); int r600_cp_start(ScrnInfoPtr pScrn); +void r600_finish_op(ScrnInfoPtr pScrn, int vtx_size); extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index); extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index); @@ -334,4 +335,5 @@ extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv); extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix); extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix); + #endif diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c index 7598429f..69deb815 100644 --- a/src/r600_textured_videofuncs.c +++ b/src/r600_textured_videofuncs.c @@ -45,6 +45,8 @@ #include "damage.h" +#include "radeon_vbo.h" + /* Parameters for ITU-R BT.601 and ITU-R BT.709 colour spaces note the difference to the parameters used in overlay are due to 10bit vs. float calcs */ @@ -57,61 +59,7 @@ static REF_TRANSFORM trans[2] = static void R600DoneTexturedVideo(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_accel_state *accel_state = info->accel_state; - draw_config_t draw_conf; - vtx_resource_t vtx_res; - - CLEAR (draw_conf); - CLEAR (vtx_res); - - if (accel_state->vb_index == 0) { - R600IBDiscard(pScrn, accel_state->ib); - r600_vb_discard(pScrn); - return; - } - - accel_state->vb_size = accel_state->vb_index * 16; - - /* flush vertex cache */ - if ((info->ChipFamily == CHIP_FAMILY_RV610) || - (info->ChipFamily == CHIP_FAMILY_RV620) || - (info->ChipFamily == CHIP_FAMILY_RS780) || - (info->ChipFamily == CHIP_FAMILY_RS880) || - (info->ChipFamily == CHIP_FAMILY_RV710)) - cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - else - cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit, - accel_state->vb_size, accel_state->vb_mc_addr, - accel_state->vb_bo, RADEON_GEM_DOMAIN_GTT, 0); - - /* Vertex buffer setup */ - vtx_res.id = SQ_VTX_RESOURCE_vs; - vtx_res.vtx_size_dw = 16 / 4; - vtx_res.vtx_num_entries = accel_state->vb_size / 4; - vtx_res.mem_req_size = 1; - vtx_res.vb_addr = accel_state->vb_mc_addr; - vtx_res.bo = accel_state->vb_bo; - set_vtx_resource (pScrn, accel_state->ib, &vtx_res); - - draw_conf.prim_type = DI_PT_RECTLIST; - draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX; - draw_conf.num_instances = 1; - draw_conf.num_indices = vtx_res.vtx_num_entries / vtx_res.vtx_size_dw; - draw_conf.index_type = DI_INDEX_SIZE_16_BIT; - - draw_auto(pScrn, accel_state->ib, &draw_conf); - - wait_3d_idle_clean(pScrn, accel_state->ib); - - /* sync destination surface */ - cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit), - accel_state->dst_size, accel_state->dst_mc_addr, - accel_state->dst_bo, 0, RADEON_GEM_DOMAIN_VRAM); - - R600CPFlushIndirect(pScrn, accel_state->ib); + r600_finish_op(pScrn, 16); } void @@ -260,15 +208,9 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) dstyoff = 0; #endif + radeon_vbo_check(pScrn, 16); r600_cp_start(pScrn); - /* Init */ -#if defined(XF86DRM_MODE) - if (info->cs) - accel_state->XInited3D = FALSE; -#endif - start_3d(pScrn, accel_state->ib); - set_default_state(pScrn, accel_state->ib); set_generic_scissor(pScrn, accel_state->ib, 0, 0, pPixmap->drawable.width, pPixmap->drawable.height); @@ -595,12 +537,6 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) int dstX, dstY, dstw, dsth; float *vb; - if (((accel_state->vb_index + 3) * 16) > accel_state->vb_total) { - R600DoneTexturedVideo(pScrn); - r600_cp_start(pScrn); - } - - vb = (pointer)((char*)accel_state->vb_ptr+accel_state->vb_index*16); dstX = pBox->x1 + dstxoff; dstY = pBox->y1 + dstyoff; @@ -617,6 +553,8 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) srcw = (pPriv->src_w * dstw) / pPriv->dst_w; srch = (pPriv->src_h * dsth) / pPriv->dst_h; + vb = radeon_vbo_space(pScrn, 16); + vb[0] = (float)dstX; vb[1] = (float)dstY; vb[2] = (float)srcX; @@ -632,7 +570,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) vb[10] = (float)(srcX + srcw); vb[11] = (float)(srcY + srch); - accel_state->vb_index += 3; + radeon_vbo_commit(pScrn); pBox++; } diff --git a/src/r6xx_accel.c b/src/r6xx_accel.c index dd74d468..0ca942ef 100644 --- a/src/r6xx_accel.c +++ b/src/r6xx_accel.c @@ -38,29 +38,11 @@ #include "r600_state.h" #include "radeon_drm.h" +#include "radeon_vbo.h" -#if defined(XF86DRM_MODE) -void r600_cs_flush_indirect(ScrnInfoPtr pScrn) -{ - RADEONInfoPtr info = RADEONPTR(pScrn); - int ret; - - if (!info->cs->cdw) - return; - - if (info->accel_state->vb_ptr) { - radeon_bo_unmap(info->accel_state->vb_bo); - info->accel_state->vb_ptr = NULL; - } - - radeon_cs_emit(info->cs); - radeon_cs_erase(info->cs); - - ret = radeon_cs_space_check(info->cs); - if (ret) - ErrorF("space check failed in flush\n"); -} -#endif +/* we try and batch operations together under KMS - + but it doesn't work yet without misrendering */ +#define KMS_MULTI_OP 1 /* Flush the indirect buffer to the kernel for submission to the card */ void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib) @@ -72,7 +54,7 @@ void R600CPFlushIndirect(ScrnInfoPtr pScrn, drmBufPtr ib) #if defined(XF86DRM_MODE) if (info->cs) { - r600_cs_flush_indirect(pScrn); + radeon_cs_flush_indirect(pScrn); return; } #endif @@ -106,12 +88,21 @@ void R600IBDiscard(ScrnInfoPtr pScrn, drmBufPtr ib) int ret; RADEONInfoPtr info = RADEONPTR(pScrn); if (info->cs) { + if (info->accel_state->ib_reset_op) { + /* if we have data just reset the CS and ignore the operation */ + info->cs->cdw = info->accel_state->ib_reset_op; + info->accel_state->ib_reset_op = 0; + return; + } if (info->accel_state->vb_ptr) { - radeon_bo_unmap(info->accel_state->vb_bo); info->accel_state->vb_ptr = NULL; - } + } + + info->accel_state->vb_offset = 0; + info->accel_state->vb_start_op = -1; + if (CS_FULL(info->cs)) { - r600_cs_flush_indirect(pScrn); + radeon_cs_flush_indirect(pScrn); return; } radeon_cs_erase(info->cs); @@ -738,15 +729,15 @@ set_default_state(ScrnInfoPtr pScrn, drmBufPtr ib) RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; - memset(&tex_res, 0, sizeof(tex_resource_t)); - memset(&fs_conf, 0, sizeof(shader_config_t)); - if (accel_state->XInited3D) return; + memset(&tex_res, 0, sizeof(tex_resource_t)); + memset(&fs_conf, 0, sizeof(shader_config_t)); + accel_state->XInited3D = TRUE; - wait_3d_idle(pScrn, ib); + start_3d(pScrn, accel_state->ib); // ASIC specific setup, see drm BEGIN_BATCH(15); @@ -1178,44 +1169,27 @@ r600_vb_get(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_accel_state *accel_state = info->accel_state; -#if defined(XF86DRM_MODE) - int ret; - if (info->cs) { - if (accel_state->vb_bo == NULL) { - accel_state->vb_mc_addr = 0; - accel_state->vb_bo = radeon_bo_open(info->bufmgr, 0, 16 * 1024, - 0, RADEON_GEM_DOMAIN_GTT, 0); - if (accel_state->vb_bo == NULL) - return FALSE; - accel_state->vb_total = 16 * 1024; - } - if (!accel_state->vb_ptr) { - ret = radeon_bo_map(accel_state->vb_bo, 1); - if (ret) { - FatalError("failed to vb %d\n", ret); - return FALSE; - } - accel_state->vb_ptr = accel_state->vb_bo->ptr; - } - } else -#endif - { - accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart + - (accel_state->ib->idx*accel_state->ib->total)+ - (accel_state->ib->total / 2); - accel_state->vb_total = (accel_state->ib->total / 2); - accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address + - (accel_state->ib->total / 2)); - } - accel_state->vb_index = 0; + + accel_state->vb_mc_addr = info->gartLocation + info->dri->bufStart + + (accel_state->ib->idx*accel_state->ib->total)+ + (accel_state->ib->total / 2); + accel_state->vb_total = (accel_state->ib->total / 2); + accel_state->vb_ptr = (pointer)((char*)accel_state->ib->address + + (accel_state->ib->total / 2)); + accel_state->vb_offset = 0; return TRUE; } void r600_vb_discard(ScrnInfoPtr pScrn) { + RADEONInfoPtr info = RADEONPTR(pScrn); + + info->accel_state->vb_start_op = -1; } + + int r600_cp_start(ScrnInfoPtr pScrn) { @@ -1224,13 +1198,11 @@ r600_cp_start(ScrnInfoPtr pScrn) #if defined(XF86DRM_MODE) if (info->cs) { - if (!r600_vb_get(pScrn)) - return -1; - if (accel_state->vb_bo) - radeon_cs_space_add_persistent_bo(info->cs, accel_state->vb_bo, - RADEON_GEM_DOMAIN_GTT, 0); - - radeon_cs_space_check(info->cs); + if (CS_FULL(info->cs)) { + radeon_cs_flush_indirect(pScrn); + } + accel_state->ib_reset_op = info->cs->cdw; + accel_state->vb_start_op = accel_state->vb_offset; } else #endif { @@ -1238,6 +1210,106 @@ r600_cp_start(ScrnInfoPtr pScrn) if (!r600_vb_get(pScrn)) { return -1; } + accel_state->vb_start_op = accel_state->vb_offset; } return 0; } + +void r600_finish_op(ScrnInfoPtr pScrn, int vtx_size) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + draw_config_t draw_conf; + vtx_resource_t vtx_res; + + if (accel_state->vb_start_op == -1) + return; + + CLEAR (draw_conf); + CLEAR (vtx_res); + + if (accel_state->vb_offset == accel_state->vb_start_op) { + R600IBDiscard(pScrn, accel_state->ib); + r600_vb_discard(pScrn); + return; + } + + /* flush vertex cache */ + if ((info->ChipFamily == CHIP_FAMILY_RV610) || + (info->ChipFamily == CHIP_FAMILY_RV620) || + (info->ChipFamily == CHIP_FAMILY_RS780) || + (info->ChipFamily == CHIP_FAMILY_RS880) || + (info->ChipFamily == CHIP_FAMILY_RV710)) + cp_set_surface_sync(pScrn, accel_state->ib, TC_ACTION_ENA_bit, + accel_state->vb_offset, accel_state->vb_mc_addr, + accel_state->vb_bo, + RADEON_GEM_DOMAIN_GTT, 0); + else + cp_set_surface_sync(pScrn, accel_state->ib, VC_ACTION_ENA_bit, + accel_state->vb_offset, accel_state->vb_mc_addr, + accel_state->vb_bo, + RADEON_GEM_DOMAIN_GTT, 0); + + /* Vertex buffer setup */ + accel_state->vb_size = accel_state->vb_offset - accel_state->vb_start_op; + vtx_res.id = SQ_VTX_RESOURCE_vs; + vtx_res.vtx_size_dw = vtx_size / 4; + vtx_res.vtx_num_entries = accel_state->vb_size / 4; + vtx_res.mem_req_size = 1; + vtx_res.vb_addr = accel_state->vb_mc_addr + accel_state->vb_start_op; + vtx_res.bo = accel_state->vb_bo; + set_vtx_resource (pScrn, accel_state->ib, &vtx_res); + + /* Draw */ + draw_conf.prim_type = DI_PT_RECTLIST; + draw_conf.vgt_draw_initiator = DI_SRC_SEL_AUTO_INDEX; + draw_conf.num_instances = 1; + draw_conf.num_indices = vtx_res.vtx_num_entries / vtx_res.vtx_size_dw; + draw_conf.index_type = DI_INDEX_SIZE_16_BIT; + + draw_auto(pScrn, accel_state->ib, &draw_conf); + + wait_3d_idle_clean(pScrn, accel_state->ib); + + /* sync dst surface */ + cp_set_surface_sync(pScrn, accel_state->ib, (CB_ACTION_ENA_bit | CB0_DEST_BASE_ENA_bit), + accel_state->dst_size, accel_state->dst_mc_addr, + accel_state->dst_bo, RADEON_GEM_DOMAIN_VRAM, 0); + + wait_3d_idle_clean(pScrn, accel_state->ib); + + accel_state->vb_start_op = -1; + accel_state->ib_reset_op = 0; + +#if KMS_MULTI_OP + if (!info->cs) +#endif + R600CPFlushIndirect(pScrn, accel_state->ib); +} + +void r600_vb_no_space(ScrnInfoPtr pScrn, int vert_size) +{ +#ifdef XF86DRM_MODE + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + if (info->cs) { + if (accel_state->vb_bo) { + if (accel_state->vb_start_op != accel_state->vb_offset) { + r600_finish_op(pScrn, vert_size); + accel_state->ib_reset_op = info->cs->cdw; + } + + /* release the current VBO */ + radeon_vbo_put(pScrn); + } + + /* get a new one */ + radeon_vbo_get(pScrn); + return; + } +#endif + + r600_finish_op(pScrn, vert_size); + r600_cp_start(pScrn); +} diff --git a/src/radeon.h b/src/radeon.h index fc43df69..c9f388ad 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -100,6 +100,7 @@ #include "picturestr.h" #endif +#include "simple_list.h" #include "atipcirename.h" #ifndef MAX @@ -173,6 +174,7 @@ typedef enum { OPTION_PCIAPER_SIZE, #ifdef USE_EXA OPTION_ACCEL_DFS, + OPTION_EXA_PIXMAPS, #endif #endif OPTION_IGNORE_EDID, @@ -382,6 +384,12 @@ typedef enum { (info->ChipFamily == CHIP_FAMILY_RV560) || \ (info->ChipFamily == CHIP_FAMILY_RV570)) +#define IS_R400_3D ((info->ChipFamily == CHIP_FAMILY_R420) || \ + (info->ChipFamily == CHIP_FAMILY_RV410) || \ + (info->ChipFamily == CHIP_FAMILY_RS690) || \ + (info->ChipFamily == CHIP_FAMILY_RS600) || \ + (info->ChipFamily == CHIP_FAMILY_RS740)) + #define IS_R300_3D ((info->ChipFamily == CHIP_FAMILY_R300) || \ (info->ChipFamily == CHIP_FAMILY_RV350) || \ (info->ChipFamily == CHIP_FAMILY_R350) || \ @@ -645,6 +653,14 @@ struct radeon_dri { }; #endif +#define DMA_BO_FREE_TIME 1000 + +struct radeon_dma_bo { + struct radeon_dma_bo *next, *prev; + struct radeon_bo *bo; + int expire_counter; +}; + struct radeon_accel_state { /* common accel data */ int fifo_slots; /* Free slots in the FIFO (64 max) */ @@ -696,12 +712,22 @@ struct radeon_accel_state { Bool vsync; drmBufPtr ib; - int vb_index; + int vb_offset; uint64_t vb_mc_addr; int vb_total; void *vb_ptr; uint32_t vb_size; - struct radeon_bo *vb_bo; + uint32_t vb_op_vert_size; + int32_t vb_start_op; + /* where to discard IB from if we cancel operation */ + uint32_t ib_reset_op; + struct radeon_bo *vb_bo; +#ifdef XF86DRM_MODE + struct radeon_dma_bo bo_free; + struct radeon_dma_bo bo_wait; + struct radeon_dma_bo bo_reserved; + Bool use_vbos; +#endif // shader storage ExaOffscreenArea *shaders; @@ -888,6 +914,8 @@ typedef struct { Bool accelOn; Bool useEXA; #ifdef USE_EXA + Bool exa_pixmaps; + Bool exa_force_create; XF86ModReqInfo exaReq; #endif #ifdef USE_XAA @@ -1287,6 +1315,7 @@ extern void radeon_cs_flush_indirect(ScrnInfoPtr pScrn); extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn, int num, const char *file, const char *func, int line); +void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size); #endif struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix); void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo); diff --git a/src/radeon_atombios.c b/src/radeon_atombios.c index ee99da27..72fbe214 100644 --- a/src/radeon_atombios.c +++ b/src/radeon_atombios.c @@ -901,6 +901,7 @@ rhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, DisplayModePtr new = NULL; DisplayModePtr first = NULL; int i; + uint16_t size; data->modes = NULL; @@ -908,12 +909,11 @@ rhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, if (!rhdAtomGetTableRevisionAndSize( (ATOM_COMMON_TABLE_HEADER *)(atomDataPtr->ComponentVideoInfo.base), - &frev,&crev,NULL)) { + &crev,&frev,&size)) { return ATOM_FAILED; } switch (frev) { - case 1: switch (func) { case ATOMBIOS_GET_CV_MODES: @@ -947,6 +947,11 @@ rhdAtomCVGetTimings(atomBiosHandlePtr handle, AtomBiosRequestID func, switch (func) { case ATOMBIOS_GET_CV_MODES: for (i = 0; i < MAX_SUPPORTED_CV_STANDARDS; i++) { + /* my rv730 table has only room for one mode */ + if ((void *)&atomDataPtr->ComponentVideoInfo.ComponentVideoInfo_v21->aModeTimings[i] - + atomDataPtr->ComponentVideoInfo.base > size) + break; + new = rhdAtomDTDTimings(handle, &atomDataPtr->ComponentVideoInfo .ComponentVideoInfo_v21->aModeTimings[i]); @@ -1977,6 +1982,7 @@ RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) radeon_native_mode_ptr native_mode = &lvds->native_mode; atomDataTablesPtr atomDataPtr; uint8_t crev, frev; + uint16_t misc; atomDataPtr = info->atomBIOS->atomDataPtr; @@ -1997,6 +2003,17 @@ RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVBlanking_Time); native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncOffset); native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.usVSyncWidth); + misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->sLCDTiming.susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + native_mode->Flags |= V_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + native_mode->Flags |= V_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + native_mode->Flags |= V_CSYNC; + if (misc & ATOM_INTERLACE) + native_mode->Flags |= V_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + native_mode->Flags |= V_DBLSCAN; lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info->usOffDelayInMs); lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info->ucLVDS_Misc; lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info->ucSS_Id; @@ -2011,6 +2028,17 @@ RADEONGetATOMLVDSInfo(ScrnInfoPtr pScrn, radeon_lvds_ptr lvds) native_mode->VBlank = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVBlanking_Time); native_mode->VOverPlus = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncOffset); native_mode->VSyncWidth = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.usVSyncWidth); + misc = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->sLCDTiming.susModeMiscInfo.usAccess); + if (misc & ATOM_VSYNC_POLARITY) + native_mode->Flags |= V_NVSYNC; + if (misc & ATOM_HSYNC_POLARITY) + native_mode->Flags |= V_NHSYNC; + if (misc & ATOM_COMPOSITESYNC) + native_mode->Flags |= V_CSYNC; + if (misc & ATOM_INTERLACE) + native_mode->Flags |= V_INTERLACE; + if (misc & ATOM_DOUBLE_CLOCK_MODE) + native_mode->Flags |= V_DBLSCAN; lvds->PanelPwrDly = le16_to_cpu(atomDataPtr->LVDS_Info.LVDS_Info_v12->usOffDelayInMs); lvds->lvds_misc = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucLVDS_Misc; lvds->lvds_ss_id = atomDataPtr->LVDS_Info.LVDS_Info_v12->ucSS_Id; diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index db46d27a..103972f5 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -65,6 +65,8 @@ radeon_dri2_create_buffers(DrawablePtr drawable, int count) { ScreenPtr pScreen = drawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); BufferPtr buffers; struct dri2_buffer_priv *privates; PixmapPtr pixmap, depth_pixmap; @@ -120,7 +122,9 @@ radeon_dri2_create_buffers(DrawablePtr drawable, if (attachments[i] == DRI2BufferDepth) { depth_pixmap = pixmap; } + info->exa_force_create = TRUE; exaMoveInPixmap(pixmap); + info->exa_force_create = FALSE; driver_priv = exaGetPixmapDriverPrivate(pixmap); r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers[i].name); if (r) @@ -143,6 +147,8 @@ radeon_dri2_create_buffer(DrawablePtr drawable, unsigned int format) { ScreenPtr pScreen = drawable->pScreen; + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); BufferPtr buffers; struct dri2_buffer_priv *privates; PixmapPtr pixmap, depth_pixmap; @@ -198,7 +204,9 @@ radeon_dri2_create_buffer(DrawablePtr drawable, if (attachment == DRI2BufferDepth) { depth_pixmap = pixmap; } + info->exa_force_create = TRUE; exaMoveInPixmap(pixmap); + info->exa_force_create = FALSE; driver_priv = exaGetPixmapDriverPrivate(pixmap); r = radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name); if (r) @@ -322,45 +330,13 @@ radeon_dri2_screen_init(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; RADEONInfoPtr info = RADEONPTR(pScrn); DRI2InfoRec dri2_info = { 0 }; - int fd; - char *bus_id; - char *tmp_bus_id; - int cmp; - int i; if (!info->useEXA) { xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requires EXA\n"); return FALSE; } - /* The whole drmOpen thing is a fiasco and we need to find a way - * back to just using open(2). For now, however, lets just make - * things worse with even more ad hoc directory walking code to - * discover the device file name. */ - bus_id = DRICreatePCIBusID(info->PciInfo); - for (i = 0; i < DRM_MAX_MINOR; i++) { - sprintf(info->dri2.device_name, DRM_DEV_NAME, DRM_DIR_NAME, i); - fd = open(info->dri2.device_name, O_RDWR); - if (fd < 0) - continue; - - tmp_bus_id = drmGetBusid(fd); - close(fd); - if (tmp_bus_id == NULL) - continue; - - cmp = strcmp(tmp_bus_id, bus_id); - drmFree(tmp_bus_id); - if (cmp == 0) - break; - } - xfree(bus_id); - - if (i == DRM_MAX_MINOR) { - xf86DrvMsg(pScrn->scrnIndex, X_WARNING, - "DRI2: failed to open drm device\n"); - return FALSE; - } + info->dri2.device_name = drmGetDeviceNameFromFd(info->dri2.drm_fd); if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) { dri2_info.driverName = R600_DRIVER_NAME; @@ -389,7 +365,11 @@ radeon_dri2_screen_init(ScreenPtr pScreen) void radeon_dri2_close_screen(ScreenPtr pScreen) { + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + RADEONInfoPtr info = RADEONPTR(pScrn); + DRI2CloseScreen(pScreen); + drmFree(info->dri2.device_name); } #endif diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h index 899a6261..c391e739 100644 --- a/src/radeon_dri2.h +++ b/src/radeon_dri2.h @@ -30,7 +30,7 @@ struct radeon_dri2 { int drm_fd; Bool enabled; - char device_name[64]; + char *device_name; }; #ifdef RADEON_DRI2 diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 99a93a4e..bff6ec05 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -391,6 +391,14 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) RADEONInfoPtr info = RADEONPTR(pScrn); struct radeon_exa_pixmap_priv *new_priv; +#ifdef EXA_MIXED_PIXMAPS + if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { + if (size != 0 && !info->exa_force_create && + info->exa_pixmaps == FALSE) + return NULL; + } +#endif + new_priv = xcalloc(1, sizeof(struct radeon_exa_pixmap_priv)); if (!new_priv) return NULL; @@ -421,7 +429,15 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, uint32_t size; uint32_t tiling = 0; int pixmap_align = 0; - + +#ifdef EXA_MIXED_PIXMAPS + if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) { + if (width != 0 && height != 0 && !info->exa_force_create && + info->exa_pixmaps == FALSE) + return NULL; + } +#endif + if (usage_hint) { if (info->allowColorTiling) { if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index b7457057..c1448900 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -1348,8 +1348,13 @@ static Bool R300CheckComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskP } else { max_tex_w = 2048; max_tex_h = 2048; - max_dst_w = 4021; - max_dst_h = 4021; + if (IS_R400_3D) { + max_dst_w = 4021; + max_dst_h = 4021; + } else { + max_dst_w = 2560; + max_dst_h = 2560; + } } if (pSrcPixmap->drawable.width > max_tex_w || diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 8e46a8a2..c06b8328 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -41,7 +41,6 @@ #include "atipciids.h" - #ifdef XF86DRM_MODE #include "radeon_chipset_gen.h" @@ -52,6 +51,8 @@ #include "radeon_bo_gem.h" #include "radeon_cs_gem.h" +#include "radeon_vbo.h" + static Bool radeon_setup_kernel_mem(ScreenPtr pScreen); const OptionInfoRec RADEONOptions_KMS[] = { @@ -67,29 +68,48 @@ const OptionInfoRec RADEONOptions_KMS[] = { { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_TVSTD, "TVStandard", OPTV_STRING, {0}, FALSE }, { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; void radeon_cs_flush_indirect(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; int ret; if (!info->cs->cdw) return; + + if (info->accel_state->vb_ptr) + info->accel_state->vb_ptr = NULL; + + /* release the current VBO so we don't block on mapping it later */ + if (info->accel_state->vb_offset && info->accel_state->vb_bo) { + radeon_vbo_put(pScrn); + info->accel_state->vb_start_op = -1; + } + radeon_cs_emit(info->cs); radeon_cs_erase(info->cs); - ret = radeon_cs_space_check(info->cs); + if (accel_state->use_vbos) + radeon_vbo_flush_bos(pScrn); + + ret = radeon_cs_space_check_with_bo(info->cs, + accel_state->vb_bo, + RADEON_GEM_DOMAIN_GTT, 0); if (ret) ErrorF("space check failed in flush\n"); if (info->reemit_current2d && info->state_2d.op) - info->reemit_current2d(pScrn, info->state_2d.op); + info->reemit_current2d(pScrn, info->state_2d.op); + if (info->dri2.enabled) { - info->accel_state->XInited3D = FALSE; - info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; + info->accel_state->XInited3D = FALSE; + info->accel_state->engineMode = EXA_ENGINEMODE_UNKNOWN; } + } void radeon_ddx_cs_start(ScrnInfoPtr pScrn, @@ -450,6 +470,16 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) (unsigned long long)mminfo.vram_visible); } } + + info->exa_pixmaps = xf86ReturnOptValBool(info->Options, + OPTION_EXA_PIXMAPS, + (info->vram_size > (32 * 1024 * 1024))); + if (info->exa_pixmaps) + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA: Driver will allow EXA pixmaps in VRAM\n"); + else + xf86DrvMsg(pScrn->scrnIndex, X_INFO, + "EXA: Driver will not allow EXA pixmaps in VRAM\n"); RADEONSetPitch(pScrn); /* Set display resolution */ @@ -520,12 +550,18 @@ static Bool RADEONCloseScreen_KMS(int scrnIndex, ScreenPtr pScreen) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONCloseScreen\n"); + if (info->cs) + radeon_cs_flush_indirect(pScrn); + if (info->accel_state->exa) { exaDriverFini(pScreen); xfree(info->accel_state->exa); info->accel_state->exa = NULL; } + if (info->accel_state->use_vbos) + radeon_vbo_free_lists(pScrn); + drmDropMaster(info->dri->drmFD); if (info->cursor) xf86DestroyCursorInfoRec(info->cursor); @@ -946,13 +982,31 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) } xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024); - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Remaining VRAM size (used for pixmaps): %dK\n", remain_size_bytes/1024); + radeon_kms_update_vram_limit(pScrn, screen_size); + return TRUE; +} - /* set the emit limit at 90% of VRAM */ - remain_size_bytes = (remain_size_bytes / 10) * 9; +void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); + int remain_size_bytes; + int total_size_bytes; + int c; + + for (c = 0; c < xf86_config->num_crtc; c++) { + if (info->cursor_bo[c] != NULL) { + total_size_bytes += (64 * 4 * 64); + } + } + total_size_bytes += new_fb_size; + remain_size_bytes = info->vram_size - new_fb_size; + remain_size_bytes = (remain_size_bytes / 10) * 9; radeon_cs_set_limit(info->cs, RADEON_GEM_DOMAIN_VRAM, remain_size_bytes); - return TRUE; + + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "VRAM usage limit set to %dK\n", remain_size_bytes / 1024); } + #endif diff --git a/src/radeon_modes.c b/src/radeon_modes.c index ec60cc9b..3e3d4c80 100644 --- a/src/radeon_modes.c +++ b/src/radeon_modes.c @@ -158,7 +158,7 @@ static DisplayModePtr RADEONFPNativeMode(xf86OutputPtr output) new->VSyncEnd = new->VSyncStart + native_mode->VSyncWidth; new->Clock = native_mode->DotClock; - new->Flags = 0; + new->Flags = native_mode->Flags; if (new) { new->type = M_T_DRIVER | M_T_PREFERRED; diff --git a/src/radeon_output.c b/src/radeon_output.c index 71803340..107955d5 100644 --- a/src/radeon_output.c +++ b/src/radeon_output.c @@ -154,7 +154,7 @@ void RADEONPrintPortMap(ScrnInfoPtr pScrn) if (radeon_output->devices & ATOM_DEVICE_TV1_SUPPORT) ErrorF(" TV1: %s\n", encoder_name[info->encoders[ATOM_DEVICE_TV1_INDEX]->encoder_id]); if (radeon_output->devices & ATOM_DEVICE_CV_SUPPORT) - ErrorF(" CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CRT1_INDEX]->encoder_id]); + ErrorF(" CV: %s\n", encoder_name[info->encoders[ATOM_DEVICE_CV_INDEX]->encoder_id]); ErrorF(" DDC reg: 0x%x\n",(unsigned int)radeon_output->ddc_i2c.mask_clk_reg); } diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c index 39c75749..7396f6f0 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -349,7 +349,9 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, #ifdef USE_EXA if (info->useEXA) { /* Force the pixmap into framebuffer so we can draw to it. */ + info->exa_force_create = TRUE; exaMoveInPixmap(pPriv->pPixmap); + info->exa_force_create = FALSE; } #endif diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index c7d9b028..bd3fa174 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -344,12 +344,17 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv FINISH_ACCEL(); } - BEGIN_ACCEL(2); - OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); - OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, (((pPixmap->drawable.width) << RADEON_RE_WIDTH_SHIFT) | - ((pPixmap->drawable.height) << RADEON_RE_HEIGHT_SHIFT))); - FINISH_ACCEL(); - + { + int scissor_w, scissor_h; + scissor_w = MIN(pPixmap->drawable.width, 2047); + scissor_h = MIN(pPixmap->drawable.height, 2047); + + BEGIN_ACCEL(2); + OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); + OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) | + (scissor_h << RADEON_RE_HEIGHT_SHIFT))); + FINISH_ACCEL(); + } if (pPriv->vsync) { xf86CrtcPtr crtc; if (pPriv->desired_crtc) @@ -382,7 +387,7 @@ FUNC_NAME(RADEONDisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv * We render a single, large triangle and use the scissor * functionality to restrict it to the desired rectangle. * Due to guardband limits on r3xx/r4xx, we can only use - * the single triangle up to 4021 pixels; above that we + * the single triangle up to 2560/4021 pixels; above that we * render as a quad. */ @@ -907,10 +912,15 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) FINISH_ACCEL(); } - BEGIN_ACCEL(2); - OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); - OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, (((pPixmap->drawable.width) << RADEON_RE_WIDTH_SHIFT) | - ((pPixmap->drawable.height) << RADEON_RE_HEIGHT_SHIFT))); + { + int scissor_w, scissor_h; + scissor_w = MIN(pPixmap->drawable.width, 2047); + scissor_h = MIN(pPixmap->drawable.height, 2047); + BEGIN_ACCEL(2); + OUT_ACCEL_REG(RADEON_RE_TOP_LEFT, 0); + OUT_ACCEL_REG(RADEON_RE_WIDTH_HEIGHT, ((scissor_w << RADEON_RE_WIDTH_SHIFT) | + (scissor_h << RADEON_RE_HEIGHT_SHIFT))); + } FINISH_ACCEL(); if (pPriv->vsync) { @@ -945,7 +955,7 @@ FUNC_NAME(R200DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) * We render a single, large triangle and use the scissor * functionality to restrict it to the desired rectangle. * Due to guardband limits on r3xx/r4xx, we can only use - * the single triangle up to 4021 pixels; above that we + * the single triangle up to 2560/4021 pixels; above that we * render as a quad. */ @@ -2321,7 +2331,7 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) * We render a single, large triangle and use the scissor * functionality to restrict it to the desired rectangle. * Due to guardband limits on r3xx/r4xx, we can only use - * the single triangle up to 4021 pixels; above that we + * the single triangle up to 2560/4021 pixels; above that we * render as a quad. */ @@ -2349,8 +2359,13 @@ FUNC_NAME(R300DisplayTexturedVideo)(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) ErrorF("src: %d, %d, %d, %d\n", srcX, srcY, srcw, srch); #endif - if ((dstw+dsth) > 4021) - use_quad = TRUE; + if (IS_R400_3D) { + if ((dstw+dsth) > 4021) + use_quad = TRUE; + } else { + if ((dstw+dsth) > 2560) + use_quad = TRUE; + } /* * Set up the scissor area to that of the output size. */ diff --git a/src/radeon_vbo.c b/src/radeon_vbo.c new file mode 100644 index 00000000..ad650b2d --- /dev/null +++ b/src/radeon_vbo.c @@ -0,0 +1,206 @@ +/* + * Copyright © 2009 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 <airlied@redhat.com> + * + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <errno.h> +#include "radeon.h" +#include "radeon_bo.h" +#include "radeon_cs.h" + +#define VBO_SIZE (16*1024) + +/* KMS vertex buffer support - for R600 only but could be used on previous gpus */ + +#ifdef XF86DRM_MODE + +static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn); + +void radeon_vbo_put(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + if (accel_state->vb_bo) { + radeon_bo_unmap(accel_state->vb_bo); + radeon_bo_unref(accel_state->vb_bo); + accel_state->vb_bo = NULL; + accel_state->vb_total = 0; + } + + accel_state->vb_offset = 0; +} + +void radeon_vbo_get(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + accel_state->vb_bo = radeon_vbo_get_bo(pScrn); + + accel_state->vb_total = VBO_SIZE; + accel_state->vb_offset = 0; + accel_state->vb_start_op = accel_state->vb_offset; +} + +/* these functions could migrate to libdrm and + be shared with the radeon 3D driver */ +static int radeon_bo_is_idle(struct radeon_bo *bo) +{ + uint32_t domain; + int ret = radeon_bo_is_busy(bo, &domain); + return ret != -EBUSY; +} + +void radeon_vbo_init_lists(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + accel_state->use_vbos = TRUE; + make_empty_list(&accel_state->bo_free); + make_empty_list(&accel_state->bo_wait); + make_empty_list(&accel_state->bo_reserved); +} + +void radeon_vbo_free_lists(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + struct radeon_dma_bo *dma_bo, *temp; + + foreach_s(dma_bo, temp, &accel_state->bo_free) { + remove_from_list(dma_bo); + radeon_bo_unref(dma_bo->bo); + xfree(dma_bo); + } + + foreach_s(dma_bo, temp, &accel_state->bo_wait) { + remove_from_list(dma_bo); + radeon_bo_unref(dma_bo->bo); + xfree(dma_bo); + } + + foreach_s(dma_bo, temp, &accel_state->bo_reserved) { + remove_from_list(dma_bo); + radeon_bo_unref(dma_bo->bo); + xfree(dma_bo); + } +} + +void radeon_vbo_flush_bos(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + struct radeon_dma_bo *dma_bo, *temp; + const int expire_at = ++accel_state->bo_free.expire_counter + DMA_BO_FREE_TIME; + const int time = accel_state->bo_free.expire_counter; + + foreach_s(dma_bo, temp, &accel_state->bo_wait) { + if (dma_bo->expire_counter == time) { + ErrorF("leaking dma buffer\n"); + while ((dma_bo->bo = radeon_bo_unref(dma_bo->bo))) {} + remove_from_list(dma_bo); + xfree(dma_bo); + continue; + } + + if (!radeon_bo_is_idle(dma_bo->bo)) + continue; + + remove_from_list(dma_bo); + dma_bo->expire_counter = expire_at; + insert_at_tail(&accel_state->bo_free, dma_bo); + } + + /* move reserved to wait list */ + foreach_s(dma_bo, temp, &accel_state->bo_reserved) { + remove_from_list(dma_bo); + dma_bo->expire_counter = expire_at; + insert_at_tail(&accel_state->bo_wait, dma_bo); + } + + /* free bos that have been unused */ + foreach_s(dma_bo, temp, &accel_state->bo_free) { + if (dma_bo->expire_counter != time) + break; + /* always keep one hanging around at end */ + if (at_end(&accel_state->bo_free, dma_bo)) { + dma_bo->expire_counter = time + DMA_BO_FREE_TIME; + break; + } + + remove_from_list(dma_bo); + radeon_bo_unref(dma_bo->bo); + xfree(dma_bo); + } +} + +static struct radeon_bo *radeon_vbo_get_bo(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + struct radeon_dma_bo *dma_bo = NULL; + struct radeon_bo *bo; + + if (is_empty_list(&accel_state->bo_free)) { + dma_bo = xcalloc(1, sizeof(struct radeon_dma_bo)); + if (!dma_bo) + return NULL; + +again_alloc: + dma_bo->bo = radeon_bo_open(info->bufmgr, 0, VBO_SIZE, + 0, RADEON_GEM_DOMAIN_GTT, 0); + + if (!dma_bo->bo) { + ErrorF("failure to allocate DMA BO\n"); + return NULL; + } + insert_at_head(&accel_state->bo_reserved, dma_bo); + } else { + dma_bo = last_elem(&accel_state->bo_free); + remove_from_list(dma_bo); + insert_at_head(&accel_state->bo_reserved, dma_bo); + } + + /* need a space check */ + if (radeon_cs_space_check_with_bo(info->cs, + first_elem(&accel_state->bo_reserved)->bo, + RADEON_GEM_DOMAIN_GTT, 0)) + fprintf(stderr,"failed to revalidated\n"); + + if (is_empty_list(&accel_state->bo_reserved)) { + goto again_alloc; + } + + bo = first_elem(&accel_state->bo_reserved)->bo; + radeon_bo_ref(bo); + return bo; +} + +#endif diff --git a/src/radeon_vbo.h b/src/radeon_vbo.h new file mode 100644 index 00000000..a8c70b30 --- /dev/null +++ b/src/radeon_vbo.h @@ -0,0 +1,62 @@ + +#ifndef RADEON_VBO_H +#define RADEON_VBO_H + +extern void r600_vb_no_space(ScrnInfoPtr pScrn, int vert_size); +extern void radeon_vbo_init_lists(ScrnInfoPtr pScrn); +extern void radeon_vbo_free_lists(ScrnInfoPtr pScrn); +extern void radeon_vbo_flush_bos(ScrnInfoPtr pScrn); +extern void radeon_vbo_get(ScrnInfoPtr pScrn); +extern void radeon_vbo_put(ScrnInfoPtr pScrn); + +static inline void radeon_vbo_check(ScrnInfoPtr pScrn, int vert_size) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + if ((accel_state->vb_offset + (3 * vert_size)) > accel_state->vb_total) { + r600_vb_no_space(pScrn, vert_size); + } +} + +static inline void * +radeon_vbo_space(ScrnInfoPtr pScrn, int vert_size) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + void *vb; + + /* we've ran out of space in the vertex buffer - need to get a + new one */ + if ((accel_state->vb_offset + (3 * vert_size)) > accel_state->vb_total) { + r600_vb_no_space(pScrn, vert_size); + } + accel_state->vb_op_vert_size = vert_size; +#if defined(XF86DRM_MODE) + if (info->cs) { + int ret; + struct radeon_bo *bo = accel_state->vb_bo; + + if (!bo->ptr) { + ret = radeon_bo_map(bo, 1); + if (ret) { + FatalError("Failed to map vb %d\n", ret); + return NULL; + } + } + vb = (pointer)((char *)bo->ptr + accel_state->vb_offset); + } else +#endif + vb = (pointer)((char *)accel_state->vb_ptr + accel_state->vb_offset); + return vb; +} + +static inline void radeon_vbo_commit(ScrnInfoPtr pScrn) +{ + RADEONInfoPtr info = RADEONPTR(pScrn); + struct radeon_accel_state *accel_state = info->accel_state; + + accel_state->vb_offset += 3 * accel_state->vb_op_vert_size; +} + +#endif diff --git a/src/simple_list.h b/src/simple_list.h new file mode 100644 index 00000000..ff7f8882 --- /dev/null +++ b/src/simple_list.h @@ -0,0 +1,202 @@ +/** + * \file simple_list.h + * Simple macros for type-safe, intrusive lists. + * + * Intended to work with a list sentinal which is created as an empty + * list. Insert & delete are O(1). + * + * \author + * (C) 1997, Keith Whitwell + */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 Brian Paul 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, 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 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 + * BRIAN PAUL 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. + */ + + +#ifndef _SIMPLE_LIST_H +#define _SIMPLE_LIST_H + +struct simple_node { + struct simple_node *next; + struct simple_node *prev; +}; + +/** + * Remove an element from list. + * + * \param elem element to remove. + */ +#define remove_from_list(elem) \ +do { \ + (elem)->next->prev = (elem)->prev; \ + (elem)->prev->next = (elem)->next; \ +} while (0) + +/** + * Insert an element to the list head. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_head(list, elem) \ +do { \ + (elem)->prev = list; \ + (elem)->next = (list)->next; \ + (list)->next->prev = elem; \ + (list)->next = elem; \ +} while(0) + +/** + * Insert an element to the list tail. + * + * \param list list. + * \param elem element to insert. + */ +#define insert_at_tail(list, elem) \ +do { \ + (elem)->next = list; \ + (elem)->prev = (list)->prev; \ + (list)->prev->next = elem; \ + (list)->prev = elem; \ +} while(0) + +/** + * Move an element to the list head. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_head(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_head(list, elem); \ +} while (0) + +/** + * Move an element to the list tail. + * + * \param list list. + * \param elem element to move. + */ +#define move_to_tail(list, elem) \ +do { \ + remove_from_list(elem); \ + insert_at_tail(list, elem); \ +} while (0) + +/** + * Make a empty list empty. + * + * \param sentinal list (sentinal element). + */ +#define make_empty_list(sentinal) \ +do { \ + (sentinal)->next = sentinal; \ + (sentinal)->prev = sentinal; \ +} while (0) + +/** + * Get list first element. + * + * \param list list. + * + * \return pointer to first element. + */ +#define first_elem(list) ((list)->next) + +/** + * Get list last element. + * + * \param list list. + * + * \return pointer to last element. + */ +#define last_elem(list) ((list)->prev) + +/** + * Get next element. + * + * \param elem element. + * + * \return pointer to next element. + */ +#define next_elem(elem) ((elem)->next) + +/** + * Get previous element. + * + * \param elem element. + * + * \return pointer to previous element. + */ +#define prev_elem(elem) ((elem)->prev) + +/** + * Test whether element is at end of the list. + * + * \param list list. + * \param elem element. + * + * \return non-zero if element is at end of list, or zero otherwise. + */ +#define at_end(list, elem) ((elem) == (list)) + +/** + * Test if a list is empty. + * + * \param list list. + * + * \return non-zero if list empty, or zero otherwise. + */ +#define is_empty_list(list) ((list)->next == (list)) + +/** + * Walk through the elements of a list. + * + * \param ptr pointer to the current element. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach(ptr, list) \ + for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next ) + +/** + * Walk through the elements of a list. + * + * Same as #foreach but lets you unlink the current value during a list + * traversal. Useful for freeing a list, element by element. + * + * \param ptr pointer to the current element. + * \param t temporary pointer. + * \param list list. + * + * \note It should be followed by a { } block or a single statement, as in a \c + * for loop. + */ +#define foreach_s(ptr, t, list) \ + for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next) + +#endif |