nouveau: nv10: set projection matrix from viewport size
[mesa.git] / src / mesa / drivers / dri / nouveau / nouveau_sync.c
1 /*
2 * Copyright (C) 2007 Ben Skeggs.
3 *
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a 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, sublicense, 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
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 */
27
28 #include "vblank.h" /* for DO_USLEEP */
29
30 #include "nouveau_context.h"
31 #include "nouveau_fifo.h"
32 #include "nouveau_mem.h"
33 #include "nouveau_msg.h"
34 #include "nouveau_object.h"
35 #include "nouveau_reg.h"
36 #include "nouveau_sync.h"
37
38 #define NOTIFIER(__v) \
39 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx); \
40 volatile uint32_t *__v = (void*)nmesa->fifo.notifier_block + \
41 notifier->offset
42
43 struct drm_nouveau_notifierobj_alloc *
44 nouveau_notifier_new(GLcontext *ctx, GLuint handle, GLuint count)
45 {
46 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
47 struct drm_nouveau_notifierobj_alloc *notifier;
48 int ret;
49
50 #ifdef NOUVEAU_RING_DEBUG
51 return NULL;
52 #endif
53 notifier = CALLOC_STRUCT(drm_nouveau_notifierobj_alloc);
54 if (!notifier)
55 return NULL;
56
57 notifier->channel = nmesa->fifo.drm.channel;
58 notifier->handle = handle;
59 notifier->count = count;
60 ret = drmCommandWriteRead(nmesa->driFd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
61 notifier, sizeof(*notifier));
62 if (ret) {
63 MESSAGE("Failed to create notifier 0x%08x: %d\n", handle, ret);
64 FREE(notifier);
65 return NULL;
66 }
67
68 return notifier;
69 }
70
71 void
72 nouveau_notifier_destroy(GLcontext *ctx,
73 struct drm_nouveau_notifierobj_alloc *notifier)
74 {
75 /*XXX: free notifier object.. */
76 FREE(notifier);
77 }
78
79 void
80 nouveau_notifier_reset(GLcontext *ctx,
81 struct drm_nouveau_notifierobj_alloc *notifier,
82 GLuint id)
83 {
84 NOTIFIER(n);
85
86 #ifdef NOUVEAU_RING_DEBUG
87 return;
88 #endif
89
90 n[NV_NOTIFY_TIME_0 /4] = 0x00000000;
91 n[NV_NOTIFY_TIME_1 /4] = 0x00000000;
92 n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
93 n[NV_NOTIFY_STATE /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
94 NV_NOTIFY_STATE_STATUS_SHIFT);
95 }
96
97 GLuint
98 nouveau_notifier_status(GLcontext *ctx,
99 struct drm_nouveau_notifierobj_alloc *notifier,
100 GLuint id)
101 {
102 NOTIFIER(n);
103
104 return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
105 }
106
107 GLuint
108 nouveau_notifier_return_val(GLcontext *ctx,
109 struct drm_nouveau_notifierobj_alloc *notifier,
110 GLuint id)
111 {
112 NOTIFIER(n);
113
114 return n[NV_NOTIFY_RETURN_VALUE/4];
115 }
116
117 GLboolean
118 nouveau_notifier_wait_status(GLcontext *ctx,
119 struct drm_nouveau_notifierobj_alloc *notifier,
120 GLuint id, GLuint status, GLuint timeout)
121 {
122 NOTIFIER(n);
123 unsigned int time = 0;
124
125 #ifdef NOUVEAU_RING_DEBUG
126 return GL_TRUE;
127 #endif
128
129 while (time <= timeout) {
130 if (n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_ERROR_CODE_MASK) {
131 MESSAGE("Notifier returned error: 0x%04x\n",
132 n[NV_NOTIFY_STATE/4] &
133 NV_NOTIFY_STATE_ERROR_CODE_MASK);
134 return GL_FALSE;
135 }
136
137 if (((n[NV_NOTIFY_STATE/4] & NV_NOTIFY_STATE_STATUS_MASK) >>
138 NV_NOTIFY_STATE_STATUS_SHIFT) == status)
139 return GL_TRUE;
140
141 if (timeout) {
142 DO_USLEEP(1);
143 time++;
144 }
145 }
146
147 MESSAGE("Notifier timed out\n");
148 return GL_FALSE;
149 }
150
151 void
152 nouveau_notifier_wait_nop(GLcontext *ctx,
153 struct drm_nouveau_notifierobj_alloc *notifier,
154 GLuint subc)
155 {
156 NOTIFIER(n);
157 GLboolean ret;
158
159 nouveau_notifier_reset(ctx, notifier, 0);
160
161 BEGIN_RING_SIZE(subc, NV_NOTIFY, 1);
162 OUT_RING (NV_NOTIFY_STYLE_WRITE_ONLY);
163 BEGIN_RING_SIZE(subc, NV_NOP, 1);
164 OUT_RING (0);
165 FIRE_RING();
166
167 ret = nouveau_notifier_wait_status(ctx, notifier, 0,
168 NV_NOTIFY_STATE_STATUS_COMPLETED,
169 0 /* no timeout */);
170 if (ret == GL_FALSE) MESSAGE("wait on notifier failed\n");
171 }
172
173 GLboolean nouveauSyncInitFuncs(GLcontext *ctx)
174 {
175 nouveauContextPtr nmesa = NOUVEAU_CONTEXT(ctx);
176
177 #ifdef NOUVEAU_RING_DEBUG
178 return GL_TRUE;
179 #endif
180
181 nmesa->syncNotifier = nouveau_notifier_new(ctx, NvSyncNotify, 1);
182 if (!nmesa->syncNotifier) {
183 MESSAGE("Failed to create channel sync notifier\n");
184 return GL_FALSE;
185 }
186
187 /* 0x180 is SET_DMA_NOTIFY, should be correct for all supported 3D
188 * object classes
189 */
190 BEGIN_RING_CACHE(NvSub3D, 0x180, 1);
191 OUT_RING_CACHE (NvSyncNotify);
192 BEGIN_RING_SIZE(NvSubMemFormat,
193 NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
194 OUT_RING (NvSyncNotify);
195
196 return GL_TRUE;
197 }
198