Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / gallium / winsys / g3dvl / nouveau / nouveau_lock.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include <pthread.h>
29 #include <driclient.h>
30 #include "nouveau_context.h"
31 #include "nouveau_screen.h"
32
33 static pthread_mutex_t lockMutex = PTHREAD_MUTEX_INITIALIZER;
34
35 static void
36 nouveau_contended_lock(struct nouveau_context *nv, unsigned int flags)
37 {
38 dri_drawable_t *dri_drawable = nv->dri_drawable;
39 dri_screen_t *dri_screen = nv->dri_context->dri_screen;
40 struct nouveau_screen *nv_screen = nv->nv_screen;
41 struct nouveau_device *dev = nv_screen->device;
42 struct nouveau_device_priv *nvdev = nouveau_device(dev);
43
44 drmGetLock(nvdev->fd, nvdev->ctx, flags);
45
46 /* If the window moved, may need to set a new cliprect now.
47 *
48 * NOTE: This releases and regains the hw lock, so all state
49 * checking must be done *after* this call:
50 */
51 if (dri_drawable)
52 DRI_VALIDATE_DRAWABLE_INFO(dri_screen, dri_drawable);
53 }
54
55 /* Lock the hardware and validate our state.
56 */
57 void
58 LOCK_HARDWARE(struct nouveau_context *nv)
59 {
60 struct nouveau_screen *nv_screen = nv->nv_screen;
61 struct nouveau_device *dev = nv_screen->device;
62 struct nouveau_device_priv *nvdev = nouveau_device(dev);
63 char __ret=0;
64
65 pthread_mutex_lock(&lockMutex);
66 assert(!nv->locked);
67
68 DRM_CAS(nvdev->lock, nvdev->ctx,
69 (DRM_LOCK_HELD | nvdev->ctx), __ret);
70
71 if (__ret)
72 nouveau_contended_lock(nv, 0);
73 nv->locked = 1;
74 }
75
76
77 /* Unlock the hardware using the global current context
78 */
79 void
80 UNLOCK_HARDWARE(struct nouveau_context *nv)
81 {
82 struct nouveau_screen *nv_screen = nv->nv_screen;
83 struct nouveau_device *dev = nv_screen->device;
84 struct nouveau_device_priv *nvdev = nouveau_device(dev);
85
86 assert(nv->locked);
87 nv->locked = 0;
88
89 DRM_UNLOCK(nvdev->fd, nvdev->lock, nvdev->ctx);
90
91 pthread_mutex_unlock(&lockMutex);
92 }