aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp')
-rw-r--r--Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp219
1 files changed, 219 insertions, 0 deletions
diff --git a/Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp b/Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp
new file mode 100644
index 00000000..d095da03
--- /dev/null
+++ b/Src/Wasabi/api/wnd/wndclass/ddrawwnd.cpp
@@ -0,0 +1,219 @@
+#include "precomp.h"
+#include <process.h>
+
+#include "ddrawwnd.h"
+#include "../bfc/canvas.h"
+#include "../bfc/region.h"
+
+DDrawWnd::DDrawWnd() {
+ m_lpDD = NULL;
+ lpClipper = NULL;
+ m_lpRenderSurf = NULL;
+ m_lpPrimSurf = NULL;
+}
+
+DDrawWnd::~DDrawWnd() {
+ deleteFrameBuffer(NULL);
+}
+
+void DDrawWnd::deleteFrameBuffer(Canvas *canvas) {
+ if (m_lpRenderSurf) m_lpRenderSurf->Release();
+ if (m_lpPrimSurf) m_lpPrimSurf->Release();
+ if (lpClipper) lpClipper->Release();
+ if (m_lpDD) m_lpDD->Release();
+ m_lpRenderSurf = NULL;
+ m_lpPrimSurf = NULL;
+ m_lpDD = NULL;
+ lpClipper = NULL;
+ ddlist.removeItem(this);
+}
+
+int DDrawWnd::onInit() {
+ DDRAWWND_PARENT::onInit();
+ if (!allow_dd) return 1;
+ return 1;
+}
+
+Canvas *DDrawWnd::createFrameBuffer(int _w, int _h) {
+
+ if (!allow_dd) return DDRAWWND_PARENT::createFrameBuffer(_w, _h);
+
+ if (virtualCanvas && !m_lpPrimSurf)
+ DDRAWWND_PARENT::deleteFrameBuffer(virtualCanvas);
+
+ deleteFrameBuffer(NULL);
+
+ int resize_h = 8;
+ int resize_w = 8;
+
+ w = _w;
+ h = _h;
+
+ if (DirectDrawCreate(NULL,&m_lpDD,NULL) != DD_OK) {
+ m_lpDD=NULL;
+ MessageBox(gethWnd(),"Error creating ddraw object","DDraw",0);
+ return NULL;
+ }
+
+ int dbl=0;
+
+ m_lpDD->SetCooperativeLevel(gethWnd(), DDSCL_NORMAL);
+ resize_w=(((w>>dbl)+3)&~3);
+// g_noshoww=resize_w-(w>>dbl);
+ resize_h=h>>dbl;
+
+ DDSURFACEDESC DDsd={sizeof(DDsd),};
+
+ DDsd.dwFlags = DDSD_CAPS;
+ DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+ if (m_lpDD->CreateSurface(&DDsd, &m_lpPrimSurf, NULL) != DD_OK) {
+ m_lpPrimSurf=0;
+ return NULL;
+ }
+
+ if (m_lpDD->CreateClipper(0, &lpClipper, NULL) != DD_OK ) {
+ m_lpPrimSurf->Release();
+ m_lpPrimSurf=0;
+ return NULL;
+ }
+
+ lpClipper->SetHWnd(0, gethWnd());
+ m_lpPrimSurf->SetClipper(lpClipper);
+
+ DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT;
+ DDsd.dwWidth=resize_w;
+ DDsd.dwHeight=resize_h;
+ DDsd.lPitch=resize_w*sizeof(int);
+ DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
+ DDsd.ddpfPixelFormat.dwSize = sizeof(DDsd.ddpfPixelFormat);
+ DDsd.ddpfPixelFormat.dwFlags=DDPF_RGB;
+ DDsd.ddpfPixelFormat.dwRGBBitCount = 32;
+ DDsd.ddpfPixelFormat.dwRBitMask=0xff0000;
+ DDsd.ddpfPixelFormat.dwGBitMask=0x00ff00;
+ DDsd.ddpfPixelFormat.dwBBitMask=0x0000ff;
+ if (m_lpDD->CreateSurface(&DDsd, &m_lpRenderSurf, NULL) != DD_OK) {
+ m_lpRenderSurf->Release();
+ m_lpPrimSurf->Release();
+ lpClipper->Release();
+ m_lpRenderSurf=0;
+ m_lpPrimSurf=0;
+ lpClipper=0;
+ return NULL;
+ }
+ fb_canvas = new DDSurfaceCanvas(m_lpRenderSurf, w, h);
+
+ ddlist.addItem(this);
+
+ if (!thread)
+ startThread();
+
+ return fb_canvas;
+}
+
+int DDrawWnd::virtualBeforePaint(api_region *r) {
+ if (!allow_dd) return DDRAWWND_PARENT::virtualBeforePaint(r);
+ EnterCriticalSection(&DDrawWnd::cs);
+ fb_canvas->enter();
+ return 1;
+}
+
+int DDrawWnd::virtualAfterPaint(api_region *r) {
+ if (!allow_dd) return DDRAWWND_PARENT::virtualAfterPaint(r);
+ fb_canvas->exit();
+ LeaveCriticalSection(&DDrawWnd::cs);
+ return 1;
+}
+
+void DDrawWnd::virtualCanvasCommit(Canvas *canvas, RECT *internalrect, double ra) {
+ if (!allow_dd) { DDRAWWND_PARENT::commitFrameBuffer(canvas, internalrect, ra); return; }
+
+ internalrect->left = MAX(0, (int)internalrect->left);
+ internalrect->top = MAX(0, (int)internalrect->top);
+ internalrect->right = MAX(w, (int)internalrect->right);
+ internalrect->bottom = MAX(h, (int)internalrect->bottom);
+
+ RECT wr;
+ RECT screenrect = *internalrect;
+
+ getWindowRect(&wr);
+ screenrect.left += wr.left;
+ screenrect.top += wr.top;
+ screenrect.right += wr.left;
+ screenrect.bottom += wr.top;
+
+ if (ra == 1.0) {
+ if (m_lpPrimSurf->Blt(&screenrect,m_lpRenderSurf,internalrect,DDBLT_WAIT,NULL) == DDERR_SURFACELOST) {
+ m_lpPrimSurf->Restore();
+ }
+ } else {
+ RECT rcr=screenrect;
+ rcr.left = wr.left + (int)((double)internalrect->left*ra);
+ rcr.top = wr.top + (int)((double)internalrect->top*ra);
+ rcr.right = rcr.left + (int)((double)(internalrect->right-internalrect->left)*ra);
+ rcr.bottom = rcr.top + (int)((double)(internalrect->bottom-internalrect->top)*ra);
+
+ if (m_lpPrimSurf->Blt(&rcr,m_lpRenderSurf,internalrect,DDBLT_WAIT,NULL) == DDERR_SURFACELOST)
+ m_lpPrimSurf->Restore();
+ }
+}
+
+void DDrawWnd::startThread() {
+ DWORD id;
+ quitthread=0;
+ InitializeCriticalSection(&cs);
+ thread = (HANDLE)_beginthreadex(NULL,0,renderThread,0,0,(unsigned int *)&id);
+}
+
+void DDrawWnd::stopThread() {
+ quitthread = 1;
+}
+
+unsigned int WINAPI DDrawWnd::renderThread(void *) {
+ while (!quitthread) {
+ for (int i=0;i<ddlist.getNumItems();i++)
+ ddlist.enumItem(i)->flushPaint();
+ Sleep(MIN(MAX(sleep_val,1),100));
+ }
+ _endthreadex(0);
+ return 1;
+}
+
+void DDrawWnd::invalidate() {
+ if (!allow_dd) { DDRAWWND_PARENT::invalidate(); return; }
+ DDRAWWND_PARENT::deferedInvalidate();
+}
+
+void DDrawWnd::invalidateRect(RECT *r) {
+ if (!allow_dd) { DDRAWWND_PARENT::invalidateRect(r); return; }
+ DDRAWWND_PARENT::deferedInvalidateRect(r);
+}
+
+void DDrawWnd::invalidateRgn(api_region *rgn) {
+ if (!allow_dd) { DDRAWWND_PARENT::invalidateRgn(rgn); return; }
+ DDRAWWND_PARENT::deferedInvalidateRgn(rgn);
+}
+
+void DDrawWnd::validate() {
+ if (!allow_dd) { DDRAWWND_PARENT::validate(); return; }
+ DDRAWWND_PARENT::deferedValidate();
+}
+
+void DDrawWnd::validateRect(RECT *r) {
+ if (!allow_dd) { DDRAWWND_PARENT::validateRect(r); return; }
+ DDRAWWND_PARENT::deferedValidateRect(r);
+}
+
+void DDrawWnd::validateRgn(api_region *rgn) {
+ if (!allow_dd) { DDRAWWND_PARENT::validateRgn(rgn); return; }
+ DDRAWWND_PARENT::deferedValidateRgn(rgn);
+}
+
+
+CRITICAL_SECTION DDrawWnd::cs;
+HANDLE DDrawWnd::thread=NULL;
+int DDrawWnd::quitthread=0;
+PtrList<DDrawWnd> DDrawWnd::ddlist;
+int DDrawWnd::allow_dd = 1;
+int DDrawWnd::sleep_val = 10;
+
+