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