//============================================================//

// File:		beScreen.cpp

// 

// Date:		10-19-2000

//============================================================//

#include "../header/Render2DCore.h"



//============================================================//

// beScreen()

//============================================================//

beScreen::beScreen()

{

	m_pDDraw			= NULL;

	m_pddsBackBuffer	= NULL;

	m_pddsPrimary		= NULL;

}



//============================================================//

// ~beScreen()

//============================================================//

beScreen::~beScreen()

{

	beSafeRelease(m_pddsPrimary);

	beSafeRelease(m_pDDraw);

}



//============================================================//

// Initialize()

//============================================================//

bool beScreen::Initialize(beScreenParams sparam)

{

	// setup class

	m_ScreenParams = sparam;



    // Create the main DirectDraw object

    HRESULT hRet = DirectDrawCreateEx(NULL, (VOID**)&m_pDDraw, IID_IDirectDraw7, NULL);

    if (FAILED(hRet))

        return false;



	// Initialize surfaces

	if (!InitializeSurfaces())

		return false;	



	InitializeMask();



	return true;

}



//============================================================//

// Delete()

//============================================================//

void beScreen::Delete()

{

    if (m_pDDraw != NULL)

    {

        m_pDDraw->SetCooperativeLevel(m_ScreenParams.m_OwnerWnd, DDSCL_NORMAL);

        if (m_pddsBackBuffer != NULL)

        {

            m_pddsBackBuffer->Release();

            m_pddsBackBuffer = NULL;

        }

        if (m_pddsPrimary != NULL)

        {

            m_pddsPrimary->Release();

            m_pddsPrimary = NULL;

        }

    }

    return;

}



//============================================================//

// InitializeSurfaces()

//============================================================//

bool beScreen::InitializeSurfaces()

{

    HRESULT		        hRet;

    DDSURFACEDESC2      ddsd;

    DDSCAPS2            ddscaps;

    LPDIRECTDRAWCLIPPER pClipper;



    if ( m_ScreenParams.m_Flags & BE_SCREENFLAGS_WINDOWED )

    {

        // Get normal windowed mode

        hRet = m_pDDraw->SetCooperativeLevel(m_ScreenParams.m_OwnerWnd, DDSCL_NORMAL);

        if (hRet != DD_OK)

            return false;



    	// Get the dimensions of the viewport and screen bounds

    	GetClientRect(m_ScreenParams.m_OwnerWnd, &m_rcViewport);

    	GetClientRect(m_ScreenParams.m_OwnerWnd, &m_rcScreen);

    	ClientToScreen(m_ScreenParams.m_OwnerWnd, (POINT*)&m_rcScreen.left);

    	ClientToScreen(m_ScreenParams.m_OwnerWnd, (POINT*)&m_rcScreen.right);



        // Create the primary surface

        ZeroMemory(&ddsd,sizeof(ddsd));

        ddsd.dwSize = sizeof(ddsd);

        ddsd.dwFlags = DDSD_CAPS;

        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

        hRet = m_pDDraw->CreateSurface(&ddsd, &this->m_pddsPrimary, NULL);

        if (hRet != DD_OK)

            return false;



        // Create a clipper object since this is for a Windowed render

        hRet = m_pDDraw->CreateClipper(0, &pClipper, NULL);

        if (hRet != DD_OK)

            return false;



        // Associate the clipper with the window

        

		pClipper->SetHWnd(0, m_ScreenParams.m_OwnerWnd);

        m_pddsPrimary->SetClipper(pClipper);

        pClipper->Release();

        pClipper = NULL;



        // Get the backbuffer. For fullscreen mode, the backbuffer was created

        // along with the primary, but windowed mode still needs to create one.

        ddsd.dwFlags        = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;

        ddsd.dwWidth        = m_ScreenParams.m_iScreenWidth;

        ddsd.dwHeight       = m_ScreenParams.m_iScreenHeight;

        ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

        hRet = m_pDDraw->CreateSurface(&ddsd, &m_pddsBackBuffer, NULL);

        if (hRet != DD_OK)

            return false;



	//	MessageBox(NULL,"AAAAAAAAH","ASH",MB_OK);

	} else {



        // Get exclusive mode

        hRet = m_pDDraw->SetCooperativeLevel(m_ScreenParams.m_OwnerWnd, DDSCL_EXCLUSIVE |

                                                DDSCL_FULLSCREEN);

        if (hRet != DD_OK)

            return false;



        // Set the video mode 

        hRet = m_pDDraw->SetDisplayMode( m_ScreenParams.m_iScreenWidth, m_ScreenParams.m_iScreenHeight, m_ScreenParams.m_iScreenBitCount, 0, 0);

        if (hRet != DD_OK)

            return false;



    	// Get the dimensions of the viewport and screen bounds

    	// Store the rectangle which contains the renderer

    	SetRect(&m_rcViewport, 0, 0, m_ScreenParams.m_iScreenWidth, m_ScreenParams.m_iScreenHeight );

    	memcpy(&m_rcScreen, &m_rcViewport, sizeof(RECT) );



        // Create the primary surface with 1 back buffer

        ZeroMemory(&ddsd,sizeof(ddsd));

        ddsd.dwSize = sizeof(ddsd);

        ddsd.dwFlags = DDSD_CAPS |

                       DDSD_BACKBUFFERCOUNT;

        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE |

                			  DDSCAPS_FLIP |

                			  DDSCAPS_COMPLEX;

        ddsd.dwBackBufferCount = 1;

        hRet = m_pDDraw->CreateSurface( &ddsd, &m_pddsPrimary, NULL);

        if (hRet != DD_OK)

            return false;



        ZeroMemory(&ddscaps, sizeof(ddscaps));

        ddscaps.dwCaps = DDSCAPS_BACKBUFFER;

        hRet = m_pddsPrimary->GetAttachedSurface(&ddscaps, &m_pddsBackBuffer);

        if (hRet != DD_OK)

            return false;

	}



	return true;

}



