SDL  2.0
SDL_os2dive.c
Go to the documentation of this file.
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;
39  ULONG ulWidth;
40  ULONG ulHeight;
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 
59  voOpen,
60  voClose,
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 
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: */
#define SDL_SetError
#define SDL_malloc
#define SDL_free
#define SDL_calloc
#define SDL_OutOfMemory()
Definition: SDL_error.h:88
#define memset
Definition: SDL_malloc.c:627
#define debug_os2(s,...)
Definition: SDL_os2.h:38
static PVODATA voOpen(void)
Definition: SDL_os2dive.c:98
static BOOL voSetVisibleRegion(PVODATA pVOData, HWND hwnd, SDL_DisplayMode *pSDLDisplayMode, HRGN hrgnShape, BOOL fVisible)
Definition: SDL_os2dive.c:123
OS2VIDEOOUTPUT voDive
Definition: SDL_os2dive.c:57
static BOOL voQueryInfo(VIDEOOUTPUTINFO *pInfo)
Definition: SDL_os2dive.c:68
static BOOL voUpdate(PVODATA pVOData, HWND hwnd, SDL_Rect *pSDLRects, ULONG cSDLRects)
Definition: SDL_os2dive.c:287
static VOID voClose(PVODATA pVOData)
Definition: SDL_os2dive.c:116
static PVOID voVideoBufAlloc(PVODATA pVOData, ULONG ulWidth, ULONG ulHeight, ULONG ulBPP, ULONG fccColorEncoding, PULONG pulScanLineSize)
static VOID voVideoBufFree(PVODATA pVOData)
Definition: SDL_os2dive.c:264
struct _VODATA * PVODATA
Definition: SDL_os2output.h:26
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:360
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:361
#define NULL
Definition: begin_code.h:163
#define TRUE
Definition: edid-parse.c:33
#define FALSE
Definition: edid-parse.c:34
The structure that defines a display mode.
Definition: SDL_video.h:54
A rectangle, with the origin at the upper left (integer).
Definition: SDL_rect.h:78
int h
Definition: SDL_rect.h:80
int y
Definition: SDL_rect.h:79
ULONG fccColorEncoding
Definition: SDL_os2output.h:30
ULONG ulVertResolution
Definition: SDL_os2output.h:33
ULONG ulHorizResolution
Definition: SDL_os2output.h:32
BOOL fBlitterReady
Definition: SDL_os2dive.c:41
HDIVE hDive
Definition: SDL_os2dive.c:35
ULONG ulDIVEBufNum
Definition: SDL_os2dive.c:37
ULONG ulWidth
Definition: SDL_os2dive.c:39
ULONG ulHeight
Definition: SDL_os2dive.c:40
PVOID pBuffer
Definition: SDL_os2dive.c:36
FOURCC fccColorEncoding
Definition: SDL_os2dive.c:38