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 c9e8470b6cca2e031b61a22bbd12e737b48a5c55..9985a2d816535686292198f0565c0fccacc85dca 100644 |
| --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc |
| @@ -56,6 +56,7 @@ |
| #include "gpu/command_buffer/service/shader_manager.h" |
| #include "gpu/command_buffer/service/shader_translator.h" |
| #include "gpu/command_buffer/service/texture_manager.h" |
| +#include "gpu/command_buffer/service/transform_feedback_manager.h" |
| #include "gpu/command_buffer/service/vertex_array_manager.h" |
| #include "gpu/command_buffer/service/vertex_attrib_manager.h" |
| #include "third_party/smhasher/src/City.h" |
| @@ -751,6 +752,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| bool DeletePathsCHROMIUMHelper(GLuint first_client_id, GLsizei range); |
| bool GenSamplersHelper(GLsizei n, const GLuint* client_ids); |
| void DeleteSamplersHelper(GLsizei n, const GLuint* client_ids); |
| + bool GenTransformFeedbacksHelper(GLsizei n, const GLuint* client_ids); |
| + void DeleteTransformFeedbacksHelper(GLsizei n, const GLuint* client_ids); |
| // Workarounds |
| void OnFboChanged() const; |
| @@ -780,6 +783,10 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| return group_->sampler_manager(); |
| } |
| + TransformFeedbackManager* transform_feedback_manager() { |
| + return group_->transform_feedback_manager(); |
| + } |
| + |
| ShaderManager* shader_manager() { |
| return group_->shader_manager(); |
| } |
| @@ -854,6 +861,24 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| sampler_manager()->RemoveSampler(client_id); |
| } |
| + // Creates a TransformFeedback for the given transformfeedback. |
| + TransformFeedback* CreateTransformFeedback( |
| + GLuint client_id, GLuint service_id) { |
| + return transform_feedback_manager()->CreateTransformFeedback( |
| + client_id, service_id); |
| + } |
| + |
| + // Gets the TransformFeedback info for the given transformfeedback. |
| + // Returns nullptr if none exists. |
| + TransformFeedback* GetTransformFeedback(GLuint client_id) { |
| + return transform_feedback_manager()->GetTransformFeedback(client_id); |
| + } |
| + |
| + // Deletes the TransformFeedback info for the given transformfeedback. |
| + void RemoveTransformFeedback(GLuint client_id) { |
| + transform_feedback_manager()->RemoveTransformFeedback(client_id); |
| + } |
| + |
| // Get the size (in pixels) of the currently bound frame buffer (either FBO |
| // or regular back buffer). |
| gfx::Size GetBoundReadFrameBufferSize(); |
| @@ -1371,6 +1396,22 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| // Wrapper for glBindSampler since we need to track the current targets. |
| void DoBindSampler(GLuint unit, GLuint sampler); |
| + // Wrapper for glBindTransformFeedback since we need to emulate ES3 behaviors |
| + // for BindBufferRange on Desktop GL lower than 4.2. |
| + void DoBindTransformFeedback(GLenum target, GLuint transform_feedback); |
| + |
| + // Wrapper for glBeginTransformFeedback. |
| + void DoBeginTransformFeedback(GLenum primitive_mode); |
| + |
| + // Wrapper for glEndTransformFeedback. |
| + void DoEndTransformFeedback(); |
| + |
| + // Wrapper for glPauseTransformFeedback. |
| + void DoPauseTransformFeedback(); |
| + |
| + // Wrapper for glResumeTransformFeedback. |
| + void DoResumeTransformFeedback(); |
| + |
| // Wrapper for glBindVertexArrayOES |
| void DoBindVertexArrayOES(GLuint array); |
| void EmulateVertexArrayState(); |
| @@ -1546,6 +1587,7 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient { |
| bool DoIsShader(GLuint client_id); |
| bool DoIsTexture(GLuint client_id); |
| bool DoIsSampler(GLuint client_id); |
| + bool DoIsTransformFeedback(GLuint client_id); |
| bool DoIsVertexArrayOES(GLuint client_id); |
| bool DoIsPathCHROMIUM(GLuint client_id); |
| @@ -2730,6 +2772,14 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface, |
| frag_depth_explicitly_enabled_ = true; |
| draw_buffers_explicitly_enabled_ = true; |
| // TODO(zmo): Look into shader_texture_lod_explicitly_enabled_ situation. |
| + |
| + // Create a fake default transform feedback and bind to it. |
| + GLuint default_transform_feedback = 0; |
| + glGenTransformFeedbacks(1, &default_transform_feedback); |
| + state_.default_transform_feedback = new TransformFeedback( |
| + group_->transform_feedback_manager(), default_transform_feedback); |
| + glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, default_transform_feedback); |
| + state_.bound_transform_feedback = state_.default_transform_feedback.get(); |
| } |
| state_.attrib_values.resize(group_->max_vertex_attribs()); |
| @@ -3473,6 +3523,21 @@ bool GLES2DecoderImpl::GenSamplersHelper(GLsizei n, const GLuint* client_ids) { |
| return true; |
| } |
| +bool GLES2DecoderImpl::GenTransformFeedbacksHelper( |
| + GLsizei n, const GLuint* client_ids) { |
| + for (GLsizei ii = 0; ii < n; ++ii) { |
| + if (GetTransformFeedback(client_ids[ii])) { |
| + return false; |
| + } |
| + } |
| + std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); |
| + glGenTransformFeedbacks(n, service_ids.get()); |
| + for (GLsizei ii = 0; ii < n; ++ii) { |
| + CreateTransformFeedback(client_ids[ii], service_ids[ii]); |
| + } |
| + return true; |
| +} |
| + |
| bool GLES2DecoderImpl::GenPathsCHROMIUMHelper(GLuint first_client_id, |
| GLsizei range) { |
| GLuint last_client_id; |
| @@ -3516,6 +3581,9 @@ void GLES2DecoderImpl::DeleteBuffersHelper( |
| if (buffer && !buffer->IsDeleted()) { |
| buffer->RemoveMappedRange(); |
| state_.RemoveBoundBuffer(buffer); |
| + if (transform_feedback_manager()) { |
|
piman
2016/04/28 01:38:47
nit: transform_feedback_manager() is always non-nu
Zhenyao Mo
2016/04/29 21:07:54
Done.
|
| + transform_feedback_manager()->RemoveBoundBuffer(buffer); |
| + } |
| RemoveBuffer(client_ids[ii]); |
| } |
| } |
| @@ -3641,7 +3709,25 @@ void GLES2DecoderImpl::DeleteSamplersHelper( |
| } |
| } |
| -// } // anonymous namespace |
| +void GLES2DecoderImpl::DeleteTransformFeedbacksHelper( |
| + GLsizei n, const GLuint* client_ids) { |
| + for (GLsizei ii = 0; ii < n; ++ii) { |
| + TransformFeedback* transform_feedback = GetTransformFeedback( |
| + client_ids[ii]); |
| + if (transform_feedback && !transform_feedback->deleted()) { |
|
piman
2016/04/28 01:38:47
nit: because the transform feedback objects are no
Zhenyao Mo
2016/04/29 21:07:54
Done.
|
| + if (state_.bound_transform_feedback.get() == transform_feedback) { |
| + // Bind to the default transform feedback. |
| + DCHECK(state_.default_transform_feedback.get()); |
| + state_.default_transform_feedback->DoBindTransformFeedback( |
| + feature_info_->gl_version_info(), GL_TRANSFORM_FEEDBACK); |
| + state_.bound_transform_feedback = |
| + state_.default_transform_feedback.get(); |
| + } |
| + |
| + RemoveTransformFeedback(client_ids[ii]); |
| + } |
| + } |
| +} |
| bool GLES2DecoderImpl::MakeCurrent() { |
| if (!context_.get()) |
| @@ -4042,23 +4128,25 @@ void GLES2DecoderImpl::Destroy(bool have_context) { |
| if (!initialized()) |
| return; |
| - DCHECK(!have_context || context_->IsCurrent(NULL)); |
| + DCHECK(!have_context || context_->IsCurrent(nullptr)); |
| // Unbind everything. |
| - state_.vertex_attrib_manager = NULL; |
| - state_.default_vertex_attrib_manager = NULL; |
| + state_.vertex_attrib_manager = nullptr; |
| + state_.default_vertex_attrib_manager = nullptr; |
| state_.texture_units.clear(); |
| state_.sampler_units.clear(); |
| - state_.bound_array_buffer = NULL; |
| - state_.bound_copy_read_buffer = NULL; |
| - state_.bound_copy_write_buffer = NULL; |
| - state_.bound_pixel_pack_buffer = NULL; |
| - state_.bound_pixel_unpack_buffer = NULL; |
| - state_.bound_transform_feedback_buffer = NULL; |
| - state_.bound_uniform_buffer = NULL; |
| - framebuffer_state_.bound_read_framebuffer = NULL; |
| - framebuffer_state_.bound_draw_framebuffer = NULL; |
| - state_.bound_renderbuffer = NULL; |
| + state_.bound_array_buffer = nullptr; |
| + state_.bound_copy_read_buffer = nullptr; |
| + state_.bound_copy_write_buffer = nullptr; |
| + state_.bound_pixel_pack_buffer = nullptr; |
| + state_.bound_pixel_unpack_buffer = nullptr; |
| + state_.bound_transform_feedback_buffer = nullptr; |
| + state_.bound_uniform_buffer = nullptr; |
| + framebuffer_state_.bound_read_framebuffer = nullptr; |
| + framebuffer_state_.bound_draw_framebuffer = nullptr; |
| + state_.bound_renderbuffer = nullptr; |
| + state_.bound_transform_feedback = nullptr; |
| + state_.default_transform_feedback = nullptr; |
| if (offscreen_saved_color_texture_info_.get()) { |
| DCHECK(offscreen_target_color_texture_); |
| @@ -4595,7 +4683,12 @@ void GLES2DecoderImpl::BindIndexedBufferImpl( |
| "index out of range"); |
| return; |
| } |
| - // TODO(zmo): Check transform feedback isn't currently active. |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + if (state_.bound_transform_feedback->active()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, |
| + "bound transform feedback is active"); |
| + return; |
| + } |
| break; |
| } |
| case GL_UNIFORM_BUFFER: { |
| @@ -4666,17 +4759,37 @@ void GLES2DecoderImpl::BindIndexedBufferImpl( |
| } |
| LogClientServiceForInfo(buffer, client_id, function_name); |
| - switch (function_type) { |
| - case kBindBufferBase: |
| - glBindBufferBase(target, index, service_id); |
| + switch (target) { |
| + case GL_TRANSFORM_FEEDBACK_BUFFER: |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + switch (function_type) { |
| + case kBindBufferBase: |
| + state_.bound_transform_feedback->DoBindBufferBase( |
| + target, index, buffer); |
| + break; |
| + case kBindBufferRange: |
| + state_.bound_transform_feedback->DoBindBufferRange( |
| + feature_info_->gl_version_info(), |
| + target, index, buffer, offset, size); |
| + break; |
| + } |
| break; |
| - case kBindBufferRange: |
| - // TODO(zmo): On Desktop GL 4.1 or lower, clamp the offset/size not to |
| - // exceed the size of the buffer. crbug.com/604436. |
| - glBindBufferRange(target, index, service_id, offset, size); |
| + case GL_UNIFORM_BUFFER: |
| + // TODO(zmo): emulate Desktop GL 4.1 or lower behavior and keep track of |
| + // indexed buffer bindings. |
| + switch (function_type) { |
| + case kBindBufferBase: |
| + glBindBufferBase(target, index, service_id); |
| + break; |
| + case kBindBufferRange: |
| + glBindBufferRange(target, index, service_id, offset, size); |
| + break; |
| + } |
| + break; |
| + default: |
| + NOTREACHED(); |
| break; |
| } |
| - // TODO(kbr): track indexed bound buffers. |
| } |
| void GLES2DecoderImpl::DoBindBufferBase(GLenum target, GLuint index, |
| @@ -5010,6 +5123,82 @@ void GLES2DecoderImpl::DoBindSampler(GLuint unit, GLuint client_id) { |
| state_.sampler_units[unit] = sampler; |
| } |
| +void GLES2DecoderImpl::DoBindTransformFeedback( |
| + GLenum target, GLuint client_id) { |
| + const char* function_name = "glBindTransformFeedback"; |
| + if (!validators_->transform_feedback_bind_target.IsValid(target)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, target, "target"); |
| + return; |
| + } |
|
piman
2016/04/28 01:38:47
If the currently bound transform feedback is activ
Zhenyao Mo
2016/04/29 21:07:54
Done.
|
| + |
| + TransformFeedback* transform_feedback = nullptr; |
| + if (client_id != 0) { |
| + transform_feedback = GetTransformFeedback(client_id); |
| + if (!transform_feedback) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, |
| + "id not generated by glGenTransformFeedbacks"); |
| + return; |
| + } |
| + } else { |
| + transform_feedback = state_.default_transform_feedback.get(); |
| + } |
| + DCHECK(transform_feedback); |
| + LogClientServiceForInfo(transform_feedback, client_id, function_name); |
| + transform_feedback->DoBindTransformFeedback( |
| + feature_info_->gl_version_info(), target); |
| + state_.bound_transform_feedback = transform_feedback; |
| +} |
| + |
| +void GLES2DecoderImpl::DoBeginTransformFeedback(GLenum primitive_mode) { |
| + const char* function_name = "glBeginTransformFeedback"; |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + if (!validators_->transform_feedback_primitive_mode.IsValid(primitive_mode)) { |
| + LOCAL_SET_GL_ERROR_INVALID_ENUM( |
| + function_name, primitive_mode, "primitiveMode"); |
| + return; |
| + } |
| + if (state_.bound_transform_feedback->active()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, |
| + "transform feedback is already active"); |
| + return; |
| + } |
| + state_.bound_transform_feedback->DoBeginTransformFeedback(primitive_mode); |
| +} |
| + |
| +void GLES2DecoderImpl::DoEndTransformFeedback() { |
| + const char* function_name = "glEndTransformFeedback"; |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + if (!state_.bound_transform_feedback->active()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, |
| + "transform feedback is not active"); |
| + return; |
| + } |
| + // TODO(zmo): Validate binding points. |
| + state_.bound_transform_feedback->DoEndTransformFeedback(); |
| +} |
| + |
| +void GLES2DecoderImpl::DoPauseTransformFeedback() { |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + if (!state_.bound_transform_feedback->active() || |
| + state_.bound_transform_feedback->paused()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glPauseTransformFeedback", |
| + "transform feedback is not active or already paused"); |
| + return; |
| + } |
| + state_.bound_transform_feedback->DoPauseTransformFeedback(); |
| +} |
| + |
| +void GLES2DecoderImpl::DoResumeTransformFeedback() { |
| + DCHECK(state_.bound_transform_feedback.get()); |
| + if (!state_.bound_transform_feedback->active() || |
| + !state_.bound_transform_feedback->paused()) { |
| + LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glResumeTransformFeedback", |
| + "transform feedback is not active or not paused"); |
| + return; |
| + } |
| + state_.bound_transform_feedback->DoResumeTransformFeedback(); |
| +} |
| + |
| void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) { |
| if (state_.vertex_attrib_manager->Enable(index, false)) { |
| if (index != 0 || feature_info_->gl_version_info().BehavesLikeGLES()) { |
| @@ -8710,6 +8899,12 @@ bool GLES2DecoderImpl::DoIsSampler(GLuint client_id) { |
| return sampler && !sampler->IsDeleted(); |
| } |
| +bool GLES2DecoderImpl::DoIsTransformFeedback(GLuint client_id) { |
| + const TransformFeedback* transform_feedback = |
| + GetTransformFeedback(client_id); |
| + return transform_feedback && !transform_feedback->deleted(); |
|
piman
2016/04/28 01:38:47
Also, technically, IsTransformFeedback should only
piman
2016/04/28 01:38:47
nit: same as above, I don't think deleted() is pos
Zhenyao Mo
2016/04/29 21:07:54
Done.
Zhenyao Mo
2016/04/29 21:07:54
Done.
|
| +} |
| + |
| void GLES2DecoderImpl::DoAttachShader( |
| GLuint program_client_id, GLint shader_client_id) { |
| Program* program = GetProgramInfoNotShader( |