Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Unified Diff: gpu/command_buffer/service/gles2_cmd_decoder.cc

Issue 1922633002: Implement TransformFeedbackManager in GPU command buffer. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 fd688cf290519a478f28d15c2dc0bf35f6d9152e..d233b3251ac497504504d5e4cc467dfa86a3f7c9 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"
@@ -630,6 +631,9 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
void RestoreAllAttributes() const override;
QueryManager* GetQueryManager() override { return query_manager_.get(); }
+ TransformFeedbackManager* GetTransformFeedbackManager() override {
+ return transform_feedback_manager_.get();
+ }
VertexArrayManager* GetVertexArrayManager() override {
return vertex_array_manager_.get();
}
@@ -752,6 +756,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;
@@ -855,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();
@@ -1375,6 +1399,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();
@@ -1550,6 +1590,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);
@@ -1954,6 +1995,8 @@ class GLES2DecoderImpl : public GLES2Decoder, public ErrorStateClient {
// All the state for this context.
ContextState state_;
+ std::unique_ptr<TransformFeedbackManager> transform_feedback_manager_;
+
// Current width and height of the offscreen frame buffer.
gfx::Size offscreen_size_;
@@ -2749,6 +2792,11 @@ bool GLES2DecoderImpl::Initialize(const scoped_refptr<gfx::GLSurface>& surface,
return false;
}
CHECK_GL_ERROR();
+
+ bool needs_emulation = feature_info_->gl_version_info().IsLowerThanGL(4, 2);
+ transform_feedback_manager_.reset(new TransformFeedbackManager(
+ group_->max_transform_feedback_separate_attribs(), needs_emulation));
+
if (feature_info_->context_type() == CONTEXT_TYPE_WEBGL2 ||
feature_info_->context_type() == CONTEXT_TYPE_OPENGLES3) {
if (!feature_info_->IsES3Capable()) {
@@ -2762,6 +2810,15 @@ 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 =
+ transform_feedback_manager_->CreateTransformFeedback(
+ 0, 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());
@@ -3505,6 +3562,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;
@@ -3548,6 +3620,7 @@ void GLES2DecoderImpl::DeleteBuffersHelper(
if (buffer && !buffer->IsDeleted()) {
buffer->RemoveMappedRange();
state_.RemoveBoundBuffer(buffer);
+ transform_feedback_manager_->RemoveBoundBuffer(buffer);
RemoveBuffer(client_ids[ii]);
}
}
@@ -3673,7 +3746,24 @@ 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) {
+ 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(
+ GL_TRANSFORM_FEEDBACK);
+ state_.bound_transform_feedback =
+ state_.default_transform_feedback.get();
+ }
+ RemoveTransformFeedback(client_ids[ii]);
+ }
+ }
+}
bool GLES2DecoderImpl::MakeCurrent() {
if (!context_.get())
@@ -4075,23 +4165,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_);
@@ -4186,6 +4278,14 @@ void GLES2DecoderImpl::Destroy(bool have_context) {
vertex_array_manager_.reset();
}
+ if (transform_feedback_manager_.get()) {
+ if (!have_context) {
+ transform_feedback_manager_->MarkContextLost();
+ }
+ transform_feedback_manager_->Destroy();
+ transform_feedback_manager_.reset();
+ }
+
if (image_manager_.get()) {
image_manager_->Destroy(have_context);
image_manager_.reset();
@@ -4714,7 +4814,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: {
@@ -4785,17 +4890,36 @@ 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(
+ 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,
@@ -5121,6 +5245,89 @@ 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;
+ }
+
+ 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);
+ if (transform_feedback == state_.bound_transform_feedback.get())
+ return;
+ if (state_.bound_transform_feedback->active() &&
+ !state_.bound_transform_feedback->paused()) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
+ "currently bound transform feedback is active");
+ return;
+ }
+ LogClientServiceForInfo(transform_feedback, client_id, function_name);
+ transform_feedback->DoBindTransformFeedback(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()) {
@@ -8824,6 +9031,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->has_been_bound();
+}
+
void GLES2DecoderImpl::DoAttachShader(
GLuint program_client_id, GLint shader_client_id) {
Program* program = GetProgramInfoNotShader(
@@ -13254,6 +13467,10 @@ void GLES2DecoderImpl::MarkContextLost(error::ContextLostReason reason) {
context_lost_reason_ = reason;
current_decoder_error_ = error::kLostContext;
context_was_lost_ = true;
+
+ if (transform_feedback_manager_.get()) {
+ transform_feedback_manager_->MarkContextLost();
+ }
}
bool GLES2DecoderImpl::CheckResetStatus() {
« no previous file with comments | « gpu/command_buffer/service/gles2_cmd_decoder.h ('k') | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698