Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(61)

Unified Diff: gpu/command_buffer/client/gles2_implementation.cc

Issue 851503003: Update from https://crrev.com/311076 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/client/gles2_implementation.cc
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc
index ccbb45745169eaf0ca7a319281a891c6a20acfc4..2b4cc9e76b010bb648490a39bd8fc296e841a4d1 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -8,6 +8,7 @@
#include <GLES2/gl2ext.h>
#include <GLES2/gl2extchromium.h>
+#include <GLES3/gl3.h>
#include <algorithm>
#include <limits>
#include <map>
@@ -77,8 +78,10 @@ GLES2Implementation::GLES2Implementation(
unpack_alignment_(4),
unpack_flip_y_(false),
unpack_row_length_(0),
+ unpack_image_height_(0),
unpack_skip_rows_(0),
unpack_skip_pixels_(0),
+ unpack_skip_images_(0),
pack_reverse_row_order_(false),
active_texture_unit_(0),
bound_framebuffer_(0),
@@ -99,6 +102,7 @@ GLES2Implementation::GLES2Implementation(
support_client_side_arrays_(support_client_side_arrays),
use_count_(0),
error_message_callback_(NULL),
+ current_trace_stack_(0),
gpu_control_(gpu_control),
capabilities_(gpu_control->GetCapabilities()),
weak_ptr_factory_(this) {
@@ -1105,12 +1109,18 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) {
case GL_UNPACK_ROW_LENGTH_EXT:
unpack_row_length_ = param;
return;
+ case GL_UNPACK_IMAGE_HEIGHT:
+ unpack_image_height_ = param;
+ return;
case GL_UNPACK_SKIP_ROWS_EXT:
unpack_skip_rows_ = param;
return;
case GL_UNPACK_SKIP_PIXELS_EXT:
unpack_skip_pixels_ = param;
return;
+ case GL_UNPACK_SKIP_IMAGES:
+ unpack_skip_images_ = param;
+ return;
case GL_UNPACK_FLIP_Y_CHROMIUM:
unpack_flip_y_ = (param != 0);
break;
@@ -1611,7 +1621,7 @@ void GLES2Implementation::TexImage2D(
uint32 unpadded_row_size;
uint32 padded_row_size;
if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, unpack_alignment_, &size,
+ width, height, 1, format, type, unpack_alignment_, &size,
&unpadded_row_size, &padded_row_size)) {
SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large");
return;
@@ -1692,6 +1702,126 @@ void GLES2Implementation::TexImage2D(
CheckGLError();
}
+void GLES2Implementation::TexImage3D(
+ GLenum target, GLint level, GLint internalformat, GLsizei width,
+ GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type,
+ const void* pixels) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage3D("
+ << GLES2Util::GetStringTextureTarget(target) << ", "
+ << level << ", "
+ << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
+ << width << ", " << height << ", " << depth << ", " << border << ", "
+ << GLES2Util::GetStringTextureFormat(format) << ", "
+ << GLES2Util::GetStringPixelType(type) << ", "
+ << static_cast<const void*>(pixels) << ")");
+ if (level < 0 || height < 0 || width < 0 || depth < 0) {
+ SetGLError(GL_INVALID_VALUE, "glTexImage3D", "dimension < 0");
+ return;
+ }
+ if (border != 0) {
+ SetGLError(GL_INVALID_VALUE, "glTexImage3D", "border != 0");
+ return;
+ }
+ uint32 size;
+ uint32 unpadded_row_size;
+ uint32 padded_row_size;
+ if (!GLES2Util::ComputeImageDataSizes(
+ width, height, depth, format, type, unpack_alignment_, &size,
+ &unpadded_row_size, &padded_row_size)) {
+ SetGLError(GL_INVALID_VALUE, "glTexImage3D", "image size too large");
+ return;
+ }
+
+ // If there's a pixel unpack buffer bound use it when issuing TexImage3D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(pixels);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
+ "glTexImage3D", offset, size);
+ if (buffer && buffer->shm_id() != -1) {
+ helper_->TexImage3D(
+ target, level, internalformat, width, height, depth, format, type,
+ buffer->shm_id(), buffer->shm_offset() + offset);
+ buffer->set_last_usage_token(helper_->InsertToken());
+ CheckGLError();
+ }
+ return;
+ }
+
+ // If there's no data just issue TexImage3D
+ if (!pixels) {
+ helper_->TexImage3D(
+ target, level, internalformat, width, height, depth, format, type,
+ 0, 0);
+ CheckGLError();
+ return;
+ }
+
+ // compute the advance bytes per row for the src pixels
+ uint32 src_padded_row_size;
+ if (unpack_row_length_ > 0) {
+ if (!GLES2Util::ComputeImagePaddedRowSize(
+ unpack_row_length_, format, type, unpack_alignment_,
+ &src_padded_row_size)) {
+ SetGLError(
+ GL_INVALID_VALUE, "glTexImage3D", "unpack row length too large");
+ return;
+ }
+ } else {
+ src_padded_row_size = padded_row_size;
+ }
+ uint32 src_height = unpack_image_height_ > 0 ? unpack_image_height_ : height;
+
+ // advance pixels pointer past the skip images/rows/pixels
+ pixels = reinterpret_cast<const int8*>(pixels) +
+ unpack_skip_images_ * src_padded_row_size * src_height +
+ unpack_skip_rows_ * src_padded_row_size;
+ if (unpack_skip_pixels_) {
+ uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type);
+ pixels = reinterpret_cast<const int8*>(pixels) +
+ unpack_skip_pixels_ * group_size;
+ }
+
+ // Check if we can send it all at once.
+ ScopedTransferBufferPtr buffer(size, helper_, transfer_buffer_);
+ if (!buffer.valid()) {
+ return;
+ }
+
+ if (buffer.size() >= size) {
+ void* buffer_pointer = buffer.address();
+ for (GLsizei z = 0; z < depth; ++z) {
+ // Only the last row of the last image is unpadded.
+ uint32 src_unpadded_row_size =
+ (z == depth - 1) ? unpadded_row_size : src_padded_row_size;
+ // TODO(zmo): Ignore flip_y flag for now.
+ CopyRectToBuffer(
+ pixels, height, src_unpadded_row_size, src_padded_row_size, false,
+ buffer_pointer, padded_row_size);
+ pixels = reinterpret_cast<const int8*>(pixels) +
+ src_padded_row_size * src_height;
+ buffer_pointer = reinterpret_cast<int8*>(buffer_pointer) +
+ padded_row_size * height;
+ }
+ helper_->TexImage3D(
+ target, level, internalformat, width, height, depth, format, type,
+ buffer.shm_id(), buffer.offset());
+ CheckGLError();
+ return;
+ }
+
+ // No, so send it using TexSubImage3D.
+ helper_->TexImage3D(
+ target, level, internalformat, width, height, depth, format, type,
+ 0, 0);
+ TexSubImage3DImpl(
+ target, level, 0, 0, 0, width, height, depth, format, type,
+ unpadded_row_size, pixels, src_padded_row_size, GL_TRUE, &buffer,
+ padded_row_size);
+ CheckGLError();
+}
+
void GLES2Implementation::TexSubImage2D(
GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
GLsizei height, GLenum format, GLenum type, const void* pixels) {
@@ -1717,7 +1847,7 @@ void GLES2Implementation::TexSubImage2D(
uint32 unpadded_row_size;
uint32 padded_row_size;
if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, unpack_alignment_, &temp_size,
+ width, height, 1, format, type, unpack_alignment_, &temp_size,
&unpadded_row_size, &padded_row_size)) {
SetGLError(GL_INVALID_VALUE, "glTexSubImage2D", "size to large");
return;
@@ -1770,15 +1900,100 @@ void GLES2Implementation::TexSubImage2D(
CheckGLError();
}
+void GLES2Implementation::TexSubImage3D(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+ const void* pixels) {
+ GPU_CLIENT_SINGLE_THREAD_CHECK();
+ GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexSubImage3D("
+ << GLES2Util::GetStringTextureTarget(target) << ", "
+ << level << ", "
+ << xoffset << ", " << yoffset << ", " << zoffset << ", "
+ << width << ", " << height << ", " << depth << ", "
+ << GLES2Util::GetStringTextureFormat(format) << ", "
+ << GLES2Util::GetStringPixelType(type) << ", "
+ << static_cast<const void*>(pixels) << ")");
+
+ if (level < 0 || height < 0 || width < 0 || depth < 0) {
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "dimension < 0");
+ return;
+ }
+ if (height == 0 || width == 0 || depth == 0) {
+ return;
+ }
+
+ uint32 temp_size;
+ uint32 unpadded_row_size;
+ uint32 padded_row_size;
+ if (!GLES2Util::ComputeImageDataSizes(
+ width, height, depth, format, type, unpack_alignment_, &temp_size,
+ &unpadded_row_size, &padded_row_size)) {
+ SetGLError(GL_INVALID_VALUE, "glTexSubImage3D", "size to large");
+ return;
+ }
+
+ // If there's a pixel unpack buffer bound use it when issuing TexSubImage2D.
+ if (bound_pixel_unpack_transfer_buffer_id_) {
+ GLuint offset = ToGLuint(pixels);
+ BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
+ bound_pixel_unpack_transfer_buffer_id_,
+ "glTexSubImage3D", offset, temp_size);
+ if (buffer && buffer->shm_id() != -1) {
+ helper_->TexSubImage3D(
+ target, level, xoffset, yoffset, zoffset, width, height, depth,
+ format, type, buffer->shm_id(), buffer->shm_offset() + offset, false);
+ buffer->set_last_usage_token(helper_->InsertToken());
+ CheckGLError();
+ }
+ return;
+ }
+
+ // compute the advance bytes per row for the src pixels
+ uint32 src_padded_row_size;
+ if (unpack_row_length_ > 0) {
+ if (!GLES2Util::ComputeImagePaddedRowSize(
+ unpack_row_length_, format, type, unpack_alignment_,
+ &src_padded_row_size)) {
+ SetGLError(
+ GL_INVALID_VALUE, "glTexImage3D", "unpack row length too large");
+ return;
+ }
+ } else {
+ src_padded_row_size = padded_row_size;
+ }
+ uint32 src_height = unpack_image_height_ > 0 ? unpack_image_height_ : height;
+
+ // advance pixels pointer past the skip images/rows/pixels
+ pixels = reinterpret_cast<const int8*>(pixels) +
+ unpack_skip_images_ * src_padded_row_size * src_height +
+ unpack_skip_rows_ * src_padded_row_size;
+ if (unpack_skip_pixels_) {
+ uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type);
+ pixels = reinterpret_cast<const int8*>(pixels) +
+ unpack_skip_pixels_ * group_size;
+ }
+
+ ScopedTransferBufferPtr buffer(temp_size, helper_, transfer_buffer_);
+ TexSubImage3DImpl(
+ target, level, xoffset, yoffset, zoffset, width, height, depth,
+ format, type, unpadded_row_size, pixels, src_padded_row_size, GL_FALSE,
+ &buffer, padded_row_size);
+ CheckGLError();
+}
+
static GLint ComputeNumRowsThatFitInBuffer(
uint32 padded_row_size, uint32 unpadded_row_size,
- unsigned int size) {
+ unsigned int size, GLsizei remaining_rows) {
DCHECK_GE(unpadded_row_size, 0u);
if (padded_row_size == 0) {
return 1;
}
GLint num_rows = size / padded_row_size;
- return num_rows + (size - num_rows * padded_row_size) / unpadded_row_size;
+ if (num_rows + 1 == remaining_rows &&
+ size - num_rows * padded_row_size >= unpadded_row_size) {
+ num_rows++;
+ }
+ return num_rows;
}
void GLES2Implementation::TexSubImage2DImpl(
@@ -1805,7 +2020,7 @@ void GLES2Implementation::TexSubImage2DImpl(
}
GLint num_rows = ComputeNumRowsThatFitInBuffer(
- buffer_padded_row_size, unpadded_row_size, buffer->size());
+ buffer_padded_row_size, unpadded_row_size, buffer->size(), height);
num_rows = std::min(num_rows, height);
CopyRectToBuffer(
source, num_rows, unpadded_row_size, pixels_padded_row_size,
@@ -1821,6 +2036,119 @@ void GLES2Implementation::TexSubImage2DImpl(
}
}
+void GLES2Implementation::TexSubImage3DImpl(
+ GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei zoffset,
+ GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
+ uint32 unpadded_row_size, const void* pixels, uint32 pixels_padded_row_size,
+ GLboolean internal, ScopedTransferBufferPtr* buffer,
+ uint32 buffer_padded_row_size) {
+ DCHECK(buffer);
+ DCHECK_GE(level, 0);
+ DCHECK_GT(height, 0);
+ DCHECK_GT(width, 0);
+ DCHECK_GT(depth, 0);
+ const int8* source = reinterpret_cast<const int8*>(pixels);
+ GLsizei total_rows = height * depth;
+ GLint row_index = 0, depth_index = 0;
+ while (total_rows) {
+ // Each time, we either copy one or more images, or copy one or more rows
+ // within a single image, depending on the buffer size limit.
+ GLsizei max_rows;
+ unsigned int desired_size;
+ if (row_index > 0) {
+ // We are in the middle of an image. Send the remaining of the image.
+ max_rows = height - row_index;
+ if (total_rows <= height) {
+ // Last image, so last row is unpadded.
+ desired_size = buffer_padded_row_size * (max_rows - 1) +
+ unpadded_row_size;
+ } else {
+ desired_size = buffer_padded_row_size * max_rows;
+ }
+ } else {
+ // Send all the remaining data if possible.
+ max_rows = total_rows;
+ desired_size =
+ buffer_padded_row_size * (max_rows - 1) + unpadded_row_size;
+ }
+ if (!buffer->valid() || buffer->size() == 0) {
+ buffer->Reset(desired_size);
+ if (!buffer->valid()) {
+ return;
+ }
+ }
+ GLint num_rows = ComputeNumRowsThatFitInBuffer(
+ buffer_padded_row_size, unpadded_row_size, buffer->size(), total_rows);
+ num_rows = std::min(num_rows, max_rows);
+ GLint num_images = num_rows / height;
+ GLsizei my_height, my_depth;
+ if (num_images > 0) {
+ num_rows = num_images * height;
+ my_height = height;
+ my_depth = num_images;
+ } else {
+ my_height = num_rows;
+ my_depth = 1;
+ }
+
+ // TODO(zmo): Ignore flip_y flag for now.
+ if (num_images > 0) {
+ int8* buffer_pointer = reinterpret_cast<int8*>(buffer->address());
+ uint32 src_height =
+ unpack_image_height_ > 0 ? unpack_image_height_ : height;
+ uint32 image_size_dst = buffer_padded_row_size * height;
+ uint32 image_size_src = pixels_padded_row_size * src_height;
+ for (GLint ii = 0; ii < num_images; ++ii) {
+ uint32 my_unpadded_row_size;
+ if (total_rows == num_rows && ii + 1 == num_images)
+ my_unpadded_row_size = unpadded_row_size;
+ else
+ my_unpadded_row_size = pixels_padded_row_size;
+ CopyRectToBuffer(
+ source + ii * image_size_src, my_height, my_unpadded_row_size,
+ pixels_padded_row_size, false, buffer_pointer + ii * image_size_dst,
+ buffer_padded_row_size);
+ }
+ } else {
+ uint32 my_unpadded_row_size;
+ if (total_rows == num_rows)
+ my_unpadded_row_size = unpadded_row_size;
+ else
+ my_unpadded_row_size = pixels_padded_row_size;
+ CopyRectToBuffer(
+ source, my_height, my_unpadded_row_size, pixels_padded_row_size,
+ false, buffer->address(), buffer_padded_row_size);
+ }
+ helper_->TexSubImage3D(
+ target, level, xoffset, yoffset + row_index, zoffset + depth_index,
+ width, my_height, my_depth,
+ format, type, buffer->shm_id(), buffer->offset(), internal);
+ buffer->Release();
+
+ total_rows -= num_rows;
+ if (total_rows > 0) {
+ GLint num_image_paddings;
+ if (num_images > 0) {
+ DCHECK_EQ(row_index, 0);
+ depth_index += num_images;
+ num_image_paddings = num_images;
+ } else {
+ row_index = (row_index + my_height) % height;
+ num_image_paddings = 0;
+ if (my_height > 0 && row_index == 0) {
+ depth_index++;
+ num_image_paddings++;
+ }
+ }
+ source += num_rows * pixels_padded_row_size;
+ if (unpack_image_height_ > height && num_image_paddings > 0) {
+ source += num_image_paddings * (unpack_image_height_ - height) *
+ pixels_padded_row_size;
+ }
+ }
+ }
+}
+
bool GLES2Implementation::GetActiveAttribHelper(
GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size,
GLenum* type, char* name) {
@@ -2187,8 +2515,8 @@ void GLES2Implementation::ReadPixels(
uint32 unpadded_row_size;
uint32 padded_row_size;
if (!GLES2Util::ComputeImageDataSizes(
- width, 2, format, type, pack_alignment_, &temp_size, &unpadded_row_size,
- &padded_row_size)) {
+ width, 2, 1, format, type, pack_alignment_, &temp_size,
+ &unpadded_row_size, &padded_row_size)) {
SetGLError(GL_INVALID_VALUE, "glReadPixels", "size too large.");
return;
}
@@ -2215,13 +2543,13 @@ void GLES2Implementation::ReadPixels(
// Transfer by rows.
// The max rows we can transfer.
while (height) {
- GLsizei desired_size = padded_row_size * height - 1 + unpadded_row_size;
+ GLsizei desired_size = padded_row_size * (height - 1) + unpadded_row_size;
ScopedTransferBufferPtr buffer(desired_size, helper_, transfer_buffer_);
if (!buffer.valid()) {
return;
}
GLint num_rows = ComputeNumRowsThatFitInBuffer(
- padded_row_size, unpadded_row_size, buffer.size());
+ padded_row_size, unpadded_row_size, buffer.size(), height);
num_rows = std::min(num_rows, height);
// NOTE: We must look up the address of the result area AFTER allocation
// of the transfer buffer since the transfer buffer may be reallocated.
@@ -2986,7 +3314,7 @@ void* GLES2Implementation::MapTexSubImage2DCHROMIUM(
}
uint32 size;
if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, unpack_alignment_, &size, NULL, NULL)) {
+ width, height, 1, format, type, unpack_alignment_, &size, NULL, NULL)) {
SetGLError(
GL_INVALID_VALUE, "glMapTexSubImage2DCHROMIUM", "image size too large");
return NULL;
@@ -3530,34 +3858,24 @@ void GLES2Implementation::TraceBeginCHROMIUM(
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceBeginCHROMIUM("
<< category_name << ", " << trace_name << ")");
- if (current_trace_category_.get() || current_trace_name_.get()) {
- SetGLError(GL_INVALID_OPERATION, "glTraceBeginCHROMIUM",
- "trace already running");
- return;
- }
- TRACE_EVENT_COPY_ASYNC_BEGIN0(category_name, trace_name, this);
SetBucketAsCString(kResultBucketId, category_name);
- SetBucketAsCString(kResultBucketId + 1, category_name);
+ SetBucketAsCString(kResultBucketId + 1, trace_name);
helper_->TraceBeginCHROMIUM(kResultBucketId, kResultBucketId + 1);
helper_->SetBucketSize(kResultBucketId, 0);
helper_->SetBucketSize(kResultBucketId + 1, 0);
- current_trace_category_.reset(new std::string(category_name));
- current_trace_name_.reset(new std::string(trace_name));
+ current_trace_stack_++;
}
void GLES2Implementation::TraceEndCHROMIUM() {
GPU_CLIENT_SINGLE_THREAD_CHECK();
GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTraceEndCHROMIUM(" << ")");
- if (!current_trace_category_.get() || !current_trace_name_.get()) {
+ if (current_trace_stack_ == 0) {
SetGLError(GL_INVALID_OPERATION, "glTraceEndCHROMIUM",
"missing begin trace");
return;
}
helper_->TraceEndCHROMIUM();
- TRACE_EVENT_COPY_ASYNC_END0(current_trace_category_->c_str(),
- current_trace_name_->c_str(), this);
- current_trace_category_.reset();
- current_trace_name_.reset();
+ current_trace_stack_--;
}
void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) {
@@ -3727,7 +4045,7 @@ void GLES2Implementation::AsyncTexImage2DCHROMIUM(
uint32 unpadded_row_size;
uint32 padded_row_size;
if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, unpack_alignment_, &size,
+ width, height, 1, format, type, unpack_alignment_, &size,
&unpadded_row_size, &padded_row_size)) {
SetGLError(GL_INVALID_VALUE, "glTexImage2D", "image size too large");
return;
@@ -3787,7 +4105,7 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
uint32 unpadded_row_size;
uint32 padded_row_size;
if (!GLES2Util::ComputeImageDataSizes(
- width, height, format, type, unpack_alignment_, &size,
+ width, height, 1, format, type, unpack_alignment_, &size,
&unpadded_row_size, &padded_row_size)) {
SetGLError(
GL_INVALID_VALUE, "glAsyncTexSubImage2DCHROMIUM", "size to large");
« no previous file with comments | « gpu/command_buffer/client/gles2_implementation.h ('k') | gpu/command_buffer/client/gles2_implementation_autogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698