summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2005-06-14 22:51:44 +0000
committerIan Romanick <idr@us.ibm.com>2005-06-14 22:51:44 +0000
commitaa2691547281a09da86f7fcc3f991b92a29fc9c7 (patch)
tree68f09948c573a39a6c68674450c96dc30e469626
parentfb818a0b115afaf43a5a3a32e649c86165ccc366 (diff)
Adds support for MGA DRM version 3.2.
This patch makes use of two of the new ioctls added in MGA DRM version 3.2. Specifically, the DRM_MGA_SET_FENCE and DRM_MGA_WAIT_FENCE ioctls are used in mgaWaitForFrameCompletion. As a result the MMIO register region and the primary DMA region are *not* mapped (if DRM 3.2 is available). This patch does *not* make use of the new get_param query was added to differentiate between G4x0 cards and G550 cards. That is left to a future update. Xorg bug: 3259 Reviewed by: Eric Anholt
-rw-r--r--src/mesa/drivers/dri/mga/mga_xmesa.c35
-rw-r--r--src/mesa/drivers/dri/mga/mgacontext.h3
-rw-r--r--src/mesa/drivers/dri/mga/mgadd.c2
-rw-r--r--src/mesa/drivers/dri/mga/mgaioctl.c167
4 files changed, 134 insertions, 73 deletions
diff --git a/src/mesa/drivers/dri/mga/mga_xmesa.c b/src/mesa/drivers/dri/mga/mga_xmesa.c
index aa4cfe5ccd..44e69dd1de 100644
--- a/src/mesa/drivers/dri/mga/mga_xmesa.c
+++ b/src/mesa/drivers/dri/mga/mga_xmesa.c
@@ -31,6 +31,7 @@
*/
#include <stdlib.h>
+#include <stdint.h>
#include "drm.h"
#include "mga_drm.h"
#include "mga_xmesa.h"
@@ -264,22 +265,30 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
* primary DMA region base address needs to be known is so that the driver
* can busy wait for certain DMA operations to complete (see
* mgaWaitForFrameCompletion in mgaioctl.c).
+ *
+ * Starting with MGA DRM version 3.2, these are completely unneeded as
+ * there is a new, in-kernel mechanism for handling the wait.
*/
- mgaScreen->mmio.handle = serverInfo->registers.handle;
- mgaScreen->mmio.size = serverInfo->registers.size;
- if ( drmMap( sPriv->fd,
- mgaScreen->mmio.handle, mgaScreen->mmio.size,
- &mgaScreen->mmio.map ) < 0 ) {
- FREE( mgaScreen );
- sPriv->private = NULL;
- __driUtilMessage( "Couldn't map MMIO registers" );
- return GL_FALSE;
- }
-
- mgaScreen->primary.handle = serverInfo->primary.handle;
- mgaScreen->primary.size = serverInfo->primary.size;
+ if (mgaScreen->sPriv->drmMinor < 2) {
+ mgaScreen->mmio.handle = serverInfo->registers.handle;
+ mgaScreen->mmio.size = serverInfo->registers.size;
+ if ( drmMap( sPriv->fd,
+ mgaScreen->mmio.handle, mgaScreen->mmio.size,
+ &mgaScreen->mmio.map ) < 0 ) {
+ FREE( mgaScreen );
+ sPriv->private = NULL;
+ __driUtilMessage( "Couldn't map MMIO registers" );
+ return GL_FALSE;
+ }
+ mgaScreen->primary.handle = serverInfo->primary.handle;
+ mgaScreen->primary.size = serverInfo->primary.size;
+ }
+ else {
+ (void) memset( & mgaScreen->primary, 0, sizeof( mgaScreen->primary ) );
+ (void) memset( & mgaScreen->mmio, 0, sizeof( mgaScreen->mmio ) );
+ }
mgaScreen->textureOffset[MGA_CARD_HEAP] = serverInfo->textureOffset;
mgaScreen->textureOffset[MGA_AGP_HEAP] = (serverInfo->agpTextureOffset |
diff --git a/src/mesa/drivers/dri/mga/mgacontext.h b/src/mesa/drivers/dri/mga/mgacontext.h
index 72c1841fed..1d8c5da6da 100644
--- a/src/mesa/drivers/dri/mga/mgacontext.h
+++ b/src/mesa/drivers/dri/mga/mgacontext.h
@@ -29,6 +29,7 @@
#ifndef MGALIB_INC
#define MGALIB_INC
+#include <stdint.h>
#include "drm.h"
#include "mga_drm.h"
#include "dri_util.h"
@@ -268,6 +269,8 @@ struct mga_context_t {
GLuint swap_count;
GLuint swap_missed_count;
+ uint32_t last_frame_fence;
+
PFNGLXGETUSTPROC get_ust;
/* Drawable, cliprect and scissor information
diff --git a/src/mesa/drivers/dri/mga/mgadd.c b/src/mesa/drivers/dri/mga/mgadd.c
index 7310641efa..8532ea95f1 100644
--- a/src/mesa/drivers/dri/mga/mgadd.c
+++ b/src/mesa/drivers/dri/mga/mgadd.c
@@ -41,7 +41,7 @@
#include "mga_xmesa.h"
#include "utils.h"
-#define DRIVER_DATE "20030328"
+#define DRIVER_DATE "20050609"
/***************************************
diff --git a/src/mesa/drivers/dri/mga/mgaioctl.c b/src/mesa/drivers/dri/mga/mgaioctl.c
index d741b57cea..62785f6344 100644
--- a/src/mesa/drivers/dri/mga/mgaioctl.c
+++ b/src/mesa/drivers/dri/mga/mgaioctl.c
@@ -50,6 +50,49 @@
#include "vblank.h"
+int
+mgaSetFence( mgaContextPtr mmesa, uint32_t * fence )
+{
+ int ret = ENOSYS;
+
+ if ( mmesa->driScreen->drmMinor >= 2 ) {
+ ret = drmCommandWriteRead( mmesa->driScreen->fd, DRM_MGA_SET_FENCE,
+ fence, sizeof( uint32_t ));
+ if (ret) {
+ fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+ exit(1);
+ }
+ }
+
+ return ret;
+}
+
+
+int
+mgaWaitFence( mgaContextPtr mmesa, uint32_t fence, uint32_t * curr_fence )
+{
+ int ret = ENOSYS;
+
+ if ( mmesa->driScreen->drmMinor >= 2 ) {
+ uint32_t temp = fence;
+
+ ret = drmCommandWriteRead( mmesa->driScreen->fd,
+ DRM_MGA_WAIT_FENCE,
+ & temp, sizeof( uint32_t ));
+ if (ret) {
+ fprintf(stderr, "drmMgaSetFence: %d\n", ret);
+ exit(1);
+ }
+
+ if ( curr_fence ) {
+ *curr_fence = temp;
+ }
+ }
+
+ return ret;
+}
+
+
static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
unsigned long dest,
int length)
@@ -294,58 +337,64 @@ mgaClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
* \bug
* The loop in this function should have some sort of a timeout mechanism.
*
- * \todo
- * This routine should be modified to wait on a semaphore. To do this,
- * the DRM would have to queue an interrupt when the swap command was
- * put in the DMA buffer. When the interrupt occured, the DRM would UP
- * the semaphore. This function would then just DOWN the semaphore.
+ * \warning
+ * This routine used to assume that the hardware lock was held on entry. It
+ * now assumes that the lock is \b not held on entry.
*/
static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
{
- unsigned wait = 0;
- const GLuint last_frame = mmesa->sarea->last_frame.head;
- const GLuint last_wrap = mmesa->sarea->last_frame.wrap;
-
-
- /* The DMA routines in the kernel track a couple values in the SAREA that
- * we use here. The number of times that the primary DMA buffer has
- * "wrapped" around is tracked in last_wrap. In addition, the wrap count
- * and the buffer position at the end of the last frame are stored in
- * last_frame.wrap and last_frame.head.
- *
- * By comparing the wrap counts and the current DMA pointer value (read
- * directly from the hardware) to last_frame.head, we can determine when
- * the graphics processor has processed all of the commands for the last
- * frame.
- *
- * In this case "last frame" means the frame of the *previous* swap-
- * buffers call. This is done to prevent queuing a second buffer swap
- * before the previous swap is executed.
- */
- while ( 1 ) {
- if ( last_wrap < mmesa->sarea->last_wrap ||
- ( last_wrap == mmesa->sarea->last_wrap &&
- last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) -
- mmesa->primary_offset) ) ) {
- break;
- }
- if ( 0 ) {
- wait++;
- fprintf( stderr, " last: head=0x%06x wrap=%d\n",
- last_frame, last_wrap );
- fprintf( stderr, " head: head=0x%06lx wrap=%d\n",
- (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset),
- mmesa->sarea->last_wrap );
- }
- UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
+ if ( mgaWaitFence( mmesa, mmesa->last_frame_fence, NULL ) == ENOSYS ) {
+ unsigned wait = 0;
+ GLuint last_frame;
+ GLuint last_wrap;
+
+
+ LOCK_HARDWARE( mmesa );
+ last_frame = mmesa->sarea->last_frame.head;
+ last_wrap = mmesa->sarea->last_frame.wrap;
+
+ /* The DMA routines in the kernel track a couple values in the SAREA
+ * that we use here. The number of times that the primary DMA buffer
+ * has "wrapped" around is tracked in last_wrap. In addition, the
+ * wrap count and the buffer position at the end of the last frame are
+ * stored in last_frame.wrap and last_frame.head.
+ *
+ * By comparing the wrap counts and the current DMA pointer value
+ * (read directly from the hardware) to last_frame.head, we can
+ * determine when the graphics processor has processed all of the
+ * commands for the last frame.
+ *
+ * In this case "last frame" means the frame of the *previous* swap-
+ * buffers call. This is done to prevent queuing a second buffer swap
+ * before the previous swap is executed.
+ */
+ while ( 1 ) {
+ if ( last_wrap < mmesa->sarea->last_wrap ||
+ ( last_wrap == mmesa->sarea->last_wrap &&
+ last_frame <= (MGA_READ( MGAREG_PRIMADDRESS ) -
+ mmesa->primary_offset) ) ) {
+ break;
+ }
+ if ( 0 ) {
+ wait++;
+ fprintf( stderr, " last: head=0x%06x wrap=%d\n",
+ last_frame, last_wrap );
+ fprintf( stderr, " head: head=0x%06lx wrap=%d\n",
+ (long)(MGA_READ( MGAREG_PRIMADDRESS ) - mmesa->primary_offset),
+ mmesa->sarea->last_wrap );
+ }
+ UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
- UNLOCK_HARDWARE( mmesa );
- DO_USLEEP( 1 );
- LOCK_HARDWARE( mmesa );
- }
- if ( wait )
- fprintf( stderr, "\n" );
+ UNLOCK_HARDWARE( mmesa );
+ DO_USLEEP( 1 );
+ LOCK_HARDWARE( mmesa );
+ }
+ if ( wait )
+ fprintf( stderr, "\n" );
+
+ UNLOCK_HARDWARE( mmesa );
+ }
}
@@ -370,9 +419,7 @@ void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv )
FLUSH_BATCH( mmesa );
- LOCK_HARDWARE( mmesa );
mgaWaitForFrameCompletion( mmesa );
- UNLOCK_HARDWARE( mmesa );
driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
& missed_target );
if ( missed_target ) {
@@ -410,6 +457,7 @@ void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv )
}
}
+ (void) mgaSetFence( mmesa, & mmesa->last_frame_fence );
UNLOCK_HARDWARE( mmesa );
mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
@@ -425,17 +473,12 @@ void mgaCopyBuffer( const __DRIdrawablePrivate *dPriv )
*
* \param ctx Context where the \c glFinish command was issued.
*
- * \todo
- * This is overkill. The lock, update-lock, unlock sequence grabs the
- * hardware, waits for \b all hardware activity to finish, then releases the
- * hardware. A better way would be to flush the pending DMA buffers, emit
- * a SOFTRAP, and wait for the SOFTRAP.
- *
* \sa glFinish, mgaFlush, mgaFlushDMA
*/
static void mgaFinish( GLcontext *ctx )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
+ uint32_t fence;
LOCK_HARDWARE( mmesa );
@@ -443,12 +486,18 @@ static void mgaFinish( GLcontext *ctx )
mgaFlushVerticesLocked( mmesa );
}
- if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) {
- fprintf(stderr, "mgaRegetLockQuiescent\n");
+ if ( mgaSetFence( mmesa, & fence ) == 0 ) {
+ UNLOCK_HARDWARE( mmesa );
+ (void) mgaWaitFence( mmesa, fence, NULL );
}
+ else {
+ if (MGA_DEBUG&DEBUG_VERBOSE_IOCTL) {
+ fprintf(stderr, "mgaRegetLockQuiescent\n");
+ }
- UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH );
- UNLOCK_HARDWARE( mmesa );
+ UPDATE_LOCK( mmesa, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH );
+ UNLOCK_HARDWARE( mmesa );
+ }
}