Merge branch 'mesa_7_6_branch'
[mesa.git] / src / gallium / winsys / g3dvl / xlib / xsp_winsys.c
1 #include <vl_winsys.h>
2 #include <X11/Xutil.h>
3 #include <pipe/internal/p_winsys_screen.h>
4 #include <pipe/p_state.h>
5 #include <pipe/p_inlines.h>
6 #include <util/u_memory.h>
7 #include <util/u_math.h>
8 #include <softpipe/sp_winsys.h>
9 #include <softpipe/sp_video_context.h>
10 #include <softpipe/sp_texture.h>
11
12 /* pipe_winsys implementation */
13
14 struct xsp_pipe_winsys
15 {
16 struct pipe_winsys base;
17 Display *display;
18 int screen;
19 XImage *fbimage;
20 };
21
22 struct xsp_context
23 {
24 Drawable drawable;
25
26 void (*pipe_destroy)(struct pipe_video_context *vpipe);
27 };
28
29 struct xsp_buffer
30 {
31 struct pipe_buffer base;
32 boolean is_user_buffer;
33 void *data;
34 void *mapped_data;
35 };
36
37 static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
38 {
39 struct xsp_buffer *buffer;
40
41 assert(pws);
42
43 buffer = calloc(1, sizeof(struct xsp_buffer));
44 pipe_reference_init(&buffer->base.reference, 1);
45 buffer->base.alignment = alignment;
46 buffer->base.usage = usage;
47 buffer->base.size = size;
48 buffer->data = align_malloc(size, alignment);
49
50 return (struct pipe_buffer*)buffer;
51 }
52
53 static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
54 {
55 struct xsp_buffer *buffer;
56
57 assert(pws);
58
59 buffer = calloc(1, sizeof(struct xsp_buffer));
60 pipe_reference_init(&buffer->base.reference, 1);
61 buffer->base.size = size;
62 buffer->is_user_buffer = TRUE;
63 buffer->data = data;
64
65 return (struct pipe_buffer*)buffer;
66 }
67
68 static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
69 {
70 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
71
72 assert(pws);
73 assert(buffer);
74
75 xsp_buf->mapped_data = xsp_buf->data;
76
77 return xsp_buf->mapped_data;
78 }
79
80 static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
81 {
82 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
83
84 assert(pws);
85 assert(buffer);
86
87 xsp_buf->mapped_data = NULL;
88 }
89
90 static void xsp_buffer_destroy(struct pipe_buffer *buffer)
91 {
92 struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
93
94 assert(buffer);
95
96 if (!xsp_buf->is_user_buffer)
97 align_free(xsp_buf->data);
98
99 free(xsp_buf);
100 }
101
102 static struct pipe_buffer* xsp_surface_buffer_create
103 (
104 struct pipe_winsys *pws,
105 unsigned width,
106 unsigned height,
107 enum pipe_format format,
108 unsigned usage,
109 unsigned tex_usage,
110 unsigned *stride
111 )
112 {
113 const unsigned int ALIGNMENT = 1;
114 struct pipe_format_block block;
115 unsigned nblocksx, nblocksy;
116
117 pf_get_block(format, &block);
118 nblocksx = pf_get_nblocksx(&block, width);
119 nblocksy = pf_get_nblocksy(&block, height);
120 *stride = align(nblocksx * block.size, ALIGNMENT);
121
122 return pws->buffer_create(pws, ALIGNMENT,
123 usage,
124 *stride * nblocksy);
125 }
126
127 static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
128 {
129 assert(pws);
130 assert(ptr);
131 assert(fence);
132 }
133
134 static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
135 {
136 assert(pws);
137 assert(fence);
138
139 return 0;
140 }
141
142 static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
143 {
144 assert(pws);
145 assert(fence);
146
147 return 0;
148 }
149
150 static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
151 {
152 struct xsp_pipe_winsys *xsp_winsys;
153 struct xsp_context *xsp_context;
154
155 assert(pws);
156 assert(surface);
157 assert(context_private);
158
159 xsp_winsys = (struct xsp_pipe_winsys*)pws;
160 xsp_context = (struct xsp_context*)context_private;
161 xsp_winsys->fbimage->width = surface->width;
162 xsp_winsys->fbimage->height = surface->height;
163 xsp_winsys->fbimage->bytes_per_line = surface->width * (xsp_winsys->fbimage->bits_per_pixel >> 3);
164 xsp_winsys->fbimage->data = (char*)((struct xsp_buffer *)softpipe_texture(surface->texture)->buffer)->data + surface->offset;
165
166 XPutImage
167 (
168 xsp_winsys->display, xsp_context->drawable,
169 XDefaultGC(xsp_winsys->display, xsp_winsys->screen),
170 xsp_winsys->fbimage, 0, 0, 0, 0,
171 surface->width, surface->height
172 );
173 XFlush(xsp_winsys->display);
174 }
175
176 static const char* xsp_get_name(struct pipe_winsys *pws)
177 {
178 assert(pws);
179 return "X11 SoftPipe";
180 }
181
182 static void xsp_destroy(struct pipe_winsys *pws)
183 {
184 struct xsp_pipe_winsys *xsp_winsys = (struct xsp_pipe_winsys*)pws;
185
186 assert(pws);
187
188 /* XDestroyImage() wants to free the data as well */
189 xsp_winsys->fbimage->data = NULL;
190
191 XDestroyImage(xsp_winsys->fbimage);
192 FREE(xsp_winsys);
193 }
194
195 /* Called through pipe_video_context::destroy() */
196 static void xsp_pipe_destroy(struct pipe_video_context *vpipe)
197 {
198 struct xsp_context *xsp_context;
199
200 assert(vpipe);
201
202 xsp_context = vpipe->priv;
203
204 /* Call the original destroy */
205 xsp_context->pipe_destroy(vpipe);
206
207 FREE(xsp_context);
208 }
209
210 /* Show starts here */
211
212 Drawable
213 vl_video_bind_drawable(struct pipe_video_context *vpipe, Drawable drawable)
214 {
215 struct xsp_context *xsp_context;
216 Drawable old_drawable;
217
218 assert(vpipe);
219
220 xsp_context = vpipe->priv;
221 old_drawable = xsp_context->drawable;
222 xsp_context->drawable = drawable;
223
224 return old_drawable;
225 }
226
227 struct pipe_screen*
228 vl_screen_create(Display *display, int screen)
229 {
230 struct xsp_pipe_winsys *xsp_winsys;
231
232 assert(display);
233
234 xsp_winsys = CALLOC_STRUCT(xsp_pipe_winsys);
235 if (!xsp_winsys)
236 return NULL;
237
238 xsp_winsys->base.buffer_create = xsp_buffer_create;
239 xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
240 xsp_winsys->base.buffer_map = xsp_buffer_map;
241 xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
242 xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
243 xsp_winsys->base.surface_buffer_create = xsp_surface_buffer_create;
244 xsp_winsys->base.fence_reference = xsp_fence_reference;
245 xsp_winsys->base.fence_signalled = xsp_fence_signalled;
246 xsp_winsys->base.fence_finish = xsp_fence_finish;
247 xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
248 xsp_winsys->base.get_name = xsp_get_name;
249 xsp_winsys->base.destroy = xsp_destroy;
250 xsp_winsys->display = display;
251 xsp_winsys->screen = screen;
252 xsp_winsys->fbimage = XCreateImage
253 (
254 display,
255 XDefaultVisual(display, screen),
256 XDefaultDepth(display, screen),
257 ZPixmap,
258 0,
259 NULL,
260 0, /* Don't know the width and height until flush_frontbuffer */
261 0,
262 32,
263 0
264 );
265
266 if (!xsp_winsys->fbimage)
267 {
268 FREE(xsp_winsys);
269 return NULL;
270 }
271
272 XInitImage(xsp_winsys->fbimage);
273
274 return softpipe_create_screen(&xsp_winsys->base);
275 }
276
277 struct pipe_video_context*
278 vl_video_create(struct pipe_screen *screen,
279 enum pipe_video_profile profile,
280 enum pipe_video_chroma_format chroma_format,
281 unsigned width, unsigned height)
282 {
283 struct pipe_video_context *vpipe;
284 struct xsp_context *xsp_context;
285
286 assert(screen);
287 assert(width && height);
288
289 vpipe = sp_video_create(screen, profile, chroma_format, width, height);
290 if (!vpipe)
291 return NULL;
292
293 xsp_context = CALLOC_STRUCT(xsp_context);
294 if (!xsp_context)
295 {
296 vpipe->destroy(vpipe);
297 return NULL;
298 }
299
300 /* Override this so we can free our xsp_context when the pipe is freed */
301 xsp_context->pipe_destroy = vpipe->destroy;
302 vpipe->destroy = xsp_pipe_destroy;
303
304 vpipe->priv = xsp_context;
305
306 return vpipe;
307 }