| // Copyright 2015 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 "ui/gfx/buffer_format_util.h" | 
 |  | 
 | #include "base/logging.h" | 
 | #include "base/numerics/safe_math.h" | 
 |  | 
 | namespace gfx { | 
 |  | 
 | size_t NumberOfPlanesForBufferFormat(BufferFormat format) { | 
 |   switch (format) { | 
 |     case BufferFormat::ATC: | 
 |     case BufferFormat::ATCIA: | 
 |     case BufferFormat::DXT1: | 
 |     case BufferFormat::DXT5: | 
 |     case BufferFormat::ETC1: | 
 |     case BufferFormat::R_8: | 
 |     case BufferFormat::RGBA_4444: | 
 |     case BufferFormat::RGBA_8888: | 
 |     case BufferFormat::BGRX_8888: | 
 |     case BufferFormat::BGRA_8888: | 
 |     case BufferFormat::UYVY_422: | 
 |       return 1; | 
 |     case BufferFormat::YUV_420: | 
 |       return 3; | 
 |   } | 
 |   NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | size_t SubsamplingFactorForBufferFormat(BufferFormat format, int plane) { | 
 |   switch (format) { | 
 |     case BufferFormat::ATC: | 
 |     case BufferFormat::ATCIA: | 
 |     case BufferFormat::DXT1: | 
 |     case BufferFormat::DXT5: | 
 |     case BufferFormat::ETC1: | 
 |     case BufferFormat::R_8: | 
 |     case BufferFormat::RGBA_4444: | 
 |     case BufferFormat::RGBA_8888: | 
 |     case BufferFormat::BGRX_8888: | 
 |     case BufferFormat::BGRA_8888: | 
 |     case BufferFormat::UYVY_422: | 
 |       return 1; | 
 |     case BufferFormat::YUV_420: { | 
 |       static size_t factor[] = {1, 2, 2}; | 
 |       DCHECK_LT(static_cast<size_t>(plane), arraysize(factor)); | 
 |       return factor[plane]; | 
 |     } | 
 |   } | 
 |   NOTREACHED(); | 
 |   return 0; | 
 | } | 
 |  | 
 | size_t RowSizeForBufferFormat(size_t width, BufferFormat format, int plane) { | 
 |   size_t row_size = 0; | 
 |   bool valid = RowSizeForBufferFormatChecked(width, format, plane, &row_size); | 
 |   DCHECK(valid); | 
 |   return row_size; | 
 | } | 
 |  | 
 | bool RowSizeForBufferFormatChecked( | 
 |     size_t width, BufferFormat format, int plane, size_t* size_in_bytes) { | 
 |   base::CheckedNumeric<size_t> checked_size = width; | 
 |   switch (format) { | 
 |     case BufferFormat::ATCIA: | 
 |     case BufferFormat::DXT5: | 
 |       DCHECK_EQ(0, plane); | 
 |       *size_in_bytes = width; | 
 |       return true; | 
 |     case BufferFormat::ATC: | 
 |     case BufferFormat::DXT1: | 
 |     case BufferFormat::ETC1: | 
 |       DCHECK_EQ(0, plane); | 
 |       DCHECK_EQ(0u, width % 2); | 
 |       *size_in_bytes = width / 2; | 
 |       return true; | 
 |     case BufferFormat::R_8: | 
 |       checked_size += 3; | 
 |       if (!checked_size.IsValid()) | 
 |         return false; | 
 |       *size_in_bytes = checked_size.ValueOrDie() & ~0x3; | 
 |       return true; | 
 |     case BufferFormat::RGBA_4444: | 
 |     case BufferFormat::UYVY_422: | 
 |       checked_size *= 2; | 
 |       if (!checked_size.IsValid()) | 
 |         return false; | 
 |       *size_in_bytes = checked_size.ValueOrDie(); | 
 |       return true; | 
 |     case BufferFormat::BGRX_8888: | 
 |     case BufferFormat::RGBA_8888: | 
 |     case BufferFormat::BGRA_8888: | 
 |       checked_size *= 4; | 
 |       if (!checked_size.IsValid()) | 
 |         return false; | 
 |       *size_in_bytes = checked_size.ValueOrDie(); | 
 |       return true; | 
 |     case BufferFormat::YUV_420: | 
 |       DCHECK_EQ(0u, width % 2); | 
 |       *size_in_bytes = width / SubsamplingFactorForBufferFormat(format, plane); | 
 |       return true; | 
 |   } | 
 |   NOTREACHED(); | 
 |   return false; | 
 | } | 
 |  | 
 | size_t BufferSizeForBufferFormat( | 
 |     const Size& size, BufferFormat format) { | 
 |   size_t buffer_size = 0; | 
 |   bool valid = BufferSizeForBufferFormatChecked(size, format, &buffer_size); | 
 |   DCHECK(valid); | 
 |   return buffer_size; | 
 | } | 
 |  | 
 | bool BufferSizeForBufferFormatChecked( | 
 |     const Size& size, BufferFormat format, size_t* size_in_bytes) { | 
 |   base::CheckedNumeric<size_t> checked_size = 0; | 
 |   size_t num_planes = NumberOfPlanesForBufferFormat(format); | 
 |   for (size_t i = 0; i < num_planes; ++i) { | 
 |     size_t row_size = 0; | 
 |     if (!RowSizeForBufferFormatChecked(size.width(), format, i, &row_size)) | 
 |       return false; | 
 |     base::CheckedNumeric<size_t> checked_plane_size = row_size; | 
 |     checked_plane_size *= size.height() / | 
 |                           SubsamplingFactorForBufferFormat(format, i); | 
 |     if (!checked_plane_size.IsValid()) | 
 |       return false; | 
 |     checked_size += checked_plane_size.ValueOrDie(); | 
 |     if (!checked_size.IsValid()) | 
 |       return false; | 
 |   } | 
 |   *size_in_bytes = checked_size.ValueOrDie(); | 
 |   return true; | 
 | } | 
 |  | 
 | }  // namespace gfx |