source: OGRE/trunk/ogrenew/RenderSystems/Direct3D7/src/OgreDDDriver.cpp @ 657

Revision 657, 16.7 KB checked in by mattausch, 18 years ago (diff)

added ogre dependencies and patched ogre sources

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreD3D7RenderSystem.h"
26#include "OgreDDDriver.h"
27#include "OgreDDVideoModeList.h"
28#include "OgreDDVideoMode.h"
29#include "OgreD3D7DeviceList.h"
30#include "OgreD3D7Device.h"
31#include "OgreLogManager.h"
32#include "OgreException.h"
33
34namespace Ogre {
35    DDDriver DDDriver::operator=(const DDDriver &orig)
36    {
37
38
39        mGuid = orig.mGuid;
40        //mDriverDesc = new char(strlen(orig.mDriverDesc) + 1);
41        //strcpy(mDriverDesc, orig.mDriverDesc);
42        mDriverDesc = orig.mDriverDesc;
43        //mDriverName = new char(strlen(orig.mDriverName)+1);
44        //strcpy(mDriverName, orig.mDriverName);
45        mDriverName = orig.mDriverName;
46        mPrimaryDisplay = orig.mPrimaryDisplay;
47        active3DDevice = orig.active3DDevice;
48        activeVideoMode = orig.activeVideoMode;
49        lpD3D = orig.lpD3D;
50        lpDD7 = orig.lpDD7;
51        lpDDClipper = orig.lpDDClipper;
52        lpDDSBack = orig.lpDDSBack;
53        lpDDSPrimary = orig.lpDDSPrimary;
54        mSWCaps = orig.mSWCaps;
55        mHWCaps = orig.mHWCaps;
56        mDeviceList = orig.mDeviceList;
57        mVideoModeList = orig.mVideoModeList;
58
59
60        return *this;
61
62    }
63
64    // Default constructor
65    DDDriver::DDDriver()
66    {
67        // Init pointers
68        active3DDevice = NULL;
69        activeHWnd = 0;
70        activeVideoMode = NULL;
71        lpD3D = NULL;
72        lpDD7 = NULL;
73        lpDDClipper = NULL;
74        lpDDSBack = NULL;
75        lpDDSPrimary = NULL;
76        mDeviceList = NULL;
77        mVideoModeList = NULL;
78
79
80    }
81
82    DDDriver::~DDDriver()
83    {
84        // Delete related system objects
85        if (mDeviceList)
86            delete mDeviceList;
87        if (mVideoModeList)
88            delete mVideoModeList;
89
90    }
91
92
93    // Copy Constructor
94    DDDriver::DDDriver(const DDDriver &ob)
95    {
96
97
98        mGuid = ob.mGuid;
99        //mDriverDesc = new char(strlen(ob.mDriverDesc) + 1);
100        //strcpy(mDriverDesc, ob.mDriverDesc);
101        mDriverDesc = ob.mDriverDesc;
102        //mDriverName = new char(strlen(ob.mDriverName)+1);
103        //strcpy(mDriverName, ob.mDriverName);
104        mDriverName = ob.mDriverName;
105        mPrimaryDisplay = ob.mPrimaryDisplay;
106        active3DDevice = ob.active3DDevice;
107        activeVideoMode = ob.activeVideoMode;
108        lpD3D = ob.lpD3D;
109        lpDD7 = ob.lpDD7;
110        lpDDClipper = ob.lpDDClipper;
111        lpDDSBack = ob.lpDDSBack;
112        lpDDSPrimary = ob.lpDDSPrimary;
113        mSWCaps = ob.mSWCaps;
114        mHWCaps = ob.mHWCaps;
115        mDeviceList = ob.mDeviceList;
116        mVideoModeList = ob.mVideoModeList;
117
118    }
119
120    // Constructor with enumeration details
121    DDDriver::DDDriver(GUID FAR *lpGuid,
122                                LPSTR lpDriverDescription,
123                                LPSTR lpDriverName)
124    {
125        HRESULT hr;
126
127        // Init pointers
128        active3DDevice = NULL;
129        activeHWnd = 0;
130        activeVideoMode = NULL;
131        lpD3D = NULL;
132        lpDD7 = NULL;
133        lpDDClipper = NULL;
134        lpDDSBack = NULL;
135        lpDDSPrimary = NULL;
136        mDeviceList = NULL;
137        mVideoModeList = NULL;
138
139        // Copy GUID, Description and Name
140        // Deal with NULL (default display driver)
141        if (lpGuid)
142        {
143            memcpy(&mGuid, lpGuid, sizeof(GUID));
144            mPrimaryDisplay = false;
145        }
146        else
147            mPrimaryDisplay = true;
148
149
150        mDriverDesc = String(lpDriverDescription);
151        //mDriverDesc = new char(strlen(lpDriverDescription)+1);
152        //strcpy(mDriverDesc, lpDriverDescription);
153
154        mDriverName = String(lpDriverName);
155        //mDriverName = new char(strlen(lpDriverName)+1);
156        //strcpy(mDriverName, lpDriverName);
157
158
159        // Get capabilities
160        mHWCaps.dwSize = sizeof(DDCAPS);
161        mSWCaps.dwSize = sizeof(DDCAPS);
162
163        hr = directDraw()->GetCaps(&mHWCaps, &mSWCaps);
164        if (FAILED(hr))
165            throw Exception(hr, "Cannot get direct draw driver capabilities.",
166                "DIM_DDDriver - directDraw()");
167
168
169    }
170
171    void DDDriver::createWindowSurfaces(HWND hWnd, unsigned int width, unsigned int height, unsigned int colourDepth, bool fullScreen,
172            LPDIRECTDRAWSURFACE7 *front, LPDIRECTDRAWSURFACE7 *back)
173    {
174
175        char msg[150];
176        DWORD dwFlags;
177        DDSURFACEDESC2 ddsd;
178        HRESULT hr;
179        DDSCAPS2 ddscaps;
180        LPDIRECTDRAWCLIPPER clip;
181
182        LogManager::getSingleton().logMessage("Creating DirectDraw surfaces for window with dimensions:");
183
184        if (fullScreen)
185            sprintf(msg, "  FULLSCREEN w:%i h:%i bpp:%i", width, height, colourDepth);
186        else
187            sprintf(msg, "  WINDOWED w:%i h:%i", width, height);
188
189        LogManager::getSingleton().logMessage(msg);
190
191        // Set co-op level
192        if (fullScreen)
193        {
194            dwFlags = DDSCL_FULLSCREEN | DDSCL_EXCLUSIVE;
195        }
196        else
197        {
198            dwFlags = DDSCL_NORMAL;
199        }
200
201        // Also set FPU cooperative mode (optimisation)
202        dwFlags = dwFlags | DDSCL_FPUSETUP;
203
204        hr = directDraw()->SetCooperativeLevel(hWnd, dwFlags);
205        if (FAILED(hr))
206            throw Exception(hr, "Error setting cooperative mode",
207                "DDDriver - createWindowSurfaces");
208
209
210        // Create surfaces
211        // If we're running fullscreen, create a complex flipping
212        // chain surface (implicit back buffer)
213        // Otherwise we need separate back buffers
214
215        if (fullScreen)
216        {
217            // Set Video Mode
218            hr = lpDD7->SetDisplayMode(width, height, colourDepth, 0, 0);
219            if (FAILED(hr))
220                throw Exception(hr, "Unable to set fullScreen display mode.", "DDDriver - createWindowSurfaces");
221
222            // Set up surfaces
223            ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
224            ddsd.dwSize = sizeof(DDSURFACEDESC2);
225            ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
226            ddsd.ddsCaps.dwCaps = DDSCAPS_COMPLEX |
227                DDSCAPS_FLIP | DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
228
229            // Create a single back buffer
230            ddsd.dwBackBufferCount = 1;
231            hr = directDraw()->CreateSurface(&ddsd,front,NULL);
232            if (FAILED(hr))
233                throw Exception(hr, "Error creating linked surface buffers",
234                    "DDDriver - createWindowSurfaces");
235
236            // Get back buffer
237            ZeroMemory(&ddscaps, sizeof(DDSCAPS2));
238            ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
239            hr = (*front)->GetAttachedSurface(&ddscaps, back);
240
241            if (FAILED(hr))
242                throw Exception(hr, "Error retrieving linked back buffer",
243                    "DDDriver - createWindowSurfaces");
244
245            LogManager::getSingleton().logMessage("Successfully created full screen rendering surface / flipping chain.");
246        }
247        else
248        {
249            // Explicitly create front and back buffers, and create
250            // a clipper object
251
252            // Standard non-auto-flip primary
253            ZeroMemory( &ddsd, sizeof(DDSURFACEDESC2) );
254            ddsd.dwSize  = sizeof(DDSURFACEDESC2);
255            ddsd.dwFlags = DDSD_CAPS;
256            ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
257            hr = directDraw()->CreateSurface(&ddsd,front,NULL);
258            if (FAILED(hr))
259                throw Exception(hr, "Error creating primary surface buffer",
260                    "DDDriver - createWindowSurfaces");
261
262
263            // Create offscreen buffer
264            ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
265            ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN |
266                DDSCAPS_3DDEVICE;
267            // Set the dimensions of the back buffer. Note that if our window changes
268            // size, we need to destroy this surface and create a new one.
269            ddsd.dwWidth  = width;
270            ddsd.dwHeight = height;
271            // Create the back buffer. The most likely reason for failure is running
272            // out of video memory. (A more sophisticated app should handle this.)
273            hr = directDraw()->CreateSurface( &ddsd, back, NULL );
274            if( FAILED( hr ) )
275                throw Exception(hr, "Error creating back surface buffer",
276                    "DDDriver - createWindowSurfaces");
277
278            LogManager::getSingleton().logMessage("Windowed mode rendering & display surfaces created.");
279
280            // Create clipper
281            hr = directDraw()->CreateClipper(0, &clip, NULL);
282            if (FAILED(hr))
283                throw Exception(hr, "Error creating clipper",
284                    "DDDriver - createWindowSurfaces");
285
286            // Assign it to the window
287            clip->SetHWnd(0,hWnd);
288            // Assign it to primary surface
289            (*front)->SetClipper(clip);
290            clip->Release();
291
292            LogManager::getSingleton().logMessage("Window clipper created.");
293
294        }
295
296
297
298    }
299
300
301    String DDDriver::DriverName(void) const
302    {
303        return mDriverName;
304    }
305
306    String DDDriver::DriverDescription(void) const
307    {
308        return mDriverDesc;
309    }
310
311    D3DDeviceList* DDDriver::get3DDeviceList(void)
312    {
313        if (!mDeviceList)
314            mDeviceList = new D3DDeviceList(lpD3D);
315
316        return mDeviceList;
317    }
318
319    DDVideoModeList* DDDriver::getVideoModeList(void)
320    {
321        if (!mVideoModeList)
322            mVideoModeList = new DDVideoModeList(lpDD7);
323
324        return mVideoModeList;
325    }
326
327    DDVideoMode* DDDriver::getActiveVideoMode(void)
328    {
329        return activeVideoMode;
330    }
331
332
333    D3DDevice* DDDriver::get3DDevice(void)
334    {
335        return active3DDevice;
336    }
337
338
339    LPDIRECTDRAW7 DDDriver::directDraw()
340    {
341        HRESULT rVal;
342
343        if (!lpDD7)
344        {
345            // We need to create a direct draw object
346            // Create with GUID for this driver
347            if (mPrimaryDisplay)
348                rVal = DirectDrawCreateEx( NULL, (VOID**)&lpDD7, IID_IDirectDraw7, NULL );
349            else
350                rVal = DirectDrawCreateEx( &mGuid, (VOID**)&lpDD7, IID_IDirectDraw7, NULL );
351            if (rVal != DD_OK)
352                throw Exception(rVal, "Cannot create direct draw interface.",
353                    "DIM_DDDriver - directDraw()");
354
355            // Get Direct3D interface too
356            lpDD7->QueryInterface(IID_IDirect3D7, (VOID**)&lpD3D);
357
358
359        }
360
361        return lpDD7;
362    }
363
364    void DDDriver::Cleanup(void)
365    {
366        // Tell 3D Device to clean itself up
367        if (active3DDevice)
368        {
369            active3DDevice->Cleanup();
370        }
371
372        if (activeHWnd && lpDD7)
373            lpDD7->SetCooperativeLevel(activeHWnd, DDSCL_NORMAL);
374
375        // Release DirectX system objects
376
377        if (lpDDSBack)
378        {
379            lpDDSBack->Release();
380            lpDDSBack = NULL;
381        }
382
383        if (lpDDSPrimary)
384        {
385            lpDDSPrimary->Release();
386            lpDDSPrimary = NULL;
387        }
388
389        if (lpD3D)
390        {
391            lpD3D->Release();
392            lpD3D = NULL;
393        }
394
395        if (lpDD7)
396        {
397            lpDD7->Release();
398            lpDD7 = NULL;
399        }
400
401
402
403
404    }
405
406
407    void DDDriver::CheckWindow(void)
408    {
409        // If windowed mode, check window size & position
410        RECT rcCheck;
411
412        if (RunningFullScreen())
413            return;
414
415        GetClientRect( activeHWnd, &rcCheck );
416        ClientToScreen( activeHWnd, (POINT*)&rcCheck.left );
417        ClientToScreen( activeHWnd, (POINT*)&rcCheck.right );
418
419        // Has the window resized? If so, we need to recreate surfaces
420        if ((rcCheck.right - rcCheck.left !=
421                rcViewport.right - rcViewport.left) ||
422            (rcCheck.bottom - rcCheck.top !=
423                rcViewport.bottom - rcViewport.top))
424        {
425            // The window has changed size
426            //g_DIMSystem->CleanupRenderer();
427            //g_DIMSystem->Reinitialise();
428        }
429        else if (rcCheck.left != rcViewport.left ||
430            rcCheck.top != rcViewport.top)
431        {
432            // Window has only moved
433            // Just alter the blit location
434            rcViewport = rcCheck;
435        }
436
437
438    }
439
440
441    void DDDriver::FlipBuffers(void)
442    {
443        HRESULT hr;
444        if (runningFullScreen)
445        {
446            // Use flipping chain
447            hr = lpDDSPrimary->Flip(NULL,DDFLIP_WAIT);
448
449
450        }
451        else
452        {
453            // Ordinary Blit
454            RECT srcRect;
455            srcRect.left = 0;
456            srcRect.top = 0;
457            srcRect.right = rcViewport.right - rcViewport.left;
458            srcRect.bottom = rcViewport.bottom - rcViewport.top;
459            hr = lpDDSPrimary->Blt(&rcViewport,lpDDSBack,&srcRect,DDBLT_WAIT,NULL);
460        }
461
462        if (hr == DDERR_SURFACELOST)
463        {
464            // Restore surfaces
465            RestoreSurfaces();
466        }
467        else
468        {
469            if (FAILED(hr))
470             throw Exception(hr,"Error flipping surfaces", "DDDriver::FlipBuffers");
471        }
472
473    }
474
475    void DDDriver::RestoreSurfaces(void)
476    {
477        HRESULT hr;
478
479        if (lpDDSPrimary->IsLost())
480        {
481            hr = lpDDSPrimary->Restore();
482            if (FAILED(hr))
483                throw Exception(hr, "Error restoring lost primary surface.", "DDDriver - RestoreSurfaces");
484        }
485
486        if (lpDDSBack->IsLost())
487        {
488            hr = lpDDSBack->Restore();
489            if (FAILED(hr))
490                throw Exception(hr, "Error restoring lost back buffer surface.", "DDDriver - RestoreSurfaces");
491        }
492
493    }
494
495    void DDDriver::OutputText(int x, int y, char* text)
496    {
497        HDC hDC;
498
499        // Get a DC for the surface. Then, write out the buffer
500        if( lpDDSBack )
501        {
502            if( SUCCEEDED( lpDDSBack->GetDC(&hDC) ) )
503            {
504                SetTextColor( hDC, RGB(255,255,0) );
505                SetBkMode( hDC, TRANSPARENT );
506                ExtTextOut( hDC, x, y, 0, NULL, text, lstrlen(text), NULL );
507                lpDDSBack->ReleaseDC(hDC);
508            }
509        }
510    }
511
512    bool DDDriver::RunningFullScreen(void) const
513    {
514        return runningFullScreen;
515    }
516
517    RECT DDDriver::ViewportRect(void) const
518    {
519        return rcViewport;
520    }
521
522    bool DDDriver::CanRenderWindowed(void) const
523    {
524        return (mHWCaps.dwCaps2 & DDCAPS2_CANRENDERWINDOWED) > 0;
525    }
526
527
528    bool DDDriver::Has3DAcceleration(void) const
529    {
530        return (mHWCaps.dwCaps & DDCAPS_3D);
531    }
532
533
534
535    void DDDriver::GetDisplayDetails(unsigned int& width, unsigned int& height, unsigned int& colourDepth)
536    {
537        // Get details from primary surface
538        // This works for both windowed and fullscreen modes
539
540        DDSURFACEDESC2 ddsd;
541
542
543        if (lpDDSPrimary)
544        {
545            ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
546            ddsd.dwSize = sizeof(DDSURFACEDESC2);
547            lpDDSPrimary->GetSurfaceDesc(&ddsd);
548
549            width = ddsd.dwWidth;
550            height = ddsd.dwHeight;
551            colourDepth = ddsd.ddpfPixelFormat.dwRGBBitCount;
552        }
553    }
554
555    void DDDriver::logCaps(void) const
556    {
557        // Sends capabilities of this driver to the log
558        char msg[255];
559
560        LogManager::getSingleton().logMessage("DirectDraw Driver Capabilities:");
561
562        sprintf(msg, "  3D Acceleration: %i", Has3DAcceleration());
563        LogManager::getSingleton().logMessage(msg);
564
565        sprintf(msg, "  Render in a window: %i", CanRenderWindowed());
566        LogManager::getSingleton().logMessage(msg);
567
568
569
570    }
571
572}
573
574
Note: See TracBrowser for help on using the repository browser.