source: trunk/src/opengl/mesa/mesadive.c

Last change on this file was 21916, checked in by dmik, 14 years ago

Merge branch gcc-kmk to trunk.

File size: 17.7 KB
Line 
1/* $Id: mesadive.c,v 1.3 2000-12-30 13:55:43 sandervl Exp $ */
2/*****************************************************************************/
3/* */
4/* DIVE code for OpenGL */
5/* */
6/*****************************************************************************/
7
8#ifdef DIVE
9#define INCL_BASE
10#define INCL_WIN
11#define INCL_GPI
12
13
14#include <os2wrap.h>
15#include "../../ddraw/divewrap.h"
16#include <memory.h>
17#include <malloc.h>
18#include <fourcc.h>
19#include <misc.h>
20#include <winuser32.h>
21
22#define mmioFOURCC( ch0, ch1, ch2, ch3 ) \
23 ( (DWORD)(BYTE)(ch0) | ( (DWORD)(BYTE)(ch1) << 8 ) | \
24 ( (DWORD)(BYTE)(ch2) << 16 ) | ( (DWORD)(BYTE)(ch3) << 24 ) )
25
26/* Some extra typedefs to be able to import some of the underneath headers */
27typedef ULONG HPALETTE;
28typedef ULONG HPEN;
29typedef ULONG COLORREF;
30
31#include "gl.h"
32#include "config.h"
33#include "context.h"
34#include "wmesadef.h"
35#include "colors.h"
36
37#include "mesadive.h"
38
39extern BYTE DITHER_RGB_2_8BIT( int red, int green, int blue, int pixel, int scanline);
40extern void WMesaUpdateScreenPos(PWMC c,HWND hWnd);
41extern INT WINAPI MessageBoxA(HWND,LPCSTR,LPCSTR,UINT);
42
43extern PWMC Current;
44
45DIVE_CAPS DiveCaps;
46
47typedef struct tagFN
48 {
49 HWND hwnd;
50 PFNWP f;
51 struct tagFN *Next;
52 }FN;
53
54FN *WndFuncs;
55
56void StoreFn(HWND hwnd,PFNWP f)
57{
58 FN *p=WndFuncs;
59
60 while(p)
61 {
62 if(p->hwnd==hwnd)
63 {
64 p->f=f;
65 return;
66 }
67
68 p=p->Next;
69 }
70
71 p=(FN *)calloc(sizeof(FN),1);
72
73 p->hwnd=hwnd;
74 p->f=f;
75 p->Next=WndFuncs;
76
77 WndFuncs=p;
78}
79
80PFNWP QueryFn(HWND hwnd)
81{
82 FN *p=WndFuncs;
83
84 while(p)
85 {
86 if(p->hwnd==hwnd)
87 return p->f;
88
89 p=p->Next;
90 }
91
92 return 0;
93}
94
95FOURCC GetFOURCC(int pf)
96{
97 switch(pf)
98 {
99 case PF_8A8B8G8R:
100 return FOURCC_BGR4;
101
102 case PF_8R8G8B:
103 return FOURCC_RGB3;
104
105 case PF_5R6G5B:
106 return FOURCC_R565;
107
108 case PF_DITHER8:
109 break;
110
111 case PF_LOOKUP:
112 return FOURCC_LUT8;
113
114 case PF_GRAYSCALE:
115 return FOURCC_GREY;
116
117 case PF_BADFORMAT:
118 return FOURCC_RGB3;
119
120 case PF_INDEX8:
121 return FOURCC_LUT8;
122
123 default:
124 break;
125 }
126
127 return 0;
128}
129
130void DiveWriteBackbuffer( PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
131{
132 PBYTE lpb = pwc->pbPixels;
133 PDWORD lpdw;
134 PWORD lpw;
135 ULONG nBypp = pwc->cColorBits >> 3;
136 ULONG nOffset = iPixel % nBypp;
137
138 lpb += pwc->ScanWidth * iScanLine;
139
140 lpb += iPixel * nBypp;
141 lpdw = (LPDWORD)lpb;
142 lpw = (LPWORD)lpb;
143
144 if(nBypp == 1)
145 {
146 if(pwc->dither_flag)
147 *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
148 else
149 *lpb = BGR8(r,g,b);
150 }
151 else
152 if(nBypp == 2)
153 *lpw = BGR16(r,g,b);
154 else
155 if (nBypp == 3)
156 *lpdw = BGR24(r,g,b);
157 else
158 if (nBypp == 4)
159 *lpdw = BGR32(r,g,b);
160}
161
162void DiveWriteFrontbuffer( PWMC pwc, int iScanLine, int iPixel, BYTE r, BYTE g, BYTE b)
163{
164 /* Check whether the point is clipped - if so don't draw it! */
165 POINTL pt;
166 ULONG rc;
167
168 pt.x=iPixel; pt.y=iScanLine;
169
170 rc=GpiPtInRegion(pwc->hps,pwc->hrgn,&pt);
171
172 if(rc!=PRGN_INSIDE)
173 return;
174
175 if(DiveCaps.fBankSwitched)
176 {
177 MessageBoxA( NULL, "Bank-Switched DIVE access currently not supported", "", MB_OK );
178 }
179 else
180 {
181 PBYTE lpb = (PBYTE)pwc->ppFrameBuffer;
182 PDWORD lpdw;
183 PWORD lpw;
184 ULONG nBypp = DiveCaps.ulDepth >> 3;
185/* ULONG nOffset = iPixel % nBypp;*/
186
187 iScanLine+=pwc->WinPos.y;
188 iPixel+=pwc->WinPos.x;
189
190 lpb += iScanLine * DiveCaps.ulScanLineBytes;
191 lpb += iPixel * nBypp;
192 lpdw = (LPDWORD)lpb;
193 lpw = (LPWORD)lpb;
194
195 if(nBypp == 1){
196 if(pwc->dither_flag)
197 *lpb = DITHER_RGB_2_8BIT(r,g,b,iScanLine,iPixel);
198 else
199 *lpb = BGR8(r,g,b);
200 }
201 else if(nBypp == 2)
202 *lpw = BGR16(r,g,b);
203 else if (nBypp == 3){
204 *lpdw = BGR24(r,g,b);
205 }
206 else if (nBypp == 4)
207 *lpdw = BGR32(r,g,b);
208 }
209}
210
211void DiveFlush( PWMC pwc )
212{
213 ULONG rc;
214
215 if(!pwc->hDiveInstance)
216 {
217 dprintf(("DIVE ERROR : no instance!"));
218 return;
219 }
220
221 if(pwc->DiveSoftwareBlit)
222 {
223 /* Perform software blitting if DiveSetupBlitter failed! */
224 /* The source and target format will always be identical */
225 /* This is accomplished by wmesa.c's wmSetPixelFormat */
226 /* routine that uses the native output-format... */
227
228 PBYTE lpb = (PBYTE)pwc->ppFrameBuffer;
229 PBYTE lpbb = pwc->pbPixels;
230 ULONG nBypp = pwc->cColorBits >> 3;
231 ULONG bpl = nBypp*pwc->awidth;
232
233 lpb += pwc->WinPos.y*DiveCaps.ulScanLineBytes;
234 lpb += pwc->WinPos.x*nBypp;
235
236 lpbb += (pwc->height-1) * pwc->ScanWidth;
237
238 for(int y=0; y<pwc->height; y++)
239 {
240 memcpy(lpb,lpbb,bpl);
241
242 lpb+=DiveCaps.ulScanLineBytes;
243 lpbb-=pwc->ScanWidth;
244 }
245 }
246 else
247 {
248 rc=DiveEndImageBufferAccess(pwc->hDiveInstance,
249 pwc->BackBufferNumber);
250
251 rc=DiveBlitImage(pwc->hDiveInstance,
252 pwc->BackBufferNumber,
253 DIVE_BUFFER_SCREEN);
254
255 ULONG bsl;
256
257 rc=DiveBeginImageBufferAccess(pwc->hDiveInstance,
258 pwc->BackBufferNumber,
259 &pwc->pbPixels,
260 &pwc->ScanWidth,
261 &bsl);
262 }
263}
264
265void DiveDefineRegion(PWMC wc,HWND hWnd)
266{
267 RGNRECT rgnCtl;
268 HWND hwnd=Win32ToOS2Handle(hWnd);
269 ULONG rc;
270
271
272 rgnCtl.ircStart=0;
273 rgnCtl.crc=50;
274 rgnCtl.ulDirection=RECTDIR_LFRT_TOPBOT;
275
276 if(wc->hrgn)
277 GpiDestroyRegion(wc->hps,wc->hrgn);
278
279 if(wc->hps)
280 WinReleasePS(wc->hps);
281
282 wc->hps=WinGetPS(hwnd);
283
284 wc->hrgn=(ULONG)GpiCreateRegion(wc->hps,0,NULL);
285
286 rc=WinQueryVisibleRegion(hwnd,wc->hrgn);
287
288 rc=GpiQueryRegionRects(wc->hps,wc->hrgn,NULL,&rgnCtl,(RECTL *)wc->rctls);
289
290 wc->NumClipRects=rgnCtl.crcReturned;
291}
292
293ULONG DiveBlitSetup(PWMC wc,BOOL fActivate)
294{
295 SETUP_BLITTER setup;
296 POINTL pointl;
297 SWP swp;
298 ULONG rc;
299
300 if(!wc)
301 return 0;
302
303 if(!fActivate)
304 return DiveSetupBlitter(wc->hDiveInstance,0);
305
306 DiveDefineRegion(wc,wc->hwnd);
307
308 /* If not double-buffered we don't actually need to setup the blitter! */
309 /* Also, if setting up the blitter failed once, it will probably fail */
310 /* again, so no need to pursue this piece of logic... */
311 if(!wc->db_flag || wc->DiveSoftwareBlit)
312 return 0;
313
314 memset(&setup,0,sizeof(SETUP_BLITTER));
315
316 setup.ulStructLen=sizeof(SETUP_BLITTER);
317
318 setup.fInvert=1;
319
320 setup.fccSrcColorFormat=GetFOURCC(wc->pixelformat);
321 setup.fccDstColorFormat=FOURCC_SCRN;
322
323 setup.ulSrcWidth=wc->awidth;
324 setup.ulDstWidth=wc->awidth;
325 setup.ulSrcHeight=wc->aheight;
326 setup.ulDstHeight=wc->aheight;
327
328 WinQueryWindowPos(Win32ToOS2Handle(wc->hwnd),&swp);
329
330 pointl.x=swp.x; pointl.y=swp.y;
331
332 WinMapWindowPoints(WinQueryWindow(Win32ToOS2Handle(wc->hwnd),QW_PARENT),
333 HWND_DESKTOP,
334 &pointl,
335 1);
336
337 setup.lScreenPosX=pointl.x;
338 setup.lScreenPosY=pointl.y;
339
340 setup.ulNumDstRects=wc->NumClipRects;
341 setup.pVisDstRects=(RECTL *)wc->rctls;
342
343 rc=DiveSetupBlitter(wc->hDiveInstance,&setup);
344
345 if(rc==DIVE_ERR_INVALID_CONVERSION)
346 {
347 /* Hmmm, my Matrox does this all the time in 24-bit depth mode */
348 /* It works in lower color-depths, but in order to use Dive even */
349 /* if the conversion-code in DIVE is somehow malfunctioning use */
350 /* a software blitter to blit the image. Do however change the */
351 /* backbuffer's pixelformat to that of the screen. */
352 wc->DiveSoftwareBlit=TRUE;
353
354 rc=0;
355 }
356
357 return rc;
358}
359
360MRESULT EXPENTRY os2DiveWndProc(HWND hwnd,ULONG msg,MPARAM mp1,MPARAM mp2)
361{
362 PFNWP f=QueryFn(hwnd);
363 ULONG rc;
364
365 switch(msg)
366 {
367 case WM_VRNENABLED:
368 if(Current)
369 {
370 DiveBlitSetup(Current,TRUE);
371 WMesaUpdateScreenPos(Current,Current->hwnd);
372 }
373 break;
374
375 case WM_VRNDISABLED:
376 if(Current)
377 DiveBlitSetup(Current,FALSE);
378 break;
379
380 case WM_SETFOCUS:
381 if(Current)
382 DiveDefineRegion(Current,Current->hwnd);
383 break;
384
385 case WM_SIZE:
386 if(Current)
387 {
388 WMesaUpdateScreenPos(Current,Current->hwnd);
389 /* DiveResizeBuffers(Current->width,Current->Height);*/
390 }
391 break;
392
393 case WM_DESTROY:
394 WinSetVisibleRegionNotify(hwnd,FALSE);
395 break;
396 }
397
398 return (*f)(hwnd,msg,mp1,mp2);
399}
400
401PBYTE AllocateBuffer(int width,int height,int pf,ULONG *s)
402{
403 *s=width*4;
404
405 return (PBYTE)malloc(width*height*4);
406}
407
408/*
409* doInit - do work required for every instance of the application:
410* create the window, initialize data
411*/
412BOOL DiveInit( PWMC wc, HWND hwnd)
413{
414 ULONG rc;
415 RECT rect;
416
417/* wc->fullScreen = displayOptions.fullScreen;
418 wc->gMode = displayOptions.mode;*/
419 wc->hwnd = hwnd;
420
421 /* Register Region change Notifications for our window */
422 /* This allows us to set the correct clipping rects and window position */
423 /* We must subclass the OS/2 hwnd in order to accomplish this, since the*/
424 /* WM_VRNxxxxx messages are not relayed to the WIN hwnd. */
425 PFNWP f=WinSubclassWindow(Win32ToOS2Handle(hwnd),(PFNWP)os2DiveWndProc);
426 StoreFn(Win32ToOS2Handle(hwnd),f);
427
428 WinSetVisibleRegionNotify(Win32ToOS2Handle(hwnd),TRUE);
429
430/* stereo_flag = displayOptions.stereo;
431
432 if(wc->db_flag!= TRUE)
433 stereo_flag = FALSE;
434*/
435 rc=DiveOpen(&wc->hDiveInstance,
436 FALSE,
437 &wc->ppFrameBuffer);
438
439 dprintf(("OPENGL32: Created a new dive-instance (%08X) - pfb %08X - rc was %d",
440 wc->hDiveInstance,
441 wc->ppFrameBuffer,
442 rc));
443
444 if(rc)
445 return FALSE;
446/* For later? Switch to FullScreen mode ...
447 switch( wc->gMode )
448 {
449 case 1: ddrval = DiveSetDisplayMode( wc->lpDD, 640, 480, displayOptions.bpp); break;
450 case 2: ddrval = DiveSetDisplayMode( wc->lpDD, 800, 600, displayOptions.bpp); break;
451 case 3: ddrval = DiveSetDisplayMode( wc->lpDD, 1024, 768, displayOptions.bpp); break;
452 case 4: ddrval = DiveSetDisplayMode( wc->lpDD, 1152, 864, displayOptions.bpp); break;
453 case 5: ddrval = DiveSetDisplayMode( wc->lpDD, 1280, 1024, displayOptions.bpp); break;
454 }
455*/
456
457 /* If in double-buffer mode allocate an offscreen rendering buffer! */
458 if(wc->db_flag)
459 {
460 wc->BackBufferNumber=0;
461
462 wc->awidth=wc->width;
463 wc->aheight=wc->height;
464
465 rc=DiveAllocImageBuffer(wc->hDiveInstance,
466 &wc->BackBufferNumber,
467 GetFOURCC(wc->pixelformat),
468 wc->awidth,
469 wc->aheight,
470 0,
471 0);
472
473 dprintf(("Allocated imagebuffer %d (double-buffered screen). rc is %d",wc->BackBufferNumber,rc));
474
475 if(rc==DIVE_ERR_SOURCE_FORMAT)
476 {
477 /* Darn - the driver doesn't support the format we want! */
478 /* Well, just allocate it ourselves then!! */
479 wc->BackBufferOwnAllocation=TRUE;
480
481 wc->pbPixels=AllocateBuffer(wc->awidth,
482 wc->aheight,
483 wc->pixelformat,
484 &wc->ScanWidth);
485
486 wc->BackBufferNumber=0;
487
488 rc=DiveAllocImageBuffer(wc->hDiveInstance,
489 &wc->BackBufferNumber,
490 GetFOURCC(wc->pixelformat),
491 wc->awidth,
492 wc->aheight,
493 wc->ScanWidth,
494 wc->pbPixels);
495
496 dprintf(("Allocated imagebuffer @%08X. rc is %d",wc->pbPixels,rc));
497 }
498 else
499 {
500 if(rc)
501 {
502 DiveClose(wc->hDiveInstance);
503 wc->hDiveInstance=0;
504
505 return FALSE;
506 }
507 }
508
509 ULONG bsl;
510
511 rc=DiveBeginImageBufferAccess(wc->hDiveInstance,
512 wc->BackBufferNumber,
513 &wc->pbPixels,
514 &wc->ScanWidth,
515 &bsl);
516
517 if(rc)
518 {
519 DiveFree(wc);
520
521 return FALSE;
522 }
523
524 rc=DiveBlitSetup(wc,TRUE);
525
526 if(rc)
527 {
528 DiveFree(wc);
529
530 return FALSE;
531 }
532 }
533
534 return TRUE;
535}
536
537void DiveFree(PWMC wc)
538{
539 ULONG rc;
540
541 if(wc->hDiveInstance!=0)
542 {
543 if(wc->BackBufferNumber) /* A backbuffer allocated??*/
544 {
545 rc=DiveEndImageBufferAccess(wc->hDiveInstance,
546 wc->BackBufferNumber);
547
548 rc=DiveFreeImageBuffer(wc->hDiveInstance,
549 wc->BackBufferNumber);
550
551 }
552
553 wc->BackBufferNumber=0;
554
555 rc=DiveClose(wc->hDiveInstance);
556
557 wc->hDiveInstance=0;
558 }
559}
560
561void _System DiveGlobalInitialize(void)/* Called by INITTERM */
562{
563 DiveQueryCaps(&DiveCaps,DIVE_BUFFER_SCREEN);
564/*
565 WriteLog("OPENGL32: Dive Capabilities\n");
566 WriteLog("OPENGL32: ulPlaneCount %d\n",DiveCaps.ulPlaneCount);
567 WriteLog("OPENGL32: fScreenDirect %d\n",DiveCaps.fScreenDirect);
568 WriteLog("OPENGL32: fBankSwitched %d\n",DiveCaps.fBankSwitched);
569 WriteLog("OPENGL32: ulDepth %d\n",DiveCaps.ulDepth);
570 WriteLog("OPENGL32: ulHorizontalResolution %d\n",DiveCaps.ulHorizontalResolution);
571 WriteLog("OPENGL32: ulVerticalResolution %d\n",DiveCaps.ulVerticalResolution);
572 WriteLog("OPENGL32: ulScanLineBytes %d\n",DiveCaps.ulScanLineBytes);
573 WriteLog("OPENGL32: fccColorEncoding %08X\n",DiveCaps.fccColorEncoding);
574 WriteLog("OPENGL32: ulApertureSize %d\n",DiveCaps.ulApertureSize);
575 WriteLog("OPENGL32: ulInputFormats %d\n",DiveCaps.ulInputFormats);
576 WriteLog("OPENGL32: ulOutputFormats %d\n",DiveCaps.ulOutputFormats);
577 WriteLog("OPENGL32: ulFormatLength %d\n",DiveCaps.ulFormatLength);
578 WriteLog("OPENGL32: pFormatData %08X\n",DiveCaps.pFormatData);
579*/
580}
581
582void _System DiveGlobalTerminate(void)
583{
584 if(Current)
585 {
586 PWMC c=Current;
587
588 Current=0;
589
590 if(c->BackBufferNumber)
591 {
592 ULONG ulb=c->BackBufferNumber;
593
594 c->BackBufferNumber=0;
595
596 DiveEndImageBufferAccess(Current->hDiveInstance,ulb);
597 }
598 }
599}
600
601BOOL _System DiveDirectAccess(void)
602{
603 return DiveCaps.fScreenDirect;
604}
605
606ULONG _System DiveQueryDepth(void)
607{
608 return DiveCaps.ulDepth;
609}
610
611ULONG _System DiveQueryNativePixelFormat(void)
612{
613 switch(DiveCaps.fccColorEncoding)
614 {
615 case FOURCC_LUT8:
616 return PF_INDEX8;
617
618 case FOURCC_BGR4:
619 return PF_8A8B8G8R;
620
621 case FOURCC_RGB3:
622 return PF_8R8G8B;
623
624 case FOURCC_R565:
625 return PF_5R6G5B;
626
627 case FOURCC_GREY:
628 return PF_GRAYSCALE;
629
630 default:
631 break;
632 }
633
634 return 0;
635}
636
637void _System DiveResizeBuffers(GLint width,GLint height)
638{
639 ULONG rc;
640
641 if(!Current)
642 return;
643
644 if(Current->awidth==width && Current->aheight==height)
645 return;
646
647 DiveBlitSetup(Current,FALSE);
648
649 Current->awidth=width;
650 Current->aheight=height;
651
652 if(Current->db_flag)
653 {
654 rc=DiveEndImageBufferAccess(Current->hDiveInstance,
655 Current->BackBufferNumber);
656
657 rc=DiveFreeImageBuffer(Current->hDiveInstance,
658 Current->BackBufferNumber);
659
660 if(Current->BackBufferOwnAllocation)
661 {
662 free(Current->pbPixels);
663
664 Current->pbPixels=AllocateBuffer(Current->awidth,
665 Current->aheight,
666 Current->pixelformat,
667 &Current->ScanWidth);
668
669 Current->BackBufferNumber=0;
670
671 rc=DiveAllocImageBuffer(Current->hDiveInstance,
672 &Current->BackBufferNumber,
673 GetFOURCC(Current->pixelformat),
674 Current->awidth,
675 Current->aheight,
676 Current->ScanWidth,
677 Current->pbPixels);
678
679 ULONG bsl;
680
681 rc=DiveBeginImageBufferAccess(Current->hDiveInstance,
682 Current->BackBufferNumber,
683 &Current->pbPixels,
684 &Current->ScanWidth,
685 &bsl);
686 }
687 else
688 {
689 Current->BackBufferNumber=0;
690
691 rc=DiveAllocImageBuffer(Current->hDiveInstance,
692 &Current->BackBufferNumber,
693 GetFOURCC(Current->pixelformat),
694 Current->awidth,
695 Current->aheight,
696 0,
697 0);
698
699 ULONG bsl;
700
701 rc=DiveBeginImageBufferAccess(Current->hDiveInstance,
702 Current->BackBufferNumber,
703 &Current->pbPixels,
704 &Current->ScanWidth,
705 &bsl);
706 }
707 }
708
709 DiveBlitSetup(Current,TRUE);
710}
711#endif
Note: See TracBrowser for help on using the repository browser.