summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer/service/gles2_cmd_decoder.cc
diff options
context:
space:
mode:
authorgman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-18 18:43:40 +0000
committergman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-18 18:43:40 +0000
commit8fbedc0f80187f0244b952979ee32396d84d4823 (patch)
treea584f7ac105bf685b4a3e91d5930e718a3ab7aae /gpu/command_buffer/service/gles2_cmd_decoder.cc
parentedb22cfd39987c08be44997d9f2bc75f7721ce13 (diff)
downloadchromium_src-8fbedc0f80187f0244b952979ee32396d84d4823.zip
chromium_src-8fbedc0f80187f0244b952979ee32396d84d4823.tar.gz
chromium_src-8fbedc0f80187f0244b952979ee32396d84d4823.tar.bz2
Adds support for GL_FIXED vertex attributes.
Similar to sharing VBOs for both index buffers and vertex buffers this support is off by default but is turned on in the OpenGL ES 2.0 conformance tests (another CL) We can decide how/if to expose it to Pepper later if we want to claim Pepper is Open GL ES 2.0 conformant. TEST=The GL_FIXED OpenGL ES 2.0 conformance tests passes BUG=none Review URL: http://codereview.chromium.org/5026003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66649 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/service/gles2_cmd_decoder.cc')
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc237
1 files changed, 200 insertions, 37 deletions
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 {