surface_alloc() is now a winsys function.
[mesa.git] / src / mesa / drivers / x11 / 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 * XMesa winsys, derived from softpipe winsys.
46 * NOTE: there's nothing really X-specific in this winsys layer so
47 * we could probably lift it up somewhere.
48 */
49 struct xm_winsys
50 {
51 struct softpipe_winsys sws;
52 int foo; /* placeholder */
53 };
54
55
56 /**
57 * Low-level OS/window system memory buffer
58 */
59 struct xm_buffer
60 {
61 boolean userBuffer; /** Is this a user-space buffer? */
62 int refcount;
63 unsigned size;
64 void *data;
65 void *mapped;
66 };
67
68
69
70 /* Turn the softpipe opaque buffer pointer into a dri_bufmgr opaque
71 * buffer pointer...
72 */
73 static inline struct xm_buffer *
74 xm_bo( struct pipe_buffer_handle *bo )
75 {
76 return (struct xm_buffer *) bo;
77 }
78
79 static inline struct pipe_buffer_handle *
80 pipe_bo( struct xm_buffer *bo )
81 {
82 return (struct pipe_buffer_handle *) bo;
83 }
84
85 /* Turn a softpipe winsys into an xm/softpipe winsys:
86 */
87 static inline struct xm_winsys *
88 xm_winsys(struct softpipe_winsys *sws)
89 {
90 return (struct xm_winsys *) sws;
91 }
92
93
94 /* Most callbacks map direcly onto dri_bufmgr operations:
95 */
96 static void *
97 xm_buffer_map(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
98 unsigned flags)
99 {
100 struct xm_buffer *xm_buf = xm_bo(buf);
101 xm_buf->mapped = xm_buf->data;
102 return xm_buf->mapped;
103 }
104
105 static void
106 xm_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer_handle *buf)
107 {
108 struct xm_buffer *xm_buf = xm_bo(buf);
109 xm_buf->mapped = NULL;
110 }
111
112 static void
113 xm_buffer_reference(struct pipe_winsys *pws,
114 struct pipe_buffer_handle **ptr,
115 struct pipe_buffer_handle *buf)
116 {
117 if (*ptr) {
118 struct xm_buffer *oldBuf = xm_bo(*ptr);
119 oldBuf->refcount--;
120 assert(oldBuf->refcount >= 0);
121 if (oldBuf->refcount == 0) {
122 if (oldBuf->data) {
123 if (!oldBuf->userBuffer)
124 free(oldBuf->data);
125 oldBuf->data = NULL;
126 }
127 free(oldBuf);
128 }
129 *ptr = NULL;
130 }
131
132 assert(!(*ptr));
133
134 if (buf) {
135 struct xm_buffer *newBuf = xm_bo(buf);
136 newBuf->refcount++;
137 *ptr = buf;
138 }
139 }
140
141 static void
142 xm_buffer_data(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
143 unsigned size, const void *data )
144 {
145 struct xm_buffer *xm_buf = xm_bo(buf);
146 assert(!xm_buf->userBuffer);
147 if (xm_buf->size != size) {
148 if (xm_buf->data)
149 free(xm_buf->data);
150 xm_buf->data = malloc(size);
151 xm_buf->size = size;
152 }
153 if (data)
154 memcpy(xm_buf->data, data, size);
155 }
156
157 static void
158 xm_buffer_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
159 unsigned long offset, unsigned long size, const void *data)
160 {
161 struct xm_buffer *xm_buf = xm_bo(buf);
162 GLubyte *b = (GLubyte *) xm_buf->data;
163 assert(!xm_buf->userBuffer);
164 assert(b);
165 memcpy(b + offset, data, size);
166 }
167
168 static void
169 xm_buffer_get_subdata(struct pipe_winsys *pws, struct pipe_buffer_handle *buf,
170 unsigned long offset, unsigned long size, void *data)
171 {
172 const struct xm_buffer *xm_buf = xm_bo(buf);
173 const GLubyte *b = (GLubyte *) xm_buf->data;
174 assert(!xm_buf->userBuffer);
175 assert(b);
176 memcpy(data, b + offset, size);
177 }
178
179 static void
180 xm_flush_frontbuffer(struct pipe_winsys *pws)
181 {
182 /*
183 struct intel_context *intel = intel_pipe_winsys(sws)->intel;
184 __DRIdrawablePrivate *dPriv = intel->driDrawable;
185
186 intelCopyBuffer(dPriv, NULL);
187 */
188 }
189
190 static void
191 xm_wait_idle(struct pipe_winsys *pws)
192 {
193 /* no-op */
194 }
195
196 static void
197 xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
198 {
199 va_list args;
200 va_start( args, fmtString );
201 vfprintf(stderr, fmtString, args);
202 va_end( args );
203 }
204
205 static const char *
206 xm_get_name(struct pipe_winsys *pws)
207 {
208 return "Xlib";
209 }
210
211
212 static struct pipe_buffer_handle *
213 xm_buffer_create(struct pipe_winsys *pws, unsigned alignment)
214 {
215 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
216 buffer->refcount = 1;
217 return pipe_bo(buffer);
218 }
219
220
221 /**
222 * Create buffer which wraps user-space data.
223 */
224 static struct pipe_buffer_handle *
225 xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
226 {
227 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
228 buffer->userBuffer = TRUE;
229 buffer->refcount = 1;
230 buffer->data = ptr;
231 buffer->size = bytes;
232 return pipe_bo(buffer);
233 }
234
235
236
237 /**
238 * Round n up to next multiple.
239 */
240 static INLINE unsigned
241 round_up(unsigned n, unsigned multiple)
242 {
243 return (n + multiple - 1) & ~(multiple - 1);
244 }
245
246
247 static struct pipe_region *
248 xm_region_alloc(struct pipe_winsys *winsys,
249 unsigned cpp, unsigned width, unsigned height, unsigned flags)
250 {
251 struct pipe_region *region = CALLOC_STRUCT(pipe_region);
252 const unsigned alignment = 64;
253
254 region->cpp = cpp;
255 region->pitch = round_up(width, alignment / cpp);
256 region->height = height;
257 region->refcount = 1;
258
259 assert(region->pitch > 0);
260
261 region->buffer = winsys->buffer_create( winsys, alignment )
262 ;
263
264 /* NULL data --> just allocate the space */
265 winsys->buffer_data( winsys,
266 region->buffer,
267 region->pitch * cpp * height,
268 NULL );
269 return region;
270 }
271
272
273 static void
274 xm_region_release(struct pipe_winsys *winsys, struct pipe_region **region)
275 {
276 if (!*region)
277 return;
278
279 assert((*region)->refcount > 0);
280 (*region)->refcount--;
281
282 if ((*region)->refcount == 0) {
283 assert((*region)->map_refcount == 0);
284
285 winsys->buffer_reference( winsys, &((*region)->buffer), NULL );
286 free(*region);
287 }
288 *region = NULL;
289 }
290
291
292 /**
293 * Called via pipe->surface_alloc() to create new surfaces (textures,
294 * renderbuffers, etc.
295 */
296 static struct pipe_surface *
297 xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
298 {
299 struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
300
301 assert(ws);
302 assert(pipeFormat);
303
304 xms->surface.format = pipeFormat;
305 xms->surface.refcount = 1;
306 #if 0
307 /*
308 * This is really just a softpipe surface, not an XImage/Pixmap surface.
309 */
310 softpipe_init_surface_funcs(&xms->surface);
311 #endif
312 return &xms->surface;
313 }
314
315
316
317
318 struct xmesa_pipe_winsys
319 {
320 struct pipe_winsys winsys;
321 XMesaContext xmesa;
322 };
323
324 static struct pipe_winsys *
325 xmesa_create_pipe_winsys( XMesaContext xmesa )
326 {
327 struct xmesa_pipe_winsys *xws = CALLOC_STRUCT(xmesa_pipe_winsys);
328
329 /* Fill in this struct with callbacks that pipe will need to
330 * communicate with the window system, buffer manager, etc.
331 *
332 * Pipe would be happy with a malloc based memory manager, but
333 * the SwapBuffers implementation in this winsys driver requires
334 * that rendering be done to an appropriate _DriBufferObject.
335 */
336 xws->winsys.buffer_create = xm_buffer_create;
337 xws->winsys.user_buffer_create = xm_user_buffer_create;
338 xws->winsys.buffer_map = xm_buffer_map;
339 xws->winsys.buffer_unmap = xm_buffer_unmap;
340 xws->winsys.buffer_reference = xm_buffer_reference;
341 xws->winsys.buffer_data = xm_buffer_data;
342 xws->winsys.buffer_subdata = xm_buffer_subdata;
343 xws->winsys.buffer_get_subdata = xm_buffer_get_subdata;
344
345 xws->winsys.region_alloc = xm_region_alloc;
346 xws->winsys.region_release = xm_region_release;
347
348 xws->winsys.surface_alloc = xm_surface_alloc;
349
350 xws->winsys.flush_frontbuffer = xm_flush_frontbuffer;
351 xws->winsys.wait_idle = xm_wait_idle;
352 xws->winsys.printf = xm_printf;
353 xws->winsys.get_name = xm_get_name;
354 xws->xmesa = xmesa;
355
356 return &xws->winsys;
357 }
358
359
360 struct pipe_context *
361 xmesa_create_softpipe(XMesaContext xmesa)
362 {
363 struct xm_winsys *xm_ws = CALLOC_STRUCT( xm_winsys );
364
365 /* Create the softpipe context:
366 */
367 return softpipe_create( xmesa_create_pipe_winsys(xmesa), &xm_ws->sws );
368 }