From 5e1b8ed88ae8fb8b697515140f7a00d022ac2db0 Mon Sep 17 00:00:00 2001 From: Michel Daenzer Date: Tue, 29 Oct 2002 13:49:26 +0000 Subject: [PATCH] preserve CRTC{,2}_OFFSET_CNTL in 2D driver to avoid bad effects when pageflipping after a mode switch take current page into account in AdjustFrame(); writing the CRTC offset via the CP was probably a bad idea as this can happen asynchronously, reverted take frame offset into account when flipping pages handle CRTC2 as well for pageflipping (untested) preserve GEN_INT_CNTL on mode switches to prevent interrupts from getting disabled --- bsd/Imakefile | 1 + linux/Makefile.linux | 2 +- shared-core/drm_sarea.h | 57 ++++++++++++++++++++++++++++++++++++++ shared-core/radeon_drm.h | 1 + shared-core/radeon_drv.h | 4 +-- shared-core/radeon_state.c | 38 ++++++++++++------------- shared/drm_sarea.h | 57 ++++++++++++++++++++++++++++++++++++++ shared/radeon_drm.h | 1 + shared/radeon_drv.h | 4 +-- shared/radeon_state.c | 38 ++++++++++++------------- 10 files changed, 160 insertions(+), 43 deletions(-) create mode 100644 shared-core/drm_sarea.h create mode 100644 shared/drm_sarea.h diff --git a/bsd/Imakefile b/bsd/Imakefile index 13b2791f..0e92b13f 100644 --- a/bsd/Imakefile +++ b/bsd/Imakefile @@ -19,6 +19,7 @@ all:: clean:: $(MAKE) -f Makefile.bsd clean +LinkSourceFile(drm_sarea.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga.h,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_dma.c,$(XF86OSSRC)/shared/drm/kernel) LinkSourceFile(mga_drm.h,$(XF86OSSRC)/shared/drm/kernel) diff --git a/linux/Makefile.linux b/linux/Makefile.linux index 7c3f1db9..a498ed8c 100644 --- a/linux/Makefile.linux +++ b/linux/Makefile.linux @@ -44,7 +44,7 @@ LIBS = DRMTEMPLATES = drm_auth.h drm_bufs.h drm_context.h drm_dma.h drm_drawable.h \ drm_drv.h drm_fops.h drm_init.h drm_ioctl.h drm_lists.h \ drm_lock.h drm_memory.h drm_proc.h drm_stub.h drm_vm.h -DRMHEADERS = drm.h drmP.h +DRMHEADERS = drm.h drmP.h drm_sarea.h GAMMAOBJS = gamma_drv.o gamma_dma.o GAMMAHEADERS = gamma_drv.h $(DRMHEADERS) $(DRMTEMPLATES) diff --git a/shared-core/drm_sarea.h b/shared-core/drm_sarea.h new file mode 100644 index 00000000..cee48eee --- /dev/null +++ b/shared-core/drm_sarea.h @@ -0,0 +1,57 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Michel Dänzer + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff --git a/shared-core/radeon_drm.h b/shared-core/radeon_drm.h index 91b395c3..6ef0c97a 100644 --- a/shared-core/radeon_drm.h +++ b/shared-core/radeon_drm.h @@ -355,6 +355,7 @@ typedef struct { int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; diff --git a/shared-core/radeon_drv.h b/shared-core/radeon_drv.h index 81615a78..65f3c926 100644 --- a/shared-core/radeon_drv.h +++ b/shared-core/radeon_drv.h @@ -109,8 +109,6 @@ typedef struct drm_radeon_private { int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev); #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_RB3D_COLORPITCH 0x1c48 diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index b4d66524..7b480a7e 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -30,6 +30,7 @@ #include "radeon.h" #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" #include "radeon_drm.h" #include "radeon_drv.h" @@ -803,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, @@ -816,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) radeon_cp_performance_boxes( dev_priv ); } - BEGIN_RING( 4 ); + /* Update the frame offsets for both CRTCs + */ + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); - - if ( dev_priv->current_page == 0 ) { - OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; - } else { - OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -836,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -1304,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) DRM_DEBUG( "\n" ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - BEGIN_RING( 4 ); + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); - OUT_RING( dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); ADVANCE_RING(); dev_priv->page_flipping = 1; @@ -1330,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev ) if (dev_priv->current_page != 0) radeon_cp_dispatch_flip( dev ); - /* FIXME: If the X server changes screen resolution, it - * clobbers the value of RADEON_CRTC_OFFSET_CNTL, above, - * leading to a flashing efect. - */ dev_priv->page_flipping = 0; return 0; } diff --git a/shared/drm_sarea.h b/shared/drm_sarea.h new file mode 100644 index 00000000..cee48eee --- /dev/null +++ b/shared/drm_sarea.h @@ -0,0 +1,57 @@ +/* sarea.h -- SAREA definitions -*- linux-c -*- + * + * Copyright 2002 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, 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 + * TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Michel Dänzer + */ + +#ifndef _DRM_SAREA_H_ +#define _DRM_SAREA_H_ + +#define SAREA_MAX_DRAWABLES 256 + +typedef struct _drm_sarea_drawable_t { + unsigned int stamp; + unsigned int flags; +} drm_sarea_drawable_t; + +typedef struct _dri_sarea_frame_t { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + unsigned int fullscreen; +} drm_sarea_frame_t; + +typedef struct _drm_sarea_t { + /* first thing is always the drm locking structure */ + drm_hw_lock_t lock; + /* NOT_DONE: Use readers/writer lock for drawable_lock */ + drm_hw_lock_t drawable_lock; + drm_sarea_drawable_t drawableTable[SAREA_MAX_DRAWABLES]; + drm_sarea_frame_t frame; + drm_context_t dummy_context; +} drm_sarea_t; + +#endif /* _DRM_SAREA_H_ */ diff --git a/shared/radeon_drm.h b/shared/radeon_drm.h index 91b395c3..6ef0c97a 100644 --- a/shared/radeon_drm.h +++ b/shared/radeon_drm.h @@ -355,6 +355,7 @@ typedef struct { int ctx_owner; int pfState; /* number of 3d windows (0,1,2ormore) */ int pfCurrentPage; /* which buffer is being displayed? */ + int crtc2_base; /* CRTC2 frame offset */ } drm_radeon_sarea_t; diff --git a/shared/radeon_drv.h b/shared/radeon_drv.h index 81615a78..65f3c926 100644 --- a/shared/radeon_drv.h +++ b/shared/radeon_drv.h @@ -109,8 +109,6 @@ typedef struct drm_radeon_private { int do_boxes; int page_flipping; int current_page; - u32 crtc_offset; - u32 crtc_offset_cntl; u32 color_fmt; unsigned int front_offset; @@ -230,6 +228,8 @@ extern int radeon_emit_irq(drm_device_t *dev); #define RADEON_CRTC_OFFSET_CNTL 0x0228 # define RADEON_CRTC_TILE_EN (1 << 15) # define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) +#define RADEON_CRTC2_OFFSET 0x0324 +#define RADEON_CRTC2_OFFSET_CNTL 0x0328 #define RADEON_RB3D_COLORPITCH 0x1c48 diff --git a/shared/radeon_state.c b/shared/radeon_state.c index b4d66524..7b480a7e 100644 --- a/shared/radeon_state.c +++ b/shared/radeon_state.c @@ -30,6 +30,7 @@ #include "radeon.h" #include "drmP.h" #include "drm.h" +#include "drm_sarea.h" #include "radeon_drm.h" #include "radeon_drv.h" @@ -803,6 +804,9 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) static void radeon_cp_dispatch_flip( drm_device_t *dev ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; + int offset = (dev_priv->current_page == 1) + ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, @@ -816,18 +820,17 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) radeon_cp_performance_boxes( dev_priv ); } - BEGIN_RING( 4 ); + /* Update the frame offsets for both CRTCs + */ + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET, 0 ) ); - - if ( dev_priv->current_page == 0 ) { - OUT_RING( dev_priv->back_offset ); - dev_priv->current_page = 1; - } else { - OUT_RING( dev_priv->front_offset ); - dev_priv->current_page = 0; - } + OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + + sarea->frame.x + * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + + offset ); + OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + + offset ); ADVANCE_RING(); @@ -836,7 +839,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; - dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page; + dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = + 1 - dev_priv->current_page; BEGIN_RING( 2 ); @@ -1304,12 +1308,12 @@ static int radeon_do_init_pageflip( drm_device_t *dev ) DRM_DEBUG( "\n" ); - dev_priv->crtc_offset_cntl = RADEON_READ( RADEON_CRTC_OFFSET_CNTL ); - - BEGIN_RING( 4 ); + BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING( CP_PACKET0( RADEON_CRTC_OFFSET_CNTL, 0 ) ); - OUT_RING( dev_priv->crtc_offset_cntl | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( RADEON_READ( RADEON_CRTC_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); + OUT_RING( CP_PACKET0( RADEON_CRTC2_OFFSET_CNTL, 0 ) ); + OUT_RING( RADEON_READ( RADEON_CRTC2_OFFSET_CNTL ) | RADEON_CRTC_OFFSET_FLIP_CNTL ); ADVANCE_RING(); dev_priv->page_flipping = 1; @@ -1330,10 +1334,6 @@ int radeon_do_cleanup_pageflip( drm_device_t *dev ) if (dev_priv->current_page != 0) radeon_cp_dispatch_flip( dev ); - /* FIXME: If the X server changes screen resolution, it - * clobbers the value of RADEON_CRTC_OFFSET_CNTL, above, - * leading to a flashing efect. - */ dev_priv->page_flipping = 0; return 0; }