| // Copyright 2016 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/viz/common/resources/resource_format_utils.h" |
| |
| #include "base/logging.h" |
| #include "base/stl_util.h" |
| #include "third_party/khronos/GLES2/gl2.h" |
| #include "third_party/khronos/GLES2/gl2ext.h" |
| #include "ui/gfx/buffer_types.h" |
| |
| namespace viz { |
| |
| SkColorType ResourceFormatToClosestSkColorType(bool gpu_compositing, |
| ResourceFormat format) { |
| if (!gpu_compositing) { |
| // In software compositing we lazily use RGBA_8888 throughout the system, |
| // but actual pixel encodings are the native skia bit ordering, which can be |
| // RGBA or BGRA. |
| return kN32_SkColorType; |
| } |
| |
| // Use kN32_SkColorType if there is no corresponding SkColorType. |
| switch (format) { |
| case RGBA_4444: |
| return kARGB_4444_SkColorType; |
| case RGBA_8888: |
| return kRGBA_8888_SkColorType; |
| case BGRA_8888: |
| return kBGRA_8888_SkColorType; |
| case ALPHA_8: |
| return kAlpha_8_SkColorType; |
| case RGB_565: |
| return kRGB_565_SkColorType; |
| case LUMINANCE_8: |
| return kGray_8_SkColorType; |
| case RGBX_8888: |
| return kRGB_888x_SkColorType; |
| case ETC1: |
| case RED_8: |
| case LUMINANCE_F16: |
| case R16_EXT: |
| case BGR_565: |
| case RG_88: |
| case BGRX_8888: |
| case RGBX_1010102: |
| case BGRX_1010102: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| return kN32_SkColorType; |
| case RGBA_F16: |
| return kRGBA_F16_SkColorType; |
| } |
| NOTREACHED(); |
| return kN32_SkColorType; |
| } |
| |
| int BitsPerPixel(ResourceFormat format) { |
| switch (format) { |
| case RGBA_F16: |
| return 64; |
| case BGRA_8888: |
| case RGBA_8888: |
| case RGBX_8888: |
| case BGRX_8888: |
| case RGBX_1010102: |
| case BGRX_1010102: |
| return 32; |
| case RGBA_4444: |
| case RGB_565: |
| case LUMINANCE_F16: |
| case R16_EXT: |
| case BGR_565: |
| case RG_88: |
| case UYVY_422: |
| return 16; |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| return 12; |
| case ALPHA_8: |
| case LUMINANCE_8: |
| case RED_8: |
| return 8; |
| case ETC1: |
| return 4; |
| } |
| NOTREACHED(); |
| return 0; |
| } |
| |
| unsigned int GLDataType(ResourceFormat format) { |
| DCHECK_LE(format, RESOURCE_FORMAT_MAX); |
| static const GLenum format_gl_data_type[] = { |
| GL_UNSIGNED_BYTE, // RGBA_8888 |
| GL_UNSIGNED_SHORT_4_4_4_4, // RGBA_4444 |
| GL_UNSIGNED_BYTE, // BGRA_8888 |
| GL_UNSIGNED_BYTE, // ALPHA_8 |
| GL_UNSIGNED_BYTE, // LUMINANCE_8 |
| GL_UNSIGNED_SHORT_5_6_5, // RGB_565, |
| GL_ZERO, // BGR_565 |
| GL_UNSIGNED_BYTE, // ETC1 |
| GL_UNSIGNED_BYTE, // RED_8 |
| GL_UNSIGNED_BYTE, // RG_88 |
| GL_HALF_FLOAT_OES, // LUMINANCE_F16 |
| GL_HALF_FLOAT_OES, // RGBA_F16 |
| GL_UNSIGNED_SHORT, // R16_EXT |
| GL_UNSIGNED_BYTE, // RGBX_8888 |
| GL_ZERO, // BGRX_8888 |
| GL_UNSIGNED_INT_2_10_10_10_REV_EXT, // RGBX_1010102 |
| GL_ZERO, // BGRX_1010102 |
| GL_ZERO, // YVU_420 |
| GL_ZERO, // YUV_420_BIPLANAR |
| GL_ZERO, // UYVY_422 |
| }; |
| static_assert(base::size(format_gl_data_type) == (RESOURCE_FORMAT_MAX + 1), |
| "format_gl_data_type does not handle all cases."); |
| |
| return format_gl_data_type[format]; |
| } |
| |
| unsigned int GLDataFormat(ResourceFormat format) { |
| DCHECK_LE(format, RESOURCE_FORMAT_MAX); |
| static const GLenum format_gl_data_format[] = { |
| GL_RGBA, // RGBA_8888 |
| GL_RGBA, // RGBA_4444 |
| GL_BGRA_EXT, // BGRA_8888 |
| GL_ALPHA, // ALPHA_8 |
| GL_LUMINANCE, // LUMINANCE_8 |
| GL_RGB, // RGB_565 |
| GL_ZERO, // BGR_565 |
| GL_ETC1_RGB8_OES, // ETC1 |
| GL_RED_EXT, // RED_8 |
| GL_RG_EXT, // RG_88 |
| GL_LUMINANCE, // LUMINANCE_F16 |
| GL_RGBA, // RGBA_F16 |
| GL_RED_EXT, // R16_EXT |
| GL_RGB, // RGBX_8888 |
| GL_ZERO, // BGRX_8888 |
| GL_RGBA, // RGBX_1010102 |
| GL_ZERO, // BGRX_1010102 |
| GL_ZERO, // YVU_420 |
| GL_ZERO, // YUV_420_BIPLANAR |
| GL_ZERO, // UYVY_422 |
| }; |
| static_assert(base::size(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1), |
| "format_gl_data_format does not handle all cases."); |
| |
| return format_gl_data_format[format]; |
| } |
| |
| unsigned int GLInternalFormat(ResourceFormat format) { |
| // In GLES2, the internal format must match the texture format. (It no longer |
| // is true in GLES3, however it still holds for the BGRA extension.) |
| // GL_EXT_texture_norm16 follows GLES3 semantics and only exposes a sized |
| // internal format (GL_R16_EXT). |
| if (format == R16_EXT) |
| return GL_R16_EXT; |
| else if (format == RG_88) |
| return GL_RG8_EXT; |
| |
| return GLDataFormat(format); |
| } |
| |
| unsigned int GLCopyTextureInternalFormat(ResourceFormat format) { |
| // In GLES2, valid formats for glCopyTexImage2D are: GL_ALPHA, GL_LUMINANCE, |
| // GL_LUMINANCE_ALPHA, GL_RGB, or GL_RGBA. |
| // Extensions typically used for glTexImage2D do not also work for |
| // glCopyTexImage2D. For instance GL_BGRA_EXT may not be used for |
| // anything but gl(Sub)TexImage2D: |
| // https://www.khronos.org/registry/gles/extensions/EXT/EXT_texture_format_BGRA8888.txt |
| DCHECK_LE(format, RESOURCE_FORMAT_MAX); |
| static const GLenum format_gl_data_format[] = { |
| GL_RGBA, // RGBA_8888 |
| GL_RGBA, // RGBA_4444 |
| GL_RGBA, // BGRA_8888 |
| GL_ALPHA, // ALPHA_8 |
| GL_LUMINANCE, // LUMINANCE_8 |
| GL_RGB, // RGB_565 |
| GL_ZERO, // BGR_565 |
| GL_RGB, // ETC1 |
| GL_LUMINANCE, // RED_8 |
| GL_RGBA, // RG_88 |
| GL_LUMINANCE, // LUMINANCE_F16 |
| GL_RGBA, // RGBA_F16 |
| GL_LUMINANCE, // R16_EXT |
| GL_RGB, // RGBX_8888 |
| GL_RGB, // BGRX_8888 |
| GL_ZERO, // RGBX_1010102 |
| GL_ZERO, // BGRX_1010102 |
| GL_ZERO, // YVU_420 |
| GL_ZERO, // YUV_420_BIPLANAR |
| GL_ZERO, // UYVY_422 |
| }; |
| |
| static_assert(base::size(format_gl_data_format) == (RESOURCE_FORMAT_MAX + 1), |
| "format_gl_data_format does not handle all cases."); |
| |
| return format_gl_data_format[format]; |
| } |
| |
| gfx::BufferFormat BufferFormat(ResourceFormat format) { |
| switch (format) { |
| case BGRA_8888: |
| return gfx::BufferFormat::BGRA_8888; |
| case RED_8: |
| return gfx::BufferFormat::R_8; |
| case R16_EXT: |
| return gfx::BufferFormat::R_16; |
| case RGBA_4444: |
| return gfx::BufferFormat::RGBA_4444; |
| case RGBA_8888: |
| return gfx::BufferFormat::RGBA_8888; |
| case RGBA_F16: |
| return gfx::BufferFormat::RGBA_F16; |
| case BGR_565: |
| return gfx::BufferFormat::BGR_565; |
| case RG_88: |
| return gfx::BufferFormat::RG_88; |
| case RGBX_8888: |
| return gfx::BufferFormat::RGBX_8888; |
| case BGRX_8888: |
| return gfx::BufferFormat::BGRX_8888; |
| case RGBX_1010102: |
| return gfx::BufferFormat::RGBX_1010102; |
| case BGRX_1010102: |
| return gfx::BufferFormat::BGRX_1010102; |
| case YVU_420: |
| return gfx::BufferFormat::YVU_420; |
| case YUV_420_BIPLANAR: |
| return gfx::BufferFormat::YUV_420_BIPLANAR; |
| case UYVY_422: |
| return gfx::BufferFormat::UYVY_422; |
| case ETC1: |
| case ALPHA_8: |
| case LUMINANCE_8: |
| case RGB_565: |
| case LUMINANCE_F16: |
| // These types not allowed by IsGpuMemoryBufferFormatSupported(), so |
| // give a default value that will not be used. |
| break; |
| } |
| return gfx::BufferFormat::RGBA_8888; |
| } |
| |
| bool IsResourceFormatCompressed(ResourceFormat format) { |
| return format == ETC1; |
| } |
| |
| unsigned int TextureStorageFormat(ResourceFormat format) { |
| switch (format) { |
| case RGBA_8888: |
| return GL_RGBA8_OES; |
| case BGRA_8888: |
| return GL_BGRA8_EXT; |
| case RGBA_F16: |
| return GL_RGBA16F_EXT; |
| case RGBA_4444: |
| return GL_RGBA4; |
| case ALPHA_8: |
| return GL_ALPHA8_EXT; |
| case LUMINANCE_8: |
| return GL_LUMINANCE8_EXT; |
| case RGB_565: |
| return GL_RGB565; |
| case RED_8: |
| return GL_R8_EXT; |
| case RG_88: |
| return GL_RG8_EXT; |
| case LUMINANCE_F16: |
| return GL_LUMINANCE16F_EXT; |
| case R16_EXT: |
| return GL_R16_EXT; |
| case RGBX_8888: |
| return GL_RGB8_OES; |
| case RGBX_1010102: |
| return GL_RGB10_A2_EXT; |
| case BGR_565: |
| case ETC1: |
| case BGRX_8888: |
| case BGRX_1010102: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| break; |
| } |
| NOTREACHED(); |
| return GL_RGBA8_OES; |
| } |
| |
| bool IsGpuMemoryBufferFormatSupported(ResourceFormat format) { |
| switch (format) { |
| case BGRA_8888: |
| case RED_8: |
| case R16_EXT: |
| case RGBA_4444: |
| case RGBA_8888: |
| case RGBA_F16: |
| return true; |
| // These formats have no BufferFormat equivalent or are only used |
| // for external textures, or have no GL equivalent formats. |
| case ETC1: |
| case ALPHA_8: |
| case LUMINANCE_8: |
| case RGB_565: |
| case LUMINANCE_F16: |
| case BGR_565: |
| case RG_88: |
| case RGBX_8888: |
| case BGRX_8888: |
| case RGBX_1010102: |
| case BGRX_1010102: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| return false; |
| } |
| NOTREACHED(); |
| return false; |
| } |
| |
| bool IsBitmapFormatSupported(ResourceFormat format) { |
| switch (format) { |
| case RGBA_8888: |
| return true; |
| case RGBA_4444: |
| case BGRA_8888: |
| case ALPHA_8: |
| case LUMINANCE_8: |
| case RGB_565: |
| case ETC1: |
| case RED_8: |
| case LUMINANCE_F16: |
| case RGBA_F16: |
| case R16_EXT: |
| case BGR_565: |
| case RG_88: |
| case RGBX_8888: |
| case BGRX_8888: |
| case RGBX_1010102: |
| case BGRX_1010102: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| return false; |
| } |
| NOTREACHED(); |
| return false; |
| } |
| |
| ResourceFormat GetResourceFormat(gfx::BufferFormat format) { |
| switch (format) { |
| case gfx::BufferFormat::BGRA_8888: |
| return BGRA_8888; |
| case gfx::BufferFormat::R_8: |
| return RED_8; |
| case gfx::BufferFormat::R_16: |
| return R16_EXT; |
| case gfx::BufferFormat::RGBA_4444: |
| return RGBA_4444; |
| case gfx::BufferFormat::RGBA_8888: |
| return RGBA_8888; |
| case gfx::BufferFormat::RGBA_F16: |
| return RGBA_F16; |
| case gfx::BufferFormat::BGR_565: |
| return BGR_565; |
| case gfx::BufferFormat::RG_88: |
| return RG_88; |
| case gfx::BufferFormat::RGBX_8888: |
| return RGBX_8888; |
| case gfx::BufferFormat::BGRX_8888: |
| return BGRX_8888; |
| case gfx::BufferFormat::RGBX_1010102: |
| return RGBX_1010102; |
| case gfx::BufferFormat::BGRX_1010102: |
| return BGRX_1010102; |
| case gfx::BufferFormat::YVU_420: |
| return YVU_420; |
| case gfx::BufferFormat::YUV_420_BIPLANAR: |
| return YUV_420_BIPLANAR; |
| case gfx::BufferFormat::UYVY_422: |
| return UYVY_422; |
| default: |
| NOTREACHED(); |
| return RGBA_8888; |
| } |
| } |
| |
| bool GLSupportsFormat(ResourceFormat format) { |
| switch (format) { |
| case BGR_565: |
| case BGRX_8888: |
| case BGRX_1010102: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| return false; |
| default: |
| return true; |
| } |
| } |
| |
| #if BUILDFLAG(ENABLE_VULKAN) |
| VkFormat ToVkFormat(ResourceFormat format) { |
| switch (format) { |
| case RGBA_8888: |
| return VK_FORMAT_R8G8B8A8_UNORM; // or VK_FORMAT_R8G8B8A8_SRGB |
| case RGBA_4444: |
| return VK_FORMAT_R4G4B4A4_UNORM_PACK16; |
| case BGRA_8888: |
| return VK_FORMAT_B8G8R8A8_UNORM; |
| case RED_8: |
| return VK_FORMAT_R8_UNORM; |
| case RGB_565: |
| return VK_FORMAT_R5G6B5_UNORM_PACK16; |
| case BGR_565: |
| return VK_FORMAT_B5G6R5_UNORM_PACK16; |
| case RG_88: |
| return VK_FORMAT_R8G8_UNORM; |
| case RGBA_F16: |
| return VK_FORMAT_R16_SFLOAT; |
| case R16_EXT: |
| return VK_FORMAT_R16_UNORM; |
| case RGBX_8888: |
| return VK_FORMAT_R8G8B8_UNORM; |
| case BGRX_8888: |
| return VK_FORMAT_B8G8R8_UNORM; |
| case RGBX_1010102: |
| return VK_FORMAT_A2R10G10B10_UNORM_PACK32; |
| case BGRX_1010102: |
| return VK_FORMAT_A2B10G10R10_UNORM_PACK32; |
| case ALPHA_8: |
| case LUMINANCE_8: |
| case LUMINANCE_F16: |
| case YVU_420: |
| case YUV_420_BIPLANAR: |
| case UYVY_422: |
| case ETC1: |
| break; |
| } |
| NOTREACHED(); |
| return VK_FORMAT_UNDEFINED; |
| } |
| #endif |
| |
| } // namespace viz |