static UINT8 *CreateSurfaceHelper(PDev *pdev, UINT32 surface_id, UINT32 cx, UINT32 cy, ULONG format, UINT8 allocation_type, INT32 *stride, UINT32 *surface_format, QXLPHYSICAL *phys_mem) { UINT32 depth; SurfaceInfo *surface_info = GetSurfaceInfo(pdev, surface_id); UINT8 *base_mem; int size; BitmapFormatToDepthAndSurfaceFormat(format, &depth, surface_format); ASSERT(pdev, depth != 0); ASSERT(pdev, stride); QXLGetSurface(pdev, phys_mem, cx, cy, depth, stride, &base_mem, allocation_type); DEBUG_PRINT((pdev, 3, "%s: %d, pm %0lX, fmt %d, d %d, s (%d, %d) st %d\n", __FUNCTION__, surface_id, (uint64_t)*phys_mem, *surface_format, depth, cx, cy, *stride)); size = abs(*stride) * cy; if (!base_mem) { DEBUG_PRINT((pdev, 0, "%s: %p: %d: QXLGetSurface failed (%d bytes alloc)\n", __FUNCTION__, pdev, surface_id, size)); return NULL; } if (!CreateDrawArea(pdev, base_mem, surface_info->bitmap_format, cx, cy, *stride, surface_id)) { DEBUG_PRINT((pdev, 0, "%s: %p: CreateDrawArea failed (%d)\n", __FUNCTION__, pdev, surface_id, size)); // TODO: Why did it fail? nothing in the MSDN QXLDelSurface(pdev, base_mem, allocation_type); return NULL; } return base_mem; }
static BOOL CreateDrawArea(PDev *pdev, UINT8 *base_mem, ULONG format, UINT32 cx, UINT32 cy, UINT32 stride, UINT32 surface_id) { SIZEL size; DrawArea *drawarea; size.cx = cx; size.cy = cy; drawarea = &GetSurfaceInfo(pdev, surface_id)->draw_area; if (!(drawarea->bitmap = (HSURF)EngCreateBitmap(size, stride, format, 0, base_mem))) { DEBUG_PRINT((pdev, 0, "%s: EngCreateBitmap failed\n", __FUNCTION__)); return FALSE; } if (!EngAssociateSurface(drawarea->bitmap, pdev->eng, 0)) { DEBUG_PRINT((pdev, 0, "%s: EngAssociateSurface failed\n", __FUNCTION__)); goto error; } if (!(drawarea->surf_obj = EngLockSurface(drawarea->bitmap))) { DEBUG_PRINT((pdev, 0, "%s: EngLockSurface failed\n", __FUNCTION__)); goto error; } drawarea->base_mem = base_mem; return TRUE; error: EngDeleteSurface(drawarea->bitmap); return FALSE; }
/* to_surface_id is exclusive */ static void SendSurfaceRangeCreateCommand(PDev *pdev, UINT32 from_surface_id, UINT32 to_surface_id) { UINT32 surface_id; ASSERT(pdev, from_surface_id < to_surface_id); ASSERT(pdev, to_surface_id <= pdev->n_surfaces); for (surface_id = from_surface_id; surface_id < to_surface_id; surface_id++) { SurfaceInfo *surface_info; SURFOBJ *surf_obj; QXLPHYSICAL phys_mem; UINT32 surface_format; UINT32 depth; surface_info = GetSurfaceInfo(pdev, surface_id); if (!surface_info->draw_area.base_mem) { continue; } surf_obj = surface_info->draw_area.surf_obj; if (!surf_obj) { continue; } phys_mem = SurfaceToPhysical(pdev, surface_info->draw_area.base_mem); BitmapFormatToDepthAndSurfaceFormat(surface_info->bitmap_format, &depth, &surface_format); SendSurfaceCreateCommand(pdev, surface_id, surf_obj->sizlBitmap, surface_format, -surface_info->stride, phys_mem, /* the surface is still there, tell server not to erase */ 1); } }
VOID DeleteDeviceBitmap(PDev *pdev, UINT32 surface_id, UINT8 allocation_type) { DrawArea *drawarea; drawarea = &GetSurfaceInfo(pdev,surface_id)->draw_area; FreeDrawArea(drawarea); if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0 && pdev->surfaces_info[surface_id].draw_area.base_mem != NULL) { if (allocation_type == DEVICE_BITMAP_ALLOCATION_TYPE_RAM) { /* server side this surface is already destroyed, just free it here */ ASSERT(pdev, pdev->surfaces_info[surface_id].draw_area.base_mem == pdev->surfaces_info[surface_id].copy); QXLDelSurface(pdev, pdev->surfaces_info[surface_id].draw_area.base_mem, allocation_type); FreeSurfaceInfo(pdev, surface_id); } else { QXLSurfaceCmd *surface_cmd; surface_cmd = SurfaceCmd(pdev, QXL_SURFACE_CMD_DESTROY, surface_id); QXLGetDelSurface(pdev, surface_cmd, surface_id, allocation_type); PushSurfaceCmd(pdev, surface_cmd); } } }
INT CmSurfaceManager::CreateSurface2D(CmOsResource * pCmOsResource, BOOL bIsCmCreated, CmSurface2D * &pSurface2D) { UINT handle = 0; UINT index = m_pCmDevice->ValidSurfaceIndexStart(); INT result = 0; UINT width = 0; UINT height = 0; UINT pitch = 0; CM_SURFACE_FORMAT format = CM_SURFACE_FORMAT_UNKNOWN; if (pCmOsResource == NULL) { return CM_INVALID_GENOS_RESOURCE_HANDLE; } pSurface2D = NULL; result = GetSurfaceInfo(pCmOsResource, width, height, pitch, format); if (result != CM_SUCCESS) { CM_ASSERT(0); return result; } result = Surface2DSanityCheck(width, height, format); if (result != CM_SUCCESS) { CM_ASSERT(0); return result; } if (GetFreeSurfaceIndex(index) != CM_SUCCESS) { CM_ASSERT(0); return CM_EXCEED_SURFACE_AMOUNT; } if (m_2DSurfaceCount >= m_max2DSurfaceCount) { CM_ASSERT(0); return CM_EXCEED_SURFACE_AMOUNT; } result = AllocateSurface2D(width, height, format, pCmOsResource, handle); if (result != CM_SUCCESS) { CM_ASSERT(0); return result; } result = CmSurface2D::Create(index, handle, width, height, pitch, format, bIsCmCreated, this, pSurface2D); if (result != CM_SUCCESS) { FreeSurface2D(handle); CM_ASSERT(0); return result; } m_SurfaceArray[index] = pSurface2D; UPDATE_PROFILE_FOR_2D_SURFACE(index, width, height, format, FALSE); return CM_SUCCESS; }
static void CleanupSurfaceInfo(PDev *pdev, UINT32 surface_id, UINT8 allocation_type) { SurfaceInfo *surface_info = GetSurfaceInfo(pdev, surface_id); FreeDrawArea(&surface_info->draw_area); if (surface_info->draw_area.base_mem != NULL) { QXLDelSurface(pdev, surface_info->draw_area.base_mem, allocation_type); } }
BOOL MoveAllSurfacesToRam(PDev *pdev) { UINT32 surface_id; SurfaceInfo *surface_info; SURFOBJ *surf_obj; UINT8 *copy; UINT8 *line0; int size; QXLPHYSICAL phys_mem; for (surface_id = 1 ; surface_id < pdev->n_surfaces ; ++surface_id) { surface_info = GetSurfaceInfo(pdev, surface_id); if (!surface_info->draw_area.base_mem) { continue; } surf_obj = surface_info->draw_area.surf_obj; if (!surf_obj) { DEBUG_PRINT((pdev, 3, "%s: %d: no surfobj, not copying\n", __FUNCTION__, surface_id)); continue; } size = surf_obj->sizlBitmap.cy * abs(surf_obj->lDelta); copy = EngAllocMem(0, size, ALLOC_TAG); DEBUG_PRINT((pdev, 3, "%s: %d: copying #%d to %p (%d)\n", __FUNCTION__, surface_id, size, copy, surf_obj->lDelta)); RtlCopyMemory(copy, surface_info->draw_area.base_mem, size); surface_info->copy = copy; line0 = surf_obj->lDelta > 0 ? copy : copy + abs(surf_obj->lDelta) * (surf_obj->sizlBitmap.cy - 1); if (!EngModifySurface((HSURF)surface_info->hbitmap, pdev->eng, 0, /* from the example: used to monitor memory HOOK_COPYBITS | HOOK_BITBLT, */ 0, /* It's system-memory */ (DHSURF)surface_info, line0, surf_obj->lDelta, NULL)) { /* Send a create messsage for this surface - we previously did a destroy all. */ EngFreeMem(surface_info->copy); surface_info->copy = NULL; DEBUG_PRINT((pdev, 0, "%s: %d: EngModifySurface failed, sending create for %d-%d\n", __FUNCTION__, surface_id, surface_id, pdev->n_surfaces - 1)); SendSurfaceRangeCreateCommand(pdev, surface_id, pdev->n_surfaces); return FALSE; } QXLDelSurface(pdev, surface_info->draw_area.base_mem, DEVICE_BITMAP_ALLOCATION_TYPE_VRAM); surface_info->draw_area.base_mem = copy; FreeDrawArea(&surface_info->draw_area); } return TRUE; }
HBITMAP CreateDeviceBitmap(PDev *pdev, SIZEL size, ULONG format, QXLPHYSICAL *phys_mem, UINT8 **base_mem, UINT32 surface_id, UINT8 allocation_type) { UINT32 surface_format, depth; HBITMAP hbitmap; INT32 stride; SurfaceInfo *surface_info; DEBUG_PRINT((pdev, 9, "%s: %p: %d, (%dx%d), %d\n", __FUNCTION__, pdev, surface_id, size.cx, size.cy, format)); surface_info = GetSurfaceInfo(pdev, surface_id); if (!(hbitmap = EngCreateDeviceBitmap((DHSURF)surface_info, size, format))) { DEBUG_PRINT((pdev, 0, "%s: EngCreateDeviceBitmap failed, pdev 0x%lx, surface_id=%d\n", __FUNCTION__, pdev, surface_id)); goto out_error1; } if (!EngAssociateSurface((HSURF)hbitmap, pdev->eng, QXL_SURFACE_HOOKS)) { DEBUG_PRINT((pdev, 0, "%s: EngAssociateSurface failed\n", __FUNCTION__)); goto out_error2; } surface_info->u.pdev = pdev; surface_info->hbitmap = hbitmap; surface_info->copy = NULL; surface_info->size = size; surface_info->bitmap_format = format; if ((*base_mem = CreateSurfaceHelper(pdev, surface_id, size.cx, size.cy, format, allocation_type, &stride, &surface_format, phys_mem)) == NULL) { DEBUG_PRINT((pdev, 0, "%s: failed, pdev 0x%lx, surface_id=%d\n", __FUNCTION__, pdev, surface_id)); goto out_error2; } surface_info->stride = stride; if (allocation_type != DEVICE_BITMAP_ALLOCATION_TYPE_SURF0) { SendSurfaceCreateCommand(pdev, surface_id, size, surface_format, -stride, *phys_mem, 0); } return hbitmap; out_error2: EngDeleteSurface((HSURF)hbitmap); out_error1: return 0; }
BOOL MoveSurfaceToVideoRam(PDev *pdev, UINT32 surface_id) { QXLSurfaceCmd *surface; UINT32 surface_format; UINT32 depth; int count_used = 0; int size; INT32 stride = 0; QXLPHYSICAL phys_mem; SurfaceInfo *surface_info = GetSurfaceInfo(pdev, surface_id); UINT32 cx = surface_info->size.cx; UINT32 cy = surface_info->size.cy; UINT8 *base_mem; DEBUG_PRINT((pdev, 3, "%s: %d\n", __FUNCTION__, surface_id)); if ((base_mem = CreateSurfaceHelper(pdev, surface_id, cx, cy, surface_info->bitmap_format, DEVICE_BITMAP_ALLOCATION_TYPE_VRAM, &stride, &surface_format, &phys_mem)) == NULL) { DEBUG_PRINT((pdev, 0, "%s: %p: %d: failed\n", __FUNCTION__, pdev, surface_id)); return FALSE; } size = abs(stride) * cy; if (!EngModifySurface((HSURF)surface_info->hbitmap, pdev->eng, QXL_SURFACE_HOOKS, MS_NOTSYSTEMMEMORY, (DHSURF)surface_info, NULL, 0, NULL)) { DEBUG_PRINT((pdev, 0, "%s: %p: %d: EngModifySurface failed\n", __FUNCTION__, pdev, surface_id)); CleanupSurfaceInfo(pdev, surface_id, DEVICE_BITMAP_ALLOCATION_TYPE_VRAM); return FALSE; } DEBUG_PRINT((pdev, 3, "%s: stride = %d, phys_mem = %0lX, base_mem = %p\n", __FUNCTION__, -stride, (uint64_t)phys_mem, base_mem)); DEBUG_PRINT((pdev, 3, "%s: copy %d bytes to %d\n", __FUNCTION__, size, surface_id)); // Everything allocated, nothing can fail (API wise) from this point RtlCopyMemory(base_mem, surface_info->copy, size); EngFreeMem(surface_info->copy); surface_info->copy = NULL; SendSurfaceCreateCommand(pdev, surface_id, surface_info->size, surface_format, -stride, phys_mem, 1); return TRUE; }
/* when we return from S3 we need to resend all the surface creation commands. * Actually moving the memory vram<->guest is not strictly neccessary since vram * is not reset during the suspend, so contents are not lost */ int MoveAllSurfacesToVideoRam(PDev *pdev) { UINT32 surface_id; SurfaceInfo *surface_info; /* brute force implementation - alternative is to keep an updated used_surfaces list */ DEBUG_PRINT((pdev, 3, "%s %p\n", __FUNCTION__, pdev)); for (surface_id = 1 ; surface_id < pdev->n_surfaces ; ++surface_id) { surface_info = GetSurfaceInfo(pdev, surface_id); if (!surface_info->draw_area.base_mem) { continue; } if (surface_info->u.pdev != pdev) { DEBUG_PRINT((pdev, 3, "%s: %p: not our pdev (%p)\n", __FUNCTION__, pdev, surface_info->u.pdev)); continue; } if (surface_info->draw_area.surf_obj) { DEBUG_PRINT((pdev, 3, "%s: surface_id = %d, surf_obj not empty\n", __FUNCTION__, surface_id)); continue; } if (surface_info->copy == NULL) { DEBUG_PRINT((pdev, 3, "%s: %p: %d: no copy buffer, ignored\n", __FUNCTION__, pdev, surface_id)); continue; } if (!MoveSurfaceToVideoRam(pdev, surface_id)) { /* Some of the surfaces have not been moved to video ram. * they will remain managed by GDI. */ DEBUG_PRINT((pdev, 0, "%s: %p: %d: failed moving to vram\n", __FUNCTION__, pdev, surface_id)); } } return TRUE; }
virtual void Complete_MT() { // loader.LoadPVR_Bind( m_hw_texptr, 0 ); // gEnv->pFileSystem->closeResFile( pTextureFile ); glActiveTexture(GL_TEXTURE0); glGenTextures(1, m_hw_texptr); glBindTexture(GL_TEXTURE_2D, *m_hw_texptr); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, iMipCount); uint32 RowBytes, NumRows; for( int i = 0; i < iMipCount; i++ ) { GetSurfaceInfo( iWidth, iHeight, fmt, NULL, &RowBytes, &NumRows ); { //BYTE* pDestBits = ( BYTE* )LockedRect.pBits; if (IsCompressedTex(fmt)) { glCompressedTexImage2D( GL_TEXTURE_2D, i, fmt, iWidth, iHeight, 0, RowBytes * NumRows, pSrcBits); GLenum error = glGetError(); if (error) { gkLogWarning(_T("bind compress texture error.")); } } else { //uint8* white = new uint8[iWidth * iHeight * 4]; //memset(white, 0xff, iWidth * iHeight * 4); glTexImage2D( GL_TEXTURE_2D, i, fmt, iWidth, iHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, pSrcBits ); //delete white; GLenum error = glGetError(); if (error) { gkLogWarning(_T("bind texture error.")); } } //glPixelStorei(GL_UNPACK_ALIGNMENT, 4); pSrcBits += (RowBytes * NumRows); } GLenum error = glGetError(); if (error) { gkLogWarning(_T("bind texture error.")); } iWidth = iWidth >> 1; iHeight = iHeight >> 1; if( iWidth == 0 ) iWidth = 1; if( iHeight == 0 ) iHeight = 1; } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); gEnv->pFileSystem->closeResFile( pFile ); }
//-------------------------------------------------------------------------------------- static HRESULT CreateTextureFromDDS( ID3D10Device* pDev, DDS_HEADER* pHeader, BYTE* pBitData, UINT BitSize, ID3D10ShaderResourceView** ppSRV, bool bSRGB ) { HRESULT hr = S_OK; UINT iWidth = pHeader->dwWidth; UINT iHeight = pHeader->dwHeight; UINT iMipCount = pHeader->dwMipMapCount; if( 0 == iMipCount ) iMipCount = 1; D3D10_TEXTURE2D_DESC desc; if (( pHeader->ddspf.dwFlags & DDS_FOURCC ) && (MAKEFOURCC( 'D', 'X', '1', '0' ) == pHeader->ddspf.dwFourCC ) ) { DDS_HEADER_DXT10* d3d10ext = (DDS_HEADER_DXT10*)( (char*)pHeader + sizeof(DDS_HEADER) ); desc.ArraySize = d3d10ext->arraySize; desc.Format = d3d10ext->dxgiFormat; // For now, we only support 2D textures if ( d3d10ext->resourceDimension != D3D10_RESOURCE_DIMENSION_TEXTURE2D ) return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } else { desc.ArraySize = 1; desc.Format = GetDXGIFormat( pHeader->ddspf ); if (pHeader->dwCubemapFlags != 0 || (pHeader->dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME) ) { // For now only support 2D textures, not cubemaps or volumes return E_FAIL; } if( desc.Format == DXGI_FORMAT_UNKNOWN ) { D3DFORMAT fmt = GetD3D9Format( pHeader->ddspf ); // Swizzle some RGB to BGR common formats to be DXGI (1.0) supported switch( fmt ) { case D3DFMT_X8R8G8B8: case D3DFMT_A8R8G8B8: { desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; for( UINT i = 0; i < BitSize; i += 4 ) { BYTE a = pBitData[i]; pBitData[i] = pBitData[i + 2]; pBitData[i + 2] = a; } } break; // Need more room to try to swizzle 24bpp or 4bpp formats default: return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ); } } } if ( bSRGB ) desc.Format = MAKE_SRGB( desc.Format ); // Create the texture desc.Width = iWidth; desc.Height = iHeight; desc.MipLevels = iMipCount; desc.SampleDesc.Count = 1; desc.SampleDesc.Quality = 0; desc.Usage = D3D10_USAGE_DEFAULT; desc.BindFlags = D3D10_BIND_SHADER_RESOURCE; desc.CPUAccessFlags = 0; desc.MiscFlags = 0; ID3D10Texture2D* pTex2D; D3D10_SUBRESOURCE_DATA* pInitData = new D3D10_SUBRESOURCE_DATA[iMipCount]; if( !pInitData ) return E_OUTOFMEMORY; UINT NumBytes = 0; UINT RowBytes = 0; UINT NumRows = 0; BYTE* pSrcBits = pBitData; for( UINT j = 0; j < desc.ArraySize; j++ ) { for( UINT i = 0; i < iMipCount; i++ ) { GetSurfaceInfo( iWidth, iHeight, desc.Format, &NumBytes, &RowBytes, &NumRows ); pInitData[i].pSysMem = ( void* )pSrcBits; pInitData[i].SysMemPitch = RowBytes; pSrcBits += NumBytes; iWidth = iWidth >> 1; iHeight = iHeight >> 1; if( iWidth == 0 ) iWidth = 1; if( iHeight == 0 ) iHeight = 1; } } hr = pDev->CreateTexture2D( &desc, pInitData, &pTex2D ); if( SUCCEEDED( hr ) && pTex2D ) { D3D10_SHADER_RESOURCE_VIEW_DESC SRVDesc; ZeroMemory( &SRVDesc, sizeof( SRVDesc ) ); SRVDesc.Format = desc.Format; SRVDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D; SRVDesc.Texture2D.MipLevels = desc.MipLevels; hr = pDev->CreateShaderResourceView( pTex2D, &SRVDesc, ppSRV ); SAFE_RELEASE( pTex2D ); } SAFE_DELETE( pInitData ); return hr; }
//-------------------------------------------------------------------------------------- HRESULT CreateTextureFromDDS( LPDIRECT3DDEVICE9 pDev, DDS_HEADER* pHeader, BYTE* pBitData, UINT BitSize, LPDIRECT3DTEXTURE9* ppTex ) { HRESULT hr = S_OK; D3DLOCKED_RECT LockedRect; UINT iWidth = pHeader->dwWidth; UINT iHeight = pHeader->dwHeight; UINT iMipCount = pHeader->dwMipMapCount; if( 0 == iMipCount ) iMipCount = 1; if (pHeader->dwCubemapFlags != 0 || (pHeader->dwHeaderFlags & DDS_HEADER_FLAGS_VOLUME) ) { // For now only support 2D textures, not cubemaps or volumes return E_FAIL; } D3DFORMAT fmt = GetD3D9Format( pHeader->ddspf ); // Create the texture LPDIRECT3DTEXTURE9 pTexture; LPDIRECT3DTEXTURE9 pStagingTexture; hr = pDev->CreateTexture( iWidth, iHeight, iMipCount, 0, // usage fmt, D3DPOOL_DEFAULT, &pTexture, NULL ); if( FAILED( hr ) ) return hr; hr = pDev->CreateTexture( iWidth, iHeight, iMipCount, 0, // usage fmt, D3DPOOL_SYSTEMMEM, &pStagingTexture, NULL ); if( FAILED( hr ) ) { SAFE_RELEASE( pTexture ); return hr; } // Lock, fill, unlock UINT RowBytes, NumRows; BYTE* pSrcBits = pBitData; for( UINT i = 0; i < iMipCount; i++ ) { GetSurfaceInfo( iWidth, iHeight, fmt, NULL, &RowBytes, &NumRows ); if( SUCCEEDED( pStagingTexture->LockRect( i, &LockedRect, NULL, 0 ) ) ) { BYTE* pDestBits = ( BYTE* )LockedRect.pBits; // Copy stride line by line for( UINT h = 0; h < NumRows; h++ ) { CopyMemory( pDestBits, pSrcBits, RowBytes ); pDestBits += LockedRect.Pitch; pSrcBits += RowBytes; } pStagingTexture->UnlockRect( i ); } iWidth = iWidth >> 1; iHeight = iHeight >> 1; if( iWidth == 0 ) iWidth = 1; if( iHeight == 0 ) iHeight = 1; } hr = pDev->UpdateTexture( pStagingTexture, pTexture ); SAFE_RELEASE( pStagingTexture ); if( FAILED( hr ) ) return hr; // Set the result *ppTex = pTexture; return hr; }
static LPDIRECT3DTEXTURE9 LoadBC45TextureFromFileInMemory(LPDIRECT3DDEVICE9 pDevice, const void *data, int size, bool NONPOW2) { if ((((DDS_HEADER *)data)->ddspf.dwFourCC != FOURCC_ATI1N) && (((DDS_HEADER *)data)->ddspf.dwFourCC != FOURCC_ATI2N)) return NULL; #if 0 // Check if ATI1N is supported hr = lastOBGEDirect3D9->CheckDeviceFormat(AdapterOrdinal, DeviceType, AdapterFormat, 0, D3DRTYPE_TEXTURE, FOURCC_ATI1N); BOOL bATI1NSupported = (hr == D3D_OK); • To check support for ATI2N: // Check if ATI2N is supported HRESULT hr; hr = lastOBGEDirect3D9->CheckDeviceFormat(AdapterOrdinal, DeviceType, AdapterFormat, 0, D3DRTYPE_TEXTURE, FOURCC_ATI2N); BOOL bATI2NSupported = (hr == D3D_OK); #endif LPDIRECT3DTEXTURE9 GPUTexture = NULL; HRESULT res; if (FAILED(res = pDevice->CreateTexture( ((DDS_HEADER *)data)->dwWidth, ((DDS_HEADER *)data)->dwHeight, ((DDS_HEADER *)data)->dwMipMapCount, 0, (D3DFORMAT) ((DDS_HEADER *)data)->ddspf.dwFourCC, D3DPOOL_MANAGED, &GPUTexture, NULL))) return NULL; // Lock, fill, unlock D3DLOCKED_RECT LockedRect; UINT RowBytes, NumRows; BYTE *pSrcBits = (BYTE *)data + sizeof(DDS_HEADER); UINT iWidth = ((DDS_HEADER *)data)->dwWidth; UINT iHeight = ((DDS_HEADER *)data)->dwHeight; UINT iMipCount = ((DDS_HEADER *)data)->dwMipMapCount; DWORD iFourCC = ((DDS_HEADER *)data)->ddspf.dwFourCC; if (0 == iMipCount) iMipCount = 1; for (UINT i = 0; i < iMipCount; i++) { GetSurfaceInfo(iWidth, iHeight, iFourCC, NULL, &RowBytes, &NumRows); if (SUCCEEDED(GPUTexture->LockRect(i, &LockedRect, NULL, 0))) { BYTE *pDestBits = (BYTE *)LockedRect.pBits; #if 1 int size = (iWidth * iHeight * (iFourCC == FOURCC_ATI2N ? 2 : 1)) >> 1; CopyMemory(pDestBits, pSrcBits, size); pDestBits += size; pSrcBits += size; #else // Copy stride line by line for (UINT h = 0; h < NumRows; h++) { CopyMemory(pDestBits, pSrcBits, RowBytes); pDestBits += LockedRect.Pitch; pSrcBits += RowBytes; } #endif GPUTexture->UnlockRect(i); } iWidth = iWidth >> 1; iHeight = iHeight >> 1; if (iWidth == 0) iWidth = 1; if (iHeight == 0) iHeight = 1; }