- new GUI lib
[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(): queue(2048), queuelock(MAXSIZE)
26 {
27         ASSERT(!instance);
28         instance=this;
29         queuelock.lock(MAXSIZE);
30 #ifndef SYNC_PAINT
31         int res = pthread_create(&the_thread, 0, thread_wrapper, this);
32         if (res)
33                 eFatal("RC thread couldn't be created");
34         else
35                 eDebug("RC thread createted successfully");
36 #endif
37 }
38
39 DEFINE_REF(gRC);
40
41 gRC::~gRC()
42 {
43         instance=0;
44
45         gOpcode o;
46         o.opcode=gOpcode::shutdown;
47         submit(o);
48 #ifndef SYNC_PAINT
49         eDebug("waiting for gRC thread shutdown");
50         pthread_join(the_thread, 0);
51         eDebug("gRC thread has finished");
52 #endif
53 }
54
55 void *gRC::thread()
56 {
57 #ifndef SYNC_PAINT
58         while (1)
59 #else
60         while (queue.size())
61 #endif
62         {
63                 queuelock.lock(1);
64                 gOpcode& o(queue.current());
65                 if (o.opcode==gOpcode::shutdown)
66                         break;
67                 o.dc->exec(&o);
68                 o.dc->Release();
69                 queue.dequeue();
70         }
71 #ifndef SYNC_PAINT
72         pthread_exit(0);
73 #endif
74         return 0;
75 }
76
77 gRC *gRC::getInstance()
78 {
79         return instance;
80 }
81
82 static int gPainter_instances;
83
84 gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance())
85 {
86 //      ASSERT(!gPainter_instances);
87         gPainter_instances++;
88 //      begin(rect);
89 }
90
91 gPainter::~gPainter()
92 {
93         end();
94         gPainter_instances--;
95 }
96
97 void gPainter::setBackgroundColor(const gColor &color)
98 {
99         gOpcode o;
100         o.opcode = gOpcode::setBackgroundColor;
101         o.dc = m_dc.grabRef();
102         o.parm.setColor = new gOpcode::para::psetColor;
103         o.parm.setColor->color = color;
104         
105         m_rc->submit(o);
106 }
107
108 void gPainter::setForegroundColor(const gColor &color)
109 {
110         gOpcode o;
111         o.opcode = gOpcode::setForegroundColor;
112         o.dc = m_dc.grabRef();
113         o.parm.setColor = new gOpcode::para::psetColor;
114         o.parm.setColor->color = color;
115         
116         m_rc->submit(o);
117 }
118
119 void gPainter::setFont(gFont *font)
120 {
121         gOpcode o;
122         o.opcode = gOpcode::setFont;
123         o.dc = m_dc.grabRef();
124         font->AddRef();
125         o.parm.setFont = new gOpcode::para::psetFont;
126         o.parm.setFont->font = font;
127         
128         m_rc->submit(o);
129 }
130
131 void gPainter::renderText(const eRect &pos, const std::string &string, int flags)
132 {
133         gOpcode o;
134         o.opcode=gOpcode::renderText;
135         o.dc = m_dc.grabRef();
136         o.parm.renderText = new gOpcode::para::prenderText;
137         o.parm.renderText->area = pos;
138         o.parm.renderText->text = string;
139         o.parm.renderText->flags = flags;
140         m_rc->submit(o);
141 }
142
143 void gPainter::renderPara(eTextPara *para, ePoint offset)
144 {
145         gOpcode o;
146         o.opcode=gOpcode::renderPara;
147         o.dc = m_dc.grabRef();
148         o.parm.renderPara = new gOpcode::para::prenderPara;
149         o.parm.renderPara->offset = offset;
150
151         para->AddRef();
152         o.parm.renderPara->textpara = para;
153         m_rc->submit(o);
154 }
155
156 void gPainter::fill(const eRect &area)
157 {
158         gOpcode o;
159         o.opcode=gOpcode::fill;
160
161         o.dc = m_dc.grabRef();
162         o.parm.fill = new gOpcode::para::pfillRect;
163         o.parm.fill->area = area;
164         m_rc->submit(o);
165 }
166
167 void gPainter::clear()
168 {
169         gOpcode o;
170         o.opcode=gOpcode::clear;
171         o.dc = m_dc.grabRef();
172         o.parm.fill = new gOpcode::para::pfillRect;
173         o.parm.fill->area = eRect();
174         m_rc->submit(o);
175 }
176
177 void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags)
178 {
179         gOpcode o;
180
181         o.opcode=gOpcode::blit;
182         o.dc = m_dc.grabRef();
183         pixmap->AddRef();
184         o.parm.blit  = new gOpcode::para::pblit;
185         o.parm.blit->pixmap = pixmap;
186         o.parm.blit->position = pos;
187         o.parm.blit->clip = clip;
188         o.flags=flags;
189         m_rc->submit(o);
190 }
191
192
193 void gPainter::setPalette(gRGB *colors, int start, int len)
194 {
195         gOpcode o;
196         o.opcode=gOpcode::setPalette;
197         o.dc = m_dc.grabRef();
198         gPalette *p=new gPalette;
199         
200         o.parm.setPalette = new gOpcode::para::psetPalette;
201         p->data=new gRGB[len];
202         
203         memcpy(p->data, colors, len*sizeof(gRGB));
204         p->start=start;
205         p->colors=len;
206         o.parm.setPalette->palette = p;
207         m_rc->submit(o);
208 }
209
210 void gPainter::mergePalette(gPixmap *target)
211 {
212         gOpcode o;
213         o.opcode=gOpcode::mergePalette;
214         o.dc = m_dc.grabRef();
215         target->AddRef();
216         o.parm.mergePalette->target = target;
217         m_rc->submit(o);
218 }
219
220 void gPainter::line(ePoint start, ePoint end)
221 {
222         gOpcode o;
223         o.opcode=gOpcode::line;
224         o.dc = m_dc.grabRef();
225         o.parm.line = new gOpcode::para::pline;
226         o.parm.line->start = start;
227         o.parm.line->end = end;
228         m_rc->submit(o);
229 }
230
231 void gPainter::setOffset(ePoint val)
232 {
233         gOpcode o;
234         o.opcode=gOpcode::setOffset;
235         o.dc = m_dc.grabRef();
236         o.parm.setOffset = new gOpcode::para::psetOffset;
237         o.parm.setOffset->rel = 0;
238         o.parm.setOffset->value = val;
239         m_rc->submit(o);
240 }
241
242 void gPainter::moveOffset(ePoint rel)
243 {
244         gOpcode o;
245         o.opcode=gOpcode::setOffset;
246         o.dc = m_dc.grabRef();
247         o.parm.setOffset = new gOpcode::para::psetOffset;
248         o.parm.setOffset->rel = 1;
249         o.parm.setOffset->value = rel;
250         m_rc->submit(o);
251 }
252
253 void gPainter::resetOffset()
254 {
255         gOpcode o;
256         o.opcode=gOpcode::setOffset;
257         o.dc = m_dc.grabRef();
258         o.parm.setOffset = new gOpcode::para::psetOffset;
259         o.parm.setOffset->rel = 0;
260         o.parm.setOffset->value = ePoint(0, 0);
261         m_rc->submit(o);
262 }
263
264 void gPainter::resetClip(const gRegion &region)
265 {
266         gOpcode o;
267         o.opcode = gOpcode::setClip;
268         o.dc = m_dc.grabRef();
269         o.parm.clip = new gOpcode::para::psetClip;
270         o.parm.clip->region = region;
271         m_rc->submit(o);
272 }
273
274 void gPainter::clip(const gRegion &region)
275 {
276         gOpcode o;
277         o.opcode = gOpcode::addClip;
278         o.dc = m_dc.grabRef();
279         o.parm.clip = new gOpcode::para::psetClip;
280         o.parm.clip->region = region;
281         m_rc->submit(o);
282 }
283
284 void gPainter::clippop()
285 {
286         gOpcode o;
287         o.opcode = gOpcode::popClip;
288         o.dc = m_dc.grabRef();
289         m_rc->submit(o);
290 }
291
292 void gPainter::flush()
293 {
294 }
295
296 void gPainter::end()
297 {
298 }
299
300 gDC::gDC()
301 {
302 }
303
304 gDC::gDC(gPixmap *pixmap): m_pixmap(pixmap)
305 {
306 }
307
308 gDC::~gDC()
309 {
310 }
311
312 void gDC::exec(gOpcode *o)
313 {
314         switch (o->opcode)
315         {
316         case gOpcode::setBackgroundColor:
317                 m_background_color = o->parm.setColor->color;
318                 delete o->parm.setColor;
319                 break;
320         case gOpcode::setForegroundColor:
321                 m_foreground_color = o->parm.setColor->color;
322                 delete o->parm.setColor;
323                 break;
324         case gOpcode::setFont:
325                 m_current_font = o->parm.setFont->font;
326                 o->parm.setFont->font->Release();
327                 delete o->parm.setFont;
328                 break;
329         case gOpcode::renderText:
330         {
331                 ePtr<eTextPara> para = new eTextPara(o->parm.renderText->area);
332                 assert(m_current_font);
333                 para->setFont(m_current_font);
334                 para->renderString(o->parm.renderText->text, o->parm.renderText->flags);
335                 para->blit(*this, m_current_offset, getRGB(m_foreground_color), getRGB(m_background_color));
336                 delete o->parm.renderText;
337                 break;
338         }
339         case gOpcode::renderPara:
340         {
341                 o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset + m_current_offset, getRGB(m_foreground_color), getRGB(m_background_color));
342                 o->parm.renderPara->textpara->Release();
343                 delete o->parm.renderPara;
344                 break;
345         }
346         case gOpcode::fill:
347         {
348                 eRect area = o->parm.fill->area;
349                 area.moveBy(m_current_offset);
350                 gRegion clip = m_current_clip & area;
351                 m_pixmap->fill(clip, m_foreground_color);
352                 delete o->parm.fill;
353                 break;
354         }
355         case gOpcode::clear:
356                 m_pixmap->fill(m_current_clip, m_background_color);
357                 delete o->parm.fill;
358                 break;
359         case gOpcode::blit:
360         {
361                 gRegion clip;
362                 if (!o->parm.blit->clip.valid())
363                 {
364                         clip.intersect(gRegion(o->parm.blit->clip), clip);
365                 } else
366                         clip = m_current_clip;
367                 m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, o->parm.blit->flags);
368                 o->parm.blit->pixmap->Release();
369                 delete o->parm.blit;
370                 break;
371         }
372         case gOpcode::setPalette:
373                 if (o->parm.setPalette->palette->start > m_pixmap->surface->clut.colors)
374                         o->parm.setPalette->palette->start = m_pixmap->surface->clut.colors;
375                 if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start))
376                         o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start;
377                 if (o->parm.setPalette->palette->colors)
378                         memcpy(m_pixmap->surface->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB));
379                 
380                 delete[] o->parm.setPalette->palette->data;
381                 delete o->parm.setPalette->palette;
382                 delete o->parm.setPalette;
383                 break;
384         case gOpcode::mergePalette:
385 #if 0
386                 pixmap->mergePalette(*o->parm.blit->pixmap);
387                 o->parm.blit->pixmap->unlock();
388                 delete o->parm.blit;
389 #endif
390                 break;
391         case gOpcode::line:
392         {
393                 ePoint start = o->parm.line->start + m_current_offset, end = o->parm.line->end + m_current_offset;
394                 m_pixmap->line(m_current_clip, start, end, m_foreground_color);
395                 delete o->parm.line;
396                 break;
397         }
398         case gOpcode::addClip:
399                 m_clip_stack.push(m_current_clip);
400                 o->parm.clip->region.moveBy(m_current_offset);
401                 m_current_clip &= o->parm.clip->region;
402                 delete o->parm.clip;
403                 break;
404         case gOpcode::setClip:
405                 o->parm.clip->region.moveBy(m_current_offset);
406                 m_current_clip = o->parm.clip->region & eRect(ePoint(0, 0), m_pixmap->getSize());
407                 delete o->parm.clip;
408                 break;
409         case gOpcode::popClip:
410                 if (!m_clip_stack.empty())
411                 {
412                         m_current_clip = m_clip_stack.top();
413                         m_clip_stack.pop();
414                 }
415                 break;
416         case gOpcode::setOffset:
417                 if (o->parm.setOffset->rel)
418                         m_current_offset += o->parm.setOffset->value;
419                 else
420                         m_current_offset  = o->parm.setOffset->value;
421                 delete o->parm.setOffset;
422                 break;
423         default:
424                 eFatal("illegal opcode %d. expect memory leak!", o->opcode);
425         }
426 }
427
428 gRGB gDC::getRGB(gColor col)
429 {
430         if ((!m_pixmap) || (!m_pixmap->surface->clut.data))
431                 return gRGB(col, col, col);
432         if (col<0)
433         {
434                 eFatal("bla transp");
435                 return gRGB(0, 0, 0, 0xFF);
436         }
437         return m_pixmap->surface->clut.data[col];
438 }
439
440 DEFINE_REF(gDC);
441
442 eAutoInitPtr<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");
443