--- a/hostsupport/hostopenvg/src/src/riImage.h Wed Oct 06 17:59:01 2010 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1593 +0,0 @@
-#ifndef __RIIMAGE_H
-#define __RIIMAGE_H
-
-/*------------------------------------------------------------------------
- *
- * OpenVG 1.1 Reference Implementation
- * -----------------------------------
- *
- * Copyright (c) 2007 The Khronos Group Inc.
- * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and /or associated documentation files
- * (the "Materials "), to deal in the Materials without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Materials,
- * and to permit persons to whom the Materials are furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Materials.
- *
- * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
- * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
- * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
- * THE USE OR OTHER DEALINGS IN THE MATERIALS.
- *
- *//**
- * \file
- * \brief Color and Image classes.
- * \note
- *//*-------------------------------------------------------------------*/
-
-#ifndef _OPENVG_H
-#include "VG/openvg.h"
-#endif
-
-#ifndef __RIMATH_H
-#include "riMath.h"
-#endif
-
-#ifndef __RIARRAY_H
-#include "riArray.h"
-#endif
-
-#include "sfAlphaRcp.h"
-#include "sfGammaLUT.h"
-#include "riUtils.h"
-
-//==============================================================================================
-
-namespace OpenVGRI
-{
-
-class VGContext;
-class DynamicBlitter;
-
-/*-------------------------------------------------------------------*//*!
-* \brief A class representing rectangles.
-* \param
-* \return
-* \note
-*//*-------------------------------------------------------------------*/
-
-class Rectangle
-{
-public:
- Rectangle() : x(0), y(0), width(0), height(0) {}
- Rectangle(int rx, int ry, int rw, int rh) : x(rx), y(ry), width(rw), height(rh) {}
- void intersect(const Rectangle& r)
- {
- if(width >= 0 && r.width >= 0 && height >= 0 && r.height >= 0)
- {
- int x1 = RI_INT_MIN(RI_INT_ADDSATURATE(x, width), RI_INT_ADDSATURATE(r.x, r.width));
- x = RI_INT_MAX(x, r.x);
- width = RI_INT_MAX(x1 - x, 0);
-
- int y1 = RI_INT_MIN(RI_INT_ADDSATURATE(y, height), RI_INT_ADDSATURATE(r.y, r.height));
- y = RI_INT_MAX(y, r.y);
- height = RI_INT_MAX(y1 - y, 0);
- }
- else
- {
- x = 0;
- y = 0;
- width = 0;
- height = 0;
- }
- }
- bool isEmpty() const { return width == 0 || height == 0; }
-
- int x;
- int y;
- int width;
- int height;
-};
-
-/*-------------------------------------------------------------------*//*!
-* \brief A class representing color for processing and converting it
-* to and from various surface formats.
-* \param
-* \return
-* \note
-*//*-------------------------------------------------------------------*/
-
-class Color
-{
-public:
- enum FormatSize
- {
- SIZE_1 = 0,
- SIZE_4 = 1,
- SIZE_8 = 2,
- SIZE_16 = 3,
- SIZE_24 = 4,
- SIZE_32 = 5
- };
-
- enum Shape
- {
- SHAPE_RGBA = 0,
- SHAPE_RGBX = 1,
- SHAPE_RGB = 2,
- SHAPE_LA = 3,
- SHAPE_L = 4,
- SHAPE_A = 5,
- SHAPE_ARGB = 6,
- SHAPE_XRGB = 7,
- SHAPE_AL = 8,
- SHAPE_BGRA = 9,
- SHAPE_BGRX = 10,
- SHAPE_BGR = 11,
- SHAPE_ABGR = 12,
- SHAPE_XBGR = 13
- };
- enum InternalFormat
- {
- lRGBA = 0,
- sRGBA = 1,
- lRGBA_PRE = 2,
- sRGBA_PRE = 3,
- lLA = 4,
- sLA = 5,
- lLA_PRE = 6,
- sLA_PRE = 7
- };
- enum FormatBits
- {
- NONLINEAR = (1<<0),
- PREMULTIPLIED = (1<<1),
- LUMINANCE = (1<<2)
- };
- struct SmallDescriptor
- {
- RIuint32 toUint32()
- {
- RIuint32 ret = 0;
- ret = (RIuint32)size;
- ret |= (RIuint32)shape << 3;
- ret |= (RIuint32)internalFormat << (3 + 4);
- return ret;
- }
- FormatSize size;
- Shape shape;
- InternalFormat internalFormat;
- };
- class Descriptor
- {
- public:
- Descriptor() {};
- RI_INLINE Descriptor(int dredBits, int dredShift, int dgreenBits, int dgreenShift, int dblueBits, int dblueShift, int dalphaBits, int dalphaShift, int dluminanceBits, int dluminanceShift, InternalFormat dinternalFormat, int dbpp, Shape shape);
- RI_INLINE bool isNonlinear() const { return (internalFormat & NONLINEAR) ? true : false; }
- RI_INLINE void setNonlinear(bool nonlinear);
- RI_INLINE bool isPremultiplied() const { return (internalFormat & PREMULTIPLIED) ? true : false; }
- RI_INLINE bool isLuminance() const { return (internalFormat & LUMINANCE) ? true : false; }
- RI_INLINE bool isAlphaOnly() const { return (alphaBits && (redBits+greenBits+blueBits+luminanceBits) == 0) ? true : false; }
- RI_INLINE bool isBW() const { return isLuminance() && (luminanceBits == 1); }
- RI_INLINE bool hasAlpha() const { return alphaBits > 0; }
- RI_INLINE bool operator==(const Descriptor& rhs) const;
- RI_INLINE bool isShiftConversionToLower(const Descriptor& rhs) const;
- RI_INLINE bool isShiftConversion(const Descriptor& rhs) const;
- RI_INLINE bool isZeroConversion(const Descriptor& rhs) const;
- RI_INLINE bool maybeUnsafe() const { return internalFormat & PREMULTIPLIED ? true : false; };
- static RI_INLINE RIuint32 crossConvertToLower(RIuint32 c, const Descriptor& src, const Descriptor& dst);
- void toSmallDescriptor(SmallDescriptor& smallDesc) const;
- RI_INLINE RIuint32 toIndex() const;
- static Descriptor getDummyDescriptor();
- Shape getShape() const;
-
- int redBits;
- int redShift;
- int greenBits;
- int greenShift;
- int blueBits;
- int blueShift;
- int alphaBits;
- int alphaShift;
- int luminanceBits;
- int luminanceShift;
- Shape shape;
- VGImageFormat vgFormat; // \note Storage only
- InternalFormat internalFormat;
- int bitsPerPixel;
- // Derived info:
- int bytesPerPixel;
- int maskBits;
- int maskShift;
- };
-
- RI_INLINE Color() : r(0.0f), g(0.0f), b(0.0f), a(0.0f), m_format(sRGBA_PRE) {}
- RI_INLINE Color(RIfloat cl, RIfloat ca, InternalFormat cs) : r(cl), g(cl), b(cl), a(ca), m_format(cs) { RI_ASSERT(cs == lLA || cs == sLA || cs == lLA_PRE || cs == sLA_PRE); }
- RI_INLINE Color(RIfloat cr, RIfloat cg, RIfloat cb, RIfloat ca, InternalFormat cs) : r(cr), g(cg), b(cb), a(ca), m_format(cs) { RI_ASSERT(cs == lRGBA || cs == sRGBA || cs == lRGBA_PRE || cs == sRGBA_PRE || cs == lLA || cs == sLA || cs == lLA_PRE || cs == sLA_PRE); }
- RI_INLINE Color(const Color& c) : r(c.r), g(c.g), b(c.b), a(c.a), m_format(c.m_format) {}
- RI_INLINE Color& operator=(const Color&c) { r = c.r; g = c.g; b = c.b; a = c.a; m_format = c.m_format; return *this; }
- RI_INLINE void operator*=(RIfloat f) { r *= f; g *= f; b *= f; a*= f; }
- RI_INLINE void operator+=(const Color& c1) { RI_ASSERT(m_format == c1.getInternalFormat()); r += c1.r; g += c1.g; b += c1.b; a += c1.a; }
- RI_INLINE void operator-=(const Color& c1) { RI_ASSERT(m_format == c1.getInternalFormat()); r -= c1.r; g -= c1.g; b -= c1.b; a -= c1.a; }
-
- void set(RIfloat cl, RIfloat ca, InternalFormat cs) { RI_ASSERT(cs == lLA || cs == sLA || cs == lLA_PRE || cs == sLA_PRE); r = cl; g = cl; b = cl; a = ca; m_format = cs; }
- void set(RIfloat cr, RIfloat cg, RIfloat cb, RIfloat ca, InternalFormat cs) { RI_ASSERT(cs == lRGBA || cs == sRGBA || cs == lRGBA_PRE || cs == sRGBA_PRE); r = cr; g = cg; b = cb; a = ca; m_format = cs; }
- void unpack(unsigned int inputData, const Descriptor& inputDesc);
- unsigned int pack(const Descriptor& outputDesc) const;
- RI_INLINE InternalFormat getInternalFormat() const { return m_format; }
-
- //clamps nonpremultiplied colors and alpha to [0,1] range, and premultiplied alpha to [0,1], colors to [0,a]
- void clamp() { a = RI_CLAMP(a,0.0f,1.0f); RIfloat u = (m_format & PREMULTIPLIED) ? a : (RIfloat)1.0f; r = RI_CLAMP(r,0.0f,u); g = RI_CLAMP(g,0.0f,u); b = RI_CLAMP(b,0.0f,u); }
- void convert(InternalFormat outputFormat);
- void premultiply() { if(!(m_format & PREMULTIPLIED)) { r *= a; g *= a; b *= a; m_format = (InternalFormat)(m_format | PREMULTIPLIED); } }
- void unpremultiply() { if(m_format & PREMULTIPLIED) { RIfloat ooa = (a != 0.0f) ? 1.0f/a : (RIfloat)0.0f; r *= ooa; g *= ooa; b *= ooa; m_format = (InternalFormat)(m_format & ~PREMULTIPLIED); } }
- void luminanceToRGB() { if(m_format & LUMINANCE) { RI_ASSERT(r == g && g == b); m_format = (InternalFormat)(m_format & ~LUMINANCE); } }
-
- bool isNonlinear() const { return (m_format & NONLINEAR) ? true : false; }
- bool isPremultiplied() const { return (m_format & PREMULTIPLIED) ? true : false; }
- bool isLuminance() const { return (m_format & LUMINANCE) ? true : false; }
-
- RI_INLINE void assertConsistency() const;
-
- // \note Why are these in the color class instead of descriptor?
- static VGImageFormat descriptorToVGImageFormat(const Descriptor& desc);
- RI_INLINE static Descriptor formatToDescriptorConst(VGImageFormat format);
- static Descriptor formatToDescriptor(VGImageFormat format);
- static bool isValidDescriptor(const Descriptor& desc);
-
- RIfloat r;
- RIfloat g;
- RIfloat b;
- RIfloat a;
-private:
- InternalFormat m_format;
-};
-
-RI_INLINE Color::Descriptor::Descriptor(int dredBits, int dredShift, int dgreenBits, int dgreenShift, int dblueBits, int dblueShift, int dalphaBits, int dalphaShift, int dluminanceBits, int dluminanceShift, InternalFormat dinternalFormat, int dbpp, Shape shape) :
- redBits(dredBits),
- redShift(dredShift),
- greenBits(dgreenBits),
- greenShift(dgreenShift),
- blueBits(dblueBits),
- blueShift(dblueShift),
- alphaBits(dalphaBits),
- alphaShift(dalphaShift),
- luminanceBits(dluminanceBits),
- luminanceShift(dluminanceShift),
- shape(shape),
- internalFormat(dinternalFormat),
- bitsPerPixel(dbpp)
-{
- bytesPerPixel = bitsPerPixel / 8;
-
- if (alphaBits)
- {
- maskBits = alphaBits;
- maskShift = alphaShift;
- }
- else if (!this->isLuminance())
- {
- maskBits = redBits;
- maskShift = redShift;
- }
- else
- {
- maskBits = luminanceBits;
- maskShift = luminanceShift;
- }
- RI_ASSERT(getShape() == shape);
-}
-
-RI_INLINE void Color::Descriptor::setNonlinear(bool nonlinear)
-{
- if (nonlinear)
- internalFormat = (InternalFormat)(((RIuint32)internalFormat)|NONLINEAR);
- else
- internalFormat = (InternalFormat)(((RIuint32)internalFormat)&(~NONLINEAR));
-}
-
-/**
- * \brief Creates a pixel format descriptor out of VGImageFormat
- * \todo The formats without alpha were non-premultiplied in the reference
- * implementation, but wouldn't it make more sense to consider them
- * premultiplied? This would make sense at least when blitting to
- * windows, etc., where the output color should have the alpha
- * multiplied "in".
- */
-RI_INLINE Color::Descriptor Color::formatToDescriptorConst(VGImageFormat format)
-{
- switch(format)
- {
- case VG_sRGBX_8888:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 0, 0, 0, 0, Color::sRGBA, 32, SHAPE_RGBX);
- case VG_sRGBA_8888:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 8, 0, 0, 0, Color::sRGBA, 32, SHAPE_RGBA);
- case VG_sRGBA_8888_PRE:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 8, 0, 0, 0, Color::sRGBA_PRE, 32, SHAPE_RGBA);
- case VG_sRGB_565:
- return Color::Descriptor(5, 11, 6, 5, 5, 0, 0, 0, 0, 0, Color::sRGBA, 16, SHAPE_RGB);
- case VG_sRGBA_5551:
- return Color::Descriptor(5, 11, 5, 6, 5, 1, 1, 0, 0, 0, Color::sRGBA, 16, SHAPE_RGBA);
- case VG_sRGBA_4444:
- return Color::Descriptor(4, 12, 4, 8, 4, 4, 4, 0, 0, 0, Color::sRGBA, 16, SHAPE_RGBA);
- case VG_sL_8:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 0, 0, 8, 0, Color::sLA, 8, SHAPE_L);
- case VG_lRGBX_8888:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 0, 0, 0, 0, Color::lRGBA, 32, SHAPE_RGBX);
- case VG_lRGBA_8888:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 8, 0, 0, 0, Color::lRGBA, 32, SHAPE_RGBA);
- case VG_lRGBA_8888_PRE:
- return Color::Descriptor(8, 24, 8, 16, 8, 8, 8, 0, 0, 0, Color::lRGBA_PRE, 32, SHAPE_RGBA);
- case VG_lL_8:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 0, 0, 8, 0, Color::lLA, 8, SHAPE_L);
- case VG_A_8:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 8, 0, 0, 0, Color::lRGBA, 8, SHAPE_A);
- case VG_BW_1:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 0, 0, 1, 0, Color::lLA, 1, SHAPE_L);
- case VG_A_1:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 1, 0, 0, 0, Color::lRGBA, 1, SHAPE_A);
- case VG_A_4:
- return Color::Descriptor(0, 0, 0, 0, 0, 0, 4, 0, 0, 0, Color::lRGBA, 4, SHAPE_A);
-
- /* {A,X}RGB channel ordering */
- case VG_sXRGB_8888:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 0, 0, 0, 0, Color::sRGBA, 32, SHAPE_XRGB);
- case VG_sARGB_8888:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 8, 24, 0, 0, Color::sRGBA, 32, SHAPE_ARGB);
- case VG_sARGB_8888_PRE:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 8, 24, 0, 0, Color::sRGBA_PRE, 32, SHAPE_ARGB);
- case VG_sARGB_1555:
- return Color::Descriptor(5, 10, 5, 5, 5, 0, 1, 15, 0, 0, Color::sRGBA, 16, SHAPE_ARGB);
- case VG_sARGB_4444:
- return Color::Descriptor(4, 8, 4, 4, 4, 0, 4, 12, 0, 0, Color::sRGBA, 16, SHAPE_ARGB);
- case VG_lXRGB_8888:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 0, 0, 0, 0, Color::lRGBA, 32, SHAPE_XRGB);
- case VG_lARGB_8888:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 8, 24, 0, 0, Color::lRGBA, 32, SHAPE_ARGB);
- case VG_lARGB_8888_PRE:
- return Color::Descriptor(8, 16, 8, 8, 8, 0, 8, 24, 0, 0, Color::lRGBA_PRE, 32, SHAPE_ARGB);
-
- /* BGR{A,X} channel ordering */
- case VG_sBGRX_8888:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 0, 0, 0, 0, Color::sRGBA, 32, SHAPE_BGRX);
- case VG_sBGRA_8888:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 8, 0, 0, 0, Color::sRGBA, 32, SHAPE_BGRA);
- case VG_sBGRA_8888_PRE:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 8, 0, 0, 0, Color::sRGBA_PRE, 32, SHAPE_BGRA);
- case VG_sBGR_565:
- return Color::Descriptor(5, 0, 6, 5, 5, 11, 0, 0, 0, 0, Color::sRGBA, 16, SHAPE_BGR);
- case VG_sBGRA_5551:
- return Color::Descriptor(5, 1, 5, 6, 5, 11, 1, 0, 0, 0, Color::sRGBA, 16, SHAPE_BGRA);
- case VG_sBGRA_4444:
- return Color::Descriptor(4, 4, 4, 8, 4, 12, 4, 0, 0, 0, Color::sRGBA, 16, SHAPE_BGRA);
- case VG_lBGRX_8888:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 0, 0, 0, 0, Color::lRGBA, 32, SHAPE_BGRX);
- case VG_lBGRA_8888:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 8, 0, 0, 0, Color::lRGBA, 32, SHAPE_BGRA);
- case VG_lBGRA_8888_PRE:
- return Color::Descriptor(8, 8, 8, 16, 8, 24, 8, 0, 0, 0, Color::lRGBA_PRE, 32, SHAPE_BGRA);
-
- /* {A,X}BGR channel ordering */
- case VG_sXBGR_8888:
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 0, 0, 0, 0, Color::sRGBA, 32, SHAPE_XBGR);
- case VG_sABGR_8888:
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 8, 24, 0, 0, Color::sRGBA, 32, SHAPE_ABGR);
- case VG_sABGR_8888_PRE:
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 8, 24, 0, 0, Color::sRGBA_PRE, 32, SHAPE_ABGR);
- case VG_sABGR_1555:
- return Color::Descriptor(5, 0, 5, 5, 5, 10, 1, 15, 0, 0, Color::sRGBA, 16, SHAPE_ABGR);
- case VG_sABGR_4444:
- return Color::Descriptor(4, 0, 4, 4, 4, 8, 4, 12, 0, 0, Color::sRGBA, 16, SHAPE_ABGR);
- case VG_lXBGR_8888:
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 0, 0, 0, 0, Color::lRGBA, 32, SHAPE_XBGR);
- case VG_lABGR_8888:
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 8, 24, 0, 0, Color::lRGBA, 32, SHAPE_ABGR);
- default:
- //case VG_lABGR_8888_PRE:
- RI_ASSERT(format == VG_lABGR_8888_PRE);
- return Color::Descriptor(8, 0, 8, 8, 8, 16, 8, 24, 0, 0, Color::lRGBA_PRE, 32, SHAPE_ABGR);
- }
-}
-
-RI_INLINE bool Color::Descriptor::operator==(const Descriptor& rhs) const
-{
- return memcmp(this, &rhs, sizeof(Descriptor)) ? false : true;
-}
-
-RI_INLINE bool Color::Descriptor::isZeroConversion(const Descriptor& rhs) const
-{
- return (shape == rhs.shape) &&
- (internalFormat == rhs.internalFormat) &&
- (redBits == rhs.redBits) &&
- (greenBits == rhs.greenBits) &&
- (blueBits == rhs.blueBits) &&
- (alphaBits == rhs.alphaBits) &&
- (luminanceBits == rhs.luminanceBits);
-}
-
-RI_INLINE bool Color::Descriptor::isShiftConversion(const Descriptor& rhs) const
-{
- // \note BW conversion is always forced to full at the moment.
- if (isBW() != rhs.isBW())
- return false;
-
- return (isPremultiplied() == rhs.isPremultiplied())
- && (isNonlinear() == rhs.isNonlinear())
- && (isLuminance() == rhs.isLuminance());
-}
-
-RI_INLINE bool Color::Descriptor::isShiftConversionToLower(const Descriptor& rhs) const
-{
- // \note BW conversion is always forced to full at the moment.
- if (isBW() != rhs.isBW())
- return false;
- // \note Mask bits are not checked because they are derived information.
- return (isShiftConversion(rhs)
- && (rhs.redBits <= redBits)
- && (rhs.greenBits <= greenBits)
- && (rhs.blueBits <= blueBits)
- && (rhs.alphaBits <= alphaBits)
- && (rhs.luminanceBits <= luminanceBits));
-
-}
-
-/**
- * \brief In-place conversion of packed color to lower bit-depth
- * \param c Input packed color
- * \param src Source color descriptor
- * \param dst Destination color descriptor
- */
-RI_INLINE RIuint32 Color::Descriptor::crossConvertToLower(RIuint32 c, const Descriptor& src, const Descriptor& dst)
-{
- RIuint32 r = 0;
-
- RI_ASSERT(dst.redBits <= src.redBits);
- RI_ASSERT(dst.greenBits <= src.greenBits);
- RI_ASSERT(dst.blueBits <= src.blueBits);
- RI_ASSERT(dst.alphaBits <= src.alphaBits);
-
- if (src.isLuminance())
- {
- RI_ASSERT(dst.isLuminance());
- r = ((c >> (src.luminanceShift + src.luminanceBits - dst.luminanceBits)) & ((1u<<dst.luminanceBits)-1)) << dst.luminanceShift;
- } else
- {
- r = ((c >> (src.redShift + src.redBits - dst.redBits)) & ((1u<<dst.redBits)-1)) << dst.redShift;
- r |= ((c >> (src.greenShift + src.greenBits - dst.greenBits)) & ((1u<<dst.greenBits)-1)) << dst.greenShift;
- r |= ((c >> (src.blueShift + src.blueBits - dst.blueBits)) & ((1u<<dst.blueBits)-1)) << dst.blueShift;
- }
-
- if (src.hasAlpha())
- {
- if (dst.hasAlpha())
- r |= ((c >> (src.alphaShift + src.alphaBits - dst.alphaBits)) & ((1u<<dst.alphaBits)-1)) << dst.alphaShift;
- else
- {
- // Make sure that the alpha is applied to the color if doing only a shift conversion.
- RI_ASSERT(src.isPremultiplied() == dst.isPremultiplied());
- }
- }
-
- return r;
-}
-
-RI_INLINE RIuint32 Color::Descriptor::toIndex() const
-{
- SmallDescriptor smallDesc;
- toSmallDescriptor(smallDesc);
- return smallDesc.toUint32();
-}
-
-RI_INLINE Color operator*(const Color& c, RIfloat f) { return Color(c.r*f, c.g*f, c.b*f, c.a*f, c.getInternalFormat()); }
-RI_INLINE Color operator*(RIfloat f, const Color& c) { return Color(c.r*f, c.g*f, c.b*f, c.a*f, c.getInternalFormat()); }
-RI_INLINE Color operator+(const Color& c0, const Color& c1) { RI_ASSERT(c0.getInternalFormat() == c1.getInternalFormat()); return Color(c0.r+c1.r, c0.g+c1.g, c0.b+c1.b, c0.a+c1.a, c0.getInternalFormat()); }
-RI_INLINE Color operator-(const Color& c0, const Color& c1) { RI_ASSERT(c0.getInternalFormat() == c1.getInternalFormat()); return Color(c0.r-c1.r, c0.g-c1.g, c0.b-c1.b, c0.a-c1.a, c0.getInternalFormat()); }
-RI_INLINE void Color::assertConsistency() const
-{
- RI_ASSERT(r >= 0.0f && r <= 1.0f);
- RI_ASSERT(g >= 0.0f && g <= 1.0f);
- RI_ASSERT(b >= 0.0f && b <= 1.0f);
- RI_ASSERT(a >= 0.0f && a <= 1.0f);
- RI_ASSERT(!isPremultiplied() || (r <= a && g <= a && b <= a)); //premultiplied colors must have color channels less than or equal to alpha
- RI_ASSERT((isLuminance() && r == g && r == b) || !isLuminance()); //if luminance, r=g=b
-}
-
-class IntegerColor
-{
-public:
-
- IntegerColor() {r = g = b = a = 0;}
- IntegerColor(const Color& color);
-
- RI_INLINE IntegerColor(RIuint32 packedColor, const Color::Descriptor& desc) { fromPackedColor(packedColor, desc); }
- RI_INLINE IntegerColor(RIuint32 cr, RIuint32 cg, RIuint32 cb, RIuint32 ca) { r = cr; g = cg; b = cb; a = ca; }
- RI_INLINE void asFixedPoint(const Color& color);
- RI_INLINE void fromPackedColor(RIuint32 packedColor, const Color::Descriptor& desc);
- RI_INLINE void expandColor(const Color::Descriptor& desc);
- RI_INLINE void truncateColor(const Color::Descriptor& desc);
- RI_INLINE void clampToAlpha();
- RI_INLINE RIuint32 getPackedColor(const Color::Descriptor& desc) const;
- RI_INLINE RIuint32 getPackedMaskColor(const Color::Descriptor& desc) const;
- RI_INLINE void premultiply(bool luminance = false);
- RI_INLINE void unpremultiply(bool luminance = false);
- //RI_INLINE void linearToGamma(bool luminance, bool premultipliedIn, bool premultipliedOut);
- RI_INLINE void linearToGamma(bool luminance = false);
- RI_INLINE void gammaToLinear(bool luminance = false);
- RI_INLINE void fromPackedMask(RIuint32 packedColor, const Color::Descriptor& desc);
- RI_INLINE void expandMask(const Color::Descriptor& desc);
- RI_INLINE void truncateMask(const Color::Descriptor& desc);
- RI_INLINE void fullLuminanceToRGB(bool premultipliedIn, bool gammaIn, bool premultipliedOut, bool gammaOut);
- RI_INLINE void fullRGBToLuminance(bool premultipliedIn, bool gammaIn, bool premultipliedOut, bool gammaOut);
- RI_INLINE void luminanceToRGB();
- RI_INLINE void rgbToLuminance();
- RI_INLINE void convertToFrom(const Color::Descriptor& dst, const Color::Descriptor& src, bool srcIsMask);
-
- RI_INLINE static IntegerColor linearBlendNS(const IntegerColor& c0, const IntegerColor& c1, int k);
-
- RIuint32 r;
- RIuint32 g;
- RIuint32 b;
- RIuint32 a;
-
-};
-
-/**
- * \brief Blend two colors linearly. The output will not be scaled into original range.
- * \param k Blend coefficient. Must be [0..255] for correct results.
- * \todo Parameterize against bits in k? To perform well, that setup must be compiled rt.
- */
-RI_INLINE IntegerColor IntegerColor::linearBlendNS(const IntegerColor& c0, const IntegerColor& c1, int k)
-{
- RI_ASSERT(k >= 0 && k <= 255);
- IntegerColor ret;
- RIuint32 ik = 255 - k;
-
- ret.r = ik * c0.r + k * c1.r;
- ret.g = ik * c0.g + k * c1.g;
- ret.b = ik * c0.b + k * c1.b;
- ret.a = ik * c0.a + k * c1.a;
-
- return ret;
-}
-
-/**
- * \note Assumes that each individual component is in proper range (usually indicated by the
- * corresponding shift).
- */
-RI_INLINE RIuint32 packRGBAInteger(RIuint32 cr, int rs, RIuint32 cg, int gs, RIuint32 cb, int bs, RIuint32 ca, int as)
-{
- return (cr << rs) | (cg << gs) | (cb << bs) | (ca << as);
-}
-
-/**
- * \brief Packs a color into RIuint32.
- * \note The color must have been truncated to contain correct amount of bits per channel
- * \note This function is efficient only if runtime compilation is used.
- */
-RI_INLINE RIuint32 IntegerColor::getPackedColor(const Color::Descriptor& desc) const
-{
- RIuint32 res = 0;
- if (desc.luminanceBits)
- {
- RI_ASSERT(desc.redBits == 0 && desc.greenBits == 0 && desc.blueBits == 0);
- RI_ASSERT(r < (1u<<desc.luminanceBits));
- res = r << desc.luminanceShift;
- }
- else if (desc.redBits)
- {
- RI_ASSERT(r < (1u<<desc.redBits));
- res = r << desc.redShift;
- if (desc.greenBits)
- {
- RI_ASSERT(desc.blueBits);
- RI_ASSERT(g < (1u<<desc.greenBits));
- RI_ASSERT(b < (1u<<desc.blueBits));
- res |= g << desc.greenShift;
- res |= b << desc.blueShift;
- }
- }
-
- if (desc.alphaBits)
- {
- RI_ASSERT(a < (1u<<desc.alphaBits));
- res |= a << desc.alphaShift;
- }
-
- return res;
-}
-
-RI_INLINE RIuint32 IntegerColor::getPackedMaskColor(const Color::Descriptor& desc) const
-{
- if (desc.alphaBits)
- return packRGBAInteger(0, desc.redShift, 0, desc.greenShift, 0, desc.blueShift, a, desc.alphaShift);
- else if(desc.redBits)
- return packRGBAInteger(a, desc.redShift, 0, desc.greenShift, 0, desc.blueShift, 0, desc.alphaShift);
- else
- {
- RI_ASSERT(desc.luminanceBits);
- return packRGBAInteger(a, desc.luminanceBits, 0, desc.greenShift, 0, desc.blueShift, 0, desc.alphaShift);
- }
-
-}
-
-RI_INLINE void IntegerColor::premultiply(bool luminance)
-{
- // \todo Check the round!!!
- RIuint32 fxa = a + (a>>7);
- r = (r * fxa); r = (r + (1<<7))>>8;
-
- if (!luminance)
- {
- g = (g * fxa); g = (g + (1<<7))>>8;
- b = (b * fxa); b = (b + (1<<7))>>8;
- }
-}
-
-RI_INLINE void IntegerColor::unpremultiply(bool luminance)
-{
- RI_ASSERT(a <= 255);
-
- RIuint32 rcp = sc_alphaRcp[a];
- r = (r * rcp) >> 8;
-
- if (!luminance)
- {
- g = (g * rcp) >> 8;
- b = (b * rcp) >> 8;
- }
-}
-
-RI_INLINE void IntegerColor::linearToGamma(bool luminance)
-{
- RI_ASSERT(r <= 255 && g <= 255 && b <= 255 && a <= 255);
-
- r = sc_lRGB_to_sRGB[r];
-
- if (!luminance)
- {
- g = sc_lRGB_to_sRGB[g];
- b = sc_lRGB_to_sRGB[b];
- }
-
- // \note Alpha is _not_ converted and it must be considered linear always
-}
-
-RI_INLINE void IntegerColor::gammaToLinear(bool luminance)
-{
- RI_ASSERT(r <= 255 && g <= 255 && b <= 255 && a <= 255);
-
- r = sc_sRGB_to_lRGB[r];
- if (!luminance)
- {
- g = sc_sRGB_to_lRGB[g];
- b = sc_sRGB_to_lRGB[b];
- }
-
- // \note Alpha is _not_ converted and it must be considered linear always
-}
-
-RI_INLINE void IntegerColor::asFixedPoint(const Color& color)
-{
- r = (RIuint32)(color.r * 256.0f + 0.5f);
- g = (RIuint32)(color.g * 256.0f + 0.5f);
- b = (RIuint32)(color.b * 256.0f + 0.5f);
- a = (RIuint32)(color.a * 256.0f + 0.5f);
-}
-
-RI_INLINE void IntegerColor::fromPackedColor(RIuint32 packedColor, const Color::Descriptor& desc)
-{
- /* \note Expand MUST be done separately! */
-
- if (desc.luminanceBits)
- {
- r = (packedColor >> desc.luminanceShift) & ((1u << desc.luminanceBits)-1);
- g = b = r;
- }
- else
- {
- r = (packedColor >> desc.redShift) & ((1u << desc.redBits)-1);
- g = (packedColor >> desc.greenShift) & ((1u << desc.greenBits)-1);
- b = (packedColor >> desc.blueShift) & ((1u << desc.blueBits)-1);
- }
-
- if (desc.alphaBits)
- a = (packedColor >> desc.alphaShift) & ((1u << desc.alphaBits)-1);
- else
- a = 255;
-}
-
-/**
- * \brief Expand color to larger (or same) bit depth as in the OpenVG specification.
- * \todo 1 and 2 bpp!
- */
-RI_INLINE RIuint32 expandComponent(RIuint32 c, RIuint32 srcBits)
-{
- const RIuint32 destBits = 8;
- RI_ASSERT(destBits >= srcBits);
-
- if (!srcBits) return 0;
-
- if (srcBits == destBits) return c;
-
- switch (srcBits)
- {
- case 6:
- return (c << 2) | (c >> 4);
- case 5:
- return (c << 3) | (c >> 2);
- case 4:
- return (c << 4) | c;
- case 2:
- return c | (c << 2) | (c << 4) | (c << 6);
- default:
- RI_ASSERT(srcBits == 1);
- if (c) return 0xff;
- return 0;
- }
-}
-
-/**
- * \brief Expands integer color representation to internal format (8-bits per component atm.).
- * \todo Do nothing when bits == 8.
- */
-RI_INLINE void IntegerColor::expandColor(const Color::Descriptor& desc)
-{
- if (desc.luminanceBits)
- {
- r = expandComponent(r, desc.luminanceBits);
- g = b = r;
- a = 255;
- } else
- {
- if (desc.redBits < 8 || desc.luminanceBits < 8)
- r = expandComponent(r, desc.redBits);
- if (desc.greenBits < 8)
- g = expandComponent(g, desc.greenBits);
- if (desc.blueBits < 8)
- b = expandComponent(b, desc.blueBits);
- }
-
- if (desc.alphaBits && desc.alphaBits < 8)
- a = expandComponent(a, desc.alphaBits);
-
- if (desc.isAlphaOnly())
- {
- if (!desc.isPremultiplied())
- r = g = b = 255;
- else
- r = g = b = a;
- }
-}
-
-/**
- * \brief Convert IntegerColor components to destination bitdepth (from internal) by
- * shifting. Rounding does not take place.
- */
-RI_INLINE void IntegerColor::truncateColor(const Color::Descriptor& desc)
-{
- if (desc.luminanceBits)
- {
- RI_ASSERT(desc.redBits == 0 && desc.greenBits == 0 && desc.blueBits == 0);
- if (desc.luminanceBits == 1)
- {
- // Round the 1-bit case a bit better?
- r = (r + 128)>>8;
- } else if (desc.luminanceBits < 8)
- r >>= (8 - desc.luminanceBits);
- }
- else
- {
- if (desc.redBits < 8)
- r >>= (8 - desc.redBits);
- if (desc.greenBits < 8)
- g >>= (8 - desc.greenBits);
- if (desc.blueBits < 8)
- b >>= (8 - desc.blueBits);
- }
-
- if (desc.alphaBits < 8)
- {
- if (desc.alphaBits == 1)
- a = (a+128)>>8;
- else
- a >>= (8 - desc.alphaBits);
- }
-}
-
-RI_INLINE void IntegerColor::truncateMask(const Color::Descriptor& desc)
-{
- if (desc.redBits < 8 || desc.luminanceBits < 8)
- r >>= (8 - desc.maskBits);
- if (desc.greenBits < 8)
- g >>= (8 - desc.maskBits);
- if (desc.blueBits < 8)
- b >>= (8 - desc.maskBits);
- if (desc.alphaBits < 8)
- a >>= (8 - desc.maskBits);
-}
-
-RI_INLINE void IntegerColor::clampToAlpha()
-{
- if (r > a) r = a;
- if (g > a) g = a;
- if (b > a) b = a;
-}
-
-RI_INLINE void IntegerColor::fromPackedMask(RIuint32 packedMask, const Color::Descriptor& desc)
-{
- RI_ASSERT(desc.maskBits);
- a = (packedMask >> desc.maskShift) & ((1u << desc.maskBits)-1);
-}
-
-RI_INLINE void IntegerColor::expandMask(const Color::Descriptor& desc)
-{
- a = expandComponent(a, desc.maskBits);
- r = g = b = a;
-}
-
-#if 0
-RI_INLINE void IntegerColor::truncateMask(const Color::Descriptor& desc)
-{
- a >>= (8 - desc.maskBits);
-}
-#endif
-
-RI_INLINE void IntegerColor::fullLuminanceToRGB(bool premultipliedIn, bool gammaIn, bool premultipliedOut, bool gammaOut)
-{
- if (premultipliedIn)
- unpremultiply();
-
- luminanceToRGB();
-
- if (gammaIn != gammaOut)
- {
- if (gammaIn)
- gammaToLinear();
- else
- linearToGamma();
- }
-
- if (premultipliedOut)
- premultiply();
-
-}
-
-RI_INLINE void IntegerColor::fullRGBToLuminance(bool premultipliedIn, bool gammaIn, bool premultipliedOut, bool gammaOut)
-{
- if (premultipliedIn)
- unpremultiply();
-
- if (gammaIn)
- gammaToLinear();
-
- rgbToLuminance();
-
- if (gammaOut)
- linearToGamma();
-
- if (premultipliedOut)
- premultiply();
-
-}
-
-
-// \todo This should not be needed (only r-channel is used anyway)
-RI_INLINE void IntegerColor::luminanceToRGB()
-{
- g = b = r;
-}
-
-// \todo Only write to R!
-RI_INLINE void IntegerColor::rgbToLuminance()
-{
- enum { Rx = 871, Gx = 2929, Bx = 296, Bits = 12 };
- //enum { Rx = 54, Gx = 183, Bx = 18, Bits = 8 };
- RIuint32 l = Rx * r + Gx * g + Bx * b;
- r = g = b = l >> Bits;
-}
-
-#if 0
-RI_INLINE void IntegerColor::convertFromInternal(const Color::Descriptor& dst)
-{
-}
-#endif
-
-/**
- * \brief Convert color from one format to another using integer operations.
- * \note Currently expands the color to intermediate format first (8 bits
- * per component.
- */
-RI_INLINE void IntegerColor::convertToFrom(const Color::Descriptor& dst, const Color::Descriptor& src, bool srcIsMask)
-{
- if (src.isZeroConversion(dst))
- return;
-
- if (src.isShiftConversionToLower(dst))
- {
- if (dst.luminanceBits)
- {
- if (dst.luminanceBits == 1)
- {
- RI_ASSERT(src.luminanceBits == 8);
- r = (r + 128)>>8;
- }
- else
- r = r >> (src.luminanceBits - dst.luminanceBits);
- } else
- {
- r = r >> (src.redBits - dst.redBits);
- g = g >> (src.greenBits - dst.greenBits);
- b = b >> (src.blueBits - dst.blueBits);
- }
- if (dst.alphaBits)
- {
- //a = (a+128)>>8;
- if (dst.alphaBits == 1)
- a = (a+(1<<(src.alphaBits-1)))>>src.alphaBits;
- else
- a = a >> (src.alphaBits - dst.alphaBits);
- }
-
- return;
- }
-
- if (!srcIsMask)
- expandColor(src);
- else
- expandMask(src);
-
-
- if (dst.isLuminance() != src.isLuminance())
- {
- if (src.isLuminance())
- fullLuminanceToRGB(src.isPremultiplied(), src.isNonlinear(), dst.isPremultiplied(), dst.isNonlinear());
- else
- fullRGBToLuminance(src.isPremultiplied(), src.isNonlinear(), dst.isPremultiplied(), dst.isNonlinear());
- }
- else if (dst.isNonlinear() != src.isNonlinear())
- {
- // No luminance/rgb change.
- // Change of gamma requires unpremultiplication:
- if (src.isPremultiplied() && !(src.isAlphaOnly()))
- unpremultiply();
-
- if (src.isNonlinear())
- gammaToLinear(src.isLuminance());
- else
- linearToGamma(src.isLuminance());
-
- if (dst.isPremultiplied() && !(dst.isAlphaOnly()))
- premultiply();
- }
- else
- if ((dst.isPremultiplied() != src.isPremultiplied()) && !(dst.isAlphaOnly() || dst.isAlphaOnly()))
- {
- // \todo Make sure non-alpha formats are properly handled.
- if (src.isPremultiplied())
- unpremultiply(dst.isLuminance());
- else
- premultiply(dst.isLuminance());
- }
-
- truncateColor(dst);
-}
-
-//==============================================================================================
-
-/*-------------------------------------------------------------------*//*!
-* \brief Storage and operations for VGImage.
-* \param
-* \return
-* \note
-*//*-------------------------------------------------------------------*/
-
-class Surface;
-class Image
-{
-public:
- Image(const Color::Descriptor& desc, int width, int height, VGbitfield allowedQuality); //throws bad_alloc
- //use data from a memory buffer. NOTE: data is not copied, so it is user's responsibility to make sure the data remains valid while the Image is in use.
- Image(const Color::Descriptor& desc, int width, int height, int stride, RIuint8* data); //throws bad_alloc
- //child image constructor
- Image(Image* parent, int x, int y, int width, int height); //throws bad_alloc
- ~Image();
-
- const Color::Descriptor& getDescriptor() const { return m_desc; }
- int getWidth() const { return m_width; }
- int getHeight() const { return m_height; }
- int getStride() const { return m_stride; }
- Image* getParent() const { return m_parent; }
- VGbitfield getAllowedQuality() const { return m_allowedQuality; }
- void addInUse() { m_inUse++; }
- void removeInUse() { RI_ASSERT(m_inUse > 0); m_inUse--; }
- int isInUse() const { return m_inUse; }
- RIuint8* getData() const { return m_data; }
- void addReference() { m_referenceCount++; }
- int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
- bool overlaps(const Image* src) const;
- void setUnsafe(bool unsafe) { if (unsafe && m_desc.maybeUnsafe()) m_unsafeData = unsafe; else m_unsafeData = false; }
- bool isUnsafe() const { return m_unsafeData; }
-
- void clear(const Color& clearColor, int x, int y, int w, int h);
- void blit(VGContext* context, const Image* src, int sx, int sy, int dx, int dy, int w, int h, Array<Rectangle>* scissors = NULL, bool dither = false); //throws bad_alloc
-
- RI_INLINE static const void* incrementPointer(const void* ptr, int bpp, RIint32 x);
- RI_INLINE static void* calculateAddress(const void* basePtr, int bpp, int x, int y, int stride);
-
- static RI_INLINE RIuint32 readPackedPixelFromAddress(const void *ptr, int bpp, int x);
- static RI_INLINE void writePackedPixelToAddress(void* ptr, int bpp, int x, RIuint32 packedColor);
-
- RI_INLINE RIuint32 readPackedPixel(int x, int y) const;
- Color readPixel(int x, int y) const;
- RI_INLINE void writePackedPixelToAddress(void* ptr, int x, RIuint32 packedColor);
- void writePackedPixel(int x, int y, RIuint32 packedColor);
- void writePixel(int x, int y, const Color& c);
-
- void fillPacked(RIuint32 packedColor);
-
- static RI_INLINE void fillPackedPixels(void* data, int bpp, int x, int y, int stride, int nPixels, RIuint32 packedColor);
- RI_INLINE void fillPackedPixels(int x, int y, int nPixels, RIuint32 packedColor);
- RI_INLINE void fillPackedRectangle(int x0, int y0, int width, int height, RIuint32 packedColor);
-
- void writeFilteredPixel(int x, int y, const Color& c, VGbitfield channelMask);
-
- RIfloat readMaskPixel(int x, int y) const; //can read any image format
- void writeMaskPixel(int x, int y, RIfloat m); //can write only to VG_A_x
-
- Color resample(RIfloat x, RIfloat y, const Matrix3x3& surfaceToImage, VGImageQuality quality, VGTilingMode tilingMode, const Color& tileFillColor); //throws bad_alloc
- void makeMipMaps(); //throws bad_alloc
-
- void colorMatrix(const Image& src, const RIfloat* matrix, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
- void convolve(const Image& src, int kernelWidth, int kernelHeight, int shiftX, int shiftY, const RIint16* kernel, RIfloat scale, RIfloat bias, VGTilingMode tilingMode, const Color& edgeFillColor, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
- void separableConvolve(const Image& src, int kernelWidth, int kernelHeight, int shiftX, int shiftY, const RIint16* kernelX, const RIint16* kernelY, RIfloat scale, RIfloat bias, VGTilingMode tilingMode, const Color& edgeFillColor, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
- void gaussianBlur(const Image& src, RIfloat stdDeviationX, RIfloat stdDeviationY, VGTilingMode tilingMode, const Color& edgeFillColor, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
- void lookup(const Image& src, const RIuint8 * redLUT, const RIuint8 * greenLUT, const RIuint8 * blueLUT, const RIuint8 * alphaLUT, bool outputLinear, bool outputPremultiplied, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
- void lookupSingle(const Image& src, const RIuint32 * lookupTable, VGImageChannel sourceChannel, bool outputLinear, bool outputPremultiplied, bool filterFormatLinear, bool filterFormatPremultiplied, VGbitfield channelMask);
-
- RI_INLINE static int descriptorToStride(const Color::Descriptor& desc, int width) { return (width*desc.bitsPerPixel+7)/8; };
-
- void getStorageOffset(int& x, int& y) const { x = m_storageOffsetX; y = m_storageOffsetY; }
-
-private:
- Image(const Image&); //!< Not allowed.
- void operator=(const Image&); //!< Not allowed.
-
-#if defined(RI_DEBUG)
- bool ptrInImage(const void* ptr) const;
-#endif
- Color readTexel(int u, int v, int level, VGTilingMode tilingMode, const Color& tileFillColor) const;
-
- Color::Descriptor m_desc;
- int m_width;
- int m_height;
- VGbitfield m_allowedQuality;
- int m_inUse;
- int m_stride;
- RIuint8* m_data;
- int m_referenceCount;
- bool m_ownsData;
- Image* m_parent;
- int m_storageOffsetX;
- int m_storageOffsetY;
- bool m_unsafeData; // Data may contain incorrect pixel data
-
-#ifndef RI_COMPILE_LLVM_BYTECODE
-
-#endif /* RI_COMPILE_LLVM_BYTECODE */
-};
-
-#if defined(RI_DEBUG)
-RI_INLINE bool Image::ptrInImage(const void* ptr) const
-{
- RIuint8* p = (RIuint8*)ptr;
-
- if (p < m_data) return false;
- if (p >= (m_data + m_height * m_stride)) return false;
- return true;
-}
-#endif
-
-RI_INLINE const void* Image::incrementPointer(const void* ptr, int bpp, int x)
-{
- if (bpp >= 8)
- return (((RIuint8*)ptr) + (bpp >> 3));
- // Increment the pointer only when the byte is actually about to change.
- int mask;
- if (bpp == 4)
- mask = 1;
- else if (bpp == 2)
- mask = 3;
- else
- mask = 7;
- if ((x & mask) == mask)
- return ((RIuint8*)ptr + 1);
- return ptr;
-}
-
-RI_INLINE void* Image::calculateAddress(const void* basePtr, int bpp, int x, int y, int stride)
-{
- if (bpp >= 8)
- {
- return (void*)((RIuint8*)basePtr + y * stride + x * (bpp >> 3));
- } else
- {
- // 4, 2, or 1 bits per pixel
- RI_ASSERT(bpp == 4 || bpp == 2 || bpp == 1);
- return (void*)((RIuint8*)basePtr + y * stride + ((x * bpp) >> 3));
- }
-}
-
-RI_INLINE RIuint32 Image::readPackedPixel(int x, int y) const
-{
- RI_ASSERT(m_data);
- RI_ASSERT(x >= 0 && x < m_width);
- RI_ASSERT(y >= 0 && y < m_height);
- RI_ASSERT(m_referenceCount > 0);
-
- RIuint32 p = 0;
-
- void* ptr = Image::calculateAddress(m_data, m_desc.bitsPerPixel, x+m_storageOffsetX, y+m_storageOffsetY, m_stride);
- p = readPackedPixelFromAddress(ptr, m_desc.bitsPerPixel, x+m_storageOffsetX);
-
- return p;
-}
-
-
-RI_INLINE void Image::writePackedPixelToAddress(void* ptr, int bpp, int x, RIuint32 packedColor)
-{
- // \note packedColor must contain the whole data (including < 8 bpp data)?
- switch(bpp)
- {
- case 32:
- {
- RIuint32* s = ((RIuint32*)ptr);
- *s = (RIuint32)packedColor;
- break;
- }
-
- case 16:
- {
- RIuint16* s = ((RIuint16*)ptr);
- *s = (RIuint16)packedColor;
- break;
- }
-
- case 8:
- {
- RIuint8* s = ((RIuint8*)ptr);
- *s = (RIuint8)packedColor;
- break;
- }
- case 4:
- {
- RIuint8* s = ((RIuint8*)ptr);
- *s = (RIuint8)((packedColor << ((x&1)<<2)) | ((unsigned int)*s & ~(0xf << ((x&1)<<2))));
- break;
- }
-
- case 2:
- {
- RIuint8* s = ((RIuint8*)ptr);
- *s = (RIuint8)((packedColor << ((x&3)<<1)) | ((unsigned int)*s & ~(0x3 << ((x&3)<<1))));
- break;
- }
-
- default:
- {
- RI_ASSERT(bpp == 1);
- RIuint8* s = ((RIuint8*)ptr);
- *s = (RIuint8)((packedColor << (x&7)) | ((unsigned int)*s & ~(0x1 << (x&7))));
- break;
- }
- }
- // m_mipmapsValid = false; // \note Will never do this, must be handled outside this class somehow!
-}
-
-/**
- * \brief Write packed pixel into address.
- * \param x Which x-coordinate (starting from the start of the scanline
- * pointed to) is addressed? This is only required for formats
- * that have less than 8 bpp.
- */
-void Image::writePackedPixelToAddress(void* address, int x, RIuint32 packedColor)
-{
- writePackedPixelToAddress(address, m_desc.bitsPerPixel, x, packedColor);
-}
-
-/**
- * \brief Read a packed pixel from a given address. Notice the use of param x!
- * \param x Check which part of byte to return if bpp < 8
- */
-RI_INLINE RIuint32 Image::readPackedPixelFromAddress(const void *ptr, int bpp, int x)
-{
- switch(bpp)
- {
- case 32:
- {
- RIuint32* s = (RIuint32*)ptr;
- return *s;
- }
-
- case 16:
- {
- RIuint16* s = (RIuint16*)ptr;
- return (RIuint32)*s;
- }
-
- case 8:
- {
- RIuint8* s = (RIuint8*)ptr;
- return (RIuint32)*s;
- }
- case 4:
- {
- RIuint8* s = ((RIuint8*)ptr);
- return (RIuint32)(*s >> ((x&1)<<2)) & 0xf;
- }
-
- case 2:
- {
- RIuint8* s = ((RIuint8*)ptr);
- return (RIuint32)(*s >> ((x&3)<<1)) & 0x3;
- }
-
- default:
- {
- RI_ASSERT(bpp == 1);
- RIuint8* s = ((RIuint8*)ptr);
- return (RIuint32)(*s >> (x&7)) & 0x1;
- }
- }
-}
-
-RI_INLINE void Image::writePackedPixel(int x, int y, RIuint32 packedColor)
-{
- RI_ASSERT(m_data);
- RI_ASSERT(x >= 0 && x < m_width);
- RI_ASSERT(y >= 0 && y < m_height);
- RI_ASSERT(m_referenceCount > 0);
-
- x += m_storageOffsetX;
- y += m_storageOffsetY;
-
- RIuint8* scanline = m_data + y * m_stride;
- switch(m_desc.bitsPerPixel)
- {
- case 32:
- {
- RIuint32* s = ((RIuint32*)scanline) + x;
- *s = (RIuint32)packedColor;
- break;
- }
-
- case 16:
- {
- RIuint16* s = ((RIuint16*)scanline) + x;
- *s = (RIuint16)packedColor;
- break;
- }
-
- case 8:
- {
- RIuint8* s = ((RIuint8*)scanline) + x;
- *s = (RIuint8)packedColor;
- break;
- }
- case 4:
- {
- RIuint8* s = ((RIuint8*)scanline) + (x>>1);
- *s = (RIuint8)((packedColor << ((x&1)<<2)) | ((unsigned int)*s & ~(0xf << ((x&1)<<2))));
- break;
- }
-
- case 2:
- {
- RIuint8* s = ((RIuint8*)scanline) + (x>>2);
- *s = (RIuint8)((packedColor << ((x&3)<<1)) | ((unsigned int)*s & ~(0x3 << ((x&3)<<1))));
- break;
- }
-
- default:
- {
- RI_ASSERT(m_desc.bitsPerPixel == 1);
- RIuint8* s = ((RIuint8*)scanline) + (x>>3);
- *s = (RIuint8)((packedColor << (x&7)) | ((unsigned int)*s & ~(0x1 << (x&7))));
- break;
- }
- }
- //m_mipmapsValid = false;
-}
-
-
-/**
- * \brief Unsafe static method for setting image pixels
- */
-RI_INLINE void Image::fillPackedPixels(void* data, int bpp, int x, int y, int stride, int nPixels, RIuint32 packedColor)
-{
- RI_ASSERT(nPixels > 0);
- RI_ASSERT(data);
-
- RIuint8* scanline = (RIuint8*)data + y * stride;
-
- switch(bpp)
- {
- case 32:
- {
- RIuint32* s = ((RIuint32*)scanline) + x;
-
- for (int i = 0; i < nPixels; i++)
- s[i] = packedColor;
-
- break;
- }
-
- case 16:
- {
- RIuint16* s = ((RIuint16*)scanline) + x;
-
- for (int i = 0; i < nPixels; i++)
- s[i] = (RIuint16)packedColor;
-
- break;
- }
-
- case 8:
- {
- RIuint8* s = ((RIuint8*)scanline) + x;
-
- for (int i = 0; i < nPixels; i++)
- s[i] = (RIuint8)packedColor;
-
- break;
- }
- case 4:
- {
- //RI_ASSERT((packedColor & 0xf) == 0);
- //packedColor &= 0xf;
- RIuint8* s = ((RIuint8*)scanline) + (x>>1);
- if (x & 1)
- {
- *s = (RIuint8)((packedColor << ((x&1)<<2)) | ((unsigned int)*s & ~(0xf << ((x&1)<<2))));
- s++;
- x++;
- nPixels--;
- }
- RI_ASSERT(!(x&1));
-
- int c = nPixels / 2;
- RIuint8 bytePacked = packedColor | (packedColor << 4);
- while (c)
- {
- *s++ = bytePacked;
- c--;
- x+=2;
- }
- nPixels &= 1;
-
- if (nPixels)
- {
- *s = (RIuint8)((packedColor << ((x&1)<<2)) | ((unsigned int)*s & ~(0xf << ((x&1)<<2))));
- s++;
- x++;
- nPixels--;
- }
- RI_ASSERT(nPixels == 0);
- break;
- }
-
- case 2:
- {
- // This case should not be needed!
- RI_ASSERT(false);
- RIuint8* s = ((RIuint8*)scanline) + (x>>2);
- *s = (RIuint8)((packedColor << ((x&3)<<1)) | ((unsigned int)*s & ~(0x3 << ((x&3)<<1))));
- break;
- }
-
- default:
- {
- RI_ASSERT(bpp == 1);
- RIuint8* s = ((RIuint8*)scanline) + (x>>3);
- // \todo Get this as input instead?
- RI_ASSERT(packedColor == 1 || packedColor == 0);
- RIuint8 fullyPacked = (RIuint8)(-(RIint8)packedColor);
-
- if (x & 7)
- {
- // Handle the first byte:
- RIuint8 o = *s;
- int a = x&7;
- RI_ASSERT(a>=1);
- int b = RI_INT_MIN(a + nPixels, 8);
- RI_ASSERT(b > a);
- RIuint8 emask = (1u << b)-1;
- RIuint8 mask = (0xffu<<a) & emask;
- RI_ASSERT(mask>0);
- RI_ASSERT(mask<=254);
- *s++ = (o&(~mask))|(fullyPacked & mask);
- nPixels -= 8-(x&7);
- x += 8-(x&7);
- }
-
- if (nPixels < 0)
- return;
-
- RI_ASSERT(!(x&1));
-
- int c = nPixels/8;
- while (c)
- {
- *s++ = fullyPacked;
- c--;
- x+=8;
- }
- nPixels -= ((nPixels/8) * 8);
-
-
- if (nPixels)
- {
- RI_ASSERT((x&7) == 0);
-
- RIuint8 o = *s;
- int b = nPixels;
- RI_ASSERT(b<=7);
- RIuint8 mask = (1u<<b)-1;
- RI_ASSERT(mask <= 127);
- *s++ = (o&(~mask))|(fullyPacked & mask);
- }
- break;
- }
- }
- //m_mipmapsValid = false;
-}
-RI_INLINE void Image::fillPackedPixels(int x, int y, int nPixels, RIuint32 packedColor)
-{
- fillPackedPixels((void*)m_data, m_desc.bitsPerPixel, x + m_storageOffsetX, y + m_storageOffsetY, m_stride, nPixels, packedColor);
-}
-
-RI_INLINE void Image::fillPackedRectangle(int x0, int y0, int width, int height, RIuint32 packedColor)
-{
- int y = y0;
- while (height)
- {
- fillPackedPixels(x0, y, width, packedColor);
- y++;
- height--;
- }
-}
-
-/*-------------------------------------------------------------------*//*!
-* \brief Surface class abstracting multisampled rendering surface.
-* \param
-* \return
-* \note
-*//*-------------------------------------------------------------------*/
-
-class Surface
-{
-public:
- Surface(const Color::Descriptor& desc, int width, int height, int numSamples); //throws bad_alloc
- Surface(Image* image); //throws bad_alloc
- Surface(const Color::Descriptor& desc, int width, int height, int stride, RIuint8* data); //throws bad_alloc
- ~Surface();
-
- RI_INLINE const Image* getImage() const {return m_image;}
- RI_INLINE const Color::Descriptor& getDescriptor() const { return m_image->getDescriptor(); }
- RI_INLINE int getWidth() const { return m_width; }
- RI_INLINE int getHeight() const { return m_height; }
- RI_INLINE int getNumSamples() const { return m_numSamples; }
- RI_INLINE void addReference() { m_referenceCount++; }
- RI_INLINE int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
- RI_INLINE int isInUse() const { return m_image->isInUse(); }
- RI_INLINE bool isInUse(Image* image) const { return image == m_image ? true : false; }
-
- void clear(const Color& clearColor, int x, int y, int w, int h, const Array<Rectangle>* scissors = NULL);
-#if 0
- // Currently does not support msaa surfaces
- void blit(const Image& src, int sx, int sy, int dx, int dy, int w, int h); //throws bad_alloc
- void blit(const Image& src, int sx, int sy, int dx, int dy, int w, int h, const Array<Rectangle>& scissors); //throws bad_alloc
- void blit(const Surface* src, int sx, int sy, int dx, int dy, int w, int h); //throws bad_alloc
- void blit(const Surface* src, int sx, int sy, int dx, int dy, int w, int h, const Array<Rectangle>& scissors); //throws bad_alloc
-#endif
- void mask(DynamicBlitter& blitter, const Image* src, VGMaskOperation operation, int x, int y, int w, int h);
-
- RI_INLINE void writePackedPixelToAddress(void* address, int x, RIuint32 p) { m_image->writePackedPixelToAddress(address, x, p); }
- RI_INLINE RIuint32 readPackedSample(int x, int y, int sample) const { return m_image->readPackedPixel(x*m_numSamples+sample, y); }
- RI_INLINE Color readSample(int x, int y, int sample) const { return m_image->readPixel(x*m_numSamples+sample, y); }
- RI_INLINE void writePackedSample(int x, int y, int sample, RIuint32 p) { m_image->writePackedPixel(x*m_numSamples+sample, y, p); }
- RI_INLINE void writeSample(int x, int y, int sample, const Color& c) { m_image->writePixel(x*m_numSamples+sample, y, c); }
- RI_INLINE void fillPackedSamples(int x, int y, int nPixels, RIuint32 p);
-
- RIfloat readMaskCoverage(int x, int y) const;
- void writeMaskCoverage(int x, int y, RIfloat m);
- unsigned int readMaskMSAA(int x, int y) const;
- void writeMaskMSAA(int x, int y, unsigned int m);
-
- RIuint32 FSAAResolvePacked(int x, int y) const;
- Color FSAAResolve(int x, int y) const; //for fb=>img: vgGetPixels, vgReadPixels
-
-private:
- Surface(const Surface&); //!< Not allowed.
- void operator=(const Surface&); //!< Not allowed.
-
- struct ScissorEdge
- {
- ScissorEdge() : x(0), miny(0), maxy(0), direction(0) {}
- bool operator<(const ScissorEdge& e) const { return x < e.x; }
- int x;
- int miny;
- int maxy;
- int direction; //1 start, -1 end
- };
-
- int m_width;
- int m_height;
- int m_numSamples;
- int m_referenceCount;
-
-public:
- // \todo TERO: Broke the design of this by making it public, make proper
- // friend/etc. C++ accessor for optimized pixel-pipelines. Combine with the
- // removal of (remnants of) the FSAA support.
- Image* m_image;
-};
-
-RI_INLINE void Surface::fillPackedSamples(int x, int y, int nPixels, RIuint32 p)
-{
- m_image->fillPackedPixels(x, y, nPixels, p);
-}
-
-
-/*-------------------------------------------------------------------*//*!
-* \brief Drawable class for encapsulating color and mask buffers.
-* \param
-* \return
-* \note
-*//*-------------------------------------------------------------------*/
-
-class Drawable
-{
-public:
- Drawable(const Color::Descriptor& desc, int width, int height, int numSamples, int maskBits); //throws bad_alloc
- Drawable(Image* image, int maskBits); //throws bad_alloc
- Drawable(const Color::Descriptor& desc, int width, int height, int stride, RIuint8* data, int maskBits); //throws bad_alloc
- ~Drawable();
-
- RI_INLINE const Color::Descriptor& getDescriptor() const { return m_color->getDescriptor(); }
- RI_INLINE int getNumMaskBits() const { if(!m_mask) return 0; return m_mask->getDescriptor().alphaBits; }
- RI_INLINE int getWidth() const { return m_color->getWidth(); }
- RI_INLINE int getHeight() const { return m_color->getHeight(); }
- RI_INLINE int getNumSamples() const { return m_color->getNumSamples(); }
- RI_INLINE void addReference() { m_referenceCount++; }
- RI_INLINE int removeReference() { m_referenceCount--; RI_ASSERT(m_referenceCount >= 0); return m_referenceCount; }
- RI_INLINE int isInUse() const { return m_color->isInUse() || (m_mask && m_mask->isInUse()); }
- RI_INLINE bool isInUse(Image* image) const { return m_color->isInUse(image) || (m_mask && m_mask->isInUse(image)); }
- RI_INLINE Surface* getColorBuffer() const { return m_color; }
- RI_INLINE Surface* getMaskBuffer() const { return m_mask; }
-
- void resize(VGContext* context, int newWidth, int newHeight); //throws bad_alloc
-private:
- Drawable(const Drawable&); //!< Not allowed.
- void operator=(const Drawable&); //!< Not allowed.
-
- int m_referenceCount;
- Surface* m_color;
- Surface* m_mask;
-};
-
-//==============================================================================================
-
-} //namespace OpenVGRI
-
-//==============================================================================================
-
-#endif /* __RIIMAGE_H */