radeon/r200/r300: cleanup some of the renderbuffer code
[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 /* Borrowed from Mesa's xm_winsys */
100 static unsigned int round_up(unsigned n, unsigned multiple)
101 {
102 return (n + multiple - 1) & ~(multiple - 1);
103 }
104
105 static struct pipe_buffer* xsp_surface_buffer_create
106 (
107 struct pipe_winsys *pws,
108 unsigned width,
109 unsigned height,
110 enum pipe_format format,
111 unsigned usage,
112 unsigned *stride
113 )
114 {
115 const unsigned int ALIGNMENT = 1;
116 struct pipe_format_block block;
117 unsigned nblocksx, nblocksy;
118
119 pf_get_block(format, &block);
120 nblocksx = pf_get_nblocksx(&block, width);
121 nblocksy = pf_get_nblocksy(&block, height);
122 *stride = round_up(nblocksx * block.size, ALIGNMENT);
123
124 return winsys->buffer_create(winsys, ALIGNMENT,
125 usage,
126 *stride * nblocksy);
127 }
128
129 static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
130 {
131 assert(pws);
132 assert(ptr);
133 assert(fence);
134 }
135
136 static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
137 {
138 assert(pws);
139 assert(fence);
140
141 return 0;
142 }
143
144 static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
145 {
146 assert(pws);
147 assert(fence);
148
149 return 0;
150 }
151
152 static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
153 {
154 struct xsp_pipe_winsys *xsp_winsys;
155 struct xsp_context *xsp_context;
156
157 assert(pws);
158 assert(surface);
159 assert(context_private);
160
161 xsp_winsys = (struct xsp_pipe_winsys*)pws;
162 xsp_context = (struct xsp_context*)context_private;
163
164 if (!xsp_context->drawable_bound)
165 return;
166
167 xsp_winsys->fbimage.width = surface->width;
168 xsp_winsys->fbimage.height = surface->height;
169 xsp_winsys->fbimage.bytes_per_line = surface->width * (xsp_winsys->fbimage.bits_per_pixel >> 3);
170 xsp_winsys->fbimage.data = pipe_surface_map(surface, 0);
171
172 XPutImage
173 (
174 xsp_context->display,
175 xsp_context->drawable,
176 XDefaultGC(xsp_context->display, xsp_context->screen),
177 &xsp_winsys->fbimage,
178 0,
179 0,
180 0,
181 0,
182 surface->width,
183 surface->height
184 );
185 XFlush(xsp_context->display);
186 pipe_surface_unmap(surface);
187 }
188
189 static const char* xsp_get_name(struct pipe_winsys *pws)
190 {
191 assert(pws);
192 return "X11 SoftPipe";
193 }
194
195 /* Show starts here */
196
197 int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable)
198 {
199 struct xsp_context *xsp_context;
200
201 assert(pipe);
202
203 xsp_context = pipe->priv;
204 xsp_context->drawable = drawable;
205 xsp_context->drawable_bound = 1;
206
207 return 0;
208 }
209
210 int unbind_pipe_drawable(struct pipe_context *pipe)
211 {
212 struct xsp_context *xsp_context;
213
214 assert(pipe);
215
216 xsp_context = pipe->priv;
217 xsp_context->drawable_bound = 0;
218
219 return 0;
220 }
221
222 struct pipe_context* create_pipe_context(Display *display, int screen)
223 {
224 struct xsp_pipe_winsys *xsp_winsys;
225 struct xsp_context *xsp_context;
226 struct pipe_screen *sp_screen;
227 struct pipe_context *sp_pipe;
228
229 assert(display);
230
231 xsp_winsys = calloc(1, sizeof(struct xsp_pipe_winsys));
232 xsp_winsys->base.buffer_create = xsp_buffer_create;
233 xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
234 xsp_winsys->base.buffer_map = xsp_buffer_map;
235 xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
236 xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
237 xsp_winsys->base.surface_buffer_create = xsp_surface_buffer_create;
238 xsp_winsys->base.fence_reference = xsp_fence_reference;
239 xsp_winsys->base.fence_signalled = xsp_fence_signalled;
240 xsp_winsys->base.fence_finish = xsp_fence_finish;
241 xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
242 xsp_winsys->base.get_name = xsp_get_name;
243
244 {
245 /* XXX: Can't use the returned XImage* directly,
246 since we don't have control over winsys destruction
247 and we wouldn't be able to free it */
248 XImage *template = XCreateImage
249 (
250 display,
251 XDefaultVisual(display, XDefaultScreen(display)),
252 XDefaultDepth(display, XDefaultScreen(display)),
253 ZPixmap,
254 0,
255 NULL,
256 0, /* Don't know the width and height until flush_frontbuffer */
257 0,
258 32,
259 0
260 );
261
262 memcpy(&xsp_winsys->fbimage, template, sizeof(XImage));
263 XInitImage(&xsp_winsys->fbimage);
264
265 XDestroyImage(template);
266 }
267
268 sp_screen = softpipe_create_screen((struct pipe_winsys*)xsp_winsys);
269 sp_pipe = softpipe_create(sp_screen, (struct pipe_winsys*)xsp_winsys, NULL);
270
271 xsp_context = calloc(1, sizeof(struct xsp_context));
272 xsp_context->display = display;
273 xsp_context->screen = screen;
274
275 sp_pipe->priv = xsp_context;
276
277 return sp_pipe;
278 }
279
280 int destroy_pipe_context(struct pipe_context *pipe)
281 {
282 struct pipe_screen *screen;
283 struct pipe_winsys *winsys;
284
285 assert(pipe);
286
287 screen = pipe->screen;
288 winsys = pipe->winsys;
289 free(pipe->priv);
290 pipe->destroy(pipe);
291 screen->destroy(screen);
292 free(winsys);
293
294 return 0;
295 }