| // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| // utilities.cpp: Conversion functions and other utility routines. |
| |
| #include "utilities.h" |
| |
| #include "mathutil.h" |
| #include "Context.h" |
| #include "common/debug.h" |
| |
| #include <limits> |
| #include <stdio.h> |
| |
| namespace es1 |
| { |
| bool IsCompressed(GLenum format) |
| { |
| return format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || |
| format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || |
| format == GL_ETC1_RGB8_OES; |
| } |
| |
| bool IsSizedInternalFormat(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_ALPHA8_EXT: |
| case GL_LUMINANCE8_ALPHA8_EXT: |
| case GL_LUMINANCE8_EXT: |
| case GL_RGBA4_OES: |
| case GL_RGB5_A1_OES: |
| case GL_RGB565_OES: |
| case GL_RGB8_OES: |
| case GL_RGBA8_OES: |
| case GL_BGRA8_EXT: // GL_APPLE_texture_format_BGRA8888 |
| case GL_DEPTH_COMPONENT16_OES: |
| case GL_STENCIL_INDEX8_OES: |
| case GL_DEPTH24_STENCIL8_OES: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset, |
| GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture) |
| { |
| if(!texture) |
| { |
| return GL_INVALID_OPERATION; |
| } |
| |
| GLenum sizedInternalFormat = texture->getFormat(target, level); |
| |
| if(compressed) |
| { |
| if(format != sizedInternalFormat) |
| { |
| return GL_INVALID_OPERATION; |
| } |
| } |
| else if(!copy) // CopyTexSubImage doesn't have format/type parameters. |
| { |
| GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, target); |
| if(validationError != GL_NO_ERROR) |
| { |
| return validationError; |
| } |
| } |
| |
| if(compressed) |
| { |
| if((width % 4 != 0 && width != texture->getWidth(target, 0)) || |
| (height % 4 != 0 && height != texture->getHeight(target, 0))) |
| { |
| return GL_INVALID_OPERATION; |
| } |
| } |
| |
| if(xoffset + width > texture->getWidth(target, level) || |
| yoffset + height > texture->getHeight(target, level)) |
| { |
| return GL_INVALID_VALUE; |
| } |
| |
| return GL_NO_ERROR; |
| } |
| |
| bool IsDepthTexture(GLenum format) |
| { |
| return format == GL_DEPTH_STENCIL_OES; |
| } |
| |
| bool IsStencilTexture(GLenum format) |
| { |
| return format == GL_DEPTH_STENCIL_OES; |
| } |
| |
| bool IsCubemapTextureTarget(GLenum target) |
| { |
| return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES); |
| } |
| |
| int CubeFaceIndex(GLenum cubeFace) |
| { |
| switch(cubeFace) |
| { |
| case GL_TEXTURE_CUBE_MAP_OES: |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_X_OES: return 0; |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_OES: return 1; |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_OES: return 2; |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_OES: return 3; |
| case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_OES: return 4; |
| case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_OES: return 5; |
| default: UNREACHABLE(cubeFace); return 0; |
| } |
| } |
| |
| bool IsTextureTarget(GLenum target) |
| { |
| return target == GL_TEXTURE_2D; |
| } |
| |
| // Verify that format/type are one of the combinations from table 3.4. |
| GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLenum target) |
| { |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: |
| case GL_UNSIGNED_SHORT_4_4_4_4: |
| case GL_UNSIGNED_SHORT_5_5_5_1: |
| case GL_UNSIGNED_SHORT_5_6_5: |
| case GL_UNSIGNED_INT_24_8_OES: // GL_OES_packed_depth_stencil |
| break; |
| default: |
| return GL_INVALID_ENUM; |
| } |
| |
| switch(format) |
| { |
| case GL_ALPHA: |
| case GL_RGB: |
| case GL_RGBA: |
| case GL_LUMINANCE: |
| case GL_LUMINANCE_ALPHA: |
| case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888 |
| break; |
| case GL_DEPTH_STENCIL_OES: // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES) |
| switch(target) |
| { |
| case GL_TEXTURE_2D: |
| break; |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| default: |
| return GL_INVALID_ENUM; |
| } |
| |
| if((GLenum)internalformat != format) |
| { |
| if(gl::IsUnsizedInternalFormat(internalformat)) |
| { |
| return GL_INVALID_OPERATION; |
| } |
| |
| if(!IsSizedInternalFormat(internalformat)) |
| { |
| return GL_INVALID_VALUE; |
| } |
| } |
| |
| if((GLenum)internalformat == format) |
| { |
| // Validate format, type, and unsized internalformat combinations [OpenGL ES 1.1 Table 3.3] |
| switch(format) |
| { |
| case GL_RGBA: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: |
| case GL_UNSIGNED_SHORT_4_4_4_4: |
| case GL_UNSIGNED_SHORT_5_5_5_1: |
| break; |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_RGB: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: |
| case GL_UNSIGNED_SHORT_5_6_5: |
| break; |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_LUMINANCE_ALPHA: |
| case GL_LUMINANCE: |
| case GL_ALPHA: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: |
| break; |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_DEPTH_STENCIL_OES: |
| switch(type) |
| { |
| case GL_UNSIGNED_INT_24_8_OES: // GL_OES_packed_depth_stencil |
| break; |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_BGRA_EXT: |
| if(type != GL_UNSIGNED_BYTE) // GL_APPLE_texture_format_BGRA8888 / GL_EXT_texture_format_BGRA8888 |
| { |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| default: |
| UNREACHABLE(format); |
| return GL_INVALID_ENUM; |
| } |
| |
| return GL_NO_ERROR; |
| } |
| |
| // Validate format, type, and sized internalformat combinations [OpenGL ES 3.0 Table 3.2] |
| bool validSizedInternalformat = false; |
| #define VALIDATE_INTERNALFORMAT(...) { GLint validInternalformats[] = {__VA_ARGS__}; for(GLint v : validInternalformats) {if(internalformat == v) validSizedInternalformat = true;} } break; |
| |
| switch(format) |
| { |
| case GL_RGBA: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RGBA8_OES, GL_RGB5_A1_OES, GL_RGBA4_OES) |
| case GL_UNSIGNED_SHORT_4_4_4_4: VALIDATE_INTERNALFORMAT(GL_RGBA4_OES) |
| case GL_UNSIGNED_SHORT_5_5_5_1: VALIDATE_INTERNALFORMAT(GL_RGB5_A1_OES) |
| default: return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_RGB: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_RGB8_OES, GL_RGB565_OES) |
| case GL_UNSIGNED_SHORT_5_6_5: VALIDATE_INTERNALFORMAT(GL_RGB565_OES) |
| default: return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_DEPTH_STENCIL_OES: |
| switch(type) |
| { |
| case GL_UNSIGNED_INT_24_8_OES: VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8_OES) |
| default: return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_LUMINANCE_ALPHA: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_ALPHA8_EXT) |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_LUMINANCE: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_EXT) |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_ALPHA: |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT) |
| default: |
| return GL_INVALID_OPERATION; |
| } |
| break; |
| case GL_BGRA_EXT: // GL_APPLE_texture_format_BGRA8888 |
| switch(type) |
| { |
| case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_BGRA8_EXT) |
| default: return GL_INVALID_OPERATION; |
| } |
| break; |
| default: |
| UNREACHABLE(format); |
| return GL_INVALID_ENUM; |
| } |
| |
| #undef VALIDATE_INTERNALFORMAT |
| |
| if(!validSizedInternalformat) |
| { |
| return GL_INVALID_OPERATION; |
| } |
| |
| return GL_NO_ERROR; |
| } |
| |
| bool IsColorRenderable(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_RGBA4_OES: |
| case GL_RGB5_A1_OES: |
| case GL_RGB565_OES: |
| case GL_RGB8_OES: |
| case GL_RGBA8_OES: |
| return true; |
| case GL_DEPTH_COMPONENT16_OES: |
| case GL_STENCIL_INDEX8_OES: |
| case GL_DEPTH24_STENCIL8_OES: |
| return false; |
| default: |
| UNIMPLEMENTED(); |
| } |
| |
| return false; |
| } |
| |
| bool IsDepthRenderable(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_DEPTH_COMPONENT16_OES: |
| case GL_DEPTH24_STENCIL8_OES: |
| return true; |
| case GL_STENCIL_INDEX8_OES: |
| case GL_RGBA4_OES: |
| case GL_RGB5_A1_OES: |
| case GL_RGB565_OES: |
| case GL_RGB8_OES: |
| case GL_RGBA8_OES: |
| return false; |
| default: |
| UNIMPLEMENTED(); |
| } |
| |
| return false; |
| } |
| |
| bool IsStencilRenderable(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_STENCIL_INDEX8_OES: |
| case GL_DEPTH24_STENCIL8_OES: |
| return true; |
| case GL_RGBA4_OES: |
| case GL_RGB5_A1_OES: |
| case GL_RGB565_OES: |
| case GL_RGB8_OES: |
| case GL_RGBA8_OES: |
| case GL_DEPTH_COMPONENT16_OES: |
| return false; |
| default: |
| UNIMPLEMENTED(); |
| } |
| |
| return false; |
| } |
| |
| GLuint GetAlphaSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_NONE_OES: return 0; |
| case GL_RGBA4_OES: return 4; |
| case GL_RGB5_A1_OES: return 1; |
| case GL_RGB565_OES: return 0; |
| case GL_RGB8_OES: return 0; |
| case GL_RGBA8_OES: return 8; |
| case GL_BGRA8_EXT: return 8; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| GLuint GetRedSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_NONE_OES: return 0; |
| case GL_RGBA4_OES: return 4; |
| case GL_RGB5_A1_OES: return 5; |
| case GL_RGB565_OES: return 5; |
| case GL_RGB8_OES: return 8; |
| case GL_RGBA8_OES: return 8; |
| case GL_BGRA8_EXT: return 8; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| GLuint GetGreenSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_NONE_OES: return 0; |
| case GL_RGBA4_OES: return 4; |
| case GL_RGB5_A1_OES: return 5; |
| case GL_RGB565_OES: return 6; |
| case GL_RGB8_OES: return 8; |
| case GL_RGBA8_OES: return 8; |
| case GL_BGRA8_EXT: return 8; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| GLuint GetBlueSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_NONE_OES: return 0; |
| case GL_RGBA4_OES: return 4; |
| case GL_RGB5_A1_OES: return 5; |
| case GL_RGB565_OES: return 5; |
| case GL_RGB8_OES: return 8; |
| case GL_RGBA8_OES: return 8; |
| case GL_BGRA8_EXT: return 8; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| GLuint GetDepthSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_STENCIL_INDEX8_OES: return 0; |
| case GL_DEPTH_COMPONENT16_OES: return 16; |
| case GL_DEPTH24_STENCIL8_OES: return 24; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| GLuint GetStencilSize(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_STENCIL_INDEX8_OES: return 8; |
| case GL_DEPTH_COMPONENT16_OES: return 0; |
| case GL_DEPTH24_STENCIL8_OES: return 8; |
| default: |
| // UNREACHABLE(internalformat); |
| return 0; |
| } |
| } |
| |
| bool IsAlpha(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_ALPHA8_EXT: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| bool IsRGB(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_LUMINANCE8_EXT: |
| case GL_RGB565_OES: |
| case GL_RGB8_OES: |
| case SW_YV12_BT601: |
| case SW_YV12_BT709: |
| case SW_YV12_JFIF: |
| return true; |
| default: |
| return false; |
| } |
| } |
| |
| bool IsRGBA(GLint internalformat) |
| { |
| switch(internalformat) |
| { |
| case GL_LUMINANCE8_ALPHA8_EXT: |
| case GL_RGBA: |
| case GL_BGRA8_EXT: // GL_EXT_texture_format_BGRA8888 |
| case GL_RGBA4_OES: |
| case GL_RGB5_A1_OES: |
| case GL_RGBA8_OES: |
| return true; |
| default: |
| return false; |
| } |
| } |
| } |
| |
| namespace es2sw |
| { |
| sw::DepthCompareMode ConvertDepthComparison(GLenum comparison) |
| { |
| switch(comparison) |
| { |
| case GL_NEVER: return sw::DEPTH_NEVER; |
| case GL_ALWAYS: return sw::DEPTH_ALWAYS; |
| case GL_LESS: return sw::DEPTH_LESS; |
| case GL_LEQUAL: return sw::DEPTH_LESSEQUAL; |
| case GL_EQUAL: return sw::DEPTH_EQUAL; |
| case GL_GREATER: return sw::DEPTH_GREATER; |
| case GL_GEQUAL: return sw::DEPTH_GREATEREQUAL; |
| case GL_NOTEQUAL: return sw::DEPTH_NOTEQUAL; |
| default: UNREACHABLE(comparison); |
| } |
| |
| return sw::DEPTH_ALWAYS; |
| } |
| |
| sw::StencilCompareMode ConvertStencilComparison(GLenum comparison) |
| { |
| switch(comparison) |
| { |
| case GL_NEVER: return sw::STENCIL_NEVER; |
| case GL_ALWAYS: return sw::STENCIL_ALWAYS; |
| case GL_LESS: return sw::STENCIL_LESS; |
| case GL_LEQUAL: return sw::STENCIL_LESSEQUAL; |
| case GL_EQUAL: return sw::STENCIL_EQUAL; |
| case GL_GREATER: return sw::STENCIL_GREATER; |
| case GL_GEQUAL: return sw::STENCIL_GREATEREQUAL; |
| case GL_NOTEQUAL: return sw::STENCIL_NOTEQUAL; |
| default: UNREACHABLE(comparison); |
| } |
| |
| return sw::STENCIL_ALWAYS; |
| } |
| |
| sw::AlphaCompareMode ConvertAlphaComparison(GLenum comparison) |
| { |
| switch(comparison) |
| { |
| case GL_NEVER: return sw::ALPHA_NEVER; |
| case GL_ALWAYS: return sw::ALPHA_ALWAYS; |
| case GL_LESS: return sw::ALPHA_LESS; |
| case GL_LEQUAL: return sw::ALPHA_LESSEQUAL; |
| case GL_EQUAL: return sw::ALPHA_EQUAL; |
| case GL_GREATER: return sw::ALPHA_GREATER; |
| case GL_GEQUAL: return sw::ALPHA_GREATEREQUAL; |
| case GL_NOTEQUAL: return sw::ALPHA_NOTEQUAL; |
| default: UNREACHABLE(comparison); |
| } |
| |
| return sw::ALPHA_ALWAYS; |
| } |
| |
| sw::Color<float> ConvertColor(es1::Color color) |
| { |
| return sw::Color<float>(color.red, color.green, color.blue, color.alpha); |
| } |
| |
| sw::BlendFactor ConvertBlendFunc(GLenum blend) |
| { |
| switch(blend) |
| { |
| case GL_ZERO: return sw::BLEND_ZERO; |
| case GL_ONE: return sw::BLEND_ONE; |
| case GL_SRC_COLOR: return sw::BLEND_SOURCE; |
| case GL_ONE_MINUS_SRC_COLOR: return sw::BLEND_INVSOURCE; |
| case GL_DST_COLOR: return sw::BLEND_DEST; |
| case GL_ONE_MINUS_DST_COLOR: return sw::BLEND_INVDEST; |
| case GL_SRC_ALPHA: return sw::BLEND_SOURCEALPHA; |
| case GL_ONE_MINUS_SRC_ALPHA: return sw::BLEND_INVSOURCEALPHA; |
| case GL_DST_ALPHA: return sw::BLEND_DESTALPHA; |
| case GL_ONE_MINUS_DST_ALPHA: return sw::BLEND_INVDESTALPHA; |
| case GL_SRC_ALPHA_SATURATE: return sw::BLEND_SRCALPHASAT; |
| default: UNREACHABLE(blend); |
| } |
| |
| return sw::BLEND_ZERO; |
| } |
| |
| sw::BlendOperation ConvertBlendOp(GLenum blendOp) |
| { |
| switch(blendOp) |
| { |
| case GL_FUNC_ADD_OES: return sw::BLENDOP_ADD; |
| case GL_FUNC_SUBTRACT_OES: return sw::BLENDOP_SUB; |
| case GL_FUNC_REVERSE_SUBTRACT_OES: return sw::BLENDOP_INVSUB; |
| case GL_MIN_EXT: return sw::BLENDOP_MIN; |
| case GL_MAX_EXT: return sw::BLENDOP_MAX; |
| default: UNREACHABLE(blendOp); |
| } |
| |
| return sw::BLENDOP_ADD; |
| } |
| |
| sw::LogicalOperation ConvertLogicalOperation(GLenum logicalOperation) |
| { |
| switch(logicalOperation) |
| { |
| case GL_CLEAR: return sw::LOGICALOP_CLEAR; |
| case GL_SET: return sw::LOGICALOP_SET; |
| case GL_COPY: return sw::LOGICALOP_COPY; |
| case GL_COPY_INVERTED: return sw::LOGICALOP_COPY_INVERTED; |
| case GL_NOOP: return sw::LOGICALOP_NOOP; |
| case GL_INVERT: return sw::LOGICALOP_INVERT; |
| case GL_AND: return sw::LOGICALOP_AND; |
| case GL_NAND: return sw::LOGICALOP_NAND; |
| case GL_OR: return sw::LOGICALOP_OR; |
| case GL_NOR: return sw::LOGICALOP_NOR; |
| case GL_XOR: return sw::LOGICALOP_XOR; |
| case GL_EQUIV: return sw::LOGICALOP_EQUIV; |
| case GL_AND_REVERSE: return sw::LOGICALOP_AND_REVERSE; |
| case GL_AND_INVERTED: return sw::LOGICALOP_AND_INVERTED; |
| case GL_OR_REVERSE: return sw::LOGICALOP_OR_REVERSE; |
| case GL_OR_INVERTED: return sw::LOGICALOP_OR_INVERTED; |
| default: UNREACHABLE(logicalOperation); |
| } |
| |
| return sw::LOGICALOP_COPY; |
| } |
| |
| sw::StencilOperation ConvertStencilOp(GLenum stencilOp) |
| { |
| switch(stencilOp) |
| { |
| case GL_ZERO: return sw::OPERATION_ZERO; |
| case GL_KEEP: return sw::OPERATION_KEEP; |
| case GL_REPLACE: return sw::OPERATION_REPLACE; |
| case GL_INCR: return sw::OPERATION_INCRSAT; |
| case GL_DECR: return sw::OPERATION_DECRSAT; |
| case GL_INVERT: return sw::OPERATION_INVERT; |
| case GL_INCR_WRAP_OES: return sw::OPERATION_INCR; |
| case GL_DECR_WRAP_OES: return sw::OPERATION_DECR; |
| default: UNREACHABLE(stencilOp); |
| } |
| |
| return sw::OPERATION_KEEP; |
| } |
| |
| sw::AddressingMode ConvertTextureWrap(GLenum wrap) |
| { |
| switch(wrap) |
| { |
| case GL_REPEAT: return sw::ADDRESSING_WRAP; |
| case GL_CLAMP_TO_EDGE: return sw::ADDRESSING_CLAMP; |
| case GL_MIRRORED_REPEAT_OES: return sw::ADDRESSING_MIRROR; |
| default: UNREACHABLE(wrap); |
| } |
| |
| return sw::ADDRESSING_WRAP; |
| } |
| |
| sw::CullMode ConvertCullMode(GLenum cullFace, GLenum frontFace) |
| { |
| switch(cullFace) |
| { |
| case GL_FRONT: |
| return (frontFace == GL_CCW ? sw::CULL_CLOCKWISE : sw::CULL_COUNTERCLOCKWISE); |
| case GL_BACK: |
| return (frontFace == GL_CCW ? sw::CULL_COUNTERCLOCKWISE : sw::CULL_CLOCKWISE); |
| case GL_FRONT_AND_BACK: |
| return sw::CULL_NONE; // culling will be handled during draw |
| default: UNREACHABLE(cullFace); |
| } |
| |
| return sw::CULL_COUNTERCLOCKWISE; |
| } |
| |
| unsigned int ConvertColorMask(bool red, bool green, bool blue, bool alpha) |
| { |
| return (red ? 0x00000001 : 0) | |
| (green ? 0x00000002 : 0) | |
| (blue ? 0x00000004 : 0) | |
| (alpha ? 0x00000008 : 0); |
| } |
| |
| sw::MipmapType ConvertMipMapFilter(GLenum minFilter) |
| { |
| switch(minFilter) |
| { |
| case GL_NEAREST: |
| case GL_LINEAR: |
| return sw::MIPMAP_NONE; |
| break; |
| case GL_NEAREST_MIPMAP_NEAREST: |
| case GL_LINEAR_MIPMAP_NEAREST: |
| return sw::MIPMAP_POINT; |
| break; |
| case GL_NEAREST_MIPMAP_LINEAR: |
| case GL_LINEAR_MIPMAP_LINEAR: |
| return sw::MIPMAP_LINEAR; |
| break; |
| default: |
| UNREACHABLE(minFilter); |
| return sw::MIPMAP_NONE; |
| } |
| } |
| |
| sw::FilterType ConvertTextureFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) |
| { |
| if(maxAnisotropy > 1.0f) |
| { |
| return sw::FILTER_ANISOTROPIC; |
| } |
| |
| sw::FilterType magFilterType = sw::FILTER_POINT; |
| switch(magFilter) |
| { |
| case GL_NEAREST: magFilterType = sw::FILTER_POINT; break; |
| case GL_LINEAR: magFilterType = sw::FILTER_LINEAR; break; |
| default: UNREACHABLE(magFilter); |
| } |
| |
| switch(minFilter) |
| { |
| case GL_NEAREST: |
| case GL_NEAREST_MIPMAP_NEAREST: |
| case GL_NEAREST_MIPMAP_LINEAR: |
| return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; |
| case GL_LINEAR: |
| case GL_LINEAR_MIPMAP_NEAREST: |
| case GL_LINEAR_MIPMAP_LINEAR: |
| return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_MIN_LINEAR_MAG_POINT : sw::FILTER_LINEAR; |
| default: |
| UNREACHABLE(minFilter); |
| return (magFilterType == sw::FILTER_POINT) ? sw::FILTER_POINT : sw::FILTER_MIN_POINT_MAG_LINEAR; |
| } |
| } |
| |
| bool ConvertPrimitiveType(GLenum primitiveType, GLsizei elementCount, GLenum elementType, sw::DrawType &drawType, int &primitiveCount) |
| { |
| switch(primitiveType) |
| { |
| case GL_POINTS: |
| drawType = sw::DRAW_POINTLIST; |
| primitiveCount = elementCount; |
| break; |
| case GL_LINES: |
| drawType = sw::DRAW_LINELIST; |
| primitiveCount = elementCount / 2; |
| break; |
| case GL_LINE_LOOP: |
| drawType = sw::DRAW_LINELOOP; |
| primitiveCount = elementCount; |
| break; |
| case GL_LINE_STRIP: |
| drawType = sw::DRAW_LINESTRIP; |
| primitiveCount = elementCount - 1; |
| break; |
| case GL_TRIANGLES: |
| drawType = sw::DRAW_TRIANGLELIST; |
| primitiveCount = elementCount / 3; |
| break; |
| case GL_TRIANGLE_STRIP: |
| drawType = sw::DRAW_TRIANGLESTRIP; |
| primitiveCount = elementCount - 2; |
| break; |
| case GL_TRIANGLE_FAN: |
| drawType = sw::DRAW_TRIANGLEFAN; |
| primitiveCount = elementCount - 2; |
| break; |
| default: |
| return false; |
| } |
| |
| sw::DrawType elementSize; |
| switch(elementType) |
| { |
| case GL_NONE_OES: elementSize = sw::DRAW_NONINDEXED; break; |
| case GL_UNSIGNED_BYTE: elementSize = sw::DRAW_INDEXED8; break; |
| case GL_UNSIGNED_SHORT: elementSize = sw::DRAW_INDEXED16; break; |
| case GL_UNSIGNED_INT: elementSize = sw::DRAW_INDEXED32; break; |
| default: return false; |
| } |
| |
| drawType = sw::DrawType(drawType | elementSize); |
| |
| return true; |
| } |
| |
| sw::TextureStage::StageOperation ConvertCombineOperation(GLenum operation) |
| { |
| switch(operation) |
| { |
| case GL_REPLACE: return sw::TextureStage::STAGE_SELECTARG1; |
| case GL_MODULATE: return sw::TextureStage::STAGE_MODULATE; |
| case GL_ADD: return sw::TextureStage::STAGE_ADD; |
| case GL_ADD_SIGNED: return sw::TextureStage::STAGE_ADDSIGNED; |
| case GL_INTERPOLATE: return sw::TextureStage::STAGE_LERP; |
| case GL_SUBTRACT: return sw::TextureStage::STAGE_SUBTRACT; |
| case GL_DOT3_RGB: return sw::TextureStage::STAGE_DOT3; |
| case GL_DOT3_RGBA: return sw::TextureStage::STAGE_DOT3; |
| default: UNREACHABLE(operation); return sw::TextureStage::STAGE_SELECTARG1; |
| } |
| } |
| |
| sw::TextureStage::SourceArgument ConvertSourceArgument(GLenum argument) |
| { |
| switch(argument) |
| { |
| case GL_TEXTURE: return sw::TextureStage::SOURCE_TEXTURE; |
| case GL_CONSTANT: return sw::TextureStage::SOURCE_CONSTANT; |
| case GL_PRIMARY_COLOR: return sw::TextureStage::SOURCE_DIFFUSE; |
| case GL_PREVIOUS: return sw::TextureStage::SOURCE_CURRENT; |
| default: UNREACHABLE(argument); return sw::TextureStage::SOURCE_CURRENT; |
| } |
| } |
| |
| sw::TextureStage::ArgumentModifier ConvertSourceOperand(GLenum operand) |
| { |
| switch(operand) |
| { |
| case GL_SRC_COLOR: return sw::TextureStage::MODIFIER_COLOR; |
| case GL_ONE_MINUS_SRC_COLOR: return sw::TextureStage::MODIFIER_INVCOLOR; |
| case GL_SRC_ALPHA: return sw::TextureStage::MODIFIER_ALPHA; |
| case GL_ONE_MINUS_SRC_ALPHA: return sw::TextureStage::MODIFIER_INVALPHA; |
| default: UNREACHABLE(operand); return sw::TextureStage::MODIFIER_COLOR; |
| } |
| } |
| } |
| |
| namespace sw2es |
| { |
| GLenum ConvertBackBufferFormat(sw::Format format) |
| { |
| switch(format) |
| { |
| case sw::FORMAT_A4R4G4B4: return GL_RGBA4_OES; |
| case sw::FORMAT_A8R8G8B8: return GL_RGBA8_OES; |
| case sw::FORMAT_A8B8G8R8: return GL_RGBA8_OES; |
| case sw::FORMAT_A1R5G5B5: return GL_RGB5_A1_OES; |
| case sw::FORMAT_R5G6B5: return GL_RGB565_OES; |
| case sw::FORMAT_X8R8G8B8: return GL_RGB8_OES; |
| case sw::FORMAT_X8B8G8R8: return GL_RGB8_OES; |
| default: |
| UNREACHABLE(format); |
| } |
| |
| return GL_RGBA4_OES; |
| } |
| |
| GLenum ConvertDepthStencilFormat(sw::Format format) |
| { |
| switch(format) |
| { |
| case sw::FORMAT_D16: |
| case sw::FORMAT_D24X8: |
| case sw::FORMAT_D32: |
| return GL_DEPTH_COMPONENT16_OES; |
| case sw::FORMAT_D24S8: |
| return GL_DEPTH24_STENCIL8_OES; |
| default: |
| UNREACHABLE(format); |
| } |
| |
| return GL_DEPTH24_STENCIL8_OES; |
| } |
| } |