1 /*
2    (c) Copyright 2001-2010  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/mem.h>
35 
36 #include <core/surface_pool.h>
37 
38 #include <gfx/convert.h>
39 
40 #include "fbdev.h"
41 #include "surfacemanager.h"
42 
43 extern FBDev *dfb_fbdev;
44 
45 D_DEBUG_DOMAIN( FBDev_Surfaces, "FBDev/Surfaces", "FBDev Framebuffer Surface Pool" );
46 D_DEBUG_DOMAIN( FBDev_SurfLock, "FBDev/SurfLock", "FBDev Framebuffer Surface Pool Locks" );
47 
48 /**********************************************************************************************************************/
49 
50 typedef struct {
51      int             magic;
52 
53      SurfaceManager *manager;
54 } FBDevPoolData;
55 
56 typedef struct {
57      int             magic;
58 
59      CoreDFB        *core;
60 } FBDevPoolLocalData;
61 
62 typedef struct {
63      int    magic;
64 
65      Chunk *chunk;
66 } FBDevAllocationData;
67 
68 /**********************************************************************************************************************/
69 
70 static int
fbdevPoolDataSize(void)71 fbdevPoolDataSize( void )
72 {
73      return sizeof(FBDevPoolData);
74 }
75 
76 static int
fbdevPoolLocalDataSize(void)77 fbdevPoolLocalDataSize( void )
78 {
79      return sizeof(FBDevPoolLocalData);
80 }
81 
82 static int
fbdevAllocationDataSize(void)83 fbdevAllocationDataSize( void )
84 {
85      return sizeof(FBDevAllocationData);
86 }
87 
88 static DFBResult
fbdevInitPool(CoreDFB * core,CoreSurfacePool * pool,void * pool_data,void * pool_local,void * system_data,CoreSurfacePoolDescription * ret_desc)89 fbdevInitPool( CoreDFB                    *core,
90                CoreSurfacePool            *pool,
91                void                       *pool_data,
92                void                       *pool_local,
93                void                       *system_data,
94                CoreSurfacePoolDescription *ret_desc )
95 {
96      DFBResult           ret;
97      FBDevPoolData      *data  = pool_data;
98      FBDevPoolLocalData *local = pool_local;
99 
100      D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
101 
102      D_ASSERT( core != NULL );
103      D_MAGIC_ASSERT( pool, CoreSurfacePool );
104      D_ASSERT( data != NULL );
105      D_ASSERT( local != NULL );
106      D_ASSERT( ret_desc != NULL );
107 
108      ret = dfb_surfacemanager_create( core, dfb_fbdev->shared->fix.smem_len, &data->manager );
109      if (ret)
110           return ret;
111 
112      ret_desc->caps              = CSPCAPS_PHYSICAL | CSPCAPS_VIRTUAL;
113      ret_desc->access[CSAID_CPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;
114      ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE | CSAF_SHARED;
115      ret_desc->types             = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;
116      ret_desc->priority          = CSPP_DEFAULT;
117 
118      /* For hardware layers */
119      ret_desc->access[CSAID_LAYER0] = CSAF_READ;
120      ret_desc->access[CSAID_LAYER1] = CSAF_READ;
121      ret_desc->access[CSAID_LAYER2] = CSAF_READ;
122      ret_desc->access[CSAID_LAYER3] = CSAF_READ;
123      ret_desc->access[CSAID_LAYER4] = CSAF_READ;
124      ret_desc->access[CSAID_LAYER5] = CSAF_READ;
125      ret_desc->access[CSAID_LAYER6] = CSAF_READ;
126      ret_desc->access[CSAID_LAYER7] = CSAF_READ;
127      ret_desc->access[CSAID_LAYER8] = CSAF_READ;
128      ret_desc->access[CSAID_LAYER9] = CSAF_READ;
129      ret_desc->access[CSAID_LAYER10] = CSAF_READ;
130      ret_desc->access[CSAID_LAYER11] = CSAF_READ;
131      ret_desc->access[CSAID_LAYER12] = CSAF_READ;
132      ret_desc->access[CSAID_LAYER13] = CSAF_READ;
133      ret_desc->access[CSAID_LAYER14] = CSAF_READ;
134      ret_desc->access[CSAID_LAYER15] = CSAF_READ;
135 
136      snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "Frame Buffer Memory" );
137 
138      local->core = core;
139 
140      D_MAGIC_SET( data, FBDevPoolData );
141      D_MAGIC_SET( local, FBDevPoolLocalData );
142 
143 
144      D_ASSERT( dfb_fbdev != NULL );
145      D_ASSERT( dfb_fbdev->shared != NULL );
146 
147      dfb_fbdev->shared->manager = data->manager;
148 
149      return DFB_OK;
150 }
151 
152 static DFBResult
fbdevJoinPool(CoreDFB * core,CoreSurfacePool * pool,void * pool_data,void * pool_local,void * system_data)153 fbdevJoinPool( CoreDFB                    *core,
154                CoreSurfacePool            *pool,
155                void                       *pool_data,
156                void                       *pool_local,
157                void                       *system_data )
158 {
159      FBDevPoolData      *data  = pool_data;
160      FBDevPoolLocalData *local = pool_local;
161 
162      D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
163 
164      D_ASSERT( core != NULL );
165      D_MAGIC_ASSERT( pool, CoreSurfacePool );
166      D_MAGIC_ASSERT( data, FBDevPoolData );
167      D_ASSERT( local != NULL );
168 
169      (void) data;
170 
171      local->core = core;
172 
173      D_MAGIC_SET( local, FBDevPoolLocalData );
174 
175      return DFB_OK;
176 }
177 
178 static DFBResult
fbdevDestroyPool(CoreSurfacePool * pool,void * pool_data,void * pool_local)179 fbdevDestroyPool( CoreSurfacePool *pool,
180                   void            *pool_data,
181                   void            *pool_local )
182 {
183      FBDevPoolData      *data  = pool_data;
184      FBDevPoolLocalData *local = pool_local;
185 
186      D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
187 
188      D_MAGIC_ASSERT( pool, CoreSurfacePool );
189      D_MAGIC_ASSERT( data, FBDevPoolData );
190      D_MAGIC_ASSERT( local, FBDevPoolLocalData );
191 
192      dfb_surfacemanager_destroy( data->manager );
193 
194      D_MAGIC_CLEAR( data );
195      D_MAGIC_CLEAR( local );
196 
197      return DFB_OK;
198 }
199 
200 static DFBResult
fbdevLeavePool(CoreSurfacePool * pool,void * pool_data,void * pool_local)201 fbdevLeavePool( CoreSurfacePool *pool,
202                 void            *pool_data,
203                 void            *pool_local )
204 {
205      FBDevPoolData      *data  = pool_data;
206      FBDevPoolLocalData *local = pool_local;
207 
208      D_DEBUG_AT( FBDev_Surfaces, "%s()\n", __FUNCTION__ );
209 
210      D_MAGIC_ASSERT( pool, CoreSurfacePool );
211      D_MAGIC_ASSERT( data, FBDevPoolData );
212      D_MAGIC_ASSERT( local, FBDevPoolLocalData );
213 
214      (void) data;
215 
216      D_MAGIC_CLEAR( local );
217 
218      return DFB_OK;
219 }
220 
221 static DFBResult
fbdevTestConfig(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,const CoreSurfaceConfig * config)222 fbdevTestConfig( CoreSurfacePool         *pool,
223                  void                    *pool_data,
224                  void                    *pool_local,
225                  CoreSurfaceBuffer       *buffer,
226                  const CoreSurfaceConfig *config )
227 {
228      DFBResult           ret;
229      CoreSurface        *surface;
230      FBDevPoolData      *data  = pool_data;
231      FBDevPoolLocalData *local = pool_local;
232 
233      D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
234 
235      D_MAGIC_ASSERT( pool, CoreSurfacePool );
236      D_MAGIC_ASSERT( data, FBDevPoolData );
237      D_MAGIC_ASSERT( local, FBDevPoolLocalData );
238      D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
239 
240      surface = buffer->surface;
241      D_MAGIC_ASSERT( surface, CoreSurface );
242 
243      if ((surface->type & CSTF_LAYER) && surface->resource_id == DLID_PRIMARY)
244           return DFB_OK;
245 
246      ret = dfb_surfacemanager_allocate( local->core, data->manager, buffer, NULL, NULL );
247 
248      D_DEBUG_AT( FBDev_Surfaces, "  -> %s\n", DirectFBErrorString(ret) );
249 
250      return ret;
251 }
252 
253 static DFBResult
fbdevAllocateBuffer(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,CoreSurfaceAllocation * allocation,void * alloc_data)254 fbdevAllocateBuffer( CoreSurfacePool       *pool,
255                      void                  *pool_data,
256                      void                  *pool_local,
257                      CoreSurfaceBuffer     *buffer,
258                      CoreSurfaceAllocation *allocation,
259                      void                  *alloc_data )
260 {
261      DFBResult            ret;
262      CoreSurface         *surface;
263      FBDevPoolData       *data  = pool_data;
264      FBDevPoolLocalData  *local = pool_local;
265      FBDevAllocationData *alloc = alloc_data;
266 
267      D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
268 
269      D_MAGIC_ASSERT( pool, CoreSurfacePool );
270      D_MAGIC_ASSERT( data, FBDevPoolData );
271      D_MAGIC_ASSERT( local, FBDevPoolLocalData );
272      D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
273 
274      surface = buffer->surface;
275      D_MAGIC_ASSERT( surface, CoreSurface );
276 
277      if (surface->type & CSTF_LAYER && surface->resource_id == DLID_PRIMARY) {
278           D_DEBUG_AT( FBDev_Surfaces, "  -> primary layer buffer (index %d)\n", dfb_surface_buffer_index( buffer ) );
279 
280           dfb_surface_calc_buffer_size( surface, 8, 1, NULL, &allocation->size );
281      }
282      else {
283           ret = dfb_surfacemanager_allocate( local->core, data->manager, buffer, allocation, &alloc->chunk );
284           if (ret)
285                return ret;
286 
287           D_MAGIC_ASSERT( alloc->chunk, Chunk );
288 
289           allocation->offset = alloc->chunk->offset;
290           allocation->size   = alloc->chunk->length;
291      }
292 
293      D_MAGIC_SET( alloc, FBDevAllocationData );
294 
295      return DFB_OK;
296 }
297 
298 static DFBResult
fbdevDeallocateBuffer(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer,CoreSurfaceAllocation * allocation,void * alloc_data)299 fbdevDeallocateBuffer( CoreSurfacePool       *pool,
300                        void                  *pool_data,
301                        void                  *pool_local,
302                        CoreSurfaceBuffer     *buffer,
303                        CoreSurfaceAllocation *allocation,
304                        void                  *alloc_data )
305 {
306      FBDevPoolData       *data  = pool_data;
307      FBDevAllocationData *alloc = alloc_data;
308 
309      D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
310 
311      D_MAGIC_ASSERT( pool, CoreSurfacePool );
312      D_MAGIC_ASSERT( data, FBDevPoolData );
313      D_MAGIC_ASSERT( alloc, FBDevAllocationData );
314 
315      if (alloc->chunk)
316           dfb_surfacemanager_deallocate( data->manager, alloc->chunk );
317 
318      D_MAGIC_CLEAR( alloc );
319 
320      return DFB_OK;
321 }
322 
323 static DFBResult
fbdevMuckOut(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceBuffer * buffer)324 fbdevMuckOut( CoreSurfacePool   *pool,
325               void              *pool_data,
326               void              *pool_local,
327               CoreSurfaceBuffer *buffer )
328 {
329      FBDevPoolData      *data  = pool_data;
330      FBDevPoolLocalData *local = pool_local;
331 
332      D_DEBUG_AT( FBDev_Surfaces, "%s( %p )\n", __FUNCTION__, buffer );
333 
334      D_MAGIC_ASSERT( pool, CoreSurfacePool );
335      D_MAGIC_ASSERT( data, FBDevPoolData );
336      D_MAGIC_ASSERT( local, FBDevPoolLocalData );
337      D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
338 
339      return dfb_surfacemanager_displace( local->core, data->manager, buffer );
340 }
341 
342 static DFBResult
fbdevLock(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceAllocation * allocation,void * alloc_data,CoreSurfaceBufferLock * lock)343 fbdevLock( CoreSurfacePool       *pool,
344            void                  *pool_data,
345            void                  *pool_local,
346            CoreSurfaceAllocation *allocation,
347            void                  *alloc_data,
348            CoreSurfaceBufferLock *lock )
349 {
350      FBDevAllocationData *alloc  = alloc_data;
351      FBDevShared         *shared = dfb_fbdev->shared;
352 
353      D_MAGIC_ASSERT( pool, CoreSurfacePool );
354      D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
355      D_MAGIC_ASSERT( alloc, FBDevAllocationData );
356      D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
357 
358      D_DEBUG_AT( FBDev_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer );
359 
360      if (allocation->type & CSTF_LAYER && allocation->resource_id == DLID_PRIMARY) {
361           int index  = dfb_surface_buffer_index( allocation->buffer );
362 
363           D_DEBUG_AT( FBDev_Surfaces, "  -> primary layer buffer (index %d)\n", index );
364 
365           lock->pitch  = shared->fix.line_length;
366           lock->offset = index * allocation->config.size.h * lock->pitch;
367 #if D_DEBUG_ENABLED
368           allocation->offset = lock->offset;
369 #endif
370      }
371      else {
372           D_MAGIC_ASSERT( alloc->chunk, Chunk );
373 
374           lock->pitch  = alloc->chunk->pitch;
375           lock->offset = alloc->chunk->offset;
376      }
377 
378      lock->addr = dfb_fbdev->framebuffer_base + lock->offset;
379      lock->phys = dfb_fbdev->shared->fix.smem_start + lock->offset;
380 
381      D_DEBUG_AT( FBDev_SurfLock, "  -> offset %lu, pitch %d, addr %p, phys 0x%08lx\n",
382                  lock->offset, lock->pitch, lock->addr, lock->phys );
383 
384      return DFB_OK;
385 }
386 
387 static DFBResult
fbdevUnlock(CoreSurfacePool * pool,void * pool_data,void * pool_local,CoreSurfaceAllocation * allocation,void * alloc_data,CoreSurfaceBufferLock * lock)388 fbdevUnlock( CoreSurfacePool       *pool,
389              void                  *pool_data,
390              void                  *pool_local,
391              CoreSurfaceAllocation *allocation,
392              void                  *alloc_data,
393              CoreSurfaceBufferLock *lock )
394 {
395      FBDevAllocationData *alloc = alloc_data;
396 
397      D_MAGIC_ASSERT( pool, CoreSurfacePool );
398      D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
399      D_MAGIC_ASSERT( alloc, FBDevAllocationData );
400      D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
401 
402      D_DEBUG_AT( FBDev_SurfLock, "%s( %p )\n", __FUNCTION__, lock->buffer );
403 
404      (void) alloc;
405 
406      return DFB_OK;
407 }
408 
409 const SurfacePoolFuncs fbdevSurfacePoolFuncs = {
410      .PoolDataSize       = fbdevPoolDataSize,
411      .PoolLocalDataSize  = fbdevPoolLocalDataSize,
412      .AllocationDataSize = fbdevAllocationDataSize,
413 
414      .InitPool           = fbdevInitPool,
415      .JoinPool           = fbdevJoinPool,
416      .DestroyPool        = fbdevDestroyPool,
417      .LeavePool          = fbdevLeavePool,
418 
419      .TestConfig         = fbdevTestConfig,
420      .AllocateBuffer     = fbdevAllocateBuffer,
421      .DeallocateBuffer   = fbdevDeallocateBuffer,
422 
423      .MuckOut            = fbdevMuckOut,
424 
425      .Lock               = fbdevLock,
426      .Unlock             = fbdevUnlock,
427 };
428 
429