OSDN Git Service

e7bc4fcd5ee45838b3fb606b20f9195c7d06ce0a
[android-x86/external-mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_sync.c
1 #include "vblank.h" /* for DO_USLEEP */
2
3 #include "nouveau_context.h"
4 #include "nouveau_buffers.h"
5 #include "nouveau_object.h"
6 #include "nouveau_fifo.h"
7 #include "nouveau_reg.h"
8 #include "nouveau_msg.h"
9 #include "nouveau_sync.h"
10
11 nouveau_notifier *
12 nouveau_notifier_new(GLcontext *ctx, GLuint handle)
13 {
14         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
15         nouveau_notifier *notifier;
16
17 #ifdef NOUVEAU_RING_DEBUG
18         return NULL;
19 #endif
20
21         notifier = CALLOC_STRUCT(nouveau_notifier_t);
22         if (!notifier)
23                 return NULL;
24
25         notifier->mem = nouveau_mem_alloc(ctx,
26                                           NOUVEAU_MEM_FB | NOUVEAU_MEM_MAPPED,
27                                           32,
28                                           0);
29         if (!notifier->mem) {
30                 FREE(notifier);
31                 return NULL;
32         }
33
34         if (!nouveauCreateDmaObject(nmesa, handle, notifier->mem->offset,
35                                                    notifier->mem->size,
36                                                    0 /* NV_DMA_TARGET_FB */,
37                                                    0 /* NV_DMA_ACCESS_RW */)) {
38                 nouveau_mem_free(ctx, notifier->mem);
39                 FREE(notifier);
40                 return NULL;
41         }
42
43         notifier->handle = handle;
44         return notifier;
45 }
46
47 void
48 nouveau_notifier_destroy(GLcontext *ctx, nouveau_notifier *notifier)
49 {
50         /*XXX: free DMA object.. */
51         nouveau_mem_free(ctx, notifier->mem);
52         FREE(notifier);
53 }
54
55 void
56 nouveau_notifier_reset(nouveau_notifier *notifier)
57 {
58         volatile GLuint *n = notifier->mem->map;
59
60 #ifdef NOUVEAU_RING_DEBUG
61         return;
62 #endif
63
64         n[NV_NOTIFY_TIME_0      /4] = 0x00000000;
65         n[NV_NOTIFY_TIME_1      /4] = 0x00000000;
66         n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
67         n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
68                                        NV_NOTIFY_STATE_STATUS_SHIFT);
69 }
70
71 GLboolean
72 nouveau_notifier_wait_status(nouveau_notifier *notifier, GLuint status,
73                                                          GLuint timeout)
74 {
75         volatile GLuint *n = notifier->mem->map;
76         unsigned int time = 0;
77
78 #ifdef NOUVEAU_RING_DEBUG
79         return GL_TRUE;
80 #endif
81
82         while (time <= timeout) {
83                 if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
84                         MESSAGE("Notifier returned error: 0x%04x\n",
85                                         n[NV_NOTIFY_STATE] &
86                                         NV_NOTIFY_STATE_ERROR_CODE_MASK);
87                         return GL_FALSE;
88                 }
89
90                 if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >>
91                                 NV_NOTIFY_STATE_STATUS_SHIFT) == status)
92                         return GL_TRUE;
93
94                 if (timeout) {
95                         DO_USLEEP(1);
96                         time++;
97                 }
98         }
99
100         MESSAGE("Notifier timed out\n");
101         return GL_FALSE;
102 }
103
104 void
105 nouveau_notifier_wait_nop(GLcontext *ctx, nouveau_notifier *notifier,
106                                           GLuint subc)
107 {
108         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
109         GLboolean ret;
110
111         nouveau_notifier_reset(notifier);
112
113         BEGIN_RING_SIZE(subc, NV_NOTIFY, 1);
114         OUT_RING       (NV_NOTIFY_STYLE_WRITE_ONLY);
115         BEGIN_RING_SIZE(subc, NV_NOP, 1);
116         OUT_RING       (0);
117         FIRE_RING();
118
119         ret = nouveau_notifier_wait_status(notifier,
120                                            NV_NOTIFY_STATE_STATUS_COMPLETED,
121                                            0 /* no timeout */);
122         if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n");
123 }
124
125 GLboolean nouveauSyncInitFuncs(GLcontext *ctx)
126 {
127         nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
128
129 #ifdef NOUVEAU_RING_DEBUG
130         return GL_TRUE;
131 #endif
132
133         nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify);
134         if (!nmesa->syncNotifier) {
135                 MESSAGE("Failed to create channel sync notifier\n");
136                 return GL_FALSE;
137         }
138
139         /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D
140          * object classes
141          */
142         BEGIN_RING_CACHE(NvSub3D, 0x180, 1);
143         OUT_RING_CACHE  (NvSyncNotify);
144 #ifdef ALLOW_MULTI_SUBCHANNEL
145         BEGIN_RING_SIZE(NvSubMemFormat,
146                         NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
147         OUT_RING       (NvSyncNotify);
148 #endif
149
150         return GL_TRUE;
151 }
152