 Chromium Code Reviews
 Chromium Code Reviews Issue 9968113:
  Addition of GL_CHROMIUM_copy_texture extension.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/
    
  
    Issue 9968113:
  Addition of GL_CHROMIUM_copy_texture extension.  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src/| Index: gpu/command_buffer/service/gles2_cmd_decoder.cc | 
| =================================================================== | 
| --- gpu/command_buffer/service/gles2_cmd_decoder.cc (revision 132190) | 
| +++ gpu/command_buffer/service/gles2_cmd_decoder.cc (working copy) | 
| @@ -33,6 +33,7 @@ | 
| #include "gpu/command_buffer/service/feature_info.h" | 
| #include "gpu/command_buffer/service/framebuffer_manager.h" | 
| #include "gpu/command_buffer/service/gl_utils.h" | 
| +#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h" | 
| #include "gpu/command_buffer/service/gles2_cmd_validation.h" | 
| #include "gpu/command_buffer/service/gpu_switches.h" | 
| #include "gpu/command_buffer/service/program_manager.h" | 
| @@ -726,6 +727,12 @@ | 
| GLuint io_surface_id, | 
| GLuint plane); | 
| + void DoCopyTextureCHROMIUM( | 
| + GLenum target, | 
| + GLuint source_id, | 
| + GLuint target_id, | 
| + GLint level); | 
| + | 
| // Wrapper for TexStorage2DEXT. | 
| void DoTexStorage2DEXT( | 
| GLenum target, | 
| @@ -1132,6 +1139,9 @@ | 
| void DoVertexAttrib3fv(GLuint index, const GLfloat *v); | 
| void DoVertexAttrib4fv(GLuint index, const GLfloat *v); | 
| + // Wrapper for glViewport | 
| + void DoViewport(GLint x, GLint y, GLsizei width, GLsizei height); | 
| + | 
| // Wrapper for glUseProgram | 
| void DoUseProgram(GLuint program); | 
| @@ -1166,7 +1176,7 @@ | 
| // simulated. | 
| bool SimulateAttrib0( | 
| GLuint max_vertex_accessed, bool* simulated); | 
| - void RestoreStateForSimulatedAttrib0(); | 
| + void RestoreStateForAttrib(GLuint attrib); | 
| // Returns true if textures were set. | 
| bool SetBlackTextureForNonRenderableTextures(); | 
| @@ -1332,6 +1342,12 @@ | 
| // unpack alignment as last set by glPixelStorei | 
| GLint unpack_alignment_; | 
| + // unpack flip y as last set by glPixelStorei | 
| + bool unpack_flip_y_; | 
| + | 
| + // unpack premultiply alpha as last set by glPixelStorei | 
| + bool unpack_premultiply_alpha_; | 
| + | 
| // The currently bound array buffer. If this is 0 it is illegal to call | 
| // glVertexAttribPointer. | 
| BufferManager::BufferInfo::Ref bound_array_buffer_; | 
| @@ -1384,6 +1400,7 @@ | 
| GLuint mask_stencil_back_; | 
| GLclampf clear_depth_; | 
| GLboolean mask_depth_; | 
| + bool enable_cull_face_; | 
| bool enable_scissor_test_; | 
| bool enable_depth_test_; | 
| bool enable_stencil_test_; | 
| @@ -1487,6 +1504,13 @@ | 
| typedef std::vector<GLES2DecoderImpl*> ChildList; | 
| ChildList children_; | 
| + scoped_ptr<CopyTextureCHROMIUMResourceManager> copy_texture_CHROMIUM_; | 
| + | 
| + // Cached values of the currently assigned viewport dimensions. | 
| + GLint viewport_x_, viewport_y_; | 
| + GLsizei viewport_width_, viewport_height_; | 
| + GLsizei viewport_max_width_, viewport_max_height_; | 
| + | 
| DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); | 
| }; | 
| @@ -1830,6 +1854,8 @@ | 
| error_bits_(0), | 
| pack_alignment_(4), | 
| unpack_alignment_(4), | 
| + unpack_flip_y_(false), | 
| + unpack_premultiply_alpha_(false), | 
| attrib_0_buffer_id_(0), | 
| attrib_0_buffer_matches_value_(true), | 
| attrib_0_size_(0), | 
| @@ -1849,6 +1875,7 @@ | 
| mask_stencil_back_(-1), | 
| clear_depth_(1.0f), | 
| mask_depth_(true), | 
| + enable_cull_face_(false), | 
| enable_scissor_test_(false), | 
| enable_depth_test_(false), | 
| enable_stencil_test_(false), | 
| @@ -1877,7 +1904,13 @@ | 
| needs_glsl_built_in_function_emulation_(false), | 
| force_webgl_glsl_validation_(false), | 
| derivatives_explicitly_enabled_(false), | 
| - compile_shader_always_succeeds_(false) { | 
| + compile_shader_always_succeeds_(false), | 
| + viewport_x_(0), | 
| + viewport_y_(0), | 
| + viewport_width_(0), | 
| + viewport_height_(0), | 
| + viewport_max_width_(0), | 
| + viewport_max_height_(0) { | 
| DCHECK(group); | 
| attrib_0_value_.v[0] = 0.0f; | 
| @@ -1959,8 +1992,12 @@ | 
| Destroy(); | 
| return false; | 
| } | 
| + CHECK_GL_ERROR(); | 
| + copy_texture_CHROMIUM_.reset(new CopyTextureCHROMIUMResourceManager()); | 
| + copy_texture_CHROMIUM_->Initialize(); | 
| CHECK_GL_ERROR(); | 
| + | 
| disallowed_features_ = disallowed_features; | 
| vertex_attrib_manager_.reset(new VertexAttribManager()); | 
| @@ -2180,6 +2217,17 @@ | 
| return false; | 
| } | 
| + GLint viewport_params[4]; | 
| + glGetIntegerv(GL_VIEWPORT, viewport_params); | 
| + viewport_x_ = viewport_params[0]; | 
| + viewport_y_ = viewport_params[1]; | 
| + viewport_width_ = viewport_params[2]; | 
| + viewport_height_ = viewport_params[3]; | 
| + | 
| + glGetIntegerv(GL_MAX_VIEWPORT_DIMS, viewport_params); | 
| + viewport_max_width_ = viewport_params[0]; | 
| + viewport_max_height_ = viewport_params[0]; | 
| + | 
| return true; | 
| } | 
| @@ -2686,6 +2734,8 @@ | 
| bound_renderbuffer_ = NULL; | 
| if (have_context) { | 
| + copy_texture_CHROMIUM_->Destroy(); | 
| + | 
| if (current_program_) { | 
| program_manager()->UnuseProgram(shader_manager(), current_program_); | 
| current_program_ = NULL; | 
| @@ -2736,6 +2786,7 @@ | 
| if (offscreen_resolved_color_texture_.get()) | 
| offscreen_resolved_color_texture_->Invalidate(); | 
| } | 
| + copy_texture_CHROMIUM_.reset(); | 
| if (query_manager_.get()) { | 
| query_manager_->Destroy(have_context); | 
| @@ -3200,6 +3251,8 @@ | 
| glStencilMaskSeparate(GL_FRONT, have_stencil ? mask_stencil_front_ : 0); | 
| glStencilMaskSeparate(GL_BACK, have_stencil ? mask_stencil_back_ : 0); | 
| EnableDisable(GL_STENCIL_TEST, enable_stencil_test_ && have_stencil); | 
| + EnableDisable(GL_CULL_FACE, enable_cull_face_); | 
| + EnableDisable(GL_SCISSOR_TEST, enable_scissor_test_); | 
| state_dirty_ = false; | 
| } | 
| } | 
| @@ -4010,6 +4063,9 @@ | 
| bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) { | 
| switch (cap) { | 
| + case GL_CULL_FACE: | 
| + enable_cull_face_ = enabled; | 
| + return true; | 
| case GL_SCISSOR_TEST: | 
| enable_scissor_test_ = enabled; | 
| return true; | 
| @@ -4998,9 +5054,9 @@ | 
| return true; | 
| } | 
| -void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() { | 
| +void GLES2DecoderImpl::RestoreStateForAttrib(GLuint attrib) { | 
| const VertexAttribManager::VertexAttribInfo* info = | 
| - vertex_attrib_manager_->GetVertexAttribInfo(0); | 
| + vertex_attrib_manager_->GetVertexAttribInfo(attrib); | 
| const void* ptr = reinterpret_cast<const void*>(info->offset()); | 
| BufferManager::BufferInfo* buffer_info = info->buffer(); | 
| glBindBuffer(GL_ARRAY_BUFFER, buffer_info ? buffer_info->service_id() : 0); | 
| @@ -5011,6 +5067,12 @@ | 
| glVertexAttribDivisorANGLE(0, info->divisor()); | 
| glBindBuffer(GL_ARRAY_BUFFER, | 
| bound_array_buffer_ ? bound_array_buffer_->service_id() : 0); | 
| + | 
| + if (info->enabled()) { | 
| + glEnableVertexAttribArray(attrib); | 
| + } else { | 
| + glDisableVertexAttribArray(attrib); | 
| + } | 
| } | 
| bool GLES2DecoderImpl::SimulateFixedAttribs( | 
| @@ -5183,7 +5245,7 @@ | 
| } | 
| } | 
| if (simulated_attrib_0) { | 
| - RestoreStateForSimulatedAttrib0(); | 
| + RestoreStateForAttrib(0); | 
| } | 
| if (WasContextLost()) { | 
| LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawArrays."; | 
| @@ -5294,7 +5356,7 @@ | 
| } | 
| } | 
| if (simulated_attrib_0) { | 
| - RestoreStateForSimulatedAttrib0(); | 
| + RestoreStateForAttrib(0); | 
| } | 
| if (WasContextLost()) { | 
| LOG(ERROR) << " GLES2DecoderImpl: Context lost during DrawElements."; | 
| @@ -5934,6 +5996,15 @@ | 
| return error::kNoError; | 
| } | 
| +void GLES2DecoderImpl::DoViewport(GLint x, GLint y, GLsizei width, | 
| + GLsizei height) { | 
| + viewport_x_ = x; | 
| + viewport_y_ = y; | 
| + viewport_width_ = std::min(width, viewport_max_width_); | 
| + viewport_height_ = std::min(height, viewport_max_height_); | 
| + glViewport(x, y, width, height); | 
| +} | 
| + | 
| error::Error GLES2DecoderImpl::HandleVertexAttribDivisorANGLE( | 
| uint32 immediate_data_size, const gles2::VertexAttribDivisorANGLE& c) { | 
| if (!feature_info_->feature_flags().angle_instanced_arrays) { | 
| @@ -6132,6 +6203,12 @@ | 
| case GL_UNPACK_ALIGNMENT: | 
| unpack_alignment_ = param; | 
| break; | 
| + case GL_UNPACK_FLIP_Y_CHROMIUM: | 
| + unpack_flip_y_ = (param != 0); | 
| + break; | 
| + case GL_UNPACK_PREMULTIPLY_ALPHA_CHROMIUM: | 
| + unpack_premultiply_alpha_ = (param != 0); | 
| + break; | 
| default: | 
| // Validation should have prevented us from getting here. | 
| NOTREACHED(); | 
| @@ -8216,6 +8293,72 @@ | 
| } | 
| } | 
| +void GLES2DecoderImpl::DoCopyTextureCHROMIUM( | 
| + GLenum target, GLuint source_id, GLuint dest_id, GLint level) { | 
| + TextureManager::TextureInfo* dest_info = GetTextureInfo(dest_id); | 
| + TextureManager::TextureInfo* source_info = GetTextureInfo(source_id); | 
| + | 
| + if (!source_info || !dest_info) { | 
| + SetGLError(GL_INVALID_VALUE, "glCopyTextureCHROMIUM: unknown texture id"); | 
| + return; | 
| + } | 
| + | 
| + if (GL_TEXTURE_2D != target) { | 
| + SetGLError(GL_INVALID_VALUE, | 
| + "glCopyTextureCHROMIUM: invalid texture target"); | 
| + return; | 
| + } | 
| + | 
| + int source_width, source_height, dest_width, dest_height; | 
| + if (!source_info->GetLevelSize(GL_TEXTURE_2D, 0, &source_width, | 
| + &source_height)) { | 
| + SetGLError(GL_INVALID_VALUE, | 
| + "glCopyTextureChromium: source texture has no level 0"); | 
| + return; | 
| + } | 
| + | 
| + if (!dest_info->GetLevelSize(GL_TEXTURE_2D, level, &dest_width, | 
| + &dest_height)) { | 
| + SetGLError(GL_INVALID_VALUE, | 
| + "glCopyTextureChromium: destination texture level does not exist"); | 
| + return; | 
| + } | 
| + | 
| + // Resize the destination texture to the dimensions of the source texture. | 
| + if (dest_width != source_width && dest_height != source_height) { | 
| + GLenum type; | 
| + GLenum internal_format; | 
| + dest_info->GetLevelType(GL_TEXTURE_2D, level, &type, &internal_format); | 
| 
greggman
2012/04/18 01:04:30
Hi Jeff, continued from the email
This code needs
 
Jeff Timanus
2012/04/18 14:59:08
Done.
 | 
| + glTexImage2D(GL_TEXTURE_2D, level, internal_format, source_width, | 
| + source_height, 0, internal_format, type, NULL); | 
| + | 
| + dest_info->SetLevelSize(GL_TEXTURE_2D, level, source_width, source_height); | 
| 
greggman
2012/04/17 04:58:06
See comments in other places about the problems wi
 
Jeff Timanus
2012/04/18 14:59:08
Done.
 | 
| + } | 
| + | 
| + state_dirty_ = true; | 
| + glViewport(0, 0, dest_width, dest_height); | 
| + copy_texture_CHROMIUM_->DoCopyTexture(target, source_info->service_id(), | 
| + dest_info->service_id(), level, | 
| + unpack_flip_y_, | 
| + unpack_premultiply_alpha_); | 
| + glViewport(viewport_x_, viewport_y_, viewport_width_, viewport_height_); | 
| + | 
| + // Restore all of the state touched by the extension. | 
| + if (current_program_) | 
| + glUseProgram(current_program_->service_id()); | 
| + else | 
| + glUseProgram(0); | 
| + | 
| + RestoreCurrentFramebufferBindings(); | 
| + RestoreCurrentTexture2DBindings(); | 
| + RestoreStateForAttrib( | 
| + CopyTextureCHROMIUMResourceManager::kVertexPositionAttrib); | 
| + RestoreStateForAttrib( | 
| + CopyTextureCHROMIUMResourceManager::kVertexTextureAttrib); | 
| + | 
| + ApplyDirtyState(); | 
| +} | 
| + | 
| static GLenum ExtractTypeFromStorageFormat(GLenum internalformat) { | 
| switch (internalformat) { | 
| case GL_RGB565: |