st/xorg: Work around cursor reference counting bugs in older X servers.
[mesa.git] / src / gallium / state_trackers / egl / x11 / 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 "util/u_simple_screen.h"
39 #include "pipe/p_state.h"
40 #include "util/u_inlines.h"
41 #include "util/u_format.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44
45 #include "sw_winsys.h"
46
47
48
49 /** Subclass of pipe_winsys */
50 struct sw_pipe_winsys
51 {
52 struct pipe_winsys Base;
53 /* no extra fields for now */
54 };
55
56
57 /** subclass of pipe_buffer */
58 struct sw_pipe_buffer
59 {
60 struct pipe_buffer Base;
61 boolean UserBuffer; /** Is this a user-space buffer? */
62 void *Data;
63 void *Mapped;
64 };
65
66
67 /** cast wrapper */
68 static INLINE struct sw_pipe_buffer *
69 sw_pipe_buffer(struct pipe_buffer *b)
70 {
71 return (struct sw_pipe_buffer *) b;
72 }
73
74
75 static const char *
76 get_name(struct pipe_winsys *pws)
77 {
78 return "software";
79 }
80
81
82 /** Create new pipe_buffer and allocate storage of given size */
83 static struct pipe_buffer *
84 buffer_create(struct pipe_winsys *pws,
85 unsigned alignment,
86 unsigned usage,
87 unsigned size)
88 {
89 struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
90 if (!buffer)
91 return NULL;
92
93 pipe_reference_init(&buffer->Base.reference, 1);
94 buffer->Base.alignment = alignment;
95 buffer->Base.usage = usage;
96 buffer->Base.size = size;
97
98 /* align to 16-byte multiple for Cell */
99 buffer->Data = align_malloc(size, MAX2(alignment, 16));
100
101 return &buffer->Base;
102 }
103
104
105 /**
106 * Create buffer which wraps user-space data.
107 */
108 static struct pipe_buffer *
109 user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes)
110 {
111 struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer);
112 if (!buffer)
113 return NULL;
114
115 pipe_reference_init(&buffer->Base.reference, 1);
116 buffer->Base.size = bytes;
117 buffer->UserBuffer = TRUE;
118 buffer->Data = ptr;
119
120 return &buffer->Base;
121 }
122
123
124 static void *
125 buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags)
126 {
127 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
128 buffer->Mapped = buffer->Data;
129 return buffer->Mapped;
130 }
131
132
133 static void
134 buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf)
135 {
136 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
137 buffer->Mapped = NULL;
138 }
139
140
141 static void
142 buffer_destroy(struct pipe_buffer *buf)
143 {
144 struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf);
145
146 if (buffer->Data && !buffer->UserBuffer) {
147 align_free(buffer->Data);
148 buffer->Data = NULL;
149 }
150
151 free(buffer);
152 }
153
154
155 static struct pipe_buffer *
156 surface_buffer_create(struct pipe_winsys *winsys,
157 unsigned width, unsigned height,
158 enum pipe_format format,
159 unsigned usage,
160 unsigned tex_usage,
161 unsigned *stride)
162 {
163 const unsigned alignment = 64;
164 unsigned nblocksy;
165
166 nblocksy = util_format_get_nblocksy(format, height);
167 *stride = align(util_format_get_stride(format, width), alignment);
168
169 return winsys->buffer_create(winsys, alignment,
170 usage,
171 *stride * nblocksy);
172 }
173
174
175 static void
176 fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr,
177 struct pipe_fence_handle *fence)
178 {
179 /* no-op */
180 }
181
182
183 static int
184 fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
185 unsigned flag)
186 {
187 /* no-op */
188 return 0;
189 }
190
191
192 static int
193 fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence,
194 unsigned flag)
195 {
196 /* no-op */
197 return 0;
198 }
199
200
201 /**
202 * Create/return a new pipe_winsys object.
203 */
204 struct pipe_winsys *
205 create_sw_winsys(void)
206 {
207 struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys);
208 if (!ws)
209 return NULL;
210
211 /* Fill in this struct with callbacks that pipe will need to
212 * communicate with the window system, buffer manager, etc.
213 */
214 ws->Base.buffer_create = buffer_create;
215 ws->Base.user_buffer_create = user_buffer_create;
216 ws->Base.buffer_map = buffer_map;
217 ws->Base.buffer_unmap = buffer_unmap;
218 ws->Base.buffer_destroy = buffer_destroy;
219
220 ws->Base.surface_buffer_create = surface_buffer_create;
221
222 ws->Base.fence_reference = fence_reference;
223 ws->Base.fence_signalled = fence_signalled;
224 ws->Base.fence_finish = fence_finish;
225
226 ws->Base.flush_frontbuffer = NULL; /* not implemented here! */
227
228 ws->Base.get_name = get_name;
229
230 return &ws->Base;
231 }