result CMuli3DRenderTarget::SetDepthBuffer( CMuli3DSurface *i_pDepthBuffer ) { if( i_pDepthBuffer ) { if( i_pDepthBuffer->fmtGetFormat() != m3dfmt_r32f ) { FUNC_FAILING( "CMuli3DRenderTarget::SetDepthBuffer: invalid texture format.\n" ); return e_invalidformat; } if( m_pColorBuffer ) { if( i_pDepthBuffer->iGetWidth() != m_pColorBuffer->iGetWidth() || i_pDepthBuffer->iGetHeight() != m_pColorBuffer->iGetHeight() ) { FUNC_FAILING( "CMuli3DDevice::SetDepthBuffer: depthbuffer and framebuffer dimensions are not equal.\n" ); return e_invalidformat; } } } SAFE_RELEASE( m_pDepthBuffer ); m_pDepthBuffer = i_pDepthBuffer; if( m_pDepthBuffer ) m_pDepthBuffer->AddRef(); return s_ok; }
result CMuli3DVolumeTexture::Create( uint32 i_iWidth, uint32 i_iHeight, uint32 i_iDepth, uint32 i_iMipLevels, m3dformat i_fmtFormat ) { if( !i_iWidth || !i_iHeight || !i_iDepth ) { FUNC_FAILING( "CMuli3DVolumeTexture::Create: texture dimensions are invalid.\n" ); return e_invalidparameters; } if( i_fmtFormat < m3dfmt_r32f || i_fmtFormat > m3dfmt_r32g32b32a32f ) { FUNC_FAILING( "CMuli3DVolumeTexture::Create: invalid format specified.\n" ); return e_invalidformat; } m_fSquaredWidth = (float32)(i_iWidth * i_iWidth); m_fSquaredHeight = (float32)(i_iHeight * i_iHeight); m_fSquaredDepth = (float32)(i_iDepth * i_iDepth); if( !i_iMipLevels ) { // Create a full chain ... uint32 iWidth = i_iWidth, iHeight = i_iHeight, iDepth = i_iDepth; do { ++i_iMipLevels; iWidth >>= 1; iHeight >>= 1; iDepth >>= 1; } while( iWidth && iHeight && iDepth ); }
result CMuli3DPresentTargetAmigaOS4::Create() { m3ddeviceparameters DeviceParameters = m_pParent->GetDeviceParameters(); if( !DeviceParameters.iBackbufferWidth || !DeviceParameters.iBackbufferHeight ) { FUNC_FAILING( "CMuli3DPresentTargetAmigaOS4::Create: invalid backbuffer dimensions have been supplied.\n" ); return e_invalidparameters; } // Allocate buffer: if ( !( m_pBitMap = IP96->p96AllocBitMap( DeviceParameters.iBackbufferWidth, DeviceParameters.iBackbufferHeight, 24, BMF_CLEAR|BMF_DISPLAYABLE, 0, RGBFB_R8G8B8 ) ) ) { FUNC_FAILING( "CMuli3dPresentTargetAmigaOS4::Create: couldn't allocate bitmap.\n"); return e_unknown; } return s_ok; }
result CMuli3DIndexBuffer::GetVertexIndex( uint32 i_iArrayIndex, uint32 &o_iValue ) { switch( m_fmtFormat ) { case m3dfmt_index16: { if( i_iArrayIndex >= m_iLength / 2 ) { FUNC_FAILING( "CMuli3DIndexBuffer::GetVertexIndex: parameter i_iArrayIndex exceeds vertex buffer size.\n" ); return e_invalidparameters; } const uint16 *pData = (const uint16 *)m_pData; o_iValue = pData[i_iArrayIndex]; return s_ok; } case m3dfmt_index32: { if( i_iArrayIndex >= m_iLength / 4 ) { FUNC_FAILING( "CMuli3DIndexBuffer::GetVertexIndex: parameter i_iArrayIndex exceeds vertex buffer size.\n" ); return e_invalidparameters; } const uint32 *pData = (const uint32 *)m_pData; o_iValue = pData[i_iArrayIndex]; return s_ok; } default: // cannot happen FUNC_FAILING( "CMuli3DIndexBuffer::GetVertexIndex: invalid format.\n" ); return e_invalidformat; } }
result CMuli3DIndexBuffer::Create( uint32 i_iLength, m3dformat i_fmtFormat ) { if( !i_iLength ) { FUNC_FAILING( "CMuli3DIndexBuffer::Create: parameter i_iLength is 0.\n" ); return e_invalidparameters; } if( i_fmtFormat != m3dfmt_index16 && i_fmtFormat != m3dfmt_index32 ) { FUNC_FAILING( "CMuli3DIndexBuffer::Create: invalid format specified.\n" ); return e_invalidformat; } m_iLength = i_iLength; m_fmtFormat = i_fmtFormat; m_pData = new byte[i_iLength]; if( !m_pData ) { FUNC_FAILING( "CMuli3DIndexBuffer::Create: out of memory, cannot create index buffer.\n" ); return e_outofmemory; } return s_ok; }
result CMuli3DIndexBuffer::GetPointer( uint32 i_iOffset, void **o_ppData ) { if( !o_ppData ) { FUNC_FAILING( "CMuli3DIndexBuffer::GetPointer: parameter o_ppData points to null.\n" ); return e_invalidparameters; } if( i_iOffset >= m_iLength ) { *o_ppData = 0; FUNC_FAILING( "CMuli3DIndexBuffer::GetPointer: i_iOffset is larger than index buffer length.\n" ); return e_invalidparameters; } *o_ppData = &m_pData[i_iOffset]; return s_ok; }
result CMuli3DRenderTarget::ClearDepthBuffer( float32 i_fDepth, const m3drect *i_pRect ) { if( !m_pDepthBuffer ) { FUNC_FAILING( "CMuli3DRenderTarget::ClearDepthBuffer: no depthbuffer has been set.\n" ); return e_invalidstate; } return m_pDepthBuffer->Clear( vector4( i_fDepth, 0, 0, 0 ), i_pRect ); }
result CMuli3DRenderTarget::ClearColorBuffer( const vector4 &i_vColor, const m3drect *i_pRect ) { if( !m_pColorBuffer ) { FUNC_FAILING( "CMuli3DRenderTarget::ClearColorBuffer: no framebuffer has been set.\n" ); return e_invalidstate; } return m_pColorBuffer->Clear( i_vColor, i_pRect ); }
result CMuli3DPresentTargetWin32::Create() { m3ddeviceparameters DeviceParameters = m_pParent->GetDeviceParameters(); if( !DeviceParameters.iBackbufferWidth || !DeviceParameters.iBackbufferHeight ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: invalid backbuffer dimensions have been supplied.\n" ); return e_invalidparameters; } if( FAILED( DirectDrawCreateEx( 0, (void **)&m_pDirectDraw, IID_IDirectDraw7, 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't create DirectDraw 7 instance.\n" ); return e_unknown; } uint32 iDDFlags = DeviceParameters.bWindowed ? DDSCL_NORMAL : DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN|DDSCL_ALLOWREBOOT; if( FAILED( m_pDirectDraw->SetCooperativeLevel( DeviceParameters.hDeviceWindow, iDDFlags ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't set cooperative level.\n" ); return e_unknown; } if( !DeviceParameters.bWindowed ) { switch( DeviceParameters.iFullscreenColorBits ) { case 16: case 24: case 32: break; default: FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: invalid backbuffer bit-depth specified.\n" ); return e_unknown; } // Go to fullscreen mode if( FAILED( m_pDirectDraw->SetDisplayMode( DeviceParameters.iBackbufferWidth, DeviceParameters.iBackbufferHeight, DeviceParameters.iFullscreenColorBits, 0, 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't set display mode.\n" ); return e_unknown; } } else { // Determine display mode. DDSURFACEDESC2 descSurface; descSurface.dwSize = sizeof( descSurface ); if( FAILED( m_pDirectDraw->GetDisplayMode( &descSurface ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't get display mode.\n" ); return e_unknown; } switch( descSurface.ddpfPixelFormat.dwRGBBitCount ) { case 16: // also handles formats 555(15-bit) and 444(12-bit) { uint16 iNumRedBits, iNumGreenBits, iNumBlueBits; ProcessBits( descSurface.ddpfPixelFormat.dwRBitMask, m_i16bitShift[0], iNumRedBits ); ProcessBits( descSurface.ddpfPixelFormat.dwGBitMask, m_i16bitShift[1], iNumGreenBits ); ProcessBits( descSurface.ddpfPixelFormat.dwBBitMask, m_i16bitShift[2], iNumBlueBits ); m_i16bitMaxVal[0] = (uint16)(( 1 << iNumRedBits ) - 1); m_i16bitMaxVal[1] = (uint16)(( 1 << iNumGreenBits ) - 1); m_i16bitMaxVal[2] = (uint16)(( 1 << iNumBlueBits ) - 1); } break; case 24: case 32: break; default: FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: display modes with colors other than 16-, 24- or 32-bit are not supported!\n" ); return e_unknown; } } if( DeviceParameters.bWindowed ) { // Create a primary surface without a backbuffer - a secondary surface will be used as backbuffer. DDSURFACEDESC2 descSurface; ZeroMemory( &descSurface, sizeof( descSurface ) ); descSurface.dwSize = sizeof( descSurface ); descSurface.dwFlags = DDSD_CAPS; descSurface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; if( FAILED( m_pDirectDraw->CreateSurface( &descSurface, &m_pDirectDrawSurfaces[0], 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't create primary surface.\n" ); return e_unknown; } // Create the secondary surface descSurface.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH; descSurface.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; descSurface.dwWidth = DeviceParameters.iBackbufferWidth; descSurface.dwHeight = DeviceParameters.iBackbufferHeight; if( FAILED( m_pDirectDraw->CreateSurface( &descSurface, &m_pDirectDrawSurfaces[1], 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't create secondary surface.\n" ); return e_unknown; } // Create clipper if( FAILED( m_pDirectDraw->CreateClipper( 0, &m_pDirectDrawClipper, 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't create clipper.\n" ); return e_unknown; } // Set clipper to window if( FAILED( m_pDirectDrawClipper->SetHWnd( 0, DeviceParameters.hDeviceWindow ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't set clipper window handle.\n" ); return e_unknown; } // Attach clipper object to primary surface if( FAILED( m_pDirectDrawSurfaces[0]->SetClipper( m_pDirectDrawClipper ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't attach clipper to primary surface.\n" ); return e_unknown; } } else { // Create a primary surface with one backbuffer if in fullscreen mode. DDSURFACEDESC2 descSurface; ZeroMemory( &descSurface, sizeof( descSurface ) ); descSurface.dwSize = sizeof( descSurface ); descSurface.dwFlags = DDSD_CAPS|DDSD_BACKBUFFERCOUNT; descSurface.dwBackBufferCount = 1; descSurface.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP; if( FAILED( m_pDirectDraw->CreateSurface( &descSurface, &m_pDirectDrawSurfaces[0], 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't create primary surface.\n" ); return e_unknown; } // Get DD backbuffer DDSCAPS2 capsDirectDraw = { DDSCAPS_BACKBUFFER }; if( FAILED( m_pDirectDrawSurfaces[0]->GetAttachedSurface( &capsDirectDraw, &m_pDirectDrawSurfaces[1] ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Create: couldn't access secondary surface.\n" ); return e_unknown; } } return s_ok; }
result CMuli3DPresentTargetLinuxX11::Create() { m3ddeviceparameters DeviceParameters = m_pParent->GetDeviceParameters(); if( !DeviceParameters.iBackbufferWidth || !DeviceParameters.iBackbufferHeight ) { FUNC_FAILING( "CMuli3DPresentTargetLinuxX11::Create: invalid backbuffer dimensions have been supplied.\n" ); return e_invalidparameters; } m_pDisplay = XOpenDisplay( 0 ); if( !m_pDisplay ) { FUNC_FAILING( "CMuli3DPresentTargetLinuxX11::Create: couldn't open X-display.\n" ); return e_unknown; } const int32 iScreen = DefaultScreen( m_pDisplay ); const int32 iDepth = DefaultDepth( m_pDisplay, iScreen ); m_iPixelBytes = 0; int32 iPixmapFormatCount = 0; XPixmapFormatValues *pPixmapFormats = XListPixmapFormats( m_pDisplay, &iPixmapFormatCount ); for( int32 iPixmapFormat = 0; iPixmapFormat < iPixmapFormatCount && !m_iPixelBytes; ++iPixmapFormat ) { if( pPixmapFormats[iPixmapFormat].depth == iDepth ) { switch( pPixmapFormats[iPixmapFormat].bits_per_pixel ) { case 12: m_iPixelBytes = 2; m_i16bitMaxVal[0] = 15; m_i16bitMaxVal[1] = 15; m_i16bitMaxVal[2] = 15; m_i16bitShift[0] = 8; m_i16bitShift[1] = 4; m_i16bitShift[2] = 0; break; case 15: m_iPixelBytes = 2; m_i16bitMaxVal[0] = 31; m_i16bitMaxVal[1] = 31; m_i16bitMaxVal[2] = 31; m_i16bitShift[0] = 10; m_i16bitShift[1] = 5; m_i16bitShift[2] = 0; break; case 16: m_iPixelBytes = 2; m_i16bitMaxVal[0] = 31; m_i16bitMaxVal[1] = 63; m_i16bitMaxVal[2] = 31; m_i16bitShift[0] = 11; m_i16bitShift[1] = 5; m_i16bitShift[2] = 0; break; case 24: m_iPixelBytes = 3; break; case 32: m_iPixelBytes = 4; break; default: break; } } } XFree( pPixmapFormats ); if( !m_iPixelBytes ) { XCloseDisplay( m_pDisplay ); m_pDisplay = 0; FUNC_FAILING( "CMuli3DPresentTargetLinuxX11::Create: invalid pixel-depth! Make sure you're running in 16-, 24- or 32bits color-mode.\n" ); return e_unknown; } m_WindowGC = DefaultGC( m_pDisplay, iScreen ); m_pXImage = XCreateImage( m_pDisplay, CopyFromParent, iDepth, ZPixmap, 0, 0, DeviceParameters.iBackbufferWidth, DeviceParameters.iBackbufferHeight, 32, DeviceParameters.iBackbufferWidth * m_iPixelBytes ); if( !m_pXImage ) { FUNC_FAILING( "CMuli3DPresentTargetLinuxX11::Create: couldn't create X-image.\n" ); XCloseDisplay( m_pDisplay ); m_pDisplay = 0; return e_unknown; } m_pXImage->data = new char[DeviceParameters.iBackbufferWidth * DeviceParameters.iBackbufferHeight * m_iPixelBytes]; if( !m_pXImage->data ) { XDestroyImage( m_pXImage ); m_pXImage = 0; XCloseDisplay( m_pDisplay ); m_pDisplay = 0; FUNC_FAILING( "CMuli3DPresentTargetLinuxX11::Create: couldn't allocate memory for backbuffer.\n" ); return e_outofmemory; } return s_ok; }
result CMuli3DPresentTargetWin32::Present( const float32 *i_pSource, uint32 i_iFloats ) { m3ddeviceparameters DeviceParameters = m_pParent->GetDeviceParameters(); // Check for lost DirectDraw surfaces ------------------------------------- if( m_bDDSurfaceLost ) { m_pDirectDrawSurfaces[0]->Restore(); if( DeviceParameters.bWindowed ) m_pDirectDrawSurfaces[1]->Restore(); m_bDDSurfaceLost = false; } // Lock backbuffer-surface------------------------------------------------- DDSURFACEDESC2 descSurface; descSurface.dwSize = sizeof( DDSURFACEDESC2 ); if( FAILED( m_pDirectDrawSurfaces[1]->Lock( 0, &descSurface, DDLOCK_WAIT|DDLOCK_NOSYSLOCK|DDLOCK_WRITEONLY, 0 ) ) ) { FUNC_FAILING( "CMuli3DPresentTargetWin32::Present: couldn't lock secondary surface.\n" ); return e_unknown; } const uint32 iDestBytes = descSurface.ddpfPixelFormat.dwRGBBitCount / 8; // Copy pixels to the backbuffer-surface ---------------------------------- const uint32 iDestRowJump = descSurface.lPitch - iDestBytes * DeviceParameters.iBackbufferWidth; uint8 *pDestination = (uint8 *)descSurface.lpSurface; fpuTruncate(); if( iDestBytes == 2 ) { // 16-bit uint32 iHeight = DeviceParameters.iBackbufferHeight; while( iHeight-- ) { uint32 iWidth = DeviceParameters.iBackbufferWidth; while( iWidth-- ) { const int32 iR = iClamp( ftol( i_pSource[0] * m_i16bitMaxVal[0] ), 0, m_i16bitMaxVal[0] ); const int32 iG = iClamp( ftol( i_pSource[1] * m_i16bitMaxVal[1] ), 0, m_i16bitMaxVal[1] ); const int32 iB = iClamp( ftol( i_pSource[2] * m_i16bitMaxVal[2] ), 0, m_i16bitMaxVal[2] ); i_pSource += i_iFloats; *((uint16 *)pDestination) = ( iR << m_i16bitShift[0] ) | ( iG << m_i16bitShift[1] ) | ( iB << m_i16bitShift[2] ); pDestination += 2; } pDestination += iDestRowJump; } } else { // 24- or 32-bit uint32 iHeight = DeviceParameters.iBackbufferHeight; while( iHeight-- ) { uint32 iWidth = DeviceParameters.iBackbufferWidth; while( iWidth-- ) { pDestination[0] = iClamp( ftol( i_pSource[2] * 255.0f ), 0, 255 ); // b pDestination[1] = iClamp( ftol( i_pSource[1] * 255.0f ), 0, 255 ); // g pDestination[2] = iClamp( ftol( i_pSource[0] * 255.0f ), 0, 255 ); // r i_pSource += i_iFloats; pDestination += iDestBytes; } pDestination += iDestRowJump; } } fpuReset(); // Unlock backbuffer-surface and surface m_pDirectDrawSurfaces[1]->Unlock( 0 ); // Present the image to the screen ---------------------------------------- if( DeviceParameters.bWindowed ) { POINT pntTopLeft = { 0, 0 }; ClientToScreen( DeviceParameters.hDeviceWindow, &pntTopLeft ); RECT rctDestination; GetClientRect( DeviceParameters.hDeviceWindow, &rctDestination ); OffsetRect( &rctDestination, pntTopLeft.x, pntTopLeft.y ); RECT rctSource; SetRect( &rctSource, 0, 0, DeviceParameters.iBackbufferWidth, DeviceParameters.iBackbufferHeight ); // Blt secondary to primary surface if( FAILED( m_pDirectDrawSurfaces[0]->Blt( &rctDestination, m_pDirectDrawSurfaces[1], &rctSource, DDBLT_WAIT, 0 ) ) ) { m_bDDSurfaceLost = true; FUNC_FAILING( "CMuli3DPresentTargetWin32::Present: primary surfaces have been lost!\n" ); return e_unknown; } } else { if( FAILED( m_pDirectDrawSurfaces[0]->Flip( 0, DDFLIP_WAIT ) ) ) { m_bDDSurfaceLost = true; FUNC_FAILING( "CMuli3DPresentTargetWin32::Present: surfaces have been lost!\n" ); return e_unknown; } } return s_ok; }