aboutsummaryrefslogtreecommitdiff
path: root/lib/gdi/accel.cpp
blob: fc739e92b917e3058b4bbb3f360a94a8b7723b66 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#include <cstring>
#include <lib/base/init.h>
#include <lib/base/init_num.h>
#include <lib/gdi/accel.h>
#include <lib/base/eerror.h>
#include <lib/gdi/esize.h>
#include <lib/gdi/epoint.h>
#include <lib/gdi/erect.h>
#include <lib/gdi/gpixmap.h>

gAccel *gAccel::instance;
#define BCM_ACCEL

#ifdef ATI_ACCEL
extern int ati_accel_init(void);
extern void ati_accel_close(void);
extern void ati_accel_blit(
		int src_addr, int src_width, int src_height, int src_stride,
		int dst_addr, int dst_width, int dst_height, int dst_stride,
		int src_x, int src_y, int width, int height,
		int dst_x, int dst_y);
extern void ati_accel_fill(
		int dst_addr, int dst_width, int dst_height, int dst_stride,
		int x, int y, int width, int height,
		unsigned long color);
#endif
#ifdef BCM_ACCEL
extern int bcm_accel_init(void);
extern void bcm_accel_close(void);
extern void bcm_accel_blit(
		int src_addr, int src_width, int src_height, int src_stride, int src_format,
		int dst_addr, int dst_width, int dst_height, int dst_stride,
		int src_x, int src_y, int width, int height,
		int dst_x, int dst_y, int dwidth, int dheight,
		int pal_addr, int flags);
extern void bcm_accel_fill(
		int dst_addr, int dst_width, int dst_height, int dst_stride,
		int x, int y, int width, int height,
		unsigned long color);
#endif

gAccel::gAccel()
{
	m_accel_addr = 0;
	m_accel_phys_addr = 0;
	m_accel_size = 0;
	m_accel_allocation = 0;
	instance = this;

#ifdef ATI_ACCEL	
	ati_accel_init();
#endif
#ifdef BCM_ACCEL	
	m_bcm_accel_state = bcm_accel_init();
#endif
}

gAccel::~gAccel()
{
#ifdef ATI_ACCEL
	ati_accel_close();
#endif
#ifdef BCM_ACCEL
	bcm_accel_close();
#endif
	instance = 0;
}

gAccel *gAccel::getInstance()
{
	return instance;
}
 
void gAccel::setAccelMemorySpace(void *addr, int phys_addr, int size)
{
	if (m_accel_allocation)
		delete[] m_accel_allocation;
	
	m_accel_size = size >> 12;
	
	m_accel_allocation = new int[m_accel_size];
	memset(m_accel_allocation, 0, sizeof(int)*m_accel_size);
	
	m_accel_addr = addr;
	m_accel_phys_addr = phys_addr;
}

int gAccel::blit(gSurface *dst, const gSurface *src, const eRect &p, const eRect &area, int flags)
{
#ifdef ATI_ACCEL
	ati_accel_blit(
		src->data_phys, src->x, src->y, src->stride,
		dst->data_phys, dst->x, dst->y, dst->stride, 
		area.left(), area.top(), area.width(), area.height(),
		p.x(), p.y());
	return 0;
#endif
#ifdef BCM_ACCEL
	if (!m_bcm_accel_state)
	{
		if (flags & (gPixmap::blitAlphaTest|gPixmap::blitAlphaBlend)) /* unsupported flags */
			return -1;
		unsigned long pal_addr = 0;
		int src_format = 0;
		if (src->bpp == 32)
			src_format = 0;
		else if ((src->bpp == 8) && src->clut.data)
		{
			src_format = 1;
			/* sync pal */
			int i;
			pal_addr = src->stride * src->y;
			unsigned long *pal = (unsigned long*)(((unsigned char*)src->data) + pal_addr);
			pal_addr += src->data_phys;
			for (i = 0; i < src->clut.colors; ++i)
				*pal++ = src->clut.data[i].argb() ^ 0xFF000000;
		} else
			return -1; /* unsupported source format */

		bcm_accel_blit(
			src->data_phys, src->x, src->y, src->stride, src_format,
			dst->data_phys, dst->x, dst->y, dst->stride, 
			area.left(), area.top(), area.width(), area.height(),
			p.x(), p.y(), p.width(), p.height(),
			pal_addr, flags);
		return 0;
	}
#endif
	return -1;
}

int gAccel::fill(gSurface *dst, const eRect &area, unsigned long col)
{
#ifdef ATI_ACCEL
	ati_accel_fill(
		dst->data_phys, dst->x, dst->y, dst->stride, 
		area.left(), area.top(), area.width(), area.height(),
		col);
	return 0;
#endif
#if 0 // def BCM_ACCEL
	bcm_accel_fill(
		dst->data_phys, dst->x, dst->y, dst->stride, 
		area.left(), area.top(), area.width(), area.height(),
		col);
	return 0;
#endif
	return -1;
}

int gAccel::accelAlloc(void *&addr, int &phys_addr, int size)
{
	eDebug("accel %d bytes", size);
	if ((!size) || (!m_accel_allocation))
	{
		eDebug("size: %d, alloc %p", size, m_accel_allocation);
		addr = 0;
		phys_addr = 0;
		return -1;
	}
	
	size += 4095; size >>= 12;
	int i;
	
	int used = 0, free = 0, s = 0;
	for (i=0; i < m_accel_size; ++i)
	{
		if (m_accel_allocation[i] == 0)
			free++;
		else if (m_accel_allocation[i] == -1)
			used++;
		else
		{
			used++;
			s += m_accel_allocation[i];
		}
	}
	eDebug("accel memstat: used=%d kB, free %d kB, s %d kB", used * 4, free * 4, s * 4);

	for (i=0; i < m_accel_size - size; ++i)
	{
		int a;
		for (a=0; a<size; ++a)
			if (m_accel_allocation[i+a])
				break;
		if (a == size)
		{
			m_accel_allocation[i] = size;
			for (a=1; a<size; ++a)
				m_accel_allocation[i+a] = -1;
			addr = ((unsigned char*)m_accel_addr) + (i << 12);
			phys_addr = m_accel_phys_addr + (i << 12);
			return 0;
		}
	}
	eDebug("accel alloc failed\n");
	return -1;
}

void gAccel::accelFree(int phys_addr)
{
	phys_addr -= m_accel_phys_addr;
	phys_addr >>= 12;
	
	int size = m_accel_allocation[phys_addr];
	
	ASSERT(size > 0);
	
	while (size--)
		m_accel_allocation[phys_addr++] = 0;
}

eAutoInitP0<gAccel> init_gAccel(eAutoInitNumbers::graphic-2, "graphics acceleration manager");