SDL_os2dive.c (10540B)
1 /* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org> 4 5 This software is provided 'as-is', without any express or implied 6 warranty. In no event will the authors be held liable for any damages 7 arising from the use of this software. 8 9 Permission is granted to anyone to use this software for any purpose, 10 including commercial applications, and to alter it and redistribute it 11 freely, subject to the following restrictions: 12 13 1. The origin of this software must not be misrepresented; you must not 14 claim that you wrote the original software. If you use this software 15 in a product, an acknowledgment in the product documentation would be 16 appreciated but is not required. 17 2. Altered source versions must be plainly marked as such, and must not be 18 misrepresented as being the original software. 19 3. This notice may not be removed or altered from any source distribution. 20 */ 21 #include "../../SDL_internal.h" 22 #include "../SDL_sysvideo.h" 23 #define INCL_WIN 24 #define INCL_GPI 25 #include <os2.h> 26 #define _MEERROR_H_ 27 #include <mmioos2.h> 28 #include <os2me.h> 29 #define INCL_MM_OS2 30 #include <dive.h> 31 #include <fourcc.h> 32 #include "SDL_os2output.h" 33 34 typedef struct _VODATA { 35 HDIVE hDive; 36 PVOID pBuffer; 37 ULONG ulDIVEBufNum; 38 FOURCC fccColorEncoding; 39 ULONG ulWidth; 40 ULONG ulHeight; 41 BOOL fBlitterReady; 42 } VODATA; 43 44 static BOOL voQueryInfo(VIDEOOUTPUTINFO *pInfo); 45 static PVODATA voOpen(void); 46 static VOID voClose(PVODATA pVOData); 47 static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd, 48 SDL_DisplayMode *pSDLDisplayMode, 49 HRGN hrgnShape, BOOL fVisible); 50 static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight, 51 ULONG ulBPP, ULONG fccColorEncoding, 52 PULONG pulScanLineSize); 53 static VOID voVideoBufFree(PVODATA pVOData); 54 static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects, 55 ULONG cSDLRects); 56 57 OS2VIDEOOUTPUT voDive = { 58 voQueryInfo, 59 voOpen, 60 voClose, 61 voSetVisibleRegion, 62 voVideoBufAlloc, 63 voVideoBufFree, 64 voUpdate 65 }; 66 67 68 static BOOL voQueryInfo(VIDEOOUTPUTINFO *pInfo) 69 { 70 DIVE_CAPS sDiveCaps = { 0 }; 71 FOURCC fccFormats[100] = { 0 }; 72 73 /* Query information about display hardware from DIVE. */ 74 sDiveCaps.pFormatData = fccFormats; 75 sDiveCaps.ulFormatLength = 100; 76 sDiveCaps.ulStructLen = sizeof(DIVE_CAPS); 77 78 if (DiveQueryCaps(&sDiveCaps, DIVE_BUFFER_SCREEN)) { 79 debug_os2("DiveQueryCaps() failed."); 80 return FALSE; 81 } 82 83 if (sDiveCaps.ulDepth < 8) { 84 debug_os2("Not enough screen colors to run DIVE. " 85 "Must be at least 256 colors."); 86 return FALSE; 87 } 88 89 pInfo->ulBPP = sDiveCaps.ulDepth; 90 pInfo->fccColorEncoding = sDiveCaps.fccColorEncoding; 91 pInfo->ulScanLineSize = sDiveCaps.ulScanLineBytes; 92 pInfo->ulHorizResolution = sDiveCaps.ulHorizontalResolution; 93 pInfo->ulVertResolution = sDiveCaps.ulVerticalResolution; 94 95 return TRUE; 96 } 97 98 PVODATA voOpen(void) 99 { 100 PVODATA pVOData = SDL_calloc(1, sizeof(VODATA)); 101 102 if (pVOData == NULL) { 103 SDL_OutOfMemory(); 104 return NULL; 105 } 106 107 if (DiveOpen(&pVOData->hDive, FALSE, NULL) != DIVE_SUCCESS) { 108 SDL_free(pVOData); 109 SDL_SetError("DIVE: A display engine instance open failed"); 110 return NULL; 111 } 112 113 return pVOData; 114 } 115 116 static VOID voClose(PVODATA pVOData) 117 { 118 voVideoBufFree(pVOData); 119 DiveClose(pVOData->hDive); 120 SDL_free(pVOData); 121 } 122 123 static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd, 124 SDL_DisplayMode *pSDLDisplayMode, 125 HRGN hrgnShape, BOOL fVisible) 126 { 127 HPS hps; 128 HRGN hrgn; 129 RGNRECT rgnCtl; 130 PRECTL prectl = NULL; 131 ULONG ulRC; 132 133 if (!fVisible) { 134 if (pVOData->fBlitterReady) { 135 pVOData->fBlitterReady = FALSE; 136 DiveSetupBlitter(pVOData->hDive, 0); 137 debug_os2("DIVE blitter is tuned off"); 138 } 139 return TRUE; 140 } 141 142 /* Query visible rectangles */ 143 hps = WinGetPS(hwnd); 144 hrgn = GpiCreateRegion(hps, 0, NULL); 145 if (hrgn == NULLHANDLE) { 146 WinReleasePS(hps); 147 SDL_SetError("GpiCreateRegion() failed"); 148 } else { 149 WinQueryVisibleRegion(hwnd, hrgn); 150 if (hrgnShape != NULLHANDLE) 151 GpiCombineRegion(hps, hrgn, hrgn, hrgnShape, CRGN_AND); 152 153 rgnCtl.ircStart = 1; 154 rgnCtl.crc = 0; 155 rgnCtl.ulDirection = 1; 156 GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, NULL); 157 if (rgnCtl.crcReturned != 0) { 158 prectl = SDL_malloc(rgnCtl.crcReturned * sizeof(RECTL)); 159 if (prectl != NULL) { 160 rgnCtl.ircStart = 1; 161 rgnCtl.crc = rgnCtl.crcReturned; 162 rgnCtl.ulDirection = 1; 163 GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, prectl); 164 } else { 165 SDL_OutOfMemory(); 166 } 167 } 168 GpiDestroyRegion(hps, hrgn); 169 WinReleasePS(hps); 170 171 if (prectl != NULL) { 172 /* Setup DIVE blitter. */ 173 SETUP_BLITTER sSetupBlitter; 174 SWP swp; 175 POINTL pointl = { 0 }; 176 177 WinQueryWindowPos(hwnd, &swp); 178 WinMapWindowPoints(hwnd, HWND_DESKTOP, &pointl, 1); 179 180 sSetupBlitter.ulStructLen = sizeof(SETUP_BLITTER); 181 sSetupBlitter.fccSrcColorFormat = pVOData->fccColorEncoding; 182 sSetupBlitter.fInvert = FALSE; 183 sSetupBlitter.ulSrcWidth = pVOData->ulWidth; 184 sSetupBlitter.ulSrcHeight = pVOData->ulHeight; 185 sSetupBlitter.ulSrcPosX = 0; 186 sSetupBlitter.ulSrcPosY = 0; 187 sSetupBlitter.ulDitherType = 0; 188 sSetupBlitter.fccDstColorFormat = FOURCC_SCRN; 189 sSetupBlitter.ulDstWidth = swp.cx; 190 sSetupBlitter.ulDstHeight = swp.cy; 191 sSetupBlitter.lDstPosX = 0; 192 sSetupBlitter.lDstPosY = 0; 193 sSetupBlitter.lScreenPosX = pointl.x; 194 sSetupBlitter.lScreenPosY = pointl.y; 195 196 sSetupBlitter.ulNumDstRects = rgnCtl.crcReturned; 197 sSetupBlitter.pVisDstRects = prectl; 198 199 ulRC = DiveSetupBlitter(pVOData->hDive, &sSetupBlitter); 200 SDL_free(prectl); 201 202 if (ulRC == DIVE_SUCCESS) { 203 pVOData->fBlitterReady = TRUE; 204 WinInvalidateRect(hwnd, NULL, TRUE); 205 debug_os2("DIVE blitter is ready now."); 206 return TRUE; 207 } 208 209 SDL_SetError("DiveSetupBlitter(), rc = 0x%X", ulRC); 210 } /* if (prectl != NULL) */ 211 } /* if (hrgn == NULLHANDLE) else */ 212 213 pVOData->fBlitterReady = FALSE; 214 DiveSetupBlitter(pVOData->hDive, 0); 215 return FALSE; 216 } 217 218 static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight, 219 ULONG ulBPP, FOURCC fccColorEncoding, 220 PULONG pulScanLineSize) 221 { 222 ULONG ulRC; 223 ULONG ulScanLineSize = ulWidth * (ulBPP >> 3); 224 225 /* Destroy previous buffer. */ 226 voVideoBufFree(pVOData); 227 228 if (ulWidth == 0 || ulHeight == 0 || ulBPP == 0) 229 return NULL; 230 231 /* Bytes per line. */ 232 ulScanLineSize = (ulScanLineSize + 3) & ~3; /* 4-byte aligning */ 233 *pulScanLineSize = ulScanLineSize; 234 235 ulRC = DosAllocMem(&pVOData->pBuffer, 236 (ulHeight * ulScanLineSize) + sizeof(ULONG), 237 PAG_COMMIT | PAG_EXECUTE | PAG_READ | PAG_WRITE); 238 if (ulRC != NO_ERROR) { 239 debug_os2("DosAllocMem(), rc = %u", ulRC); 240 return NULL; 241 } 242 243 ulRC = DiveAllocImageBuffer(pVOData->hDive, &pVOData->ulDIVEBufNum, 244 fccColorEncoding, ulWidth, ulHeight, 245 ulScanLineSize, pVOData->pBuffer); 246 if (ulRC != DIVE_SUCCESS) { 247 debug_os2("DiveAllocImageBuffer(), rc = 0x%X", ulRC); 248 DosFreeMem(pVOData->pBuffer); 249 pVOData->pBuffer = NULL; 250 pVOData->ulDIVEBufNum = 0; 251 return NULL; 252 } 253 254 pVOData->fccColorEncoding = fccColorEncoding; 255 pVOData->ulWidth = ulWidth; 256 pVOData->ulHeight = ulHeight; 257 258 debug_os2("buffer: 0x%P, DIVE buffer number: %u", 259 pVOData->pBuffer, pVOData->ulDIVEBufNum); 260 261 return pVOData->pBuffer; 262 } 263 264 static VOID voVideoBufFree(PVODATA pVOData) 265 { 266 ULONG ulRC; 267 268 if (pVOData->ulDIVEBufNum != 0) { 269 ulRC = DiveFreeImageBuffer(pVOData->hDive, pVOData->ulDIVEBufNum); 270 if (ulRC != DIVE_SUCCESS) { 271 debug_os2("DiveFreeImageBuffer(,%u), rc = %u", pVOData->ulDIVEBufNum, ulRC); 272 } else { 273 debug_os2("DIVE buffer %u destroyed", pVOData->ulDIVEBufNum); 274 } 275 pVOData->ulDIVEBufNum = 0; 276 } 277 278 if (pVOData->pBuffer != NULL) { 279 ulRC = DosFreeMem(pVOData->pBuffer); 280 if (ulRC != NO_ERROR) { 281 debug_os2("DosFreeMem(), rc = %u", ulRC); 282 } 283 pVOData->pBuffer = NULL; 284 } 285 } 286 287 static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects, 288 ULONG cSDLRects) 289 { 290 ULONG ulRC; 291 292 if (!pVOData->fBlitterReady || (pVOData->ulDIVEBufNum == 0)) { 293 debug_os2("DIVE blitter is not ready"); 294 return FALSE; 295 } 296 297 if (pSDLRects != 0) { 298 PBYTE pbLineMask; 299 300 pbLineMask = SDL_stack_alloc(BYTE, pVOData->ulHeight); 301 if (pbLineMask == NULL) { 302 debug_os2("Not enough stack size"); 303 return FALSE; 304 } 305 memset(pbLineMask, 0, pVOData->ulHeight); 306 307 for ( ; ((LONG)cSDLRects) > 0; cSDLRects--, pSDLRects++) { 308 memset(&pbLineMask[pSDLRects->y], 1, pSDLRects->h); 309 } 310 311 ulRC = DiveBlitImageLines(pVOData->hDive, pVOData->ulDIVEBufNum, 312 DIVE_BUFFER_SCREEN, pbLineMask); 313 SDL_stack_free(pbLineMask); 314 315 if (ulRC != DIVE_SUCCESS) { 316 debug_os2("DiveBlitImageLines(), rc = 0x%X", ulRC); 317 } 318 } else { 319 ulRC = DiveBlitImage(pVOData->hDive, pVOData->ulDIVEBufNum, 320 DIVE_BUFFER_SCREEN); 321 if (ulRC != DIVE_SUCCESS) { 322 debug_os2("DiveBlitImage(), rc = 0x%X", ulRC); 323 } 324 } 325 326 return ulRC == DIVE_SUCCESS; 327 } 328 329 /* vi: set ts=4 sw=4 expandtab: */