X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fpixelformat.cpp;h=0b13f3ccefa7fe53cf2e5868b157a7d0c0e5588b;hp=d968917b25956440bf0f8f096baffec4dcba7737;hb=abb4e50bdbb6d62d7e6ee249d52353ccf22762a4;hpb=a5797c9babd17673285b3b15c7572c2d8fe1595c diff --git a/source/pixelformat.cpp b/source/pixelformat.cpp index d968917b..0b13f3cc 100644 --- a/source/pixelformat.cpp +++ b/source/pixelformat.cpp @@ -1,11 +1,6 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - -#include "except.h" +#include +#include +#include #include "pixelformat.h" using namespace std; @@ -13,55 +8,329 @@ using namespace std; namespace Msp { namespace GL { -istream &operator>>(istream &in, PixelFormat &fmt) +void operator>>(const LexicalConverter &conv, PixelFormat &fmt) { - string word; - - in>>word; - if(word=="COLOR_INDEX") - fmt=COLOR_INDEX; - else if(word=="STENCIL_INDEX") - fmt=STENCIL_INDEX; - else if(word=="DEPTH_COMPONENT") - fmt=DEPTH_COMPONENT; - else if(word=="RED") - fmt=RED; - else if(word=="GREEN") - fmt=GREEN; - else if(word=="BLUE") - fmt=BLUE; - else if(word=="ALPHA") - fmt=ALPHA; - else if(word=="RGB") - fmt=RGB; - else if(word=="RGBA") - fmt=RGBA; - else if(word=="BGR") - fmt=BGR; - else if(word=="BGRA") - fmt=BGRA; - else if(word=="LUMINANCE") - fmt=LUMINANCE; - else if(word=="LUMINANCE_ALPHA") - fmt=LUMINANCE_ALPHA; + if(conv.get()=="STENCIL_INDEX") + fmt = STENCIL_INDEX; + else if(conv.get()=="DEPTH_COMPONENT") + fmt = DEPTH_COMPONENT; + else if(conv.get()=="RED") + fmt = RED; + else if(conv.get()=="RG") + fmt = RG; + else if(conv.get()=="RGB") + fmt = RGB; + else if(conv.get()=="RGBA") + fmt = RGBA; + else if(conv.get()=="BGR") + fmt = BGR; + else if(conv.get()=="BGRA") + fmt = BGRA; + else if(conv.get()=="SRGB") + fmt = SRGB; + else if(conv.get()=="SRGB_ALPHA") + fmt = SRGB_ALPHA; + else if(conv.get()=="LUMINANCE") + fmt = LUMINANCE; + else if(conv.get()=="LUMINANCE_ALPHA") + fmt = LUMINANCE_ALPHA; + else if(conv.get()=="SLUMINANCE") + fmt = SLUMINANCE; + else if(conv.get()=="SLUMINANCE_ALPHA") + fmt = SLUMINANCE_ALPHA; else - in.setstate(ios_base::failbit); - - return in; + throw lexical_error(format("conversion of '%s' to PixelFormat", conv.get())); } PixelFormat pixelformat_from_graphics(Graphics::PixelFormat pf) { switch(pf) { - case Graphics::COLOR_INDEX: return COLOR_INDEX; case Graphics::LUMINANCE: return LUMINANCE; case Graphics::LUMINANCE_ALPHA: return LUMINANCE_ALPHA; case Graphics::RGB: return RGB; + case Graphics::RGBX: case Graphics::RGBA: return RGBA; case Graphics::BGR: return BGR; + case Graphics::BGRX: case Graphics::BGRA: return BGRA; - default: throw InvalidParameterValue("Unknown Graphics::PixelFormat"); + default: throw invalid_argument("pixelformat_from_graphics"); + } +} + +PixelFormat storage_pixelformat_from_graphics(Graphics::PixelFormat pf, bool srgb) +{ + PixelFormat result; + switch(pf) + { + case Graphics::RGBX: + case Graphics::BGR: + case Graphics::BGRX: result = RGB; break; + case Graphics::BGRA: result = RGBA; break; + default: result = pixelformat_from_graphics(pf); + } + + if(srgb) + return get_srgb_pixelformat(result); + else + return result; +} + +PixelFormat get_base_pixelformat(PixelFormat pf) +{ + PixelFormat unsized = get_unsized_pixelformat(pf); + switch(unsized) + { + case SRGB: return RGB; + case SRGB_ALPHA: return RGBA; + case SLUMINANCE: return LUMINANCE; + case SLUMINANCE_ALPHA: return LUMINANCE_ALPHA; + default: return unsized; + } +} + +PixelFormat get_unsized_pixelformat(PixelFormat pf) +{ + switch(pf) + { + case R8: + case R16F: + case R32F: return RED; + case RG8: + case RG16F: + case RG32F: return RG; + case RGB8: + case RGB16F: + case RGB32F: return RGB; + case SRGB8: return SRGB; + case RGBA8: + case RGBA16F: + case RGBA32F: return RGBA; + case SRGB8_ALPHA8: return SRGB_ALPHA; + case LUMINANCE8: return LUMINANCE; + case SLUMINANCE8: return SLUMINANCE; + case LUMINANCE_ALPHA8: return LUMINANCE_ALPHA; + case SLUMINANCE8_ALPHA8: return SLUMINANCE_ALPHA; + case DEPTH_COMPONENT16: + case DEPTH_COMPONENT24: + case DEPTH_COMPONENT32: + case DEPTH_COMPONENT32F: return DEPTH_COMPONENT; + default: return pf; + } +} + +PixelFormat get_sized_pixelformat(PixelFormat pf, unsigned size) +{ + if(!size || size>4) + throw invalid_argument("get_sized_pixelformat"); + + pf = get_unsized_pixelformat(pf); + + switch(size) + { + case 1: + switch(pf) + { + case RED: return R8; + case RG: return RG8; + case RGB: return RGB8; + case RGBA: return RGBA8; + case SRGB: return SRGB8; + case SRGB_ALPHA: return SRGB8_ALPHA8; + case LUMINANCE: return LUMINANCE8; + case SLUMINANCE: return SLUMINANCE8; + case LUMINANCE_ALPHA: return LUMINANCE8_ALPHA8; + case SLUMINANCE_ALPHA: return SLUMINANCE8_ALPHA8; + default: throw invalid_argument("get_sized_pixelformat"); + } + case 2: + switch(pf) + { + case RED: return R16F; + case RG: return RG16F; + case RGB: return RGB16F; + case RGBA: return RGBA16F; + case DEPTH_COMPONENT: return DEPTH_COMPONENT16; + default: throw invalid_argument("get_sized_pixelformat"); + } + case 3: + if(pf==DEPTH_COMPONENT) + return DEPTH_COMPONENT24; + else + throw invalid_argument("get_sized_pixelformat"); + case 4: + switch(pf) + { + case RED: return R32F; + case RG: return RG32F; + case RGB: return RGB32F; + case RGBA: return RGBA32F; + case DEPTH_COMPONENT: return ARB_depth_buffer_float ? DEPTH_COMPONENT32F : DEPTH_COMPONENT32; + default: throw invalid_argument("get_sized_pixelformat"); + } + default: + throw invalid_argument("get_sized_pixelformat"); + } +} + +PixelFormat get_default_sized_pixelformat(PixelFormat pf) +{ + pf = get_unsized_pixelformat(pf); + unsigned size = 1; + if(pf==DEPTH_COMPONENT) + { + if(get_gl_api()==OPENGL_ES2 && !ARB_depth_buffer_float) + size = 2; + else + size = 4; + } + return get_sized_pixelformat(pf, size); +} + +PixelFormat get_srgb_pixelformat(PixelFormat pf) +{ + switch(pf) + { + case RGB: return SRGB; + case RGBA: return SRGB_ALPHA; + case RGB8: return SRGB8; + case RGBA8: return SRGB8_ALPHA8; + case LUMINANCE: return SLUMINANCE; + case LUMINANCE8: return SLUMINANCE8; + case LUMINANCE_ALPHA: return SLUMINANCE_ALPHA; + case LUMINANCE_ALPHA8: return SLUMINANCE8_ALPHA8; + default: return pf; + } +} + +unsigned get_component_count(PixelFormat pf) +{ + switch(get_base_pixelformat(pf)) + { + case STENCIL_INDEX: + case DEPTH_COMPONENT: + case RED: + case LUMINANCE: + case SLUMINANCE: + return 1; + case RG: + case LUMINANCE_ALPHA: + case SLUMINANCE_ALPHA: + return 2; + case RGB: + case BGR: + return 3; + case RGBA: + case BGRA: + return 4; + default: + throw invalid_argument("get_component_count"); + } +} + +unsigned get_component_size(PixelFormat pf) +{ + switch(pf) + { + case R8: + case RG8: + case RGB8: + case RGBA8: + case SRGB8: + case SRGB8_ALPHA8: + case LUMINANCE8: + case LUMINANCE8_ALPHA8: + case SLUMINANCE8: + case SLUMINANCE8_ALPHA8: + return 1; + case R16F: + case RG16F: + case RGB16F: + case RGBA16F: + case DEPTH_COMPONENT16: + return 2; + case DEPTH_COMPONENT24: + return 3; + case R32F: + case RG32F: + case RGB32F: + case RGBA32F: + case DEPTH_COMPONENT32: + case DEPTH_COMPONENT32F: + return 4; + default: + return 0; + } +} + +unsigned get_pixel_size(PixelFormat pf) +{ + return get_component_count(pf)*max(get_component_size(pf), 1U); +} + +void require_pixelformat(PixelFormat pf) +{ + /* TODO These checks are only accurate for textures. On OpenGL ES some + formats are allowed for render buffers earlier than textures. In particular + it's possible to create a 16-bit depth renderbuffer on OpenGL ES 2.0 but + depth textures are only available with 3.0 or the OES_depth_texture + extension.*/ + switch(pf) + { + case RGB8: + case RGBA8: + { static Require _req(OES_required_internalformat); } + break; + case RED: + case R8: + case RG: + case RG8: + { static Require _req(ARB_texture_rg); } + break; + case R16F: + case R32F: + case RG16F: + case RG32F: + { static Require _req(ARB_texture_rg); } + { static Require _req(ARB_texture_float); } + break; + case RGB16F: + case RGB32F: + case RGBA16F: + case RGBA32F: + { static Require _req(ARB_texture_float); } + break; + case SRGB: + case SRGB8: + case SRGB_ALPHA: + case SRGB8_ALPHA8: + case SLUMINANCE: + case SLUMINANCE8: + case SLUMINANCE_ALPHA: + case SLUMINANCE8_ALPHA8: + { static Require _req(EXT_texture_sRGB); } + break; + case BGR: + case BGRA: + { static Require _req(EXT_bgra); } + break; + case DEPTH_COMPONENT: + { static Require _req(ARB_depth_texture); } + break; + case DEPTH_COMPONENT16: + case DEPTH_COMPONENT24: + case DEPTH_COMPONENT32: + { static Require _req(ARB_depth_texture); } + { static Require _req(OES_required_internalformat); } + break; + case DEPTH_COMPONENT32F: + { static Require _req(ARB_depth_buffer_float); } + break; + case STENCIL_INDEX: + { static Require _req(OES_texture_stencil8); } + break; + default: + break; } }