Chromium Code Reviews| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc |
| diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| index 68b894846bb0ff89ffbdd837869f1f4f0492aaf6..c97b9c357d114ab3acb0003177ea7dabd9cd4e7c 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -13264,19 +13264,61 @@ void GLES2DecoderImpl::DoCopyTexSubImage3D( |
| return; |
| } |
| - // For 3D textures, we always clear the entire texture. See the code in |
| - // TextureManager::ValidateAndDoTexSubImage for TexSubImage3D. |
| + ScopedResolvedFrameBufferBinder binder(this, false, true); |
| + gfx::Size size = GetBoundReadFrameBufferSize(); |
| + GLint copyX = 0; |
| + GLint copyY = 0; |
| + GLint copyWidth = 0; |
| + GLint copyHeight = 0; |
| + Clip(x, width, size.width(), ©X, ©Width); |
| + Clip(y, height, size.height(), ©Y, ©Height); |
| + |
| + GLint dx = copyX - x; |
| + GLint dy = copyY - y; |
| + GLint destX = xoffset + dx; |
| + GLint destY = yoffset + dy; |
| + // For 3D textures, we always clear the entire texture to 0 if it is not |
| + // cleared. See the code in TextureManager::ValidateAndDoTexSubImage |
| + // for TexSubImage3D. |
| if (!texture->IsLevelCleared(target, level)) { |
| texture_manager()->ClearTextureLevel(this, texture_ref, target, level); |
| DCHECK(texture->IsLevelCleared(target, level)); |
| + } else { |
| + // For any pixel lying outside the framebuffer, all channels of the |
| + // associated texel are initialized to 0. |
| + if (x != copyX || y != copyY || |
| + width != copyWidth || height != copyHeight) { |
| + uint32_t pixels_size = 0; |
| + GLenum format = |
| + TextureManager::ExtractFormatFromStorageFormat(internal_format); |
| + GLenum type = |
| + TextureManager::ExtractTypeFromStorageFormat(internal_format); |
| + // The internal_format was selected and validated previously by either |
| + // a TexImage3D or a TexStorage3D. So the format / type pair is valid. |
| + DCHECK(format && type); |
| + |
| + if (!GLES2Util::ComputeImageDataSizes( |
| + width, height, 1, format, type, |
| + state_.unpack_alignment, &pixels_size, NULL, NULL)) { |
| + LOCAL_SET_GL_ERROR(GL_OUT_OF_MEMORY, func_name, "dimensions too large"); |
| + return; |
| + } |
| + |
| + // some part was clipped so clear the rect. |
| + std::unique_ptr<char[]> zero(new char[pixels_size]); |
| + memset(zero.get(), 0, pixels_size); |
| + glTexSubImage3D(target, level, xoffset, yoffset, zoffset, |
| + width, height, 1, format, type, zero.get()); |
|
Ken Russell (switch to Gerrit)
2016/08/12 17:50:27
Per comments above and on the bug: let's change th
yunchao
2016/08/12 23:59:43
Acknowledged.
|
| + } |
| } |
| // TODO(yunchao): Follow-up CLs are necessary. For instance: |
| // 1. emulation of unsized formats in core profile |
| - // 2. out-of-bounds reading, etc. |
| - glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, |
| - height); |
| + if (copyHeight > 0 && copyWidth > 0) { |
| + glCopyTexSubImage3D(target, level, destX, destY, zoffset, |
| + copyX, copyY, copyWidth, copyHeight); |
| + } |
| // This may be a slow command. Exit command processing to allow for |
| // context preemption and GPU watchdog checks. |