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( |