Clean up xmesa winsys stuff
[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 )
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 {
162 /*
163 struct intel_context *intel = intel_pipe_winsys(sws)->intel;
164 __DRIdrawablePrivate *dPriv = intel->driDrawable;
165
166 intelCopyBuffer(dPriv, NULL);
167 */
168 }
169
170 static void
171 xm_wait_idle(struct pipe_winsys *pws)
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 return region;
250 }
251
252
253 static void
254 xm_region_release(struct pipe_winsys *winsys, struct pipe_region **region)
255 {
256 if (!*region)
257 return;
258
259 assert((*region)->refcount > 0);
260 (*region)->refcount--;
261
262 if ((*region)->refcount == 0) {
263 assert((*region)->map_refcount == 0);
264
265 winsys->buffer_reference( winsys, &((*region)->buffer), NULL );
266 free(*region);
267 }
268 *region = NULL;
269 }
270
271
272 /**
273 * Called via pipe->surface_alloc() to create new surfaces (textures,
274 * renderbuffers, etc.
275 */
276 static struct pipe_surface *
277 xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
278 {
279 struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
280
281 assert(ws);
282 assert(pipeFormat);
283
284 xms->surface.format = pipeFormat;
285 xms->surface.refcount = 1;
286 #if 0
287 /*
288 * This is really just a softpipe surface, not an XImage/Pixmap surface.
289 */
290 softpipe_init_surface_funcs(&xms->surface);
291 #endif
292 return &xms->surface;
293 }
294
295
296
297
298 /**
299 * Create a winsys layer.
300 * Nothing special for the Xlib driver so no subclassing or anything.
301 */
302 static struct pipe_winsys *
303 xmesa_create_pipe_winsys(void)
304 {
305 struct pipe_winsys *ws = CALLOC_STRUCT(pipe_winsys);
306
307 /* Fill in this struct with callbacks that pipe will need to
308 * communicate with the window system, buffer manager, etc.
309 */
310 ws->buffer_create = xm_buffer_create;
311 ws->user_buffer_create = xm_user_buffer_create;
312 ws->buffer_map = xm_buffer_map;
313 ws->buffer_unmap = xm_buffer_unmap;
314 ws->buffer_reference = xm_buffer_reference;
315 ws->buffer_data = xm_buffer_data;
316 ws->buffer_subdata = xm_buffer_subdata;
317 ws->buffer_get_subdata = xm_buffer_get_subdata;
318
319 ws->region_alloc = xm_region_alloc;
320 ws->region_release = xm_region_release;
321
322 ws->surface_alloc = xm_surface_alloc;
323
324 ws->flush_frontbuffer = xm_flush_frontbuffer;
325 ws->wait_idle = xm_wait_idle;
326 ws->printf = xm_printf;
327 ws->get_name = xm_get_name;
328
329 return ws;
330 }
331
332
333 static boolean
334 xmesa_is_format_supported(struct softpipe_winsys *sws, uint format)
335 {
336 switch (format) {
337 case PIPE_FORMAT_U_A8_R8_G8_B8:
338 case PIPE_FORMAT_S_R16_G16_B16_A16:
339 case PIPE_FORMAT_S8_Z24:
340 return TRUE;
341 default:
342 return FALSE;
343 };
344 }
345
346
347 static struct softpipe_winsys *
348 xmesa_create_softpipe_winsys(void)
349 {
350 struct softpipe_winsys *spws = CALLOC_STRUCT(softpipe_winsys);
351 if (spws) {
352 spws->is_format_supported = xmesa_is_format_supported;
353 }
354 return spws;
355 }
356
357
358 struct pipe_context *
359 xmesa_create_softpipe(XMesaContext xmesa)
360 {
361 struct pipe_winsys *pws = xmesa_create_pipe_winsys();
362 struct softpipe_winsys *spws = xmesa_create_softpipe_winsys();
363
364 return softpipe_create( pws, spws );
365 }