Merge branch 'mesa_7_7_branch'
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_lock.c
index 5774f7ebcf7ec3d275d874cc0ba93f6265d8efd8..9dee691938a0848981f56d29c082e4eb5e3e96b1 100644 (file)
@@ -58,11 +58,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
 {
-       __DRIdrawablePrivate *const drawable = radeon_get_drawable(rmesa);
-       __DRIdrawablePrivate *const readable = radeon_get_readable(rmesa);
-       __DRIscreenPrivate *sPriv = rmesa->dri.screen;
-
-       assert(drawable != NULL);
+       __DRIdrawable *const drawable = radeon_get_drawable(rmesa);
+       __DRIdrawable *const readable = radeon_get_readable(rmesa);
+       __DRIscreen *sPriv = rmesa->dri.screen;
 
        drmGetLock(rmesa->dri.fd, rmesa->dri.hwContext, flags);
 
@@ -74,22 +72,47 @@ void radeonGetLock(radeonContextPtr rmesa, GLuint flags)
         * Since the hardware state depends on having the latest drawable
         * clip rects, all state checking must be done _after_ this call.
         */
-       DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
-       if (drawable != readable) {
+       if (drawable)
+               DRI_VALIDATE_DRAWABLE_INFO(sPriv, drawable);
+       if (readable && drawable != readable) {
                DRI_VALIDATE_DRAWABLE_INFO(sPriv, readable);
        }
 
-       if (rmesa->lastStamp != drawable->lastStamp) {
+       if (drawable && (rmesa->lastStamp != drawable->lastStamp)) {
                radeon_window_moved(rmesa);
                rmesa->lastStamp = drawable->lastStamp;
        }
 
        rmesa->vtbl.get_lock(rmesa);
-
-       rmesa->lost_context = GL_TRUE;
 }
-
-void radeon_lock_hardware(radeonContextPtr radeon)
+#ifndef NDEBUG
+struct lock_debug {
+       const char* function;
+       const char* file;
+       int line;
+};
+
+static struct lock_debug ldebug = {0};
+#endif
+
+#if 0
+/** TODO: use atomic operations for reference counting **/
+/** gcc 4.2 has builtin functios for this **/
+#define ATOMIC_INC_AND_FETCH(atomic) __sync_add_and_fetch(&atomic, 1)
+#define ATOMIC_DEC_AND_FETCH(atomic) __sync_sub_and_fetch(&atomic, 1)
+#else
+#define ATOMIC_INC_AND_FETCH(atomic) (++atomic)
+#define ATOMIC_DEC_AND_FETCH(atomic) (--atomic)
+#endif
+
+
+void radeon_lock_hardware(radeonContextPtr radeon
+#ifndef NDEBUG
+               ,const char* function
+               ,const char* file
+               ,const int line
+#endif
+               )
 {
        char ret = 0;
        struct radeon_framebuffer *rfb = NULL;
@@ -104,16 +127,39 @@ void radeon_lock_hardware(radeonContextPtr radeon)
        }
 
        if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+               if (ATOMIC_INC_AND_FETCH(radeon->dri.hwLockCount) > 1)
+               {
+#ifndef NDEBUG
+                       if ( RADEON_DEBUG & RADEON_SANITY )
+                               fprintf(stderr, "*** %d times of recursive call to %s ***\n"
+                                               "Original call was from %s (file: %s line: %d)\n"
+                                               "Now call is coming from %s (file: %s line: %d)\n"
+                                               , radeon->dri.hwLockCount, __FUNCTION__
+                                               , ldebug.function, ldebug.file, ldebug.line
+                                               , function, file, line
+                                          );
+#endif
+                       return;
+               }
                DRM_CAS(radeon->dri.hwLock, radeon->dri.hwContext,
                         (DRM_LOCK_HELD | radeon->dri.hwContext), ret );
                if (ret)
                        radeonGetLock(radeon, 0);
+#ifndef NDEBUG
+               ldebug.function = function;
+               ldebug.file = file;
+               ldebug.line = line;
+#endif
        }
 }
 
 void radeon_unlock_hardware(radeonContextPtr radeon)
 {
        if (!radeon->radeonScreen->driScreen->dri2.enabled) {
+               if (ATOMIC_DEC_AND_FETCH(radeon->dri.hwLockCount) > 0)
+               {
+                       return;
+               }
                DRM_UNLOCK( radeon->dri.fd,
                            radeon->dri.hwLock,
                            radeon->dri.hwContext );