123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- #include <precomp.h>
- #include "qpaintwnd.h"
- #include <tataki/canvas/bltcanvas.h>
- #include "../nu/threadpool/TimerHandle.hpp"
- #define TIMER_QUICKPAINT 0x650
- // thread context, this is here so we can avoid the windows types in quickpaintwnd.h
- class QuickPaintContext
- {
- public:
- QuickPaintContext(QuickPaintWnd *_wnd, int timeout)
- {
- killswitch = 0;
- wnd = _wnd;
- death = CreateEvent(NULL, FALSE, FALSE, NULL);
- timer_ms = timeout;
- WASABI_API_THREADPOOL->AddHandle(0, timer_handle, QPThreadPoolFunc, (void *)this, 0, 0/*api_threadpool::FLAG_LONG_EXECUTION*/);
- timer_handle.Wait(timer_ms);
- }
- ~QuickPaintContext()
- {
- CloseHandle(death);
- timer_handle.Close();
- }
- void Kill()
- {
- InterlockedExchangePointer((volatile PVOID*)&wnd, 0);
- killswitch=1;
- WaitForSingleObject(death, INFINITE);
- }
- QuickPaintWnd *wnd;
- TimerHandle timer_handle;
- HANDLE death;
- volatile int killswitch;
- int timer_ms;
- static int QPThreadPoolFunc(HANDLE h, void *user_data, intptr_t t);
- };
- int QuickPaintContext::QPThreadPoolFunc(HANDLE h, void *user_data, intptr_t t)
- {
- QuickPaintContext *context = (QuickPaintContext *)user_data;
- if (context->killswitch)
- {
- WASABI_API_THREADPOOL->RemoveHandle(0, h);
- SetEvent(context->death);
- }
- else
- {
- DWORD start = GetTickCount();
- QuickPaintWnd *wnd = 0;
- InterlockedExchangePointer((volatile PVOID*)&wnd, context->wnd);
- if (wnd)
- {
- wnd->quickPaint();
- TimerHandle timer_handle(h);
- DWORD end = GetTickCount();
- if (end-start > (DWORD)context->timer_ms)
- timer_handle.Wait(1);
- else
- timer_handle.Wait(context->timer_ms - (end - start));
- }
- }
- return 0;
- }
- // -----------------------------------------------------------------------
- QuickPaintWnd::QuickPaintWnd()
- {
- invalidates_required = 0;
- realtime = 1;
- canvas_w = -1;
- canvas_h = -1;
- timerset = 0;
- speed = 25;
- enabled = 0;
- render_canvas1 = NULL;
- render_canvas2 = NULL;
- paint_canvas = NULL;
- thread_context = 0;
- while (1)
- {
- svc_skinFilter *obj = sfe.getNext();
- if (!obj) break;
- filters.addItem(obj);
- }
- invalidated = 0;
- }
- // -----------------------------------------------------------------------
- QuickPaintWnd::~QuickPaintWnd()
- {
- foreach(filters)
- sfe.release(filters.getfor());
- endfor;
- KillThread();
- delete render_canvas1;
- delete render_canvas2;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::setRealtime(int rt)
- {
- realtime = rt;
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::getRealtime() const
- {
- return realtime;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::setSpeed(int ms)
- {
- speed = ms;
- if (enabled && timerset)
- {
- if (thread_context)
- thread_context->timer_ms = ms;
- // let it change the timer value on the invalidate() timer
- killTimer(TIMER_QUICKPAINT);
- setTimer(TIMER_QUICKPAINT, getSpeed());
- }
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::startQuickPaint()
- {
- enabled = 1;
- if (!isInited()) return;
- CreateRenderThread();
- timerset=1;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::stopQuickPaint()
- {
- enabled = 0;
- if (!isInited()) return;
- KillThread();
- timerset=0;
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::isQuickPainting()
- {
- return enabled;
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::getSpeed()
- {
- return speed;
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::onInit()
- {
- QUICKPAINTWND_PARENT::onInit();
- if (enabled)
- {
- ASSERT(!thread_context);
- CreateRenderThread();
- timerset = 1;
- }
- return 1;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::timerCallback(int id)
- {
- switch (id)
- {
- case TIMER_QUICKPAINT:
- if (invalidates_required)
- {
- invalidated = 1;
- if (getRealtime() && isVisible() && !isMinimized())
- cascadeRepaint();
- else
- invalidate();
- InterlockedExchange(&invalidates_required, 0);
- }
- //quickPaint();
- break;
- default:
- QUICKPAINTWND_PARENT::timerCallback(id);
- }
- }
- void QuickPaintWnd::SetPaintingCanvas(BltCanvas *c)
- {
- InterlockedExchangePointer((volatile PVOID*)&paint_canvas, c);
- }
- BltCanvas *&QuickPaintWnd::GetDrawingConvas()
- {
- if (paint_canvas == render_canvas2)
- return render_canvas1;
- else
- return render_canvas2;
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::quickPaint()
- {
- int repaint=0;
- int w, h;
- getQuickPaintSize(&w, &h);
- if (wantEvenAlignment())
- {
- if (w & 1) w++;
- if (h & 1) h++;
- }
- if (w == 0 && h == 0) return 0;
- BltCanvas *&render_canvas = GetDrawingConvas();
- int newone = 0;
- if (canvas_w != w || canvas_h != h)
- {
- delete render_canvas1; render_canvas1=0;
- delete render_canvas2; render_canvas2=0;
- }
- if (!render_canvas)
- {
- render_canvas = new BltCanvas(w, wantNegativeHeight() ? -h : h, getOsWindowHandle());
- canvas_w = w;
- canvas_h = h;
- newone = 1;
- }
- repaint = onQuickPaint(render_canvas, canvas_w, canvas_h, newone);
- SetPaintingCanvas(render_canvas);
- if (repaint)
- InterlockedIncrement(&invalidates_required);
- return repaint;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::getQuickPaintSize(int *w, int *h)
- {
- RECT r;
- getClientRect(&r);
- if (w) *w = r.right - r.left;
- if (h) *h = r.bottom - r.top;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::getQuickPaintSource(RECT *r)
- {
- ASSERT(r != NULL);
- r->left = 0;
- r->right = canvas_w;
- r->top = 0;
- r->bottom = canvas_h;
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::getQuickPaintDest(RECT *r)
- {
- ASSERT(r != NULL);
- getClientRect(r);
- }
- // -----------------------------------------------------------------------
- void QuickPaintWnd::onSetVisible(int show)
- {
- QUICKPAINTWND_PARENT::onSetVisible(show);
- if (!show)
- {
- if (timerset)
- {
- KillThread();
- timerset = 0;
- }
- }
- else
- {
- if (enabled && !timerset)
- {
- CreateRenderThread();
- timerset = 1;
- }
- }
- }
- // -----------------------------------------------------------------------
- int QuickPaintWnd::onPaint(Canvas *canvas)
- {
- QUICKPAINTWND_PARENT::onPaint(canvas);
- if (!enabled) return 1;
- BltCanvas *render_canvas;
- InterlockedExchangePointer((volatile PVOID*)&render_canvas, paint_canvas);
- if (!render_canvas) return 1;
- RECT r;
- getQuickPaintDest(&r);
- RECT sr;
- getQuickPaintSource(&sr);
- if (invalidated && wantFilters())
- {
- foreach(filters)
- filters.getfor()->filterBitmap((unsigned char *)render_canvas->getBits(), canvas_w, canvas_h, 32, NULL, getFiltersGroup());
- endfor;
- invalidated = 0;
- }
- render_canvas->/*getSkinBitmap()->*/stretchToRectAlpha(canvas, &sr, &r, getPaintingAlpha());
- InterlockedExchange(&invalidates_required, 0);
- return 1;
- }
- void QuickPaintWnd::KillThread()
- {
- if (thread_context)
- {
- killTimer(TIMER_QUICKPAINT);
- thread_context->Kill();
- delete thread_context;
- thread_context = 0;
- }
- }
- void QuickPaintWnd::CreateRenderThread()
- {
- int sp = getSpeed();
- if (!thread_context)
- {
- thread_context = new QuickPaintContext(this, sp);
- }
- else
- thread_context->timer_ms = sp;
- setTimer(TIMER_QUICKPAINT, sp);
- }
|