Skip to content

Commit

Permalink
A step in making it possible for WebGL to request no features
Browse files Browse the repository at this point in the history
and the add them in as extensions are enabled.

The idea is when WebGL inits it's context it will pass ""
to FeatureInfo::Initialize.  After that it can pass various
GL extension strings to FeatureInfo::AddFeatures
to turn on more features.

It can then call glGetString(GL_EXTENSIONS) to see if the
feature was turned on.

Questions: I started this CL trying to make it possible
so each context could have it's own FeatureInfo. I decided
against that. So that brings up the question, should I 
get rid of FeatureInfo and just put this stuff back on
ContextGroup or leave it as is?

If I leave it as is, should I move all the max_XXX stuff
on ContextGroup to FeatureInfo?

TEST=unit tests
BUG=none

Review URL: http://codereview.chromium.org/3413038

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61114 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
gman@chromium.org committed Sep 30, 2010
1 parent d15e56c commit 915a59a
Show file tree
Hide file tree
Showing 20 changed files with 1,081 additions and 786 deletions.
38 changes: 24 additions & 14 deletions gpu/command_buffer/client/gles2_implementation.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1144,22 +1144,32 @@ void GLES2Implementation::GetShaderPrecisionFormat(
}

const GLubyte* GLES2Implementation::GetString(GLenum name) {
const char* result;
GLStringMap::const_iterator it = gl_strings_.find(name);
if (it != gl_strings_.end()) {
result = it->second.c_str();
} else {
// Clear the bucket so if we the command fails nothing will be in it.
helper_->SetBucketSize(kResultBucketId, 0);
helper_->GetString(name, kResultBucketId);
std::string str;
if (GetBucketAsString(kResultBucketId, &str)) {
std::pair<GLStringMap::const_iterator, bool> insert_result =
gl_strings_.insert(std::make_pair(name, str));
const char* result = NULL;
// Clear the bucket so if the command fails nothing will be in it.
helper_->SetBucketSize(kResultBucketId, 0);
helper_->GetString(name, kResultBucketId);
std::string str;
if (GetBucketAsString(kResultBucketId, &str)) {
// Because of WebGL the extensions can change. We have to cache each
// unique result since we don't know when the client will stop referring to
// a previous one it queries.
GLStringMap::iterator it = gl_strings_.find(name);
if (it == gl_strings_.end()) {
std::set<std::string> strings;
std::pair<GLStringMap::iterator, bool> insert_result =
gl_strings_.insert(std::make_pair(name, strings));
GPU_DCHECK(insert_result.second);
result = insert_result.first->second.c_str();
it = insert_result.first;
}
std::set<std::string>& string_set = it->second;
std::set<std::string>::const_iterator sit = string_set.find(str);
if (sit != string_set.end()) {
result = sit->c_str();
} else {
result = NULL;
std::pair<std::set<std::string>::const_iterator, bool> insert_result =
string_set.insert(str);
GPU_DCHECK(insert_result.second);
result = insert_result.first->c_str();
}
}
return reinterpret_cast<const GLubyte*>(result);
Expand Down
3 changes: 2 additions & 1 deletion gpu/command_buffer/client/gles2_implementation.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <GLES2/gl2.h>

#include <map>
#include <set>
#include <string>
#include <vector>

Expand Down Expand Up @@ -375,7 +376,7 @@ class GLES2Implementation {

// Map of GLenum to Strings for glGetString. We need to cache these because
// the pointer passed back to the client has to remain valid for eternity.
typedef std::map<uint32, std::string> GLStringMap;
typedef std::map<uint32, std::set<std::string> > GLStringMap;
GLStringMap gl_strings_;

typedef std::map<const void*, MappedBuffer> MappedBufferMap;
Expand Down
193 changes: 8 additions & 185 deletions gpu/command_buffer/service/context_group.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,189 +43,19 @@ static void GetIntegerv(GLenum pname, uint32* var) {
*var = value;
}

bool ContextGroup::Initialize() {
if (initialized_) {
return true;
}

// Figure out what extensions to turn on.
const char* extensions =
reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
bool npot_ok = false;

AddExtensionString("GL_CHROMIUM_map_sub");

// Check if we should allow GL_EXT_texture_compression_dxt1 and
// GL_EXT_texture_compression_s3tc.
bool enable_dxt1 = false;
bool enable_s3tc = false;

if (strstr(extensions, "GL_EXT_texture_compression_dxt1")) {
enable_dxt1 = true;
}
if (strstr(extensions, "GL_EXT_texture_compression_s3tc")) {
enable_dxt1 = true;
enable_s3tc = true;
}

if (enable_dxt1) {
AddExtensionString("GL_EXT_texture_compression_dxt1");
validators_.compressed_texture_format.AddValue(
GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
validators_.compressed_texture_format.AddValue(
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
}

if (enable_s3tc) {
AddExtensionString("GL_EXT_texture_compression_s3tc");
validators_.compressed_texture_format.AddValue(
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
validators_.compressed_texture_format.AddValue(
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
}

// Check if we should enable GL_EXT_texture_filter_anisotropic.
if (strstr(extensions, "GL_EXT_texture_filter_anisotropic")) {
AddExtensionString("GL_EXT_texture_filter_anisotropic");
validators_.texture_parameter.AddValue(
GL_TEXTURE_MAX_ANISOTROPY_EXT);
validators_.g_l_state.AddValue(
GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT);
}

// Check if we should support GL_OES_packed_depth_stencil and/or
// GL_GOOGLE_depth_texture.
// NOTE: GL_OES_depth_texture requires support for depth
// cubemaps. GL_ARB_depth_texture requires other features that
// GL_OES_packed_depth_stencil does not provide. Therefore we made up
// GL_GOOGLE_depth_texture.
bool enable_depth_texture = false;
if (strstr(extensions, "GL_ARB_depth_texture") ||
strstr(extensions, "GL_OES_depth_texture")) {
enable_depth_texture = true;
AddExtensionString("GL_GOOGLE_depth_texture");
validators_.texture_internal_format.AddValue(GL_DEPTH_COMPONENT);
validators_.texture_format.AddValue(GL_DEPTH_COMPONENT);
validators_.pixel_type.AddValue(GL_UNSIGNED_SHORT);
validators_.pixel_type.AddValue(GL_UNSIGNED_INT);
}
// TODO(gman): Add depth types fo ElementsPerGroup and BytesPerElement

if (strstr(extensions, "GL_EXT_packed_depth_stencil") ||
strstr(extensions, "GL_OES_packed_depth_stencil")) {
AddExtensionString("GL_OES_packed_depth_stencil");
if (enable_depth_texture) {
validators_.texture_internal_format.AddValue(GL_DEPTH_STENCIL);
validators_.texture_format.AddValue(GL_DEPTH_STENCIL);
validators_.pixel_type.AddValue(GL_UNSIGNED_INT_24_8);
}
validators_.render_buffer_format.AddValue(GL_DEPTH24_STENCIL8);
}

bool enable_texture_format_bgra8888 = false;
bool enable_read_format_bgra = false;
// Check if we should allow GL_EXT_texture_format_BGRA8888
if (strstr(extensions, "GL_EXT_texture_format_BGRA8888") ||
strstr(extensions, "GL_APPLE_texture_format_BGRA8888")) {
enable_texture_format_bgra8888 = true;
}

if (strstr(extensions, "GL_EXT_bgra")) {
enable_texture_format_bgra8888 = true;
enable_read_format_bgra = true;
}

if (strstr(extensions, "GL_EXT_read_format_bgra")) {
enable_read_format_bgra = true;
}

if (enable_texture_format_bgra8888) {
AddExtensionString("GL_EXT_texture_format_BGRA8888");
validators_.texture_internal_format.AddValue(GL_BGRA_EXT);
validators_.texture_format.AddValue(GL_BGRA_EXT);
}

if (enable_read_format_bgra) {
AddExtensionString("GL_EXT_read_format_bgra");
validators_.read_pixel_format.AddValue(GL_BGRA_EXT);
}

// Check if we should allow GL_OES_texture_npot
if (strstr(extensions, "GL_ARB_texture_non_power_of_two") ||
strstr(extensions, "GL_OES_texture_npot")) {
AddExtensionString("GL_OES_texture_npot");
npot_ok = true;
}

// Check if we should allow GL_OES_texture_float, GL_OES_texture_half_float,
// GL_OES_texture_float_linear, GL_OES_texture_half_float_linear
bool enable_texture_float = false;
bool enable_texture_float_linear = false;
bool enable_texture_half_float = false;
bool enable_texture_half_float_linear = false;
if (strstr(extensions, "GL_ARB_texture_float")) {
enable_texture_float = true;
enable_texture_float_linear = true;
enable_texture_half_float = true;
enable_texture_half_float_linear = true;
} else {
if (strstr(extensions, "GL_OES_texture_float")) {
enable_texture_float = true;
if (strstr(extensions, "GL_OES_texture_float_linear")) {
enable_texture_float_linear = true;
}
}
if (strstr(extensions, "GL_OES_texture_half_float")) {
enable_texture_half_float = true;
if (strstr(extensions, "GL_OES_texture_half_float_linear")) {
enable_texture_half_float_linear = true;
}
}
}

if (enable_texture_float) {
validators_.pixel_type.AddValue(GL_FLOAT);
AddExtensionString("GL_OES_texture_float");
if (enable_texture_float_linear) {
AddExtensionString("GL_OES_texture_float_linear");
}
}

if (enable_texture_half_float) {
validators_.pixel_type.AddValue(GL_HALF_FLOAT_OES);
AddExtensionString("GL_OES_texture_half_float");
if (enable_texture_half_float_linear) {
AddExtensionString("GL_OES_texture_half_float_linear");
}
}

// Check for multisample support
if (strstr(extensions, "GL_EXT_framebuffer_multisample")) {
extension_flags_.ext_framebuffer_multisample = true;
validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT);
validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT);
validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT);
validators_.render_buffer_parameter.AddValue(GL_MAX_SAMPLES_EXT);
AddExtensionString("GL_EXT_framebuffer_multisample");
AddExtensionString("GL_EXT_framebuffer_blit");
}

if (strstr(extensions, "GL_OES_depth24") ||
gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
AddExtensionString("GL_OES_depth24");
validators_.render_buffer_format.AddValue(GL_DEPTH_COMPONENT24);
bool ContextGroup::Initialize(const char* allowed_features) {
if (initialized_) {
return true;
}

if (strstr(extensions, "GL_OES_standard_derivatives") ||
gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) {
AddExtensionString("GL_OES_standard_derivatives");
extension_flags_.oes_standard_derivatives = true;
if (!feature_info_.Initialize(allowed_features)) {
LOG(ERROR) << "ContextGroup::Initialize failed because FeatureInfo "
<< "initialization failed.";
return false;
}

// TODO(gman): Add support for these extensions.
// GL_OES_depth32
// GL_OES_element_index_uint

buffer_manager_.reset(new BufferManager());
framebuffer_manager_.reset(new FramebufferManager());
renderbuffer_manager_.reset(new RenderbufferManager());
Expand Down Expand Up @@ -253,10 +83,7 @@ bool ContextGroup::Initialize() {
GLint max_cube_map_texture_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
glGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &max_cube_map_texture_size);
texture_manager_.reset(new TextureManager(npot_ok,
enable_texture_float_linear,
enable_texture_half_float_linear,
max_texture_size,
texture_manager_.reset(new TextureManager(max_texture_size,
max_cube_map_texture_size));

GetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &max_texture_image_units_);
Expand Down Expand Up @@ -320,10 +147,6 @@ void ContextGroup::Destroy(bool have_context) {
}
}

void ContextGroup::AddExtensionString(const std::string& str) {
extensions_ += (extensions_.empty() ? "" : " ") + str;
}

IdAllocator* ContextGroup::GetIdAllocator(unsigned namespace_id) {
IdAllocatorMap::iterator it = id_namespaces_.find(namespace_id);
if (it != id_namespaces_.end()) {
Expand Down
39 changes: 7 additions & 32 deletions gpu/command_buffer/service/context_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "base/linked_ptr.h"
#include "base/scoped_ptr.h"
#include "gpu/command_buffer/service/gles2_cmd_validation.h"
#include "gpu/command_buffer/service/feature_info.h"

namespace gpu {

Expand All @@ -30,21 +31,11 @@ class TextureManager;
// resources.
class ContextGroup {
public:
struct ExtensionFlags {
ExtensionFlags()
: ext_framebuffer_multisample(false),
oes_standard_derivatives(false) {
}

bool ext_framebuffer_multisample;
bool oes_standard_derivatives;
};

ContextGroup();
~ContextGroup();

// This should only be called by GLES2Decoder.
bool Initialize();
bool Initialize(const char* allowed_features);

// Destroys all the resources. MUST be called before destruction.
void Destroy(bool have_context);
Expand Down Expand Up @@ -77,6 +68,10 @@ class ContextGroup {
return max_vertex_uniform_vectors_;
}

FeatureInfo* feature_info() {
return &feature_info_;
}

BufferManager* buffer_manager() const {
return buffer_manager_.get();
}
Expand All @@ -103,21 +98,7 @@ class ContextGroup {

IdAllocator* GetIdAllocator(unsigned namepsace_id);

const Validators* validators() const {
return &validators_;
}

const std::string& extensions() const {
return extensions_;
}

const ExtensionFlags& extension_flags() const {
return extension_flags_;
}

private:
void AddExtensionString(const std::string& str);

// Whether or not this context is initialized.
bool initialized_;

Expand All @@ -144,13 +125,7 @@ class ContextGroup {
typedef std::map<uint32, linked_ptr<IdAllocator> > IdAllocatorMap;
IdAllocatorMap id_namespaces_;

Validators validators_;

// The extensions string returned by glGetString(GL_EXTENSIONS);
std::string extensions_;

// Flags for some extensions
ExtensionFlags extension_flags_;
FeatureInfo feature_info_;

DISALLOW_COPY_AND_ASSIGN(ContextGroup);
};
Expand Down
Loading

0 comments on commit 915a59a

Please sign in to comment.