summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gpu/GLES2/gles2_command_buffer.h2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc2
-rw-r--r--gpu/command_buffer/service/buffer_manager.cc11
-rw-r--r--gpu/command_buffer/service/buffer_manager.h3
-rw-r--r--gpu/command_buffer/service/buffer_manager_unittest.cc18
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc237
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc19
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h1
8 files changed, 249 insertions, 44 deletions
diff --git a/gpu/GLES2/gles2_command_buffer.h b/gpu/GLES2/gles2_command_buffer.h
index 3f6b39d..30bc7a7 100644
--- a/gpu/GLES2/gles2_command_buffer.h
+++ b/gpu/GLES2/gles2_command_buffer.h
@@ -11,6 +11,8 @@
// constants for CommandBufferEnable command.
#define PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS \
"pepper3d_allow_buffers_on_multiple_targets"
+#define PEPPER3D_SUPPORT_FIXED_ATTRIBS \
+ "pepper3d_support_fixed_attribs"
// TODO(gman): remove this
#define PEPPER3D_SKIP_GLSL_TRANSLATION \
"pepper3d_skip_glsl_translation"
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc
index b9806ab..e4f9c8c 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils.cc
+++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -444,6 +444,8 @@ size_t GLES2Util::GetGLTypeSizeForTexturesAndBuffers(uint32 type) {
return sizeof(GLuint); // NOLINT
case GL_FLOAT:
return sizeof(GLfloat); // NOLINT
+ case GL_FIXED:
+ return sizeof(GLfixed); // NOLINT
default:
return 0;
}
diff --git a/gpu/command_buffer/service/buffer_manager.cc b/gpu/command_buffer/service/buffer_manager.cc
index 70c5ccb..07a9753 100644
--- a/gpu/command_buffer/service/buffer_manager.cc
+++ b/gpu/command_buffer/service/buffer_manager.cc
@@ -79,8 +79,7 @@ void BufferManager::BufferInfo::SetSize(GLsizeiptr size, bool shadow) {
bool BufferManager::BufferInfo::SetRange(
GLintptr offset, GLsizeiptr size, const GLvoid * data) {
DCHECK(!IsDeleted());
- if (offset + size < offset ||
- offset + size > size_) {
+ if (offset + size < offset || offset + size > size_) {
return false;
}
if (shadowed_) {
@@ -90,6 +89,14 @@ bool BufferManager::BufferInfo::SetRange(
return true;
}
+const void* BufferManager::BufferInfo::GetRange(
+ GLintptr offset, GLsizeiptr size) const {
+ if (!shadowed_ || (offset + size < offset || offset + size > size_)) {
+ return NULL;
+ }
+ return shadow_.get() + offset;
+}
+
void BufferManager::BufferInfo::ClearCache() {
range_set_.clear();
}
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h
index 86f6bb8..81ad2af 100644
--- a/gpu/command_buffer/service/buffer_manager.h
+++ b/gpu/command_buffer/service/buffer_manager.h
@@ -49,6 +49,9 @@ class BufferManager {
bool GetMaxValueForRange(GLuint offset, GLsizei count, GLenum type,
GLuint* max_value);
+ // Returns a pointer to shadowed data.
+ const void* GetRange(GLintptr offset, GLsizeiptr size) const;
+
bool IsDeleted() {
return service_id_ == 0;
}
diff --git a/gpu/command_buffer/service/buffer_manager_unittest.cc b/gpu/command_buffer/service/buffer_manager_unittest.cc
index 3f4a66b..37bd00f 100644
--- a/gpu/command_buffer/service/buffer_manager_unittest.cc
+++ b/gpu/command_buffer/service/buffer_manager_unittest.cc
@@ -101,6 +101,24 @@ TEST_F(BufferManagerTest, SetRange) {
EXPECT_FALSE(info->SetRange(0, sizeof(data) + 1, data));
}
+TEST_F(BufferManagerTest, GetRange) {
+ const GLuint kClientBufferId = 1;
+ const GLuint kServiceBufferId = 11;
+ const uint8 data[] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+ manager_.CreateBufferInfo(kClientBufferId, kServiceBufferId);
+ BufferManager::BufferInfo* info = manager_.GetBufferInfo(kClientBufferId);
+ ASSERT_TRUE(info != NULL);
+ manager_.SetTarget(info, GL_ELEMENT_ARRAY_BUFFER);
+ manager_.SetSize(info, sizeof(data));
+ const char* buf = static_cast<const char*>(info->GetRange(0, sizeof(data)));
+ ASSERT_TRUE(buf != NULL);
+ const char* buf1 =
+ static_cast<const char*>(info->GetRange(1, sizeof(data) - 1));
+ EXPECT_EQ(buf + 1, buf1);
+ EXPECT_TRUE(info->GetRange(sizeof(data), 1) == NULL);
+ EXPECT_TRUE(info->GetRange(0, sizeof(data) + 1) == NULL);
+}
+
TEST_F(BufferManagerTest, GetMaxValueForRangeUint8) {
const GLuint kClientBufferId = 1;
const GLuint kServiceBufferId = 11;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index c8883af..5927914 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -448,28 +448,6 @@ class VertexAttribManager {
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;
- }
-
- void ClearBuffer() {
- buffer_ = NULL;
- }
-
bool enabled() const {
return enabled_;
}
@@ -504,6 +482,24 @@ class VertexAttribManager {
list_ = new_list;
}
+ 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;
+ }
+
// The index of this attrib.
GLuint index_;
@@ -545,13 +541,18 @@ class VertexAttribManager {
typedef std::list<VertexAttribInfo*> VertexAttribInfoList;
VertexAttribManager()
- : max_vertex_attribs_(0) {
+ : max_vertex_attribs_(0),
+ num_fixed_attribs_(0) {
}
void Initialize(uint32 num_vertex_attribs);
bool Enable(GLuint index, bool enable);
+ bool HaveFixedAttribs() const {
+ return num_fixed_attribs_ != 0;
+ }
+
const VertexAttribInfoList& GetEnabledVertexAttribInfos() const {
return enabled_vertex_attribs_;
}
@@ -563,9 +564,35 @@ class VertexAttribManager {
return NULL;
}
+ void SetAttribInfo(
+ GLuint index,
+ BufferManager::BufferInfo* buffer,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei gl_stride,
+ GLsizei real_stride,
+ GLsizei offset) {
+ VertexAttribInfo* info = GetVertexAttribInfo(index);
+ if (info) {
+ if (info->type() == GL_FIXED) {
+ --num_fixed_attribs_;
+ }
+ if (type == GL_FIXED) {
+ ++num_fixed_attribs_;
+ }
+ info->SetInfo(
+ buffer, size, type, normalized, gl_stride, real_stride, offset);
+ }
+ }
+
+
private:
uint32 max_vertex_attribs_;
+ // number of attribs using type GL_FIXED.
+ int num_fixed_attribs_;
+
// Info for each vertex attribute saved so we can check at glDrawXXX time
// if it is safe to draw.
scoped_array<VertexAttribInfo> vertex_attrib_infos_;
@@ -1204,6 +1231,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
bool SetBlackTextureForNonRenderableTextures();
void RestoreStateForNonRenderableTextures();
+ // Returns true if GL_FIXED attribs were simulated.
+ bool SimulateFixedAttribs(GLuint max_vertex_accessed, bool* simulated);
+ void RestoreStateForSimulatedFixedAttribs();
+
// Gets the buffer id for a given target.
BufferManager::BufferInfo* GetBufferInfoForTarget(GLenum target) {
DCHECK(target == GL_ARRAY_BUFFER || target == GL_ELEMENT_ARRAY_BUFFER);
@@ -1328,6 +1359,12 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>,
// The size of attrib 0.
GLsizei attrib_0_size_;
+ // The buffer used to simulate GL_FIXED attribs.
+ GLuint fixed_attrib_buffer_id_;
+
+ // The size of fiixed attrib buffer.
+ GLsizei fixed_attrib_buffer_size_;
+
// Current active texture by 0 - n index.
// In other words, if we call glActiveTexture(GL_TEXTURE2) this value would
// be 2.
@@ -1695,6 +1732,8 @@ GLES2DecoderImpl::GLES2DecoderImpl(ContextGroup* group)
unpack_alignment_(4),
attrib_0_buffer_id_(0),
attrib_0_size_(0),
+ fixed_attrib_buffer_id_(0),
+ fixed_attrib_buffer_size_(0),
active_texture_unit_(0),
clear_red_(0),
clear_green_(0),
@@ -1777,6 +1816,7 @@ bool GLES2DecoderImpl::Initialize(gfx::GLContext* context,
glBindBuffer(GL_ARRAY_BUFFER, attrib_0_buffer_id_);
glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, NULL);
glBindBuffer(GL_ARRAY_BUFFER, 0);
+ glGenBuffersARB(1, &fixed_attrib_buffer_id_);
texture_units_.reset(
new TextureUnit[group_->max_texture_units()]);
@@ -2405,6 +2445,9 @@ void GLES2DecoderImpl::Destroy() {
if (attrib_0_buffer_id_) {
glDeleteBuffersARB(1, &attrib_0_buffer_id_);
}
+ if (fixed_attrib_buffer_id_) {
+ glDeleteBuffersARB(1, &fixed_attrib_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
@@ -3216,12 +3259,19 @@ void GLES2DecoderImpl::DoDrawArrays(
return;
}
- if (IsDrawValid(first + count - 1)) {
- bool simulated_attrib_0 = SimulateAttrib0(first + count - 1);
- bool textures_set = SetBlackTextureForNonRenderableTextures();
- glDrawArrays(mode, first, count);
- if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ GLuint max_vertex_accessed = first + count - 1;
+ if (IsDrawValid(max_vertex_accessed)) {
+ bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
+ bool simulated_fixed_attribs = false;
+ if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
+ bool textures_set = SetBlackTextureForNonRenderableTextures();
+ glDrawArrays(mode, first, count);
+ if (textures_set) {
+ RestoreStateForNonRenderableTextures();
+ }
+ if (simulated_fixed_attribs) {
+ RestoreStateForSimulatedFixedAttribs();
+ }
}
if (simulated_attrib_0) {
RestoreStateForSimulatedAttrib0();
@@ -3877,7 +3927,7 @@ bool GLES2DecoderImpl::IsDrawValid(GLuint max_vertex_accessed) {
const VertexAttribManager::VertexAttribInfoList& infos =
vertex_attrib_manager_.GetEnabledVertexAttribInfos();
for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
- infos.begin(); it != infos.end(); ++it) {
+ infos.begin(); it != infos.end(); ++it) {
const VertexAttribManager::VertexAttribInfo* info = *it;
const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
current_program_->GetAttribInfoByLocation(info->index());
@@ -3958,6 +4008,98 @@ void GLES2DecoderImpl::RestoreStateForSimulatedAttrib0() {
bound_array_buffer_ ? bound_array_buffer_->service_id() : 0);
}
+bool GLES2DecoderImpl::SimulateFixedAttribs(
+ GLuint max_vertex_accessed, bool* simulated) {
+ DCHECK(simulated);
+ *simulated = false;
+ if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2)
+ return true;
+
+ if (!vertex_attrib_manager_.HaveFixedAttribs()) {
+ return true;
+ }
+
+ // NOTE: we could be smart and try to check if a buffer is used
+ // twice in 2 different attribs, find the overlapping parts and therefore
+ // duplicate the minimum amount of data but this whole code path is not meant
+ // to be used normally. It's just here to pass that OpenGL ES 2.0 conformance
+ // tests so we just add to the buffer attrib used.
+
+ // Compute the number of elements needed.
+ int num_vertices = max_vertex_accessed + 1;
+ int elements_needed = 0;
+ const VertexAttribManager::VertexAttribInfoList& infos =
+ vertex_attrib_manager_.GetEnabledVertexAttribInfos();
+ for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
+ infos.begin(); it != infos.end(); ++it) {
+ const VertexAttribManager::VertexAttribInfo* info = *it;
+ const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
+ current_program_->GetAttribInfoByLocation(info->index());
+ if (attrib_info &&
+ info->CanAccess(max_vertex_accessed) &&
+ info->type() == GL_FIXED) {
+ int elements_used = 0;
+ if (!SafeMultiply(
+ static_cast<int>(num_vertices),
+ info->size(), &elements_used) ||
+ !SafeAdd(elements_needed, elements_used, &elements_needed)) {
+ SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
+ return false;
+ }
+ }
+ }
+
+ const int kSizeOfFloat = sizeof(float); // NOLINT
+ int size_needed = 0;
+ if (!SafeMultiply(elements_needed, kSizeOfFloat, &size_needed)) {
+ SetGLError(GL_OUT_OF_MEMORY, "glDrawXXX: simulating GL_FIXED attribs");
+ return false;
+ }
+
+
+ glBindBuffer(GL_ARRAY_BUFFER, fixed_attrib_buffer_id_);
+ if (size_needed > fixed_attrib_buffer_size_) {
+ glBufferData(GL_ARRAY_BUFFER, size_needed, NULL, GL_DYNAMIC_DRAW);
+ }
+
+ // Copy the elements and convert to float
+ GLintptr offset = 0;
+ for (VertexAttribManager::VertexAttribInfoList::const_iterator it =
+ infos.begin(); it != infos.end(); ++it) {
+ const VertexAttribManager::VertexAttribInfo* info = *it;
+ const ProgramManager::ProgramInfo::VertexAttribInfo* attrib_info =
+ current_program_->GetAttribInfoByLocation(info->index());
+ if (attrib_info &&
+ info->CanAccess(max_vertex_accessed) &&
+ info->type() == GL_FIXED) {
+ int num_elements = info->size() * kSizeOfFloat;
+ int size = num_elements * num_vertices;
+ scoped_array<float> data(new float[size]);
+ const int32* src = reinterpret_cast<const int32 *>(
+ info->buffer()->GetRange(info->offset(), size));
+ const int32* end = src + num_elements;
+ float* dst = data.get();
+ while (src != end) {
+ *dst++ = static_cast<float>(*src++) / 65536.0f;
+ }
+ glBufferSubData(GL_ARRAY_BUFFER, offset, size, data.get());
+ glVertexAttribPointer(
+ info->index(), info->size(), GL_FLOAT, false, 0,
+ reinterpret_cast<GLvoid*>(offset));
+ offset += size;
+ }
+ }
+ *simulated = true;
+ return true;
+}
+
+void GLES2DecoderImpl::RestoreStateForSimulatedFixedAttribs() {
+ // There's no need to call glVertexAttribPointer because we shadow all the
+ // settings and passing GL_FIXED to it will not work.
+ 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) {
if (!bound_element_array_buffer_ ||
@@ -4002,11 +4144,17 @@ error::Error GLES2DecoderImpl::HandleDrawElements(
if (IsDrawValid(max_vertex_accessed)) {
bool simulated_attrib_0 = SimulateAttrib0(max_vertex_accessed);
- bool textures_set = SetBlackTextureForNonRenderableTextures();
- const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
- glDrawElements(mode, count, type, indices);
- if (textures_set) {
- RestoreStateForNonRenderableTextures();
+ bool simulated_fixed_attribs = false;
+ if (SimulateFixedAttribs(max_vertex_accessed, &simulated_fixed_attribs)) {
+ bool textures_set = SetBlackTextureForNonRenderableTextures();
+ const GLvoid* indices = reinterpret_cast<const GLvoid*>(offset);
+ glDrawElements(mode, count, type, indices);
+ if (textures_set) {
+ RestoreStateForNonRenderableTextures();
+ }
+ if (simulated_fixed_attribs) {
+ RestoreStateForSimulatedFixedAttribs();
+ }
}
if (simulated_attrib_0) {
RestoreStateForSimulatedAttrib0();
@@ -4540,7 +4688,8 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
"glVertexAttribPointer: stride not valid for type");
return error::kNoError;
}
- vertex_attrib_manager_.GetVertexAttribInfo(indx)->SetInfo(
+ vertex_attrib_manager_.SetAttribInfo(
+ indx,
bound_array_buffer_,
size,
type,
@@ -4548,7 +4697,9 @@ error::Error GLES2DecoderImpl::HandleVertexAttribPointer(
stride,
stride != 0 ? stride : component_size * size,
offset);
- glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+ if (type != GL_FIXED) {
+ glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+ }
return error::kNoError;
}
@@ -5745,6 +5896,18 @@ error::Error GLES2DecoderImpl::HandleCommandBufferEnable(
// TODO(gman): make this some kind of table to function pointer thingy.
if (feature_str.compare(PEPPER3D_ALLOW_BUFFERS_ON_MULTIPLE_TARGETS) == 0) {
buffer_manager()->set_allow_buffers_on_multiple_targets(true);
+ } else if (feature_str.compare(PEPPER3D_SUPPORT_FIXED_ATTRIBS) == 0) {
+ buffer_manager()->set_allow_buffers_on_multiple_targets(true);
+ // TODO(gman): decide how to remove the need for this const_cast.
+ // I could make validators_ non const but that seems bad as this is the only
+ // place it is needed. I could make some special friend class of validators
+ // just to allow this to set them. That seems silly. I could refactor this
+ // code to use the extension mechanism or the initialization attributes to
+ // turn this feature on. Given that the only real point of this is to make
+ // the conformance tests pass and given that there is lots of real work that
+ // needs to be done it seems like refactoring for one to one of those
+ // methods is a very low priority.
+ const_cast<Validators*>(validators_)->vertex_attrib_type.AddValue(GL_FIXED);
} else if (feature_str.compare(PEPPER3D_SKIP_GLSL_TRANSLATION) == 0) {
use_shader_translator_ = false;
} else {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index e253a73..1b082dd 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -50,12 +50,15 @@ void GLES2DecoderTestBase::InitDecoder(const char* extensions) {
EXPECT_CALL(*gl_, EnableVertexAttribArray(0))
.Times(1)
.RetiresOnSaturation();
- static GLuint attrib_ids[] = {
+ static GLuint attrib_0_id[] = {
kServiceAttrib0BufferId,
};
- EXPECT_CALL(*gl_, GenBuffersARB(arraysize(attrib_ids), _))
- .WillOnce(SetArrayArgument<1>(attrib_ids,
- attrib_ids + arraysize(attrib_ids)))
+ static GLuint fixed_attrib_buffer_id[] = {
+ kServiceFixedAttribBufferId,
+ };
+ EXPECT_CALL(*gl_, GenBuffersARB(arraysize(attrib_0_id), _))
+ .WillOnce(SetArrayArgument<1>(attrib_0_id,
+ attrib_0_id + arraysize(attrib_0_id)))
.RetiresOnSaturation();
EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, kServiceAttrib0BufferId))
.Times(1)
@@ -66,6 +69,11 @@ void GLES2DecoderTestBase::InitDecoder(const char* extensions) {
EXPECT_CALL(*gl_, BindBuffer(GL_ARRAY_BUFFER, 0))
.Times(1)
.RetiresOnSaturation();
+ EXPECT_CALL(*gl_, GenBuffersARB(arraysize(fixed_attrib_buffer_id), _))
+ .WillOnce(SetArrayArgument<1>(
+ fixed_attrib_buffer_id,
+ fixed_attrib_buffer_id + arraysize(fixed_attrib_buffer_id)))
+ .RetiresOnSaturation();
for (GLint tt = 0; tt < TestHelper::kNumTextureUnits; ++tt) {
EXPECT_CALL(*gl_, ActiveTexture(GL_TEXTURE0 + tt))
@@ -146,7 +154,7 @@ void GLES2DecoderTestBase::TearDown() {
// All Tests should have read all their GLErrors before getting here.
EXPECT_EQ(GL_NO_ERROR, GetGLError());
EXPECT_CALL(*gl_, DeleteBuffersARB(1, _))
- .Times(1)
+ .Times(2)
.RetiresOnSaturation();
decoder_->Destroy();
decoder_.reset();
@@ -394,6 +402,7 @@ const GLint GLES2DecoderTestBase::kMaxVaryingVectors;
const GLint GLES2DecoderTestBase::kMaxVertexUniformVectors;
const GLuint GLES2DecoderTestBase::kServiceAttrib0BufferId;
+const GLuint GLES2DecoderTestBase::kServiceFixedAttribBufferId;
const GLuint GLES2DecoderTestBase::kServiceBufferId;
const GLuint GLES2DecoderTestBase::kServiceFramebufferId;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
index d5981c7..a6c8cad 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h
@@ -49,6 +49,7 @@ class GLES2DecoderTestBase : public testing::Test {
static const GLint kMaxVertexUniformVectors = 128;
static const GLuint kServiceAttrib0BufferId = 801;
+ static const GLuint kServiceFixedAttribBufferId = 802;
static const GLuint kServiceBufferId = 301;
static const GLuint kServiceFramebufferId = 302;