Replaced OOPixMap.components with saner OOPixMap.format.

git-svn-id: http://svn.berlios.de/svnroot/repos/oolite-linux/trunk@3362 127b21dd-08f5-0310-b4b7-95ae10353056
This commit is contained in:
Jens Ayton 2010-05-16 13:17:38 +00:00
parent 15fcc13c8a
commit 4fd327af6b
12 changed files with 254 additions and 162 deletions

View File

@ -258,7 +258,7 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB);
if (haveEmission) DUMP(_emissionPx, @"source emission map");
// Extract illumination component if emission_and_illumination_map.
if (haveEmission && _isCombinedMap && _emissionPx.components > 1)
if (haveEmission && _isCombinedMap && OOPixMapFormatHasAlpha(_emissionPx.format))
{
OOPixMapToRGBA(&_emissionPx);
illuminationPx = OODuplicatePixMap(_emissionPx, 0);
@ -332,24 +332,8 @@ static void ScaleToMatch(OOPixMap *pmA, OOPixMap *pmB);
_width = _emissionPx.width;
_height = _emissionPx.height;
_rowBytes = _emissionPx.rowBytes;
switch (_emissionPx.components)
{
case 1:
_format = kOOTextureDataGrayscale;
break;
case 2:
_format = kOOTextureDataGrayscaleAlpha;
break;
case 4:
_format = kOOTextureDataRGBA;
break;
default:
OOLogERR(@"texture.combinedEmissionMap.error", @"Unexepected component count %u for %@", _emissionPx.components, self);
_data = NULL;
}
_format = _emissionPx.format;
_emissionPx.pixels = NULL; // So it won't be freed by -dealloc.
}
if (_data == NULL)

View File

