sdl

FORK: Simple Directmedia Layer
git clone https://git.neptards.moe/neptards/sdl.git
Log | Files | Refs

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: */