diff options
Diffstat (limited to 'backends/platform/psp/display_client.cpp')
-rw-r--r-- | backends/platform/psp/display_client.cpp | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/backends/platform/psp/display_client.cpp b/backends/platform/psp/display_client.cpp new file mode 100644 index 0000000000..73a3fefe5b --- /dev/null +++ b/backends/platform/psp/display_client.cpp @@ -0,0 +1,805 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/psp/osys_psp.cpp $ + * $Id: osys_psp.cpp 46126 2009-11-24 14:18:46Z fingolfin $ + * + */ + +#include <pspgu.h> +#include <pspdisplay.h> +#include <psputils.h> + +#include "common/scummsys.h" +#include "backends/platform/psp/display_client.h" +#include "backends/platform/psp/display_manager.h" +#include "backends/platform/psp/memory.h" + +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ +#include "backends/platform/psp/trace.h" + +#define PSP_BUFFER_WIDTH (512) +#define PSP_SCREEN_WIDTH 480 +#define PSP_SCREEN_HEIGHT 272 +#define PSP_FRAME_SIZE (PSP_BUFFER_WIDTH * PSP_SCREEN_HEIGHT) + +DisplayManager *GuRenderer::_displayManager = 0; + + +// class Palette ------------------------------------------------------------ +// +void Palette::clear() { + DEBUG_ENTER_FUNC(); + + if (_values && _numOfEntries) + memset(_values, 0, getSizeInBytes()); + + PSP_DEBUG_PRINT("_values[%p]\n", _values); + + DEBUG_EXIT_FUNC(); +} + +// Used to clear the specific keycolor +// +void Palette::setColorPositionAlpha(uint32 position, bool alpha) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(position < _numOfEntries); + + PSP_DEBUG_PRINT("position[%d], numofEntries[%u], bpp[%u], values[%p]\n", position, _numOfEntries, + _pixelFormat.bitsPerPixel, _values); + + if (_numOfEntries <= 16) + position &= 0xF; + else if (_numOfEntries <= 256) + position &= 0xFF; + + switch (_pixelFormat.bitsPerPixel) { + case 16: { + uint16 *shortVal = (uint16 *)&_values[_pixelFormat.pixelsToBytes(position)]; + *shortVal = _pixelFormat.setColorAlpha((uint32)*shortVal, alpha ? 255 : 0); + } + break; + case 32: { + uint32 *wordVal = (uint32 *)&_values[_pixelFormat.pixelsToBytes(position)]; + *wordVal = _pixelFormat.setColorAlpha((uint32)*wordVal, alpha ? 255 : 0); + } + break; + default: + PSP_ERROR("Incorrect bits per pixel value[%u]\n", _pixelFormat.bitsPerPixel); + } + + DEBUG_EXIT_FUNC(); +} + +// Set some of the palette to color values in array +// By default, ScummVm doesn't support alpha values in palettes +void Palette::setPartial(const byte *colors, uint32 start, uint32 num, bool supportsAlpha /* = false */) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(_numOfEntries); + + const byte *src = colors; + + if (start + num > _numOfEntries) // Check boundary + num = _numOfEntries - start; + + if (_pixelFormat.bitsPerPixel == 16) { + uint16 *palette = (uint16 *)_values; + palette += start; + + for (uint32 i = 0; i < num; ++i) { + byte alphaVal = supportsAlpha ? src[3] : 0xFF; + *palette = (uint16)_pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal); + src += 4; + palette++; + } + } + else if (_pixelFormat.bitsPerPixel == 32) { + uint32 *palette = (uint32 *)_values; + palette += start; + + for (uint32 i = 0; i < num; ++i) { + byte alphaVal = supportsAlpha ? src[3] : 0xFF; + *palette = _pixelFormat.rgbaToColor(src[0], src[1], src[2], alphaVal); + src += 4; + palette++; + } + } + + DEBUG_EXIT_FUNC(); +} + +// Sets pixel format and number of entries by the buffer's pixel format */ +void Palette::setPixelFormats(PSPPixelFormat::Type paletteType, PSPPixelFormat::Type bufferType, bool swapRedBlue /* = false */) { + DEBUG_ENTER_FUNC(); + + if (paletteType == PSPPixelFormat::Type_Unknown) + PSP_ERROR("Unknown paletteType[%u]\n", paletteType); + + switch (bufferType) { + case PSPPixelFormat::Type_Palette_8bit: + _numOfEntries = 256; + break; + case PSPPixelFormat::Type_Palette_4bit: + _numOfEntries = 16; + break; + case PSPPixelFormat::Type_Unknown: + case PSPPixelFormat::Type_None: + PSP_ERROR("Unhandled bufferType[%u]\n", bufferType); + break; + default: // No palette + _numOfEntries = 0; + break; + } + + _pixelFormat.set(paletteType, swapRedBlue); + + DEBUG_EXIT_FUNC(); +} + +bool Palette::allocate() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("_numOfEntries[%u]\n", _numOfEntries); + PSP_DEBUG_PRINT("_pixelFormat: format[%u], bpp[%u]\n", _pixelFormat.format, _pixelFormat.bitsPerPixel); + + if (_values) { + free (CACHED(_values)); + _values = 0; + } + + // We allocate on 64bytes to get a cache line, and round up to 64bytes to get the full line + uint32 amountInBytes = getSizeInBytes(); + if (amountInBytes < 64) + amountInBytes = 64; + _values = (byte *)memalign(64, amountInBytes); + + // Use uncached memory + GuRenderer::cacheInvalidate(_values, amountInBytes); + _values = UNCACHED(_values); + + if (!_values) { + PSP_ERROR("Couldn't allocate palette.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + + PSP_DEBUG_PRINT("_values[%p]\n", _values); + clear(); + + DEBUG_EXIT_FUNC(); + return true; +} + +void Palette::deallocate() { + DEBUG_ENTER_FUNC(); + + free (CACHED(_values)); + _values = 0; + _numOfEntries = 0; + + DEBUG_EXIT_FUNC(); +} + +// Copy some of the palette to an array of colors +// +void Palette::getPartial(byte *colors, uint start, uint num) { + DEBUG_ENTER_FUNC(); + + assert(_values); + assert(_numOfEntries); + + uint32 r, g, b, a; + + if (start + num > _numOfEntries) // Check boundary + num = _numOfEntries - start; + + if (_pixelFormat.bitsPerPixel == 16) { + uint16 *palette = (uint16 *)_values; + palette += start; + + for (uint32 i = start; i < start + num; i++) { + _pixelFormat.colorToRgba(*palette, r, g, b, a); + + *colors++ = (byte)r; + *colors++ = (byte)g; + *colors++ = (byte)b; + *colors++ = (byte)a; + palette++; + } + } else if (_pixelFormat.bitsPerPixel == 32) { + uint32 *palette = (uint32 *)_values; + palette += start; + + for (uint32 i = start; i < start + num; i++) { + _pixelFormat.colorToRgba(*palette, r, g, b, a); + + *colors++ = (byte)r; + *colors++ = (byte)g; + *colors++ = (byte)b; + *colors++ = (byte)a; + palette++; + } + } + + DEBUG_EXIT_FUNC(); +} + +void Palette::setSingleColorRGBA(uint32 num, byte r, byte g, byte b, byte a) { + // DEBUG_ENTER_FUNC(); + uint16 *shortValues; + uint32 *wordValues; + + assert (_values); + assert (num < _numOfEntries); + + switch (_pixelFormat.bitsPerPixel) { + case 16: + shortValues = (uint16 *)_values; + shortValues[num] = _pixelFormat.rgbaToColor(r, g, b, a); + break; + case 32: + wordValues = (uint32 *)_values; + wordValues[num] = _pixelFormat.rgbaToColor(r, g, b, a); + break; + default: + PSP_ERROR("Incorrect bitsPerPixel[%d]\n", _pixelFormat.bitsPerPixel); + break; + } + // DEBUG_EXIT_FUNC(); +} + +// Print to screen +void Palette::print(uint32 numToPrint /* = 0 */) { + if (_numOfEntries > 0) { + assert (_values); + + if (numToPrint > _numOfEntries || numToPrint == 0) + numToPrint = _numOfEntries; + + PSP_INFO_PRINT("cursor palette:\n"); + + for (unsigned int i=0; i<numToPrint; i++) { + byte *pcolor = &_values[_pixelFormat.pixelsToBytes(i)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + + PSP_INFO_PRINT("[%u=%x] ", i, color); + } + + PSP_INFO_PRINT("\n"); + } +} + +uint32 Palette::getRawColorAt(uint32 position) { + byte *pcolor = &_values[_pixelFormat.pixelsToBytes(position)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + return color; +} + +uint32 Palette::getRGBAColorAt(uint32 position) { + uint32 color = getRawColorAt(position); + uint32 r, g, b, a; + _pixelFormat.colorToRgba(color, r, g, b, a); + return (a << 24 | b << 16 | g << 8 | r); +} + +// class Buffer --------------------------------------------------- + +void Buffer::setPixelFormat(PSPPixelFormat::Type type, bool swapRedBlue) { + if (type == PSPPixelFormat::Type_None || + type == PSPPixelFormat::Type_Unknown) + PSP_ERROR("Unhandled buffer format[%u]\n", type); + + _pixelFormat.set(type, swapRedBlue); +} + +bool Buffer::hasPalette() { + if (_pixelFormat.format == PSPPixelFormat::Type_Palette_8bit || + _pixelFormat.format == PSPPixelFormat::Type_Palette_4bit) + return true; + + return false; +} + +/* pitch is in bytes */ +void Buffer::copyFromArray(const byte *buffer, int pitch) { + DEBUG_ENTER_FUNC(); + + // We use sourceSize because outside, they won't know what the true size is + copyFromRect(buffer, pitch, 0, 0, _sourceSize.width, _sourceSize.height); + + DEBUG_EXIT_FUNC(); +} + +/* pitch is in bytes */ +void Buffer::copyFromRect(const byte *buf, uint32 pitch, int destX, int destY, uint32 recWidth, uint32 recHeight) { + // Removed silly clipping code + DEBUG_ENTER_FUNC(); + assert (_pixels); + + if (recWidth > _sourceSize.width - destX) { + recWidth = _sourceSize.width - destX; + } + + if (recHeight > _sourceSize.height - destY) { + recHeight = _sourceSize.height - destY; + } + + if (recWidth <= 0 || recHeight <= 0) { + DEBUG_EXIT_FUNC(); + return; + } + + byte *dst = _pixels + _pixelFormat.pixelsToBytes((destY * _width) + destX); + + uint32 recWidthInBytes = _pixelFormat.pixelsToBytes(recWidth); + uint32 realWidthInBytes = _pixelFormat.pixelsToBytes(_width); + + if (pitch == realWidthInBytes && pitch == recWidthInBytes) { + //memcpy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth)); + Copier::copy(dst, buf, _pixelFormat.pixelsToBytes(recHeight * recWidth), &_pixelFormat); + } else { + do { + //memcpy(dst, buf, recWidthInBytes); + Copier::copy(dst, buf, recWidthInBytes, &_pixelFormat); + buf += pitch; + dst += realWidthInBytes; + } while (--recHeight); + } + + DEBUG_EXIT_FUNC(); +} + +/* pitch is in bytes */ +void Buffer::copyToArray(byte *dst, int pitch) { + DEBUG_ENTER_FUNC(); + assert (_pixels); + + uint32 h = _height; + byte *src = _pixels; + uint32 sourceWidthInBytes = _pixelFormat.pixelsToBytes(_sourceSize.width); + uint32 realWidthInBytes = _pixelFormat.pixelsToBytes(_width); + + do { + //memcpy(dst, src, sourceWidthInBytes); + Copier::copy(dst, src, sourceWidthInBytes, &_pixelFormat); + src += realWidthInBytes; + dst += pitch; + } while (--h); + + DEBUG_EXIT_FUNC(); +} + +/* We can size the buffer either by texture size (multiple of 2^n) or source size. The GU can + really handle both, but is supposed to get only 2^n size buffers */ +void Buffer::setSize(uint32 width, uint32 height, HowToSize textureOrSource/*=kSizeByTextureSize*/) { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("w[%u], h[%u], %s\n", width, height, textureOrSource ? "size by source" : "size by texture"); + + _sourceSize.width = width; + _sourceSize.height = height; + + _textureSize.width = scaleUpToPowerOfTwo(width); + _textureSize.height = scaleUpToPowerOfTwo(height); + + if (textureOrSource == kSizeByTextureSize) { + _width = _textureSize.width; + _height = _textureSize.height; + } + else { /* kSizeBySourceSize */ + _width = _sourceSize.width; + _height = _sourceSize.height; + } + + DEBUG_EXIT_FUNC(); +} + +/* Scale a dimension (width/height) up to power of 2 for the texture */ +uint32 Buffer::scaleUpToPowerOfTwo(uint32 size) { + + uint32 textureDimension = 0; + if (size <= 16) + textureDimension = 16; + else if (size <= 32) + textureDimension = 32; + else if (size <= 64) + textureDimension = 64; + else if (size <= 128) + textureDimension = 128; + else if (size <= 256) + textureDimension = 256; + else + textureDimension = 512; + + PSP_DEBUG_PRINT("power of 2 = %u\n", textureDimension); + + return textureDimension; +} + +bool Buffer::allocate(bool inVram/*=false*/) { + DEBUG_ENTER_FUNC(); + + PSP_DEBUG_PRINT("_width[%u], _height[%u]\n", _width, _height); + PSP_DEBUG_PRINT("_pixelFormat: format[%u], bpp[%u]\n", _pixelFormat.format, _pixelFormat.bitsPerPixel); + + if (_pixels) { + if (VramAllocator::isAddressInVram(_pixels)) // Check if in VRAM + VramAllocator::instance().deallocate(_pixels); + else // not in VRAM + free (CACHED(_pixels)); + + _pixels = 0; + } + + uint32 size = getSizeInBytes(); + + if (inVram) { + _pixels = (byte *)VramAllocator::instance().allocate(size); + } + + if (!_pixels) { // Either we are not in vram or we didn't manage to allocate in vram + // Align to 64 bytes. All normal buffer sizes are multiples of 64 anyway + _pixels = (byte *)memalign(64, size); + } + + if (!_pixels) { + PSP_ERROR("couldn't allocate buffer.\n"); + DEBUG_EXIT_FUNC(); + return false; + } + + // Use uncached memory + GuRenderer::cacheInvalidate(_pixels, size); + _pixels = UNCACHED(_pixels); + + clear(); + DEBUG_EXIT_FUNC(); + return true; +} + +void Buffer::deallocate() { + DEBUG_ENTER_FUNC(); + + if (!_pixels) + return; + + if (VramAllocator::isAddressInVram(_pixels)) // Check if in VRAM + VramAllocator::instance().deallocate(_pixels); + else + free(CACHED(_pixels)); + + _pixels = 0; + + DEBUG_EXIT_FUNC(); +} + +void Buffer::clear() { + DEBUG_ENTER_FUNC(); + + if (_pixels) + memset(_pixels, 0, getSizeInBytes()); + + DEBUG_EXIT_FUNC(); +} + +/* Convert 4 bit images to match weird PSP format */ +void Buffer::flipNibbles() { + DEBUG_ENTER_FUNC(); + + if (_pixelFormat.bitsPerPixel != 4) + return; + + assert(_pixels); + + uint32 *dest = (uint32 *)_pixels; + + for (uint32 i = 0; i < getSourceHeight(); i++) { + for (uint32 j = 0; j < (getWidth() >> 3); j++) { // /8 because we do it in 32bit chunks + uint32 val = *dest; + *dest++ = ((val >> 4) & 0x0F0F0F0F) | ((val << 4) & 0xF0F0F0F0); + } + } + + DEBUG_EXIT_FUNC(); +} + +// Print buffer contents to screen (only source size is printed out) +void Buffer::print(uint32 mask, uint32 numToPrint /*=0*/) { + assert(_pixels); + + if (numToPrint > _sourceSize.width * _sourceSize.height || numToPrint == 0) + numToPrint = _sourceSize.width * _sourceSize.height; + + PSP_INFO_PRINT("buffer: \n"); + PSP_INFO_PRINT("width[%u], height[%u]\n\n", _sourceSize.width, _sourceSize.height); + + for (unsigned int i=0; i < _sourceSize.height; i++) { + for (unsigned int j=0; j < _sourceSize.width; j++) { + if (numToPrint <= 0) // check if done + break; + + byte *pcolor = &_pixels[_pixelFormat.pixelsToBytes((i * _width) + j)]; + uint32 color = _pixelFormat.getColorValueAt(pcolor); + + //if (color != 0) PSP_INFO_PRINT("[%x] ", color); + PSP_INFO_PRINT("[%x] ", mask & color); + + numToPrint--; + } + PSP_INFO_PRINT("\n"); + } + PSP_INFO_PRINT("\n"); +} + +// class GuRenderer ------------------------------------------------- +//#define __PSP_DEBUG_FUNCS__ /* For debugging the stack */ +//#define __PSP_DEBUG_PRINT__ + +#include "backends/platform/psp/trace.h" + + +void GuRenderer::render() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("Buffer[%p] Palette[%p]\n", _buffer->getPixels(), _palette->getRawValues()); + + setMaxTextureOffsetByIndex(0, 0); + + guProgramDrawBehavior(); + + if (_buffer->hasPalette()) + guLoadPalette(); + + guProgramTextureFormat(); + guLoadTexture(); + + Vertex *vertices = guGetVertices(); + fillVertices(vertices); + + guDrawVertices(vertices); + + if (_buffer->getSourceWidth() > 512) { + setMaxTextureOffsetByIndex(1, 0); + + guLoadTexture(); + + vertices = guGetVertices(); + fillVertices(vertices); + + guDrawVertices(vertices); + } + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::setMaxTextureOffsetByIndex(uint32 x, uint32 y) { + DEBUG_ENTER_FUNC(); + const uint32 maxTextureSizeShift = 9; /* corresponds to 512 = max texture size*/ + + _maxTextureOffset.x = x << maxTextureSizeShift; /* x times 512 */ + _maxTextureOffset.y = y << maxTextureSizeShift; /* y times 512 */ + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guProgramDrawBehavior() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("blending[%s] colorTest[%s] reverseAlpha[%s] keyColor[%u]\n", _blending ? "on" : "off", _colorTest ? "on" : "off", _alphaReverse ? "on" : "off", _keyColor); + + if (_blending) { + sceGuEnable(GU_BLEND); + + if (_alphaReverse) // Reverse the alpha value (0 is 1) + sceGuBlendFunc(GU_ADD, GU_ONE_MINUS_SRC_ALPHA, GU_SRC_ALPHA, 0, 0); + else // Normal alpha values + sceGuBlendFunc(GU_ADD, GU_SRC_ALPHA, GU_ONE_MINUS_SRC_ALPHA, 0, 0); + + } else + sceGuDisable(GU_BLEND); + + if (_colorTest) { + sceGuEnable(GU_COLOR_TEST); + sceGuColorFunc(GU_NOTEQUAL, _keyColor, 0x00ffffff); + } else + sceGuDisable(GU_COLOR_TEST); + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guLoadPalette() { + DEBUG_ENTER_FUNC(); + + uint32 mask; + + if (_buffer->getBitsPerPixel() == 4) + mask = 0x0F; + else if (_buffer->getBitsPerPixel() == 8) + mask = 0xFF; + else + assert(0); /* error */ + + PSP_DEBUG_PRINT("numOfEntries[%d]\n", _palette->getNumOfEntries()); + PSP_DEBUG_PRINT("bpp[%d], pixelformat[%d], mask[%x]\n", _buffer->getBitsPerPixel(), _palette->getPixelFormat(), mask); + + sceGuClutMode(convertToGuPixelFormat(_palette->getPixelFormat()), 0, mask, 0); + sceGuClutLoad(_palette->getNumOfEntries() >> 3, _palette->getRawValues()); + + DEBUG_EXIT_FUNC(); +} + +inline void GuRenderer::guProgramTextureFormat() { + DEBUG_ENTER_FUNC(); + PSP_DEBUG_PRINT("pixelFormat[%d]\n", _buffer->getPixelFormat()); + + sceGuTexMode(convertToGuPixelFormat(_buffer->getPixelFormat()), 0, 0, 0); + DEBUG_EXIT_FUNC(); +} + +inline uint32 GuRenderer::convertToGuPixelFormat(PSPPixelFormat::Type format) { + DEBUG_ENTER_FUNC(); + + uint32 guFormat = 0; + + switch (format) { + case PSPPixelFormat::Type_4444: + guFormat = GU_PSM_4444; + break; + case PSPPixelFormat::Type_5551: + guFormat = GU_PSM_5551; + break; + case PSPPixelFormat::Type_5650: + guFormat = GU_PSM_5650; + break; + case PSPPixelFormat::Type_8888: + guFormat = GU_PSM_8888; + break; + case PSPPixelFormat::Type_Palette_8bit: + guFormat = GU_PSM_T8; + break; + case PSPPixelFormat::Type_Palette_4bit: + guFormat = GU_PSM_T4; + break; + default: + break; + } + + PSP_DEBUG_PRINT("Pixelformat[%d], guFormat[%d]\n", format, guFormat); + + DEBUG_EXIT_FUNC(); + return guFormat; + +} + +inline void GuRenderer::guLoadTexture() { + DEBUG_ENTER_FUNC(); + + sceGuTexImage(0, _buffer->getTextureWidth(), _buffer->getTextureHeight(), _buffer->getWidth(), _buffer->getPixels() + _buffer->_pixelFormat.pixelsToBytes(_maxTextureOffset.x)); + + DEBUG_EXIT_FUNC(); +} + +inline Vertex *GuRenderer::guGetVertices() { + DEBUG_ENTER_FUNC(); + + Vertex *ret = (Vertex *)sceGuGetMemory(2 * sizeof(Vertex)); + + DEBUG_EXIT_FUNC(); + return ret; +} + +// Fills the vertices. Most of the logic is here. +void GuRenderer::fillVertices(Vertex *vertices) { + DEBUG_ENTER_FUNC(); + + uint32 outputWidth = _displayManager->getOutputWidth(); + uint32 outputHeight = _displayManager->getOutputHeight(); + + float textureStartX, textureStartY, textureEndX, textureEndY; + + // Texture adjustments for eliminating half-pixel artifacts from scaling + // Not necessary if we don't scale + float textureAdjustment = 0.0f; + if (_useGlobalScaler && + (_displayManager->getScaleX() != 1.0f || _displayManager->getScaleX() != 1.0f)) + textureAdjustment = 0.5f; + + textureStartX = textureAdjustment + _offsetInBuffer.x; //debug + textureStartY = textureAdjustment + _offsetInBuffer.y; + // We subtract maxTextureOffset because our shifted texture starts at 512 and will go to 640 + textureEndX = _offsetInBuffer.x + _drawSize.width - textureAdjustment - _maxTextureOffset.x; + textureEndY = _offsetInBuffer.y + _drawSize.height - textureAdjustment; + + // For scaling to the final image size, calculate the gaps on both sides + uint32 gapX = _useGlobalScaler ? (PSP_SCREEN_WIDTH - outputWidth) >> 1 : 0; + uint32 gapY = _useGlobalScaler ? (PSP_SCREEN_HEIGHT - outputHeight) >> 1 : 0; + + float imageStartX, imageStartY, imageEndX, imageEndY; + + imageStartX = gapX + ( scaleSourceToOutputX(_maxTextureOffset.x) ); + imageStartY = gapY; + + imageStartX += scaleSourceToOutputX(_offsetOnScreen.x); + imageStartY += scaleSourceToOutputY(_offsetOnScreen.y); + + if (_fullScreen) { // shortcut + imageEndX = PSP_SCREEN_WIDTH - gapX; + imageEndY = PSP_SCREEN_HEIGHT - gapY; + } else { /* !fullScreen */ + imageEndX = imageStartX + scaleSourceToOutputX(_drawSize.width); + imageEndY = imageStartY + scaleSourceToOutputY(_drawSize.height); + } + + vertices[0].u = textureStartX; + vertices[0].v = textureStartY; + vertices[1].u = textureEndX; + vertices[1].v = textureEndY; + + vertices[0].x = imageStartX; + vertices[0].y = imageStartY; + vertices[0].z = 0; + vertices[1].x = imageEndX; + vertices[1].y = imageEndY; + vertices[1].z = 0; + + PSP_DEBUG_PRINT("TextureStart: X[%f] Y[%f] TextureEnd: X[%.1f] Y[%.1f]\n", textureStartX, textureStartY, textureEndX, textureEndY); + PSP_DEBUG_PRINT("ImageStart: X[%f] Y[%f] ImageEnd: X[%.1f] Y[%.1f]\n", imageStartX, imageStartY, imageEndX, imageEndY); + + DEBUG_EXIT_FUNC(); +} + +/* Scale the input X offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutputX(float offset) { + float result; + + if (!_useGlobalScaler) + result = offset; + else if (!offset) + result = 0.0f; + else + result = offset * _displayManager->getScaleX(); + + return result; +} + +/* Scale the input Y offset to appear in proper position on the screen */ +inline float GuRenderer::scaleSourceToOutputY(float offset) { + float result; + + if (!_useGlobalScaler) + result = offset; + else if (!offset) + result = 0.0f; + else + result = offset * _displayManager->getScaleY(); + + return result; +} + +inline void GuRenderer::guDrawVertices(Vertex *vertices) { + DEBUG_ENTER_FUNC(); + + sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF|GU_VERTEX_32BITF|GU_TRANSFORM_2D, 2, 0, vertices); + DEBUG_EXIT_FUNC(); +} + +void GuRenderer::cacheInvalidate(void *pointer, uint32 size) { + sceKernelDcacheWritebackInvalidateRange(pointer, size); +} |