fixes bug #582
[enigma2.git] / lib / gdi / accel.cpp
1 #include <cstring>
2 #include <lib/base/init.h>
3 #include <lib/base/init_num.h>
4 #include <lib/gdi/accel.h>
5 #include <lib/base/eerror.h>
6 #include <lib/gdi/esize.h>
7 #include <lib/gdi/epoint.h>
8 #include <lib/gdi/erect.h>
9 #include <lib/gdi/gpixmap.h>
10
11 gAccel *gAccel::instance;
12 #define BCM_ACCEL
13
14 #ifdef ATI_ACCEL
15 extern int ati_accel_init(void);
16 extern void ati_accel_close(void);
17 extern void ati_accel_blit(
18                 int src_addr, int src_width, int src_height, int src_stride,
19                 int dst_addr, int dst_width, int dst_height, int dst_stride,
20                 int src_x, int src_y, int width, int height,
21                 int dst_x, int dst_y);
22 extern void ati_accel_fill(
23                 int dst_addr, int dst_width, int dst_height, int dst_stride,
24                 int x, int y, int width, int height,
25                 unsigned long color);
26 #endif
27 #ifdef BCM_ACCEL
28 extern int bcm_accel_init(void);
29 extern void bcm_accel_close(void);
30 extern void bcm_accel_blit(
31                 int src_addr, int src_width, int src_height, int src_stride, int src_format,
32                 int dst_addr, int dst_width, int dst_height, int dst_stride,
33                 int src_x, int src_y, int width, int height,
34                 int dst_x, int dst_y, int dwidth, int dheight,
35                 int pal_addr, int flags);
36 extern void bcm_accel_fill(
37                 int dst_addr, int dst_width, int dst_height, int dst_stride,
38                 int x, int y, int width, int height,
39                 unsigned long color);
40 #endif
41
42 gAccel::gAccel()
43 {
44         m_accel_addr = 0;
45         m_accel_phys_addr = 0;
46         m_accel_size = 0;
47         m_accel_allocation = 0;
48         instance = this;
49
50 #ifdef ATI_ACCEL        
51         ati_accel_init();
52 #endif
53 #ifdef BCM_ACCEL        
54         m_bcm_accel_state = bcm_accel_init();
55 #endif
56 }
57
58 gAccel::~gAccel()
59 {
60 #ifdef ATI_ACCEL
61         ati_accel_close();
62 #endif
63 #ifdef BCM_ACCEL
64         bcm_accel_close();
65 #endif
66         instance = 0;
67 }
68
69 gAccel *gAccel::getInstance()
70 {
71         return instance;
72 }
73  
74 void gAccel::setAccelMemorySpace(void *addr, int phys_addr, int size)
75 {
76         if (m_accel_allocation)
77                 delete[] m_accel_allocation;
78         
79         m_accel_size = size >> 12;
80         
81         m_accel_allocation = new int[m_accel_size];
82         memset(m_accel_allocation, 0, sizeof(int)*m_accel_size);
83         
84         m_accel_addr = addr;
85         m_accel_phys_addr = phys_addr;
86 }
87
88 int gAccel::blit(gSurface *dst, const gSurface *src, const eRect &p, const eRect &area, int flags)
89 {
90 #ifdef ATI_ACCEL
91         ati_accel_blit(
92                 src->data_phys, src->x, src->y, src->stride,
93                 dst->data_phys, dst->x, dst->y, dst->stride, 
94                 area.left(), area.top(), area.width(), area.height(),
95                 p.x(), p.y());
96         return 0;
97 #endif
98 #ifdef BCM_ACCEL
99         if (!m_bcm_accel_state)
100         {
101                 if (flags & (gPixmap::blitAlphaTest|gPixmap::blitAlphaBlend)) /* unsupported flags */
102                         return -1;
103                 unsigned long pal_addr = 0;
104                 int src_format = 0;
105                 if (src->bpp == 32)
106                         src_format = 0;
107                 else if ((src->bpp == 8) && src->clut.data)
108                 {
109                         src_format = 1;
110                         /* sync pal */
111                         int i;
112                         pal_addr = src->stride * src->y;
113                         unsigned long *pal = (unsigned long*)(((unsigned char*)src->data) + pal_addr);
114                         pal_addr += src->data_phys;
115                         for (i = 0; i < 256; ++i)
116                                 *pal++ = src->clut.data[i].argb() ^ 0xFF000000;
117                 } else
118                         return -1; /* unsupported source format */
119
120                 bcm_accel_blit(
121                         src->data_phys, src->x, src->y, src->stride, src_format,
122                         dst->data_phys, dst->x, dst->y, dst->stride, 
123                         area.left(), area.top(), area.width(), area.height(),
124                         p.x(), p.y(), p.width(), p.height(),
125                         pal_addr, flags);
126                 return 0;
127         }
128 #endif
129         return -1;
130 }
131
132 int gAccel::fill(gSurface *dst, const eRect &area, unsigned long col)
133 {
134 #ifdef ATI_ACCEL
135         ati_accel_fill(
136                 dst->data_phys, dst->x, dst->y, dst->stride, 
137                 area.left(), area.top(), area.width(), area.height(),
138                 col);
139         return 0;
140 #endif
141 #if 0 // def BCM_ACCEL
142         bcm_accel_fill(
143                 dst->data_phys, dst->x, dst->y, dst->stride, 
144                 area.left(), area.top(), area.width(), area.height(),
145                 col);
146         return 0;
147 #endif
148         return -1;
149 }
150
151 int gAccel::accelAlloc(void *&addr, int &phys_addr, int size)
152 {
153         eDebug("accel %d bytes", size);
154         if ((!size) || (!m_accel_allocation))
155         {
156                 eDebug("size: %d, alloc %p", size, m_accel_allocation);
157                 addr = 0;
158                 phys_addr = 0;
159                 return -1;
160         }
161         
162         size += 4095; size >>= 12;
163         int i;
164         
165         int used = 0, free = 0, s = 0;
166         for (i=0; i < m_accel_size; ++i)
167         {
168                 if (m_accel_allocation[i] == 0)
169                         free++;
170                 else if (m_accel_allocation[i] == -1)
171                         used++;
172                 else
173                 {
174                         used++;
175                         s += m_accel_allocation[i];
176                 }
177         }
178         eDebug("accel memstat: used=%d kB, free %d kB, s %d kB", used * 4, free * 4, s * 4);
179
180         for (i=0; i < m_accel_size - size; ++i)
181         {
182                 int a;
183                 for (a=0; a<size; ++a)
184                         if (m_accel_allocation[i+a])
185                                 break;
186                 if (a == size)
187                 {
188                         m_accel_allocation[i] = size;
189                         for (a=1; a<size; ++a)
190                                 m_accel_allocation[i+a] = -1;
191                         addr = ((unsigned char*)m_accel_addr) + (i << 12);
192                         phys_addr = m_accel_phys_addr + (i << 12);
193                         return 0;
194                 }
195         }
196         eDebug("accel alloc failed\n");
197         return -1;
198 }
199
200 void gAccel::accelFree(int phys_addr)
201 {
202         phys_addr -= m_accel_phys_addr;
203         phys_addr >>= 12;
204         
205         int size = m_accel_allocation[phys_addr];
206         
207         ASSERT(size > 0);
208         
209         while (size--)
210                 m_accel_allocation[phys_addr++] = 0;
211 }
212
213 eAutoInitP0<gAccel> init_gAccel(eAutoInitNumbers::graphic-2, "graphics acceleration manager");