Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / gallium / winsys / g3dvl / xsp_winsys.c
1 #include "vl_winsys.h"
2 #include <X11/Xutil.h>
3 #include <pipe/p_winsys.h>
4 #include <pipe/p_state.h>
5 #include <pipe/p_inlines.h>
6 #include <util/u_memory.h>
7 #include <softpipe/sp_winsys.h>
8
9 /* pipe_winsys implementation */
10
11 struct xsp_pipe_winsys
12 {
13 struct pipe_winsys base;
14 XImage fbimage;
15 };
16
17 struct xsp_context
18 {
19 Display *display;
20 int screen;
21 Drawable drawable;
22 int drawable_bound;
23 };
24
25 struct xsp_buffer
26 {
27 struct pipe_buffer base;
28 boolean is_user_buffer;
29 void *data;
30 void *mapped_data;
31 };
32
33 static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
34 {
35 struct xsp_buffer *buffer;
36
37 assert(pws);
38
39 buffer = calloc(1, sizeof(struct xsp_buffer));
40 buffer->base.refcount = 1;
41 buffer->base.alignment = alignment;
42 buffer->base.usage = usage;
43 buffer->base.size = size;
44 buffer->data = align_malloc(size, alignment);
45
46 return (struct pipe_buffer*)buffer;
47 }
48
49 static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
50 {
51 struct xsp_buffer *buffer;
52
53 assert(pws);
54
55 buffer = calloc(1, sizeof(struct xsp_buffer));
56 buffer->base.refcount = 1;
57 buffer->base.size = size;
58 buffer->is_user_buffer = TRUE;
59 buffer->data = data;
60
61 return (struct pipe_buffer*)buffer;
62 }
63
64 static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
65 {
66 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
67
68 assert(pws);
69 assert(buffer);
70
71 xsp_buf->mapped_data = xsp_buf->data;
72
73 return xsp_buf->mapped_data;
74 }
75
76 static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
77 {
78 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
79
80 assert(pws);
81 assert(buffer);
82
83 xsp_buf->mapped_data = NULL;
84 }
85
86 static void xsp_buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buffer)
87 {
88 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
89
90 assert(pws);
91 assert(buffer);
92
93 if (!xsp_buf->is_user_buffer)
94 align_free(xsp_buf->data);
95
96 free(xsp_buf);
97 }
98
99 static struct pipe_surface* xsp_surface_alloc(struct pipe_winsys *pws)
100 {
101 struct pipe_surface *surface;
102
103 assert(pws);
104
105 surface = calloc(1, sizeof(struct pipe_surface));
106 surface->refcount = 1;
107 surface->winsys = pws;
108
109 return surface;
110 }
111
112 /* Borrowed from Mesa's xm_winsys */
113 static unsigned int round_up(unsigned n, unsigned multiple)
114 {
115 return (n + multiple - 1) & ~(multiple - 1);
116 }
117
118 static int xsp_surface_alloc_storage
119 (
120 struct pipe_winsys *pws,
121 struct pipe_surface *surface,
122 unsigned width,
123 unsigned height,
124 enum pipe_format format,
125 unsigned flags,
126 unsigned tex_usage
127 )
128 {
129 const unsigned int ALIGNMENT = 1;
130
131 assert(pws);
132 assert(surface);
133
134 surface->width = width;
135 surface->height = height;
136 surface->format = format;
137 pf_get_block(format, &surface->block);
138 surface->nblocksx = pf_get_nblocksx(&surface->block, width);
139 surface->nblocksy = pf_get_nblocksy(&surface->block, height);
140 surface->stride = round_up(surface->nblocksx * surface->block.size, ALIGNMENT);
141 surface->usage = flags;
142 surface->buffer = pws->buffer_create(pws, ALIGNMENT, PIPE_BUFFER_USAGE_PIXEL, surface->stride * surface->nblocksy);
143
144 return 0;
145 }
146
147 static void xsp_surface_release(struct pipe_winsys *pws, struct pipe_surface **surface)
148 {
149 struct pipe_surface *s;
150
151 assert(pws);
152 assert(surface);
153 assert(*surface);
154
155 s = *surface;
156
157 s->refcount--;
158
159 if (s->refcount == 0)
160 {
161 winsys_buffer_reference(pws, &s->buffer, NULL);
162 free(s);
163 }
164
165 *surface = NULL;
166 }
167
168 static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
169 {
170 assert(pws);
171 assert(ptr);
172 assert(fence);
173 }
174
175 static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
176 {
177 assert(pws);
178 assert(fence);
179
180 return 0;
181 }
182
183 static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
184 {
185 assert(pws);
186 assert(fence);
187
188 return 0;
189 }
190
191 static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
192 {
193 struct xsp_pipe_winsys *xsp_winsys;
194 struct xsp_context *xsp_context;
195
196 assert(pws);
197 assert(surface);
198 assert(context_private);
199
200 xsp_winsys = (struct xsp_pipe_winsys*)pws;
201 xsp_context = (struct xsp_context*)context_private;
202
203 if (!xsp_context->drawable_bound)
204 return;
205
206 xsp_winsys->fbimage.width = surface->width;
207 xsp_winsys->fbimage.height = surface->height;
208 xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3);
209 xsp_winsys->fbimage.data = pipe_surface_map(surface, 0);
210
211 XPutImage
212 (
213 xsp_context->display,
214 xsp_context->drawable,
215 XDefaultGC(xsp_context->display, xsp_context->screen),
216 &xsp_winsys->fbimage,
217 0,
218 0,
219 0,
220 0,
221 surface->width,
222 surface->height
223 );
224 XFlush(xsp_context->display);
225 pipe_surface_unmap(surface);
226 }
227
228 static const char* xsp_get_name(struct pipe_winsys *pws)
229 {
230 assert(pws);
231 return "X11 SoftPipe";
232 }
233
234 /* Show starts here */
235
236 int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
237 {
238 struct xsp_context *xsp_context;
239
240 assert(pipe);
241
242 xsp_context = pipe->priv;
243 xsp_context->drawable = drawable;
244 xsp_context->drawable_bound = 1;
245
246 return 0;
247 }
248
249 int unbind_pipe_drawable(struct pipe_context *pipe)
250 {
251 struct xsp_context *xsp_context;
252
253 assert(pipe);
254
255 xsp_context = pipe->priv;
256 xsp_context->drawable_bound = 0;
257
258 return 0;
259 }
260
261 struct pipe_context* create_pipe_context(Display *display, int screen)
262 {
263 struct xsp_pipe_winsys *xsp_winsys;
264 struct xsp_context *xsp_context;
265 struct pipe_screen *sp_screen;
266 struct pipe_context *sp_pipe;
267
268 assert(display);
269
270 xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys));
271 xsp_winsys->base.buffer_create = xsp_buffer_create;
272 xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
273 xsp_winsys->base.buffer_map = xsp_buffer_map;
274 xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
275 xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
276 xsp_winsys->base.surface_alloc = xsp_surface_alloc;
277 xsp_winsys->base.surface_alloc_storage = xsp_surface_alloc_storage;
278 xsp_winsys->base.surface_release = xsp_surface_release;
279 xsp_winsys->base.fence_reference = xsp_fence_reference;
280 xsp_winsys->base.fence_signalled = xsp_fence_signalled;
281 xsp_winsys->base.fence_finish = xsp_fence_finish;
282 xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
283 xsp_winsys->base.get_name = xsp_get_name;
284
285 {
286 /* XXX: Can't use the returned XImage* directly,
287 since we don't have control over winsys destruction
288 and we wouldn't be able to free it */
289 XImage *template = XCreateImage
290 (
291 display,
292 XDefaultVisual(display, XDefaultScreen(display)),
293 XDefaultDepth(display, XDefaultScreen(display)),
294 ZPixmap,
295 0,
296 NULL,
297 0, /* Don't know the width and height until flush_frontbuffer */
298 0,
299 32,
300 0
301 );
302
303 memcpy(&xsp_winsys->fbimage, template, sizeof(XImage));
304 XInitImage(&xsp_winsys->fbimage);
305
306 XDestroyImage(template);
307 }
308
309 sp_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
310 sp_pipe = softpipe_create(sp_screen, (struct pipe_winsys*)xsp_winsys, NULL);
311
312 xsp_context = calloc(1, sizeof(struct xsp_context));
313 xsp_context->display = display;
314 xsp_context->screen = screen;
315
316 sp_pipe->priv = xsp_context;
317
318 return sp_pipe;
319 }
320
321 int destroy_pipe_context(struct pipe_context *pipe)
322 {
323 struct pipe_screen *screen;
324 struct pipe_winsys *winsys;
325
326 assert(pipe);
327
328 screen = pipe->screen;
329 winsys = pipe->winsys;
330 free(pipe->priv);
331 pipe->destroy(pipe);
332 screen->destroy(screen);
333 free(winsys);
334
335 return 0;
336 }