aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Texture.cpp
diff options
context:
space:
mode:
authordaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
committerdaoge_cmd <3523206925@qq.com>2026-03-01 12:16:08 +0800
commitb691c43c44ff180d10e7d4a9afc83b98551ff586 (patch)
tree3e9849222cbc6ba49f2f1fc6e5fe7179632c7390 /Minecraft.Client/Texture.cpp
parentdef8cb415354ac390b7e89052a50605285f1aca9 (diff)
Initial commit
Diffstat (limited to 'Minecraft.Client/Texture.cpp')
-rw-r--r--Minecraft.Client/Texture.cpp899
1 files changed, 899 insertions, 0 deletions
diff --git a/Minecraft.Client/Texture.cpp b/Minecraft.Client/Texture.cpp
new file mode 100644
index 00000000..e287c177
--- /dev/null
+++ b/Minecraft.Client/Texture.cpp
@@ -0,0 +1,899 @@
+#include "stdafx.h"
+#include "..\Minecraft.World\ByteBuffer.h"
+#include "Rect2i.h"
+#include "TextureManager.h"
+#include "Texture.h"
+
+#ifdef __PS3__
+#include "PS3\SPU_Tasks\Texture_blit\Texture_blit.h"
+#include "C4JSpursJob.h"
+static const int sc_maxTextureBlits = 256;
+static Texture_blit_DataIn g_textureBlitDataIn[sc_maxTextureBlits] __attribute__((__aligned__(16)));
+static int g_currentTexBlit = 0;
+C4JSpursJobQueue::Port* g_texBlitJobQueuePort;
+#endif //__PS3__
+
+#define MAX_MIP_LEVELS 5
+
+Texture::Texture(const wstring &name, int mode, int width, int height, int depth, int wrapMode, int format, int minFilter, int magFilter, bool mipMap)
+{
+ _init(name, mode, width, height, depth, wrapMode, format, minFilter, magFilter, mipMap);
+}
+
+void Texture::_init(const wstring &name, int mode, int width, int height, int depth, int wrapMode, int format, int minFilter, int magFilter, bool mipMap)
+{
+#ifdef __PS3__
+ if(g_texBlitJobQueuePort == NULL)
+ g_texBlitJobQueuePort = new C4JSpursJobQueue::Port("C4JSpursJob_Texture_blit");
+#endif
+ this->name = name;
+ this->mode = mode;
+ this->width = width;
+ this->height = height;
+ this->depth = depth;
+ this->format = format;
+ this->minFilter = minFilter;
+ this->magFilter = magFilter;
+ this->wrapMode = wrapMode;
+ immediateUpdate = false;
+ m_bInitialised = false;
+ for( int i = 0 ; i < 10; i++ )
+ {
+ data[i] = NULL;
+ }
+
+ rect = new Rect2i(0, 0, width, height);
+ // 4J Removed 1D and 3D
+ //if (height == 1 && depth == 1)
+ //{
+ // type = GL_TEXTURE_1D;
+ //}
+ //else if(depth == 1)
+ //{
+ type = GL_TEXTURE_2D;
+ //}
+ //else
+ //{
+ // type = GL_TEXTURE_3D;
+ //}
+
+ mipmapped = mipMap || (minFilter != GL_NEAREST && minFilter != GL_LINEAR) ||
+ (magFilter != GL_NEAREST && magFilter != GL_LINEAR);
+ m_iMipLevels=1;
+
+ if(mipmapped)
+ {
+ // 4J-PB - In the new XDK, the CreateTexture will fail if the number of mipmaps is higher than the width & height passed in will allow!
+ int iWidthMips=1;
+ int iHeightMips=1;
+ while((8<<iWidthMips)<width) iWidthMips++;
+ while((8<<iHeightMips)<height) iHeightMips++;
+
+ m_iMipLevels=(iWidthMips<iHeightMips)?iWidthMips:iHeightMips;
+
+ // TODO - The render libs currently limit max mip map levels to 5
+ if(m_iMipLevels > MAX_MIP_LEVELS) m_iMipLevels = MAX_MIP_LEVELS;
+ }
+
+#ifdef __PSVITA__
+ // vita doesn't have a mipmap conditional shader because it's too slow so make sure this texture don't look awful at the lower mips
+ if( name == L"terrain" )
+ {
+ m_iMipLevels = 3;
+ }
+#endif
+
+ if (mode != TM_CONTAINER)
+ {
+ glId = glGenTextures();
+
+ glBindTexture(type, glId);
+ glTexParameteri(type, GL_TEXTURE_MIN_FILTER, minFilter);
+ glTexParameteri(type, GL_TEXTURE_MAG_FILTER, magFilter);
+ glTexParameteri(type, GL_TEXTURE_WRAP_S, wrapMode);
+ glTexParameteri(type, GL_TEXTURE_WRAP_T, wrapMode);
+ }
+ else
+ {
+ glId = -1;
+ }
+
+ managerId = TextureManager::getInstance()->createTextureID();
+}
+
+void Texture::_init(const wstring &name, int mode, int width, int height, int depth, int wrapMode, int format, int minFilter, int magFilter, BufferedImage *image, bool mipMap)
+{
+ _init(name, mode, width, height, depth, wrapMode, format, minFilter, magFilter, mipMap);
+ if (image == NULL)
+ {
+ if (width == -1 || height == -1)
+ {
+ valid = false;
+ }
+ else
+ {
+ byteArray tempBytes = byteArray(width * height * depth * 4);
+ for (int index = 0; index < tempBytes.length; index++)
+ {
+ tempBytes[index] = 0;
+ }
+#ifdef __PS3__
+ data[0] = new ByteBuffer_IO(tempBytes.length);
+#else
+ data[0] = ByteBuffer::allocateDirect(tempBytes.length);
+#endif // __{S3__
+ data[0]->clear();
+ data[0]->put(tempBytes);
+ data[0]->position(0)->limit(tempBytes.length);
+
+ delete [] tempBytes.data;
+
+ if(mipmapped)
+ {
+ for(unsigned int level = 1; level < m_iMipLevels; ++level)
+ {
+ int ww = width >> level;
+ int hh = height >> height;
+
+ byteArray tempBytes = byteArray(ww * hh * depth * 4);
+ for (int index = 0; index < tempBytes.length; index++)
+ {
+ tempBytes[index] = 0;
+ }
+
+#ifdef __PS3__
+ data[level] = new ByteBuffer_IO(tempBytes.length);
+#else
+ data[level] = ByteBuffer::allocateDirect(tempBytes.length);
+#endif // __PS3__
+ data[level]->clear();
+ data[level]->put(tempBytes);
+ data[level]->position(0)->limit(tempBytes.length);
+
+ delete [] tempBytes.data;
+ }
+ }
+
+ if (immediateUpdate)
+ {
+ updateOnGPU();
+ }
+ else
+ {
+ updated = false;
+ }
+ }
+ }
+ else
+ {
+ valid = true;
+
+ transferFromImage(image);
+
+ if (mode != TM_CONTAINER)
+ {
+ updateOnGPU();
+ immediateUpdate = false;
+ }
+ }
+}
+
+Texture::Texture(const wstring &name, int mode, int width, int height, int wrapMode, int format, int minFilter, int magFilter, BufferedImage *image, bool mipMap)
+{
+ _init(name, mode, width, height, 1, wrapMode, format, minFilter, magFilter, image, mipMap);
+}
+
+Texture::Texture(const wstring &name, int mode, int width, int height, int depth, int wrapMode, int format, int minFilter, int magFilter, BufferedImage *image, bool mipMap)
+{
+ _init(name, mode, width, height, depth, wrapMode, format, minFilter, magFilter, image, mipMap);
+}
+
+Texture::~Texture()
+{
+ delete rect;
+
+ for(int i = 0; i < 10; i++ )
+ {
+ if(data[i] != NULL) delete data[i];
+ }
+
+ if(glId >= 0)
+ {
+ glDeleteTextures(glId);
+ }
+}
+
+const Rect2i *Texture::getRect()
+{
+ return rect;
+}
+
+void Texture::fill(const Rect2i *rect, int color)
+{
+ // 4J Remove 3D
+ //if (type == GL_TEXTURE_3D)
+ //{
+ // return;
+ //}
+
+ Rect2i *myRect = new Rect2i(0, 0, width, height);
+ myRect->intersect(rect);
+ data[0]->position(0);
+ for (int y = myRect->getY(); y < (myRect->getY() + myRect->getHeight()); y++)
+ {
+ int line = y * width * 4;
+ for (int x = myRect->getX(); x < (myRect->getX() + myRect->getWidth()); x++)
+ {
+ data[0]->put(line + x * 4 + 0, (BYTE)((color >> 24) & 0x000000ff));
+ data[0]->put(line + x * 4 + 1, (BYTE)((color >> 16) & 0x000000ff));
+ data[0]->put(line + x * 4 + 2, (BYTE)((color >> 8) & 0x000000ff));
+ data[0]->put(line + x * 4 + 3, (BYTE)((color >> 0) & 0x000000ff));
+ }
+ }
+ delete myRect;
+
+ if (immediateUpdate)
+ {
+ updateOnGPU();
+ }
+ else
+ {
+ updated = false;
+ }
+}
+
+void Texture::writeAsBMP(const wstring &name)
+{
+ // 4J Don't need
+#if 0
+ if (type == GL_TEXTURE_3D)
+ {
+ return;
+ }
+
+ File *outFile = new File(name);
+ if (outFile.exists())
+ {
+ outFile.delete();
+ }
+
+ DataOutputStream *outStream = NULL;
+ //try {
+ outStream = new DataOutputStream(new FileOutputStream(outFile));
+ //} catch (IOException e) {
+ // Unable to open file for writing for some reason
+ // return;
+ //}
+
+ //try {
+ // Write the header
+ outStream->writeShort((short)0x424d); // 0x0000: ID - 'BM'
+ int byteSize = width * height * 4 + 54;
+ outStream->writeByte((byte)(byteSize >> 0)); // 0x0002: Raw file size
+ outStream->writeByte((byte)(byteSize >> 8));
+ outStream->writeByte((byte)(byteSize >> 16));
+ outStream->writeByte((byte)(byteSize >> 24));
+ outStream->writeInt(0); // 0x0006: Reserved
+ outStream->writeByte(54); // 0x000A: Start of pixel data
+ outStream->writeByte(0);
+ outStream->writeByte(0);
+ outStream->writeByte(0);
+ outStream->writeByte(40); // 0x000E: Size of secondary header
+ outStream->writeByte(0);
+ outStream->writeByte(0);
+ outStream->writeByte(0);
+ outStream->writeByte((byte)(width >> 0)); // 0x0012: Image width, in pixels
+ outStream->writeByte((byte)(width >> 8));
+ outStream->writeByte((byte)(width >> 16));
+ outStream->writeByte((byte)(width >> 24));
+ outStream->writeByte((byte)(height >> 0)); // 0x0016: Image height, in pixels
+ outStream->writeByte((byte)(height >> 8));
+ outStream->writeByte((byte)(height >> 16));
+ outStream->writeByte((byte)(height >> 24));
+ outStream->writeByte(1); // 0x001A: Number of color planes, must be 1
+ outStream->writeByte(0);
+ outStream->writeByte(32); // 0x001C: Bit depth (32bpp)
+ outStream->writeByte(0);
+ outStream->writeInt(0); // 0x001E: Compression mode (BI_RGB, uncompressed)
+ int bufSize = width * height * 4;
+ outStream->writeInt((byte)(bufSize >> 0)); // 0x0022: Raw size of bitmap data
+ outStream->writeInt((byte)(bufSize >> 8));
+ outStream->writeInt((byte)(bufSize >> 16));
+ outStream->writeInt((byte)(bufSize >> 24));
+ outStream->writeInt(0); // 0x0026: Horizontal resolution in ppm
+ outStream->writeInt(0); // 0x002A: Vertical resolution in ppm
+ outStream->writeInt(0); // 0x002E: Palette size (0 to match bit depth)
+ outStream->writeInt(0); // 0x0032: Number of important colors, 0 for all
+
+ // Pixels follow in inverted Y order
+ byte[] bytes = new byte[width * height * 4];
+ data.position(0);
+ data.get(bytes);
+ for (int y = height - 1; y >= 0; y--)
+ {
+ int line = y * width * 4;
+ for (int x = 0; x < width; x++)
+ {
+ outStream->writeByte(bytes[line + x * 4 + 2]);
+ outStream->writeByte(bytes[line + x * 4 + 1]);
+ outStream->writeByte(bytes[line + x * 4 + 0]);
+ outStream->writeByte(bytes[line + x * 4 + 3]);
+ }
+ }
+
+ outStream->close();
+ //} catch (IOException e) {
+ // Unable to write to the file for some reason
+ // return;
+ //}
+#endif
+}
+
+void Texture::writeAsPNG(const wstring &filename)
+{
+ // 4J Don't need
+#if 0
+ BufferedImage *image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ ByteBuffer *buffer = this->getData();
+ byte[] bytes = new byte[width * height * 4];
+
+ buffer.position(0);
+ buffer.get(bytes);
+
+ for (int x = 0; x < width; x++)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ int pos = (y * width * 4) + x * 4;
+ int col = 0;
+
+ col |= (bytes[pos + 2] & 0xFF) << 0;
+ col |= (bytes[pos + 1] & 0xFF) << 8;
+ col |= (bytes[pos + 0] & 0xFF) << 16;
+ col |= (bytes[pos + 3] & 0xFF) << 24;
+
+ image.setRGB(x, y, col);
+ }
+ }
+
+ data.position(width * height * 4);
+
+ //try {
+ ImageIO::write(image, L"png", new File(Minecraft.getWorkingDirectory(), filename));
+ //} catch (IOException e) {
+ // e.printStackTrace();
+ //}
+#endif
+}
+
+void Texture::blit(int x, int y, Texture *source)
+{
+ blit(x, y, source, false);
+}
+
+void Texture::blit(int x, int y, Texture *source, bool rotated)
+{
+ // 4J Remove 3D
+ //if (type == GL_TEXTURE_3D)
+ //{
+ // return;
+ //}
+
+ for(unsigned int level = 0; level < m_iMipLevels; ++level)
+ {
+ ByteBuffer *srcBuffer = source->getData(level);
+
+ if(srcBuffer == NULL) break;
+
+ int yy = y >> level;
+ int xx = x >> level;
+ int hh = height >> level;
+ int ww = width >> level;
+ int shh = source->getHeight() >> level;
+ int sww = source->getWidth() >> level;
+
+ data[level]->position(0);
+ srcBuffer->position(0);
+
+#if defined __PS3__ && !defined DISABLE_SPU_CODE
+ if(g_texBlitJobQueuePort->hasCompleted())
+ {
+ // all outstanding blits have completed, so reset to the start of the blit list
+ g_currentTexBlit = 0;
+ }
+ Texture_blit_DataIn& dataIn = g_textureBlitDataIn[g_currentTexBlit];
+ g_currentTexBlit++;
+ if(g_currentTexBlit >= sc_maxTextureBlits)
+ {
+ app.DebugPrintf("ran out of tex blit slots, stalling for completion\n");
+ g_texBlitJobQueuePort->waitForCompletion();
+ g_currentTexBlit = 0;
+ }
+ dataIn.pSrcData = srcBuffer->getBuffer();
+ dataIn.pDstData = data[level]->getBuffer();
+ dataIn.yy = yy;
+ dataIn.xx = xx;
+ dataIn.hh = hh;
+ dataIn.ww = ww;
+ dataIn.shh = shh;
+ dataIn.sww = sww;
+ dataIn.rotated = rotated;
+
+ C4JSpursJob_Texture_blit blitJob(&dataIn);
+ g_texBlitJobQueuePort->submitJob(&blitJob);
+// p.waitForCompletion();
+
+#elif __PSVITA__
+ unsigned int *src = (unsigned int *) srcBuffer->getBuffer();
+ unsigned int *dst = (unsigned int *) data[level]->getBuffer();
+
+ for (int srcY = 0; srcY < shh; srcY++)
+ {
+ int dstY = yy + srcY;
+ int srcLine = srcY * sww;
+ int dstLine = dstY * ww;
+
+ if (rotated)
+ {
+ dstY = yy + (shh - srcY);
+ }
+
+ if (!rotated)
+ {
+ memcpy(dst + dstLine + xx, src + srcLine, sww * 4);
+ }
+ else
+ {
+ for (int srcX = 0; srcX < sww; srcX++)
+ {
+ int dstPos = dstLine + (srcX + xx);
+ int srcPos = srcLine + srcX;
+
+ if (rotated)
+ {
+ dstPos = (xx + srcX * ww) + dstY;
+ }
+
+ dst[dstPos] = src[srcPos];
+ }
+ }
+ }
+#else
+
+ for (int srcY = 0; srcY < shh; srcY++)
+ {
+ int dstY = yy + srcY;
+ int srcLine = srcY * sww * 4;
+ int dstLine = dstY * ww * 4;
+
+ if (rotated)
+ {
+ dstY = yy + (shh - srcY);
+ }
+
+ for (int srcX = 0; srcX < sww; srcX++)
+ {
+ int dstPos = dstLine + (srcX + xx) * 4;
+ int srcPos = srcLine + srcX * 4;
+
+ if (rotated)
+ {
+ dstPos = (xx + srcX * ww * 4) + dstY * 4;
+ }
+
+ data[level]->put(dstPos + 0, srcBuffer->get(srcPos + 0));
+ data[level]->put(dstPos + 1, srcBuffer->get(srcPos + 1));
+ data[level]->put(dstPos + 2, srcBuffer->get(srcPos + 2));
+ data[level]->put(dstPos + 3, srcBuffer->get(srcPos + 3));
+ }
+ }
+ // Don't delete this, as it belongs to the source texture
+ //delete srcBuffer;
+#endif
+ data[level]->position(ww * hh * 4);
+ }
+
+ if (immediateUpdate)
+ {
+ updateOnGPU();
+ }
+ else
+ {
+ updated = false;
+ }
+}
+
+void Texture::transferFromBuffer(intArray buffer)
+{
+ if (depth == 1)
+ {
+ return;
+ }
+
+// #ifdef __PS3__
+// int byteRemapRGBA[] = { 3, 0, 1, 2 };
+// int byteRemapBGRA[] = { 3, 2, 1, 0 };
+// #else
+ int byteRemapRGBA[] = { 0, 1, 2, 3 };
+ int byteRemapBGRA[] = { 2, 1, 0, 3 };
+// #endif
+ int *byteRemap = ((format == TFMT_BGRA) ? byteRemapBGRA : byteRemapRGBA);
+
+ for (int z = 0; z < depth; z++)
+ {
+ int plane = z * height * width * 4;
+ for (int y = 0; y < height; y++)
+ {
+ int column = plane + y * width * 4;
+ for (int x = 0; x < width; x++)
+ {
+ int texel = column + x * 4;
+ data[0]->position(0);
+ data[0]->put(texel + byteRemap[0], (byte)((buffer[texel >> 2] >> 24) & 0xff));
+ data[0]->put(texel + byteRemap[1], (byte)((buffer[texel >> 2] >> 16) & 0xff));
+ data[0]->put(texel + byteRemap[2], (byte)((buffer[texel >> 2] >> 8) & 0xff));
+ data[0]->put(texel + byteRemap[3], (byte)((buffer[texel >> 2] >> 0) & 0xff));
+ }
+ }
+ }
+
+ data[0]->position(width * height * depth * 4);
+
+ updateOnGPU();
+}
+
+void Texture::transferFromImage(BufferedImage *image)
+{
+ // 4J Remove 3D
+ //if (type == GL_TEXTURE_3D)
+ //{
+ // return;
+ //}
+
+ int imgWidth = image->getWidth();
+ int imgHeight = image->getHeight();
+ if (imgWidth > width || imgHeight > height)
+ {
+ //Minecraft::GetInstance().getLogger().warning("transferFromImage called with a BufferedImage with dimensions (" +
+ // imgWidth + ", " + imgHeight + ") larger than the Texture dimensions (" + width +
+ // ", " + height + "). Ignoring.");
+ app.DebugPrintf("transferFromImage called with a BufferedImage with dimensions (%d, %d) larger than the Texture dimensions (%d, %d). Ignoring.\n", imgWidth, imgHeight, width, height);
+ return;
+ }
+
+// #ifdef __PS3__
+// int byteRemapRGBA[] = { 0, 1, 2, 3 };
+// int byteRemapBGRA[] = { 2, 1, 0, 3 };
+// #else
+#ifdef _XBOX
+ int byteRemapRGBA[] = { 0, 1, 2, 3 };
+#else
+ int byteRemapRGBA[] = { 3, 0, 1, 2 };
+#endif
+ int byteRemapBGRA[] = { 3, 2, 1, 0 };
+// #endif
+ int *byteRemap = ((format == TFMT_BGRA) ? byteRemapBGRA : byteRemapRGBA);
+
+ intArray tempPixels = intArray(width * height);
+ int transparency = image->getTransparency();
+ image->getRGB(0, 0, width, height, tempPixels, 0, imgWidth);
+
+ byteArray tempBytes = byteArray(width * height * 4);
+ for (int y = 0; y < height; y++)
+ {
+ for (int x = 0; x < width; x++)
+ {
+ int intIndex = y * width + x;
+ int byteIndex = intIndex * 4;
+
+ // Pull ARGB bytes into either RGBA or BGRA depending on format
+
+ tempBytes[byteIndex + byteRemap[0]] = (byte)((tempPixels[intIndex] >> 24) & 0xff);
+ tempBytes[byteIndex + byteRemap[1]] = (byte)((tempPixels[intIndex] >> 16) & 0xff);
+ tempBytes[byteIndex + byteRemap[2]] = (byte)((tempPixels[intIndex] >> 8) & 0xff);
+ tempBytes[byteIndex + byteRemap[3]] = (byte)((tempPixels[intIndex] >> 0) & 0xff);
+ }
+ }
+
+ for(int i = 0; i < 10; i++ )
+ {
+ if(data[i] != NULL)
+ {
+ delete data[i];
+ data[i] = NULL;
+ }
+ }
+
+ MemSect(51);
+#ifdef __PS3__
+ data[0] = new ByteBuffer_IO(tempBytes.length);
+#else
+ data[0] = ByteBuffer::allocateDirect(tempBytes.length);
+#endif // __{S3__
+ MemSect(0);
+ data[0]->clear();
+ data[0]->put(tempBytes);
+ data[0]->limit(tempBytes.length);
+
+ delete [] tempBytes.data;
+
+ if(mipmapped || image->getData(1) != NULL)
+ {
+ mipmapped = true;
+ for(unsigned int level = 1; level < MAX_MIP_LEVELS; ++level)
+ {
+ int ww = width >> level;
+ int hh = height >> level;
+
+ byteArray tempBytes = byteArray(ww * hh * 4);
+ unsigned int *tempData = new unsigned int[ww * hh];
+
+ if( image->getData( level ) )
+ {
+ memcpy( tempData, image->getData( level ), ww * hh * 4);
+ for (int y = 0; y < hh; y++)
+ {
+ for (int x = 0; x < ww; x++)
+ {
+ int intIndex = y * ww + x;
+ int byteIndex = intIndex * 4;
+
+ // Pull ARGB bytes into either RGBA or BGRA depending on format
+
+ tempBytes[byteIndex + byteRemap[0]] = (byte)((tempData[intIndex] >> 24) & 0xff);
+ tempBytes[byteIndex + byteRemap[1]] = (byte)((tempData[intIndex] >> 16) & 0xff);
+ tempBytes[byteIndex + byteRemap[2]] = (byte)((tempData[intIndex] >> 8) & 0xff);
+ tempBytes[byteIndex + byteRemap[3]] = (byte)((tempData[intIndex] >> 0) & 0xff);
+ }
+ }
+ }
+ else
+ {
+ int ow = width >> (level - 1);
+
+ for (int x = 0; x < ww; x++)
+ for (int y = 0; y < hh; y++)
+ {
+ int c0 = data[level - 1]->getInt(((x * 2 + 0) + (y * 2 + 0) * ow) * 4);
+ int c1 = data[level - 1]->getInt(((x * 2 + 1) + (y * 2 + 0) * ow) * 4);
+ int c2 = data[level - 1]->getInt(((x * 2 + 1) + (y * 2 + 1) * ow) * 4);
+ int c3 = data[level - 1]->getInt(((x * 2 + 0) + (y * 2 + 1) * ow) * 4);
+#ifndef _XBOX
+ // 4J - convert our RGBA texels to ARGB that crispBlend is expecting
+ c0 = ( ( c0 >> 8 ) & 0x00ffffff ) | ( c0 << 24 );
+ c1 = ( ( c1 >> 8 ) & 0x00ffffff ) | ( c1 << 24 );
+ c2 = ( ( c2 >> 8 ) & 0x00ffffff ) | ( c2 << 24 );
+ c3 = ( ( c3 >> 8 ) & 0x00ffffff ) | ( c3 << 24 );
+#endif
+ int col = crispBlend(crispBlend(c0, c1), crispBlend(c2, c3));
+ // 4J - and back from ARGB -> RGBA
+ //col = ( col << 8 ) | (( col >> 24 ) & 0xff);
+ //tempData[x + y * ww] = col;
+
+ int intIndex = y * ww + x;
+ int byteIndex = intIndex * 4;
+
+ // Pull ARGB bytes into either RGBA or BGRA depending on format
+
+ tempBytes[byteIndex + byteRemap[0]] = (byte)((col >> 24) & 0xff);
+ tempBytes[byteIndex + byteRemap[1]] = (byte)((col >> 16) & 0xff);
+ tempBytes[byteIndex + byteRemap[2]] = (byte)((col >> 8) & 0xff);
+ tempBytes[byteIndex + byteRemap[3]] = (byte)((col >> 0) & 0xff);
+ }
+ }
+
+ MemSect(51);
+#ifdef __PS3__
+ data[level] = new ByteBuffer_IO(tempBytes.length);
+#else
+ data[level] = ByteBuffer::allocateDirect(tempBytes.length);
+#endif // __{S3__
+ MemSect(0);
+ data[level]->clear();
+ data[level]->put(tempBytes);
+ data[level]->limit(tempBytes.length);
+ delete [] tempBytes.data;
+ delete [] tempData;
+ }
+ }
+
+ delete [] tempPixels.data;
+
+ if (immediateUpdate)
+ {
+ updateOnGPU();
+ }
+ else
+ {
+ updated = false;
+ }
+}
+
+// 4J Kept from older versions for where we create mip-maps for levels that do not have pre-made graphics
+int Texture::crispBlend(int c0, int c1)
+{
+ int a0 = (int) (((c0 & 0xff000000) >> 24)) & 0xff;
+ int a1 = (int) (((c1 & 0xff000000) >> 24)) & 0xff;
+
+ int a = 255;
+ if (a0 + a1 < 255)
+ {
+ a = 0;
+ a0 = 1;
+ a1 = 1;
+ }
+ else if (a0 > a1)
+ {
+ a0 = 255;
+ a1 = 1;
+ }
+ else
+ {
+ a0 = 1;
+ a1 = 255;
+
+ }
+
+ int r0 = ((c0 >> 16) & 0xff) * a0;
+ int g0 = ((c0 >> 8) & 0xff) * a0;
+ int b0 = ((c0) & 0xff) * a0;
+
+ int r1 = ((c1 >> 16) & 0xff) * a1;
+ int g1 = ((c1 >> 8) & 0xff) * a1;
+ int b1 = ((c1) & 0xff) * a1;
+
+ int r = (r0 + r1) / (a0 + a1);
+ int g = (g0 + g1) / (a0 + a1);
+ int b = (b0 + b1) / (a0 + a1);
+
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+int Texture::getManagerId()
+{
+ return managerId;
+}
+
+int Texture::getGlId()
+{
+ return glId;
+}
+
+int Texture::getWidth()
+{
+ return width;
+}
+
+int Texture::getHeight()
+{
+ return height;
+}
+
+wstring Texture::getName()
+{
+ return name;
+}
+
+void Texture::setImmediateUpdate(bool immediateUpdate)
+{
+ this->immediateUpdate = immediateUpdate;
+}
+
+void Texture::bind(int mipMapIndex)
+{
+ // 4J Removed 3D
+ //if (depth == 1)
+ //{
+ glEnable(GL_TEXTURE_2D);
+ //}
+ //else
+ //{
+ // glEnable(GL_TEXTURE_3D);
+ //}
+
+ glActiveTexture(GL_TEXTURE0 + mipMapIndex);
+ glBindTexture(type, glId);
+ if (!updated)
+ {
+ updateOnGPU();
+ }
+}
+
+void Texture::updateOnGPU()
+{
+ data[0]->flip();
+ if(mipmapped)
+ {
+ for (int level = 1; level < m_iMipLevels; level++)
+ {
+ if(data[level] == NULL) break;
+
+ data[level]->flip();
+ }
+ }
+ // 4J remove 3D and 1D
+ //if (height != 1 && depth != 1)
+ //{
+ // glTexImage3D(type, 0, format, width, height, depth, 0, format, GL_UNSIGNED_BYTE, data);
+ //}
+ //else if(height != 1)
+ //{
+ // 4J Added check so we can differentiate between which RenderManager function to call
+ if(!m_bInitialised)
+ {
+ RenderManager.TextureSetTextureLevels(m_iMipLevels); // 4J added
+
+#ifdef __PSVITA__
+ // AP - replace the dynamic ram buffer to one that points to a newly allocated video ram texture buffer. This means we don't have to memcpy
+ // the ram based buffer to it any more inside RenderManager.TextureDataUpdate
+ unsigned char *newData = RenderManager.TextureData(width,height,data[0]->getBuffer(),0,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
+ ByteBuffer *oldBuffer = data[0];
+ data[0] = new ByteBuffer(data[0]->getSize(), (byte*) newData);
+ delete oldBuffer;
+ newData += width * height * 4;
+#else
+ RenderManager.TextureData(width,height,data[0]->getBuffer(),0,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
+#endif
+
+ if(mipmapped)
+ {
+ for (int level = 1; level < m_iMipLevels; level++)
+ {
+ int levelWidth = width >> level;
+ int levelHeight = height >> level;
+
+#ifdef __PSVITA__
+ // AP - replace the dynamic ram buffer to one that points to a newly allocated video ram texture buffer. This means we don't have to memcpy
+ // the ram based buffer to it any more inside RenderManager.TextureDataUpdate
+ RenderManager.TextureDataUpdate(0, 0,levelWidth,levelHeight,data[level]->getBuffer(),level);
+ ByteBuffer *oldBuffer = data[level];
+ data[level] = new ByteBuffer(data[level]->getSize(), (byte*) newData);
+ delete oldBuffer;
+ newData += levelWidth * levelHeight * 4;
+#else
+ RenderManager.TextureData(levelWidth,levelHeight,data[level]->getBuffer(),level,C4JRender::TEXTURE_FORMAT_RxGyBzAw);
+#endif
+ }
+ }
+
+ m_bInitialised = true;
+ }
+ else
+ {
+#ifdef _XBOX
+ RenderManager.TextureDataUpdate(data[0]->getBuffer(),0);
+#else
+ RenderManager.TextureDataUpdate(0, 0,width,height,data[0]->getBuffer(),0);
+#endif
+
+ if(mipmapped)
+ {
+ if (RenderManager.TextureGetTextureLevels() > 1)
+ {
+ for (int level = 1; level < m_iMipLevels; level++)
+ {
+ int levelWidth = width >> level;
+ int levelHeight = height >> level;
+
+#ifdef _XBOX
+ RenderManager.TextureDataUpdate(data[level]->getBuffer(),level);
+#else
+ RenderManager.TextureDataUpdate(0, 0,levelWidth,levelHeight,data[level]->getBuffer(),level);
+#endif
+ }
+ }
+ }
+ }
+ //glTexImage2D(type, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
+ //}
+ //else
+ //{
+ // glTexImage1D(type, 0, format, width, 0, format, GL_UNSIGNED_BYTE, data);
+ //}
+ updated = true;
+}
+
+ByteBuffer *Texture::getData(unsigned int level)
+{
+ return data[level];
+}