| // Copyright (c) 2017 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "gpu/command_buffer/service/raster_decoder.h" |
| |
| #include <stdint.h> |
| |
| #include <string> |
| |
| #include "base/logging.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/trace_event/trace_event.h" |
| #include "gpu/command_buffer/common/capabilities.h" |
| #include "gpu/command_buffer/common/command_buffer_id.h" |
| #include "gpu/command_buffer/common/constants.h" |
| #include "gpu/command_buffer/common/context_result.h" |
| #include "gpu/command_buffer/common/debug_marker_manager.h" |
| #include "gpu/command_buffer/common/raster_cmd_format.h" |
| #include "gpu/command_buffer/common/raster_cmd_ids.h" |
| #include "gpu/command_buffer/common/sync_token.h" |
| #include "gpu/command_buffer/service/context_group.h" |
| #include "gpu/command_buffer/service/context_state.h" |
| #include "gpu/command_buffer/service/decoder_client.h" |
| #include "gpu/command_buffer/service/error_state.h" |
| #include "gpu/command_buffer/service/feature_info.h" |
| #include "gpu/command_buffer/service/gles2_cmd_validation.h" |
| #include "gpu/command_buffer/service/logger.h" |
| #include "ui/gl/gl_context.h" |
| #include "ui/gl/gl_surface.h" |
| #include "ui/gl/gl_version_info.h" |
| |
| // Local versions of the SET_GL_ERROR macros |
| #define LOCAL_SET_GL_ERROR(error, function_name, msg) \ |
| ERRORSTATE_SET_GL_ERROR(state_.GetErrorState(), error, function_name, msg) |
| #define LOCAL_SET_GL_ERROR_INVALID_ENUM(function_name, value, label) \ |
| ERRORSTATE_SET_GL_ERROR_INVALID_ENUM(state_.GetErrorState(), function_name, \ |
| value, label) |
| #define LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER(function_name) \ |
| ERRORSTATE_COPY_REAL_GL_ERRORS_TO_WRAPPER(state_.GetErrorState(), \ |
| function_name) |
| #define LOCAL_PEEK_GL_ERROR(function_name) \ |
| ERRORSTATE_PEEK_GL_ERROR(state_.GetErrorState(), function_name) |
| #define LOCAL_CLEAR_REAL_GL_ERRORS(function_name) \ |
| ERRORSTATE_CLEAR_REAL_GL_ERRORS(state_.GetErrorState(), function_name) |
| #define LOCAL_PERFORMANCE_WARNING(msg) \ |
| PerformanceWarning(__FILE__, __LINE__, msg) |
| #define LOCAL_RENDER_WARNING(msg) RenderWarning(__FILE__, __LINE__, msg) |
| |
| using namespace gpu::gles2; |
| |
| namespace gpu { |
| namespace raster { |
| |
| class RasterDecoderImpl : public RasterDecoder, public gles2::ErrorStateClient { |
| public: |
| RasterDecoderImpl(DecoderClient* client, |
| CommandBufferServiceBase* command_buffer_service, |
| gles2::Outputter* outputter, |
| gles2::ContextGroup* group); |
| ~RasterDecoderImpl() override; |
| |
| GLES2Util* GetGLES2Util() override { return &util_; } |
| |
| // DecoderContext implementation. |
| base::WeakPtr<DecoderContext> AsWeakPtr() override; |
| gpu::ContextResult Initialize( |
| const scoped_refptr<gl::GLSurface>& surface, |
| const scoped_refptr<gl::GLContext>& context, |
| bool offscreen, |
| const gles2::DisallowedFeatures& disallowed_features, |
| const ContextCreationAttribs& attrib_helper) override; |
| const gles2::ContextState* GetContextState() override; |
| void Destroy(bool have_context) override; |
| bool MakeCurrent() override; |
| gl::GLContext* GetGLContext() override; |
| Capabilities GetCapabilities() override; |
| void RestoreState(const gles2::ContextState* prev_state) override; |
| void RestoreActiveTexture() const override; |
| void RestoreAllTextureUnitAndSamplerBindings( |
| const gles2::ContextState* prev_state) const override; |
| void RestoreActiveTextureUnitBinding(unsigned int target) const override; |
| void RestoreBufferBinding(unsigned int target) override; |
| void RestoreBufferBindings() const override; |
| void RestoreFramebufferBindings() const override; |
| void RestoreRenderbufferBindings() override; |
| void RestoreProgramBindings() const override; |
| void RestoreTextureState(unsigned service_id) const override; |
| void RestoreTextureUnitBindings(unsigned unit) const override; |
| void RestoreVertexAttribArray(unsigned index) override; |
| void RestoreAllExternalTextureBindingsIfNeeded() override; |
| gles2::QueryManager* GetQueryManager() override; |
| gles2::GpuFenceManager* GetGpuFenceManager() override; |
| bool HasPendingQueries() const override; |
| void ProcessPendingQueries(bool did_finish) override; |
| bool HasMoreIdleWork() const override; |
| void PerformIdleWork() override; |
| bool HasPollingWork() const override; |
| void PerformPollingWork() override; |
| TextureBase* GetTextureBase(uint32_t client_id) override; |
| bool WasContextLost() const override; |
| bool WasContextLostByRobustnessExtension() const override; |
| void MarkContextLost(error::ContextLostReason reason) override; |
| bool CheckResetStatus() override; |
| void BeginDecoding() override; |
| void EndDecoding() override; |
| const char* GetCommandName(unsigned int command_id) const; |
| error::Error DoCommands(unsigned int num_commands, |
| const volatile void* buffer, |
| int num_entries, |
| int* entries_processed) override; |
| base::StringPiece GetLogPrefix() override; |
| void BindImage(uint32_t client_texture_id, |
| uint32_t texture_target, |
| gl::GLImage* image, |
| bool can_bind_to_sampler) override; |
| gles2::ContextGroup* GetContextGroup() override; |
| gles2::ErrorState* GetErrorState() override; |
| |
| // ErrorClientState implementation. |
| void OnContextLostError() override; |
| void OnOutOfMemoryError() override; |
| |
| Logger* GetLogger() override; |
| |
| void SetIgnoreCachedStateForTest(bool ignore) override; |
| |
| private: |
| gl::GLApi* api() const { return state_.api(); } |
| |
| const FeatureInfo::FeatureFlags& features() const { |
| return feature_info_->feature_flags(); |
| } |
| |
| const gl::GLVersionInfo& gl_version_info() { |
| return feature_info_->gl_version_info(); |
| } |
| |
| const TextureManager* texture_manager() const { |
| return group_->texture_manager(); |
| } |
| |
| TextureManager* texture_manager() { return group_->texture_manager(); } |
| |
| // Creates a Texture for the given texture. |
| TextureRef* CreateTexture(GLuint client_id, GLuint service_id) { |
| return texture_manager()->CreateTexture(client_id, service_id); |
| } |
| |
| // Gets the texture info for the given texture. Returns nullptr if none |
| // exists. |
| TextureRef* GetTexture(GLuint client_id) const { |
| return texture_manager()->GetTexture(client_id); |
| } |
| |
| // Deletes the texture info for the given texture. |
| void RemoveTexture(GLuint client_id) { |
| texture_manager()->RemoveTexture(client_id); |
| } |
| |
| void UnbindTexture(TextureRef* texture_ref) { |
| // Unbind texture_ref from texture_ref units. |
| state_.UnbindTexture(texture_ref); |
| } |
| |
| // Set remaining commands to process to 0 to force DoCommands to return |
| // and allow context preemption and GPU watchdog checks in |
| // CommandExecutor(). |
| void ExitCommandProcessingEarly() { commands_to_process_ = 0; } |
| |
| template <bool DebugImpl> |
| error::Error DoCommandsImpl(unsigned int num_commands, |
| const volatile void* buffer, |
| int num_entries, |
| int* entries_processed); |
| |
| // Helper for glGetIntegerv. Returns false if pname is unhandled. |
| bool GetHelper(GLenum pname, GLint* params, GLsizei* num_written); |
| |
| // Gets the number of values that will be returned by glGetXXX. Returns |
| // false if pname is unknown. |
| bool GetNumValuesReturnedForGLGet(GLenum pname, GLsizei* num_values); |
| |
| void DoActiveTexture(GLenum texture_unit) { NOTIMPLEMENTED(); } |
| void DoBindTexture(GLenum target, GLuint texture); |
| void DeleteTexturesHelper(GLsizei n, const volatile GLuint* client_ids); |
| bool GenTexturesHelper(GLsizei n, const GLuint* client_ids); |
| bool GenQueriesEXTHelper(GLsizei n, const GLuint* client_ids) { |
| NOTIMPLEMENTED(); |
| return true; |
| } |
| void DeleteQueriesEXTHelper(GLsizei n, const volatile GLuint* client_ids) { |
| NOTIMPLEMENTED(); |
| } |
| void DoFinish(); |
| void DoFlush(); |
| void DoGetIntegerv(GLenum pname, GLint* params, GLsizei params_size); |
| void DoTexParameteri(GLenum target, GLenum pname, GLint param); |
| void DoTexStorage2DEXT(GLenum target, |
| GLsizei levels, |
| GLenum internal_format, |
| GLsizei width, |
| GLsizei height) { |
| NOTIMPLEMENTED(); |
| } |
| void DoTexStorage2DImageCHROMIUM(GLenum target, |
| GLenum internal_format, |
| GLenum buffer_usage, |
| GLsizei width, |
| GLsizei height) { |
| NOTIMPLEMENTED(); |
| } |
| void DoCopySubTextureCHROMIUM(GLuint source_id, |
| GLint source_level, |
| GLenum dest_target, |
| GLuint dest_id, |
| GLint dest_level, |
| GLint xoffset, |
| GLint yoffset, |
| GLint x, |
| GLint y, |
| GLsizei width, |
| GLsizei height, |
| GLboolean unpack_flip_y, |
| GLboolean unpack_premultiply_alpha, |
| GLboolean unpack_unmultiply_alpha) { |
| NOTIMPLEMENTED(); |
| } |
| void DoCompressedCopyTextureCHROMIUM(GLuint source_id, GLuint dest_id) { |
| NOTIMPLEMENTED(); |
| } |
| void DoProduceTextureDirectCHROMIUM(GLuint texture, |
| const volatile GLbyte* key) { |
| NOTIMPLEMENTED(); |
| } |
| void DoBindTexImage2DCHROMIUM(GLenum target, GLint image_id) { |
| NOTIMPLEMENTED(); |
| } |
| void DoReleaseTexImage2DCHROMIUM(GLenum target, GLint image_id) { |
| NOTIMPLEMENTED(); |
| } |
| void DoTraceEndCHROMIUM(); |
| void DoLoseContextCHROMIUM(GLenum current, GLenum other) { NOTIMPLEMENTED(); } |
| void DoBeginRasterCHROMIUM(GLuint texture_id, |
| GLuint sk_color, |
| GLuint msaa_sample_count, |
| GLboolean can_use_lcd_text, |
| GLboolean use_distance_field_text, |
| GLint color_type) { |
| NOTIMPLEMENTED(); |
| } |
| void DoRasterCHROMIUM(GLsizeiptr size, const void* list) { NOTIMPLEMENTED(); } |
| void DoEndRasterCHROMIUM() { NOTIMPLEMENTED(); } |
| void DoCreateTransferCacheEntryINTERNAL(GLuint entry_type, |
| GLuint entry_id, |
| GLuint handle_shm_id, |
| GLuint handle_shm_offset, |
| GLuint data_shm_id, |
| GLuint data_shm_offset, |
| GLuint data_size) { |
| NOTIMPLEMENTED(); |
| } |
| void DoUnlockTransferCacheEntryINTERNAL(GLuint entry_type, GLuint entry_id) { |
| NOTIMPLEMENTED(); |
| } |
| void DoDeleteTransferCacheEntryINTERNAL(GLuint entry_type, GLuint entry_id) { |
| NOTIMPLEMENTED(); |
| } |
| |
| #if defined(NDEBUG) |
| void LogClientServiceMapping(const char* /* function_name */, |
| GLuint /* client_id */, |
| GLuint /* service_id */) {} |
| template <typename T> |
| void LogClientServiceForInfo(T* /* info */, |
| GLuint /* client_id */, |
| const char* /* function_name */) {} |
| #else |
| void LogClientServiceMapping(const char* function_name, |
| GLuint client_id, |
| GLuint service_id) { |
| if (service_logging_) { |
| VLOG(1) << "[" << logger_.GetLogPrefix() << "] " << function_name |
| << ": client_id = " << client_id |
| << ", service_id = " << service_id; |
| } |
| } |
| template <typename T> |
| void LogClientServiceForInfo(T* info, |
| GLuint client_id, |
| const char* function_name) { |
| if (info) { |
| LogClientServiceMapping(function_name, client_id, info->service_id()); |
| } |
| } |
| #endif |
| |
| // Generate a member function prototype for each command in an automated and |
| // typesafe way. |
| #define RASTER_CMD_OP(name) \ |
| Error Handle##name(uint32_t immediate_data_size, const volatile void* data); |
| |
| RASTER_COMMAND_LIST(RASTER_CMD_OP) |
| #undef RASTER_CMD_OP |
| |
| typedef error::Error (RasterDecoderImpl::*CmdHandler)( |
| uint32_t immediate_data_size, |
| const volatile void* data); |
| |
| // A struct to hold info about each command. |
| struct CommandInfo { |
| CmdHandler cmd_handler; |
| uint8_t arg_flags; // How to handle the arguments for this command |
| uint8_t cmd_flags; // How to handle this command |
| uint16_t arg_count; // How many arguments are expected for this command. |
| }; |
| |
| // A table of CommandInfo for all the commands. |
| static const CommandInfo command_info[kNumCommands - kFirstRasterCommand]; |
| |
| // Number of commands remaining to be processed in DoCommands(). |
| int commands_to_process_; |
| |
| // The current decoder error communicates the decoder error through command |
| // processing functions that do not return the error value. Should be set |
| // only if not returning an error. |
| error::Error current_decoder_error_; |
| |
| scoped_refptr<gl::GLSurface> surface_; |
| scoped_refptr<gl::GLContext> context_; |
| |
| DecoderClient* client_; |
| |
| gles2::DebugMarkerManager debug_marker_manager_; |
| gles2::Logger logger_; |
| |
| // The ContextGroup for this decoder uses to track resources. |
| scoped_refptr<gles2::ContextGroup> group_; |
| const gles2::Validators* validators_; |
| scoped_refptr<gles2::FeatureInfo> feature_info_; |
| |
| // All the state for this context. |
| gles2::ContextState state_; |
| |
| GLES2Util util_; |
| |
| bool gpu_debug_commands_; |
| |
| // Log extra info. |
| bool service_logging_; |
| |
| base::WeakPtrFactory<DecoderContext> weak_ptr_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RasterDecoderImpl); |
| }; |
| |
| constexpr RasterDecoderImpl::CommandInfo RasterDecoderImpl::command_info[] = { |
| #define RASTER_CMD_OP(name) \ |
| { \ |
| &RasterDecoderImpl::Handle##name, cmds::name::kArgFlags, \ |
| cmds::name::cmd_flags, \ |
| sizeof(cmds::name) / sizeof(CommandBufferEntry) - 1, \ |
| }, /* NOLINT */ |
| RASTER_COMMAND_LIST(RASTER_CMD_OP) |
| #undef RASTER_CMD_OP |
| }; |
| |
| // static |
| RasterDecoder* RasterDecoder::Create( |
| DecoderClient* client, |
| CommandBufferServiceBase* command_buffer_service, |
| Outputter* outputter, |
| ContextGroup* group) { |
| return new RasterDecoderImpl(client, command_buffer_service, outputter, |
| group); |
| } |
| |
| RasterDecoder::RasterDecoder(CommandBufferServiceBase* command_buffer_service) |
| : CommonDecoder(command_buffer_service), |
| initialized_(false), |
| debug_(false), |
| log_commands_(false) {} |
| |
| RasterDecoder::~RasterDecoder() {} |
| |
| bool RasterDecoder::initialized() const { |
| return initialized_; |
| } |
| |
| TextureBase* RasterDecoder::GetTextureBase(uint32_t client_id) { |
| return nullptr; |
| } |
| |
| void RasterDecoder::BeginDecoding() {} |
| |
| void RasterDecoder::EndDecoding() {} |
| |
| base::StringPiece RasterDecoder::GetLogPrefix() { |
| return GetLogger()->GetLogPrefix(); |
| } |
| |
| RasterDecoderImpl::RasterDecoderImpl( |
| DecoderClient* client, |
| CommandBufferServiceBase* command_buffer_service, |
| Outputter* outputter, |
| ContextGroup* group) |
| : RasterDecoder(command_buffer_service), |
| commands_to_process_(0), |
| current_decoder_error_(error::kNoError), |
| client_(client), |
| logger_(&debug_marker_manager_, client), |
| group_(group), |
| validators_(group_->feature_info()->validators()), |
| feature_info_(group_->feature_info()), |
| state_(group_->feature_info(), this, &logger_), |
| service_logging_( |
| group_->gpu_preferences().enable_gpu_service_logging_gpu), |
| weak_ptr_factory_(this) {} |
| |
| RasterDecoderImpl::~RasterDecoderImpl() {} |
| |
| base::WeakPtr<DecoderContext> RasterDecoderImpl::AsWeakPtr() { |
| return weak_ptr_factory_.GetWeakPtr(); |
| } |
| |
| gpu::ContextResult RasterDecoderImpl::Initialize( |
| const scoped_refptr<gl::GLSurface>& surface, |
| const scoped_refptr<gl::GLContext>& context, |
| bool offscreen, |
| const DisallowedFeatures& disallowed_features, |
| const ContextCreationAttribs& attrib_helper) { |
| TRACE_EVENT0("gpu", "RasterDecoderImpl::Initialize"); |
| DCHECK(context->IsCurrent(surface.get())); |
| DCHECK(!context_.get()); |
| |
| state_.set_api(gl::g_current_gl_context); |
| |
| set_initialized(); |
| |
| if (!offscreen) { |
| return gpu::ContextResult::kFatalFailure; |
| } |
| |
| if (group_->gpu_preferences().enable_gpu_debugging) |
| set_debug(true); |
| |
| if (group_->gpu_preferences().enable_gpu_command_logging) |
| set_log_commands(true); |
| |
| surface_ = surface; |
| context_ = context; |
| |
| auto result = |
| group_->Initialize(this, attrib_helper.context_type, disallowed_features); |
| if (result != gpu::ContextResult::kSuccess) { |
| group_ = |
| nullptr; // Must not destroy ContextGroup if it is not initialized. |
| Destroy(true); |
| return result; |
| } |
| CHECK_GL_ERROR(); |
| |
| state_.texture_units.resize(group_->max_texture_units()); |
| state_.sampler_units.resize(group_->max_texture_units()); |
| for (uint32_t tt = 0; tt < state_.texture_units.size(); ++tt) { |
| api()->glActiveTextureFn(GL_TEXTURE0 + tt); |
| TextureRef* ref; |
| ref = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_2D); |
| state_.texture_units[tt].bound_texture_2d = ref; |
| api()->glBindTextureFn(GL_TEXTURE_2D, ref ? ref->service_id() : 0); |
| } |
| api()->glActiveTextureFn(GL_TEXTURE0); |
| CHECK_GL_ERROR(); |
| |
| return gpu::ContextResult::kSuccess; |
| } |
| |
| const gles2::ContextState* RasterDecoderImpl::GetContextState() { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| |
| void RasterDecoderImpl::Destroy(bool have_context) { |
| if (group_.get()) { |
| group_->Destroy(this, have_context); |
| group_ = NULL; |
| } |
| |
| // Destroy the surface before the context, some surface destructors make GL |
| // calls. |
| surface_ = nullptr; |
| |
| if (context_.get()) { |
| context_->ReleaseCurrent(NULL); |
| context_ = NULL; |
| } |
| } |
| |
| // Make this decoder's GL context current. |
| bool RasterDecoderImpl::MakeCurrent() { |
| DCHECK(surface_); |
| if (!context_.get()) |
| return false; |
| |
| if (WasContextLost()) { |
| LOG(ERROR) << " RasterDecoderImpl: Trying to make lost context current."; |
| return false; |
| } |
| |
| if (!context_->MakeCurrent(surface_.get())) { |
| LOG(ERROR) << " RasterDecoderImpl: Context lost during MakeCurrent."; |
| MarkContextLost(error::kMakeCurrentFailed); |
| group_->LoseContexts(error::kUnknown); |
| return false; |
| } |
| return true; |
| } |
| |
| gl::GLContext* RasterDecoderImpl::GetGLContext() { |
| return context_.get(); |
| } |
| |
| Capabilities RasterDecoderImpl::GetCapabilities() { |
| gpu::Capabilities caps; |
| caps.gpu_rasterization = true; |
| caps.supports_oop_raster = true; |
| caps.texture_target_exception_list = |
| group_->gpu_preferences().texture_target_exception_list; |
| return caps; |
| } |
| |
| void RasterDecoderImpl::RestoreState(const ContextState* prev_state) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreActiveTexture() const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreAllTextureUnitAndSamplerBindings( |
| const ContextState* prev_state) const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreActiveTextureUnitBinding( |
| unsigned int target) const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreBufferBinding(unsigned int target) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreBufferBindings() const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreFramebufferBindings() const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreRenderbufferBindings() { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreProgramBindings() const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreTextureState(unsigned service_id) const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreTextureUnitBindings(unsigned unit) const { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreVertexAttribArray(unsigned index) { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::RestoreAllExternalTextureBindingsIfNeeded() { |
| NOTIMPLEMENTED(); |
| } |
| |
| QueryManager* RasterDecoderImpl::GetQueryManager() { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| |
| GpuFenceManager* RasterDecoderImpl::GetGpuFenceManager() { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| |
| bool RasterDecoderImpl::HasPendingQueries() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void RasterDecoderImpl::ProcessPendingQueries(bool did_finish) { |
| NOTIMPLEMENTED(); |
| } |
| |
| bool RasterDecoderImpl::HasMoreIdleWork() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void RasterDecoderImpl::PerformIdleWork() { |
| NOTIMPLEMENTED(); |
| } |
| |
| bool RasterDecoderImpl::HasPollingWork() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void RasterDecoderImpl::PerformPollingWork() { |
| NOTIMPLEMENTED(); |
| } |
| |
| TextureBase* RasterDecoderImpl::GetTextureBase(uint32_t client_id) { |
| NOTIMPLEMENTED(); |
| return nullptr; |
| } |
| |
| bool RasterDecoderImpl::WasContextLost() const { |
| return false; |
| } |
| |
| bool RasterDecoderImpl::WasContextLostByRobustnessExtension() const { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| void RasterDecoderImpl::MarkContextLost(error::ContextLostReason reason) { |
| NOTIMPLEMENTED(); |
| } |
| |
| bool RasterDecoderImpl::CheckResetStatus() { |
| NOTIMPLEMENTED(); |
| return false; |
| } |
| |
| Logger* RasterDecoderImpl::GetLogger() { |
| return &logger_; |
| } |
| |
| void RasterDecoderImpl::SetIgnoreCachedStateForTest(bool ignore) { |
| state_.SetIgnoreCachedStateForTest(ignore); |
| } |
| |
| void RasterDecoderImpl::BeginDecoding() { |
| // TODO(backer): Add support the tracing commands. |
| gpu_debug_commands_ = log_commands() || debug(); |
| } |
| |
| void RasterDecoderImpl::EndDecoding() { |
| NOTIMPLEMENTED(); |
| } |
| |
| const char* RasterDecoderImpl::GetCommandName(unsigned int command_id) const { |
| if (command_id >= kFirstRasterCommand && command_id < kNumCommands) { |
| return raster::GetCommandName(static_cast<CommandId>(command_id)); |
| } |
| return GetCommonCommandName(static_cast<cmd::CommandId>(command_id)); |
| } |
| |
| template <bool DebugImpl> |
| error::Error RasterDecoderImpl::DoCommandsImpl(unsigned int num_commands, |
| const volatile void* buffer, |
| int num_entries, |
| int* entries_processed) { |
| DCHECK(entries_processed); |
| commands_to_process_ = num_commands; |
| error::Error result = error::kNoError; |
| const volatile CommandBufferEntry* cmd_data = |
| static_cast<const volatile CommandBufferEntry*>(buffer); |
| int process_pos = 0; |
| unsigned int command = 0; |
| |
| while (process_pos < num_entries && result == error::kNoError && |
| commands_to_process_--) { |
| const unsigned int size = cmd_data->value_header.size; |
| command = cmd_data->value_header.command; |
| |
| if (size == 0) { |
| result = error::kInvalidSize; |
| break; |
| } |
| |
| if (static_cast<int>(size) + process_pos > num_entries) { |
| result = error::kOutOfBounds; |
| break; |
| } |
| |
| if (DebugImpl && log_commands()) { |
| LOG(ERROR) << "[" << logger_.GetLogPrefix() << "]" |
| << "cmd: " << GetCommandName(command); |
| } |
| |
| const unsigned int arg_count = size - 1; |
| unsigned int command_index = command - kFirstRasterCommand; |
| if (command_index < arraysize(command_info)) { |
| const CommandInfo& info = command_info[command_index]; |
| unsigned int info_arg_count = static_cast<unsigned int>(info.arg_count); |
| if ((info.arg_flags == cmd::kFixed && arg_count == info_arg_count) || |
| (info.arg_flags == cmd::kAtLeastN && arg_count >= info_arg_count)) { |
| uint32_t immediate_data_size = (arg_count - info_arg_count) * |
| sizeof(CommandBufferEntry); // NOLINT |
| result = (this->*info.cmd_handler)(immediate_data_size, cmd_data); |
| if (DebugImpl && debug() && !WasContextLost()) { |
| GLenum error; |
| while ((error = api()->glGetErrorFn()) != GL_NO_ERROR) { |
| LOG(ERROR) << "[" << logger_.GetLogPrefix() << "] " |
| << "GL ERROR: " << GLES2Util::GetStringEnum(error) |
| << " : " << GetCommandName(command); |
| LOCAL_SET_GL_ERROR(error, "DoCommand", "GL error from driver"); |
| } |
| } |
| } else { |
| result = error::kInvalidArguments; |
| } |
| } else { |
| result = DoCommonCommand(command, arg_count, cmd_data); |
| } |
| |
| if (result == error::kNoError && |
| current_decoder_error_ != error::kNoError) { |
| result = current_decoder_error_; |
| current_decoder_error_ = error::kNoError; |
| } |
| |
| if (result != error::kDeferCommandUntilLater) { |
| process_pos += size; |
| cmd_data += size; |
| } |
| } |
| |
| *entries_processed = process_pos; |
| |
| if (error::IsError(result)) { |
| LOG(ERROR) << "Error: " << result << " for Command " |
| << GetCommandName(command); |
| } |
| |
| return result; |
| } |
| |
| error::Error RasterDecoderImpl::DoCommands(unsigned int num_commands, |
| const volatile void* buffer, |
| int num_entries, |
| int* entries_processed) { |
| if (gpu_debug_commands_) { |
| return DoCommandsImpl<true>(num_commands, buffer, num_entries, |
| entries_processed); |
| } else { |
| return DoCommandsImpl<false>(num_commands, buffer, num_entries, |
| entries_processed); |
| } |
| } |
| |
| bool RasterDecoderImpl::GetHelper(GLenum pname, |
| GLint* params, |
| GLsizei* num_written) { |
| DCHECK(num_written); |
| switch (pname) { |
| case GL_MAX_TEXTURE_SIZE: |
| *num_written = 1; |
| if (params) { |
| params[0] = texture_manager()->MaxSizeForTarget(GL_TEXTURE_2D); |
| } |
| return true; |
| default: |
| *num_written = util_.GLGetNumValuesReturned(pname); |
| if (*num_written) |
| break; |
| |
| return false; |
| } |
| |
| // TODO(backer): Only GL_ACTIVE_TEXTURE supported? |
| if (pname != GL_ACTIVE_TEXTURE) { |
| return false; |
| } |
| |
| if (params) { |
| api()->glGetIntegervFn(pname, params); |
| } |
| return true; |
| } |
| |
| bool RasterDecoderImpl::GetNumValuesReturnedForGLGet(GLenum pname, |
| GLsizei* num_values) { |
| *num_values = 0; |
| if (state_.GetStateAsGLint(pname, NULL, num_values)) { |
| return true; |
| } |
| return GetHelper(pname, NULL, num_values); |
| } |
| |
| base::StringPiece RasterDecoderImpl::GetLogPrefix() { |
| return logger_.GetLogPrefix(); |
| } |
| |
| void RasterDecoderImpl::BindImage(uint32_t client_texture_id, |
| uint32_t texture_target, |
| gl::GLImage* image, |
| bool can_bind_to_sampler) { |
| NOTIMPLEMENTED(); |
| } |
| |
| gles2::ContextGroup* RasterDecoderImpl::GetContextGroup() { |
| return group_.get(); |
| } |
| |
| gles2::ErrorState* RasterDecoderImpl::GetErrorState() { |
| return state_.GetErrorState(); |
| } |
| |
| void RasterDecoderImpl::OnContextLostError() { |
| NOTIMPLEMENTED(); |
| } |
| |
| void RasterDecoderImpl::OnOutOfMemoryError() { |
| NOTIMPLEMENTED(); |
| } |
| |
| error::Error RasterDecoderImpl::HandleWaitSyncTokenCHROMIUM( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| const volatile gles2::cmds::WaitSyncTokenCHROMIUM& c = |
| *static_cast<const volatile gles2::cmds::WaitSyncTokenCHROMIUM*>( |
| cmd_data); |
| |
| const gpu::CommandBufferNamespace kMinNamespaceId = |
| gpu::CommandBufferNamespace::INVALID; |
| const gpu::CommandBufferNamespace kMaxNamespaceId = |
| gpu::CommandBufferNamespace::NUM_COMMAND_BUFFER_NAMESPACES; |
| |
| gpu::CommandBufferNamespace namespace_id = |
| static_cast<gpu::CommandBufferNamespace>(c.namespace_id); |
| if ((namespace_id < static_cast<int32_t>(kMinNamespaceId)) || |
| (namespace_id >= static_cast<int32_t>(kMaxNamespaceId))) { |
| namespace_id = gpu::CommandBufferNamespace::INVALID; |
| } |
| const CommandBufferId command_buffer_id = |
| CommandBufferId::FromUnsafeValue(c.command_buffer_id()); |
| const uint64_t release = c.release_count(); |
| |
| gpu::SyncToken sync_token; |
| sync_token.Set(namespace_id, command_buffer_id, release); |
| return client_->OnWaitSyncToken(sync_token) ? error::kDeferCommandUntilLater |
| : error::kNoError; |
| } |
| |
| error::Error RasterDecoderImpl::HandleBeginQueryEXT( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| NOTIMPLEMENTED(); |
| return error::kNoError; |
| } |
| |
| error::Error RasterDecoderImpl::HandleEndQueryEXT( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| NOTIMPLEMENTED(); |
| return error::kNoError; |
| } |
| |
| error::Error RasterDecoderImpl::HandleInitializeDiscardableTextureCHROMIUM( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| NOTIMPLEMENTED(); |
| return error::kNoError; |
| } |
| |
| error::Error RasterDecoderImpl::HandleUnlockDiscardableTextureCHROMIUM( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| NOTIMPLEMENTED(); |
| return error::kNoError; |
| } |
| |
| error::Error RasterDecoderImpl::HandleLockDiscardableTextureCHROMIUM( |
| uint32_t immediate_data_size, |
| const volatile void* cmd_data) { |
| NOTIMPLEMENTED(); |
| return error::kNoError; |
| } |
| |
| void RasterDecoderImpl::DoFinish() { |
| api()->glFinishFn(); |
| ProcessPendingQueries(true); |
| } |
| |
| void RasterDecoderImpl::DoFlush() { |
| api()->glFlushFn(); |
| ProcessPendingQueries(false); |
| } |
| |
| void RasterDecoderImpl::DoGetIntegerv(GLenum pname, |
| GLint* params, |
| GLsizei params_size) { |
| DCHECK(params); |
| GLsizei num_written = 0; |
| if (state_.GetStateAsGLint(pname, params, &num_written) || |
| GetHelper(pname, params, &num_written)) { |
| DCHECK_EQ(num_written, params_size); |
| return; |
| } |
| NOTREACHED() << "Unhandled enum " << pname; |
| } |
| |
| void RasterDecoderImpl::DeleteTexturesHelper( |
| GLsizei n, |
| const volatile GLuint* client_ids) { |
| for (GLsizei ii = 0; ii < n; ++ii) { |
| GLuint client_id = client_ids[ii]; |
| TextureRef* texture_ref = GetTexture(client_id); |
| if (texture_ref) { |
| UnbindTexture(texture_ref); |
| RemoveTexture(client_id); |
| } |
| } |
| } |
| |
| bool RasterDecoderImpl::GenTexturesHelper(GLsizei n, const GLuint* client_ids) { |
| for (GLsizei ii = 0; ii < n; ++ii) { |
| if (GetTexture(client_ids[ii])) { |
| return false; |
| } |
| } |
| std::unique_ptr<GLuint[]> service_ids(new GLuint[n]); |
| api()->glGenTexturesFn(n, service_ids.get()); |
| for (GLsizei ii = 0; ii < n; ++ii) { |
| CreateTexture(client_ids[ii], service_ids[ii]); |
| } |
| return true; |
| } |
| |
| void RasterDecoderImpl::DoTexParameteri(GLenum target, |
| GLenum pname, |
| GLint param) { |
| TextureRef* texture = |
| texture_manager()->GetTextureInfoForTarget(&state_, target); |
| if (!texture) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glTexParameteri", "unknown texture"); |
| return; |
| } |
| |
| texture_manager()->SetParameteri("glTexParameteri", GetErrorState(), texture, |
| pname, param); |
| } |
| |
| void RasterDecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { |
| TextureRef* texture_ref = NULL; |
| GLuint service_id = 0; |
| if (client_id != 0) { |
| texture_ref = GetTexture(client_id); |
| if (!texture_ref) { |
| if (!group_->bind_generates_resource()) { |
| LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glBindTexture", |
| "id not generated by glGenTextures"); |
| return; |
| } |
| |
| // It's a new id so make a texture texture for it. |
| api()->glGenTexturesFn(1, &service_id); |
| DCHECK_NE(0u, service_id); |
| CreateTexture(client_id, service_id); |
| texture_ref = GetTexture(client_id); |
| } |
| } else { |
| texture_ref = texture_manager()->GetDefaultTextureInfo(target); |
| } |
| |
| // Check the texture exists |
| 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"); |
| api()->glBindTextureFn(target, texture->service_id()); |
| if (texture->target() == 0) { |
| texture_manager()->SetTarget(texture_ref, target); |
| if (!gl_version_info().BehavesLikeGLES() && |
| gl_version_info().IsAtLeastGL(3, 2)) { |
| // In Desktop GL core profile and GL ES, depth textures are always |
| // sampled to the RED channel, whereas on Desktop GL compatibility |
| // proifle, they are sampled to RED, LUMINANCE, INTENSITY, or ALPHA |
| // channel, depending on the DEPTH_TEXTURE_MODE value. |
| // In theory we only need to apply this for depth textures, but it is |
| // simpler to apply to all textures. |
| api()->glTexParameteriFn(target, GL_DEPTH_TEXTURE_MODE, GL_RED); |
| } |
| } |
| } else { |
| api()->glBindTextureFn(target, 0); |
| } |
| |
| TextureUnit& unit = state_.texture_units[state_.active_texture_unit]; |
| unit.bind_target = target; |
| unit.SetInfoForTarget(target, texture_ref); |
| } |
| |
| // Include the auto-generated part of this file. We split this because it means |
| // we can easily edit the non-auto generated parts right here in this file |
| // instead of having to edit some template or the code generator. |
| #include "base/macros.h" |
| #include "gpu/command_buffer/service/raster_decoder_autogen.h" |
| |
| } // namespace raster |
| } // namespace gpu |