BLiTT.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. // Do uncompressed transparent copying!
  19. #ifdef PATHS_IN_INCLUDES
  20. #include "GREEN/BLiT/BLIT.H"
  21. #else
  22. #include "BLIT.H"
  23. #endif
  24. #ifdef PATHS_IN_INCLUDES
  25. #include "GREEN/BLiT/_BlitInt.H"
  26. #else
  27. #include "_BlitInt.H"
  28. #endif
  29. //========================================================================================
  30. //========================================================================================
  31. // Insert this into your functions... It assumes pre-clipped, pre-sorted,
  32. // pre-validated rect copy: (Pitch will be sign based!)
  33. //
  34. template <class PIXSIZE>
  35. inline void _BLiTT(PIXSIZE ucTransparent,PIXSIZE* pSrc,PIXSIZE* pDst,long lSrcPitch, long lDstPitch,
  36. short sHeight,short sPixWidth)
  37. {
  38. union {
  39. PIXSIZE *w;
  40. UCHAR *b;
  41. } pSrcLine,pDstLine;
  42. int i;
  43. pSrcLine.w = pSrc;
  44. pDstLine.w = pDst;
  45. while (sHeight--)
  46. {
  47. pSrc = pSrcLine.w;
  48. pDst = pDstLine.w;
  49. i = sPixWidth;
  50. while (i--)
  51. {
  52. if (*pSrc != ucTransparent) *pDst = *pSrc;
  53. pDst++;pSrc++;
  54. }
  55. pSrcLine.b += lSrcPitch;
  56. pDstLine.b += lDstPitch;
  57. }
  58. }
  59. //*****************************************************************************
  60. // This is the main controller... It clips in pixels, then thinks in bytes:
  61. // if prSrc == NULL, no source clipping will occure
  62. // if prDst == NULL, it will clip to the CImage
  63. //
  64. short rspBlitT(ULONG ucTransparent,RImage* pimSrc,RImage* pimDst,short sSrcX,short sSrcY,short sDstX,
  65. short sDstY,short sW,short sH,const RRect* prDst,const RRect* prSrc)
  66. {
  67. short sClip;
  68. // 1) preliminary parameter validation:
  69. #ifdef _DEBUG
  70. if ((pimSrc == NULL) || (pimDst == NULL))
  71. {
  72. TRACE("rspBlitT: null CImage* passed\n");
  73. return -1;
  74. }
  75. if ( (sW < 1) || (sH < 1) )
  76. {
  77. TRACE("rspBlitT: zero or negative area passed\n");
  78. return -1;
  79. }
  80. if ( !ImageIsUncompressed(pimSrc->m_type) ||
  81. !ImageIsUncompressed(pimDst->m_type) )
  82. {
  83. TRACE("rspBlitT: To BLiT using COMPRESSED Images, you must specify"
  84. "your parameters differently (see BLiT.DOC)!\n");
  85. return -1;
  86. }
  87. #endif
  88. // 2) Optional Source Clipping
  89. if (prSrc)
  90. {
  91. // clip rect to source
  92. // clip against user values
  93. sClip = prSrc->sX - sDstX; // positive = clipped
  94. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prSrc->sX; }
  95. sClip = prSrc->sY - sDstY; // positive = clipped
  96. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prSrc->sY; }
  97. sClip = sDstX + sW - prSrc->sX - prSrc->sW; // positive = clipped
  98. if (sClip > 0) { sW -= sClip; }
  99. sClip = sDstY + sH - prSrc->sY - prSrc->sH; // positive = clipped
  100. if (sClip > 0) { sH -= sClip; }
  101. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  102. }
  103. // 2) Source clipping is SO critical in locked screen stuff, that we MUST check it:
  104. #ifdef _DEBUG
  105. else // no source clipping:
  106. {
  107. if ( (sSrcX < 0) || (sSrcY < 0) ||
  108. ((sSrcX + sW) > pimSrc->m_sWidth) || ((sSrcY + sH) > pimSrc->m_sHeight) )
  109. {
  110. TRACE("rspBlitT: Gone outside source buffer. Must source clip.\n");
  111. return -1;
  112. }
  113. }
  114. #endif
  115. // 3) Destination Clipping:
  116. if (prDst)
  117. {
  118. // clip against user values
  119. sClip = prDst->sX - sDstX; // positive = clipped
  120. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prDst->sX; }
  121. sClip = prDst->sY - sDstY; // positive = clipped
  122. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prDst->sY; }
  123. sClip = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
  124. if (sClip > 0) { sW -= sClip; }
  125. sClip = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
  126. if (sClip > 0) { sH -= sClip; }
  127. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  128. }
  129. else
  130. {
  131. // clip against full destination buffer
  132. if (sDstX < 0) { sW += sDstX; sSrcX -= sDstX; sDstX = 0; }
  133. if (sDstY < 0) { sH += sDstY; sSrcY -= sDstY; sDstY = 0; }
  134. sClip = sDstX + sW - pimDst->m_sWidth; // positive = clipped
  135. if (sClip > 0) sW -= sClip; // positive = clipped
  136. sClip = sDstY + sH - pimDst->m_sHeight; // positive = clipped
  137. if (sClip > 0) sH -= sClip; // positive = clipped
  138. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  139. }
  140. //************** INSERT BUFFER HOOKS HERE! ************************
  141. // do OS based copying!
  142. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  143. short sBlitTypeSrc = 0;
  144. short sBlitTypeDst = 0;
  145. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  146. #ifndef _DEBUG
  147. //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  148. #endif
  149. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  150. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  151. // has completed. (Lord help me if a blit gets interrupted)
  152. if (pimSrc->m_type == RImage::IMAGE_STUB) sBlitTypeSrc = (short)((long)pimSrc->m_pSpecial);
  153. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
  154. switch ( (sBlitTypeSrc<<3) + sBlitTypeDst) // 0 = normal image
  155. {
  156. case (BUF_MEMORY<<3) + 0: // system buffer to an image
  157. // need to lock / unlock this one:
  158. /*
  159. if (rspLockBuffer()
  160. !=0)
  161. {
  162. TRACE("rspBlitT: Unable to lock the system buffer, failed!\n");
  163. return -1;
  164. }
  165. // Locked the system buffer, remember to unlock it:
  166. sNeedToUnlock = BUF_MEMORY;
  167. */
  168. break;
  169. case (0<<3) + BUF_MEMORY: // image to system buffer
  170. /*
  171. // need to lock / unlock this one:
  172. if (rspLockBuffer()
  173. !=0)
  174. {
  175. TRACE("rspBlitT: Unable to lock the system buffer, failed!\n");
  176. return -1;
  177. }
  178. // Locked the system buffer, remember to unlock it:
  179. sNeedToUnlock = BUF_MEMORY;
  180. */
  181. break;
  182. case (BUF_VRAM<<3) + 0: // front screen to image
  183. // need to lock / unlock this one:
  184. /*
  185. if (rspLockScreen()
  186. !=0)
  187. {
  188. TRACE("rspBlitT: Unable to lock the OnScreen system buffer, failed!\n");
  189. return -1;
  190. }
  191. // Locked the front VRAM, remember to unlock it:
  192. sNeedToUnlock = BUF_VRAM;
  193. */
  194. break;
  195. case (0<<3) + BUF_VRAM: // image to front screen
  196. /*
  197. // need to lock / unlock this one:
  198. if (rspLockScreen()
  199. !=0)
  200. {
  201. TRACE("rspBlitT: Unable to lock the OnScreen system buffer, failed!\n");
  202. return -1;
  203. }
  204. // Locked the front VRAM, remember to unlock it:
  205. sNeedToUnlock = BUF_VRAM;
  206. */
  207. break;
  208. // HOOK the special case of sytem buffer to front VRAM
  209. case (BUF_MEMORY<<3) + BUF_VRAM: // system buffer to front screen
  210. rspUpdateDisplay(sDstX,sDstY,sW,sH);
  211. return 0; // DONE!!!!!
  212. break;
  213. case (BUF_VRAM<<3) + BUF_MEMORY: // front screen to system buffer
  214. // sNeedToUnlock = (BUF_VRAM<<3) + BUF_MEMORY;
  215. break;
  216. case 0: // image to image, no need to lock!
  217. break;
  218. default:
  219. TRACE("rspBlitT: This type of copy is not yet supported.\n");
  220. return -1;
  221. }
  222. //BLIT_PRELOCKED:
  223. //********************************************************************
  224. // Check for locking error:
  225. if (!pimDst->m_pData)
  226. {
  227. TRACE("rspBlitT: Null data - possible locking error.\n");
  228. return FAILURE;
  229. }
  230. // Done clipping, convert to bytes to find best alignment:
  231. // Currently based on source, assumes source = destination depth:
  232. switch (pimSrc->m_sDepth)
  233. {
  234. case 16:
  235. sDstX <<= 1;
  236. sSrcX <<= 1;
  237. sW <<= 1;
  238. break;
  239. case 32:
  240. sDstX <<= 2;
  241. sSrcX <<= 2;
  242. sW <<= 2;
  243. break;
  244. case 24:
  245. sDstX += (sDstX << 1);
  246. sSrcX += (sSrcX << 1);
  247. sW += (sW << 1);
  248. break;
  249. // 8-bit needs nothing...
  250. }
  251. // Calculate memory offsets using signed pitch:
  252. U8* pSrc = pimSrc->m_pData + sSrcX + pimSrc->m_lPitch * sSrcY;
  253. U8* pDst = pimDst->m_pData + sDstX + pimDst->m_lPitch * sDstY;
  254. // Copy based on pixel size:
  255. switch (pimDst->m_sDepth)
  256. {
  257. case 8:
  258. _BLiTT((UCHAR)ucTransparent,(U8*)pSrc,(U8*)pDst,pimSrc->m_lPitch,pimDst->m_lPitch,sH,sW);
  259. break;
  260. case 16:
  261. _BLiTT((USHORT)ucTransparent,(U16*)pSrc,(U16*)pDst,(pimSrc->m_lPitch),(pimDst->m_lPitch),sH,short(sW>>1));
  262. break;
  263. case 32:
  264. _BLiTT((ULONG)ucTransparent,(U32*)pSrc,(U32*)pDst,(pimSrc->m_lPitch),(pimDst->m_lPitch),sH,short(sW>>2));
  265. break;
  266. default:
  267. TRACE("rspBlitT: color depth not supported.\n");
  268. }
  269. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  270. #ifndef _DEBUG
  271. // if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  272. #endif
  273. //********************
  274. // OS_SPECIFIC:
  275. //******************** UNLOCK WHATEVER YOU NEED TO
  276. switch (sNeedToUnlock)
  277. {
  278. case 0:
  279. break;
  280. case BUF_MEMORY:
  281. // rspUnlockBuffer();
  282. break;
  283. case BUF_VRAM:
  284. // rspUnlockScreen();
  285. break;
  286. case BUF_VRAM2:
  287. rspUnlockVideoFlipPage();
  288. break;
  289. case (BUF_VRAM<<3) + BUF_MEMORY:
  290. // rspUnlockBuffer();
  291. // rspUnlockScreen();
  292. break;
  293. default:
  294. TRACE("rspBlitT: Unlocking error!\n");
  295. }
  296. //BLIT_DONTUNLOCK:
  297. return 0;
  298. }