#include "base/at_exit.h"
#include "base/bind.h"
+#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/debug/trace_event_synthetic_delay.h"
#include "base/memory/scoped_ptr.h"
+#include "base/numerics/safe_math.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "build/build_config.h"
#include "gpu/command_buffer/service/texture_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"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_image.h"
#include "base/win/win_util.h"
#endif
-// TODO(zmo): we can't include "City.h" due to type def conflicts.
-extern uint64 CityHash64(const char*, size_t);
-
namespace gpu {
namespace gles2 {
static const char kOESDerivativeExtension[] = "GL_OES_standard_derivatives";
static const char kEXTFragDepthExtension[] = "GL_EXT_frag_depth";
static const char kEXTDrawBuffersExtension[] = "GL_EXT_draw_buffers";
+static const char kEXTShaderTextureLodExtension[] = "GL_EXT_shader_texture_lod";
#if !defined(ANGLE_SH_VERSION) || ANGLE_SH_VERSION < 108
khronos_uint64_t CityHashForAngle(const char* name, unsigned int len) {
return true;
}
-// Wrapper for glEnable/glDisable that doesn't suck.
-static void EnableDisable(GLenum pname, bool enable) {
- if (enable) {
- glEnable(pname);
- } else {
- glDisable(pname);
- }
-}
-
// This class prevents any GL errors that occur when it is in scope from
// being reported to the client.
class ScopedGLErrorSuppressor {
scoped_ptr<gfx::GLFence> fence;
};
+class AsyncUploadTokenCompletionObserver
+ : public AsyncPixelTransferCompletionObserver {
+ public:
+ explicit AsyncUploadTokenCompletionObserver(uint32 async_upload_token)
+ : async_upload_token_(async_upload_token) {
+ }
+
+ virtual void DidComplete(const AsyncMemoryParams& mem_params) OVERRIDE {
+ DCHECK(mem_params.buffer());
+ void* data = mem_params.GetDataAddress();
+ AsyncUploadSync* sync = static_cast<AsyncUploadSync*>(data);
+ sync->SetAsyncUploadToken(async_upload_token_);
+ }
+
+ private:
+ virtual ~AsyncUploadTokenCompletionObserver() {
+ }
+
+ uint32 async_upload_token_;
+
+ DISALLOW_COPY_AND_ASSIGN(AsyncUploadTokenCompletionObserver);
+};
+
// } // anonymous namespace.
bool GLES2Decoder::GetServiceTextureId(uint32 client_texture_id,
unsigned int target) const OVERRIDE {
state_.RestoreActiveTextureUnitBinding(target);
}
- virtual void RestoreAttribute(unsigned index) const OVERRIDE {
- state_.RestoreAttribute(index);
- }
virtual void RestoreBufferBindings() const OVERRIDE {
state_.RestoreBufferBindings();
}
virtual void RestoreGlobalState() const OVERRIDE {
- state_.RestoreGlobalState();
+ state_.RestoreGlobalState(NULL);
}
virtual void RestoreProgramBindings() const OVERRIDE {
state_.RestoreProgramBindings();
virtual void ResetAsyncPixelTransferManagerForTest() OVERRIDE;
virtual void SetAsyncPixelTransferManagerForTest(
AsyncPixelTransferManager* manager) OVERRIDE;
+ virtual void SetIgnoreCachedStateForTest(bool ignore) OVERRIDE;
void ProcessFinishedAsyncTransfers();
virtual bool GetServiceTextureId(uint32 client_texture_id,
bool GenVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
void DeleteVertexArraysOESHelper(GLsizei n, const GLuint* client_ids);
+ // Helper for async upload token completion notification callback.
+ base::Closure AsyncUploadTokenCompletionClosure(uint32 async_upload_token,
+ uint32 sync_data_shm_id,
+ uint32 sync_data_shm_offset);
+
+
+
// Workarounds
void OnFboChanged() const;
void OnUseFramebuffer() const;
return group_->shader_manager();
}
+ ShaderTranslatorCache* shader_translator_cache() {
+ return group_->shader_translator_cache();
+ }
+
const TextureManager* texture_manager() const {
return group_->texture_manager();
}
}
// Creates a vertex attrib manager for the given vertex array.
- void CreateVertexAttribManager(GLuint client_id, GLuint service_id) {
+ scoped_refptr<VertexAttribManager> CreateVertexAttribManager(
+ GLuint client_id,
+ GLuint service_id,
+ bool client_visible) {
return vertex_array_manager()->CreateVertexAttribManager(
- client_id, service_id, group_->max_vertex_attribs());
+ client_id, service_id, group_->max_vertex_attribs(), client_visible);
}
void DoBindAttribLocation(GLuint client_id, GLuint index, const char* name);
bool unpack_premultiply_alpha_;
bool unpack_unpremultiply_alpha_;
- // Default vertex attribs manager, used when no VAOs are bound.
- scoped_refptr<VertexAttribManager> default_vertex_attrib_manager_;
-
// The buffer we bind to attrib 0 since OpenGL requires it (ES does not).
GLuint attrib_0_buffer_id_;
bool derivatives_explicitly_enabled_;
bool frag_depth_explicitly_enabled_;
bool draw_buffers_explicitly_enabled_;
+ bool shader_texture_lod_explicitly_enabled_;
bool compile_shader_always_succeeds_;
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, targetid);
const int width = decoder_->offscreen_size_.width();
const int height = decoder_->offscreen_size_.height();
- glDisable(GL_SCISSOR_TEST);
+ decoder->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
decoder->BlitFramebufferHelper(0,
0,
width,
"ScopedResolvedFrameBufferBinder::dtor", decoder_->GetErrorState());
decoder_->RestoreCurrentFramebufferBindings();
if (decoder_->state_.enable_flags.scissor_test) {
- glEnable(GL_SCISSOR_TEST);
+ decoder_->state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
}
}
derivatives_explicitly_enabled_(false),
frag_depth_explicitly_enabled_(false),
draw_buffers_explicitly_enabled_(false),
+ shader_texture_lod_explicitly_enabled_(false),
compile_shader_always_succeeds_(false),
lose_context_when_out_of_memory_(false),
service_logging_(CommandLine::ForCurrentProcess()->HasSwitch(
disallowed_features_ = disallowed_features;
state_.attrib_values.resize(group_->max_vertex_attribs());
- default_vertex_attrib_manager_ = new VertexAttribManager();
- default_vertex_attrib_manager_->Initialize(
+ vertex_array_manager_.reset(new VertexArrayManager());
+
+ GLuint default_vertex_attrib_service_id = 0;
+ if (features().native_vertex_array_object) {
+ glGenVertexArraysOES(1, &default_vertex_attrib_service_id);
+ glBindVertexArrayOES(default_vertex_attrib_service_id);
+ }
+
+ state_.default_vertex_attrib_manager =
+ CreateVertexAttribManager(0, default_vertex_attrib_service_id, false);
+
+ state_.default_vertex_attrib_manager->Initialize(
group_->max_vertex_attribs(),
feature_info_->workarounds().init_vertex_attributes);
- // vertex_attrib_manager is set to default_vertex_attrib_manager_ by this call
+ // vertex_attrib_manager is set to default_vertex_attrib_manager by this call
DoBindVertexArrayOES(0);
query_manager_.reset(new QueryManager(this, feature_info_.get()));
- vertex_array_manager_.reset(new VertexArrayManager());
util_.set_num_compressed_texture_formats(
validators_->compressed_texture_format.GetValues().size());
ref = texture_manager()->GetDefaultTextureInfo(
GL_TEXTURE_EXTERNAL_OES);
state_.texture_units[tt].bound_texture_external_oes = ref;
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref->service_id());
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, ref ? ref->service_id() : 0);
}
if (features().arb_texture_rectangle) {
ref = texture_manager()->GetDefaultTextureInfo(
GL_TEXTURE_RECTANGLE_ARB);
state_.texture_units[tt].bound_texture_rectangle_arb = ref;
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref->service_id());
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, ref ? ref->service_id() : 0);
}
ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP);
state_.texture_units[tt].bound_texture_cube_map = ref;
- glBindTexture(GL_TEXTURE_CUBE_MAP, ref->service_id());
+ glBindTexture(GL_TEXTURE_CUBE_MAP, ref ? ref->service_id() : 0);
ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D);
state_.texture_units[tt].bound_texture_2d = ref;
- glBindTexture(GL_TEXTURE_2D, ref->service_id());
+ glBindTexture(GL_TEXTURE_2D, ref ? ref->service_id() : 0);
}
glActiveTexture(GL_TEXTURE0);
CHECK_GL_ERROR();
state_.scissor_height = state_.viewport_height;
// Set all the default state because some GL drivers get it wrong.
- state_.InitCapabilities();
- state_.InitState();
+ state_.InitCapabilities(NULL);
+ state_.InitState(NULL);
glActiveTexture(GL_TEXTURE0 + state_.active_texture_unit);
DoBindBuffer(GL_ARRAY_BUFFER, 0);
caps.texture_storage = feature_info_->feature_flags().ext_texture_storage;
caps.discard_framebuffer =
feature_info_->feature_flags().ext_discard_framebuffer;
+ caps.sync_query = feature_info_->feature_flags().chromium_sync_query;
#if defined(OS_MACOSX)
// This is unconditionally true on mac, no need to test for it at runtime.
#endif
caps.post_sub_buffer = supports_post_sub_buffer_;
+ caps.map_image = !!image_manager();
return caps;
}
resources.EXT_draw_buffers = draw_buffers_explicitly_enabled_;
if (!draw_buffers_explicitly_enabled_)
resources.MaxDrawBuffers = 1;
+#if (ANGLE_SH_VERSION >= 123)
+ resources.EXT_shader_texture_lod = shader_texture_lod_explicitly_enabled_;
+#endif
} else {
resources.OES_standard_derivatives =
features().oes_standard_derivatives ? 1 : 0;
features().ext_draw_buffers ? 1 : 0;
resources.EXT_frag_depth =
features().ext_frag_depth ? 1 : 0;
+#if (ANGLE_SH_VERSION >= 123)
+ resources.EXT_shader_texture_lod =
+ features().ext_shader_texture_lod ? 1 : 0;
+#endif
}
ShShaderSpec shader_spec = force_webgl_glsl_validation_ ? SH_WEBGL_SPEC
if (workarounds().unroll_for_loop_with_sampler_array_index)
driver_bug_workarounds |= SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX;
- ShaderTranslatorCache* cache = ShaderTranslatorCache::GetInstance();
- vertex_translator_ = cache->GetTranslator(
- SH_VERTEX_SHADER, shader_spec, &resources,
+ vertex_translator_ = shader_translator_cache()->GetTranslator(
+ SH_VERTEX_SHADER,
+ shader_spec,
+ &resources,
implementation_type,
static_cast<ShCompileOptions>(driver_bug_workarounds));
if (!vertex_translator_.get()) {
return false;
}
- fragment_translator_ = cache->GetTranslator(
- SH_FRAGMENT_SHADER, shader_spec, &resources,
+ fragment_translator_ = shader_translator_cache()->GetTranslator(
+ SH_FRAGMENT_SHADER,
+ shader_spec,
+ &resources,
implementation_type,
static_cast<ShCompileOptions>(driver_bug_workarounds));
if (!fragment_translator_.get()) {
if (backbuffer_needs_clear_bits_) {
glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearStencil(0);
glStencilMask(-1);
glClearDepth(1.0f);
- glDepthMask(true);
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceDepthMask(GL_TRUE);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
glClear(backbuffer_needs_clear_bits_);
backbuffer_needs_clear_bits_ = 0;
RestoreClearState();
// Unbind everything.
state_.vertex_attrib_manager = NULL;
- default_vertex_attrib_manager_ = NULL;
+ state_.default_vertex_attrib_manager = NULL;
state_.texture_units.clear();
state_.bound_array_buffer = NULL;
state_.current_queries.clear();
offscreen_resolved_frame_buffer_.reset();
offscreen_resolved_color_texture_.reset();
+ // Need to release these before releasing |group_| which may own the
+ // ShaderTranslatorCache.
+ fragment_translator_ = NULL;
+ vertex_translator_ = NULL;
+
// Should destroy the transfer manager before the texture manager held
// by the context group.
async_pixel_transfer_manager_.reset();
ScopedFrameBufferBinder binder(this, offscreen_target_frame_buffer_->id());
glClearColor(0, 0, 0, (GLES2Util::GetChannelsForFormat(
offscreen_target_color_format_) & 0x0008) != 0 ? 0 : 1);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearStencil(0);
- glStencilMaskSeparate(GL_FRONT, -1);
- glStencilMaskSeparate(GL_BACK, -1);
+ state_.SetDeviceStencilMaskSeparate(GL_FRONT, -1);
+ state_.SetDeviceStencilMaskSeparate(GL_BACK, -1);
glClearDepth(0);
- glDepthMask(GL_TRUE);
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceDepthMask(GL_TRUE);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
RestoreClearState();
}
void GLES2DecoderImpl::ApplyDirtyState() {
if (framebuffer_state_.clear_state_dirty) {
- glColorMask(
- state_.color_mask_red, state_.color_mask_green, state_.color_mask_blue,
- state_.color_mask_alpha &&
- BoundFramebufferHasColorAttachmentWithAlpha(true));
+ bool have_alpha = BoundFramebufferHasColorAttachmentWithAlpha(true);
+ state_.SetDeviceColorMask(state_.color_mask_red,
+ state_.color_mask_green,
+ state_.color_mask_blue,
+ state_.color_mask_alpha && have_alpha);
+
bool have_depth = BoundFramebufferHasDepthAttachment();
- glDepthMask(state_.depth_mask && have_depth);
- EnableDisable(GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
+ state_.SetDeviceDepthMask(state_.depth_mask && have_depth);
+
bool have_stencil = BoundFramebufferHasStencilAttachment();
- glStencilMaskSeparate(
+ state_.SetDeviceStencilMaskSeparate(
GL_FRONT, have_stencil ? state_.stencil_front_writemask : 0);
- glStencilMaskSeparate(
+ state_.SetDeviceStencilMaskSeparate(
GL_BACK, have_stencil ? state_.stencil_back_writemask : 0);
- EnableDisable(
+
+ state_.SetDeviceCapabilityState(
+ GL_DEPTH_TEST, state_.enable_flags.depth_test && have_depth);
+ state_.SetDeviceCapabilityState(
GL_STENCIL_TEST, state_.enable_flags.stencil_test && have_stencil);
- EnableDisable(GL_CULL_FACE, state_.enable_flags.cull_face);
- EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
- EnableDisable(GL_BLEND, state_.enable_flags.blend);
framebuffer_state_.clear_state_dirty = false;
}
}
}
void GLES2DecoderImpl::ClearAllAttributes() const {
+ // Must use native VAO 0, as RestoreAllAttributes can't fully restore
+ // other VAOs.
+ if (feature_info_->feature_flags().native_vertex_array_object)
+ glBindVertexArrayOES(0);
+
for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i) {
if (i != 0) // Never disable attribute 0
glDisableVertexAttribArray(i);
}
void GLES2DecoderImpl::RestoreAllAttributes() const {
- for (uint32 i = 0; i < group_->max_vertex_attribs(); ++i)
- RestoreAttribute(i);
+ state_.RestoreVertexAttribs();
+}
+
+void GLES2DecoderImpl::SetIgnoreCachedStateForTest(bool ignore) {
+ state_.SetIgnoreCachedStateForTest(ignore);
}
void GLES2DecoderImpl::OnFboChanged() const {
} else {
texture_ref = texture_manager()->GetDefaultTextureInfo(target);
}
- Texture* texture = texture_ref->texture();
// Check the texture exists
- // Check that we are not trying to bind it to a different target.
- if (texture->target() != 0 && texture->target() != target) {
- LOCAL_SET_GL_ERROR(
- GL_INVALID_OPERATION,
- "glBindTexture", "texture bound to more than 1 target.");
- return;
- }
- LogClientServiceForInfo(texture, client_id, "glBindTexture");
- if (texture->target() == 0) {
- texture_manager()->SetTarget(texture_ref, target);
+ if (texture_ref) {
+ Texture* texture = texture_ref->texture();
+ // Check that we are not trying to bind it to a different target.
+ if (texture->target() != 0 && texture->target() != target) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBindTexture",
+ "texture bound to more than 1 target.");
+ return;
+ }
+ LogClientServiceForInfo(texture, client_id, "glBindTexture");
+ if (texture->target() == 0) {
+ texture_manager()->SetTarget(texture_ref, target);
+ }
+ glBindTexture(target, texture->service_id());
+ } else {
+ glBindTexture(target, 0);
}
- glBindTexture(target, texture->service_id());
TextureUnit& unit = state_.texture_units[state_.active_texture_unit];
unit.bind_target = target;
*num_written = 1;
if (params) {
if (state_.vertex_attrib_manager.get() !=
- default_vertex_attrib_manager_.get()) {
+ state_.default_vertex_attrib_manager.get()) {
GLuint client_id = 0;
vertex_array_manager_->GetClientId(
state_.vertex_attrib_manager->service_id(), &client_id);
params[0] = unpack_unpremultiply_alpha_;
}
return true;
-#if defined(OS_CHROMEOS)
case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
*num_written = 1;
if (params) {
params[0] = group_->bind_generates_resource() ? 1 : 0;
}
return true;
-#endif
default:
if (pname >= GL_DRAW_BUFFER0_ARB &&
pname < GL_DRAW_BUFFER0_ARB + group_->max_draw_buffers()) {
if (name == NULL) {
return error::kOutOfBounds;
}
- String name_str(name, name_size);
+ std::string name_str(name, name_size);
DoBindAttribLocation(program, index, name_str.c_str());
return error::kNoError;
}
if (name == NULL) {
return error::kOutOfBounds;
}
- String name_str(name, name_size);
+ std::string name_str(name, name_size);
DoBindUniformLocationCHROMIUM(program, location, name_str.c_str());
return error::kNoError;
}
(GLES2Util::GetChannelsForFormat(
framebuffer->GetColorAttachmentFormat()) & 0x0008) != 0 ? 0.0f :
1.0f);
- glColorMask(true, true, true, true);
+ state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
clear_bits |= GL_COLOR_BUFFER_BIT;
}
if (framebuffer->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT) ||
framebuffer->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)) {
glClearDepth(1.0f);
- glDepthMask(true);
+ state_.SetDeviceDepthMask(GL_TRUE);
clear_bits |= GL_DEPTH_BUFFER_BIT;
}
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
glClear(clear_bits);
framebuffer_manager()->MarkAttachmentsAsCleared(
glClearStencil(state_.stencil_clear);
glClearDepth(state_.depth_clear);
if (state_.enable_flags.scissor_test) {
- glEnable(GL_SCISSOR_TEST);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
}
}
return;
}
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
BlitFramebufferHelper(
srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
- EnableDisable(GL_SCISSOR_TEST, state_.enable_flags.scissor_test);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST,
+ state_.enable_flags.scissor_test);
}
void GLES2DecoderImpl::RenderbufferStorageMultisampleHelper(
GLboolean scissor_enabled = false;
glGetBooleanv(GL_SCISSOR_TEST, &scissor_enabled);
if (scissor_enabled)
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
- GLboolean color_mask[4] = {true, true, true, true};
+ GLboolean color_mask[4] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
glGetBooleanv(GL_COLOR_WRITEMASK, color_mask);
- glColorMask(true, true, true, true);
+ state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
GLfloat clear_color[4] = {0.0f, 0.0f, 0.0f, 0.0f};
glGetFloatv(GL_COLOR_CLEAR_VALUE, clear_color);
// Restore cached state.
if (scissor_enabled)
- glEnable(GL_SCISSOR_TEST);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, true);
- glColorMask(color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
+ state_.SetDeviceColorMask(
+ color_mask[0], color_mask[1], color_mask[2], color_mask[3]);
glClearColor(clear_color[0], clear_color[1], clear_color[2], clear_color[3]);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER, draw_framebuffer);
glBindFramebufferEXT(GL_READ_FRAMEBUFFER, read_framebuffer);
if (!state_.bound_array_buffer.get() ||
state_.bound_array_buffer->IsDeleted()) {
if (state_.vertex_attrib_manager.get() ==
- default_vertex_attrib_manager_.get()) {
+ state_.default_vertex_attrib_manager.get()) {
LOCAL_SET_GL_ERROR(
GL_INVALID_VALUE, "glVertexAttribPointer", "no array buffer bound");
return error::kNoError;
error::Error GLES2DecoderImpl::HandlePostSubBufferCHROMIUM(
uint32 immediate_data_size, const cmds::PostSubBufferCHROMIUM& c) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandlePostSubBufferCHROMIUM");
+ {
+ TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
+ }
if (!supports_post_sub_buffer_) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION,
}
}
+error::Error GLES2DecoderImpl::HandleScheduleOverlayPlaneCHROMIUM(
+ uint32 immediate_data_size,
+ const cmds::ScheduleOverlayPlaneCHROMIUM& c) {
+ NOTIMPLEMENTED() << "Overlay supported isn't finished.";
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glScheduleOverlayPlaneCHROMIUM",
+ "function not implemented");
+ return error::kNoError;
+}
+
error::Error GLES2DecoderImpl::GetAttribLocationHelper(
GLuint client_id, uint32 location_shm_id, uint32 location_shm_offset,
const std::string& name_str) {
if (!name) {
return error::kOutOfBounds;
}
- String name_str(name, name_size);
+ std::string name_str(name, name_size);
return GetAttribLocationHelper(
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
if (!name) {
return error::kOutOfBounds;
}
- String name_str(name, name_size);
+ std::string name_str(name, name_size);
return GetUniformLocationHelper(
c.program, c.location_shm_id, c.location_shm_offset, name_str);
}
std::string());
}
}
+ if (!shader_texture_lod_explicitly_enabled_) {
+ size_t offset = extensions.find(kEXTShaderTextureLodExtension);
+ if (std::string::npos != offset) {
+ extensions.replace(offset,
+ arraysize(kEXTShaderTextureLodExtension),
+ std::string());
+ }
+ }
} else {
extensions = feature_info_->extensions().c_str();
}
glClearStencil(0);
glStencilMask(-1);
glClearDepth(1.0f);
- glDepthMask(true);
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceDepthMask(GL_TRUE);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
glClear(GL_DEPTH_BUFFER_BIT | (have_stencil ? GL_STENCIL_BUFFER_BIT : 0));
RestoreClearState();
const int kS3TCBlockHeight = 4;
const int kS3TCDXT1BlockSize = 8;
const int kS3TCDXT3AndDXT5BlockSize = 16;
-const int kETC1BlockWidth = 4;
-const int kETC1BlockHeight = 4;
-const int kETC1BlockSize = 8;
bool IsValidDXTSize(GLint level, GLsizei size) {
return (size == 1) ||
(size == 2) || !(size % kS3TCBlockWidth);
}
+bool IsValidPVRTCSize(GLint level, GLsizei size) {
+ // Ensure that the size is a power of two
+ return (size & (size - 1)) == 0;
+}
+
} // anonymous namespace.
bool GLES2DecoderImpl::ValidateCompressedTexFuncData(
unsigned int bytes_required = 0;
switch (format) {
+ case GL_ATC_RGB_AMD:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: {
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
+ case GL_ETC1_RGB8_OES: {
int num_blocks_across =
(width + kS3TCBlockWidth - 1) / kS3TCBlockWidth;
int num_blocks_down =
bytes_required = num_blocks * kS3TCDXT1BlockSize;
break;
}
+ case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: {
int num_blocks_across =
bytes_required = num_blocks * kS3TCDXT3AndDXT5BlockSize;
break;
}
- case GL_ETC1_RGB8_OES: {
- int num_blocks_across =
- (width + kETC1BlockWidth - 1) / kETC1BlockWidth;
- int num_blocks_down =
- (height + kETC1BlockHeight - 1) / kETC1BlockHeight;
- int num_blocks = num_blocks_across * num_blocks_down;
- bytes_required = num_blocks * kETC1BlockSize;
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG: {
+ bytes_required = (std::max(width, 8) * std::max(height, 8) * 4 + 7)/8;
+ break;
+ }
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+ bytes_required = (std::max(width, 16) * std::max(height, 8) * 2 + 7)/8;
break;
}
default:
}
return true;
}
- case GL_ETC1_RGB8_OES:
+ case GL_ATC_RGB_AMD:
+ case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
+ case GL_ETC1_RGB8_OES: {
if (width <= 0 || height <= 0) {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name,
return false;
}
return true;
+ }
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+ if (!IsValidPVRTCSize(level, width) ||
+ !IsValidPVRTCSize(level, height)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, function_name,
+ "width or height invalid for level");
+ return false;
+ }
+ return true;
+ }
default:
return false;
}
return ValidateCompressedTexDimensions(
function_name, level, width, height, format);
}
+ case GL_ATC_RGB_AMD:
+ case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD:
+ case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, function_name,
+ "not supported for ATC textures");
+ return false;
+ }
case GL_ETC1_RGB8_OES: {
LOCAL_SET_GL_ERROR(
GL_INVALID_OPERATION, function_name,
"not supported for ECT1_RGB8_OES textures");
return false;
}
+ case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
+ case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG: {
+ if ((xoffset != 0) || (yoffset != 0)) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, function_name,
+ "xoffset and yoffset must be zero");
+ return false;
+ }
+ GLsizei tex_width = 0;
+ GLsizei tex_height = 0;
+ if (!texture->GetLevelSize(target, level, &tex_width, &tex_height) ||
+ width != tex_width ||
+ height != tex_height) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, function_name,
+ "dimensions must match existing texture level dimensions");
+ return false;
+ }
+ return ValidateCompressedTexDimensions(
+ function_name, level, width, height, format);
+ }
default:
return false;
}
"offscreen", is_offscreen,
"frame", this_frame_number);
{
- TRACE_EVENT_SYNTHETIC_DELAY("gpu.SwapBuffers");
+ TRACE_EVENT_SYNTHETIC_DELAY("gpu.PresentingFrame");
}
bool is_tracing;
ScopedFrameBufferBinder binder(this,
offscreen_saved_frame_buffer_->id());
glClearColor(0, 0, 0, 0);
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glDisable(GL_SCISSOR_TEST);
+ state_.SetDeviceColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+ state_.SetDeviceCapabilityState(GL_SCISSOR_TEST, false);
glClear(GL_COLOR_BUFFER_BIT);
RestoreClearState();
}
bool desire_standard_derivatives = false;
bool desire_frag_depth = false;
bool desire_draw_buffers = false;
+ bool desire_shader_texture_lod = false;
if (force_webgl_glsl_validation_) {
desire_standard_derivatives =
feature_str.find("GL_OES_standard_derivatives") != std::string::npos;
feature_str.find("GL_EXT_frag_depth") != std::string::npos;
desire_draw_buffers =
feature_str.find("GL_EXT_draw_buffers") != std::string::npos;
+ desire_shader_texture_lod =
+ feature_str.find("GL_EXT_shader_texture_lod") != std::string::npos;
}
if (desire_webgl_glsl_validation != force_webgl_glsl_validation_ ||
derivatives_explicitly_enabled_ |= desire_standard_derivatives;
frag_depth_explicitly_enabled_ |= desire_frag_depth;
draw_buffers_explicitly_enabled_ |= desire_draw_buffers;
+ shader_texture_lod_explicitly_enabled_ |= desire_shader_texture_lod;
InitializeShaderTranslator();
}
return false;
}
}
- // NOTE: We don't generate Query objects here. Only in BeginQueryEXT
+ query_manager_->GenQueries(n, client_ids);
return true;
}
state_.current_queries.erase(it);
query->Destroy(true);
- query_manager_->RemoveQuery(client_ids[ii]);
}
+ query_manager_->RemoveQuery(client_ids[ii]);
}
}
case GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM:
case GL_GET_ERROR_QUERY_CHROMIUM:
break;
+ case GL_COMMANDS_COMPLETED_CHROMIUM:
+ if (!features().chromium_sync_query) {
+ LOCAL_SET_GL_ERROR(
+ GL_INVALID_OPERATION, "glBeginQueryEXT",
+ "not enabled for commands completed queries");
+ return error::kNoError;
+ }
+ break;
default:
if (!features().occlusion_query_boolean) {
LOCAL_SET_GL_ERROR(
QueryManager::Query* query = query_manager_->GetQuery(client_id);
if (!query) {
- // TODO(gman): Decide if we need this check.
- //
- // Checks id was made by glGenQueries
- //
- // From the POV of OpenGL ES 2.0 you need to call glGenQueriesEXT
- // for all Query ids but from the POV of the command buffer service maybe
- // you don't.
- //
- // The client can enforce this. I don't think the service cares.
- //
- // IdAllocatorInterface* id_allocator =
- // group_->GetIdAllocator(id_namespaces::kQueries);
- // if (!id_allocator->InUse(client_id)) {
- // LOCAL_SET_GL_ERROR(
- // GL_INVALID_OPERATION,
- // "glBeginQueryEXT", "id not made by glGenQueriesEXT");
- // return error::kNoError;
- // }
+ if (!query_manager_->IsValidQuery(client_id)) {
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION,
+ "glBeginQueryEXT",
+ "id not made by glGenQueriesEXT");
+ return error::kNoError;
+ }
query = query_manager_->CreateQuery(
target, client_id, sync_shm_id, sync_shm_offset);
}
if (!features().native_vertex_array_object) {
// Emulated VAO
for (GLsizei ii = 0; ii < n; ++ii) {
- CreateVertexAttribManager(client_ids[ii], 0);
+ CreateVertexAttribManager(client_ids[ii], 0, true);
}
} else {
scoped_ptr<GLuint[]> service_ids(new GLuint[n]);
glGenVertexArraysOES(n, service_ids.get());
for (GLsizei ii = 0; ii < n; ++ii) {
- CreateVertexAttribManager(client_ids[ii], service_ids[ii]);
+ CreateVertexAttribManager(client_ids[ii], service_ids[ii], true);
}
}
GetVertexAttribManager(client_ids[ii]);
if (vao && !vao->IsDeleted()) {
if (state_.vertex_attrib_manager.get() == vao) {
- state_.vertex_attrib_manager = default_vertex_attrib_manager_;
+ DoBindVertexArrayOES(0);
}
RemoveVertexAttribManager(client_ids[ii]);
}
void GLES2DecoderImpl::DoBindVertexArrayOES(GLuint client_id) {
VertexAttribManager* vao = NULL;
- GLuint service_id = 0;
if (client_id != 0) {
vao = GetVertexAttribManager(client_id);
if (!vao) {
"glBindVertexArrayOES", "bad vertex array id.");
current_decoder_error_ = error::kNoError;
return;
- } else {
- service_id = vao->service_id();
}
} else {
- vao = default_vertex_attrib_manager_.get();
+ vao = state_.default_vertex_attrib_manager.get();
}
// Only set the VAO state if it's changed
if (!features().native_vertex_array_object) {
EmulateVertexArrayState();
} else {
+ GLuint service_id = vao->service_id();
glBindVertexArrayOES(service_id);
}
}
void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
GLenum target, GLuint source_id, GLuint dest_id, GLint level,
GLenum internal_format, GLenum dest_type) {
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::DoCopyTextureCHROMIUM");
+
TextureRef* dest_texture_ref = GetTexture(dest_id);
TextureRef* source_texture_ref = GetTexture(source_id);
Texture* dest_texture = dest_texture_ref->texture();
if (dest_texture->target() != GL_TEXTURE_2D ||
(source_texture->target() != GL_TEXTURE_2D &&
- source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
+ source_texture->target() != GL_TEXTURE_RECTANGLE_ARB &&
+ source_texture->target() != GL_TEXTURE_EXTERNAL_OES)) {
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE,
"glCopyTextureCHROMIUM",
"invalid texture target binding");
return true;
}
+base::Closure GLES2DecoderImpl::AsyncUploadTokenCompletionClosure(
+ uint32 async_upload_token,
+ uint32 sync_data_shm_id,
+ uint32 sync_data_shm_offset) {
+ scoped_refptr<gpu::Buffer> buffer = GetSharedMemoryBuffer(sync_data_shm_id);
+ if (!buffer || !buffer->GetDataAddress(sync_data_shm_offset,
+ sizeof(AsyncUploadSync)))
+ return base::Closure();
+
+ AsyncMemoryParams mem_params(buffer,
+ sync_data_shm_offset,
+ sizeof(AsyncUploadSync));
+
+ scoped_refptr<AsyncUploadTokenCompletionObserver> observer(
+ new AsyncUploadTokenCompletionObserver(async_upload_token));
+
+ return base::Bind(
+ &AsyncPixelTransferManager::AsyncNotifyCompletion,
+ base::Unretained(GetAsyncPixelTransferManager()),
+ mem_params,
+ observer);
+}
+
error::Error GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM(
uint32 immediate_data_size, const cmds::AsyncTexImage2DCHROMIUM& c) {
TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleAsyncTexImage2DCHROMIUM");
uint32 pixels_shm_id = static_cast<uint32>(c.pixels_shm_id);
uint32 pixels_shm_offset = static_cast<uint32>(c.pixels_shm_offset);
uint32 pixels_size;
+ uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+ uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+ uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+ base::ScopedClosureRunner scoped_completion_callback;
+ if (async_upload_token) {
+ base::Closure completion_closure =
+ AsyncUploadTokenCompletionClosure(async_upload_token,
+ sync_data_shm_id,
+ sync_data_shm_offset);
+ if (completion_closure.is_null())
+ return error::kInvalidArguments;
+
+ scoped_completion_callback.Reset(completion_closure);
+ }
// TODO(epenner): Move this and copies of this memory validation
// into ValidateTexImage2D step.
GLsizei height = static_cast<GLsizei>(c.height);
GLenum format = static_cast<GLenum>(c.format);
GLenum type = static_cast<GLenum>(c.type);
+ uint32 async_upload_token = static_cast<uint32>(c.async_upload_token);
+ uint32 sync_data_shm_id = static_cast<uint32>(c.sync_data_shm_id);
+ uint32 sync_data_shm_offset = static_cast<uint32>(c.sync_data_shm_offset);
+
+ base::ScopedClosureRunner scoped_completion_callback;
+ if (async_upload_token) {
+ base::Closure completion_closure =
+ AsyncUploadTokenCompletionClosure(async_upload_token,
+ sync_data_shm_id,
+ sync_data_shm_offset);
+ if (completion_closure.is_null())
+ return error::kInvalidArguments;
+
+ scoped_completion_callback.Reset(completion_closure);
+ }
// TODO(epenner): Move this and copies of this memory validation
// into ValidateTexSubImage2D step.
return error::kNoError;
}
+error::Error GLES2DecoderImpl::HandleWaitAllAsyncTexImage2DCHROMIUM(
+ uint32 immediate_data_size, const cmds::WaitAllAsyncTexImage2DCHROMIUM& c) {
+ TRACE_EVENT0("gpu", "GLES2DecoderImpl::HandleWaitAsyncTexImage2DCHROMIUM");
+
+ GetAsyncPixelTransferManager()->WaitAllAsyncTexImage2D();
+ ProcessFinishedAsyncTransfers();
+ return error::kNoError;
+}
+
void GLES2DecoderImpl::OnTextureRefDetachedFromFramebuffer(
TextureRef* texture_ref) {
Texture* texture = texture_ref->texture();