3bd007820c54e81cb057a13324aeea5c5cd62791
[enigma2.git] / lib / gdi / grc.cpp
1 // for debugging use:
2 // #define SYNC_PAINT
3 #include <unistd.h>
4 #ifndef SYNC_PAINT
5 #include <pthread.h>
6 #endif
7
8 #include <lib/gdi/grc.h>
9 #include <lib/gdi/font.h>
10 #include <lib/base/init.h>
11 #include <lib/base/init_num.h>
12
13 #define MAXSIZE 1024
14
15 #ifndef SYNC_PAINT
16 void *gRC::thread_wrapper(void *ptr)
17 {
18         nice(3);
19         return ((gRC*)ptr)->thread();
20 }
21 #endif
22
23 gRC *gRC::instance=0;
24
25 gRC::gRC(): queuelock(MAXSIZE), queue(2048)
26 {
27         ASSERT(!instance);
28         instance=this;
29         queuelock.lock(MAXSIZE);
30 #ifndef SYNC_PAINT
31         eDebug(pthread_create(&the_thread, 0, thread_wrapper, this)?"RC thread couldn't be created":"RC thread createted successfully");
32 #endif
33 }
34
35 gRC::~gRC()
36 {
37         gOpcode o;
38         o.dc=0;
39         o.opcode=gOpcode::shutdown;
40         submit(o);
41         instance=0;
42 }
43
44 void *gRC::thread()
45 {
46 #ifndef SYNC_PAINT
47         while (1)
48 #else
49         while (queue.size())
50 #endif
51         {
52                 queuelock.lock(1);
53                 gOpcode& o(queue.current());
54                 if (o.opcode==gOpcode::shutdown)
55                         break;
56                 o.dc->exec(&o);
57                 queue.dequeue();
58         }
59 #ifndef SYNC_PAINT
60         pthread_exit(0);
61 #endif
62         return 0;
63 }
64
65 gRC &gRC::getInstance()
66 {
67         return *instance;
68 }
69
70 static int gPainter_instances;
71
72 gPainter::gPainter(gDC &dc, eRect rect): dc(dc), rc(gRC::getInstance()), foregroundColor(0), backgroundColor(0)
73 {
74         if (rect.isNull())
75                 rect=eRect(ePoint(0, 0), dc.getSize());
76 //      ASSERT(!gPainter_instances);
77         gPainter_instances++;
78         begin(rect);
79 }
80
81 gPainter::~gPainter()
82 {
83         end();
84         gPainter_instances--;
85 }
86
87 void gPainter::begin(const eRect &rect)
88 {
89         gOpcode o;
90         dc.lock();
91         o.dc=&dc;
92         o.opcode=gOpcode::begin;
93         o.parm.begin=new gOpcode::para::pbegin(rect);
94 //      cliparea=std::stack<eRect, std::list<eRect> >();
95         cliparea=std::stack<eRect>();
96         cliparea.push(rect);
97         setLogicalZero(cliparea.top().topLeft());
98         rc.submit(o);
99 }
100
101 void gPainter::setBackgroundColor(const gColor &color)
102 {
103         backgroundColor=color;
104 }
105
106 void gPainter::setForegroundColor(const gColor &color)
107 {
108         foregroundColor=color;
109 }
110
111 void gPainter::setFont(const gFont &mfont)
112 {
113         font=mfont;
114 }
115
116 void gPainter::renderText(const eRect &pos, const std::string &string, int flags)
117 {
118         eRect area=pos;
119         area.moveBy(logicalZero.x(), logicalZero.y());
120
121         gOpcode o;
122         o.dc=&dc;
123         o.opcode=gOpcode::renderText;
124         o.parm.renderText=new gOpcode::para::prenderText(font, area, string, dc.getRGB(foregroundColor), dc.getRGB(backgroundColor));
125         o.flags=flags;
126         rc.submit(o);
127 }
128
129 void gPainter::renderPara(eTextPara &para, ePoint offset)
130 {
131         gOpcode o;
132         o.dc=&dc;
133         o.opcode=gOpcode::renderPara;
134         o.parm.renderPara=new gOpcode::para::prenderPara(logicalZero+offset, para.grab(), dc.getRGB(foregroundColor), dc.getRGB(backgroundColor));
135         rc.submit(o);
136 }
137
138 void gPainter::fill(const eRect &area)
139 {
140         gOpcode o;
141         o.dc=&dc;
142         o.opcode=gOpcode::fill;
143         eRect a=area;
144         a.moveBy(logicalZero.x(), logicalZero.y());
145         a&=cliparea.top();
146         
147         o.parm.fill=new gOpcode::para::pfill(a, foregroundColor);
148         rc.submit(o);
149 }
150
151 void gPainter::clear()
152 {
153         gOpcode o;
154         o.dc=&dc;
155         o.opcode=gOpcode::fill;
156         o.parm.fill=new gOpcode::para::pfill(cliparea.top(), backgroundColor);
157         rc.submit(o);
158 }
159
160 void gPainter::setPalette(gRGB *colors, int start, int len)
161 {
162         gOpcode o;
163         o.dc=&dc;
164         o.opcode=gOpcode::setPalette;
165         gPalette *p=new gPalette;
166         
167         p->data=new gRGB[len];
168         memcpy(p->data, colors, len*sizeof(gRGB));
169         p->start=start;
170         p->colors=len;
171         o.parm.setPalette=new gOpcode::para::psetPalette(p);
172         rc.submit(o);
173 }
174
175 void gPainter::mergePalette(gPixmap *target)
176 {
177         gOpcode o;
178         o.dc=&dc;
179         o.opcode=gOpcode::mergePalette;
180         o.parm.mergePalette=new gOpcode::para::pmergePalette(target);
181         rc.submit(o);
182 }
183
184 void gPainter::line(ePoint start, ePoint end)
185 {
186         gOpcode o;
187         o.dc=&dc;
188         o.opcode=gOpcode::line;
189         o.parm.line=new gOpcode::para::pline(start+logicalZero, end+logicalZero, foregroundColor);
190         rc.submit(o);
191 }
192
193 void gPainter::setLogicalZero(ePoint rel)
194 {
195         logicalZero=rel;
196 }
197
198 void gPainter::moveLogicalZero(ePoint rel)
199 {
200         logicalZero+=rel;
201 }
202
203 void gPainter::resetLogicalZero()
204 {
205         logicalZero.setX(0);
206         logicalZero.setY(0);
207 }
208
209 void gPainter::clip(eRect clip)
210 {
211         gOpcode o;
212         o.dc=&dc;
213         o.opcode=gOpcode::clip;
214         clip.moveBy(logicalZero.x(), logicalZero.y());
215         cliparea.push(cliparea.top()&clip);
216         o.parm.clip=new gOpcode::para::pclip(cliparea.top());
217
218         rc.submit(o);
219 }
220
221 void gPainter::clippop()
222 {
223         ASSERT (cliparea.size()>1);
224         gOpcode o;
225         o.dc=&dc;
226         o.opcode=gOpcode::clip;
227         cliparea.pop();
228         o.parm.clip=new gOpcode::para::pclip(cliparea.top());
229         rc.submit(o);
230 }
231
232 void gPainter::flush()
233 {
234         gOpcode o;
235         o.dc=&dc;
236         o.opcode=gOpcode::flush;
237         rc.submit(o);
238 }
239
240 void gPainter::end()
241 {
242         gOpcode o;
243         o.dc=&dc;
244         o.opcode=gOpcode::end;
245         rc.submit(o);
246 }
247
248 gDC::~gDC()
249 {
250 }
251
252 gPixmapDC::gPixmapDC(): pixmap(0)
253 {
254 }
255
256 gPixmapDC::gPixmapDC(gPixmap *pixmap): pixmap(pixmap)
257 {
258 }
259
260 gPixmapDC::~gPixmapDC()
261 {
262         dclock.lock();
263 }
264
265 void gPixmapDC::exec(gOpcode *o)
266 {
267         switch(o->opcode)
268         {
269         case gOpcode::begin:
270                 clip=o->parm.begin->area;
271                 delete o->parm.begin;
272                 break;
273         case gOpcode::renderText:
274         {
275                 eTextPara *para=new eTextPara(o->parm.renderText->area);
276                 para->setFont(o->parm.renderText->font);
277                 para->renderString(o->parm.renderText->text, o->flags);
278                 para->blit(*this, ePoint(0, 0), o->parm.renderText->backgroundColor, o->parm.renderText->foregroundColor);
279                 para->destroy();
280                 delete o->parm.renderText;
281                 break;
282         }
283         case gOpcode::renderPara:
284         {
285                 o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset, o->parm.renderPara->backgroundColor, o->parm.renderPara->foregroundColor);
286                 o->parm.renderPara->textpara->destroy();
287                 delete o->parm.renderPara;
288                 break;
289         }
290         case gOpcode::fill:
291                 pixmap->fill(o->parm.fill->area, o->parm.fill->color);
292                 delete o->parm.fill;
293                 break;
294         case gOpcode::blit:
295         {
296                 if (o->parm.blit->clip.isNull())
297                         o->parm.blit->clip=clip;
298                 else
299                         o->parm.blit->clip&=clip;
300                 pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, o->parm.blit->clip, o->flags);
301                 delete o->parm.blit;
302                 break;
303         }
304         case gOpcode::setPalette:
305                 if (o->parm.setPalette->palette->start>pixmap->clut.colors)
306                         o->parm.setPalette->palette->start=pixmap->clut.colors;
307                 if (o->parm.setPalette->palette->colors>(pixmap->clut.colors-o->parm.setPalette->palette->start))
308                         o->parm.setPalette->palette->colors=pixmap->clut.colors-o->parm.setPalette->palette->start;
309                 if (o->parm.setPalette->palette->colors)
310                         memcpy(pixmap->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB));
311                 delete[] o->parm.setPalette->palette->data;
312                 delete o->parm.setPalette->palette;
313                 delete o->parm.setPalette;
314                 break;
315         case gOpcode::mergePalette:
316                 pixmap->mergePalette(*o->parm.blit->pixmap);
317                 delete o->parm.blit;
318                 break;
319         case gOpcode::line:
320                 pixmap->line(o->parm.line->start, o->parm.line->end, o->parm.line->color);
321                 delete o->parm.line;
322                 break;
323         case gOpcode::clip:
324                 clip=o->parm.clip->clip;
325                 delete o->parm.clip;
326                 break;
327         case gOpcode::end:
328                 unlock();
329         case gOpcode::flush:
330                 break;
331         default:
332                 eFatal("illegal opcode %d. expect memory leak!", o->opcode);
333         }
334 }
335
336 gRGB gPixmapDC::getRGB(gColor col)
337 {
338         if ((!pixmap) || (!pixmap->clut.data))
339                 return gRGB(col, col, col);
340         if (col<0)
341         {
342                 eFatal("bla transp");
343                 return gRGB(0, 0, 0, 0xFF);
344         }
345         return pixmap->clut.data[col];
346 }
347
348 eAutoInitP0<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");