From 8eb21d1bac066ac314bdc7fd117f2ef70668f425 Mon Sep 17 00:00:00 2001 From: Rodolfo Osvaldo Bogado Date: Thu, 22 Apr 2010 02:51:07 +0000 Subject: [PATCH] fixed mipmap loading in both plugins. add an option to limit fps instead of vps for games with bad synchronization some minor fixes in d3d gui enjoy :) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5394 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/Core/Src/ConfigManager.cpp | 2 + Source/Core/Core/Src/ConfigManager.h | 1 + Source/Core/Core/Src/Core.cpp | 6 +- Source/Core/DolphinWX/Src/ConfigMain.cpp | 10 ++- Source/Core/DolphinWX/Src/ConfigMain.h | 8 +- .../Plugin_VideoDX9/Src/DlgSettings.cpp | 7 ++ Source/Plugins/Plugin_VideoDX9/Src/Render.cpp | 3 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 6 +- .../Plugin_VideoOGL/Src/TextureMngr.cpp | 79 ++++++++++--------- 9 files changed, 73 insertions(+), 49 deletions(-) diff --git a/Source/Core/Core/Src/ConfigManager.cpp b/Source/Core/Core/Src/ConfigManager.cpp index d82985f980..e9a2e254be 100644 --- a/Source/Core/Core/Src/ConfigManager.cpp +++ b/Source/Core/Core/Src/ConfigManager.cpp @@ -148,6 +148,7 @@ void SConfig::SaveSettings() ini.Set("Core", "RunCompareServer", m_LocalCoreStartupParameter.bRunCompareServer); ini.Set("Core", "RunCompareClient", m_LocalCoreStartupParameter.bRunCompareClient); ini.Set("Core", "FrameLimit", m_Framelimit); + ini.Set("Core", "UseFPS", b_UseFPS); // Plugins ini.Set("Core", "GFXPlugin", m_LocalCoreStartupParameter.m_strVideoPlugin); @@ -276,6 +277,7 @@ void SConfig::LoadSettings() ini.Get("Core", "RunCompareClient", &m_LocalCoreStartupParameter.bRunCompareClient, false); ini.Get("Core", "TLBHack", &m_LocalCoreStartupParameter.iTLBHack, 0); ini.Get("Core", "FrameLimit", &m_Framelimit, 1); // auto frame limit by default + ini.Get("Core", "UseFPS", &b_UseFPS, false); // use vps as default // Plugins ini.Get("Core", "GFXPlugin", &m_LocalCoreStartupParameter.m_strVideoPlugin, m_DefaultGFXPlugin.c_str()); diff --git a/Source/Core/Core/Src/ConfigManager.h b/Source/Core/Core/Src/ConfigManager.h index ca7a6b3411..2b975c204b 100644 --- a/Source/Core/Core/Src/ConfigManager.h +++ b/Source/Core/Core/Src/ConfigManager.h @@ -70,6 +70,7 @@ struct SConfig INTERFACE_LANGUAGE m_InterfaceLanguage; // framelimit choose int m_Framelimit; + bool b_UseFPS; // other interface settings bool m_InterfaceToolbar; bool m_InterfaceStatusbar; diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 270ab1d717..1a4497db25 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -608,13 +608,13 @@ void ScreenShot() void VideoThrottle() { u32 TargetVPS = (SConfig::GetInstance().m_Framelimit > 1) ? - SConfig::GetInstance().m_Framelimit * 10 : VideoInterface::TargetRefreshRate; + SConfig::GetInstance().m_Framelimit * 5 : VideoInterface::TargetRefreshRate; // When frame limit is NOT off if (SConfig::GetInstance().m_Framelimit) { // Make the limiter a bit loose - u32 frametime = DrawnVideo * 1000 / ++TargetVPS; + u32 frametime = ((SConfig::GetInstance().b_UseFPS)? Common::AtomicLoad(DrawnFrame) : DrawnVideo) * 1000 / ++TargetVPS; while ((u32)Timer.GetTimeDifference() < frametime) Common::YieldCPU(); //Common::SleepCurrentThread(1); @@ -692,7 +692,7 @@ void VideoThrottle() // depending on the framelimit set bool report_slow(int skipped) { - u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 10 + u32 TargetFPS = (SConfig::GetInstance().m_Framelimit > 1) ? SConfig::GetInstance().m_Framelimit * 5 : VideoInterface::TargetRefreshRate; u32 frames = Common::AtomicLoad(DrawnFrame); bool fps_slow = (Timer.GetTimeDifference() < (frames + skipped) * 1000 / TargetFPS) ? false : true; diff --git a/Source/Core/DolphinWX/Src/ConfigMain.cpp b/Source/Core/DolphinWX/Src/ConfigMain.cpp index cc3232e7e3..eedcae6aa3 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.cpp +++ b/Source/Core/DolphinWX/Src/ConfigMain.cpp @@ -52,6 +52,7 @@ EVT_BUTTON(wxID_CLOSE, CConfigMain::CloseClick) EVT_CHECKBOX(ID_INTERFACE_CONFIRMSTOP, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_INTERFACE_USEPANICHANDLERS, CConfigMain::CoreSettingsChanged) +EVT_CHECKBOX(ID_FRAMELIMIT_USEFPSFORLIMITING, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_DISPLAY_HIDECURSOR, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_DISPLAY_FULLSCREEN, CConfigMain::CoreSettingsChanged) EVT_CHECKBOX(ID_DISPLAY_RENDERTOMAIN, CConfigMain::CoreSettingsChanged) @@ -185,7 +186,7 @@ void CConfigMain::InitializeGUILists() // Framelimit arrayStringFor_Framelimit.Add(wxT("Off")); arrayStringFor_Framelimit.Add(wxT("Auto")); - for (int i = 20; i <= 120; i += 10) // from 20 to 120 + for (int i = 10; i <= 120; i += 5) // from 10 to 120 arrayStringFor_Framelimit.Add(wxString::Format(wxT("%i"), i)); // Themes @@ -210,6 +211,7 @@ void CConfigMain::InitializeGUIValues() SkipIdle->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bSkipIdle); EnableCheats->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bEnableCheats); Framelimit->SetSelection(SConfig::GetInstance().m_Framelimit); + UseFPSForLimiting->SetValue(SConfig::GetInstance().b_UseFPS); // General - Advanced AlwaysHLE_BS2->SetValue(SConfig::GetInstance().m_LocalCoreStartupParameter.bHLE_BS2); @@ -334,6 +336,7 @@ void CConfigMain::CreateGUIControls() // Framelimit wxStaticText *FramelimitText = new wxStaticText(GeneralPage, ID_FRAMELIMIT_TEXT, wxT("Framelimit :"), wxDefaultPosition, wxDefaultSize); Framelimit = new wxChoice(GeneralPage, ID_FRAMELIMIT, wxDefaultPosition, wxDefaultSize, arrayStringFor_Framelimit, 0, wxDefaultValidator); + UseFPSForLimiting = new wxCheckBox(GeneralPage, ID_FRAMELIMIT_USEFPSFORLIMITING, wxT("Use FPS For Limiting"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); // Core Settings - Advanced wxStaticBoxSizer* sizerCoreType = new wxStaticBoxSizer(wxVERTICAL, GeneralPage, wxT("CPU Emulator Engine")); @@ -347,6 +350,7 @@ void CConfigMain::CreateGUIControls() // Interface settings ConfirmStop = new wxCheckBox(GeneralPage, ID_INTERFACE_CONFIRMSTOP, wxT("Confirm On Stop"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); UsePanicHandlers = new wxCheckBox(GeneralPage, ID_INTERFACE_USEPANICHANDLERS, wxT("Use Panic Handlers"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator); + // Interface Language // At the moment this only changes the language displayed in m_gamelistctrl @@ -373,6 +377,7 @@ void CConfigMain::CreateGUIControls() wxBoxSizer *sFramelimit = new wxBoxSizer(wxHORIZONTAL); sFramelimit->Add(FramelimitText, 0, wxALL | wxALIGN_CENTER, 1); sFramelimit->Add(Framelimit, 0, wxALL | wxEXPAND, 5); + sFramelimit->Add(UseFPSForLimiting, 0, wxALL | wxEXPAND, 5); sbBasic->Add(sFramelimit, 0, wxALL | wxEXPAND, 5); sbAdvanced->Add(AlwaysHLE_BS2, 0, wxALL, 5); @@ -702,6 +707,9 @@ void CConfigMain::CoreSettingsChanged(wxCommandEvent& event) { switch (event.GetId()) { + case ID_FRAMELIMIT_USEFPSFORLIMITING: + SConfig::GetInstance().b_UseFPS = UseFPSForLimiting->IsChecked(); + break; case ID_INTERFACE_CONFIRMSTOP: // Interface SConfig::GetInstance().m_LocalCoreStartupParameter.bConfirmStop = ConfirmStop->IsChecked(); break; diff --git a/Source/Core/DolphinWX/Src/ConfigMain.h b/Source/Core/DolphinWX/Src/ConfigMain.h index 40dcfdaf9e..9d603452d5 100644 --- a/Source/Core/DolphinWX/Src/ConfigMain.h +++ b/Source/Core/DolphinWX/Src/ConfigMain.h @@ -48,7 +48,7 @@ private: DECLARE_EVENT_TABLE(); wxBoxSizer* sGeneralPage; // General Settings - wxCheckBox* ConfirmStop, *UsePanicHandlers; + wxCheckBox* ConfirmStop, *UsePanicHandlers, *UseFPSForLimiting; wxCheckBox* HideCursor; wxChoice* InterfaceLang; wxChoice* Framelimit; @@ -171,14 +171,16 @@ private: ID_ENABLECHEATS, ID_INTERFACE_CONFIRMSTOP, // Interface settings - ID_INTERFACE_USEPANICHANDLERS, + ID_INTERFACE_USEPANICHANDLERS, ID_DISPLAY_FULLSCREEN, ID_DISPLAY_HIDECURSOR, ID_DISPLAY_RENDERTOMAIN, ID_HOTKEY_CONFIG, ID_INTERFACE_LANG_TEXT, ID_INTERFACE_LANG, ID_INTERFACE_THEME, - ID_FRAMELIMIT_TEXT, ID_FRAMELIMIT, + ID_FRAMELIMIT_TEXT, + ID_FRAMELIMIT, + ID_FRAMELIMIT_USEFPSFORLIMITING, ID_GC_SRAM_LNG_TEXT, ID_GC_SRAM_LNG, diff --git a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp index ca8b139cda..8122305cb3 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/DlgSettings.cpp @@ -211,6 +211,13 @@ struct TabAdvanced : public W32Util::Tab g_Config.bUseXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEXFB)) ? true : false; } break; + case IDC_ENABLEREALXFB: + { + g_Config.bUseXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEREALXFB)) ? true : (Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEXFB)) ? true : false); + g_Config.bUseRealXFB = Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEREALXFB)) ? true : false; + Button_GetCheck(GetDlgItem(hDlg, IDC_ENABLEREALXFB)) ? Button_Enable(GetDlgItem(hDlg,IDC_ENABLEXFB), false) : Button_Enable(GetDlgItem(hDlg,IDC_ENABLEXFB), true); + } + break; case IDC_ENABLEEFBCOPY: { Button_GetCheck(GetDlgItem(hDlg,IDC_ENABLEEFBCOPY)) ? Button_Enable(GetDlgItem(hDlg,IDC_EFBTORAM), true) : Button_Enable(GetDlgItem(hDlg,IDC_EFBTORAM), false); diff --git a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp index 4fc041afae..e867d09dd4 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/Render.cpp @@ -219,7 +219,7 @@ static const D3DTEXTUREFILTERTYPE d3dMipFilters[4] = D3DTEXF_NONE, D3DTEXF_POINT, D3DTEXF_LINEAR, - D3DTEXF_LINEAR, //reserved + D3DTEXF_NONE, //reserved }; static const D3DTEXTUREADDRESS d3dClamps[4] = @@ -1402,6 +1402,7 @@ void Renderer::SetSamplerState(int stage, int texindex) min = (tm0.min_filter & 4) ? D3DTEXF_LINEAR : D3DTEXF_POINT; mag = tm0.mag_filter ? D3DTEXF_LINEAR : D3DTEXF_POINT; mip = (tm0.min_filter == 8)?D3DTEXF_NONE:d3dMipFilters[tm0.min_filter & 3]; + if((tm0.min_filter & 3) && (tm0.min_filter != 8) && ((tm1.max_lod >> 4) == 0)) mip = D3DTEXF_NONE; } if (texindex) stage += 4; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 9ade896a72..b41417fcec 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -278,12 +278,12 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, } entry.addr = address; - entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format); + entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format); entry.isRenderTarget = false; bool isPow2 = !((width & (width - 1)) || (height & (height - 1))); entry.isNonPow2 = false; int TexLevels = (width > height)?width:height; - TexLevels = (isPow2 && UseNativeMips && tex_format != GX_TF_CMPR) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : (isPow2?0:1); + TexLevels = (isPow2 && UseNativeMips && (maxlevel > 0)) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : ((isPow2 && g_ActiveConfig.bForceFiltering)? 0 : 1); if(TexLevels > maxlevel && maxlevel > 0) TexLevels = maxlevel; if (!skip_texture_create) @@ -292,7 +292,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, } else { - D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b); + D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, width, height, expandedWidth, d3d_fmt, swap_r_b, 0); } if(TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE) { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 075b3c48b3..ea196cbd57 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -127,11 +127,12 @@ void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode,TexMode1 & glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); - if (bHaveMipMaps) { - int filt = newmode.min_filter; - if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) - newmode.min_filter += 4; // take equivalent forced linear - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + if (bHaveMipMaps) + { + if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4) + mode.min_filter += 4; // take equivalent forced linear + int filt = newmode.min_filter; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & (((newmode1.max_lod >> 4) > 0)?7:4)]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4); //glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/2.0f)); @@ -256,11 +257,11 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width if (address == 0) return NULL; - TexMode0 &tm0 = bpmem.tex[texstage > 3].texMode0[texstage & 3]; - TexMode1 &tm1 = bpmem.tex[texstage > 3].texMode1[texstage & 3]; + TexMode0 &tm0 = bpmem.tex[texstage >> 2].texMode0[texstage & 3]; + TexMode1 &tm1 = bpmem.tex[texstage >> 2].texMode1[texstage & 3]; bool UseNativeMips = (tm0.min_filter & 3) && (tm0.min_filter != 8); - int maxlevel = (tm1.max_lod >> 4); + int maxlevel = ((tm1.max_lod >> 4)); u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; @@ -379,7 +380,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width } entry.addr = address; - entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format); + entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format); entry.isRenderTarget = false; // For static textures, we use NPOT. @@ -394,7 +395,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width bool isPow2 = !((width & (width - 1)) || (height & (height - 1))); int TexLevels = (width > height)?width:height; - TexLevels = (isPow2 && UseNativeMips && tex_format != GX_TF_CMPR) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : (isPow2?0:1); + TexLevels = (isPow2 && UseNativeMips && (maxlevel > 0)) ? (int)(log((double)TexLevels)/log((double)2)) + 1 : 1; if(TexLevels > maxlevel && maxlevel > 0) TexLevels = maxlevel; int gl_format = 0; @@ -403,9 +404,6 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width entry.bHaveMipMaps = UseNativeMips; if (dfmt != PC_TEX_FMT_DXT1) { - if (expandedWidth != width) - glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); - switch (dfmt) { default: @@ -447,24 +445,25 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width gl_type = GL_UNSIGNED_SHORT_5_6_5; break; } + if (expandedWidth != width) + glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); //generate mipmaps even if we use native mips to suport textures with less levels - bool GenerateMipmaps = !entry.isRectangle && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2); - if (GenerateMipmaps) - { - glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE); - } + bool GenerateMipmaps = isPow2 && UseNativeMips && (maxlevel > 0); + entry.bHaveMipMaps = GenerateMipmaps; if(skip_texture_create) { glTexSubImage2D(target, 0,0,0,width, height, gl_format, gl_type, temp); } else { - glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); - } - if (GenerateMipmaps) - { - glTexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); - entry.bHaveMipMaps = true; + if (GenerateMipmaps) + { + gluBuild2DMipmaps(target, gl_iformat, width, height, gl_format, gl_type, temp); + } + else + { + glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); + } } if (expandedWidth != width) // reset @@ -486,41 +485,45 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width if(TexLevels > 1 && dfmt != PC_TEX_FMT_NONE) { int level = 1; - int mipWidth = (width + 1) >> 1; - int mipHeight = (height + 1) >> 1; + int mipWidth = width >> 1; + int mipHeight = height >> 1; ptr += entry.size_in_bytes; - while((mipHeight || mipWidth)) + while((mipHeight || mipWidth) && (level < TexLevels)) { u32 currentWidth = (mipWidth > 0)? mipWidth : 1; u32 currentHeight = (mipHeight > 0)? mipHeight : 1; expandedWidth = (currentWidth + bsw) & (~bsw); expandedHeight = (currentHeight + bsh) & (~bsh); - if(level < TexLevels) - { - TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt); - } - //ugly hack but it seems to work - //complete the level not defined in hardware with pixels of the top levels - //this is not a problem as the level are filtered by lod min and max value + TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt); if (dfmt != PC_TEX_FMT_DXT1) { if (expandedWidth != (int)currentWidth) glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); - glTexImage2D(target, level, gl_iformat, currentWidth, currentHeight, 0, gl_format, gl_type, temp); - if (expandedWidth != (int)currentWidth) // reset + + glTexSubImage2D(target, level,0,0,currentWidth, currentHeight, gl_format, gl_type, temp); + + if (expandedWidth != (int)currentWidth) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { - glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, currentWidth, currentHeight, 0, expandedWidth*expandedHeight/2, temp); + if(skip_texture_create) + { + glCompressedTexSubImage2D(target, level,0,0,currentWidth, currentHeight, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,expandedWidth*expandedHeight/2, temp); + } + else + { + glCompressedTexImage2D(target, level, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, currentWidth, currentHeight, 0, expandedWidth*expandedHeight/2, temp); + } } + GL_REPORT_ERRORD(); u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1; ptr += size; mipWidth >>= 1; mipHeight >>= 1; level++; } - } + } entry.frameCount = frameCount; entry.w = width; entry.h = height;