1 /*
2 (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
3 (c) Copyright 2000-2004 Convergence (integrated media) GmbH
4
5 All rights reserved.
6
7 Written by Denis Oliver Kropp <dok@directfb.org>,
8 Andreas Hundt <andi@fischlustig.de>,
9 Sven Neumann <neo@directfb.org>,
10 Ville Syrjälä <syrjala@sci.fi> and
11 Claudio Ciccani <klan@users.sf.net>.
12
13 This library is free software; you can redistribute it and/or
14 modify it under the terms of the GNU Lesser General Public
15 License as published by the Free Software Foundation; either
16 version 2 of the License, or (at your option) any later version.
17
18 This library is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public
24 License along with this library; if not, write to the
25 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26 Boston, MA 02111-1307, USA.
27 */
28
29 //#define DIRECT_ENABLE_DEBUG
30
31 #include <config.h>
32
33 #include <direct/debug.h>
34 #include <direct/hash.h>
35 #include <direct/mem.h>
36
37 #include <fusion/shmalloc.h>
38
39 #include <core/surface_pool.h>
40
41 #include "x11.h"
42 #include "x11image.h"
43 #include "x11_surface_pool.h"
44
45 D_DEBUG_DOMAIN( X11_Surfaces, "X11/Surfaces", "X11 System Surface Pool" );
46
47 /**********************************************************************************************************************/
48
49 typedef struct {
50 } x11PoolData;
51
52 typedef struct {
53 pthread_mutex_t lock;
54 DirectHash *hash;
55
56 DFBX11 *x11;
57 } x11PoolLocalData;
58
59 /**********************************************************************************************************************/
60
61 static int
x11PoolDataSize(void)62 x11PoolDataSize( void )
63 {
64 return sizeof(x11PoolData);
65 }
66
67 static int
x11PoolLocalDataSize(void)68 x11PoolLocalDataSize( void )
69 {
70 return sizeof(x11PoolLocalData);
71 }
72
73 static int
x11AllocationDataSize(void)74 x11AllocationDataSize( void )
75 {
76 return sizeof(x11AllocationData);
77 }
78
79 static DFBResult
x11InitPool(CoreDFB * core,CoreSurfacePool * pool,void * pool_data,void * pool_local,void * system_data,CoreSurfacePoolDescription * ret_desc)80 x11InitPool( CoreDFB *core,
81 CoreSurfacePool *pool,
82 void *pool_data,
83 void *pool_local,
84 void *system_data,
85 CoreSurfacePoolDescription *ret_desc )
86 {
87 DFBResult ret;
88 x11PoolLocalData *local = pool_local;
89 DFBX11 *x11 = system_data;
90
91 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
92
93 D_MAGIC_ASSERT( pool, CoreSurfacePool );
94 D_ASSERT( ret_desc != NULL );
95
96 local->x11 = x11;
97
98 ret_desc->caps = CSPCAPS_VIRTUAL;
99 ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;
100 ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;
101 ret_desc->priority = CSPP_DEFAULT;
102
103 /* For showing our X11 window */
104 ret_desc->access[CSAID_LAYER0] = CSAF_READ;
105 ret_desc->access[CSAID_LAYER1] = CSAF_READ;
106 ret_desc->access[CSAID_LAYER2] = CSAF_READ;
107
108 snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "X11 Shm Images" );
109
110 ret = direct_hash_create( 7, &local->hash );
111 if (ret) {
112 D_DERROR( ret, "X11/Surfaces: Could not create local hash table!\n" );
113 return ret;
114 }
115
116 pthread_mutex_init( &local->lock, NULL );
117
118 return DFB_OK;
119 }
120
121 static DFBResult
x11JoinPool(CoreDFB * core,CoreSurfacePool * pool,void * pool_data,void * pool_local,void * system_data)122 x11JoinPool( CoreDFB *core,
123 CoreSurfacePool *pool,
124 void *pool_data,
125 void *pool_local,
126 void *system_data )
127 {
128 DFBResult ret;
129 x11PoolLocalData *local = pool_local;
130 DFBX11 *x11 = system_data;
131
132 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
133
134 D_MAGIC_ASSERT( pool, CoreSurfacePool );
135
136 local->x11 = x11;
137
138 ret = direct_hash_create( 7, &local->hash );
139 if (ret) {
140 D_DERROR( ret, "X11/Surfaces: Could not create local hash table!\n" );
141 return ret;
142 }
143
144 pthread_mutex_init( &local->lock, NULL );
145
146 return DFB_OK;
147 }
148
149 static DFBResult
x11DestroyPool(CoreSurfacePool * pool,void * pool_data,void * pool_local)150 x11DestroyPool( CoreSurfacePool *pool,
151 void *pool_data,
152 void *pool_local )
153 {
154 x11PoolLocalData *local = pool_local;
155
156 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
157
158 D_MAGIC_ASSERT( pool, CoreSurfacePool );
159
160 pthread_mutex_destroy( &local->lock );
161
162 direct_hash_destroy( local->hash );
163
164 return DFB_OK;
165 }
166
167 static DFBResult
x11LeavePool(CoreSurfacePool * pool,void * pool_data,void * pool_local)168 x11LeavePool( CoreSurfacePool *pool,
169 void *pool_data,
170 void *pool_local )
171 {
172 x11PoolLocalData *local = pool_local;
173
174 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
175
176 D_MAGIC_ASSERT( pool, CoreSurfacePool );
177
178 pthread_mutex_destroy( &local->lock );
179
180 direct_hash_destroy( local->hash );
181
182 return DFB_OK;
183 }
184
185 static DFBResult
x11TestConfig(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,const CoreSurfaceConfig * config)186 x11TestConfig( CoreSurfacePool *pool,
187 void *pool_data,
188 void *pool_local,
189 CoreSurfaceBuffer *buffer,
190 const CoreSurfaceConfig *config )
191 {
192 x11PoolLocalData *local = pool_local;
193 DFBX11 *x11 = local->x11;
194 DFBX11Shared *shared = x11->shared;
195
196 /* Provide a fallback only if no virtual physical pool is allocated... */
197 if (!shared->vpsmem_length)
198 return DFB_OK;
199
200 /* Pass NULL image for probing */
201 return x11ImageInit( x11, NULL, config->size.w, config->size.h, config->format );
202 }
203
204 static DFBResult
x11AllocateBuffer(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,CoreSurfaceAllocation * allocation,void * alloc_data)205 x11AllocateBuffer( CoreSurfacePool *pool,
206 void *pool_data,
207 void *pool_local,
208 CoreSurfaceBuffer *buffer,
209 CoreSurfaceAllocation *allocation,
210 void *alloc_data )
211 {
212 CoreSurface *surface;
213 x11AllocationData *alloc = alloc_data;
214 x11PoolLocalData *local = pool_local;
215 DFBX11 *x11 = local->x11;
216
217 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
218
219 D_MAGIC_ASSERT( pool, CoreSurfacePool );
220 D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
221
222 surface = buffer->surface;
223 D_MAGIC_ASSERT( surface, CoreSurface );
224
225 if (x11ImageInit( x11, &alloc->image, surface->config.size.w, surface->config.size.h, surface->config.format ) == DFB_OK) {
226 alloc->real = true;
227 alloc->pitch = alloc->image.pitch;
228
229 allocation->size = surface->config.size.h * alloc->image.pitch;
230 }
231 else
232 dfb_surface_calc_buffer_size( surface, 8, 2, &alloc->pitch, &allocation->size );
233
234 return DFB_OK;
235 }
236
237 static DFBResult
x11DeallocateBuffer(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,CoreSurfaceAllocation * allocation,void * alloc_data)238 x11DeallocateBuffer( CoreSurfacePool *pool,
239 void *pool_data,
240 void *pool_local,
241 CoreSurfaceBuffer *buffer,
242 CoreSurfaceAllocation *allocation,
243 void *alloc_data )
244 {
245 x11AllocationData *alloc = alloc_data;
246 x11PoolLocalData *local = pool_local;
247 DFBX11 *x11 = local->x11;
248 DFBX11Shared *shared = x11->shared;
249
250 D_DEBUG_AT( X11_Surfaces, "%s()\n", __FUNCTION__ );
251
252 D_MAGIC_ASSERT( pool, CoreSurfacePool );
253
254 CORE_SURFACE_ALLOCATION_ASSERT( allocation );
255
256 if (alloc->real)
257 return x11ImageDestroy( x11, &alloc->image );
258
259 if (alloc->ptr)
260 SHFREE( shared->data_shmpool, alloc->ptr );
261
262 return DFB_OK;
263 }
264
265 static DFBResult
x11Lock(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceAllocation * allocation,void * alloc_data,CoreSurfaceBufferLock * lock)266 x11Lock( CoreSurfacePool *pool,
267 void *pool_data,
268 void *pool_local,
269 CoreSurfaceAllocation *allocation,
270 void *alloc_data,
271 CoreSurfaceBufferLock *lock )
272 {
273 DFBResult ret;
274 x11PoolLocalData *local = pool_local;
275 x11AllocationData *alloc = alloc_data;
276 DFBX11 *x11 = local->x11;
277 DFBX11Shared *shared = x11->shared;
278
279 D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
280
281 D_MAGIC_ASSERT( pool, CoreSurfacePool );
282 D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
283 D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
284
285 D_ASSERT( local->hash != NULL );
286
287 pthread_mutex_lock( &local->lock );
288
289 if (alloc->real) {
290 void *addr = direct_hash_lookup( local->hash, alloc->image.seginfo.shmid );
291
292 if (!addr) {
293 ret = x11ImageAttach( &alloc->image, &addr );
294 if (ret) {
295 D_DERROR( ret, "X11/Surfaces: x11ImageAttach() failed!\n" );
296 pthread_mutex_unlock( &local->lock );
297 return ret;
298 }
299
300 direct_hash_insert( local->hash, alloc->image.seginfo.shmid, addr );
301
302 /* FIXME: When to remove/detach? */
303 }
304
305 lock->addr = addr;
306 lock->handle = &alloc->image;
307 }
308 else {
309 if (!alloc->ptr) {
310 alloc->ptr = SHCALLOC( shared->data_shmpool, 1, allocation->size );
311 if (!alloc->ptr) {
312 pthread_mutex_unlock( &local->lock );
313 return D_OOSHM();
314 }
315 }
316
317 lock->addr = alloc->ptr;
318 }
319
320 lock->pitch = alloc->pitch;
321
322 pthread_mutex_unlock( &local->lock );
323
324 return DFB_OK;
325 }
326
327 static DFBResult
x11Unlock(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceAllocation * allocation,void * alloc_data,CoreSurfaceBufferLock * lock)328 x11Unlock( CoreSurfacePool *pool,
329 void *pool_data,
330 void *pool_local,
331 CoreSurfaceAllocation *allocation,
332 void *alloc_data,
333 CoreSurfaceBufferLock *lock )
334 {
335 D_DEBUG_AT( X11_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
336
337 D_MAGIC_ASSERT( pool, CoreSurfacePool );
338 D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
339 D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
340
341 /* FIXME: Check overhead of attach/detach per lock/unlock. */
342
343 return DFB_OK;
344 }
345
346 const SurfacePoolFuncs x11SurfacePoolFuncs = {
347 .PoolDataSize = x11PoolDataSize,
348 .PoolLocalDataSize = x11PoolLocalDataSize,
349 .AllocationDataSize = x11AllocationDataSize,
350
351 .InitPool = x11InitPool,
352 .JoinPool = x11JoinPool,
353 .DestroyPool = x11DestroyPool,
354 .LeavePool = x11LeavePool,
355
356 .TestConfig = x11TestConfig,
357
358 .AllocateBuffer = x11AllocateBuffer,
359 .DeallocateBuffer = x11DeallocateBuffer,
360
361 .Lock = x11Lock,
362 .Unlock = x11Unlock,
363 };
364
365