don't display debug on increment, just on start
[enigma2.git] / lib / gdi / grc.cpp
1 #include <unistd.h>
2 #include <lib/gdi/grc.h>
3 #include <lib/gdi/font.h>
4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6
7 #ifndef SYNC_PAINT
8 void *gRC::thread_wrapper(void *ptr)
9 {
10         return ((gRC*)ptr)->thread();
11 }
12 #endif
13
14 gRC *gRC::instance=0;
15
16 gRC::gRC(): rp(0), wp(0)
17 #ifdef SYNC_PAINT
18 ,m_notify_pump(eApp, 0)
19 #else
20 ,m_notify_pump(eApp, 1)
21 #endif
22 {
23         ASSERT(!instance);
24         instance=this;
25         CONNECT(m_notify_pump.recv_msg, gRC::recv_notify);
26 #ifndef SYNC_PAINT
27         pthread_mutex_init(&mutex, 0);
28         pthread_cond_init(&cond, 0);
29         int res = pthread_create(&the_thread, 0, thread_wrapper, this);
30         if (res)
31                 eFatal("RC thread couldn't be created");
32         else
33                 eDebug("RC thread created successfully");
34 #endif
35         m_spinner_enabled = 0;
36 }
37
38 DEFINE_REF(gRC);
39
40 gRC::~gRC()
41 {
42         instance=0;
43
44         gOpcode o;
45         o.opcode=gOpcode::shutdown;
46         submit(o);
47 #ifndef SYNC_PAINT
48         eDebug("waiting for gRC thread shutdown");
49         pthread_join(the_thread, 0);
50         eDebug("gRC thread has finished");
51 #endif
52 }
53
54 void gRC::submit(const gOpcode &o)
55 {
56         while(1)
57         {
58 #ifndef SYNC_PAINT
59                 pthread_mutex_lock(&mutex);
60 #endif
61                 int tmp=wp+1;
62                 if ( tmp == MAXSIZE )
63                         tmp=0;
64                 if ( tmp == rp )
65                 {
66 #ifndef SYNC_PAINT
67                         pthread_cond_signal(&cond);  // wakeup gdi thread
68                         pthread_mutex_unlock(&mutex);
69 #else
70                         thread();
71 #endif
72                         //printf("render buffer full...\n");
73                         //fflush(stdout);
74                         usleep(1000);  // wait 1 msec
75                         continue;
76                 }
77                 int free=rp-wp;
78                 if ( free <= 0 )
79                         free+=MAXSIZE;
80                 queue[wp++]=o;
81                 if ( wp == MAXSIZE )
82                         wp = 0;
83                 if (o.opcode==gOpcode::flush||o.opcode==gOpcode::shutdown||o.opcode==gOpcode::notify)
84 #ifndef SYNC_PAINT
85                         pthread_cond_signal(&cond);  // wakeup gdi thread
86                 pthread_mutex_unlock(&mutex);
87 #else
88                         thread(); // paint
89 #endif
90                 break;
91         }
92 }
93
94 void *gRC::thread()
95 {
96         int need_notify = 0;
97 #ifndef SYNC_PAINT
98         while (1)
99         {
100 #else
101         while (rp != wp)
102         {
103 #endif
104 #ifndef SYNC_PAINT
105                 pthread_mutex_lock(&mutex);
106 #endif
107                 if ( rp != wp )
108                 {
109                         gOpcode o(queue[rp++]);
110                         if ( rp == MAXSIZE )
111                                 rp=0;
112 #ifndef SYNC_PAINT
113                         pthread_mutex_unlock(&mutex);
114 #endif
115                         if (o.opcode==gOpcode::shutdown)
116                                 break;
117                         else if (o.opcode==gOpcode::notify)
118                                 need_notify = 1;
119                         else
120                         {
121                                 o.dc->exec(&o);
122                                 // o.dc is a gDC* filled with grabref... so we must release it here
123                                 o.dc->Release();
124                         }
125                 }
126                 else
127                 {
128                         if (need_notify)
129                         {
130                                 need_notify = 0;
131                                 m_notify_pump.send(1);
132                         }
133 #ifndef SYNC_PAINT
134                         while(rp == wp)
135                         {
136                         
137                                         /* when the main thread is non-idle for a too long time without any display output,
138                                            we want to display a spinner. */
139
140                                 struct timeval time;
141                                 struct timespec timeout;
142                                 gettimeofday(&time, NULL);
143                                 timeout.tv_sec = time.tv_sec;
144                                 timeout.tv_nsec = time.tv_usec * 1000;
145                                 
146                                 if (m_spinner_enabled)
147                                         timeout.tv_nsec += 100*1000*1000;
148                                 else
149                                         timeout.tv_nsec += 500*1000*1000;
150
151                                         /* yes, this is required. */
152                                 if (timeout.tv_nsec > 1000*1000*1000)
153                                 {
154                                         timeout.tv_nsec -= 1000*1000*1000;
155                                         timeout.tv_sec++;
156                                 }
157
158                                 int idle = 1;
159
160                                 if (pthread_cond_timedwait(&cond, &mutex, &timeout) == ETIMEDOUT)
161                                 {
162                                         if (eApp && !eApp->isIdle())
163                                                 idle = 0;
164                                 }
165                                 
166                                 pthread_mutex_unlock(&mutex);
167
168                                 if (!idle)
169                                 {
170                                         if (!m_spinner_enabled)
171                                                 eDebug("main thread is non-idle! display spinner!");
172                                         enableSpinner();
173                                 } else
174                                         disableSpinner();
175                         }
176 #endif
177                 }
178         }
179 #ifndef SYNC_PAINT
180         pthread_exit(0);
181 #endif
182         return 0;
183 }
184
185 void gRC::recv_notify(const int &i)
186 {
187         notify();
188 }
189
190 gRC *gRC::getInstance()
191 {
192         return instance;
193 }
194
195 void gRC::enableSpinner()
196 {
197         if (!m_spinner_dc)
198         {
199                 eDebug("no spinner DC!");
200                 return;
201         }
202
203         m_spinner_enabled = 1;
204
205         gOpcode o;
206         o.opcode = m_spinner_enabled ? gOpcode::incrementSpinner : gOpcode::enableSpinner;
207         m_spinner_dc->exec(&o);
208 }
209
210 void gRC::disableSpinner()
211 {
212         if (!m_spinner_enabled)
213                 return;
214
215         if (!m_spinner_dc)
216         {
217                 eDebug("no spinner DC!");
218                 return;
219         }
220
221         m_spinner_enabled = 0;
222         
223         gOpcode o;
224         o.opcode = gOpcode::disableSpinner;
225         m_spinner_dc->exec(&o);
226 }
227
228 static int gPainter_instances;
229
230 gPainter::gPainter(gDC *dc, eRect rect): m_dc(dc), m_rc(gRC::getInstance())
231 {
232 //      ASSERT(!gPainter_instances);
233         gPainter_instances++;
234 //      begin(rect);
235 }
236
237 gPainter::~gPainter()
238 {
239         end();
240         gPainter_instances--;
241 }
242
243 void gPainter::setBackgroundColor(const gColor &color)
244 {
245         if ( m_dc->islocked() )
246                 return;
247         gOpcode o;
248         o.opcode = gOpcode::setBackgroundColor;
249         o.dc = m_dc.grabRef();
250         o.parm.setColor = new gOpcode::para::psetColor;
251         o.parm.setColor->color = color;
252
253         m_rc->submit(o);
254 }
255
256 void gPainter::setForegroundColor(const gColor &color)
257 {
258         if ( m_dc->islocked() )
259                 return;
260         gOpcode o;
261         o.opcode = gOpcode::setForegroundColor;
262         o.dc = m_dc.grabRef();
263         o.parm.setColor = new gOpcode::para::psetColor;
264         o.parm.setColor->color = color;
265
266         m_rc->submit(o);
267 }
268
269 void gPainter::setBackgroundColor(const gRGB &color)
270 {
271         if ( m_dc->islocked() )
272                 return;
273         gOpcode o;
274         o.opcode = gOpcode::setBackgroundColorRGB;
275         o.dc = m_dc.grabRef();
276         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
277         o.parm.setColorRGB->color = color;
278
279         m_rc->submit(o);
280 }
281
282 void gPainter::setForegroundColor(const gRGB &color)
283 {
284         if ( m_dc->islocked() )
285                 return;
286         gOpcode o;
287         o.opcode = gOpcode::setForegroundColorRGB;
288         o.dc = m_dc.grabRef();
289         o.parm.setColorRGB = new gOpcode::para::psetColorRGB;
290         o.parm.setColorRGB->color = color;
291
292         m_rc->submit(o);
293 }
294
295 void gPainter::setFont(gFont *font)
296 {
297         if ( m_dc->islocked() )
298                 return;
299         gOpcode o;
300         o.opcode = gOpcode::setFont;
301         o.dc = m_dc.grabRef();
302         font->AddRef();
303         o.parm.setFont = new gOpcode::para::psetFont;
304         o.parm.setFont->font = font;
305
306         m_rc->submit(o);
307 }
308
309 void gPainter::renderText(const eRect &pos, const std::string &string, int flags)
310 {
311         if ( m_dc->islocked() )
312                 return;
313         gOpcode o;
314         o.opcode=gOpcode::renderText;
315         o.dc = m_dc.grabRef();
316         o.parm.renderText = new gOpcode::para::prenderText;
317         o.parm.renderText->area = pos;
318         o.parm.renderText->text = string.empty()?0:strdup(string.c_str());
319         o.parm.renderText->flags = flags;
320         m_rc->submit(o);
321 }
322
323 void gPainter::renderPara(eTextPara *para, ePoint offset)
324 {
325         if ( m_dc->islocked() )
326                 return;
327         gOpcode o;
328         o.opcode=gOpcode::renderPara;
329         o.dc = m_dc.grabRef();
330         o.parm.renderPara = new gOpcode::para::prenderPara;
331         o.parm.renderPara->offset = offset;
332
333         para->AddRef();
334         o.parm.renderPara->textpara = para;
335         m_rc->submit(o);
336 }
337
338 void gPainter::fill(const eRect &area)
339 {
340         if ( m_dc->islocked() )
341                 return;
342         gOpcode o;
343         o.opcode=gOpcode::fill;
344
345         o.dc = m_dc.grabRef();
346         o.parm.fill = new gOpcode::para::pfillRect;
347         o.parm.fill->area = area;
348         m_rc->submit(o);
349 }
350
351 void gPainter::fill(const gRegion &region)
352 {
353         if ( m_dc->islocked() )
354                 return;
355         gOpcode o;
356         o.opcode=gOpcode::fillRegion;
357
358         o.dc = m_dc.grabRef();
359         o.parm.fillRegion = new gOpcode::para::pfillRegion;
360         o.parm.fillRegion->region = region;
361         m_rc->submit(o);
362 }
363
364 void gPainter::clear()
365 {
366         if ( m_dc->islocked() )
367                 return;
368         gOpcode o;
369         o.opcode=gOpcode::clear;
370         o.dc = m_dc.grabRef();
371         o.parm.fill = new gOpcode::para::pfillRect;
372         o.parm.fill->area = eRect();
373         m_rc->submit(o);
374 }
375
376 void gPainter::blit(gPixmap *pixmap, ePoint pos, const eRect &clip, int flags)
377 {
378         if ( m_dc->islocked() )
379                 return;
380         gOpcode o;
381
382         ASSERT(pixmap);
383
384         o.opcode=gOpcode::blit;
385         o.dc = m_dc.grabRef();
386         pixmap->AddRef();
387         o.parm.blit  = new gOpcode::para::pblit;
388         o.parm.blit->pixmap = pixmap;
389         o.parm.blit->position = pos;
390         o.parm.blit->clip = clip;
391         o.parm.blit->flags=flags;
392         m_rc->submit(o);
393 }
394
395
396 void gPainter::setPalette(gRGB *colors, int start, int len)
397 {
398         if ( m_dc->islocked() )
399                 return;
400         gOpcode o;
401         o.opcode=gOpcode::setPalette;
402         o.dc = m_dc.grabRef();
403         gPalette *p=new gPalette;
404
405         o.parm.setPalette = new gOpcode::para::psetPalette;
406         p->data=new gRGB[len];
407
408         memcpy(p->data, colors, len*sizeof(gRGB));
409         p->start=start;
410         p->colors=len;
411         o.parm.setPalette->palette = p;
412         m_rc->submit(o);
413 }
414
415 void gPainter::setPalette(gPixmap *source)
416 {
417         ASSERT(source);
418         setPalette(source->surface->clut.data, source->surface->clut.start, source->surface->clut.colors);
419 }
420
421 void gPainter::mergePalette(gPixmap *target)
422 {
423         if ( m_dc->islocked() )
424                 return;
425         gOpcode o;
426         o.opcode = gOpcode::mergePalette;
427         o.dc = m_dc.grabRef();
428         target->AddRef();
429         o.parm.mergePalette = new gOpcode::para::pmergePalette;
430         o.parm.mergePalette->target = target;
431         m_rc->submit(o);
432 }
433
434 void gPainter::line(ePoint start, ePoint end)
435 {
436         if ( m_dc->islocked() )
437                 return;
438         gOpcode o;
439         o.opcode=gOpcode::line;
440         o.dc = m_dc.grabRef();
441         o.parm.line = new gOpcode::para::pline;
442         o.parm.line->start = start;
443         o.parm.line->end = end;
444         m_rc->submit(o);
445 }
446
447 void gPainter::setOffset(ePoint val)
448 {
449         if ( m_dc->islocked() )
450                 return;
451         gOpcode o;
452         o.opcode=gOpcode::setOffset;
453         o.dc = m_dc.grabRef();
454         o.parm.setOffset = new gOpcode::para::psetOffset;
455         o.parm.setOffset->rel = 0;
456         o.parm.setOffset->value = val;
457         m_rc->submit(o);
458 }
459
460 void gPainter::moveOffset(ePoint rel)
461 {
462         if ( m_dc->islocked() )
463                 return;
464         gOpcode o;
465         o.opcode=gOpcode::setOffset;
466         o.dc = m_dc.grabRef();
467         o.parm.setOffset = new gOpcode::para::psetOffset;
468         o.parm.setOffset->rel = 1;
469         o.parm.setOffset->value = rel;
470         m_rc->submit(o);
471 }
472
473 void gPainter::resetOffset()
474 {
475         if ( m_dc->islocked() )
476                 return;
477         gOpcode o;
478         o.opcode=gOpcode::setOffset;
479         o.dc = m_dc.grabRef();
480         o.parm.setOffset = new gOpcode::para::psetOffset;
481         o.parm.setOffset->rel = 0;
482         o.parm.setOffset->value = ePoint(0, 0);
483         m_rc->submit(o);
484 }
485
486 void gPainter::resetClip(const gRegion &region)
487 {
488         if ( m_dc->islocked() )
489                 return;
490         gOpcode o;
491         o.opcode = gOpcode::setClip;
492         o.dc = m_dc.grabRef();
493         o.parm.clip = new gOpcode::para::psetClip;
494         o.parm.clip->region = region;
495         m_rc->submit(o);
496 }
497
498 void gPainter::clip(const gRegion &region)
499 {
500         if ( m_dc->islocked() )
501                 return;
502         gOpcode o;
503         o.opcode = gOpcode::addClip;
504         o.dc = m_dc.grabRef();
505         o.parm.clip = new gOpcode::para::psetClip;
506         o.parm.clip->region = region;
507         m_rc->submit(o);
508 }
509
510 void gPainter::clippop()
511 {
512         if ( m_dc->islocked() )
513                 return;
514         gOpcode o;
515         o.opcode = gOpcode::popClip;
516         o.dc = m_dc.grabRef();
517         m_rc->submit(o);
518 }
519
520 void gPainter::flush()
521 {
522         if ( m_dc->islocked() )
523                 return;
524         gOpcode o;
525         o.opcode = gOpcode::flush;
526         o.dc = m_dc.grabRef();
527         m_rc->submit(o);
528 }
529
530 void gPainter::waitVSync()
531 {
532         if ( m_dc->islocked() )
533                 return;
534         gOpcode o;
535         o.opcode = gOpcode::waitVSync;
536         o.dc = m_dc.grabRef();
537         m_rc->submit(o);
538 }
539
540 void gPainter::flip()
541 {
542         if ( m_dc->islocked() )
543                 return;
544         gOpcode o;
545         o.opcode = gOpcode::flip;
546         o.dc = m_dc.grabRef();
547         m_rc->submit(o);
548 }
549
550 void gPainter::notify()
551 {
552         if ( m_dc->islocked() )
553                 return;
554         gOpcode o;
555         o.opcode = gOpcode::notify;
556         o.dc = m_dc.grabRef();
557         m_rc->submit(o);
558 }
559
560 void gPainter::end()
561 {
562         if ( m_dc->islocked() )
563                 return;
564         gOpcode o;
565         o.opcode = gOpcode::flush;
566         o.dc = m_dc.grabRef();
567         m_rc->submit(o);
568 }
569
570 gDC::gDC()
571 {
572 }
573
574 gDC::gDC(gPixmap *pixmap): m_pixmap(pixmap)
575 {
576 }
577
578 gDC::~gDC()
579 {
580 }
581
582 void gDC::exec(gOpcode *o)
583 {
584         switch (o->opcode)
585         {
586         case gOpcode::setBackgroundColor:
587                 m_background_color = o->parm.setColor->color;
588                 m_background_color_rgb = getRGB(m_background_color);
589                 delete o->parm.setColor;
590                 break;
591         case gOpcode::setForegroundColor:
592                 m_foreground_color = o->parm.setColor->color;
593                 m_background_color_rgb = getRGB(m_foreground_color);
594                 delete o->parm.setColor;
595                 break;
596         case gOpcode::setBackgroundColorRGB:
597                 if (m_pixmap->needClut())
598                         m_background_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
599                 m_background_color_rgb = o->parm.setColorRGB->color;
600                 delete o->parm.setColorRGB;
601                 break;
602         case gOpcode::setForegroundColorRGB:
603                 if (m_pixmap->needClut())
604                         m_foreground_color = m_pixmap->surface->clut.findColor(o->parm.setColorRGB->color);
605                 m_foreground_color_rgb = o->parm.setColorRGB->color;
606                 delete o->parm.setColorRGB;
607                 break;
608         case gOpcode::setFont:
609                 m_current_font = o->parm.setFont->font;
610                 o->parm.setFont->font->Release();
611                 delete o->parm.setFont;
612                 break;
613         case gOpcode::renderText:
614         {
615                 ePtr<eTextPara> para = new eTextPara(o->parm.renderText->area);
616                 int flags = o->parm.renderText->flags;
617                 assert(m_current_font);
618                 para->setFont(m_current_font);
619                 para->renderString(o->parm.renderText->text, (flags & gPainter::RT_WRAP) ? RS_WRAP : 0);
620                 if (o->parm.renderText->text)
621                         free(o->parm.renderText->text);
622                 if (flags & gPainter::RT_HALIGN_RIGHT)
623                         para->realign(eTextPara::dirRight);
624                 else if (flags & gPainter::RT_HALIGN_CENTER)
625                         para->realign(eTextPara::dirCenter);
626                 else if (flags & gPainter::RT_HALIGN_BLOCK)
627                         para->realign(eTextPara::dirBlock);
628                 
629                 ePoint offset = m_current_offset;
630                 
631                 if (o->parm.renderText->flags & gPainter::RT_VALIGN_CENTER)
632                 {
633                         eRect bbox = para->getBoundBox();
634                         int vcentered_top = o->parm.renderText->area.top() + ((o->parm.renderText->area.height() - bbox.height()) / 2);
635                         int correction = vcentered_top - bbox.top();
636                         offset += ePoint(0, correction);
637                 }
638                 
639                 para->blit(*this, offset, m_background_color_rgb, m_foreground_color_rgb);
640                 delete o->parm.renderText;
641                 break;
642         }
643         case gOpcode::renderPara:
644         {
645                 o->parm.renderPara->textpara->blit(*this, o->parm.renderPara->offset + m_current_offset, m_background_color_rgb, m_foreground_color_rgb);
646                 o->parm.renderPara->textpara->Release();
647                 delete o->parm.renderPara;
648                 break;
649         }
650         case gOpcode::fill:
651         {
652                 eRect area = o->parm.fill->area;
653                 area.moveBy(m_current_offset);
654                 gRegion clip = m_current_clip & area;
655                 if (m_pixmap->needClut())
656                         m_pixmap->fill(clip, m_foreground_color);
657                 else
658                         m_pixmap->fill(clip, m_foreground_color_rgb);
659                 delete o->parm.fill;
660                 break;
661         }
662         case gOpcode::fillRegion:
663         {
664                 o->parm.fillRegion->region.moveBy(m_current_offset);
665                 gRegion clip = m_current_clip & o->parm.fillRegion->region;
666                 if (m_pixmap->needClut())
667                         m_pixmap->fill(clip, m_foreground_color);
668                 else
669                         m_pixmap->fill(clip, m_foreground_color_rgb);
670                 delete o->parm.fillRegion;
671                 break;
672         }
673         case gOpcode::clear:
674                 if (m_pixmap->needClut())
675                         m_pixmap->fill(m_current_clip, m_background_color);
676                 else
677                         m_pixmap->fill(m_current_clip, m_background_color_rgb);
678                 delete o->parm.fill;
679                 break;
680         case gOpcode::blit:
681         {
682                 gRegion clip;
683                                 // this code should be checked again but i'm too tired now
684                 
685                 o->parm.blit->position += m_current_offset;
686                 
687                 if (o->parm.blit->clip.valid())
688                 {
689                         o->parm.blit->clip.moveBy(m_current_offset);
690                         clip.intersect(gRegion(o->parm.blit->clip), m_current_clip);
691                 } else
692                         clip = m_current_clip;
693                 
694                 m_pixmap->blit(*o->parm.blit->pixmap, o->parm.blit->position, clip, o->parm.blit->flags);
695                 o->parm.blit->pixmap->Release();
696                 delete o->parm.blit;
697                 break;
698         }
699         case gOpcode::setPalette:
700                 if (o->parm.setPalette->palette->start > m_pixmap->surface->clut.colors)
701                         o->parm.setPalette->palette->start = m_pixmap->surface->clut.colors;
702                 if (o->parm.setPalette->palette->colors > (m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start))
703                         o->parm.setPalette->palette->colors = m_pixmap->surface->clut.colors-o->parm.setPalette->palette->start;
704                 if (o->parm.setPalette->palette->colors)
705                         memcpy(m_pixmap->surface->clut.data+o->parm.setPalette->palette->start, o->parm.setPalette->palette->data, o->parm.setPalette->palette->colors*sizeof(gRGB));
706                 
707                 delete[] o->parm.setPalette->palette->data;
708                 delete o->parm.setPalette->palette;
709                 delete o->parm.setPalette;
710                 break;
711         case gOpcode::mergePalette:
712                 m_pixmap->mergePalette(*o->parm.mergePalette->target);
713                 o->parm.mergePalette->target->Release();
714                 delete o->parm.mergePalette;
715                 break; 
716         case gOpcode::line:
717         {
718                 ePoint start = o->parm.line->start + m_current_offset, end = o->parm.line->end + m_current_offset;
719                 m_pixmap->line(m_current_clip, start, end, m_foreground_color);
720                 delete o->parm.line;
721                 break;
722         }
723         case gOpcode::addClip:
724                 m_clip_stack.push(m_current_clip);
725                 o->parm.clip->region.moveBy(m_current_offset);
726                 m_current_clip &= o->parm.clip->region;
727                 delete o->parm.clip;
728                 break;
729         case gOpcode::setClip:
730                 o->parm.clip->region.moveBy(m_current_offset);
731                 m_current_clip = o->parm.clip->region & eRect(ePoint(0, 0), m_pixmap->size());
732                 delete o->parm.clip;
733                 break;
734         case gOpcode::popClip:
735                 if (!m_clip_stack.empty())
736                 {
737                         m_current_clip = m_clip_stack.top();
738                         m_clip_stack.pop();
739                 }
740                 break;
741         case gOpcode::setOffset:
742                 if (o->parm.setOffset->rel)
743                         m_current_offset += o->parm.setOffset->value;
744                 else
745                         m_current_offset  = o->parm.setOffset->value;
746                 delete o->parm.setOffset;
747                 break;
748         case gOpcode::waitVSync:
749                 break;
750         case gOpcode::flip:
751                 break;
752         case gOpcode::flush:
753                 break;
754         case gOpcode::enableSpinner:
755                 break;
756         case gOpcode::disableSpinner:
757                 break;
758         case gOpcode::incrementSpinner:
759                 break;
760         default:
761                 eFatal("illegal opcode %d. expect memory leak!", o->opcode);
762         }
763 }
764
765 gRGB gDC::getRGB(gColor col)
766 {
767         if ((!m_pixmap) || (!m_pixmap->surface->clut.data))
768                 return gRGB(col, col, col);
769         if (col<0)
770         {
771                 eFatal("bla transp");
772                 return gRGB(0, 0, 0, 0xFF);
773         }
774         return m_pixmap->surface->clut.data[col];
775 }
776
777 DEFINE_REF(gDC);
778
779 eAutoInitPtr<gRC> init_grc(eAutoInitNumbers::graphic, "gRC");