summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc147
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.h43
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_unittest.cc117
-rw-r--r--gpu/command_buffer/service/context_state.cc22
-rw-r--r--gpu/command_buffer/service/context_state.h8
5 files changed, 302 insertions, 35 deletions
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index 8b547fa..30f4e2b 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -509,67 +509,156 @@ uint32 GLES2Util::ComputeImageGroupSize(int format, int type) {
return bytes_per_element * elements_per_group;
}
-bool GLES2Util::ComputeImagePaddedRowSize(
- int width, int format, int type, int unpack_alignment,
- uint32* padded_row_size) {
- DCHECK(unpack_alignment == 1 || unpack_alignment == 2 ||
- unpack_alignment == 4 || unpack_alignment == 8);
- uint32 bytes_per_group = ComputeImageGroupSize(format, type);
+bool GLES2Util::ComputeImageRowSizeHelper(
+ int width, uint32 bytes_per_group, int alignment,
+ uint32* rt_unpadded_row_size, uint32* rt_padded_row_size) {
+ DCHECK(alignment == 1 || alignment == 2 ||
+ alignment == 4 || alignment == 8);
uint32 unpadded_row_size;
if (!SafeMultiplyUint32(width, bytes_per_group, &unpadded_row_size)) {
return false;
}
uint32 temp;
- if (!SafeAddUint32(unpadded_row_size, unpack_alignment - 1, &temp)) {
- return false;
+ if (!SafeAddUint32(unpadded_row_size, alignment - 1, &temp)) {
+ return false;
}
- *padded_row_size = (temp / unpack_alignment) * unpack_alignment;
+ uint32 padded_row_size = (temp / alignment) * alignment;
+ if (rt_unpadded_row_size)
+ *rt_unpadded_row_size = unpadded_row_size;
+ if (rt_padded_row_size)
+ *rt_padded_row_size = padded_row_size;
return true;
}
+bool GLES2Util::ComputeImagePaddedRowSize(
+ int width, int format, int type, int alignment, uint32* padded_row_size) {
+ uint32 bytes_per_group = ComputeImageGroupSize(format, type);
+ return ComputeImageRowSizeHelper(
+ width, bytes_per_group, alignment, nullptr, padded_row_size);
+}
+
// Returns the amount of data glTexImage*D or glTexSubImage*D will access.
bool GLES2Util::ComputeImageDataSizes(
int width, int height, int depth, int format, int type,
- int unpack_alignment, uint32* size, uint32* ret_unpadded_row_size,
- uint32* ret_padded_row_size) {
- DCHECK(unpack_alignment == 1 || unpack_alignment == 2 ||
- unpack_alignment == 4 || unpack_alignment == 8);
+ int alignment, uint32* size, uint32* opt_unpadded_row_size,
+ uint32* opt_padded_row_size) {
+ DCHECK(width >= 0 && height >= 0 && depth >= 0);
+
uint32 bytes_per_group = ComputeImageGroupSize(format, type);
- uint32 row_size;
- if (!SafeMultiplyUint32(width, bytes_per_group, &row_size)) {
+
+ uint32 unpadded_row_size;
+ uint32 padded_row_size;
+ if (!ComputeImageRowSizeHelper(width, bytes_per_group, alignment,
+ &unpadded_row_size, &padded_row_size)) {
return false;
}
uint32 num_of_rows;
if (!SafeMultiplyUint32(height, depth, &num_of_rows)) {
return false;
}
- if (num_of_rows > 1) {
- uint32 temp;
- if (!SafeAddUint32(row_size, unpack_alignment - 1, &temp)) {
- return false;
- }
- uint32 padded_row_size = (temp / unpack_alignment) * unpack_alignment;
+ if (num_of_rows > 0) {
uint32 size_of_all_but_last_row;
if (!SafeMultiplyUint32((num_of_rows - 1), padded_row_size,
&size_of_all_but_last_row)) {
return false;
}
- if (!SafeAddUint32(size_of_all_but_last_row, row_size, size)) {
+ if (!SafeAddUint32(size_of_all_but_last_row, unpadded_row_size, size)) {
return false;
}
- if (ret_padded_row_size) {
- *ret_padded_row_size = padded_row_size;
+ } else {
+ *size = 0;
+ }
+ if (opt_padded_row_size) {
+ *opt_padded_row_size = padded_row_size;
+ }
+ if (opt_unpadded_row_size) {
+ *opt_unpadded_row_size = unpadded_row_size;
+ }
+
+ return true;
+}
+
+bool GLES2Util::ComputeImageDataSizesES3(
+ int width, int height, int depth, int format, int type,
+ const PixelStoreParams& params,
+ uint32_t* size, uint32_t* opt_unpadded_row_size,
+ uint32_t* opt_padded_row_size, uint32_t* opt_skip_size) {
+ DCHECK(width >= 0 && height >= 0 && depth >= 0);
+
+ uint32 bytes_per_group = ComputeImageGroupSize(format, type);
+
+ uint32 unpadded_row_size;
+ uint32 padded_row_size;
+ if (!ComputeImageRowSizeHelper(width, bytes_per_group, params.alignment,
+ &unpadded_row_size, &padded_row_size)) {
+ return false;
+ }
+ if (params.row_length > 0 &&
+ !ComputeImageRowSizeHelper(params.row_length, bytes_per_group,
+ params.alignment, nullptr, &padded_row_size)) {
+ // Here we re-compute the padded_row_size, but the unpadded_row_size
+ // isn't affected. That is, the last row isn't affected by ROW_LENGTH.
+ return false;
+ }
+
+ int image_height = params.image_height > 0 ? params.image_height : height;
+ uint32 num_of_rows;
+ if (depth > 0) {
+ if (!SafeMultiplyUint32(image_height, depth - 1, &num_of_rows) ||
+ !SafeAddUint32(num_of_rows, height, &num_of_rows)) {
+ return false;
}
} else {
- *size = row_size;
- if (ret_padded_row_size) {
- *ret_padded_row_size = row_size;
+ num_of_rows = 0;
+ }
+
+ if (num_of_rows > 0) {
+ uint32 size_of_all_but_last_row;
+ if (!SafeMultiplyUint32((num_of_rows - 1), padded_row_size,
+ &size_of_all_but_last_row)) {
+ return false;
}
+ if (!SafeAddUint32(size_of_all_but_last_row, unpadded_row_size, size)) {
+ return false;
+ }
+ } else {
+ *size = 0;
}
- if (ret_unpadded_row_size) {
- *ret_unpadded_row_size = row_size;
+
+ uint32 skip_size = 0;
+ if (params.skip_images > 0) {
+ uint32 image_size;
+ if (!SafeMultiplyUint32(image_height, padded_row_size, &image_size))
+ return false;
+ if (!SafeMultiplyUint32(image_size, params.skip_images, &skip_size))
+ return false;
+ }
+ if (params.skip_rows > 0) {
+ uint32 temp;
+ if (!SafeMultiplyUint32(padded_row_size, params.skip_rows, &temp))
+ return false;
+ if (!SafeAddUint32(skip_size, temp, &skip_size))
+ return false;
}
+ if (params.skip_pixels > 0) {
+ uint32 temp;
+ if (!SafeMultiplyUint32(bytes_per_group, params.skip_pixels, &temp))
+ return false;
+ if (!SafeAddUint32(skip_size, temp, &skip_size))
+ return false;
+ }
+ uint32 total_size;
+ if (!SafeAddUint32(*size, skip_size, &total_size))
+ return false;
+ if (opt_padded_row_size) {
+ *opt_padded_row_size = padded_row_size;
+ }
+ if (opt_unpadded_row_size) {
+ *opt_unpadded_row_size = unpadded_row_size;
+ }
+ if (opt_skip_size)
+ *opt_skip_size = skip_size;
return true;
}
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h
index 3aa0299..e3b82b8 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -52,6 +52,24 @@ inline bool SafeAddInt32(int32_t a, int32_t b, int32_t* dst) {
return checked.IsValid();
}
+struct GLES2_UTILS_EXPORT PixelStoreParams {
+ PixelStoreParams()
+ : alignment(4),
+ row_length(0),
+ image_height(0),
+ skip_pixels(0),
+ skip_rows(0),
+ skip_images(0) {
+ }
+
+ int32_t alignment;
+ int32_t row_length;
+ int32_t image_height;
+ int32_t skip_pixels;
+ int32_t skip_rows;
+ int32_t skip_images;
+};
+
// Utilties for GLES2 support.
class GLES2_UTILS_EXPORT GLES2Util {
public:
@@ -105,17 +123,26 @@ class GLES2_UTILS_EXPORT GLES2Util {
// Computes the size of an image row including alignment padding
static bool ComputeImagePaddedRowSize(
- int width, int format, int type, int unpack_alignment,
+ int width, int format, int type, int alignment,
uint32_t* padded_row_size);
// Computes the size of image data for TexImage2D and TexSubImage2D.
- // Optionally the unpadded and padded row sizes can be returned. If height < 2
- // then the padded_row_size will be the same as the unpadded_row_size since
- // padding is not necessary.
+ // Optionally the unpadded and padded row sizes can be returned.
static bool ComputeImageDataSizes(
int width, int height, int depth, int format, int type,
- int unpack_alignment, uint32_t* size, uint32_t* unpadded_row_size,
- uint32_t* padded_row_size);
+ int alignment, uint32_t* size, uint32_t* opt_unpadded_row_size,
+ uint32_t* opt_padded_row_size);
+
+ // Similar to the above function, but taking into consideration all ES3
+ // pixel pack/unpack parameters.
+ // Optionally the skipped bytes in the beginning can be returned.
+ // Note the returned |size| does NOT include |skip_size|.
+ // TODO(zmo): merging ComputeImageDataSize and ComputeImageDataSizeES3.
+ static bool ComputeImageDataSizesES3(
+ int width, int height, int depth, int format, int type,
+ const PixelStoreParams& params,
+ uint32_t* size, uint32_t* opt_unpadded_row_size,
+ uint32_t* opt_padded_row_size, uint32_t* opt_skip_size);
static size_t RenderbufferBytesPerPixel(int format);
@@ -192,6 +219,10 @@ class GLES2_UTILS_EXPORT GLES2Util {
static std::string GetQualifiedEnumString(
const EnumToString* table, size_t count, uint32_t value);
+ static bool ComputeImageRowSizeHelper(
+ int width, uint32 bytes_per_group, int alignment,
+ uint32* rt_unpadded_row_size, uint32* rt_padded_row_size);
+
static const EnumToString* const enum_to_string_table_;
static const size_t enum_to_string_table_len_;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
index 3eb2a38..a435f28 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils_unittest.cc
@@ -320,6 +320,123 @@ TEST_F(GLES2UtilTest, ComputeImageDataSizeDepth) {
EXPECT_EQ(kWidth * 3 + 7, padded_row_size);
}
+TEST_F(GLES2UtilTest, ComputeImageDataSizePixelStoreParams) {
+ const uint32_t kWidth = 3;
+ const uint32_t kHeight = 3;
+ const uint32_t kDepth = 3;
+ uint32_t size;
+ uint32_t unpadded_row_size;
+ uint32_t padded_row_size;
+ uint32_t skip_size;
+
+ { // Default
+ PixelStoreParams params;
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(kWidth * 3, unpadded_row_size);
+ EXPECT_EQ(kWidth * 3 + 3, padded_row_size);
+ EXPECT_EQ(padded_row_size * (kHeight * kDepth - 1) + unpadded_row_size,
+ size);
+ EXPECT_EQ(0u, skip_size);
+ }
+
+ { // row_length > width
+ PixelStoreParams params;
+ params.row_length = kWidth + 2;
+ uint32_t kPadding = 1; // 5 * 3 = 15 -> 16
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(static_cast<uint32_t>(kWidth * 3), unpadded_row_size);
+ EXPECT_EQ(static_cast<uint32_t>(params.row_length * 3 + kPadding),
+ padded_row_size);
+ EXPECT_EQ(padded_row_size * (kHeight * kDepth - 1) + unpadded_row_size,
+ size);
+ EXPECT_EQ(0u, skip_size);
+ }
+
+ { // row_length < width
+ PixelStoreParams params;
+ params.row_length = kWidth - 1;
+ uint32_t kPadding = 2; // 2 * 3 = 6 -> 8
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(static_cast<uint32_t>(kWidth * 3), unpadded_row_size);
+ EXPECT_EQ(static_cast<uint32_t>(params.row_length * 3 + kPadding),
+ padded_row_size);
+ EXPECT_EQ(padded_row_size * (kHeight * kDepth - 1) + unpadded_row_size,
+ size);
+ EXPECT_EQ(0u, skip_size);
+ }
+
+ { // image_height > height
+ PixelStoreParams params;
+ params.image_height = kHeight + 1;
+ uint32_t kPadding = 3; // 3 * 3 = 9 -> 21
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(kWidth * 3, unpadded_row_size);
+ EXPECT_EQ(kWidth * 3 + kPadding, padded_row_size);
+ EXPECT_EQ((params.image_height * (kDepth - 1) + kHeight - 1) *
+ padded_row_size + unpadded_row_size, size);
+ EXPECT_EQ(0u, skip_size);
+ }
+
+ { // image_height < height
+ PixelStoreParams params;
+ params.image_height = kHeight - 1;
+ uint32_t kPadding = 3; // 3 * 3 = 9 -> 12
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(kWidth * 3, unpadded_row_size);
+ EXPECT_EQ(kWidth * 3 + kPadding, padded_row_size);
+ EXPECT_EQ((params.image_height * (kDepth - 1) + kHeight - 1) *
+ padded_row_size + unpadded_row_size, size);
+ EXPECT_EQ(0u, skip_size);
+ }
+
+ { // skip_pixels, skip_rows, skip_images, alignment = 4, RGB
+ PixelStoreParams params;
+ params.skip_pixels = 1;
+ params.skip_rows = 10;
+ params.skip_images = 2;
+ uint32_t kPadding = 3; // 3 * 3 = 9 -> 12
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGB, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(kWidth * 3, unpadded_row_size);
+ EXPECT_EQ(kWidth * 3 + kPadding, padded_row_size);
+ EXPECT_EQ(padded_row_size * kHeight * params.skip_images +
+ padded_row_size * params.skip_rows + 3 * params.skip_pixels,
+ skip_size);
+ EXPECT_EQ(padded_row_size * (kWidth * kDepth - 1) + unpadded_row_size,
+ size);
+ }
+
+ { // skip_pixels, skip_rows, skip_images, alignment = 8, RGBA
+ PixelStoreParams params;
+ params.skip_pixels = 1;
+ params.skip_rows = 10;
+ params.skip_images = 2;
+ params.alignment = 8;
+ uint32_t kPadding = 4; // 3 * 4 = 12 -> 16
+ EXPECT_TRUE(GLES2Util::ComputeImageDataSizesES3(
+ kWidth, kHeight, kDepth, GL_RGBA, GL_UNSIGNED_BYTE, params,
+ &size, &unpadded_row_size, &padded_row_size, &skip_size));
+ EXPECT_EQ(kWidth * 4, unpadded_row_size);
+ EXPECT_EQ(kWidth * 4 + kPadding, padded_row_size);
+ EXPECT_EQ(padded_row_size * kHeight * params.skip_images +
+ padded_row_size * params.skip_rows + 4 * params.skip_pixels,
+ skip_size);
+ EXPECT_EQ(padded_row_size * (kWidth * kDepth - 1) + unpadded_row_size,
+ size);
+ }
+}
+
TEST_F(GLES2UtilTest, RenderbufferBytesPerPixel) {
EXPECT_EQ(1u, GLES2Util::RenderbufferBytesPerPixel(GL_STENCIL_INDEX8));
EXPECT_EQ(2u, GLES2Util::RenderbufferBytesPerPixel(GL_RGBA4));
diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc
index b93a372..4cbf294 100644
--- a/gpu/command_buffer/service/context_state.cc
+++ b/gpu/command_buffer/service/context_state.cc
@@ -594,6 +594,28 @@ void ContextState::UnbindSampler(Sampler* sampler) {
}
}
+PixelStoreParams ContextState::GetPackParams() {
+ PixelStoreParams params;
+ params.alignment = pack_alignment;
+ params.row_length = pack_row_length;
+ params.skip_pixels = pack_skip_pixels;
+ params.skip_rows = pack_skip_rows;
+ return params;
+}
+
+PixelStoreParams ContextState::GetUnpackParams(Dimension dimension) {
+ PixelStoreParams params;
+ params.alignment = unpack_alignment;
+ params.row_length = unpack_row_length;
+ params.skip_pixels = unpack_skip_pixels;
+ params.skip_rows = unpack_skip_rows;
+ if (dimension == k3D) {
+ params.image_height = unpack_image_height;
+ params.skip_images = unpack_skip_images;
+ }
+ return params;
+}
+
// Include the auto-generated part of this file. We split this because it means
// we can easily edit the non-auto generated parts right here in this file
// instead of having to edit some template or the code generator.
diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h
index 5f154c2..e1fa4a4 100644
--- a/gpu/command_buffer/service/context_state.h
+++ b/gpu/command_buffer/service/context_state.h
@@ -138,6 +138,11 @@ template <>
GPU_EXPORT void Vec4::SetValues<GLuint>(const GLuint* values);
struct GPU_EXPORT ContextState {
+ enum Dimension {
+ k2D,
+ k3D
+ };
+
ContextState(FeatureInfo* feature_info,
ErrorStateClient* error_state_client,
Logger* logger);
@@ -220,6 +225,9 @@ struct GPU_EXPORT ContextState {
void UnbindTexture(TextureRef* texture);
void UnbindSampler(Sampler* sampler);
+ PixelStoreParams GetPackParams();
+ PixelStoreParams GetUnpackParams(Dimension dimension);
+
#include "gpu/command_buffer/service/context_state_autogen.h"
EnableFlags enable_flags;