summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gles2_cmd_decoder.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc398
1 files changed, 392 insertions, 6 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index bc84352..3d68326 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -298,6 +298,9 @@ class VertexAttribManager {
class VertexAttribInfo {
public:
typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
+ struct Vec4 {
+ float v[4];
+ };
VertexAttribInfo()
: index_(0),
@@ -305,8 +308,14 @@ class VertexAttribManager {
size_(4),
type_(GL_FLOAT),
offset_(0),
+ normalized_(GL_FALSE),
+ gl_stride_(0),
real_stride_(16),
list_(NULL) {
+ value_.v[0] = 0.0f;
+ value_.v[1] = 0.0f;
+ value_.v[2] = 0.0f;
+ value_.v[3] = 1.0f;
}
// Returns true if this VertexAttrib can access index.
@@ -324,16 +333,36 @@ class VertexAttribManager {
return index_;
}
+ GLint size() const {
+ return size_;
+ }
+
+ GLenum type() const {
+ return type_;
+ }
+
+ GLboolean normalized() const {
+ return normalized_;
+ }
+
+ GLsizei gl_stride() const {
+ return gl_stride_;
+ }
+
void SetInfo(
BufferManager::BufferInfo* buffer,
GLint size,
GLenum type,
+ GLboolean normalized,
+ GLsizei gl_stride,
GLsizei real_stride,
GLsizei offset) {
DCHECK_GT(real_stride, 0);
buffer_ = buffer;
size_ = size;
type_ = type;
+ normalized_ = normalized;
+ gl_stride_ = gl_stride;
real_stride_ = real_stride;
offset_ = offset;
}
@@ -346,6 +375,14 @@ class VertexAttribManager {
return enabled_;
}
+ void set_value(const Vec4& value) {
+ value_ = value;
+ }
+
+ const Vec4& value() const {
+ return value_;
+ }
+
private:
friend class VertexAttribManager;
@@ -383,11 +420,19 @@ class VertexAttribManager {
// The offset into the buffer.
GLsizei offset_;
+ GLboolean normalized_;
+
+ // The stride passed to glVertexAttribPointer.
+ GLsizei gl_stride_;
+
// The stride that will be used to access the buffer. This is the actual
// stide, NOT the GL bogus stride. In other words there is never a stride
// of 0.
GLsizei real_stride_;
+ // The current value of the attrib.
+ Vec4 value_;
+
// The buffer bound to this attribute.
BufferManager::BufferInfo::Ref buffer_;
@@ -413,8 +458,10 @@ class VertexAttribManager {
}
VertexAttribInfo* GetVertexAttribInfo(GLuint index) {
- DCHECK(index < max_vertex_attribs_);
- return &vertex_attrib_infos_[index];
+ if (index < max_vertex_attribs_) {
+ return &vertex_attrib_infos_[index];
+ }
+ return NULL;
}
private:
@@ -867,6 +914,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Wrapper for glGetShaderiv
void DoGetShaderiv(GLuint shader, GLenum pname, GLint* params);
+ // Wrappers for glGetVertexAttrib.
+ void DoGetVertexAttribfv(GLuint index, GLenum pname, GLfloat *params);
+ void DoGetVertexAttribiv(GLuint index, GLenum pname, GLint *params);
+
// Wrappers for glIsXXX functions.
bool DoIsBuffer(GLuint client_id);
bool DoIsFramebuffer(GLuint client_id);
@@ -906,6 +957,17 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
void DoUniform3fv(GLint location, GLsizei count, const GLfloat* value);
void DoUniform4fv(GLint location, GLsizei count, const GLfloat* value);
+ // Wrappers for glVertexAttrib??
+ void DoVertexAttrib1f(GLuint index, GLfloat v0);
+ void DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1);
+ void DoVertexAttrib3f(GLuint index, GLfloat v0, GLfloat v1, GLfloat v2);
+ void DoVertexAttrib4f(
+ GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ void DoVertexAttrib1fv(GLuint index, const GLfloat *v);
+ void DoVertexAttrib2fv(GLuint index, const GLfloat *v);
+ void DoVertexAttrib3fv(GLuint index, const GLfloat *v);
+ void DoVertexAttrib4fv(GLuint index, const GLfloat *v);
+
// Wrapper for glUseProgram
void DoUseProgram(GLuint program);
@@ -935,6 +997,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Checks if the current program and vertex attributes are valid for drawing.
bool IsDrawValid(GLuint max_vertex_accessed);
+ // Returns true if attrib0 was simulated.
+ bool SimulateAttrib0(GLuint max_vertex_accessed);
+ void RestoreStateForSimulatedAttrib0();
+
void SetBlackTextureForNonRenderableTextures(
bool* has_non_renderable_textures);
void RestoreStateForNonRenderableTextures();
@@ -1038,6 +1104,15 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// Class that manages vertex attribs.
VertexAttribManager vertex_attrib_manager_;
+ // The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
+ GLuint attrib_0_buffer_id_;
+
+ // The value currently in attrib_0.
+ VertexAttribManager::VertexAttribInfo::Vec4 attrib_0_value_;
+
+ // The size of attrib 0.
+ GLsizei attrib_0_size_;
+
// Current active texture by 0 - n index.
// In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
// be 2.
@@ -1337,11 +1412,17 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
util_(0), // TODO(gman): Set to actual num compress texture formats.
pack_alignment_(4),
unpack_alignment_(4),
+ attrib_0_buffer_id_(0),
+ attrib_0_size_(0),
active_texture_unit_(0),
black_2d_texture_id_(0),
black_cube_texture_id_(0),
anti_aliased_(false),
use_shader_translator_(true) {
+ attrib_0_value_.v[0] = 0.0f;
+ attrib_0_value_.v[1] = 0.0f;
+ attrib_0_value_.v[2] = 0.0f;
+ attrib_0_value_.v[3] = 1.0f;
}
bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
@@ -1379,6 +1460,13 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
}
vertex_attrib_manager_.Initialize(group_->max_vertex_attribs());
+ // We have to enable vertex array 0 on OpenGL or it won't render. Note that
+ // OpenGL ES 2.0 does not have this issue.
+ glEnableVertexAttribArray(0);
+ glGenBuffersARB(1, &attrib_0_buffer_id_);
+ glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
+ glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
texture_units_.reset(
new TextureUnit[group_->max_texture_units()]);
@@ -1774,6 +1862,16 @@ void GLES2DecoderImpl::Destroy() {
if (context_) {
MakeCurrent();
+ if (black_2d_texture_id_) {
+ glDeleteTextures(1, &black_2d_texture_id_);
+ }
+ if (black_cube_texture_id_) {
+ glDeleteTextures(1, &black_cube_texture_id_);
+ }
+ if (attrib_0_buffer_id_) {
+ glDeleteBuffersARB(1, &attrib_0_buffer_id_);
+ }
+
// Remove the saved frame buffer mapping from the parent decoder. The
// parent pointer is a weak pointer so it will be null if the parent has
// already been destroyed.
@@ -2057,7 +2155,9 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) {
void GLES2DecoderImpl::DoDisableVertexAttribArray(GLuint index) {
if (vertex_attrib_manager_.Enable(index, false)) {
- glDisableVertexAttribArray(index);
+ if (index != 0) {
+ glDisableVertexAttribArray(index);
+ }
} else {
SetGLError(GL_INVALID_VALUE,
"glDisableVertexAttribArray: index out of range");
@@ -2499,11 +2599,15 @@ void GLES2DecoderImpl::DoDrawArrays(
GLenum mode, GLint first, GLsizei count) {
if (IsDrawValid(first + count - 1)) {
bool has_non_renderable_textures;
+ bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
SetBlackTextureForNonRenderableTextures(&has_non_renderable_textures);
glDrawArrays(mode, first, count);
if (has_non_renderable_textures) {
RestoreStateForNonRenderableTextures();
}
+ if (simulated_attrib_0) {
+ RestoreStateForSimulatedAttrib0();
+ }
}
}
@@ -2938,7 +3042,64 @@ bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
}
}
return true;
-};
+}
+
+bool GLES2DecoderImpl::SimulateAttrib0(GLuint max_vertex_accessed) {
+#if !defined(GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2)
+ const VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(0);
+ // If it's enabled or it's not used then we don't need to do anything.
+ if (info->enabled() || !current_program_->GetAttribInfoByLocation(0)) {
+ return false;
+ }
+
+ typedef VertexAttribManager::VertexAttribInfo::Vec4 Vec4;
+
+ glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
+
+ // Make a buffer with a single repeated vec4 value enough to
+ // simulate the constant value that is supposed to be here.
+ // This is required to emulate GLES2 on GL.
+ GLsizei num_vertices = max_vertex_accessed + 1;
+ GLsizei size_needed = num_vertices * sizeof(Vec4); // NOLINT
+ if (size_needed > attrib_0_size_ ||
+ info->value().v[0] != attrib_0_value_.v[0] ||
+ info->value().v[1] != attrib_0_value_.v[1] ||
+ info->value().v[2] != attrib_0_value_.v[2] ||
+ info->value().v[3] != attrib_0_value_.v[3]) {
+ scoped_array<Vec4> temp(new Vec4[num_vertices]);
+ for (GLsizei ii = 0; ii < num_vertices; ++ii) {
+ temp[ii] = info->value();
+ }
+ glBufferData(
+ GL_ARRAY_BUFFER,
+ size_needed,
+ &temp[0].v[0],
+ GL_DYNAMIC_DRAW);
+ attrib_0_value_ = info->value();
+ attrib_0_size_ = size_needed;
+ }
+
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, NULL);
+
+ return true;
+#else // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
+ return false;
+#endif // GLES2_GPU_SERVICE_BACKEND_NATIVE_GLES2
+}
+
+void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
+ const VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(0);
+ 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);
+ glVertexAttribPointer(
+ 0, info->size(), info->type(), info->normalized(), info->gl_stride(),
+ ptr);
+ glBindBuffer(GL_ARRAY_BUFFER,
+ bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
+}
error::Error GLES2DecoderImpl::HandleDrawElements(
uint32 immediate_data_size, const gles2::DrawElements& c) {
@@ -2980,6 +3141,7 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
if (IsDrawValid(max_vertex_accessed)) {
bool has_non_renderable_textures;
+ bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
SetBlackTextureForNonRenderableTextures(
&has_non_renderable_textures);
const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
@@ -2987,6 +3149,9 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
if (has_non_renderable_textures) {
RestoreStateForNonRenderableTextures();
}
+ if (simulated_attrib_0) {
+ RestoreStateForSimulatedAttrib0();
+ }
}
return error::kNoError;
}
@@ -3243,6 +3408,226 @@ void GLES2DecoderImpl::DoValidateProgram(GLuint program_client_id) {
glValidateProgram(info->service_id());
}
+void GLES2DecoderImpl::DoGetVertexAttribfv(
+ GLuint index, GLenum pname, GLfloat* params) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glGetVertexAttribfv: index out of range");
+ return;
+ }
+ switch (pname) {
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
+ BufferManager::BufferInfo* buffer = info->buffer();
+ if (buffer && !buffer->IsDeleted()) {
+ GLuint client_id;
+ buffer_manager()->GetClientId(buffer->service_id(), &client_id);
+ *params = static_cast<GLfloat>(client_id);
+ }
+ break;
+ }
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = static_cast<GLfloat>(info->enabled());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = static_cast<GLfloat>(info->size());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = static_cast<GLfloat>(info->gl_stride());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = static_cast<GLfloat>(info->type());
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = static_cast<GLfloat>(info->normalized());
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB:
+ params[0] = info->value().v[0];
+ params[1] = info->value().v[1];
+ params[2] = info->value().v[2];
+ params[3] = info->value().v[3];
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void GLES2DecoderImpl::DoGetVertexAttribiv(
+ GLuint index, GLenum pname, GLint* params) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glGetVertexAttribiv: index out of range");
+ return;
+ }
+ switch (pname) {
+ case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: {
+ BufferManager::BufferInfo* buffer = info->buffer();
+ if (buffer && !buffer->IsDeleted()) {
+ GLuint client_id;
+ buffer_manager()->GetClientId(buffer->service_id(), &client_id);
+ *params = client_id;
+ }
+ break;
+ }
+ case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
+ *params = info->enabled();
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_SIZE:
+ *params = info->size();
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
+ *params = info->gl_stride();
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_TYPE:
+ *params = info->type();
+ break;
+ case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
+ *params = static_cast<GLint>(info->normalized());
+ break;
+ case GL_CURRENT_VERTEX_ATTRIB:
+ params[0] = static_cast<GLint>(info->value().v[0]);
+ params[1] = static_cast<GLint>(info->value().v[1]);
+ params[2] = static_cast<GLint>(info->value().v[2]);
+ params[3] = static_cast<GLint>(info->value().v[3]);
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+}
+
+void GLES2DecoderImpl::DoVertexAttrib1f(GLuint index, GLfloat v0) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib1f: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v0;
+ value.v[1] = 0.0f;
+ value.v[2] = 0.0f;
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib1f(index, v0);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib2f(GLuint index, GLfloat v0, GLfloat v1) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib2f: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v0;
+ value.v[1] = v1;
+ value.v[2] = 0.0f;
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib2f(index, v0, v1);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib3f(
+ GLuint index, GLfloat v0, GLfloat v1, GLfloat v2) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib3f: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v0;
+ value.v[1] = v1;
+ value.v[2] = v2;
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib3f(index, v0, v1, v2);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib4f(
+ GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib4f: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v0;
+ value.v[1] = v1;
+ value.v[2] = v2;
+ value.v[3] = v3;
+ info->set_value(value);
+ glVertexAttrib4f(index, v0, v1, v2, v3);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib1fv(GLuint index, const GLfloat* v) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib1fv: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v[0];
+ value.v[1] = 0.0f;
+ value.v[2] = 0.0f;
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib1fv(index, v);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib2fv(GLuint index, const GLfloat* v) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib2fv: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v[0];
+ value.v[1] = v[1];
+ value.v[2] = 0.0f;
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib2fv(index, v);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib3fv(GLuint index, const GLfloat* v) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib3fv: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v[0];
+ value.v[1] = v[1];
+ value.v[2] = v[2];
+ value.v[3] = 1.0f;
+ info->set_value(value);
+ glVertexAttrib3fv(index, v);
+}
+
+void GLES2DecoderImpl::DoVertexAttrib4fv(GLuint index, const GLfloat* v) {
+ VertexAttribManager::VertexAttribInfo* info =
+ vertex_attrib_manager_.GetVertexAttribInfo(index);
+ if (!info) {
+ SetGLError(GL_INVALID_VALUE, "glVertexAttrib4fv: index out of range");
+ return;
+ }
+ VertexAttribManager::VertexAttribInfo::Vec4 value;
+ value.v[0] = v[0];
+ value.v[1] = v[1];
+ value.v[2] = v[2];
+ value.v[3] = v[3];
+ info->set_value(value);
+ glVertexAttrib4fv(index, v);
+}
+
error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
uint32 immediate_data_size, const gles2::VertexAttribPointer& c) {
if (!bound_array_buffer_ || bound_array_buffer_->IsDeleted()) {
@@ -3289,7 +3674,6 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
}
GLsizei component_size =
GLES2Util::GetGLTypeSizeForTexturesAndBuffers(type);
- GLsizei real_stride = stride != 0 ? stride : component_size * size;
if (offset % component_size > 0) {
SetGLError(GL_INVALID_VALUE,
"glVertexAttribPointer: stride not valid for type");
@@ -3299,7 +3683,9 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
bound_array_buffer_,
size,
type,
- real_stride,
+ normalized,
+ stride,
+ stride != 0 ? stride : component_size * size,
offset);
glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
return error::kNoError;