From 9d4857a8169913795b251b0747b565064c2e042b Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Thu, 13 Mar 2003 17:13:34 +0000 Subject: Very fragile support for VT switching between multiple running apps. Not safe to use as there is no exclusion from fbdev hw actions at vt switch time. --- src/glut/mini/init.c | 103 ----- src/glut/mini/window.c | 49 +++ src/mesa/drivers/dri/radeon/radeon_ioctl.c | 5 +- src/mesa/drivers/dri/radeon/radeon_lock.c | 50 ++- src/mesa/drivers/dri/radeon/radeon_lock.h | 14 +- src/mesa/drivers/dri/radeon/radeon_state.c | 6 +- src/mesa/drivers/dri/radeon/server/radeon_common.h | 4 + src/mesa/drivers/dri/radeon/server/radeon_dri.c | 475 +++++++++++++++------ src/mesa/glapi/glapitemp.h | 2 + src/miniglx/Makefile | 22 +- src/miniglx/dri_util.c | 6 +- src/miniglx/dri_util.h | 12 +- src/miniglx/miniglx.c | 154 ++++++- src/miniglx/miniglxP.h | 22 +- src/miniglx/xf86drm.c | 16 +- src/miniglx/xf86drm.h | 184 -------- 16 files changed, 623 insertions(+), 501 deletions(-) diff --git a/src/glut/mini/init.c b/src/glut/mini/init.c index e0feff8a65..5588db9aba 100644 --- a/src/glut/mini/init.c +++ b/src/glut/mini/init.c @@ -40,9 +40,6 @@ void APIENTRY glutInit (int *argcp, char **argv) void APIENTRY glutInitDisplayMode (unsigned int mode) { g_display_mode = mode; - -/* pc_install_keyb(); */ -/* g_mouse = pc_install_mouse(); */ } @@ -60,103 +57,3 @@ void APIENTRY glutInitWindowSize (int width, int height) } -void APIENTRY glutMainLoop (void) -{ - GLboolean idle; - static int old_mouse_x = 0; - static int old_mouse_y = 0; - static int old_mouse_b = 0; - - glutPostRedisplay(); - if (reshape_func) reshape_func(g_width, g_height); - if (visibility_func) visibility_func(GLUT_VISIBLE); -/* if (g_mouse) pc_show_mouse(); */ - - while (GL_TRUE) { - idle = GL_TRUE; - - if (g_redisplay && display_func) { - idle = GL_FALSE; - g_redisplay = GL_FALSE; - -/* if (g_mouse && !(g_display_mode & GLUT_DOUBLE)) pc_scare_mouse(); */ - display_func(); -/* if (g_mouse && !(g_display_mode & GLUT_DOUBLE)) pc_unscare_mouse(); */ - } - -#if 0 - if (pc_keypressed()) { - int key; - - idle = GL_FALSE; - key = pc_readkey(); - - switch (key>>16) { - case KEY_F1: if (special_func) special_func(GLUT_KEY_F1, 0, 0); break; - case KEY_F2: if (special_func) special_func(GLUT_KEY_F2, 0, 0); break; - case KEY_F3: if (special_func) special_func(GLUT_KEY_F3, 0, 0); break; - case KEY_F4: if (special_func) special_func(GLUT_KEY_F4, 0, 0); break; - case KEY_F5: if (special_func) special_func(GLUT_KEY_F5, 0, 0); break; - case KEY_F6: if (special_func) special_func(GLUT_KEY_F6, 0, 0); break; - case KEY_F7: if (special_func) special_func(GLUT_KEY_F7, 0, 0); break; - case KEY_F8: if (special_func) special_func(GLUT_KEY_F8, 0, 0); break; - case KEY_F9: if (special_func) special_func(GLUT_KEY_F9, 0, 0); break; - case KEY_F10: if (special_func) special_func(GLUT_KEY_F10, 0, 0); break; - case KEY_F11: if (special_func) special_func(GLUT_KEY_F11, 0, 0); break; - case KEY_F12: if (special_func) special_func(GLUT_KEY_F12, 0, 0); break; - case KEY_LEFT: if (special_func) special_func(GLUT_KEY_LEFT, 0, 0); break; - case KEY_UP: if (special_func) special_func(GLUT_KEY_UP, 0, 0); break; - case KEY_RIGHT: if (special_func) special_func(GLUT_KEY_RIGHT, 0, 0); break; - case KEY_DOWN: if (special_func) special_func(GLUT_KEY_DOWN, 0, 0); break; - case KEY_PGUP: if (special_func) special_func(GLUT_KEY_PAGE_UP, 0, 0); break; - case KEY_PGDN: if (special_func) special_func(GLUT_KEY_PAGE_DOWN, 0, 0); break; - case KEY_HOME: if (special_func) special_func(GLUT_KEY_HOME, 0, 0); break; - case KEY_END: if (special_func) special_func(GLUT_KEY_END, 0, 0); break; - case KEY_INSERT: if (special_func) special_func(GLUT_KEY_INSERT, 0, 0); break; - default: if (keyboard_func) keyboard_func(key & 0xFF, 0, 0); - } - } - - if (g_mouse) { - int mouse_x; - int mouse_y; - int mouse_b; - - mouse_b = pc_query_mouse(&mouse_x, &mouse_y); - - if (motion_func && ((mouse_x != old_mouse_x) || (mouse_y != old_mouse_y))) { - idle = GL_FALSE; - old_mouse_x = mouse_x; - old_mouse_y = mouse_y; - - motion_func(old_mouse_x, old_mouse_y); - } - - if (mouse_func && (mouse_b != old_mouse_b)) { - int new_mouse_b = mouse_b; - - if ((old_mouse_b & 1) && !(new_mouse_b & 1)) - mouse_func(GLUT_LEFT_BUTTON, GLUT_UP, mouse_x, mouse_y); - else if (!(old_mouse_b & 1) && (new_mouse_b & 1)) - mouse_func(GLUT_LEFT_BUTTON, GLUT_DOWN, mouse_x, mouse_y); - - if ((old_mouse_b & 2) && !(new_mouse_b & 2)) - mouse_func(GLUT_RIGHT_BUTTON, GLUT_UP, mouse_x, mouse_y); - else if (!(old_mouse_b & 2) && (new_mouse_b & 2)) - mouse_func(GLUT_RIGHT_BUTTON, GLUT_DOWN, mouse_x, mouse_y); - - if ((old_mouse_b & 4) && !(new_mouse_b & 4)) - mouse_func(GLUT_MIDDLE_BUTTON, GLUT_UP, mouse_x, mouse_y); - else if (!(old_mouse_b & 3) && (new_mouse_b & 4)) - mouse_func(GLUT_MIDDLE_BUTTON, GLUT_DOWN, mouse_x, mouse_y); - - idle = GL_FALSE; - old_mouse_b = new_mouse_b; - } - } -#endif - - if (idle && idle_func) - idle_func(); - } -} diff --git a/src/glut/mini/window.c b/src/glut/mini/window.c index d3bdc7a944..4c9f9f965f 100644 --- a/src/glut/mini/window.c +++ b/src/glut/mini/window.c @@ -218,3 +218,52 @@ void APIENTRY glutShowWindow (void) void APIENTRY glutHideWindow (void) { } + +void APIENTRY glutMainLoop (void) +{ + GLboolean idle; + GLboolean have_event; + XEvent evt; + + glutPostRedisplay(); + if (reshape_func) reshape_func(g_width, g_height); + + while (GL_TRUE) { + idle = GL_TRUE; + + + if (idle_func) + have_event = XCheckWindowEvent( dpy, win, ~0, &evt ); + else + have_event = XNextEvent( dpy, &evt ); + + if (have_event) { + fprintf(stderr, "got event type %d\n", evt.type); + idle = GL_FALSE; + switch(evt.type) { + case MapNotify: + if (visibility_func) visibility_func(GLUT_VISIBLE); + break; + case UnmapNotify: + if (visibility_func) visibility_func(GLUT_NOT_VISIBLE); + break; + case Expose: + g_redisplay = 1; + break; + } + } + + if (g_redisplay && display_func) { + idle = GL_FALSE; + g_redisplay = GL_FALSE; + + fprintf(stderr, "calling display_func()\n"); + display_func(); + } + + if (idle && idle_func) { + fprintf(stderr, "calling idle_func()\n"); + idle_func(); + } + } +} diff --git a/src/mesa/drivers/dri/radeon/radeon_ioctl.c b/src/mesa/drivers/dri/radeon/radeon_ioctl.c index 610d262a5f..08b1f4fc8a 100644 --- a/src/mesa/drivers/dri/radeon/radeon_ioctl.c +++ b/src/mesa/drivers/dri/radeon/radeon_ioctl.c @@ -879,7 +879,10 @@ void radeonPageFlip( const __DRIdrawablePrivate *dPriv ) b[0] = box[0]; rmesa->sarea->nbox = 1; } - + else { + UNLOCK_HARDWARE( rmesa ); + return; + } /* Throttle the frame rate -- only allow one pending swap buffers * request at a time. diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.c b/src/mesa/drivers/dri/radeon/radeon_lock.c index 3ef8b82312..655ae82e51 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.c +++ b/src/mesa/drivers/dri/radeon/radeon_lock.c @@ -109,6 +109,7 @@ radeonUpdatePageFlipping( radeonContextPtr rmesa ) return; rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip; + rmesa->doPageFlip = 0; use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT); use_back ^= (rmesa->sarea->pfCurrentPage == 1); @@ -127,23 +128,11 @@ radeonUpdatePageFlipping( radeonContextPtr rmesa ) } - -/* Update the hardware state. This is called if another context has - * grabbed the hardware lock, which includes the X server. This - * function also updates the driver's window state after the X server - * moves, resizes or restacks a window -- the change will be reflected - * in the drawable position and clip rects. Since the X server grabs - * the hardware lock when it changes the window state, this routine will - * automatically be called after such a change. - */ -void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) +static void validate_drawable( radeonContextPtr rmesa ) { __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; - __DRIscreenPrivate *sPriv = rmesa->dri.screen; - RADEONSAREAPrivPtr sarea = rmesa->sarea; - int i; - drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags ); + fprintf(stderr, "%s\n", __FUNCTION__); /* The window might have moved, so we might need to get new clip * rects. @@ -165,14 +154,45 @@ void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) radeonUpdateViewportOffset( rmesa->glCtx ); rmesa->lastStamp = dPriv->lastStamp; } +} + + +/* Update the hardware state. This is called if another context has + * grabbed the hardware lock, which includes the X server. This + * function also updates the driver's window state after the X server + * moves, resizes or restacks a window -- the change will be reflected + * in the drawable position and clip rects. Since the X server grabs + * the hardware lock when it changes the window state, this routine will + * automatically be called after such a change. + */ +void radeonGetLock( radeonContextPtr rmesa, GLuint flags ) +{ + RADEONSAREAPrivPtr sarea = rmesa->sarea; + int i; + + fprintf(stderr, "%s\n", __FUNCTION__); + drmGetLock( rmesa->dri.fd, rmesa->dri.hwContext, flags ); + + validate_drawable( rmesa ); if ( sarea->ctxOwner != rmesa->dri.hwContext ) { sarea->ctxOwner = rmesa->dri.hwContext; for ( i = 0 ; i < rmesa->texture.numHeaps ; i++ ) { - if ( rmesa->texture.heap[i] && sarea->texAge[i] != rmesa->texture.age[i] ) { + if ( rmesa->texture.heap[i] && + sarea->texAge[i] != rmesa->texture.age[i] ) { radeonAgeTextures( rmesa, i ); } } } } + +/* In the current miniglx, cliprects can change while the lock is + * held... Probably need to fix this. + */ +void radeonUnlock( radeonContextPtr rmesa ) +{ + fprintf(stderr, "%s\n", __FUNCTION__); + validate_drawable( rmesa ); + drmUnlock( rmesa->dri.fd, rmesa->dri.hwContext ); +} diff --git a/src/mesa/drivers/dri/radeon/radeon_lock.h b/src/mesa/drivers/dri/radeon/radeon_lock.h index 5fb071ab44..f8e35369ee 100644 --- a/src/mesa/drivers/dri/radeon/radeon_lock.h +++ b/src/mesa/drivers/dri/radeon/radeon_lock.h @@ -38,6 +38,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define __RADEON_LOCK_H__ extern void radeonGetLock( radeonContextPtr rmesa, GLuint flags ); +extern void radeonUnlock( radeonContextPtr rmesa ); /* Turn DEBUG_LOCKING on to find locking conflicts. */ @@ -99,12 +100,13 @@ extern int prevLockLine; /* Unlock the hardware. */ -#define UNLOCK_HARDWARE( rmesa ) \ - do { \ - DRM_UNLOCK( rmesa->dri.fd, \ - rmesa->dri.hwLock, \ - rmesa->dri.hwContext ); \ - DEBUG_RESET(); \ +#define UNLOCK_HARDWARE( rmesa ) \ + do { \ + DRM_CAS_RESULT(__ret); \ + DRM_CAS( rmesa->dri.hwLock,DRM_LOCK_HELD|rmesa->dri.hwContext, \ + rmesa->dri.hwContext,__ret); \ + if (__ret) radeonUnlock( rmesa ); \ + DEBUG_RESET(); \ } while (0) #endif /* __RADEON_LOCK_H__ */ diff --git a/src/mesa/drivers/dri/radeon/radeon_state.c b/src/mesa/drivers/dri/radeon/radeon_state.c index 511d10acfe..6ad1166dcc 100644 --- a/src/mesa/drivers/dri/radeon/radeon_state.c +++ b/src/mesa/drivers/dri/radeon/radeon_state.c @@ -1126,7 +1126,9 @@ static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode ) void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) { __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; - + + fprintf(stderr, "%s\n", __FUNCTION__); + switch ( mode ) { case GL_FRONT_LEFT: rmesa->numClipRects = dPriv->numClipRects; @@ -1153,6 +1155,8 @@ void radeonSetCliprects( radeonContextPtr rmesa, GLenum mode ) return; } + fprintf(stderr, "%s: %d cliprects\n", __FUNCTION__, rmesa->numClipRects); + if (rmesa->state.scissor.enabled) radeonRecalcScissorRects( rmesa ); } diff --git a/src/mesa/drivers/dri/radeon/server/radeon_common.h b/src/mesa/drivers/dri/radeon/server/radeon_common.h index 41c2a0e598..bd808d124b 100644 --- a/src/mesa/drivers/dri/radeon/server/radeon_common.h +++ b/src/mesa/drivers/dri/radeon/server/radeon_common.h @@ -472,6 +472,10 @@ typedef struct drm_radeon_getparam { #define RADEON_PARAM_LAST_CLEAR 4 #define RADEON_PARAM_IRQ_NR 5 #define RADEON_PARAM_AGP_BASE 6 +#define RADEON_PARAM_REGISTER_HANDLE 7 +#define RADEON_PARAM_STATUS_HANDLE 8 +#define RADEON_PARAM_SAREA_HANDLE 9 +#define RADEON_PARAM_AGP_TEX_HANDLE 10 #define RADEON_MEM_REGION_AGP 1 diff --git a/src/mesa/drivers/dri/radeon/server/radeon_dri.c b/src/mesa/drivers/dri/radeon/server/radeon_dri.c index d8702f41e6..fc4f978aed 100644 --- a/src/mesa/drivers/dri/radeon/server/radeon_dri.c +++ b/src/mesa/drivers/dri/radeon/server/radeon_dri.c @@ -12,6 +12,8 @@ #include #include "miniglxP.h" +#include "dri_util.h" +#include "drm.h" #include "radeon.h" #include "radeon_dri.h" @@ -517,6 +519,285 @@ static void RADEONDRIIrqInit(struct MiniGLXDisplayRec *dpy, info->irq); } +static int RADEONCheckDRMVersion( struct MiniGLXDisplayRec *dpy, + RADEONInfoPtr info ) +{ + drmVersionPtr version; + + version = drmGetVersion(dpy->drmFD); + if (version) { + int req_minor, req_patch; + + /* Need 1.8.x for proper cleanup-on-client-exit behaviour. + */ + req_minor = 8; + req_patch = 0; + + if (version->version_major != 1 || + version->version_minor < req_minor || + (version->version_minor == req_minor && + version->version_patchlevel < req_patch)) { + /* Incompatible drm version */ + fprintf(stderr, + "[dri] RADEONDRIScreenInit failed because of a version " + "mismatch.\n" + "[dri] radeon.o kernel module version is %d.%d.%d " + "but version 1.%d.%d or newer is needed.\n" + "[dri] Disabling DRI.\n", + version->version_major, + version->version_minor, + version->version_patchlevel, + req_minor, + req_patch); + drmFreeVersion(version); + return 0; + } + + info->drmMinor = version->version_minor; + drmFreeVersion(version); + } + + return 1; +} + +static int RADEONMemoryInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) +{ + int width_bytes = dpy->virtualWidth * dpy->cpp; + int cpp = dpy->cpp; + int bufferSize = ((dpy->virtualHeight * width_bytes + + RADEON_BUFFER_ALIGN) + & ~RADEON_BUFFER_ALIGN); + int depthSize = ((((dpy->virtualHeight+15) & ~15) * width_bytes + + RADEON_BUFFER_ALIGN) + & ~RADEON_BUFFER_ALIGN); + int l; + + info->frontOffset = 0; + info->frontPitch = dpy->virtualWidth; + + fprintf(stderr, + "Using %d MB AGP aperture\n", info->agpSize); + fprintf(stderr, + "Using %d MB for the ring buffer\n", info->ringSize); + fprintf(stderr, + "Using %d MB for vertex/indirect buffers\n", info->bufSize); + fprintf(stderr, + "Using %d MB for AGP textures\n", info->agpTexSize); + + /* Front, back and depth buffers - everything else texture?? + */ + info->textureSize = dpy->FrameBufferSize - 2 * bufferSize - depthSize; + + if (info->textureSize < 0) + return 0; + + l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + + /* Round the texture size up to the nearest whole number of + * texture regions. Again, be greedy about this, don't + * round down. + */ + info->log2TexGran = l; + info->textureSize = (info->textureSize >> l) << l; + + /* Set a minimum usable local texture heap size. This will fit + * two 256x256x32bpp textures. + */ + if (info->textureSize < 512 * 1024) { + info->textureOffset = 0; + info->textureSize = 0; + } + + /* Reserve space for textures */ + info->textureOffset = ((dpy->FrameBufferSize - info->textureSize + + RADEON_BUFFER_ALIGN) & + ~RADEON_BUFFER_ALIGN); + + /* Reserve space for the shared depth + * buffer. + */ + info->depthOffset = ((info->textureOffset - depthSize + + RADEON_BUFFER_ALIGN) & + ~RADEON_BUFFER_ALIGN); + info->depthPitch = dpy->virtualWidth; + + info->backOffset = ((info->depthOffset - bufferSize + + RADEON_BUFFER_ALIGN) & + ~RADEON_BUFFER_ALIGN); + info->backPitch = dpy->virtualWidth; + + + fprintf(stderr, + "Will use back buffer at offset 0x%x\n", + info->backOffset); + fprintf(stderr, + "Will use depth buffer at offset 0x%x\n", + info->depthOffset); + fprintf(stderr, + "Will use %d kb for textures at offset 0x%x\n", + info->textureSize/1024, info->textureOffset); + + info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | + (info->frontOffset >> 10)); + + info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | + (info->backOffset >> 10)); + + info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | + (info->depthOffset >> 10)); + + return 1; +} + +static int RADEONGetParam( int fd, int param, int *value ) +{ + drmRadeonGetParam p; + int ret; + + p.param = param; + p.value = value; + + ret = drmCommandWriteRead(fd, DRM_RADEON_GETPARAM, &p, sizeof(p)); + + return ret == 0; +} + +static void print_client_msg( RADEONDRIPtr pRADEONDRI ) +{ + fprintf(stderr, "deviceID 0x%x\n", pRADEONDRI->deviceID); + fprintf(stderr, "width 0x%x\n", pRADEONDRI->width); + fprintf(stderr, "height 0x%x\n", pRADEONDRI->height); + fprintf(stderr, "depth 0x%x\n", pRADEONDRI->depth); + fprintf(stderr, "bpp 0x%x\n", pRADEONDRI->bpp); + fprintf(stderr, "IsPCI 0x%x\n", pRADEONDRI->IsPCI); + fprintf(stderr, "AGPMode 0x%x\n", pRADEONDRI->AGPMode); + fprintf(stderr, "frontOffset 0x%x\n", pRADEONDRI->frontOffset); + fprintf(stderr, "frontPitch 0x%x\n", pRADEONDRI->frontPitch); + fprintf(stderr, "backOffset 0x%x\n", pRADEONDRI->backOffset); + fprintf(stderr, "backPitch 0x%x\n", pRADEONDRI->backPitch); + fprintf(stderr, "depthOffset 0x%x\n", pRADEONDRI->depthOffset); + fprintf(stderr, "depthPitch 0x%x\n", pRADEONDRI->depthPitch); + fprintf(stderr, "textureOffset 0x%x\n", pRADEONDRI->textureOffset); + fprintf(stderr, "textureSize 0x%x\n", pRADEONDRI->textureSize); + fprintf(stderr, "log2TexGran 0x%x\n", pRADEONDRI->log2TexGran); + fprintf(stderr, "registerHandle 0x%x\n", (unsigned)pRADEONDRI->registerHandle); + fprintf(stderr, "registerSize 0x%x\n", pRADEONDRI->registerSize); + fprintf(stderr, "statusHandle 0x%x\n", (unsigned)pRADEONDRI->statusHandle); + fprintf(stderr, "statusSize 0x%x\n", pRADEONDRI->statusSize); + fprintf(stderr, "agpTexHandle 0x%x\n", (unsigned)pRADEONDRI->agpTexHandle); + fprintf(stderr, "agpTexMapSize 0x%x\n", pRADEONDRI->agpTexMapSize); + fprintf(stderr, "log2AGPTexGran 0x%x\n", pRADEONDRI->log2AGPTexGran); + fprintf(stderr, "agpTexOffset 0x%x\n", pRADEONDRI->agpTexOffset); + fprintf(stderr, "sarea_priv_offset 0x%x\n", pRADEONDRI->sarea_priv_offset); +} + + +static int RADEONScreenJoin( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) +{ + int s, l; + RADEONDRIPtr pRADEONDRI; + + /* Check the radeon DRM version */ + if (!RADEONCheckDRMVersion(dpy, info)) { + return 0; + } + + /* Memory manager setup */ + if (!RADEONMemoryInit(dpy, info)) { + return 0; + } + + /* Query the kernel for the various map handles (a handle is an + * offset into the mmap of dpy->drmFD). + */ + if (!RADEONGetParam(dpy->drmFD, RADEON_PARAM_REGISTER_HANDLE, + (int *)&info->registerHandle) || + !RADEONGetParam(dpy->drmFD, RADEON_PARAM_STATUS_HANDLE, + (int *)&info->ringReadPtrHandle)|| + !RADEONGetParam(dpy->drmFD, RADEON_PARAM_SAREA_HANDLE, + (int *)&dpy->hSAREA)|| + !RADEONGetParam(dpy->drmFD, RADEON_PARAM_AGP_TEX_HANDLE, + (int *)&info->agpTexHandle)) { + fprintf(stderr, "[drm] kernel parameter query failed\n"); + return 0; + } + + dpy->SAREASize = DRM_PAGE_SIZE; + + /* Need to map this one here: + */ + if (drmMap( dpy->drmFD, + dpy->hSAREA, + dpy->SAREASize, + (drmAddressPtr)(&dpy->pSAREA)) < 0) + { + fprintf(stderr, "[drm] drmMap failed\n"); + return 0; + } + + + /* These assume that the default values set in __driInitFBDev are + * actually the ones in use by the kernel. These include: + * + * info->agpSize = RADEON_DEFAULT_AGP_SIZE; + * info->agpTexSize = RADEON_DEFAULT_AGP_TEX_SIZE; + * info->bufSize = RADEON_DEFAULT_BUFFER_SIZE; + * info->ringSize = RADEON_DEFAULT_RING_SIZE; + * + * Probably this should all be queried/deduced here. + */ + info->agpOffset = 0; + info->ringStart = info->agpOffset; + info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE; + info->ringReadOffset = info->ringStart + info->ringMapSize; + info->ringReadMapSize = DRM_PAGE_SIZE; + info->bufStart = info->ringReadOffset + info->ringReadMapSize; + info->bufMapSize = info->bufSize*1024*1024; + info->agpTexStart = info->bufStart + info->bufMapSize; + s = (info->agpSize*1024*1024 - info->agpTexStart); + l = RADEONMinBits((s-1) / RADEON_NR_TEX_REGIONS); + if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; + info->agpTexMapSize = (s >> l) << l; + info->log2AGPTexGran = l; + + info->registerSize = dpy->FixedInfo.mmio_len; + + /* This is the struct passed to radeon_dri.so for its initialization */ + dpy->driverClientMsg = malloc(sizeof(RADEONDRIRec)); + dpy->driverClientMsgSize = sizeof(RADEONDRIRec); + pRADEONDRI = (RADEONDRIPtr)dpy->driverClientMsg; + pRADEONDRI->deviceID = info->Chipset; + pRADEONDRI->width = dpy->virtualWidth; + pRADEONDRI->height = dpy->virtualHeight; + pRADEONDRI->depth = dpy->bpp; /* XXX: depth */ + pRADEONDRI->bpp = dpy->bpp; + pRADEONDRI->IsPCI = 0; + pRADEONDRI->AGPMode = info->agpMode; /* query */ + pRADEONDRI->frontOffset = info->frontOffset; + pRADEONDRI->frontPitch = info->frontPitch; + pRADEONDRI->backOffset = info->backOffset; + pRADEONDRI->backPitch = info->backPitch; + pRADEONDRI->depthOffset = info->depthOffset; + pRADEONDRI->depthPitch = info->depthPitch; + pRADEONDRI->textureOffset = info->textureOffset; + pRADEONDRI->textureSize = info->textureSize; + pRADEONDRI->log2TexGran = info->log2TexGran; + pRADEONDRI->registerHandle = info->registerHandle; /* param? */ + pRADEONDRI->registerSize = info->registerSize; + pRADEONDRI->statusHandle = info->ringReadPtrHandle; /* param? */ + pRADEONDRI->statusSize = info->ringReadMapSize; + pRADEONDRI->agpTexHandle = info->agpTexHandle; /* param? */ + pRADEONDRI->agpTexMapSize = info->agpTexMapSize; + pRADEONDRI->log2AGPTexGran = info->log2AGPTexGran; + pRADEONDRI->agpTexOffset = info->agpTexStart; + pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + + + print_client_msg( pRADEONDRI ); + + return 1; +} /** @@ -539,8 +820,8 @@ static void RADEONDRIIrqInit(struct MiniGLXDisplayRec *dpy, static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) { RADEONDRIPtr pRADEONDRI; - drmVersionPtr version; int err; + unsigned int serverContext; usleep(100); @@ -568,13 +849,21 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) return 0; } + info->registerSize = dpy->FixedInfo.mmio_len; + dpy->SAREASize = DRM_PAGE_SIZE; /* Note that drmOpen will try to load the kernel module, if needed. */ dpy->drmFD = drmOpen("radeon", NULL ); if (dpy->drmFD < 0) { /* failed to open DRM */ - fprintf(stderr, "[drm] drmOpen failed\n"); - return 0; + fprintf(stderr, "[drm] drmOpen failed, trying open by BusID\n"); + + dpy->drmFD = drmOpen( NULL, dpy->pciBusID ); + if (dpy->drmFD >= 0) { + fprintf(stderr, "[drm] drmOpen by BusID succeeds...\n"); + fprintf(stderr, "[drm] ...joining existing session\n"); + return RADEONScreenJoin( dpy, info ); + } } if ((err = drmSetBusid(dpy->drmFD, dpy->pciBusID)) < 0) { @@ -583,9 +872,7 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) return 0; } - - dpy->SAREASize = DRM_PAGE_SIZE; - + if (drmAddMap( dpy->drmFD, 0, dpy->SAREASize, @@ -628,7 +915,6 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) - info->registerSize = dpy->FixedInfo.mmio_len; if (drmAddMap(dpy->drmFD, dpy->FixedInfo.mmio_start, dpy->FixedInfo.mmio_len, @@ -642,37 +928,8 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) "[drm] register handle = 0x%08lx\n", info->registerHandle); /* Check the radeon DRM version */ - version = drmGetVersion(dpy->drmFD); - if (version) { - int req_minor, req_patch; - - /* Need 1.8.x for proper cleanup-on-client-exit behaviour. - */ - req_minor = 8; - req_patch = 0; - - if (version->version_major != 1 || - version->version_minor < req_minor || - (version->version_minor == req_minor && - version->version_patchlevel < req_patch)) { - /* Incompatible drm version */ - fprintf(stderr, - "[dri] RADEONDRIScreenInit failed because of a version " - "mismatch.\n" - "[dri] radeon.o kernel module version is %d.%d.%d " - "but version 1.%d.%d or newer is needed.\n" - "[dri] Disabling DRI.\n", - version->version_major, - version->version_minor, - version->version_patchlevel, - req_minor, - req_patch); - drmFreeVersion(version); - return 0; - } - - info->drmMinor = version->version_minor; - drmFreeVersion(version); + if (!RADEONCheckDRMVersion(dpy, info)) { + return 0; } /* Initialize AGP */ @@ -682,114 +939,31 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) /* Memory manager setup */ - { - int width_bytes = dpy->virtualWidth * dpy->cpp; - int cpp = dpy->cpp; - int bufferSize = ((dpy->virtualHeight * width_bytes - + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); - int depthSize = ((((dpy->virtualHeight+15) & ~15) * width_bytes - + RADEON_BUFFER_ALIGN) - & ~RADEON_BUFFER_ALIGN); - int l; - - info->frontOffset = 0; - info->frontPitch = dpy->virtualWidth; - - fprintf(stderr, - "Using %d MB AGP aperture\n", info->agpSize); - fprintf(stderr, - "Using %d MB for the ring buffer\n", info->ringSize); - fprintf(stderr, - "Using %d MB for vertex/indirect buffers\n", info->bufSize); - fprintf(stderr, - "Using %d MB for AGP textures\n", info->agpTexSize); - - /* Front, back and depth buffers - everything else texture?? - */ - info->textureSize = dpy->FrameBufferSize - 2 * bufferSize - depthSize; - - if (info->textureSize < 0) - return 0; - - l = RADEONMinBits((info->textureSize-1) / RADEON_NR_TEX_REGIONS); - if (l < RADEON_LOG_TEX_GRANULARITY) l = RADEON_LOG_TEX_GRANULARITY; - - /* Round the texture size up to the nearest whole number of - * texture regions. Again, be greedy about this, don't - * round down. - */ - info->log2TexGran = l; - info->textureSize = (info->textureSize >> l) << l; - - /* Set a minimum usable local texture heap size. This will fit - * two 256x256x32bpp textures. - */ - if (info->textureSize < 512 * 1024) { - info->textureOffset = 0; - info->textureSize = 0; - } - - /* Reserve space for textures */ - info->textureOffset = ((dpy->FrameBufferSize - info->textureSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - - /* Reserve space for the shared depth - * buffer. - */ - info->depthOffset = ((info->textureOffset - depthSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - info->depthPitch = dpy->virtualWidth; - - info->backOffset = ((info->depthOffset - bufferSize + - RADEON_BUFFER_ALIGN) & - ~RADEON_BUFFER_ALIGN); - info->backPitch = dpy->virtualWidth; - - - fprintf(stderr, - "Will use back buffer at offset 0x%x\n", - info->backOffset); - fprintf(stderr, - "Will use depth buffer at offset 0x%x\n", - info->depthOffset); - fprintf(stderr, - "Will use %d kb for textures at offset 0x%x\n", - info->textureSize/1024, info->textureOffset); - - info->frontPitchOffset = (((info->frontPitch * cpp / 64) << 22) | - (info->frontOffset >> 10)); - - info->backPitchOffset = (((info->backPitch * cpp / 64) << 22) | - (info->backOffset >> 10)); - - info->depthPitchOffset = (((info->depthPitch * cpp / 64) << 22) | - (info->depthOffset >> 10)); - } + if (!RADEONMemoryInit(dpy, info)) { + return 0; + } /* Create a 'server' context so we can grab the lock for * initialization ioctls. */ - if ((err = drmCreateContext(dpy->drmFD, &dpy->serverContext)) != 0) { + if ((err = drmCreateContext(dpy->drmFD, &serverContext)) != 0) { fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err); return 0; } - DRM_LOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext, 0); + DRM_LOCK(dpy->drmFD, dpy->pSAREA, serverContext, 0); /* Initialize the kernel data structures */ if (!RADEONDRIKernelInit(dpy, info)) { fprintf(stderr, "RADEONDRIKernelInit failed\n"); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); return 0; } /* Initialize the vertex buffers list */ if (!RADEONDRIBufInit(dpy, info)) { fprintf(stderr, "RADEONDRIBufInit failed\n"); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); return 0; } @@ -804,7 +978,7 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) /* Initialize and start the CP if required */ if ((err = drmCommandNone(dpy->drmFD, DRM_RADEON_CP_START)) != 0) { fprintf(stderr, "%s: CP start %d\n", __FUNCTION__, err); - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); return 0; } @@ -818,7 +992,7 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) } /* Can release the lock now */ - DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, dpy->serverContext); + DRM_UNLOCK(dpy->drmFD, dpy->pSAREA, serverContext); /* This is the struct passed to radeon_dri.so for its initialization */ dpy->driverClientMsg = malloc(sizeof(RADEONDRIRec)); @@ -850,6 +1024,8 @@ static int RADEONScreenInit( struct MiniGLXDisplayRec *dpy, RADEONInfoPtr info ) pRADEONDRI->agpTexOffset = info->agpTexStart; pRADEONDRI->sarea_priv_offset = sizeof(XF86DRISAREARec); + print_client_msg( pRADEONDRI ); + return 1; } @@ -1148,6 +1324,42 @@ static void __driHaltFBDev( struct MiniGLXDisplayRec *dpy ) } +/** + * \brief A VT release or aquire signal has been received, and + * requires some action. We deal with loosing the VT by setting the + * cliprects to zero and emitting an event to the application. + */ +static void __driVTSwitchHandler( struct MiniGLXDisplayRec *dpy, int have_vt ) +{ + int *lock = (int *)dpy->pSAREA; + int old, new; + DRM_CAS_RESULT(ret); + GLXDrawable draw; + __DRIdrawable *pdraw; + __DRIdrawablePrivate *pdp; + + /* Indicate cliprects have changed + */ + draw = dpy->TheWindow; + if (!draw) return; + pdraw = &draw->driDrawable; + if (!pdraw) return; + pdp = (__DRIdrawablePrivate *) pdraw->private; + if (!pdp) return; + pdp->lastStamp++; + pdp->numClipRects = have_vt ? 1 : 0; + + /* Mark the lock contended. + */ + if (!dpy->pSAREA) return; + do { + old = *(int *)dpy->pSAREA; + new = old | _DRM_LOCK_CONT; + DRM_CAS( lock, old, new, ret ); + fprintf(stderr, "old %x new %x\n", old, new ); + } while (ret); +} + /** * \brief Exported driver interface for Mini GLX. * @@ -1158,5 +1370,6 @@ struct MiniGLXDriverRec __driMiniGLXDriver = { __driValidateMode, __driPostValidateMode, __driInitFBDev, - __driHaltFBDev + __driHaltFBDev, + __driVTSwitchHandler }; diff --git a/src/mesa/glapi/glapitemp.h b/src/mesa/glapi/glapitemp.h index ba6a093787..ea2b3a67d9 100644 --- a/src/mesa/glapi/glapitemp.h +++ b/src/mesa/glapi/glapitemp.h @@ -25,6 +25,8 @@ * */ +#include +#include #ifndef KEYWORD1 #define KEYWORD1 diff --git a/src/miniglx/Makefile b/src/miniglx/Makefile index 1baafa5466..cb21e2b39b 100644 --- a/src/miniglx/Makefile +++ b/src/miniglx/Makefile @@ -2,6 +2,8 @@ # Indirect rendering not supported, etc. MESA=../.. +default: libGL.so.1.2 install drmtest +include $(MESA)/Makefile.include SOURCES = dispatch.c \ dri_util.c \ @@ -13,15 +15,9 @@ OBJS = $(SOURCES:.c=.o) INCLUDES = -I. -I.. -I$(MESA)/include -CFLAGS = -c -g $(INCLUDES) -MD - LIBS = -ldl - -default: libGL.so.1.2 install drmtest - - libGL.so.1.2: $(OBJS) Makefile gcc -shared -Wl,-soname,libGL.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@ @@ -33,9 +29,6 @@ install: ln -s libGL.so.1 $(MESA)/lib/libGL.so install example.miniglx.conf $(MESA)/lib/miniglx.conf -#miniglx.a: $(OBJECTS) Makefile -# rm -f $@ && ar rcv $@ $(OBJECTS) && ranlib $@ - drmtest: xf86drm.o drmtest.o rm -f drmtest && $(CC) -o drmtest xf86drm.o drmtest.o @@ -43,15 +36,4 @@ drmtest: xf86drm.o drmtest.o glapi.c: ../glapi.c ln -s ../glapi.c . -clean: - rm -f *~ .*~ *.o libGL.so* glapi.c *.d - -tags: - etags *.[ch] - -include $(SOURCES:.c=.d) - -.SUFFIXES: .c .d - -.c.d: - $(CC) -M $(INCLUDES) $< > $@ diff --git a/src/miniglx/dri_util.c b/src/miniglx/dri_util.c index 46ba4f8052..02c85358a9 100644 --- a/src/miniglx/dri_util.c +++ b/src/miniglx/dri_util.c @@ -282,6 +282,7 @@ static Bool driBindContext(Display *dpy, int scrn, */ void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp) { + fprintf(stderr, "%s\n", __FUNCTION__); /* nothing to do */ } @@ -319,7 +320,6 @@ static void driDestroyDrawable(Display *dpy, void *drawablePrivate) { __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate; __DRIscreenPrivate *psp = pdp->driScreenPriv; - int scrn = psp->myNum; if (pdp) { (*psp->DriverAPI.DestroyBuffer)(pdp); @@ -455,7 +455,6 @@ static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate) { __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate; __DRIscreenPrivate *psp = NULL; - __DRIdrawablePrivate *pdp; if (pcp) { (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp); @@ -602,8 +601,6 @@ __driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc, const struct __DriverAPIRec *driverAPI) { __DRIscreenPrivate *psp; - char *driverName; - drmHandle hFB; psp = (__DRIscreenPrivate *)malloc(sizeof(__DRIscreenPrivate)); if (!psp) { @@ -700,7 +697,6 @@ __driUtilCreateScreenNoDRM(Display *dpy, int scrn, __DRIscreen *psc, const struct __DriverAPIRec *driverAPI) { __DRIscreenPrivate *psp; - char *driverName; psp = (__DRIscreenPrivate *)calloc(1, sizeof(__DRIscreenPrivate)); if (!psp) diff --git a/src/miniglx/dri_util.h b/src/miniglx/dri_util.h index cd01b61c39..6ba758a295 100644 --- a/src/miniglx/dri_util.h +++ b/src/miniglx/dri_util.h @@ -80,17 +80,7 @@ typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate; /**< \brief Alias f */ #define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \ do { \ - while (*(pdp->pStamp) != pdp->lastStamp) { \ - DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, \ - pdp->driContextPriv->hHWContext); \ - \ - DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \ - DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \ - DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \ - \ - DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, \ - pdp->driContextPriv->hHWContext); \ - } \ + DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \ } while (0) diff --git a/src/miniglx/miniglx.c b/src/miniglx/miniglx.c index 007af16c0c..a4de596a3b 100644 --- a/src/miniglx/miniglx.c +++ b/src/miniglx/miniglx.c @@ -22,7 +22,7 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/* $Id: miniglx.c,v 1.1.4.46 2003/02/21 21:14:31 keithw Exp $ */ +/* $Id: miniglx.c,v 1.1.4.47 2003/03/13 17:13:56 keithw Exp $ */ /** @@ -123,7 +123,6 @@ extern void __driUtilInitScreen( Display *dpy, int scrn, __DRIscreen *psc ); - /** * \brief Current GLX context. * @@ -132,8 +131,112 @@ __driUtilInitScreen( Display *dpy, int scrn, __DRIscreen *psc ); static GLXContext CurrentContext = NULL; -static void SwitchDisplay(int i_signal) + +/* Called from signal handler context, runs atomically wrt + * XCheckWindowEvent. + */ +static void queue_event( Display *dpy, int aquire ) +{ + dpy->haveVT = aquire; + dpy->aquireVTCount += aquire; + dpy->releaseVTCount += !aquire; +} + +static Display *SignalDisplay = 0; + +static void SwitchVT(int sig) +{ + fprintf(stderr, "SwitchVT %d dpy %p\n", sig, SignalDisplay); + + if (!SignalDisplay) + return; + + switch( sig ) + { + case SIGUSR1: /* vt has been released */ + queue_event( SignalDisplay, 0 ); + if (SignalDisplay->driver) + SignalDisplay->driver->handleVTSwitch( SignalDisplay, 0 ); + ioctl( SignalDisplay->ConsoleFD, VT_RELDISP, 1 ); + break; + case SIGUSR2: /* vt has been acquired */ + queue_event( SignalDisplay, 1 ); + if (SignalDisplay->driver) + SignalDisplay->driver->handleVTSwitch( SignalDisplay, 1 ); + ioctl( SignalDisplay->ConsoleFD, VT_RELDISP, VT_ACTIVATE ); + break; + } +} + + +int XNextEvent(Display *display, XEvent *event_return) { + /* This works because our events are really signals, which will + * terminate the sleep early. If keypress, mousemove, etc. events + * are ever added to miniglx, this would have to change. + */ + while (!XCheckWindowEvent( display, display->TheWindow, ~0, event_return )) + sleep(1); + + return True; +} + + +Bool XCheckWindowEvent(Display *display, Window w, long event_mask, + XEvent *er) +{ + if (!w || w != display->TheWindow) + return False; + + /* Note: there is no actual queue for these events, so multiple + * cycles of aquire & release vt that occur between calls to + * XCheckWindowEvent will be lost, with only the current state + * being reported. However this should be safe with respect to the + * asynchronous arrival of signals, and avoids the issue of what to + * do if an event queue were to fill up. + */ + if (display->haveVT) { + if (display->mapNotifyCount != display->aquireVTCount) { + er->xmap.type = MapNotify; + er->xmap.serial = 0; + er->xmap.send_event = False; + er->xmap.display = display; + er->xmap.event = w; + er->xmap.window = w; + er->xmap.override_redirect = False; + display->mapNotifyCount = display->aquireVTCount; + return True; + } + if (display->exposeNotifyCount != display->aquireVTCount) { + er->xexpose.type = Expose; + er->xexpose.serial = 0; + er->xexpose.send_event = False; + er->xexpose.display = display; + er->xexpose.window = w; + er->xexpose.x = 0; + er->xexpose.y = 0; + er->xexpose.width = w->w; + er->xexpose.height = w->h; + er->xexpose.count = 0; + display->exposeNotifyCount = display->aquireVTCount; + return True; + } + } + else { + if (display->unmapNotifyCount != display->releaseVTCount) { + er->xunmap.type = UnmapNotify; + er->xunmap.serial = 0; + er->xunmap.send_event = False; + er->xunmap.display = display; + er->xunmap.event = w; + er->xunmap.window = w; + er->xunmap.from_configure = False; + display->unmapNotifyCount = display->releaseVTCount; + return True; + } + } + + return False; } /**********************************************************************/ @@ -180,6 +283,8 @@ OpenFBDev( Display *dpy ) fprintf(stderr, "error: couldn't get a free vt\n"); return GL_FALSE; } + + fprintf(stderr, "*** got vt nr: %d\n", vtnumber); close(fd); /* open the console tty */ @@ -209,39 +314,44 @@ OpenFBDev( Display *dpy ) struct vt_mode vt; struct sigaction sig_tty; - if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0) - printf("ioctl VT_ACTIVATE: %s\n", strerror(errno)); - if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0) - printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno)); - - if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) { - fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno)); - return GL_FALSE; - } - - - /* Set-up tty signal handler to catch the signal we request below */ + SignalDisplay = dpy; memset( &sig_tty, 0, sizeof( sig_tty ) ); - sig_tty.sa_handler = SwitchDisplay; + sig_tty.sa_handler = SwitchVT; sigemptyset( &sig_tty.sa_mask ); - if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) ) + if( sigaction( SIGUSR1, &sig_tty, &dpy->OrigSigUsr1 ) || + sigaction( SIGUSR2, &sig_tty, &dpy->OrigSigUsr2 ) ) { fprintf(stderr, "error: can't set up signal handler (%s)", strerror(errno) ); return GL_FALSE; } + vt.mode = VT_PROCESS; vt.waitv = 0; vt.relsig = SIGUSR1; - vt.acqsig = SIGUSR1; + vt.acqsig = SIGUSR2; if (ioctl(dpy->ConsoleFD, VT_SETMODE, &vt) < 0) { fprintf(stderr, "error: ioctl(VT_SETMODE) failed: %s\n", strerror(errno)); return GL_FALSE; } + + + if (ioctl(dpy->ConsoleFD, VT_ACTIVATE, vtnumber) != 0) + printf("ioctl VT_ACTIVATE: %s\n", strerror(errno)); + if (ioctl(dpy->ConsoleFD, VT_WAITACTIVE, vtnumber) != 0) + printf("ioctl VT_WAITACTIVE: %s\n", strerror(errno)); + + if (ioctl(dpy->ConsoleFD, VT_GETMODE, &vt) < 0) { + fprintf(stderr, "error: ioctl VT_GETMODE: %s\n", strerror(errno)); + return GL_FALSE; + } + + + } /* go into graphics mode */ @@ -355,6 +465,9 @@ SetupFBDev( Display *dpy, Window win ) assert(dpy); + width = dpy->virtualWidth; + height = dpy->virtualHeight; + /* Bump size up to next supported mode. */ if (width <= 800 && height <= 600) { @@ -968,8 +1081,6 @@ XOpenDisplay( const char *display_name ) void XCloseDisplay( Display *display ) { - GLXContext *ctx; - glXMakeCurrent( display, NULL, NULL); if (display->NumWindows) @@ -1374,8 +1485,6 @@ glXChooseVisual( Display *dpy, int screen, int *attribList ) GLboolean rgbFlag = GL_FALSE, dbFlag = GL_FALSE, stereoFlag = GL_FALSE; GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits = 0; GLint indexBits = 0, depthBits = 0, stencilBits = 0; - GLint accumRedBits = 0, accumGreenBits = 0; - GLint accumBlueBits = 0, accumAlphaBits = 0; GLint numSamples = 0; int i; @@ -1843,6 +1952,7 @@ glXQueryVersion( Display *dpy, int *major, int *minor ) (void) dpy; *major = 1; *minor = 0; + return True; } /*@}*/ diff --git a/src/miniglx/miniglxP.h b/src/miniglx/miniglxP.h index 572a211be9..748f32deef 100644 --- a/src/miniglx/miniglxP.h +++ b/src/miniglx/miniglxP.h @@ -205,6 +205,11 @@ struct MiniGLXDriverRec { * \brief Halt the framebuffer device. */ void (*haltFBDev)( struct MiniGLXDisplayRec *dpy ); + + /** + * \brief Handle VT switch events. + */ + void (*handleVTSwitch)( struct MiniGLXDisplayRec *dpy, int have_vt ); }; @@ -242,6 +247,8 @@ struct MiniGLXVisualRec { }; +#define MINIGLX_EVENT_QUEUE_SIZE 5 + /** * \brief X Window type. * @@ -262,6 +269,9 @@ struct MiniGLXWindowRec { GLubyte *backBottom; /**< \brief pointer to last row */ GLubyte *curBottom; /**< = frontBottom or backBottom */ __DRIdrawable driDrawable; + GLuint ismapped; + GLuint event_queue[MINIGLX_EVENT_QUEUE_SIZE]; + GLuint event_queue_len; }; @@ -289,6 +299,7 @@ struct MiniGLXDisplayRec { /** \brief original and current variable frambuffer screen info */ struct fb_var_screeninfo OrigVarInfo, VarInfo; struct sigaction OrigSigUsr1; + struct sigaction OrigSigUsr2; int OriginalVT; int ConsoleFD; /**< \brief console TTY device file descriptor */ int FrameBufferFD; /**< \brief framebuffer device file descriptor */ @@ -299,6 +310,16 @@ struct MiniGLXDisplayRec { int NumWindows; /**< \brief number of open windows */ Window TheWindow; /**< \brief open window - only allow one window for now */ + + int haveVT; + int aquireVTCount; + int releaseVTCount; + int exposeNotifyCount; + int mapNotifyCount; + int unmapNotifyCount; + + + /** * \name Visual configurations */ @@ -350,7 +371,6 @@ struct MiniGLXDisplayRec { int drmFD; /**< \brief DRM device file descriptor */ unsigned long hSAREA; unsigned long hFrameBuffer; - unsigned int serverContext; /* temporary DRM context -- make an auto var? */ int SAREASize; void *pSAREA; /*@}*/ diff --git a/src/miniglx/xf86drm.c b/src/miniglx/xf86drm.c index 85c33af63c..c2cefaa974 100644 --- a/src/miniglx/xf86drm.c +++ b/src/miniglx/xf86drm.c @@ -328,6 +328,9 @@ static int drmOpenByName(const char *name) if ((version = drmGetVersion(fd))) { if (!strcmp(version->name, name)) { drmFreeVersion(version); + +/* return fd; */ + id = drmGetBusid(fd); drmMsg("drmGetBusid returned '%s'\n", id ? id : "NULL"); if (!id || !*id) { @@ -935,6 +938,7 @@ int drmGetLock(int fd, drmContext context, drmLockFlags flags) return 0; } +static void (*drm_unlock_callback)( void ) = 0; /** * \brief Release the hardware lock. @@ -951,10 +955,20 @@ int drmGetLock(int fd, drmContext context, drmLockFlags flags) int drmUnlock(int fd, drmContext context) { drm_lock_t lock; + int ret; lock.context = context; lock.flags = 0; - return ioctl(fd, DRM_IOCTL_UNLOCK, &lock); + ret = ioctl(fd, DRM_IOCTL_UNLOCK, &lock); + + /* Need this to synchronize vt releasing. Could also teach fbdev + * about the drm lock... + */ + if (drm_unlock_callback) { + drm_unlock_callback(); + } + + return ret; } diff --git a/src/miniglx/xf86drm.h b/src/miniglx/xf86drm.h index 903c7c1b00..0169d89c28 100644 --- a/src/miniglx/xf86drm.h +++ b/src/miniglx/xf86drm.h @@ -285,100 +285,6 @@ typedef struct _drmVBlank { "r" (new)); \ } while (0) -#elif defined(__alpha__) - -#define DRM_CAS(lock, old, new, ret) \ - do { \ - int old32; \ - int cur32; \ - __asm__ __volatile__( \ - " mb\n" \ - " zap %4, 0xF0, %0\n" \ - " ldl_l %1, %2\n" \ - " zap %1, 0xF0, %1\n" \ - " cmpeq %0, %1, %1\n" \ - " beq %1, 1f\n" \ - " bis %5, %5, %1\n" \ - " stl_c %1, %2\n" \ - "1: xor %1, 1, %1\n" \ - " stl %1, %3" \ - : "+r" (old32), \ - "+&r" (cur32), \ - "=m" (__drm_dummy_lock(lock)),\ - "=m" (ret) \ - : "r" (old), \ - "r" (new)); \ - } while(0) - -#elif defined(__sparc__) - -#define DRM_CAS(lock,old,new,__ret) \ -do { register unsigned int __old __asm("o0"); \ - register unsigned int __new __asm("o1"); \ - register volatile unsigned int *__lock __asm("o2"); \ - __old = old; \ - __new = new; \ - __lock = (volatile unsigned int *)lock; \ - __asm__ __volatile__( \ - /*"cas [%2], %3, %0"*/ \ - ".word 0xd3e29008\n\t" \ - /*"membar #StoreStore | #StoreLoad"*/ \ - ".word 0x8143e00a" \ - : "=&r" (__new) \ - : "0" (__new), \ - "r" (__lock), \ - "r" (__old) \ - : "memory"); \ - __ret = (__new != __old); \ -} while(0) - -#elif defined(__ia64__) - -#if 0 -/* this currently generates bad code (missing stop bits)... */ -#include - -#define DRM_CAS(lock,old,new,__ret) \ - do { \ - __ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \ - (old), (new)) \ - != (old)); \ - } while (0) - -#else -#define DRM_CAS(lock,old,new,__ret) \ - do { \ - unsigned int __result, __old = (old); \ - __asm__ __volatile__( \ - "mf\n" \ - "mov ar.ccv=%2\n" \ - ";;\n" \ - "cmpxchg4.acq %0=%1,%3,ar.ccv" \ - : "=r" (__result), "=m" (__drm_dummy_lock(lock)) \ - : "r" (__old), "r" (new) \ - : "memory"); \ - __ret = (__result) != (__old); \ - } while (0) - -#endif - -#elif defined(__powerpc__) - -#define DRM_CAS(lock,old,new,__ret) \ - do { \ - __asm__ __volatile__( \ - "sync;" \ - "0: lwarx %0,0,%1;" \ - " xor. %0,%3,%0;" \ - " bne 1f;" \ - " stwcx. %2,0,%1;" \ - " bne- 0b;" \ - "1: " \ - "sync;" \ - : "=&r"(__ret) \ - : "r"(lock), "r"(new), "r"(old) \ - : "cr0", "memory"); \ - } while (0) #endif /* architecture */ #endif /* __GNUC__ >= 2 */ @@ -400,19 +306,6 @@ do { register unsigned int __old __asm("o0"); \ if (__ret) drmGetLock(fd,context,0); \ } while(0) -/** - * \brief Counts fast locks. - * - * \note For benchmarking only. - */ -#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \ - do { \ - DRM_CAS_RESULT(__ret); \ - DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \ - if (__ret) drmGetLock(fd,context,0); \ - else ++count; \ - } while(0) - #define DRM_LOCK(fd,lock,context,flags) \ do { \ if (flags) drmGetLock(fd,context,flags); \ @@ -426,47 +319,6 @@ do { register unsigned int __old __asm("o0"); \ if (__ret) drmUnlock(fd,context); \ } while(0) -/** - * \brief Simple spin locks. - */ -#define DRM_SPINLOCK(spin,val) \ - do { \ - DRM_CAS_RESULT(__ret); \ - do { \ - DRM_CAS(spin,0,val,__ret); \ - if (__ret) while ((spin)->lock); \ - } while (__ret); \ - } while(0) - -#define DRM_SPINLOCK_TAKE(spin,val) \ - do { \ - DRM_CAS_RESULT(__ret); \ - int cur; \ - do { \ - cur = (*spin).lock; \ - DRM_CAS(spin,cur,val,__ret); \ - } while (__ret); \ - } while(0) - -#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \ - do { \ - int __i; \ - __ret = 1; \ - for (__i = 0; __ret && __i < count; __i++) { \ - DRM_CAS(spin,0,val,__ret); \ - if (__ret) for (;__i < count && (spin)->lock; __i++); \ - } \ - } while(0) - -#define DRM_SPINUNLOCK(spin,val) \ - do { \ - DRM_CAS_RESULT(__ret); \ - if ((*spin).lock == val) { /* else server stole lock */ \ - do { \ - DRM_CAS(spin,val,0,__ret); \ - } while (__ret); \ - } \ - } while(0) /* General user-level programmer's API: unprivileged */ extern int drmAvailable(void); @@ -577,45 +429,9 @@ extern unsigned long drmAgpMemoryAvail(int fd); extern unsigned int drmAgpVendorId(int fd); extern unsigned int drmAgpDeviceId(int fd); -/* PCI scatter/gather support: X server (root) only */ -extern int drmScatterGatherAlloc(int fd, unsigned long size, - unsigned long *handle); -extern int drmScatterGatherFree(int fd, unsigned long handle); - -extern int drmWaitVBlank(int fd, drmVBlankPtr vbl); - /* Support routines */ extern int drmError(int err, const char *label); extern void *drmMalloc(int size); extern void drmFree(void *pt); -/* Hash table routines */ -extern void *drmHashCreate(void); -extern int drmHashDestroy(void *t); -extern int drmHashLookup(void *t, unsigned long key, void **value); -extern int drmHashInsert(void *t, unsigned long key, void *value); -extern int drmHashDelete(void *t, unsigned long key); -extern int drmHashFirst(void *t, unsigned long *key, void **value); -extern int drmHashNext(void *t, unsigned long *key, void **value); - -/* PRNG routines */ -extern void *drmRandomCreate(unsigned long seed); -extern int drmRandomDestroy(void *state); -extern unsigned long drmRandom(void *state); -extern double drmRandomDouble(void *state); - -/* Skip list routines */ - -extern void *drmSLCreate(void); -extern int drmSLDestroy(void *l); -extern int drmSLLookup(void *l, unsigned long key, void **value); -extern int drmSLInsert(void *l, unsigned long key, void *value); -extern int drmSLDelete(void *l, unsigned long key); -extern int drmSLNext(void *l, unsigned long *key, void **value); -extern int drmSLFirst(void *l, unsigned long *key, void **value); -extern void drmSLDump(void *l); -extern int drmSLLookupNeighbors(void *l, unsigned long key, - unsigned long *prev_key, void **prev_value, - unsigned long *next_key, void **next_value); - #endif -- cgit v1.2.3