mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-26 23:10:38 +00:00
Implement 3D texturing in the OpenGL backend too. Assorted fixes.
This commit is contained in:
parent
566385f762
commit
fecf9127a0
@ -59,6 +59,7 @@ void DirectXState::Restore() {
|
||||
texMaxMipLevel.restore(); count++;
|
||||
texAddressU.restore(); count++;
|
||||
texAddressV.restore(); count++;
|
||||
texAddressW.restore(); count++;
|
||||
}
|
||||
|
||||
} // namespace DX9
|
||||
|
@ -393,6 +393,7 @@ public:
|
||||
DxSampler0State1<D3DSAMP_MAXMIPLEVEL, 0> texMaxMipLevel;
|
||||
DxSampler0State1<D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP> texAddressU;
|
||||
DxSampler0State1<D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP> texAddressV;
|
||||
DxSampler0State1<D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP> texAddressW;
|
||||
};
|
||||
|
||||
#undef STATE1
|
||||
|
@ -348,7 +348,17 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
|
||||
GLenum internalFormat, format, type;
|
||||
int alignment;
|
||||
Thin3DFormatToFormatAndType(step.texture_image.format, internalFormat, format, type, alignment);
|
||||
glTexImage2D(tex->target, step.texture_image.level, internalFormat, step.texture_image.width, step.texture_image.height, 0, format, type, step.texture_image.data);
|
||||
if (step.texture_image.depth == 1) {
|
||||
glTexImage2D(tex->target,
|
||||
step.texture_image.level, internalFormat,
|
||||
step.texture_image.width, step.texture_image.height, 0,
|
||||
format, type, step.texture_image.data);
|
||||
} else {
|
||||
glTexImage3D(tex->target,
|
||||
step.texture_image.level, internalFormat,
|
||||
step.texture_image.width, step.texture_image.height, step.texture_image.depth, 0,
|
||||
format, type, step.texture_image.data);
|
||||
}
|
||||
allocatedTextures = true;
|
||||
if (step.texture_image.allocType == GLRAllocType::ALIGNED) {
|
||||
FreeAlignedMemory(step.texture_image.data);
|
||||
@ -364,6 +374,9 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, tex->wrapT);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, tex->magFilter);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, tex->minFilter);
|
||||
if (step.texture_image.depth > 1) {
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
break;
|
||||
}
|
||||
@ -375,7 +388,7 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps, bool ski
|
||||
glBindTexture(tex->target, tex->texture);
|
||||
boundTexture = tex->texture;
|
||||
}
|
||||
if (!gl_extensions.IsGLES || gl_extensions.GLES3) {
|
||||
if ((!gl_extensions.IsGLES || gl_extensions.GLES3) && step.texture_finalize.loadedLevels > 1) {
|
||||
glTexParameteri(tex->target, GL_TEXTURE_MAX_LEVEL, step.texture_finalize.loadedLevels - 1);
|
||||
}
|
||||
tex->maxLod = (float)step.texture_finalize.loadedLevels - 1;
|
||||
@ -1139,28 +1152,28 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (tex->canWrap) {
|
||||
if (tex->wrapS != c.textureSampler.wrapS) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, c.textureSampler.wrapS);
|
||||
tex->wrapS = c.textureSampler.wrapS;
|
||||
}
|
||||
if (tex->wrapT != c.textureSampler.wrapT) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, c.textureSampler.wrapT);
|
||||
tex->wrapT = c.textureSampler.wrapT;
|
||||
}
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (tex->magFilter != c.textureSampler.magFilter) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, c.textureSampler.magFilter);
|
||||
tex->magFilter = c.textureSampler.magFilter;
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (tex->minFilter != c.textureSampler.minFilter) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
|
||||
glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, c.textureSampler.minFilter);
|
||||
tex->minFilter = c.textureSampler.minFilter;
|
||||
}
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
if (tex->anisotropy != c.textureSampler.anisotropy) {
|
||||
if (c.textureSampler.anisotropy != 0.0f) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
|
||||
glTexParameterf(tex->target, GL_TEXTURE_MAX_ANISOTROPY_EXT, c.textureSampler.anisotropy);
|
||||
}
|
||||
tex->anisotropy = c.textureSampler.anisotropy;
|
||||
}
|
||||
@ -1180,16 +1193,16 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
|
||||
}
|
||||
#ifndef USING_GLES2
|
||||
if (tex->lodBias != c.textureLod.lodBias && !gl_extensions.IsGLES) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
|
||||
glTexParameterf(tex->target, GL_TEXTURE_LOD_BIAS, c.textureLod.lodBias);
|
||||
tex->lodBias = c.textureLod.lodBias;
|
||||
}
|
||||
#endif
|
||||
if (tex->minLod != c.textureLod.minLod) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
|
||||
glTexParameterf(tex->target, GL_TEXTURE_MIN_LOD, c.textureLod.minLod);
|
||||
tex->minLod = c.textureLod.minLod;
|
||||
}
|
||||
if (tex->maxLod != c.textureLod.maxLod) {
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
|
||||
glTexParameterf(tex->target, GL_TEXTURE_MAX_LOD, c.textureLod.maxLod);
|
||||
tex->maxLod = c.textureLod.maxLod;
|
||||
}
|
||||
break;
|
||||
@ -1200,6 +1213,7 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step, bool first, bool last
|
||||
// TODO: Need bind?
|
||||
if (!c.texture_subimage.data)
|
||||
Crash();
|
||||
_assert_(tex->target == GL_TEXTURE_2D);
|
||||
// For things to show in RenderDoc, need to split into glTexImage2D(..., nullptr) and glTexSubImage.
|
||||
GLuint internalFormat, format, type;
|
||||
int alignment;
|
||||
|
@ -259,8 +259,9 @@ struct GLRInitStep {
|
||||
GLRTexture *texture;
|
||||
Draw::DataFormat format;
|
||||
int level;
|
||||
int width;
|
||||
int height;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint16_t depth;
|
||||
GLRAllocType allocType;
|
||||
bool linearFilter;
|
||||
uint8_t *data; // owned, delete[]-d
|
||||
|
@ -21,7 +21,7 @@ static bool OnRenderThread() {
|
||||
}
|
||||
#endif
|
||||
|
||||
GLRTexture::GLRTexture(int width, int height, int numMips) {
|
||||
GLRTexture::GLRTexture(int width, int height, int depth, int numMips) {
|
||||
if (gl_extensions.OES_texture_npot) {
|
||||
canWrap = true;
|
||||
} else {
|
||||
@ -29,6 +29,7 @@ GLRTexture::GLRTexture(int width, int height, int numMips) {
|
||||
}
|
||||
w = width;
|
||||
h = height;
|
||||
depth = depth;
|
||||
this->numMips = numMips;
|
||||
}
|
||||
|
||||
|
@ -25,12 +25,13 @@ constexpr int MAX_GL_TEXTURE_SLOTS = 8;
|
||||
|
||||
class GLRTexture {
|
||||
public:
|
||||
GLRTexture(int width, int height, int numMips);
|
||||
GLRTexture(int width, int height, int depth, int numMips);
|
||||
~GLRTexture();
|
||||
|
||||
GLuint texture = 0;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
uint16_t d;
|
||||
|
||||
// We don't trust OpenGL defaults - setting wildly off values ensures that we'll end up overwriting these parameters.
|
||||
GLenum target = 0xFFFF;
|
||||
@ -49,7 +50,7 @@ public:
|
||||
class GLRFramebuffer {
|
||||
public:
|
||||
GLRFramebuffer(int _width, int _height, bool z_stencil)
|
||||
: color_texture(_width, _height, 1), z_stencil_texture(_width, _height, 1),
|
||||
: color_texture(_width, _height, 1, 1), z_stencil_texture(_width, _height, 1, 1),
|
||||
width(_width), height(_height), z_stencil_(z_stencil) {
|
||||
}
|
||||
|
||||
@ -384,9 +385,9 @@ public:
|
||||
// Creation commands. These were not needed in Vulkan since there we can do that on the main thread.
|
||||
// We pass in width/height here even though it's not strictly needed until we support glTextureStorage
|
||||
// and then we'll also need formats and stuff.
|
||||
GLRTexture *CreateTexture(GLenum target, int width, int height, int numMips) {
|
||||
GLRTexture *CreateTexture(GLenum target, int width, int height, int depth, int numMips) {
|
||||
GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE };
|
||||
step.create_texture.texture = new GLRTexture(width, height, numMips);
|
||||
step.create_texture.texture = new GLRTexture(width, height, depth, numMips);
|
||||
step.create_texture.texture->target = target;
|
||||
initSteps_.push_back(step);
|
||||
return step.create_texture.texture;
|
||||
@ -537,7 +538,7 @@ public:
|
||||
}
|
||||
|
||||
// Takes ownership over the data pointer and delete[]-s it.
|
||||
void TextureImage(GLRTexture *texture, int level, int width, int height, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) {
|
||||
void TextureImage(GLRTexture *texture, int level, int width, int height, int depth, Draw::DataFormat format, uint8_t *data, GLRAllocType allocType = GLRAllocType::NEW, bool linearFilter = false) {
|
||||
GLRInitStep step{ GLRInitStepType::TEXTURE_IMAGE };
|
||||
step.texture_image.texture = texture;
|
||||
step.texture_image.data = data;
|
||||
@ -545,6 +546,7 @@ public:
|
||||
step.texture_image.level = level;
|
||||
step.texture_image.width = width;
|
||||
step.texture_image.height = height;
|
||||
step.texture_image.depth = depth;
|
||||
step.texture_image.allocType = allocType;
|
||||
step.texture_image.linearFilter = linearFilter;
|
||||
initSteps_.push_back(step);
|
||||
|
@ -792,7 +792,7 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) :
|
||||
format_ = desc.format;
|
||||
type_ = desc.type;
|
||||
GLenum target = TypeToTarget(desc.type);
|
||||
tex_ = render->CreateTexture(target, desc.width, desc.height, desc.mipLevels);
|
||||
tex_ = render->CreateTexture(target, desc.width, desc.height, 1, desc.mipLevels);
|
||||
|
||||
mipLevels_ = desc.mipLevels;
|
||||
if (desc.initData.empty())
|
||||
@ -877,7 +877,7 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
|
||||
}
|
||||
}
|
||||
|
||||
render_->TextureImage(tex_, level, width, height, format_, texData);
|
||||
render_->TextureImage(tex_, level, width, height, depth, format_, texData);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_READ_PIXELS
|
||||
|
@ -276,8 +276,13 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
WRITE(p, "precision highp int;\n");
|
||||
}
|
||||
|
||||
if (doTexture)
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
if (doTexture) {
|
||||
if (texture3D) {
|
||||
WRITE(p, "uniform sampler3D tex;\n");
|
||||
} else {
|
||||
WRITE(p, "uniform sampler2D tex;\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (readFramebufferTex) {
|
||||
if (!compat.texelFetch) {
|
||||
@ -337,6 +342,11 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
}
|
||||
|
||||
if (texture3D) {
|
||||
*uniformMask |= DIRTY_TEXCLAMP;
|
||||
WRITE(p, "uniform float u_mipBias;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "%s %s lowp vec4 v_color0;\n", shading, compat.varying_fs);
|
||||
if (lmode)
|
||||
WRITE(p, "%s %s lowp vec3 v_color1;\n", shading, compat.varying_fs);
|
||||
|
@ -316,8 +316,9 @@ void ShaderManagerDX9::PSUpdateUniforms(u64 dirtyUniforms) {
|
||||
PSSetFloatArray(CONST_PS_TEXCLAMPOFF, texclampoff, 2);
|
||||
|
||||
float mipBias = (float)gstate.getTexLevelOffset16() * (1.0 / 16.0f);
|
||||
mipBias = (mipBias + 0.5f) / (float)(gstate.getTextureMaxLevel() + 1);
|
||||
|
||||
// NOTE: This equation needs some adjustment in D3D9. Can't get it to look completely smooth :(
|
||||
mipBias = (mipBias + 0.25f) / (float)(gstate.getTextureMaxLevel() + 1);
|
||||
PSSetFloatArray(CONST_PS_MIPBIAS, &mipBias, 1);
|
||||
}
|
||||
}
|
||||
|
@ -98,11 +98,11 @@ GLRTexture *DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, con
|
||||
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
|
||||
|
||||
DepalTexture *tex = new DepalTexture();
|
||||
tex->texture = render_->CreateTexture(GL_TEXTURE_2D, texturePixels, 1, 1);
|
||||
tex->texture = render_->CreateTexture(GL_TEXTURE_2D, texturePixels, 1, 1, 1);
|
||||
|
||||
uint8_t *clutCopy = new uint8_t[1024];
|
||||
memcpy(clutCopy, rawClut, 1024);
|
||||
render_->TextureImage(tex->texture, 0, texturePixels, 1, dstFmt, clutCopy, GLRAllocType::NEW, false);
|
||||
render_->TextureImage(tex->texture, 0, texturePixels, 1, 1, dstFmt, clutCopy, GLRAllocType::NEW, false);
|
||||
|
||||
tex->lastFrame = gpuStats.numFlips;
|
||||
texCache_[clutId] = tex;
|
||||
|
@ -502,8 +502,8 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
prevSizeU = size_u;
|
||||
prevSizeV = size_v;
|
||||
if (!data_tex[0])
|
||||
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1);
|
||||
renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[0], 0, false);
|
||||
}
|
||||
renderManager_->BindTexture(TEX_SLOT_SPLINE_POINTS, data_tex[0]);
|
||||
@ -520,8 +520,8 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
if (prevSizeWU < weights.size_u) {
|
||||
prevSizeWU = weights.size_u;
|
||||
if (!data_tex[1])
|
||||
data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[1], 0, false);
|
||||
}
|
||||
renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_U, data_tex[1]);
|
||||
@ -531,8 +531,8 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
if (prevSizeWV < weights.size_v) {
|
||||
prevSizeWV = weights.size_v;
|
||||
if (!data_tex[2])
|
||||
data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[2], 0, false);
|
||||
}
|
||||
renderManager_->BindTexture(TEX_SLOT_SPLINE_WEIGHTS_V, data_tex[2]);
|
||||
|
@ -144,8 +144,8 @@ GLRTexture *FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4]
|
||||
}
|
||||
}
|
||||
|
||||
GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D, 256, 1, 1);
|
||||
render_->TextureImage(tex, 0, 256, 1, Draw::DataFormat::R8G8B8A8_UNORM, data);
|
||||
GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D, 256, 1, 1, 1);
|
||||
render_->TextureImage(tex, 0, 256, 1, 1, Draw::DataFormat::R8G8B8A8_UNORM, data);
|
||||
return tex;
|
||||
}
|
||||
|
||||
|
@ -174,6 +174,7 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs,
|
||||
queries.push_back({ &u_tess_weights_v, "u_tess_weights_v" });
|
||||
queries.push_back({ &u_spline_counts, "u_spline_counts" });
|
||||
queries.push_back({ &u_depal_mask_shift_off_fmt, "u_depal_mask_shift_off_fmt" });
|
||||
queries.push_back({ &u_mipBias, "u_mipBias" });
|
||||
|
||||
attrMask = vs->GetAttrMask();
|
||||
availableUniforms = vs->GetUniformMask() | fs->GetUniformMask();
|
||||
@ -458,6 +459,13 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
|
||||
}
|
||||
}
|
||||
|
||||
if ((dirty & DIRTY_TEXCLAMP) && u_mipBias != -1) {
|
||||
float mipBias = (float)gstate.getTexLevelOffset16() * (1.0 / 16.0f);
|
||||
mipBias = (mipBias + 0.5f) / (float)(gstate.getTextureMaxLevel() + 1);
|
||||
|
||||
render_->SetUniformF(&u_mipBias, 1, &mipBias);
|
||||
}
|
||||
|
||||
// Transform
|
||||
if (dirty & DIRTY_WORLDMATRIX) {
|
||||
SetMatrix4x3(render_, &u_world, gstate.worldMatrix);
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
int u_cullRangeMin;
|
||||
int u_cullRangeMax;
|
||||
int u_rotation;
|
||||
int u_mipBias;
|
||||
|
||||
#ifdef USE_BONE_ARRAY
|
||||
int u_bone; // array, size is numBones
|
||||
|
@ -451,7 +451,11 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||
dstFmt = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
}
|
||||
|
||||
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, tw, tw, plan.levelsToCreate);
|
||||
if (plan.depth == 1) {
|
||||
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D, tw, tw, 1, plan.levelsToCreate);
|
||||
} else {
|
||||
entry->textureName = render_->CreateTexture(GL_TEXTURE_3D, tw, tw, plan.depth, 1);
|
||||
}
|
||||
|
||||
// Apply some additional compatibility checks.
|
||||
if (plan.levelsToLoad > 1) {
|
||||
@ -468,46 +472,68 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||
plan.levelsToCreate = plan.levelsToLoad;
|
||||
}
|
||||
|
||||
for (int i = 0; i < plan.levelsToLoad; i++) {
|
||||
int srcLevel = i == 0 ? plan.baseLevelSrc : i;
|
||||
if (plan.depth == 1) {
|
||||
for (int i = 0; i < plan.levelsToLoad; i++) {
|
||||
int srcLevel = i == 0 ? plan.baseLevelSrc : i;
|
||||
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
int w = gstate.getTextureWidth(srcLevel);
|
||||
int h = gstate.getTextureHeight(srcLevel);
|
||||
|
||||
u8 *data = nullptr;
|
||||
int stride = 0;
|
||||
u8 *data = nullptr;
|
||||
int stride = 0;
|
||||
|
||||
if (plan.replaced->GetSize(srcLevel, w, h)) {
|
||||
int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format(srcLevel));
|
||||
stride = w * bpp;
|
||||
data = (u8 *)AllocateAlignedMemory(stride * h, 16);
|
||||
} else {
|
||||
if (plan.scaleFactor > 1) {
|
||||
data = (u8 *)AllocateAlignedMemory(4 * (w * plan.scaleFactor) * (h * plan.scaleFactor), 16);
|
||||
stride = w * plan.scaleFactor * 4;
|
||||
} else {
|
||||
int bpp = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2;
|
||||
|
||||
stride = std::max(w * bpp, 4);
|
||||
if (plan.replaced->GetSize(srcLevel, w, h)) {
|
||||
int bpp = (int)Draw::DataFormatSizeInBytes(plan.replaced->Format(srcLevel));
|
||||
stride = w * bpp;
|
||||
data = (u8 *)AllocateAlignedMemory(stride * h, 16);
|
||||
} else {
|
||||
if (plan.scaleFactor > 1) {
|
||||
data = (u8 *)AllocateAlignedMemory(4 * (w * plan.scaleFactor) * (h * plan.scaleFactor), 16);
|
||||
stride = w * plan.scaleFactor * 4;
|
||||
} else {
|
||||
int bpp = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2;
|
||||
|
||||
stride = std::max(w * bpp, 4);
|
||||
data = (u8 *)AllocateAlignedMemory(stride * h, 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
ERROR_LOG(G3D, "Ran out of RAM trying to allocate a temporary texture upload buffer (%dx%d)", w, h);
|
||||
return;
|
||||
}
|
||||
|
||||
LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, dstFmt, true);
|
||||
|
||||
// NOTE: TextureImage takes ownership of data, so we don't free it afterwards.
|
||||
render_->TextureImage(entry->textureName, i, w * plan.scaleFactor, h * plan.scaleFactor, 1, dstFmt, data, GLRAllocType::ALIGNED);
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
ERROR_LOG(G3D, "Ran out of RAM trying to allocate a temporary texture upload buffer (%dx%d)", w, h);
|
||||
return;
|
||||
bool genMips = plan.levelsToCreate > plan.levelsToLoad;
|
||||
|
||||
render_->FinalizeTexture(entry->textureName, plan.levelsToLoad, genMips);
|
||||
} else {
|
||||
int bpp = dstFmt == Draw::DataFormat::R8G8B8A8_UNORM ? 4 : 2;
|
||||
int stride = bpp * (plan.w * plan.scaleFactor);
|
||||
int levelStride = stride * (plan.h * plan.scaleFactor);
|
||||
|
||||
u8 *data = (u8 *)AllocateAlignedMemory(levelStride * plan.depth, 16);
|
||||
memset(data, 0, levelStride * plan.depth);
|
||||
u8 *p = data;
|
||||
|
||||
for (int i = 0; i < plan.depth; i++) {
|
||||
LoadTextureLevel(*entry, p, stride, *plan.replaced, i, plan.scaleFactor, dstFmt, true);
|
||||
p += levelStride;
|
||||
}
|
||||
|
||||
LoadTextureLevel(*entry, data, stride, *plan.replaced, srcLevel, plan.scaleFactor, dstFmt, true);
|
||||
render_->TextureImage(entry->textureName, 0, plan.w * plan.scaleFactor, plan.h * plan.scaleFactor, plan.depth, dstFmt, data, GLRAllocType::ALIGNED);
|
||||
|
||||
// NOTE: TextureImage takes ownership of data, so we don't free it afterwards.
|
||||
render_->TextureImage(entry->textureName, i, w * plan.scaleFactor, h * plan.scaleFactor, dstFmt, data, GLRAllocType::ALIGNED);
|
||||
// Signal that we support depth textures so use it as one.
|
||||
entry->status |= TexCacheEntry::STATUS_3D;
|
||||
|
||||
render_->FinalizeTexture(entry->textureName, 1, false);
|
||||
}
|
||||
|
||||
bool genMips = plan.levelsToCreate > plan.levelsToLoad;
|
||||
|
||||
render_->FinalizeTexture(entry->textureName, plan.levelsToLoad, genMips);
|
||||
|
||||
if (plan.replaced->Valid()) {
|
||||
entry->SetAlphaStatus(TexCacheEntry::TexStatus(plan.replaced->AlphaStatus()));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user