Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1
[mesa.git] / src / gallium / winsys / dri / nouveau / nouveau_winsys.c
1 #include "pipe/p_util.h"
2
3 #include "nouveau_context.h"
4 #include "nouveau_screen.h"
5 #include "nouveau_winsys_pipe.h"
6
7 #include "nouveau/nouveau_winsys.h"
8
9 static int
10 nouveau_pipe_notifier_alloc(struct nouveau_winsys *nvws, int count,
11 struct nouveau_notifier **notify)
12 {
13 struct nouveau_context *nv = nvws->nv;
14
15 return nouveau_notifier_alloc(nv->nvc->channel, nv->nvc->next_handle++,
16 count, notify);
17 }
18
19 static int
20 nouveau_pipe_grobj_alloc(struct nouveau_winsys *nvws, int grclass,
21 struct nouveau_grobj **grobj)
22 {
23 struct nouveau_context *nv = nvws->nv;
24 struct nouveau_channel *chan = nv->nvc->channel;
25 int ret;
26
27 ret = nouveau_grobj_alloc(chan, nv->nvc->next_handle++,
28 grclass, grobj);
29 if (ret)
30 return ret;
31
32 assert(nv->nvc->next_subchannel < 7);
33 BIND_RING(chan, *grobj, nv->nvc->next_subchannel++);
34 return 0;
35 }
36
37 static int
38 nouveau_pipe_surface_copy(struct nouveau_winsys *nvws, struct pipe_surface *dst,
39 unsigned dx, unsigned dy, struct pipe_surface *src,
40 unsigned sx, unsigned sy, unsigned w, unsigned h)
41 {
42 struct nouveau_context *nv = nvws->nv;
43
44 if (nv->surface_copy_prep(nv, dst, src))
45 return 1;
46 nv->surface_copy(nv, dx, dy, sx, sy, w, h);
47 nv->surface_copy_done(nv);
48
49 return 0;
50 }
51
52 static int
53 nouveau_pipe_surface_fill(struct nouveau_winsys *nvws, struct pipe_surface *dst,
54 unsigned dx, unsigned dy, unsigned w, unsigned h,
55 unsigned value)
56 {
57 if (nvws->nv->surface_fill(nvws->nv, dst, dx, dy, w, h, value))
58 return 1;
59 return 0;
60 }
61
62 static int
63 nouveau_pipe_push_reloc(struct nouveau_winsys *nvws, void *ptr,
64 struct pipe_buffer *buf, uint32_t data,
65 uint32_t flags, uint32_t vor, uint32_t tor)
66 {
67 return nouveau_pushbuf_emit_reloc(nvws->channel, ptr,
68 nouveau_buffer(buf)->bo,
69 data, flags, vor, tor);
70 }
71
72 static int
73 nouveau_pipe_push_flush(struct nouveau_winsys *nvws, unsigned size,
74 struct pipe_fence_handle **fence)
75 {
76 if (fence) {
77 struct nouveau_pushbuf *pb = nvws->channel->pushbuf;
78 struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(pb);
79 struct nouveau_fence *ref = NULL;
80
81 nouveau_fence_ref(nvpb->fence, &ref);
82 *fence = (struct pipe_fence_handle *)ref;
83 }
84
85 return nouveau_pushbuf_flush(nvws->channel, size);
86 }
87
88 struct pipe_context *
89 nouveau_pipe_create(struct nouveau_context *nv)
90 {
91 struct nouveau_channel_context *nvc = nv->nvc;
92 struct nouveau_winsys *nvws = CALLOC_STRUCT(nouveau_winsys);
93 struct pipe_screen *(*hws_create)(struct pipe_winsys *,
94 struct nouveau_winsys *);
95 struct pipe_context *(*hw_create)(struct pipe_screen *, unsigned);
96 struct pipe_winsys *ws;
97 unsigned chipset = nv->nv_screen->device->chipset;
98
99 if (!nvws)
100 return NULL;
101
102 switch (chipset & 0xf0) {
103 case 0x10:
104 case 0x20:
105 hws_create = nv10_screen_create;
106 hw_create = nv10_create;
107 break;
108 case 0x30:
109 hws_create = nv30_screen_create;
110 hw_create = nv30_create;
111 break;
112 case 0x40:
113 case 0x60:
114 hws_create = nv40_screen_create;
115 hw_create = nv40_create;
116 break;
117 case 0x50:
118 case 0x80:
119 case 0x90:
120 hws_create = nv50_screen_create;
121 hw_create = nv50_create;
122 break;
123 default:
124 NOUVEAU_ERR("Unknown chipset NV%02x\n", chipset);
125 return NULL;
126 }
127
128 nvws->nv = nv;
129 nvws->channel = nv->nvc->channel;
130
131 nvws->res_init = nouveau_resource_init;
132 nvws->res_alloc = nouveau_resource_alloc;
133 nvws->res_free = nouveau_resource_free;
134
135 nvws->push_reloc = nouveau_pipe_push_reloc;
136 nvws->push_flush = nouveau_pipe_push_flush;
137
138 nvws->grobj_alloc = nouveau_pipe_grobj_alloc;
139 nvws->grobj_free = nouveau_grobj_free;
140
141 nvws->notifier_alloc = nouveau_pipe_notifier_alloc;
142 nvws->notifier_free = nouveau_notifier_free;
143 nvws->notifier_reset = nouveau_notifier_reset;
144 nvws->notifier_status = nouveau_notifier_status;
145 nvws->notifier_retval = nouveau_notifier_return_val;
146 nvws->notifier_wait = nouveau_notifier_wait_status;
147
148 nvws->surface_copy = nouveau_pipe_surface_copy;
149 nvws->surface_fill = nouveau_pipe_surface_fill;
150
151 ws = nouveau_create_pipe_winsys(nv);
152
153 if (!nvc->pscreen)
154 nvc->pscreen = hws_create(ws, nvws);
155 nvc->pctx[nv->pctx_id] = hw_create(nvc->pscreen, nv->pctx_id);
156 return nvc->pctx[nv->pctx_id];
157 }
158