//============================================================//

// InitializeMask()

//============================================================//

WORD GetNumberOfBits( DWORD dwMask )

{

    WORD wBits = 0;

    while( dwMask )

    {

        dwMask = dwMask & ( dwMask - 1 );

        wBits++;

    }

    return wBits;

}



WORD GetMaskPos( DWORD dwMask )

{

    WORD wPos = 0;

    //while( !(dwMask & (1 << wPos)) ) wPos++;



	while(!(dwMask & 1))

	{

		dwMask >>= 1;

		wPos++;

	}





    return wPos;

}



void beScreen::InitializeMask()

{

    DDPIXELFORMAT ddpf;

    ZeroMemory(&ddpf, sizeof(ddpf));

    ddpf.dwSize = sizeof(ddpf);

    this->GetPrimarySurface()->GetPixelFormat(&ddpf);



	m_wRBits	= GetNumberOfBits(ddpf.dwRBitMask);

	m_wGBits	= GetNumberOfBits(ddpf.dwGBitMask);

	m_wBBits	= GetNumberOfBits(ddpf.dwBBitMask);

	m_wRPos		= GetMaskPos(ddpf.dwRBitMask);

	m_wGPos		= GetMaskPos(ddpf.dwGBitMask);

	m_wBPos		= GetMaskPos(ddpf.dwBBitMask);

}



//============================================================//

// Flip()

//============================================================//

bool beScreen::Flip()

{

    HRESULT result;



    if ( m_ScreenParams.m_Flags & BE_SCREENFLAGS_WINDOWED )

    {

		result = m_pddsPrimary->Blt(&m_rcScreen, m_pddsBackBuffer,

                              NULL, DDBLT_WAIT,

                              NULL);

	} else 

		result = m_pddsPrimary->Flip(NULL, DDFLIP_WAIT);



    if (result == DDERR_SURFACELOST) result = m_pddsPrimary->Restore();

    if (FAILED(result)) return false;



    // success

    return true;

}



//============================================================//

// Move()

//============================================================//

void beScreen::Move()

{

//    GetWindowRect(m_ScreenParams.m_OwnerWnd , &m_rcWindow);

    GetClientRect(m_ScreenParams.m_OwnerWnd , &m_rcViewport);

    GetClientRect(m_ScreenParams.m_OwnerWnd , &m_rcScreen);

    ClientToScreen(m_ScreenParams.m_OwnerWnd , (POINT*)&m_rcScreen.left);

    ClientToScreen(m_ScreenParams.m_OwnerWnd , (POINT*)&m_rcScreen.right);

}

