diff options
author | zmo <zmo@chromium.org> | 2015-12-02 09:35:56 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-02 17:36:55 +0000 |
commit | cdfe65d79d2f9c02553392e0f38bb5a2279d31b8 (patch) | |
tree | 23de32884e7911ee1deefba640e9fd11c2247296 | |
parent | c34a2b26aa39a4c6bf9165f59d262c2fe2c9f321 (diff) | |
download | chromium_src-cdfe65d79d2f9c02553392e0f38bb5a2279d31b8.zip chromium_src-cdfe65d79d2f9c02553392e0f38bb5a2279d31b8.tar.gz chromium_src-cdfe65d79d2f9c02553392e0f38bb5a2279d31b8.tar.bz2 |
Reland of Upgrade PixelStorei to ES3/WebGL2. (patchset #1 id:1 of https://codereview.chromium.org/1494553002/ )
Reason for revert:
revert the revert (i.e., reland)
the WebGL 2 CTS failure is due to the bug in the test. I am going to suppress it for now and fix it in khronos and roll in.
Original issue's description:
> Revert of Upgrade PixelStorei to ES3/WebGL2. (patchset #7 id:160001 of https://codereview.chromium.org/1474513003/ )
>
> Reason for revert:
> Failing the WebGL 2 CTS:
>
> WebglConformance.conformance2_state_gl_get_calls:
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "context.getParameter(context.UNPACK_SKIP_IMAGES) should be false (of type boolean). Was 0 (of type number).", source: (11)
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "FAIL context.getParameter(context.UNPACK_SKIP_IMAGES) should be false (of type boolean). Was 0 (of type number).", source: (11)
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "context.getParameter(context.UNPACK_SKIP_PIXELS) should be false (of type boolean). Was 0 (of type number).", source: (11)
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "FAIL context.getParameter(context.UNPACK_SKIP_PIXELS) should be false (of type boolean). Was 0 (of type number).", source: (11)
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "context.getParameter(context.UNPACK_SKIP_ROWS) should be false (of type boolean). Was 0 (of type number).", source: (11)
> [3560:1299:1202/051124:INFO:CONSOLE(11)] "FAIL context.getParameter(context.UNPACK_SKIP_ROWS) should be false (of type boolean). Was 0 (of type number).", source: (11)
>
> http://build.chromium.org/p/chromium.gpu.fyi/builders/Mac%2010.10%20Release%20%28Intel%29/builds/7016
> http://build.chromium.org/p/chromium.gpu.fyi/builders/Win8%20Debug%20%28NVIDIA%29/builds/10350
> http://build.chromium.org/p/chromium.gpu.fyi/builders/Linux%20Release%20%28NVIDIA%29/builds/33475
>
> Original issue's description:
> > Upgrade PixelStorei to ES3/WebGL2.
> >
> > BUG=295792,429053
> > TEST=gpu_unittests, webgl2_conformance
> > R=kbr@chromium.org,bajones@chromium.org,piman@chromium.org
> >
> > Committed: https://crrev.com/c6c114178c562feeddfc4d41a33b9999698a4144
> > Cr-Commit-Position: refs/heads/master@{#362585}
>
> TBR=bajones@chromium.org,kbr@chromium.org,piman@chromium.org,zmo@chromium.org
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=295792,429053
>
> Committed: https://crrev.com/72ea7571631a1922f7c15e7ef5447b8098c1ab24
> Cr-Commit-Position: refs/heads/master@{#362696}
TBR=bajones@chromium.org,kbr@chromium.org,piman@chromium.org,jmadill@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=295792,429053
Review URL: https://codereview.chromium.org/1492013002
Cr-Commit-Position: refs/heads/master@{#362741}
16 files changed, 709 insertions, 96 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 67579a0..6b672b2 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -418,6 +418,62 @@ _STATES = { 'type': 'GLint', 'enum': 'GL_UNPACK_ALIGNMENT', 'default': '4' + }, + { + 'name': 'pack_row_length', + 'type': 'GLint', + 'enum': 'GL_PACK_ROW_LENGTH', + 'default': '0', + 'es3': True + }, + { + 'name': 'pack_skip_pixels', + 'type': 'GLint', + 'enum': 'GL_PACK_SKIP_PIXELS', + 'default': '0', + 'es3': True + }, + { + 'name': 'pack_skip_rows', + 'type': 'GLint', + 'enum': 'GL_PACK_SKIP_ROWS', + 'default': '0', + 'es3': True + }, + { + 'name': 'unpack_row_length', + 'type': 'GLint', + 'enum': 'GL_UNPACK_ROW_LENGTH', + 'default': '0', + 'es3': True + }, + { + 'name': 'unpack_image_height', + 'type': 'GLint', + 'enum': 'GL_UNPACK_IMAGE_HEIGHT', + 'default': '0', + 'es3': True + }, + { + 'name': 'unpack_skip_pixels', + 'type': 'GLint', + 'enum': 'GL_UNPACK_SKIP_PIXELS', + 'default': '0', + 'es3': True + }, + { + 'name': 'unpack_skip_rows', + 'type': 'GLint', + 'enum': 'GL_UNPACK_SKIP_ROWS', + 'default': '0', + 'es3': True + }, + { + 'name': 'unpack_skip_images', + 'type': 'GLint', + 'enum': 'GL_UNPACK_SKIP_IMAGES', + 'default': '0', + 'es3': True } ], }, @@ -10186,6 +10242,9 @@ void ContextState::InitState(const ContextState *prev_state) const { for item in state['states']: item_name = CachedStateName(item) + if 'es3' in item: + assert item['es3'] + f.write(" if (feature_info_->IsES3Capable()) {\n"); if 'extension_flag' in item: f.write(" if (feature_info_->feature_flags().%s) {\n " % item['extension_flag']) @@ -10211,7 +10270,7 @@ void ContextState::InitState(const ContextState *prev_state) const { (item['enum_set'] if 'enum_set' in item else item['enum']), item['name'])) - if 'gl_version_flag' in item: + if 'gl_version_flag' in item or 'es3' in item: f.write(" }\n") if test_prev: if 'extension_flag' in item: @@ -10420,7 +10479,7 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { f.write(""" } } -void GLES2DecoderTestBase::SetupInitStateExpectations() { +void GLES2DecoderTestBase::SetupInitStateExpectations(bool es3_capable) { """) # We need to sort the keys so the expectations match for state_name in sorted(_STATES.keys()): @@ -10445,6 +10504,10 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() { f.write(" if (group_->feature_info()->feature_flags().%s) {\n" % item['extension_flag']) f.write(" ") + if 'es3' in item: + assert item['es3'] + f.write(" if (es3_capable) {\n") + f.write(" ") expect_value = item['default'] if isinstance(expect_value, list): # TODO: Currently we do not check array values. @@ -10458,7 +10521,7 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() { expect_value)) f.write(" .Times(1)\n") f.write(" .RetiresOnSaturation();\n") - if 'extension_flag' in item: + if 'extension_flag' in item or 'es3' in item: f.write(" }\n") else: if 'extension_flag' in state: @@ -10793,7 +10856,9 @@ const size_t GLES2Util::enum_to_string_table_len_ = enum) valid_list = _NAMED_TYPE_INFO[enum]['valid'] if 'valid_es3' in _NAMED_TYPE_INFO[enum]: - valid_list = valid_list + _NAMED_TYPE_INFO[enum]['valid_es3'] + for es3_enum in _NAMED_TYPE_INFO[enum]['valid_es3']: + if not es3_enum in valid_list: + valid_list.append(es3_enum) assert len(valid_list) == len(set(valid_list)) if len(valid_list) > 0: f.write(" static const EnumToString string_table[] = {\n") @@ -11034,6 +11099,7 @@ def main(argv): # Add in states and capabilites to GLState gl_state_valid = _NAMED_TYPE_INFO['GLState']['valid'] + gl_state_valid_es3 = _NAMED_TYPE_INFO['GLState']['valid_es3'] for state_name in sorted(_STATES.keys()): state = _STATES[state_name] if 'extension_flag' in state: @@ -11045,8 +11111,13 @@ def main(argv): for item in state['states']: if 'extension_flag' in item: continue - if not item['enum'] in gl_state_valid: - gl_state_valid.append(item['enum']) + if 'es3' in item: + assert item['es3'] + if not item['enum'] in gl_state_valid_es3: + gl_state_valid_es3.append(item['enum']) + else: + if not item['enum'] in gl_state_valid: + gl_state_valid.append(item['enum']) for capability in _CAPABILITY_FLAGS: if 'extension_flag' in capability: continue diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index c1538fe..208a08b 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -85,6 +85,9 @@ GLES2Implementation::GLES2Implementation( angle_pack_reverse_row_order_status_(kUnknownExtensionStatus), chromium_framebuffer_multisample_(kUnknownExtensionStatus), pack_alignment_(4), + pack_row_length_(0), + pack_skip_pixels_(0), + pack_skip_rows_(0), unpack_alignment_(4), unpack_row_length_(0), unpack_image_height_(0), @@ -1717,32 +1720,41 @@ void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { << param << ")"); switch (pname) { case GL_PACK_ALIGNMENT: - pack_alignment_ = param; - break; + pack_alignment_ = param; + break; + case GL_PACK_ROW_LENGTH: + pack_row_length_ = param; + break; + case GL_PACK_SKIP_PIXELS: + pack_skip_pixels_ = param; + break; + case GL_PACK_SKIP_ROWS: + pack_skip_rows_ = param; + break; case GL_UNPACK_ALIGNMENT: - unpack_alignment_ = param; - break; + unpack_alignment_ = param; + break; case GL_UNPACK_ROW_LENGTH_EXT: - unpack_row_length_ = param; - return; + unpack_row_length_ = param; + return; case GL_UNPACK_IMAGE_HEIGHT: - unpack_image_height_ = param; - return; + unpack_image_height_ = param; + return; case GL_UNPACK_SKIP_ROWS_EXT: - unpack_skip_rows_ = param; - return; + unpack_skip_rows_ = param; + return; case GL_UNPACK_SKIP_PIXELS_EXT: - unpack_skip_pixels_ = param; - return; + unpack_skip_pixels_ = param; + return; case GL_UNPACK_SKIP_IMAGES: - unpack_skip_images_ = param; - return; + unpack_skip_images_ = param; + return; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - pack_reverse_row_order_ = - IsAnglePackReverseRowOrderAvailable() ? (param != 0) : false; - break; + pack_reverse_row_order_ = + IsAnglePackReverseRowOrderAvailable() ? (param != 0) : false; + break; default: - break; + break; } helper_->PixelStorei(pname, param); CheckGLError(); @@ -3472,6 +3484,14 @@ void GLES2Implementation::ReadPixels( return; } + if (bound_pixel_pack_buffer_) { + // TODO(zmo): Need to handle the case of reading into a PIXEL_PACK_BUFFER + // in ES3. For now, generate a GL error. + SetGLError(GL_INVALID_OPERATION, "glReadPixels", + "ReadPixels to a pixel pack buffer isn't implemented"); + return; + } + if (bound_pixel_pack_transfer_buffer_id_) { GLuint offset = ToGLuint(pixels); BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( @@ -3491,6 +3511,27 @@ void GLES2Implementation::ReadPixels( return; } + // compute the advance bytes per row for the dst pixels + uint32 dst_padded_row_size; + if (pack_row_length_ > 0) { + if (!GLES2Util::ComputeImagePaddedRowSize( + pack_row_length_, format, type, pack_alignment_, + &dst_padded_row_size)) { + SetGLError( + GL_INVALID_VALUE, "glReadPixels", "pack row length too large"); + return; + } + } else { + dst_padded_row_size = padded_row_size; + } + + // Advance pixels pointer past the skip rows and skip pixels + dest += pack_skip_rows_ * dst_padded_row_size; + if (pack_skip_pixels_) { + uint32 group_size = GLES2Util::ComputeImageGroupSize(format, type); + dest += pack_skip_pixels_ * group_size; + } + // Transfer by rows. // The max rows we can transfer. while (height) { @@ -3521,7 +3562,7 @@ void GLES2Implementation::ReadPixels( // chunk. int8* rows_dst; if (pack_reverse_row_order_) { - rows_dst = dest + (height - num_rows) * padded_row_size; + rows_dst = dest + (height - num_rows) * dst_padded_row_size; } else { rows_dst = dest; } @@ -3529,7 +3570,7 @@ void GLES2Implementation::ReadPixels( const int8* src = static_cast<const int8*>(buffer.address()); for (GLint yy = 0; yy < num_rows; ++yy) { memcpy(rows_dst, src, unpadded_row_size); - rows_dst += padded_row_size; + rows_dst += dst_padded_row_size; src += padded_row_size; } if (!pack_reverse_row_order_) { diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 97398be..1c2eba9 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -692,6 +692,15 @@ class GLES2_IMPL_EXPORT GLES2Implementation // pack alignment as last set by glPixelStorei GLint pack_alignment_; + // pack row length as last set by glPixelStorei + GLint pack_row_length_; + + // pack skip pixels as last set by glPixelStorei + GLint pack_skip_pixels_; + + // pack skip rows as last set by glPixelStorei + GLint pack_skip_rows_; + // unpack alignment as last set by glPixelStorei GLint unpack_alignment_; diff --git a/gpu/command_buffer/service/context_state.cc b/gpu/command_buffer/service/context_state.cc index e8c0072..44ad319 100644 --- a/gpu/command_buffer/service/context_state.cc +++ b/gpu/command_buffer/service/context_state.cc @@ -270,8 +270,10 @@ void ContextState::RestoreBufferBindings() const { GetBufferId(bound_copy_write_buffer.get())); glBindBuffer(GL_PIXEL_PACK_BUFFER, GetBufferId(bound_pixel_pack_buffer.get())); + UpdatePackParameters(); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, GetBufferId(bound_pixel_unpack_buffer.get())); + UpdateUnpackParameters(); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GetBufferId(bound_transform_feedback_buffer.get())); glBindBuffer(GL_UNIFORM_BUFFER, GetBufferId(bound_uniform_buffer.get())); @@ -442,6 +444,38 @@ void ContextState::EnableDisable(GLenum pname, bool enable) const { } } +void ContextState::UpdatePackParameters() const { + if (!feature_info_->IsES3Capable()) + return; + if (bound_pixel_pack_buffer.get()) { + glPixelStorei(GL_PACK_ROW_LENGTH, pack_row_length); + glPixelStorei(GL_PACK_SKIP_PIXELS, pack_skip_pixels); + glPixelStorei(GL_PACK_SKIP_ROWS, pack_skip_rows); + } else { + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_PACK_SKIP_PIXELS, 0); + glPixelStorei(GL_PACK_SKIP_ROWS, 0); + } +} + +void ContextState::UpdateUnpackParameters() const { + if (!feature_info_->IsES3Capable()) + return; + if (bound_pixel_unpack_buffer.get()) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpack_skip_pixels); + glPixelStorei(GL_UNPACK_SKIP_ROWS, unpack_skip_rows); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, unpack_skip_images); + } else { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_IMAGES, 0); + } +} + void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) { switch (target) { case GL_ARRAY_BUFFER: @@ -458,9 +492,11 @@ void ContextState::SetBoundBuffer(GLenum target, Buffer* buffer) { break; case GL_PIXEL_PACK_BUFFER: bound_pixel_pack_buffer = buffer; + UpdatePackParameters(); break; case GL_PIXEL_UNPACK_BUFFER: bound_pixel_unpack_buffer = buffer; + UpdateUnpackParameters(); break; case GL_TRANSFORM_FEEDBACK_BUFFER: bound_transform_feedback_buffer = buffer; @@ -488,9 +524,11 @@ void ContextState::RemoveBoundBuffer(Buffer* buffer) { } if (bound_pixel_pack_buffer.get() == buffer) { bound_pixel_pack_buffer = nullptr; + UpdatePackParameters(); } if (bound_pixel_unpack_buffer.get() == buffer) { bound_pixel_unpack_buffer = nullptr; + UpdateUnpackParameters(); } if (bound_transform_feedback_buffer.get() == buffer) { bound_transform_feedback_buffer = nullptr; diff --git a/gpu/command_buffer/service/context_state.h b/gpu/command_buffer/service/context_state.h index f9d4ff7..71bb8a5 100644 --- a/gpu/command_buffer/service/context_state.h +++ b/gpu/command_buffer/service/context_state.h @@ -266,6 +266,13 @@ struct GPU_EXPORT ContextState { private: void EnableDisable(GLenum pname, bool enable) const; + // If a buffer object is bound to PIXEL_PACK_BUFFER, set all pack parameters + // user values; otherwise, set them to 0. + void UpdatePackParameters() const; + // If a buffer object is bound to PIXEL_UNPACK_BUFFER, set all unpack + // parameters user values; otherwise, set them to 0. + void UpdateUnpackParameters() const; + FeatureInfo* feature_info_; scoped_ptr<ErrorState> error_state_; }; diff --git a/gpu/command_buffer/service/context_state_autogen.h b/gpu/command_buffer/service/context_state_autogen.h index 7278a24..d354bd0 100644 --- a/gpu/command_buffer/service/context_state_autogen.h +++ b/gpu/command_buffer/service/context_state_autogen.h @@ -83,6 +83,14 @@ GLint stencil_path_ref; GLuint stencil_path_mask; GLint pack_alignment; GLint unpack_alignment; +GLint pack_row_length; +GLint pack_skip_pixels; +GLint pack_skip_rows; +GLint unpack_row_length; +GLint unpack_image_height; +GLint unpack_skip_pixels; +GLint unpack_skip_rows; +GLint unpack_skip_images; GLfloat polygon_offset_factor; GLfloat polygon_offset_units; GLclampf sample_coverage_value; diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h index ce9f70f..263841b 100644 --- a/gpu/command_buffer/service/context_state_impl_autogen.h +++ b/gpu/command_buffer/service/context_state_impl_autogen.h @@ -112,6 +112,14 @@ void ContextState::Initialize() { stencil_path_mask = 0xFFFFFFFFU; pack_alignment = 4; unpack_alignment = 4; + pack_row_length = 0; + pack_skip_pixels = 0; + pack_skip_rows = 0; + unpack_row_length = 0; + unpack_image_height = 0; + unpack_skip_pixels = 0; + unpack_skip_rows = 0; + unpack_skip_images = 0; polygon_offset_factor = 0.0f; polygon_offset_units = 0.0f; sample_coverage_value = 1.0f; @@ -314,6 +322,46 @@ void ContextState::InitState(const ContextState* prev_state) const { if (prev_state->unpack_alignment != unpack_alignment) { glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); } + if (feature_info_->IsES3Capable()) { + if (prev_state->pack_row_length != pack_row_length) { + glPixelStorei(GL_PACK_ROW_LENGTH, pack_row_length); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->pack_skip_pixels != pack_skip_pixels) { + glPixelStorei(GL_PACK_SKIP_PIXELS, pack_skip_pixels); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->pack_skip_rows != pack_skip_rows) { + glPixelStorei(GL_PACK_SKIP_ROWS, pack_skip_rows); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->unpack_row_length != unpack_row_length) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->unpack_image_height != unpack_image_height) { + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->unpack_skip_pixels != unpack_skip_pixels) { + glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpack_skip_pixels); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->unpack_skip_rows != unpack_skip_rows) { + glPixelStorei(GL_UNPACK_SKIP_ROWS, unpack_skip_rows); + } + } + if (feature_info_->IsES3Capable()) { + if (prev_state->unpack_skip_images != unpack_skip_images) { + glPixelStorei(GL_UNPACK_SKIP_IMAGES, unpack_skip_images); + } + } if ((polygon_offset_factor != prev_state->polygon_offset_factor) || (polygon_offset_units != prev_state->polygon_offset_units)) glPolygonOffset(polygon_offset_factor, polygon_offset_units); @@ -392,6 +440,30 @@ void ContextState::InitState(const ContextState* prev_state) const { stencil_path_mask); glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment); glPixelStorei(GL_UNPACK_ALIGNMENT, unpack_alignment); + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_PACK_ROW_LENGTH, pack_row_length); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_PACK_SKIP_PIXELS, pack_skip_pixels); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_PACK_SKIP_ROWS, pack_skip_rows); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, unpack_row_length); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, unpack_image_height); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpack_skip_pixels); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_UNPACK_SKIP_ROWS, unpack_skip_rows); + } + if (feature_info_->IsES3Capable()) { + glPixelStorei(GL_UNPACK_SKIP_IMAGES, unpack_skip_images); + } glPolygonOffset(polygon_offset_factor, polygon_offset_units); glSampleCoverage(sample_coverage_value, sample_coverage_invert); glScissor(scissor_x, scissor_y, scissor_width, scissor_height); @@ -616,6 +688,54 @@ bool ContextState::GetStateAsGLint(GLenum pname, params[0] = static_cast<GLint>(unpack_alignment); } return true; + case GL_PACK_ROW_LENGTH: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(pack_row_length); + } + return true; + case GL_PACK_SKIP_PIXELS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(pack_skip_pixels); + } + return true; + case GL_PACK_SKIP_ROWS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(pack_skip_rows); + } + return true; + case GL_UNPACK_ROW_LENGTH: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(unpack_row_length); + } + return true; + case GL_UNPACK_IMAGE_HEIGHT: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(unpack_image_height); + } + return true; + case GL_UNPACK_SKIP_PIXELS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(unpack_skip_pixels); + } + return true; + case GL_UNPACK_SKIP_ROWS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(unpack_skip_rows); + } + return true; + case GL_UNPACK_SKIP_IMAGES: + *num_written = 1; + if (params) { + params[0] = static_cast<GLint>(unpack_skip_images); + } + return true; case GL_POLYGON_OFFSET_FACTOR: *num_written = 1; if (params) { @@ -996,6 +1116,54 @@ bool ContextState::GetStateAsGLfloat(GLenum pname, params[0] = static_cast<GLfloat>(unpack_alignment); } return true; + case GL_PACK_ROW_LENGTH: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(pack_row_length); + } + return true; + case GL_PACK_SKIP_PIXELS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(pack_skip_pixels); + } + return true; + case GL_PACK_SKIP_ROWS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(pack_skip_rows); + } + return true; + case GL_UNPACK_ROW_LENGTH: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(unpack_row_length); + } + return true; + case GL_UNPACK_IMAGE_HEIGHT: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(unpack_image_height); + } + return true; + case GL_UNPACK_SKIP_PIXELS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(unpack_skip_pixels); + } + return true; + case GL_UNPACK_SKIP_ROWS: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(unpack_skip_rows); + } + return true; + case GL_UNPACK_SKIP_IMAGES: + *num_written = 1; + if (params) { + params[0] = static_cast<GLfloat>(unpack_skip_images); + } + return true; case GL_POLYGON_OFFSET_FACTOR: *num_written = 1; if (params) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 0cc2771..b2f7f96 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -183,6 +183,11 @@ GLuint GetClientId(const MANAGER_TYPE* manager, const OBJECT_TYPE* object) { return client_id; } +template <typename OBJECT_TYPE> +GLuint GetServiceId(const OBJECT_TYPE* object) { + return object ? object->service_id() : 0; +} + struct Vec4f { explicit Vec4f(const Vec4& data) { data.GetValues(v); @@ -8809,10 +8814,9 @@ void GLES2DecoderImpl::FinishReadPixels( return; } memcpy(pixels, data, pixels_size); - // GL_PIXEL_PACK_BUFFER_ARB is currently unused, so we don't - // have to restore the state. glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB); - glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0); + glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, + GetServiceId(state_.bound_pixel_pack_buffer.get())); glDeleteBuffersARB(1, &buffer); } @@ -8892,6 +8896,13 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size, } typedef cmds::ReadPixels::Result Result; uint32 pixels_size; + if (state_.bound_pixel_pack_buffer.get()) { + // TODO(zmo): Need to handle the case of reading into a PIXEL_PACK_BUFFER + // in ES3, including more pack parameters. For now, generate a GL error. + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadPixels", + "ReadPixels to a pixel pack buffer isn't implemented"); + return error::kNoError; + } if (!GLES2Util::ComputeImageDataSizes( width, height, 1, format, type, state_.pack_alignment, &pixels_size, NULL, NULL)) { @@ -9079,7 +9090,12 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size, dst += padded_row_size; } } else { - if (async && features().use_async_readpixels) { + if (async && features().use_async_readpixels && + !state_.bound_pixel_pack_buffer.get()) { + // To simply the state tracking, we don't go down the async path if + // a PIXEL_PACK_BUFFER is bound (in which case the client can + // implement something similar on their own - all necessary functions + // should be exposed). GLuint buffer = 0; glGenBuffersARB(1, &buffer); glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, buffer); @@ -9089,6 +9105,9 @@ error::Error GLES2DecoderImpl::HandleReadPixels(uint32 immediate_data_size, glBufferData(GL_PIXEL_PACK_BUFFER_ARB, pixels_size, NULL, usage_hint); GLenum error = glGetError(); if (error == GL_NO_ERROR) { + // No need to worry about ES3 pxiel pack parameters, because no + // PIXEL_PACK_BUFFER is bound, and all these settings haven't been + // sent to GL. glReadPixels(x, y, width, height, format, type, 0); pending_readpixel_fences_.push(linked_ptr<FenceCallback>( new FenceCallback())); @@ -9120,7 +9139,7 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size, const gles2::cmds::PixelStorei& c = *static_cast<const gles2::cmds::PixelStorei*>(cmd_data); GLenum pname = c.pname; - GLenum param = c.param; + GLint param = c.param; if (!validators_->pixel_store.IsValid(pname)) { LOCAL_SET_GL_ERROR_INVALID_ENUM("glPixelStorei", pname, "pname"); return error::kNoError; @@ -9128,30 +9147,88 @@ error::Error GLES2DecoderImpl::HandlePixelStorei(uint32 immediate_data_size, switch (pname) { case GL_PACK_ALIGNMENT: case GL_UNPACK_ALIGNMENT: - if (!validators_->pixel_store_alignment.IsValid(param)) { - LOCAL_SET_GL_ERROR( - GL_INVALID_VALUE, "glPixelStorei", "param GL_INVALID_VALUE"); - return error::kNoError; - } - break; + if (!validators_->pixel_store_alignment.IsValid(param)) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glPixelStorei", "invalid param"); + return error::kNoError; + } + break; + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_PIXELS: + case GL_PACK_SKIP_ROWS: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_PIXELS: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_IMAGES: + if (param < 0) { + LOCAL_SET_GL_ERROR( + GL_INVALID_VALUE, "glPixelStorei", "invalid param"); + return error::kNoError; + } default: - break; + break; + } + // For pack and unpack parameters (except for alignment), we don't apply them + // if no buffer is bound at PIXEL_PACK or PIXEL_UNPACK. We will handle pack + // and unpack according to the user specified parameters on the client side. + switch (pname) { + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_PIXELS: + case GL_PACK_SKIP_ROWS: + if (state_.bound_pixel_pack_buffer.get()) + glPixelStorei(pname, param); + break; + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_PIXELS: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_IMAGES: + if (state_.bound_pixel_unpack_buffer.get()) + glPixelStorei(pname, param); + break; + default: + glPixelStorei(pname, param); + break; } - glPixelStorei(pname, param); switch (pname) { case GL_PACK_ALIGNMENT: - state_.pack_alignment = param; - break; + state_.pack_alignment = param; + break; case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - state_.pack_reverse_row_order = (param != 0); - break; + state_.pack_reverse_row_order = (param != 0); + break; + case GL_PACK_ROW_LENGTH: + state_.pack_row_length = param; + break; + case GL_PACK_SKIP_PIXELS: + state_.pack_skip_pixels = param; + break; + case GL_PACK_SKIP_ROWS: + state_.pack_skip_rows = param; + break; case GL_UNPACK_ALIGNMENT: - state_.unpack_alignment = param; - break; + state_.unpack_alignment = param; + break; + case GL_UNPACK_ROW_LENGTH: + state_.unpack_row_length = param; + break; + case GL_UNPACK_IMAGE_HEIGHT: + state_.unpack_image_height = param; + break; + case GL_UNPACK_SKIP_PIXELS: + state_.unpack_skip_pixels = param; + break; + case GL_UNPACK_SKIP_ROWS: + state_.unpack_skip_rows = param; + break; + case GL_UNPACK_SKIP_IMAGES: + state_.unpack_skip_images = param; + break; default: - // Validation should have prevented us from getting here. - NOTREACHED(); - break; + // Validation should have prevented us from getting here. + NOTREACHED(); + break; } return error::kNoError; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h index d934bce..116b9c6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h @@ -34,7 +34,7 @@ void GLES2DecoderTestBase::SetupInitCapabilitiesExpectations(bool es3_capable) { } } -void GLES2DecoderTestBase::SetupInitStateExpectations() { +void GLES2DecoderTestBase::SetupInitStateExpectations(bool es3_capable) { EXPECT_CALL(*gl_, BlendColor(0.0f, 0.0f, 0.0f, 0.0f)) .Times(1) .RetiresOnSaturation(); @@ -88,6 +88,46 @@ void GLES2DecoderTestBase::SetupInitStateExpectations() { EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ALIGNMENT, 4)) .Times(1) .RetiresOnSaturation(); + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_PACK_ROW_LENGTH, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_PACK_SKIP_PIXELS, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_PACK_SKIP_ROWS, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ROW_LENGTH, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_SKIP_PIXELS, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_SKIP_ROWS, 0)) + .Times(1) + .RetiresOnSaturation(); + } + if (es3_capable) { + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_SKIP_IMAGES, 0)) + .Times(1) + .RetiresOnSaturation(); + } EXPECT_CALL(*gl_, PolygonOffset(0.0f, 0.0f)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, SampleCoverage(1.0f, false)).Times(1).RetiresOnSaturation(); EXPECT_CALL(*gl_, diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index d443418..c704c28 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -358,7 +358,7 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( .RetiresOnSaturation(); SetupInitCapabilitiesExpectations(group_->feature_info()->IsES3Capable()); - SetupInitStateExpectations(); + SetupInitStateExpectations(group_->feature_info()->IsES3Capable()); EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0)) .Times(1) diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 09c4c8a..d19937d 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -240,7 +240,7 @@ class GLES2DecoderTestBase : public ::testing::TestWithParam<bool> { GLuint fragment_shader_client_id, GLuint fragment_shader_service_id); void SetupInitCapabilitiesExpectations(bool es3_capable); - void SetupInitStateExpectations(); + void SetupInitStateExpectations(bool es3_capable); void ExpectEnableDisable(GLenum cap, bool enable); // Setups up a shader for testing glUniform. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc index b1ddbba..1b3feaa 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_context_state.cc @@ -48,6 +48,34 @@ using ::testing::StrictMock; namespace gpu { namespace gles2 { +namespace { + +void SetupUpdateES3UnpackParametersExpectations( + ::gfx::MockGLInterface* gl, + GLint row_length, + GLint image_height, + GLint skip_pixels, + GLint skip_rows, + GLint skip_images) { + EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_ROW_LENGTH, row_length)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_IMAGE_HEIGHT, image_height)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_SKIP_ROWS, skip_rows)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_SKIP_PIXELS, skip_pixels)) + .Times(1) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, PixelStorei(GL_UNPACK_SKIP_IMAGES, skip_images)) + .Times(1) + .RetiresOnSaturation(); +} + +} // namespace anonymous + using namespace cmds; class GLES2DecoderRestoreStateTest : public GLES2DecoderManualInitTest { @@ -396,6 +424,42 @@ TEST_P(GLES2DecoderManualInitTest, ContextStateCapabilityCaching) { } } +TEST_P(GLES3DecoderTest, ES3PixelStoreiWithPixelUnpackBuffer) { + // Without PIXEL_UNPACK_BUFFER bound, PixelStorei with unpack parameters + // is cached and not passed down to GL. + EXPECT_CALL(*gl_, PixelStorei(_, _)).Times(0); + cmds::PixelStorei cmd; + cmd.Init(GL_UNPACK_SKIP_ROWS, 2); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // When a PIXEL_UNPACK_BUFFER is bound, all cached unpack parameters are + // applied to GL. + SetupUpdateES3UnpackParametersExpectations(gl_.get(), 0, 0, 0, 2, 0); + DoBindBuffer(GL_PIXEL_UNPACK_BUFFER, client_buffer_id_, kServiceBufferId); + + // Now with a bound PIXEL_UNPACK_BUFFER, all PixelStorei calls with unpack + // parameters are applied to GL. + EXPECT_CALL(*gl_, PixelStorei(GL_UNPACK_ROW_LENGTH, 16)) + .Times(1) + .RetiresOnSaturation(); + cmd.Init(GL_UNPACK_ROW_LENGTH, 16); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // Now unbind PIXEL_UNPACK_BUFFER, all ES3 unpack parameters are set back to + // 0. + SetupUpdateES3UnpackParametersExpectations(gl_.get(), 0, 0, 0, 0, 0); + DoBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0, 0); + + // Again, PixelStorei calls with unpack parameters are cached. + EXPECT_CALL(*gl_, PixelStorei(_, _)).Times(0); + cmd.Init(GL_UNPACK_SKIP_ROWS, 3); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // Bind a PIXEL_UNPACK_BUFFER again. + SetupUpdateES3UnpackParametersExpectations(gl_.get(), 16, 0, 0, 3, 0); + DoBindBuffer(GL_PIXEL_UNPACK_BUFFER, client_buffer_id_, kServiceBufferId); +} + // TODO(vmiura): Tests for VAO restore. // TODO(vmiura): Tests for ContextState::RestoreAttribute(). diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp index b7ac172..87fddec 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp @@ -169,6 +169,15 @@ void WebGL2RenderingContextBase::initializeNewContext() m_boundIndexedUniformBuffers.resize(maxUniformBufferBindings); m_maxBoundUniformBufferIndex = 0; + m_packRowLength = 0; + m_packSkipPixels = 0; + m_packSkipRows = 0; + m_unpackRowLength = 0; + m_unpackImageHeight = 0; + m_unpackSkipPixels = 0; + m_unpackSkipRows = 0; + m_unpackSkipImages = 0; + WebGLRenderingContextBase::initializeNewContext(); } @@ -528,6 +537,42 @@ void WebGL2RenderingContextBase::readBuffer(GLenum mode) webContext()->readBuffer(mode); } +void WebGL2RenderingContextBase::pixelStorei(GLenum pname, GLint param) +{ + if (isContextLost()) + return; + switch (pname) { + case GL_PACK_ROW_LENGTH: + m_packRowLength = param; + break; + case GL_PACK_SKIP_PIXELS: + m_packSkipPixels = param; + break; + case GL_PACK_SKIP_ROWS: + m_packSkipRows = param; + break; + case GL_UNPACK_ROW_LENGTH: + m_unpackRowLength = param; + break; + case GL_UNPACK_IMAGE_HEIGHT: + m_unpackImageHeight = param; + break; + case GL_UNPACK_SKIP_PIXELS: + m_unpackSkipPixels = param; + break; + case GL_UNPACK_SKIP_ROWS: + m_unpackSkipRows = param; + break; + case GL_UNPACK_SKIP_IMAGES: + m_unpackSkipImages = param; + break; + default: + WebGLRenderingContextBase::pixelStorei(pname, param); + return; + } + webContext()->pixelStorei(pname, param); +} + void WebGL2RenderingContextBase::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, DOMArrayBufferView* pixels) { if (isContextLost()) @@ -684,6 +729,38 @@ void WebGL2RenderingContextBase::renderbufferStorageMultisample(GLenum target, G applyStencilTest(); } +void WebGL2RenderingContextBase::resetUnpackParameters() +{ + WebGLRenderingContextBase::resetUnpackParameters(); + + if (!m_unpackRowLength) + webContext()->pixelStorei(GL_UNPACK_ROW_LENGTH, 0); + if (!m_unpackImageHeight) + webContext()->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0); + if (!m_unpackSkipPixels) + webContext()->pixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + if (!m_unpackSkipRows) + webContext()->pixelStorei(GL_UNPACK_SKIP_ROWS, 0); + if (!m_unpackSkipImages) + webContext()->pixelStorei(GL_UNPACK_SKIP_IMAGES, 0); +} + +void WebGL2RenderingContextBase::restoreUnpackParameters() +{ + WebGLRenderingContextBase::restoreUnpackParameters(); + + if (!m_unpackRowLength) + webContext()->pixelStorei(GL_UNPACK_ROW_LENGTH, m_unpackRowLength); + if (!m_unpackImageHeight) + webContext()->pixelStorei(GL_UNPACK_IMAGE_HEIGHT, m_unpackImageHeight); + if (!m_unpackSkipPixels) + webContext()->pixelStorei(GL_UNPACK_SKIP_PIXELS, m_unpackSkipPixels); + if (!m_unpackSkipRows) + webContext()->pixelStorei(GL_UNPACK_SKIP_ROWS, m_unpackSkipRows); + if (!m_unpackSkipImages) + webContext()->pixelStorei(GL_UNPACK_SKIP_IMAGES, m_unpackSkipImages); +} + /* Texture objects */ bool WebGL2RenderingContextBase::validateTexStorage(const char* functionName, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, TexStorageType functionType) { @@ -872,11 +949,9 @@ void WebGL2RenderingContextBase::texSubImage3DImpl(GLenum target, GLint level, G } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); webContext()->texSubImage3D(target, level, xoffset, yoffset, zoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 1, format, type, needConversion ? data.data() : imagePixelData); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, DOMArrayBufferView* pixels) @@ -889,22 +964,17 @@ void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint void* data = pixels->baseAddress(); Vector<uint8_t> tempData; - bool changeUnpackAlignment = false; + bool changeUnpackParameters = false; if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { - if (!WebGLImageConversion::extractTextureData(width, height, format, type, - m_unpackAlignment, - m_unpackFlipY, m_unpackPremultiplyAlpha, - data, - tempData)) - return; - data = tempData.data(); - changeUnpackAlignment = true; + // FIXME: WebGLImageConversion needs to be updated to accept image depth. + notImplemented(); + changeUnpackParameters = true; } - if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + if (changeUnpackParameters) + resetUnpackParameters(); webContext()->texSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, data); - if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + if (changeUnpackParameters) + restoreUnpackParameters(); } void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, ImageData* pixels) @@ -928,11 +998,9 @@ void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint return; } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); webContext()->texSubImage3D(target, level, xoffset, yoffset, zoffset, pixels->width(), pixels->height(), 1, format, type, needConversion ? data.data() : pixels->data()->data()); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGL2RenderingContextBase::texSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLenum format, GLenum type, HTMLImageElement* image, ExceptionState& exceptionState) @@ -2534,11 +2602,11 @@ ScriptValue WebGL2RenderingContextBase::getParameter(ScriptState* scriptState, G case GL_UNPACK_ROW_LENGTH: return getIntParameter(scriptState, pname); case GL_UNPACK_SKIP_IMAGES: - return getBooleanParameter(scriptState, pname); + return getIntParameter(scriptState, pname); case GL_UNPACK_SKIP_PIXELS: - return getBooleanParameter(scriptState, pname); + return getIntParameter(scriptState, pname); case GL_UNPACK_SKIP_ROWS: - return getBooleanParameter(scriptState, pname); + return getIntParameter(scriptState, pname); default: return WebGLRenderingContextBase::getParameter(scriptState, pname); diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h index 38b28b3..47d94d2 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.h @@ -175,6 +175,7 @@ public: ScriptValue getParameter(ScriptState*, GLenum pname) override; ScriptValue getTexParameter(ScriptState*, GLenum target, GLenum pname) override; ScriptValue getFramebufferAttachmentParameter(ScriptState*, GLenum target, GLenum attachment, GLenum pname) override; + void pixelStorei(GLenum pname, GLint param) override; void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, DOMArrayBufferView* pixels) override; void restoreCurrentFramebuffer() override; @@ -237,6 +238,9 @@ protected: void removeBoundBuffer(WebGLBuffer*) override; + void resetUnpackParameters() override; + void restoreUnpackParameters() override; + PersistentWillBeMember<WebGLFramebuffer> m_readFramebufferBinding; PersistentWillBeMember<WebGLTransformFeedback> m_transformFeedbackBinding; GLint m_maxArrayTextureLayers; @@ -258,6 +262,15 @@ protected: PersistentWillBeMember<WebGLQuery> m_currentBooleanOcclusionQuery; PersistentWillBeMember<WebGLQuery> m_currentTransformFeedbackPrimitivesWrittenQuery; PersistentHeapVectorWillBeHeapVector<Member<WebGLSampler>> m_samplerUnits; + + GLint m_packRowLength; + GLint m_packSkipPixels; + GLint m_packSkipRows; + GLint m_unpackRowLength; + GLint m_unpackImageHeight; + GLint m_unpackSkipPixels; + GLint m_unpackSkipRows; + GLint m_unpackSkipImages; }; DEFINE_TYPE_CASTS(WebGL2RenderingContextBase, CanvasRenderingContext, context, diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp index aae2e26..ac5365b 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.cpp @@ -4179,11 +4179,9 @@ void WebGLRenderingContextBase::texImage2DImpl(GLenum target, GLint level, GLenu } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); texImage2DBase(target, level, internalformat, imageExtractor.imageWidth(), imageExtractor.imageHeight(), 0, format, type, needConversion ? data.data() : imagePixelData); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } bool WebGLRenderingContextBase::validateTexFunc(const char* functionName, TexImageFunctionType functionType, TexFuncValidationSourceType sourceType, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, GLint xoffset, GLint yoffset) @@ -4302,10 +4300,10 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum in changeUnpackAlignment = true; } if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); texImage2DBase(target, level, internalformat, width, height, border, format, type, data); if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, @@ -4333,11 +4331,9 @@ void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum in return; } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, format, type, needConversion ? data.data() : pixels->data()->data()); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGLRenderingContextBase::texImage2D(GLenum target, GLint level, GLenum internalformat, @@ -4602,11 +4598,9 @@ void WebGLRenderingContextBase::texSubImage2DImpl(GLenum target, GLint level, GL } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); webContext()->texSubImage2D(target, level, xoffset, yoffset, imageExtractor.imageWidth(), imageExtractor.imageHeight(), format, type, needConversion ? data.data() : imagePixelData); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, @@ -4627,10 +4621,10 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint changeUnpackAlignment = true; } if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); webContext()->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, data); if (changeUnpackAlignment) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, @@ -4658,11 +4652,9 @@ void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint return; } } - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); + resetUnpackParameters(); webContext()->texSubImage2D(target, level, xoffset, yoffset, pixels->width(), pixels->height(), format, type, needConversion ? data.data() : pixels->data()->data()); - if (m_unpackAlignment != 1) - webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); + restoreUnpackParameters(); } void WebGLRenderingContextBase::texSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, @@ -6958,4 +6950,16 @@ DrawingBuffer* WebGLRenderingContextBase::drawingBuffer() const return m_drawingBuffer.get(); } +void WebGLRenderingContextBase::resetUnpackParameters() +{ + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, 1); +} + +void WebGLRenderingContextBase::restoreUnpackParameters() +{ + if (m_unpackAlignment != 1) + webContext()->pixelStorei(GL_UNPACK_ALIGNMENT, m_unpackAlignment); +} + } // namespace blink diff --git a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h index 201fc75..c2862a9 100644 --- a/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h +++ b/third_party/WebKit/Source/modules/webgl/WebGLRenderingContextBase.h @@ -276,7 +276,7 @@ public: void lineWidth(GLfloat); void linkProgram(WebGLProgram*); - void pixelStorei(GLenum pname, GLint param); + virtual void pixelStorei(GLenum pname, GLint param); void polygonOffset(GLfloat factor, GLfloat units); virtual void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, DOMArrayBufferView* pixels); void renderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); @@ -487,6 +487,11 @@ protected: void addCompressedTextureFormat(GLenum); void removeAllCompressedTextureFormats(); + // Set UNPACK_ALIGNMENT to 1, all other parameters to 0. + virtual void resetUnpackParameters(); + // Restore the client unpack parameters. + virtual void restoreUnpackParameters(); + PassRefPtr<Image> drawImageIntoBuffer(PassRefPtr<Image>, int width, int height, const char* functionName); PassRefPtr<Image> videoFrameToImage(HTMLVideoElement*); |