ddrawwnd.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "precomp.h"
  2. #include <process.h>
  3. #include "ddrawwnd.h"
  4. #include "../bfc/canvas.h"
  5. #include "../bfc/region.h"
  6. DDrawWnd::DDrawWnd() {
  7. m_lpDD = NULL;
  8. lpClipper = NULL;
  9. m_lpRenderSurf = NULL;
  10. m_lpPrimSurf = NULL;
  11. }
  12. DDrawWnd::~DDrawWnd() {
  13. deleteFrameBuffer(NULL);
  14. }
  15. void DDrawWnd::deleteFrameBuffer(Canvas *canvas) {
  16. if (m_lpRenderSurf) m_lpRenderSurf->Release();
  17. if (m_lpPrimSurf) m_lpPrimSurf->Release();
  18. if (lpClipper) lpClipper->Release();
  19. if (m_lpDD) m_lpDD->Release();
  20. m_lpRenderSurf = NULL;
  21. m_lpPrimSurf = NULL;
  22. m_lpDD = NULL;
  23. lpClipper = NULL;
  24. ddlist.removeItem(this);
  25. }
  26. int DDrawWnd::onInit() {
  27. DDRAWWND_PARENT::onInit();
  28. if (!allow_dd) return 1;
  29. return 1;
  30. }
  31. Canvas *DDrawWnd::createFrameBuffer(int _w, int _h) {
  32. if (!allow_dd) return DDRAWWND_PARENT::createFrameBuffer(_w, _h);
  33. if (virtualCanvas && !m_lpPrimSurf)
  34. DDRAWWND_PARENT::deleteFrameBuffer(virtualCanvas);
  35. deleteFrameBuffer(NULL);
  36. int resize_h = 8;
  37. int resize_w = 8;
  38. w = _w;
  39. h = _h;
  40. if (DirectDrawCreate(NULL,&m_lpDD,NULL) != DD_OK) {
  41. m_lpDD=NULL;
  42. MessageBox(gethWnd(),"Error creating ddraw object","DDraw",0);
  43. return NULL;
  44. }
  45. int dbl=0;
  46. m_lpDD->SetCooperativeLevel(gethWnd(), DDSCL_NORMAL);
  47. resize_w=(((w>>dbl)+3)&~3);
  48. // g_noshoww=resize_w-(w>>dbl);
  49. resize_h=h>>dbl;
  50. DDSURFACEDESC DDsd={sizeof(DDsd),};
  51. DDsd.dwFlags = DDSD_CAPS;
  52. DDsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  53. if (m_lpDD->CreateSurface(&DDsd, &m_lpPrimSurf, NULL) != DD_OK) {
  54. m_lpPrimSurf=0;
  55. return NULL;
  56. }
  57. if (m_lpDD->CreateClipper(0, &lpClipper, NULL) != DD_OK ) {
  58. m_lpPrimSurf->Release();
  59. m_lpPrimSurf=0;
  60. return NULL;
  61. }
  62. lpClipper->SetHWnd(0, gethWnd());
  63. m_lpPrimSurf->SetClipper(lpClipper);
  64. DDsd.dwFlags = DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_PIXELFORMAT;
  65. DDsd.dwWidth=resize_w;
  66. DDsd.dwHeight=resize_h;
  67. DDsd.lPitch=resize_w*sizeof(int);
  68. DDsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY;
  69. DDsd.ddpfPixelFormat.dwSize = sizeof(DDsd.ddpfPixelFormat);
  70. DDsd.ddpfPixelFormat.dwFlags=DDPF_RGB;
  71. DDsd.ddpfPixelFormat.dwRGBBitCount = 32;
  72. DDsd.ddpfPixelFormat.dwRBitMask=0xff0000;
  73. DDsd.ddpfPixelFormat.dwGBitMask=0x00ff00;
  74. DDsd.ddpfPixelFormat.dwBBitMask=0x0000ff;
  75. if (m_lpDD->CreateSurface(&DDsd, &m_lpRenderSurf, NULL) != DD_OK) {
  76. m_lpRenderSurf->Release();
  77. m_lpPrimSurf->Release();
  78. lpClipper->Release();
  79. m_lpRenderSurf=0;
  80. m_lpPrimSurf=0;
  81. lpClipper=0;
  82. return NULL;
  83. }
  84. fb_canvas = new DDSurfaceCanvas(m_lpRenderSurf, w, h);
  85. ddlist.addItem(this);
  86. if (!thread)
  87. startThread();
  88. return fb_canvas;
  89. }
  90. int DDrawWnd::virtualBeforePaint(api_region *r) {
  91. if (!allow_dd) return DDRAWWND_PARENT::virtualBeforePaint(r);
  92. EnterCriticalSection(&DDrawWnd::cs);
  93. fb_canvas->enter();
  94. return 1;
  95. }
  96. int DDrawWnd::virtualAfterPaint(api_region *r) {
  97. if (!allow_dd) return DDRAWWND_PARENT::virtualAfterPaint(r);
  98. fb_canvas->exit();
  99. LeaveCriticalSection(&DDrawWnd::cs);
  100. return 1;
  101. }
  102. void DDrawWnd::virtualCanvasCommit(Canvas *canvas, RECT *internalrect, double ra) {
  103. if (!allow_dd) { DDRAWWND_PARENT::commitFrameBuffer(canvas, internalrect, ra); return; }
  104. internalrect->left = MAX(0, (int)internalrect->left);
  105. internalrect->top = MAX(0, (int)internalrect->top);
  106. internalrect->right = MAX(w, (int)internalrect->right);
  107. internalrect->bottom = MAX(h, (int)internalrect->bottom);
  108. RECT wr;
  109. RECT screenrect = *internalrect;
  110. getWindowRect(&wr);
  111. screenrect.left += wr.left;
  112. screenrect.top += wr.top;
  113. screenrect.right += wr.left;
  114. screenrect.bottom += wr.top;
  115. if (ra == 1.0) {
  116. if (m_lpPrimSurf->Blt(&screenrect,m_lpRenderSurf,internalrect,DDBLT_WAIT,NULL) == DDERR_SURFACELOST) {
  117. m_lpPrimSurf->Restore();
  118. }
  119. } else {
  120. RECT rcr=screenrect;
  121. rcr.left = wr.left + (int)((double)internalrect->left*ra);
  122. rcr.top = wr.top + (int)((double)internalrect->top*ra);
  123. rcr.right = rcr.left + (int)((double)(internalrect->right-internalrect->left)*ra);
  124. rcr.bottom = rcr.top + (int)((double)(internalrect->bottom-internalrect->top)*ra);
  125. if (m_lpPrimSurf->Blt(&rcr,m_lpRenderSurf,internalrect,DDBLT_WAIT,NULL) == DDERR_SURFACELOST)
  126. m_lpPrimSurf->Restore();
  127. }
  128. }
  129. void DDrawWnd::startThread() {
  130. DWORD id;
  131. quitthread=0;
  132. InitializeCriticalSection(&cs);
  133. thread = (HANDLE)_beginthreadex(NULL,0,renderThread,0,0,(unsigned int *)&id);
  134. }
  135. void DDrawWnd::stopThread() {
  136. quitthread = 1;
  137. }
  138. unsigned int WINAPI DDrawWnd::renderThread(void *) {
  139. while (!quitthread) {
  140. for (int i=0;i<ddlist.getNumItems();i++)
  141. ddlist.enumItem(i)->flushPaint();
  142. Sleep(MIN(MAX(sleep_val,1),100));
  143. }
  144. _endthreadex(0);
  145. return 1;
  146. }
  147. void DDrawWnd::invalidate() {
  148. if (!allow_dd) { DDRAWWND_PARENT::invalidate(); return; }
  149. DDRAWWND_PARENT::deferedInvalidate();
  150. }
  151. void DDrawWnd::invalidateRect(RECT *r) {
  152. if (!allow_dd) { DDRAWWND_PARENT::invalidateRect(r); return; }
  153. DDRAWWND_PARENT::deferedInvalidateRect(r);
  154. }
  155. void DDrawWnd::invalidateRgn(api_region *rgn) {
  156. if (!allow_dd) { DDRAWWND_PARENT::invalidateRgn(rgn); return; }
  157. DDRAWWND_PARENT::deferedInvalidateRgn(rgn);
  158. }
  159. void DDrawWnd::validate() {
  160. if (!allow_dd) { DDRAWWND_PARENT::validate(); return; }
  161. DDRAWWND_PARENT::deferedValidate();
  162. }
  163. void DDrawWnd::validateRect(RECT *r) {
  164. if (!allow_dd) { DDRAWWND_PARENT::validateRect(r); return; }
  165. DDRAWWND_PARENT::deferedValidateRect(r);
  166. }
  167. void DDrawWnd::validateRgn(api_region *rgn) {
  168. if (!allow_dd) { DDRAWWND_PARENT::validateRgn(rgn); return; }
  169. DDRAWWND_PARENT::deferedValidateRgn(rgn);
  170. }
  171. CRITICAL_SECTION DDrawWnd::cs;
  172. HANDLE DDrawWnd::thread=NULL;
  173. int DDrawWnd::quitthread=0;
  174. PtrList<DDrawWnd> DDrawWnd::ddlist;
  175. int DDrawWnd::allow_dd = 1;
  176. int DDrawWnd::sleep_val = 10;