@ -256,12 +256,11 @@ static BOOL DecodeFormat(OOTextureDataFormat format, uint32_t options, GLenum *o
[self ensureFinishedLoading];
OOPixMap px = kOONullPixMap;
OOPixMapComponentCount components = OOTextureComponentsForFormat(_format);
if (_bytes != NULL)
{
// If possible, just copy our existing buffer.
px = OOMakePixMap(_bytes, _width, _height, components, 0, 0);
px = OOMakePixMap(_bytes, _width, _height, _format, 0, 0);
px = OODuplicatePixMap(px, 0);
}
#if OOTEXTURE_RELOADABLE
@ -276,7 +275,7 @@ static BOOL DecodeFormat(OOTextureDataFormat format, uint32_t options, GLenum *o
if (![self isCubeMap])
{
px = OOAllocatePixMap(_width, _height, components, 0, 0);
px = OOAllocatePixMap(_width, _height, _format, 0, 0);
if (!OOIsValidPixMap(px)) return kOONullPixMap;
glGetTexImage(GL_TEXTURE_2D, 0, format, type, px.pixels);
@ -284,7 +283,7 @@ static BOOL DecodeFormat(OOTextureDataFormat format, uint32_t options, GLenum *o
#if OO_TEXTURE_CUBE_MAP
else
{
px = OOAllocatePixMap(_width, _width * 6, components, 0, 0);
px = OOAllocatePixMap(_width, _width * 6, _format, 0, 0);
if (!OOIsValidPixMap(px)) return kOONullPixMap;
uint8_t *pixels = px.pixels;
@ -292,7 +291,7 @@ static BOOL DecodeFormat(OOTextureDataFormat format, uint32_t options, GLenum *o
for (i = 0; i < 6; i++)
{
glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, format, type, pixels);
pixels += components * _width * _width;
pixels += OOPixMapBytesPerPixelForFormat(_format) * _width * _width;
}
}
#endif

View File

@ -31,14 +31,23 @@ SOFTWARE.
typedef uint_fast32_t OOPixMapDimension; // Note: dimensions are assumed to be less than 1048576 (2^20) pixels.
typedef uint_fast8_t OOPixMapComponentCount; // Currently supported values are 1, 2 and 4.
//typedef uint_fast8_t OOPixMapComponentCount; // Currently supported values are 1, 2 and 4.
typedef enum
{
kOOPixMapInvalidFormat = 0,
kOOPixMapGrayscale = 1,
kOOPixMapGrayscaleAlpha = 2,
kOOPixMapRGBA = 4
} OOPixMapFormat;
typedef struct OOPixMap
{
void *pixels;
OOPixMapDimension width, height;
OOPixMapComponentCount components;
OOPixMapFormat format;
size_t rowBytes;
size_t bufferSize;
} OOPixMap;
@ -57,13 +66,13 @@ OOINLINE size_t OOMinimumPixMapBufferSize(OOPixMap pixMap) { return pixMap.rowB
invalid. If rowBytes or bufferSize are zero, minimum valid values will be
used.
*/
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount components, size_t rowBytes, size_t bufferSize);
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize);
/* OOAllocatePixMap()
Create an OOPixMap, allocating storage. If rowBytes or bufferSize are zero,
minimum valid values will be used.
*/
OOPixMap OOAllocatePixMap(OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount components, size_t rowBytes, size_t bufferSize);
OOPixMap OOAllocatePixMap(OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize);
/* OOFreePixMap()
@ -104,3 +113,26 @@ void OODumpPixMap(OOPixMap pixMap, NSString *name);
#else
#define OODumpPixMap(p, n) do {} while (0)
#endif
BOOL OOIsValidPixMapFormat(OOPixMapFormat format);
#ifndef NDEBUG
size_t OOPixMapBytesPerPixelForFormat(OOPixMapFormat format) PURE_FUNC;
#else
OOINLINE size_t OOPixMapBytesPerPixelForFormat(OOPixMapFormat format)
{
// Currently, format values are component counts. This is subject to change.
return format;
}
#endif
OOINLINE size_t OOPixMapBytesPerPixel(OOPixMap pixMap)
{
return OOPixMapBytesPerPixelForFormat(pixMap.format);
}
NSString *OOPixMapFormatName(OOPixMapFormat format) PURE_FUNC;
BOOL OOPixMapFormatHasAlpha(OOPixMapFormat format) PURE_FUNC;

View File

@ -33,7 +33,7 @@ const OOPixMap kOONullPixMap =
.pixels = NULL,
.width = 0,
.height = 0,
.components = 0,
.format = kOOPixMapInvalidFormat,
.rowBytes = 0,
.bufferSize = 0
};
@ -44,15 +44,15 @@ BOOL OOIsValidPixMap(OOPixMap pixMap)
return pixMap.pixels != NULL &&
pixMap.width > 0 &&
pixMap.height > 0 &&
(pixMap.components == 1 || pixMap.components == 2 || pixMap.components == 4) &&
pixMap.rowBytes >= pixMap.width * pixMap.components &&
OOIsValidPixMapFormat(pixMap.format) &&
pixMap.rowBytes >= pixMap.width * OOPixMapBytesPerPixelForFormat(pixMap.format) &&
pixMap.bufferSize >= pixMap.rowBytes * pixMap.height;
}
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount components, size_t rowBytes, size_t bufferSize)
OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize)
{
if (rowBytes == 0) rowBytes = width * components;
if (rowBytes == 0) rowBytes = width * OOPixMapBytesPerPixelForFormat(format);
if (bufferSize == 0) bufferSize = rowBytes * height;
OOPixMap result =
@ -60,7 +60,7 @@ OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension h
.pixels = pixels,
.width = width,
.height = height,
.components = components,
.format = format,
.rowBytes = rowBytes,
.bufferSize = bufferSize
};
@ -70,10 +70,10 @@ OOPixMap OOMakePixMap(void *pixels, OOPixMapDimension width, OOPixMapDimension h
}
OOPixMap OOAllocatePixMap(OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount components, size_t rowBytes, size_t bufferSize)
OOPixMap OOAllocatePixMap(OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format, size_t rowBytes, size_t bufferSize)
{
// Create pixmap struct with dummy pixel pointer to test validity.
OOPixMap pixMap = OOMakePixMap((void *)-1, width, height, components, rowBytes, bufferSize);
OOPixMap pixMap = OOMakePixMap((void *)-1, width, height, format, rowBytes, bufferSize);
if (EXPECT_NOT(!OOIsValidPixMap(pixMap))) return kOONullPixMap;
pixMap.pixels = malloc(pixMap.bufferSize);
@ -99,7 +99,7 @@ OOPixMap OODuplicatePixMap(OOPixMap srcPixMap, size_t desiredSize)
size_t minSize = OOMinimumPixMapBufferSize(srcPixMap);
if (desiredSize < minSize) desiredSize = minSize;
OOPixMap result = OOAllocatePixMap(srcPixMap.width, srcPixMap.width, srcPixMap.components, srcPixMap.rowBytes, desiredSize);
OOPixMap result = OOAllocatePixMap(srcPixMap.width, srcPixMap.width, srcPixMap.format, srcPixMap.rowBytes, desiredSize);
if (EXPECT_NOT(!OOIsValidPixMap(result))) return kOONullPixMap;
memcpy(result.pixels, srcPixMap.pixels, minSize);
@ -148,9 +148,13 @@ void OODumpPixMap(OOPixMap pixMap, NSString *name)
MyOpenGLView *gameView = [UNIVERSE gameView];
switch (pixMap.components)
switch (pixMap.format)
{
case 1:
case kOOPixMapInvalidFormat:
break;
case kOOPixMapGrayscale:
[gameView dumpGrayToFileNamed:name
bytes:pixMap.pixels
width:pixMap.width
@ -158,7 +162,7 @@ void OODumpPixMap(OOPixMap pixMap, NSString *name)
rowBytes:pixMap.rowBytes];
break;
case 2:
case kOOPixMapGrayscaleAlpha:
[gameView dumpGrayAlphaToFileNamed:name
bytes:pixMap.pixels
width:pixMap.width
@ -166,15 +170,7 @@ void OODumpPixMap(OOPixMap pixMap, NSString *name)
rowBytes:pixMap.rowBytes];
break;
case 3:
[gameView dumpRGBAToFileNamed:name
bytes:pixMap.pixels
width:pixMap.width
height:pixMap.height
rowBytes:pixMap.rowBytes];
break;
case 4:
case kOOPixMapRGBA:
[gameView dumpRGBAToRGBFileNamed:[name stringByAppendingString:@" rgb"]
andGrayFileNamed:[name stringByAppendingString:@" alpha"]
bytes:pixMap.pixels
@ -184,5 +180,64 @@ void OODumpPixMap(OOPixMap pixMap, NSString *name)
break;
}
}
#endif
BOOL OOIsValidPixMapFormat(OOPixMapFormat format)
{
switch (format)
{
case kOOPixMapInvalidFormat: return NO;
case kOOPixMapGrayscale:
case kOOPixMapGrayscaleAlpha:
case kOOPixMapRGBA:
return YES;
}
return NO;
}
#ifndef NDEBUG
size_t OOPixMapBytesPerPixelForFormat(OOPixMapFormat format)
{
switch (format)
{
case kOOPixMapInvalidFormat: return 0;
case kOOPixMapGrayscale: return 1;
case kOOPixMapGrayscaleAlpha: return 2;
case kOOPixMapRGBA: return 4;
}
return -1;
}
#endif
NSString *OOPixMapFormatName(OOPixMapFormat format)
{
switch (format)
{
case kOOPixMapInvalidFormat: return @"invalid";
case kOOPixMapGrayscale: return @"grayscale";
case kOOPixMapGrayscaleAlpha: return @"grayscale+alpha";
case kOOPixMapRGBA: return @"RGBA";
}
return [NSString stringWithFormat:@"invalid<%i>", (int)format];
}
BOOL OOPixMapFormatHasAlpha(OOPixMapFormat format)
{
switch (format)
{
case kOOPixMapInvalidFormat: return NO;
case kOOPixMapGrayscale: return NO;
case kOOPixMapGrayscaleAlpha: return YES;
case kOOPixMapRGBA: return YES;
}
return NO;
}

View File

@ -40,21 +40,19 @@ SOFTWARE.
pixmap, a pixmap whose channel count is not 4, or a channel index greater
than 3.
*/
BOOL OOExtractPixMapChannel(OOPixMap *ioPixMap, OOPixMapComponentCount channelIndex, BOOL compactWhenDone);
BOOL OOExtractPixMapChannel(OOPixMap *ioPixMap, uint8_t channelIndex, BOOL compactWhenDone);
/* OOPixMapToRGBA()
Convert a pixmap to RGBA format. If it has one component, it is assumed to
be greyscale. If it has two components, it is assumed to be greyscale+alpha.
If it has four components, it is left as-is.
Convert a pixmap to RGBA format.
NOTE: if successful, this will free() the original buffer and replace it.
*/
BOOL OOPixMapToRGBA(OOPixMap *ioPixMap);
/* OOPixMapModulateUniform()
Multiply all pixels by specified per-component factors. Pixmap must have
four components. The effect of using factors outside the range [0..1] is
Multiply all pixels by specified per-component factors. Pixmap must be in
RGBA format. The effect of using factors outside the range [0..1] is
undefined.
OOPixMapToRGBA() is called on ioPixMap.
*/
@ -64,7 +62,7 @@ BOOL OOPixMapModulateUniform(OOPixMap *ioPixMap, float f0, float f1, float f2, f
/* OOPixMapModulatePixMap()
Multiply each pixel of ioDstPixMap by the corresponding pixel of otherPixMap,
writing the result to ioDstPixMap.
OOPixMapToRGBA() is called on ioDstPixMap; otherPixMap must have four components.
OOPixMapToRGBA() is called on ioDstPixMap; otherPixMap must be RGBA.
*/
BOOL OOPixMapModulatePixMap(OOPixMap *ioDstPixMap, OOPixMap otherPixMap);
@ -72,6 +70,6 @@ BOOL OOPixMapModulatePixMap(OOPixMap *ioDstPixMap, OOPixMap otherPixMap);
/* OOPixMapAddPixMap()
Add each pixel of otherPixMap to the corresponding pixel of ioDstPixMap,
writing the result to ioDstPixMap.
OOPixMapToRGBA() is called on ioDstPixMap; otherPixMap must have four components.
OOPixMapToRGBA() is called on ioDstPixMap; otherPixMap must be RGBA.
*/
BOOL OOPixMapAddPixMap(OOPixMap *ioDstPixMap, OOPixMap otherPixMap);

View File

@ -29,7 +29,7 @@ SOFTWARE.
#import "OOCPUInfo.h"
static void ExtractChannel_4(OOPixMap *ioPixMap, OOPixMapComponentCount channelIndex);
static void ExtractChannel_4(OOPixMap *ioPixMap, uint8_t channelIndex);
static void ToRGBA_1(OOPixMap srcPx, OOPixMap dstPx);
static void ToRGBA_2(OOPixMap srcPx, OOPixMap dstPx);
static void ModulateUniform_4(OOPixMap pixMap, uint16_t f0, uint16_t f1, uint16_t f2, uint16_t f3);
@ -37,16 +37,16 @@ static void ModulatePixMap_4(OOPixMap mainPx, OOPixMap otherPx);
static void AddPixMap_4(OOPixMap mainPx, OOPixMap otherPx);
BOOL OOExtractPixMapChannel(OOPixMap *ioPixMap, OOPixMapComponentCount channelIndex, BOOL compactWhenDone)
BOOL OOExtractPixMapChannel(OOPixMap *ioPixMap, uint8_t channelIndex, BOOL compactWhenDone)
{
if (EXPECT_NOT(ioPixMap == NULL || !OOIsValidPixMap(*ioPixMap) || ioPixMap->components != 4 || channelIndex > 3))
if (EXPECT_NOT(ioPixMap == NULL || !OOIsValidPixMap(*ioPixMap) || ioPixMap->format != kOOPixMapRGBA || channelIndex > 3))
{
return NO;
}
ExtractChannel_4(ioPixMap, channelIndex);
ioPixMap->components = 1;
ioPixMap->format = kOOPixMapGrayscale;
ioPixMap->rowBytes = ioPixMap->width;
if (compactWhenDone)
@ -58,7 +58,7 @@ BOOL OOExtractPixMapChannel(OOPixMap *ioPixMap, OOPixMapComponentCount channelIn
}
static void ExtractChannel_4(OOPixMap *ioPixMap, OOPixMapComponentCount channelIndex)
static void ExtractChannel_4(OOPixMap *ioPixMap, uint8_t channelIndex)
{
NSCParameterAssert(ioPixMap != NULL);
@ -96,25 +96,46 @@ static void ExtractChannel_4(OOPixMap *ioPixMap, OOPixMapComponentCount channelI
BOOL OOPixMapToRGBA(OOPixMap *ioPixMap)
{
if (EXPECT_NOT(ioPixMap == NULL || !OOIsValidPixMap(*ioPixMap))) return NO;
if (ioPixMap->components == 4) return YES;
if (EXPECT_NOT(ioPixMap->components != 1 && ioPixMap->components != 2)) return NO;
if (ioPixMap->format == kOOPixMapRGBA) return YES;
OOPixMap temp = OOAllocatePixMap(ioPixMap->width, ioPixMap->height, 4, 0, 0);
if (EXPECT_NOT(OOIsNullPixMap(temp))) return NO;
if (ioPixMap->components == 1) ToRGBA_1(*ioPixMap, temp);
else if (ioPixMap->components == 2) ToRGBA_2(*ioPixMap, temp);
BOOL OK = NO;
switch (ioPixMap->format)
{
case kOOPixMapGrayscale:
ToRGBA_1(*ioPixMap, temp);
break;
case kOOPixMapGrayscaleAlpha:
ToRGBA_2(*ioPixMap, temp);
break;
case kOOPixMapRGBA:
case kOOPixMapInvalidFormat:
OK = NO;
break;
// No default, because -Wswitch-enum is our friend.
}
free(ioPixMap->pixels);
*ioPixMap = temp;
return YES;
if (OK)
{
free(ioPixMap->pixels);
*ioPixMap = temp;
}
else
{
free(temp.pixels);
}
return OK;
}
static void ToRGBA_1(OOPixMap srcPx, OOPixMap dstPx)
{
NSCParameterAssert(srcPx.components == 1 && dstPx.components == 4 && srcPx.width == dstPx.width && srcPx.height == dstPx.height);
NSCParameterAssert(OOPixMapBytesPerPixel(srcPx) == 1 && dstPx.format == kOOPixMapRGBA && srcPx.width == dstPx.width && srcPx.height == dstPx.height);
uint8_t *src;
uint32_t *dst;
@ -145,7 +166,7 @@ static void ToRGBA_1(OOPixMap srcPx, OOPixMap dstPx)
static void ToRGBA_2(OOPixMap srcPx, OOPixMap dstPx)
{
NSCParameterAssert(srcPx.components == 2 && dstPx.components == 4 && srcPx.width == dstPx.width && srcPx.height == dstPx.height);
NSCParameterAssert(OOPixMapBytesPerPixel(srcPx) == 2 && dstPx.format == kOOPixMapRGBA && srcPx.width == dstPx.width && srcPx.height == dstPx.height);
uint16_t *src;
uint_fast32_t px;
@ -196,7 +217,7 @@ static void ModulateUniform_4(OOPixMap pixMap, uint16_t f3, uint16_t f2, uint16_
#error Unknown byte order.
#endif
{
NSCParameterAssert(pixMap.components == 4);
NSCParameterAssert(OOPixMapBytesPerPixel(pixMap) == 4);
uint32_t *curr;
uint_fast32_t px;
@ -243,7 +264,7 @@ static void ModulateUniform_4(OOPixMap pixMap, uint16_t f3, uint16_t f2, uint16_
BOOL OOPixMapModulatePixMap(OOPixMap *ioDstPixMap, OOPixMap otherPixMap)
{
if (EXPECT_NOT(ioDstPixMap == NULL || !OOIsValidPixMap(*ioDstPixMap))) return NO;
if (EXPECT_NOT(!OOIsValidPixMap(otherPixMap) || otherPixMap.components != 4)) return NO;
if (EXPECT_NOT(!OOIsValidPixMap(otherPixMap) || otherPixMap.format != kOOPixMapRGBA)) return NO;
if (EXPECT_NOT(!OOPixMapToRGBA(ioDstPixMap))) return NO;
if (EXPECT_NOT(ioDstPixMap->width != otherPixMap.width || ioDstPixMap->height != otherPixMap.height)) return NO;
@ -302,7 +323,7 @@ static void ModulatePixMap_4(OOPixMap mainPx, OOPixMap otherPx)
BOOL OOPixMapAddPixMap(OOPixMap *ioDstPixMap, OOPixMap otherPixMap)
{
if (EXPECT_NOT(ioDstPixMap == NULL || !OOIsValidPixMap(*ioDstPixMap))) return NO;
if (EXPECT_NOT(!OOIsValidPixMap(otherPixMap) || otherPixMap.components != 4)) return NO;
if (EXPECT_NOT(!OOIsValidPixMap(otherPixMap) || otherPixMap.format != kOOPixMapRGBA)) return NO;
if (EXPECT_NOT(!OOPixMapToRGBA(ioDstPixMap))) return NO;
if (EXPECT_NOT(ioDstPixMap->width != otherPixMap.width || ioDstPixMap->height != otherPixMap.height)) return NO;

View File

@ -34,6 +34,7 @@ SOFTWARE.
#import <Foundation/Foundation.h>
#import "OOOpenGL.h"
#import "OOPixMap.h"
#import "OOWeakReference.h"
@class OOTextureLoader, OOTextureGenerator;
@ -95,11 +96,11 @@ enum
typedef enum
{
kOOTextureDataInvalid,
kOOTextureDataInvalid = kOOPixMapInvalidFormat,
kOOTextureDataRGBA, // GL_RGBA
kOOTextureDataGrayscale, // GL_LUMINANCE (or GL_ALPHA with kOOTextureAlphaMask)
kOOTextureDataGrayscaleAlpha // GL_LUMINANCE_ALPHA
kOOTextureDataRGBA = kOOPixMapRGBA, // GL_RGBA
kOOTextureDataGrayscale = kOOPixMapGrayscale, // GL_LUMINANCE (or GL_ALPHA with kOOTextureAlphaMask)
kOOTextureDataGrayscaleAlpha = kOOPixMapGrayscaleAlpha // GL_LUMINANCE_ALPHA
} OOTextureDataFormat;
@ -190,7 +191,7 @@ typedef enum
/* Create a new pixmap with a copy of the texture data. The caller is
responsible for free()ing the resulting buffer.
*/
- (struct OOPixMap) copyPixMapRepresentation;
- (OOPixMap) copyPixMapRepresentation;
/* Identify special texture types.
*/

View File

@ -336,7 +336,7 @@ static BOOL sHaveSetUp = NO;
void *dstBytes = ((uint8_t *)newData) + newSideSize * i;
memcpy(dstBytes, srcBytes, srcSideSize);
OOGenerateMipMaps(dstBytes, _width, _width, components);
OOGenerateMipMaps(dstBytes, _width, _width, _format);
}
free(_data);
@ -434,7 +434,7 @@ static BOOL sHaveSetUp = NO;
}
if (_generateMipMaps)
{
OOGenerateMipMaps(_data, _width, _height, components);
OOGenerateMipMaps(_data, _width, _height, _format);
}
// All done.

View File

@ -36,7 +36,7 @@ SOFTWARE.
OOPixMap OOConvertCubeMapToLatLong(OOPixMap sourcePixMap, OOPixMapDimension height, BOOL leaveSpaceForMipMaps)
{
if (!OOIsValidPixMap(sourcePixMap) || sourcePixMap.components != 4 || sourcePixMap.height != sourcePixMap.width * 6)
if (!OOIsValidPixMap(sourcePixMap) || sourcePixMap.format != kOOPixMapRGBA || sourcePixMap.height != sourcePixMap.width * 6)
{
return kOONullPixMap;
}

View File

@ -6,16 +6,11 @@
-- Ahruman 2009-09-04
*/
#define OO_HAVE_NSOPERATION 0
#ifndef OO_HAVE_NSOPERATION
#if OOLITE_MAC_OS_X
#define OO_HAVE_NSOPERATION OOLITE_LEOPARD
#elif OOLITE_GNUSTEP
#ifdef __NSOperation_h_GNUSTEP_BASE_INCLUDE
#if OS_API_VERSION(100500, GS_API_LATEST)
#define OO_HAVE_NSOPERATION 1
#endif
#endif
#define OO_HAVE_NSOPERATION OOLITE_GNUSTEP_1_20 && OS_API_VERSION(100500, GS_API_LATEST)
#endif
#endif

View File

@ -40,15 +40,8 @@ SOFTWARE.
*/
OOPixMap OOScalePixMap(OOPixMap srcPixMap, OOPixMapDimension dstWidth, OOPixMapDimension dstHeight, BOOL leaveSpaceForMipMaps);
OOINLINE void *OOScalePixMapRaw(void *srcData, OOPixMapDimension srcWidth, OOPixMapDimension srcHeight, OOPixMapComponentCount components, size_t srcRowBytes, OOPixMapDimension dstWidth, OOPixMapDimension dstHeight, BOOL leaveSpaceForMipMaps)
{
OOPixMap src = OOMakePixMap(srcData, srcWidth, srcHeight, components, srcRowBytes, 0);
OOPixMap dst = OOScalePixMap(src, dstWidth, dstHeight, leaveSpaceForMipMaps);
return dst.pixels;
}
/* Assumes 8 bits per sample, interleaved.
Buffer must have space for (4 * width * height) / 3 pixels.
*/
BOOL OOGenerateMipMaps(void *textureBytes, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount planes);
BOOL OOGenerateMipMaps(void *textureBytes, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format);

View File

@ -128,81 +128,87 @@ OOINLINE void StretchVertically(OOPixMap srcPx, OOPixMap dstPx)
OOINLINE void SqueezeVertically(OOPixMap pixMap, OOPixMapDimension dstHeight)
{
switch (pixMap.components)
switch (pixMap.format)
{
case 4:
case kOOPixMapRGBA:
SqueezeVertically4(pixMap, dstHeight);
break;
return;
case 1:
case kOOPixMapGrayscale:
SqueezeVertically1(pixMap, dstHeight);
break;
return;
case 2:
case kOOPixMapGrayscaleAlpha:
SqueezeVertically2(pixMap, dstHeight);
break;
return;
#ifndef NDEBUG
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid texture component count: %u", pixMap.components];
#else
abort();
#endif
case kOOPixMapInvalidFormat:
break;
}
#ifndef NDEBUG
[NSException raise:NSInternalInconsistencyException format:@"Unsupported pixmap format in scaler: %@", OOPixMapFormatName(pixMap.format)];
#else
abort();
#endif
}
OOINLINE void StretchHorizontally(OOPixMap srcPx, OOPixMap dstPx)
{
NSCParameterAssert(srcPx.components == dstPx.components);
NSCParameterAssert(srcPx.format == dstPx.format);
switch (srcPx.components)
switch (srcPx.format)
{
case 4:
case kOOPixMapRGBA:
StretchHorizontally4(srcPx, dstPx);
break;
return;
case 1:
case kOOPixMapGrayscale:
StretchHorizontally1(srcPx, dstPx);
break;
return;
case 2:
case kOOPixMapGrayscaleAlpha:
StretchHorizontally2(srcPx, dstPx);
break;
return;
#ifndef NDEBUG
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid texture component count: %u", srcPx.components];
#else
abort();
#endif
case kOOPixMapInvalidFormat:
break;
}
#ifndef NDEBUG
[NSException raise:NSInternalInconsistencyException format:@"Unsupported pixmap format in scaler: %@", OOPixMapFormatName(srcPx.format)];
#else
abort();
#endif
}
OOINLINE void SqueezeHorizontally(OOPixMap pixMap, OOPixMapDimension dstHeight)
{
switch (pixMap.components)
switch (pixMap.format)
{
case 4:
case kOOPixMapRGBA:
SqueezeHorizontally4(pixMap, dstHeight);
break;
return;
case 1:
case kOOPixMapGrayscale:
SqueezeHorizontally1(pixMap, dstHeight);
break;
return;
case 2:
case kOOPixMapGrayscaleAlpha:
SqueezeHorizontally2(pixMap, dstHeight);
break;
return;
#ifndef NDEBUG
default:
[NSException raise:NSInternalInconsistencyException format:@"Invalid texture component count: %u", pixMap.components];
#else
abort();
#endif
case kOOPixMapInvalidFormat:
break;
}
#ifndef NDEBUG
[NSException raise:NSInternalInconsistencyException format:@"Unsupported pixmap format in scaler: %@", OOPixMapFormatName(pixMap.format)];
#else
abort();
#endif
}
@ -258,7 +264,7 @@ OOPixMap OOScalePixMap(OOPixMap srcPx, OOPixMapDimension dstWidth, OOPixMapDimen
size_t dstSize = srcPx.rowBytes * dstHeight;
if (leaveSpaceForMipMaps && dstWidth <= srcPx.width) dstSize = dstSize * 4 / 3;
dstPx = OOAllocatePixMap(srcPx.width, dstHeight, srcPx.components, 0, dstSize);
dstPx = OOAllocatePixMap(srcPx.width, dstHeight, srcPx.format, 0, dstSize);
if (EXPECT_NOT(!OOIsValidPixMap(dstPx))) { OK = NO; goto FAIL; }
StretchVertically(srcPx, dstPx);
@ -278,17 +284,17 @@ OOPixMap OOScalePixMap(OOPixMap srcPx, OOPixMapDimension dstWidth, OOPixMapDimen
if (srcPx.width < dstWidth)
{
// Stretch horizontally. This requires a separate buffer.
size_t dstSize = srcPx.components * dstWidth * srcPx.height;
size_t dstSize = OOPixMapBytesPerPixel(srcPx) * dstWidth * srcPx.height;
if (leaveSpaceForMipMaps) dstSize = dstSize * 4 / 3;
if (dstSize <= sparePx.bufferSize)
{
dstPx = OOMakePixMap(sparePx.pixels, dstWidth, srcPx.height, srcPx.components, 0, sparePx.bufferSize);
dstPx = OOMakePixMap(sparePx.pixels, dstWidth, srcPx.height, srcPx.format, 0, sparePx.bufferSize);
sparePx = kOONullPixMap;
}
else
{
dstPx = OOAllocatePixMap(dstWidth, srcPx.height, srcPx.components, 0, dstSize);
dstPx = OOAllocatePixMap(dstWidth, srcPx.height, srcPx.format, 0, dstSize);
}
if (EXPECT_NOT(!OOIsValidPixMap(dstPx))) { OK = NO; goto FAIL; }
@ -302,7 +308,7 @@ OOPixMap OOScalePixMap(OOPixMap srcPx, OOPixMapDimension dstWidth, OOPixMapDimen
dstPx = srcPx;
dstPx.width = dstWidth;
dstPx.rowBytes = dstPx.width * dstPx.components;
dstPx.rowBytes = dstPx.width * OOPixMapBytesPerPixel(dstPx);
DUMP_SCALE_DUMP(dstPx, @"squeezed horizontally");
}
else
@ -334,7 +340,7 @@ FAIL:
// FIXME: should take an OOPixMap.
BOOL OOGenerateMipMaps(void *textureBytes, OOPixMapDimension width, OOPixMapDimension height, OOPixMapComponentCount planes)
BOOL OOGenerateMipMaps(void *textureBytes, OOPixMapDimension width, OOPixMapDimension height, OOPixMapFormat format)
{
if (EXPECT_NOT(width != OORoundUpToPowerOf2(width) || height != OORoundUpToPowerOf2(height)))
{
@ -347,15 +353,23 @@ BOOL OOGenerateMipMaps(void *textureBytes, OOPixMapDimension width, OOPixMapDime
return NO;
}
switch (planes)
switch (format)
{
case 4: return GenerateMipMaps4(textureBytes, width, height);
case 2: return GenerateMipMaps2(textureBytes, width, height);
case 1: return GenerateMipMaps1(textureBytes, width, height);
case kOOPixMapRGBA:
return GenerateMipMaps4(textureBytes, width, height);
case kOOPixMapGrayscale:
return GenerateMipMaps1(textureBytes, width, height);
case kOOPixMapGrayscaleAlpha:
return GenerateMipMaps2(textureBytes, width, height);
case kOOPixMapInvalidFormat:
break;
}
OOLog(kOOLogParameterError, @"%s(): bad plane count (%u, should be 1 or 4) - ignoring, data will be junk.", __FUNCTION__, planes);
OOLog(kOOLogParameterError, @"%s(): bad pixmap format (%@) - ignoring, data will be junk.", __FUNCTION__, OOPixMapFormatName(format));
return NO;
}
@ -886,7 +900,7 @@ static void StretchVerticallyN_x1(OOPixMap srcPx, OOPixMap dstPx)
src0 = prev = src;
xCount = srcPx.width * srcPx.components;
xCount = srcPx.width * OOPixMapBytesPerPixel(srcPx);
for (y = 1; y != dstPx.height; ++y)
{
@ -934,7 +948,7 @@ static void StretchVerticallyN_x4(OOPixMap srcPx, OOPixMap dstPx)
src0 = prev = (uint32_t *)src;
xCount = (srcPx.width * srcPx.components) >> 2;
xCount = (srcPx.width * OOPixMapBytesPerPixel(srcPx)) >> 2;
for (y = 1; y != dstPx.height; ++y)
{
@ -984,7 +998,7 @@ static void StretchVerticallyN_x8(OOPixMap srcPx, OOPixMap dstPx)
src0 = prev = (uint64_t *)src;
xCount = (srcPx.width * srcPx.components) >> 3;
xCount = (srcPx.width * OOPixMapBytesPerPixel(srcPx)) >> 3;
for (y = 1; y != dstPx.height; ++y)
{
@ -1027,7 +1041,7 @@ static void StretchHorizontally1(OOPixMap srcPx, OOPixMap dstPx)
uint_fast16_t weight0, weight1;
uint_fast32_t fractX, deltaX; // X coordinate, fixed-point (20.12), allowing widths up to 1 mebipixel
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 1 && OOIsValidPixMap(dstPx) && dstPx.components == 1);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 1 && OOIsValidPixMap(dstPx) && OOPixMapBytesPerPixel(dstPx) == 1);
srcStart = srcPx.pixels;
srcRowBytes = srcPx.rowBytes;
@ -1086,7 +1100,7 @@ static void StretchHorizontally2(OOPixMap srcPx, OOPixMap dstPx)
uint_fast16_t weight0, weight1;
uint_fast32_t fractX, deltaX; // X coordinate, fixed-point (20.12), allowing widths up to 1 mebipixel
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 2 && OOIsValidPixMap(dstPx) && dstPx.components == 2);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 2 && OOIsValidPixMap(dstPx) && OOPixMapBytesPerPixel(dstPx) == 2);
srcStart = srcPx.pixels;
srcRowBytes = srcPx.rowBytes;
@ -1151,7 +1165,7 @@ static void StretchHorizontally4(OOPixMap srcPx, OOPixMap dstPx)
uint_fast16_t weight0, weight1;
uint_fast32_t fractX, deltaX; // X coordinate, fixed-point (20.12), allowing widths up to 1 mebipixel
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 4 && OOIsValidPixMap(dstPx) && dstPx.components == 4);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 4 && OOIsValidPixMap(dstPx) && OOPixMapBytesPerPixel(dstPx) == 4);
srcStart = srcPx.pixels;
srcRowBytes = srcPx.rowBytes;
@ -1216,7 +1230,7 @@ static void SqueezeHorizontally1(OOPixMap srcPx, OOPixMapDimension dstWidth)
uint_fast32_t accum, weight;
uint_fast8_t borderWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 1);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 1);
srcStart = srcPx.pixels;
dst = srcStart; // Output is placed in same buffer, without line padding.
@ -1278,7 +1292,7 @@ static void SqueezeVertically1(OOPixMap srcPx, OOPixMapDimension dstHeight)
uint_fast32_t accum, weight;
uint_fast8_t startWeight, endWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 1);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 1);
dst = srcPx.pixels; // Output is placed in same buffer, without line padding.
srcRowBytes = srcPx.rowBytes;
@ -1366,7 +1380,7 @@ static void SqueezeHorizontally2(OOPixMap srcPx, OOPixMapDimension dstWidth)
uint_fast32_t accumHi, accumLo, weight;
uint_fast8_t borderWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 2);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 2);
srcStart = srcPx.pixels;
dst = srcStart; // Output is placed in same buffer, without line padding.
@ -1427,7 +1441,7 @@ static void SqueezeVertically2(OOPixMap srcPx, OOPixMapDimension dstHeight)
uint_fast32_t accumHi, accumLo, weight;
uint_fast8_t startWeight, endWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 2);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 2);
dst = srcPx.pixels; // Output is placed in same buffer, without line padding.
srcRowBytes = srcPx.rowBytes;
@ -1514,7 +1528,7 @@ static void SqueezeVertically2(OOPixMap srcPx, OOPixMapDimension dstHeight)
*/
#define ACCUM4TOPX() ( \
(((accum1 / weight) & 0xFF) << 24) | \
(((accum3 / weight) & 0xFF) << 8) | \
(((accum3 / weight) & 0xFF) << 8) | \
(((accum2 / weight) & 0xFF) << 16) | \
((accum4 / weight) & 0xFF) \
)
@ -1529,7 +1543,7 @@ static void SqueezeHorizontally4(OOPixMap srcPx, OOPixMapDimension dstWidth)
uint_fast32_t accum1, accum2, accum3, accum4, weight;
uint_fast8_t borderWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 4);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 4);
srcStart = srcPx.pixels;
dst = srcStart; // Output is placed in same buffer, without line padding.
@ -1591,7 +1605,7 @@ static void SqueezeVertically4(OOPixMap srcPx, OOPixMapDimension dstHeight)
uint_fast32_t accum1, accum2, accum3, accum4, weight;
uint_fast8_t startWeight, endWeight;
NSCParameterAssert(OOIsValidPixMap(srcPx) && srcPx.components == 4);
NSCParameterAssert(OOIsValidPixMap(srcPx) && OOPixMapBytesPerPixel(srcPx) == 4);
dst = srcPx.pixels; // Output is placed in same buffer, without line padding.
srcRowBytes = srcPx.rowBytes;