Eliminate struct pipe_region.
[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 void *context_private)
163 {
164 /* The Xlib driver's front color surfaces are actually X Windows so
165 * this flush is a no-op.
166 * If we instead did front buffer rendering to a temporary XImage,
167 * this would be the place to copy the Ximage to the on-screen Window.
168 */
169 }
170
171
172 static void
173 xm_printf(struct pipe_winsys *pws, const char *fmtString, ...)
174 {
175 va_list args;
176 va_start( args, fmtString );
177 vfprintf(stderr, fmtString, args);
178 va_end( args );
179 }
180
181 static const char *
182 xm_get_name(struct pipe_winsys *pws)
183 {
184 return "Xlib";
185 }
186
187
188 static struct pipe_buffer_handle *
189 xm_buffer_create(struct pipe_winsys *pws, unsigned flags)
190 {
191 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
192 buffer->refcount = 1;
193 return pipe_bo(buffer);
194 }
195
196
197 /**
198 * Create buffer which wraps user-space data.
199 */
200 static struct pipe_buffer_handle *
201 xm_user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
202 {
203 struct xm_buffer *buffer = CALLOC_STRUCT(xm_buffer);
204 buffer->userBuffer = TRUE;
205 buffer->refcount = 1;
206 buffer->data = ptr;
207 buffer->size = bytes;
208 return pipe_bo(buffer);
209 }
210
211
212
213 /**
214 * Round n up to next multiple.
215 */
216 static INLINE unsigned
217 round_up(unsigned n, unsigned multiple)
218 {
219 return (n + multiple - 1) & ~(multiple - 1);
220 }
221
222
223 static unsigned
224 xm_surface_pitch(struct pipe_winsys *winsys, unsigned cpp, unsigned width,
225 unsigned flags)
226 {
227 return round_up(width, 64 / cpp);
228 }
229
230
231 /**
232 * Called via pipe->surface_alloc() to create new surfaces (textures,
233 * renderbuffers, etc.
234 */
235 static struct pipe_surface *
236 xm_surface_alloc(struct pipe_winsys *ws, GLuint pipeFormat)
237 {
238 struct xmesa_surface *xms = CALLOC_STRUCT(xmesa_surface);
239
240 assert(ws);
241 assert(pipeFormat);
242
243 xms->surface.format = pipeFormat;
244 xms->surface.refcount = 1;
245 xms->surface.winsys = ws;
246 #if 0
247 /*
248 * This is really just a softpipe surface, not an XImage/Pixmap surface.
249 */
250 softpipe_init_surface_funcs(&xms->surface);
251 #endif
252 return &xms->surface;
253 }
254
255
256
257 static void
258 xm_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
259 {
260 struct pipe_surface *surf = *s;
261 surf->refcount--;
262 if (surf->refcount == 0) {
263 if (surf->buffer)
264 winsys->buffer_reference(winsys, &surf->buffer, NULL);
265 free(surf);
266 }
267 *s = NULL;
268 }
269
270
271
272 /**
273 * Return pointer to a pipe_winsys object.
274 * For Xlib, this is a singleton object.
275 * Nothing special for the Xlib driver so no subclassing or anything.
276 */
277 struct pipe_winsys *
278 xmesa_get_pipe_winsys(void)
279 {
280 static struct pipe_winsys *ws = NULL;
281
282 if (!ws) {
283 ws = CALLOC_STRUCT(pipe_winsys);
284
285 /* Fill in this struct with callbacks that pipe will need to
286 * communicate with the window system, buffer manager, etc.
287 */
288 ws->buffer_create = xm_buffer_create;
289 ws->user_buffer_create = xm_user_buffer_create;
290 ws->buffer_map = xm_buffer_map;
291 ws->buffer_unmap = xm_buffer_unmap;
292 ws->buffer_reference = xm_buffer_reference;
293 ws->buffer_data = xm_buffer_data;
294 ws->buffer_subdata = xm_buffer_subdata;
295 ws->buffer_get_subdata = xm_buffer_get_subdata;
296
297 ws->surface_pitch = xm_surface_pitch;
298 ws->surface_alloc = xm_surface_alloc;
299 ws->surface_release = xm_surface_release;
300
301 ws->flush_frontbuffer = xm_flush_frontbuffer;
302 ws->printf = xm_printf;
303 ws->get_name = xm_get_name;
304 }
305
306 return ws;
307 }
308
309
310 /**
311 * XXX this depends on the depths supported by the screen (8/16/32/etc).
312 * Maybe when we're about to create a context/drawable we create a new
313 * softpipe_winsys object that corresponds to the specified screen...
314 *
315 * Also, this query only really matters for on-screen drawables.
316 * For textures and FBOs we (softpipe) can support any format.o
317 */
318 static boolean
319 xmesa_is_format_supported(struct softpipe_winsys *sws, uint format)
320 {
321 /* Any format supported by softpipe can be listed here.
322 * This query is not used for allocating window-system color buffers
323 * (which would depend on the screen depth/bpp).
324 */
325 switch (format) {
326 case PIPE_FORMAT_U_A8_R8_G8_B8:
327 case PIPE_FORMAT_S_R16_G16_B16_A16:
328 case PIPE_FORMAT_S8_Z24:
329 case PIPE_FORMAT_U_S8:
330 case PIPE_FORMAT_U_Z16:
331 case PIPE_FORMAT_U_Z32:
332 return TRUE;
333 default:
334 return FALSE;
335 };
336 }
337
338
339 /**
340 * Return pointer to a softpipe_winsys object.
341 * For Xlib, this is a singleton object.
342 */
343 static struct softpipe_winsys *
344 xmesa_get_softpipe_winsys(void)
345 {
346 static struct softpipe_winsys *spws = NULL;
347
348 if (!spws) {
349 spws = CALLOC_STRUCT(softpipe_winsys);
350 if (spws) {
351 spws->is_format_supported = xmesa_is_format_supported;
352 }
353 }
354
355 return spws;
356 }
357
358
359 struct pipe_context *
360 xmesa_create_context(XMesaContext xmesa)
361 {
362 struct pipe_winsys *pws = xmesa_get_pipe_winsys();
363 struct softpipe_winsys *spws = xmesa_get_softpipe_winsys();
364
365 return softpipe_create( pws, spws );
366 }