Merge branch 'master' into gallium-0.2
[mesa.git] / src / gallium / winsys / egl_xlib / sw_winsys.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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 above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * Totally software-based winsys layer.
30 * Note that the one winsys function that we can't implement here
31 * is flush_frontbuffer().
32 * Whoever uses this code will have to provide that.
33 *
34 * Authors: Brian Paul
35 */
36
37
38 #include "pipe/p_winsys.h"
39 #include "pipe/p_state.h"
40 #include "pipe/p_inlines.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43
44 #include "sw_winsys.h"
45
46
47
48 /** Subclass of pipe_winsys */
49 struct sw_pipe_winsys
50 {
51 struct pipe_winsys Base;
52 /* no extra fields for now */
53 };
54
55
56 /** subclass of pipe_buffer */
57 struct sw_pipe_buffer
58 {
59 struct pipe_buffer Base;
60 boolean UserBuffer; /** Is this a user-space buffer? */
61 void *Data;
62 void *Mapped;
63 };
64
65
66 /** cast wrapper */
67 static INLINE struct sw_pipe_buffer *
68 sw_pipe_buffer(struct pipe_buffer *b)
69 {
70 return (struct sw_pipe_buffer *) b;
71 }
72
73
74 /**
75 * Round n up to next multiple.
76 */
77 static INLINE unsigned
78 round_up(unsigned n, unsigned multiple)
79 {
80 return (n + multiple - 1) & ~(multiple - 1);
81 }
82
83
84 static const char *
85 get_name(struct pipe_winsys *pws)
86 {
87 return "software";
88 }
89
90
91 /** Create new pipe_buffer and allocate storage of given size */
92 static struct pipe_buffer *
93 buffer_create(struct pipe_winsys *pws,
94 unsigned alignment,
95 unsigned usage,
96 unsigned size)
97 {
98 struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
99 if (!buffer)
100 return NULL;
101
102 buffer->Base.refcount = 1;
103 buffer->Base.alignment = alignment;
104 buffer->Base.usage = usage;
105 buffer->Base.size = size;
106
107 /* align to 16-byte multiple for Cell */
108 buffer->Data = align_malloc(size, MAX2(alignment, 16));
109
110 return &buffer->Base;
111 }
112
113
114 /**
115 * Create buffer which wraps user-space data.
116 */
117 static struct pipe_buffer *
118 user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
119 {
120 struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
121 if (!buffer)
122 return NULL;
123
124 buffer->Base.refcount = 1;
125 buffer->Base.size = bytes;
126 buffer->UserBuffer = TRUE;
127 buffer->Data = ptr;
128
129 return &buffer->Base;
130 }
131
132
133 static void *
134 buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
135 {
136 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
137 buffer->Mapped = buffer->Data;
138 return buffer->Mapped;
139 }
140
141
142 static void
143 buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
144 {
145 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
146 buffer->Mapped = NULL;
147 }
148
149
150 static void
151 buffer_destroy(struct pipe_winsys *pws, struct pipe_buffer *buf)
152 {
153 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
154
155 if (buffer->Data && !buffer->UserBuffer) {
156 align_free(buffer->Data);
157 buffer->Data = NULL;
158 }
159
160 free(buffer);
161 }
162
163
164 /**
165 * Called via winsys->surface_alloc() to create new surfaces.
166 */
167 static struct pipe_surface *
168 surface_alloc(struct pipe_winsys *ws)
169 {
170 struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
171 if (!surf)
172 return NULL;
173
174 surf->refcount = 1;
175 surf->winsys = ws;
176
177 return surf;
178 }
179
180
181 static int
182 surface_alloc_storage(struct pipe_winsys *winsys,
183 struct pipe_surface *surf,
184 unsigned width, unsigned height,
185 enum pipe_format format,
186 unsigned flags,
187 unsigned tex_usage)
188 {
189 const unsigned alignment = 64;
190
191 surf->width = width;
192 surf->height = height;
193 surf->format = format;
194 pf_get_block(surf->format, &surf->block);
195 surf->nblocksx = pf_get_nblocksx(&surf->block, width);
196 surf->nblocksy = pf_get_nblocksy(&surf->block, height);
197 surf->stride = round_up(surf->nblocksx * surf->block.size, alignment);
198 surf->usage = flags;
199
200 assert(!surf->buffer);
201 surf->buffer = winsys->buffer_create(winsys, alignment,
202 PIPE_BUFFER_USAGE_PIXEL,
203 surf->stride * height);
204 if(!surf->buffer)
205 return -1;
206
207 return 0;
208 }
209
210
211 static void
212 surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
213 {
214 struct pipe_surface *surf = *s;
215 assert(!surf->texture);
216 surf->refcount--;
217 if (surf->refcount == 0) {
218 if (surf->buffer)
219 winsys_buffer_reference(winsys, &surf->buffer, NULL);
220 free(surf);
221 }
222 *s = NULL;
223 }
224
225
226 static void
227 fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
228 struct pipe_fence_handle *fence)
229 {
230 /* no-op */
231 }
232
233
234 static int
235 fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
236 unsigned flag)
237 {
238 /* no-op */
239 return 0;
240 }
241
242
243 static int
244 fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
245 unsigned flag)
246 {
247 /* no-op */
248 return 0;
249 }
250
251
252 /**
253 * Create/return a new pipe_winsys object.
254 */
255 struct pipe_winsys *
256 create_sw_winsys(void)
257 {
258 struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
259 if (!ws)
260 return NULL;
261
262 /* Fill in this struct with callbacks that pipe will need to
263 * communicate with the window system, buffer manager, etc.
264 */
265 ws->Base.buffer_create = buffer_create;
266 ws->Base.user_buffer_create = user_buffer_create;
267 ws->Base.buffer_map = buffer_map;
268 ws->Base.buffer_unmap = buffer_unmap;
269 ws->Base.buffer_destroy = buffer_destroy;
270
271 ws->Base.surface_alloc = surface_alloc;
272 ws->Base.surface_alloc_storage = surface_alloc_storage;
273 ws->Base.surface_release = surface_release;
274
275 ws->Base.fence_reference = fence_reference;
276 ws->Base.fence_signalled = fence_signalled;
277 ws->Base.fence_finish = fence_finish;
278
279 ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
280
281 ws->Base.get_name = get_name;
282
283 return &ws->Base;
284 }