Remove context dependencies in winsys layer.
[mesa.git] / src / mesa / pipe / xlib / xm_winsys.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA
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 SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
18 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
19 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 *
26 *
27 **************************************************************************/
28
29 /*
30 * Authors:
31 * Keith Whitwell
32 * Brian Paul
33 */
34
35
36 #include "glxheader.h"
37 #include "xmesaP.h"
38 #include "main/macros.h"
39
40 #include "pipe/p_winsys.h"
41 #include "pipe/softpipe/sp_winsys.h"
42
43
44 /**
45 * Low-level OS/window system memory buffer
46 */
47 struct xm_buffer
48 {
49 boolean userBuffer; /** Is this a user-space buffer? */
50 int refcount;
51 unsigned size;
52 void *data;
53 void *mapped;
54 };
55
56
57
58 /* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
59 * buffer pointer...
60 */
61 static inline struct xm_buffer *
62 xm_bo( struct pipe_buffer_handle *bo )
63 {
64 return (struct xm_buffer *) bo;
65 }
66
67 static inline struct pipe_buffer_handle *
68 pipe_bo( struct xm_buffer *bo )
69 {
70 return (struct pipe_buffer_handle *) bo;
71 }
72
73
74 /* Most callbacks map direcly onto dri_bufmgr operations:
75 */
76 static void *
77 xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
78 unsigned flags)
79 {
80 struct xm_buffer *xm_buf = xm_bo(buf);
81 xm_buf->mapped = xm_buf->data;
82 return xm_buf->mapped;
83 }
84
85 static void
86 xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer_handle *buf)
87 {
88 struct xm_buffer *xm_buf = xm_bo(buf);
89 xm_buf->mapped = NULL;
90 }
91
92 static void
93 xm_buffer_reference(struct pipe_winsys *pws,
94 struct pipe_buffer_handle **ptr,
95 struct pipe_buffer_handle *buf)
96 {
97 if (*ptr) {
98 struct xm_buffer *oldBuf = xm_bo(*ptr);
99 oldBuf->refcount--;
100 assert(oldBuf->refcount >= 0);
101 if (oldBuf->refcount == 0) {
102 if (oldBuf->data) {
103 if (!oldBuf->userBuffer)
104 free(oldBuf->data);
105 oldBuf->data = NULL;
106 }
107 free(oldBuf);
108 }
109 *ptr = NULL;
110 }
111
112 assert(!(*ptr));
113
114 if (buf) {
115 struct xm_buffer *newBuf = xm_bo(buf);
116 newBuf->refcount++;
117 *ptr = buf;
118 }
119 }
120
121 static void
122 xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
123 unsigned size, const void *data, unsigned usage )
124 {
125 struct xm_buffer *xm_buf = xm_bo(buf);
126 assert(!xm_buf->userBuffer);
127 if (xm_buf->size != size) {
128 if (xm_buf->data)
129 free(xm_buf->data);
130 xm_buf->data = malloc(size);
131 xm_buf->size = size;
132 }
133 if (data)
134 memcpy(xm_buf->data, data, size);
135 }
136
137 static void
138 xm_buffer_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
139 unsigned long offset, unsigned long size, const void *data)
140 {
141 struct xm_buffer *xm_buf = xm_bo(buf);
142 GLubyte *b = (GLubyte *) xm_buf->data;
143 assert(!xm_buf->userBuffer);
144 assert(b);
145 memcpy(b + offset, data, size);
146 }
147
148 static void
149 xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
150 unsigned long offset, unsigned long size, void *data)
151 {
152 const struct xm_buffer *xm_buf = xm_bo(buf);
153 const GLubyte *b = (GLubyte *) xm_buf->data;
154 assert(!xm_buf->userBuffer);
155 assert(b);
156 memcpy(data, b + offset, size);
157 }
158
159 static void
160 xm_flush_frontbuffer(struct pipe_winsys *pws,
161 struct pipe_surface *surf )
162 {
163 /* The Xlib driver's front color surfaces are actually X Windows so
164 * this flush is a no-op.
165 * If we instead did front buffer rendering to a temporary XImage,
166 * this would be the place to copy the Ximage to the on-screen Window.
167 */
168 }
169
170 static void
171 xm_wait_idle(struct pipe_winsys *pws, void *context_private)
172 {
173 /* no-op */
174 }
175
176 static void
177 xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
178 {
179 va_list args;
180 va_start( args, fmtString );
181 vfprintf(stderr, fmtString, args);
182 va_end( args );
183 }
184
185 static const char *
186 xm_get_name(struct pipe_winsys *pws)
187 {
188 return "Xlib";
189 }
190
191
192 static struct pipe_buffer_handle *
193 xm_buffer_create(struct pipe_winsys *pws, unsigned alignment)
194 {
195 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
196 buffer->refcount = 1;
197 return pipe_bo(buffer);
198 }
199
200
201 /**
202 * Create buffer which wraps user-space data.
203 */
204 static struct pipe_buffer_handle *
205 xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
206 {
207 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
208 buffer->userBuffer = TRUE;
209 buffer->refcount = 1;
210 buffer->data = ptr;
211 buffer->size = bytes;
212 return pipe_bo(buffer);
213 }
214
215
216
217 /**
218 * Round n up to next multiple.
219 */
220 static INLINE unsigned
221 round_up(unsigned n, unsigned multiple)
222 {
223 return (n + multiple - 1) & ~(multiple - 1);
224 }
225
226
227 static struct pipe_region *
228 xm_region_alloc(struct pipe_winsys *winsys,
229 unsigned cpp, unsigned width, unsigned height, unsigned flags)
230 {
231 struct pipe_region *region = CALLOC_STRUCT(pipe_region);
232 const unsigned alignment = 64;
233
234 region->cpp = cpp;
235 region->pitch = round_up(width, alignment / cpp);
236 region->height = height;
237 region->refcount = 1;
238
239 assert(region->pitch > 0);
240
241 region->buffer = winsys->buffer_create( winsys, alignment )
242 ;
243
244 /* NULL data --> just allocate the space */
245 winsys->buffer_data( winsys,
246 region->buffer,
247 region->pitch * cpp * height,
248 NULL,
249 PIPE_BUFFER_USAGE_PIXEL );
250 return region;
251 }
252
253
254 static void
255 xm_region_release(struct pipe_winsys *winsys, struct pipe_region **region)
256 {
257 if (!*region)
258 return;
259
260 assert((*region)->refcount > 0);
261 (*region)->refcount--;
262
263 if ((*region)->refcount == 0) {
264 assert((*region)->map_refcount == 0);
265
266 winsys->buffer_reference( winsys, &((*region)->buffer), NULL );
267 free(*region);
268 }
269 *region = NULL;
270 }
271
272
273 /**
274 * Called via pipe->surface_alloc() to create new surfaces (textures,
275 * renderbuffers, etc.
276 */
277 static struct pipe_surface *
278 xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
279 {
280 struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
281
282 assert(ws);
283 assert(pipeFormat);
284
285 xms->surface.format = pipeFormat;
286 xms->surface.refcount = 1;
287 xms->surface.winsys = ws;
288 #if 0
289 /*
290 * This is really just a softpipe surface, not an XImage/Pixmap surface.
291 */
292 softpipe_init_surface_funcs(&xms->surface);
293 #endif
294 return &xms->surface;
295 }
296
297
298
299 static void
300 xm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
301 {
302 struct pipe_surface *surf = *s;
303 surf->refcount--;
304 if (surf->refcount == 0) {
305 if (surf->region)
306 winsys->region_release(winsys, &surf->region);
307 free(surf);
308 }
309 *s = NULL;
310 }
311
312
313
314 /**
315 * Return pointer to a pipe_winsys object.
316 * For Xlib, this is a singleton object.
317 * Nothing special for the Xlib driver so no subclassing or anything.
318 */
319 struct pipe_winsys *
320 xmesa_get_pipe_winsys(void)
321 {
322 static struct pipe_winsys *ws = NULL;
323
324 if (!ws) {
325 ws = CALLOC_STRUCT(pipe_winsys);
326
327 /* Fill in this struct with callbacks that pipe will need to
328 * communicate with the window system, buffer manager, etc.
329 */
330 ws->buffer_create = xm_buffer_create;
331 ws->user_buffer_create = xm_user_buffer_create;
332 ws->buffer_map = xm_buffer_map;
333 ws->buffer_unmap = xm_buffer_unmap;
334 ws->buffer_reference = xm_buffer_reference;
335 ws->buffer_data = xm_buffer_data;
336 ws->buffer_subdata = xm_buffer_subdata;
337 ws->buffer_get_subdata = xm_buffer_get_subdata;
338
339 ws->region_alloc = xm_region_alloc;
340 ws->region_release = xm_region_release;
341
342 ws->surface_alloc = xm_surface_alloc;
343 ws->surface_release = xm_surface_release;
344
345 ws->flush_frontbuffer = xm_flush_frontbuffer;
346 ws->wait_idle = xm_wait_idle;
347 ws->printf = xm_printf;
348 ws->get_name = xm_get_name;
349 }
350
351 return ws;
352 }
353
354
355 /**
356 * XXX this depends on the depths supported by the screen (8/16/32/etc).
357 * Maybe when we're about to create a context/drawable we create a new
358 * softpipe_winsys object that corresponds to the specified screen...
359 *
360 * Also, this query only really matters for on-screen drawables.
361 * For textures and FBOs we (softpipe) can support any format.o
362 */
363 static boolean
364 xmesa_is_format_supported(struct softpipe_winsys *sws, uint format)
365 {
366 /* Any format supported by softpipe can be listed here.
367 * This query is not used for allocating window-system color buffers
368 * (which would depend on the screen depth/bpp).
369 */
370 switch (format) {
371 case PIPE_FORMAT_U_A8_R8_G8_B8:
372 case PIPE_FORMAT_S_R16_G16_B16_A16:
373 case PIPE_FORMAT_S8_Z24:
374 case PIPE_FORMAT_U_S8:
375 case PIPE_FORMAT_U_Z16:
376 case PIPE_FORMAT_U_Z32:
377 return TRUE;
378 default:
379 return FALSE;
380 };
381 }
382
383
384 /**
385 * Return pointer to a softpipe_winsys object.
386 * For Xlib, this is a singleton object.
387 */
388 static struct softpipe_winsys *
389 xmesa_get_softpipe_winsys(void)
390 {
391 static struct softpipe_winsys *spws = NULL;
392
393 if (!spws) {
394 spws = CALLOC_STRUCT(softpipe_winsys);
395 if (spws) {
396 spws->is_format_supported = xmesa_is_format_supported;
397 }
398 }
399
400 return spws;
401 }
402
403
404 struct pipe_context *
405 xmesa_create_context(XMesaContext xmesa)
406 {
407 struct pipe_winsys *pws = xmesa_get_pipe_winsys();
408 struct softpipe_winsys *spws = xmesa_get_softpipe_winsys();
409
410 return softpipe_create( pws, spws );
411 }