diff options
Diffstat (limited to 'gpu/command_buffer')
21 files changed, 784 insertions, 132 deletions
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index 36dad3f..7d00e42 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -225,6 +225,7 @@ GL_APICALL void GL_APIENTRY glDestroyStreamTextureCHROMIUM (GLuint textu GL_APICALL void GL_APIENTRY glPlaceholder453CHROMIUM (void); GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLidShader shader, GLsizeiNotNegative bufsize, GLsizei* length, char* source); GL_APICALL void GL_APIENTRY glPostSubBufferCHROMIUM (GLint x, GLint y, GLint width, GLint height); +GL_APICALL void GL_APIENTRY glTexImageIOSurface2DCHROMIUM (GLenumTextureBindTarget target, GLsizei width, GLsizei height, GLuint ioSurfaceId, GLuint plane); """ # This is the list of all commmands that will be generated and their Id. @@ -435,6 +436,7 @@ _CMD_ID_TABLE = { 'GetProgramInfoCHROMIUM': 455, 'GetTranslatedShaderSourceANGLE': 456, 'PostSubBufferCHROMIUM': 457, + 'TexImageIOSurface2DCHROMIUM': 458, } # This is a list of enum names and their valid values. It is used to map @@ -1793,6 +1795,12 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, }, + 'TexImageIOSurface2DCHROMIUM': { + 'decoder_func': 'DoTexImageIOSurface2DCHROMIUM', + 'unit_test': False, + 'extension': True, + 'chromium': True, + }, } diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index 40c7102..d7fde69 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -589,6 +589,12 @@ void GLES2GetTranslatedShaderSourceANGLE( void GLES2PostSubBufferCHROMIUM(GLint x, GLint y, GLint width, GLint height) { gles2::GetGLContext()->PostSubBufferCHROMIUM(x, y, width, height); } +void GLES2TexImageIOSurface2DCHROMIUM( + GLenum target, GLsizei width, GLsizei height, GLuint ioSurfaceId, + GLuint plane) { + gles2::GetGLContext()->TexImageIOSurface2DCHROMIUM( + target, width, height, ioSurfaceId, plane); +} #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_C_LIB_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 2a5d6d7..8e1ec4e 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1253,5 +1253,13 @@ c.Init(x, y, width, height); } + void TexImageIOSurface2DCHROMIUM( + GLenum target, GLsizei width, GLsizei height, GLuint ioSurfaceId, + GLuint plane) { + gles2::TexImageIOSurface2DCHROMIUM& c = + GetCmdSpace<gles2::TexImageIOSurface2DCHROMIUM>(); + c.Init(target, width, height, ioSurfaceId, plane); + } + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_CMD_HELPER_AUTOGEN_H_ diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 0721c79..978abf8 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -1305,5 +1305,21 @@ void GetTranslatedShaderSourceANGLE( } void PostSubBufferCHROMIUM(GLint x, GLint y, GLint width, GLint height); +void TexImageIOSurface2DCHROMIUM( + GLenum target, GLsizei width, GLsizei height, GLuint ioSurfaceId, + GLuint plane) { + GPU_CLIENT_LOG("[" << this << "] glTexImageIOSurface2DCHROMIUM(" << GLES2Util::GetStringTextureBindTarget(target) << ", " << width << ", " << height << ", " << ioSurfaceId << ", " << plane << ")"); // NOLINT + if (width < 0) { + SetGLError(GL_INVALID_VALUE, "glTexImageIOSurface2DCHROMIUM: width < 0"); + return; + } + if (height < 0) { + SetGLError(GL_INVALID_VALUE, "glTexImageIOSurface2DCHROMIUM: height < 0"); + return; + } + helper_->TexImageIOSurface2DCHROMIUM( + target, width, height, ioSurfaceId, plane); +} + #endif // GPU_COMMAND_BUFFER_CLIENT_GLES2_IMPLEMENTATION_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index cb54dda..2e726f4 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -9211,6 +9211,61 @@ COMPILE_ASSERT(offsetof(PostSubBufferCHROMIUM, width) == 12, COMPILE_ASSERT(offsetof(PostSubBufferCHROMIUM, height) == 16, OffsetOf_PostSubBufferCHROMIUM_height_not_16); +struct TexImageIOSurface2DCHROMIUM { + typedef TexImageIOSurface2DCHROMIUM ValueType; + static const CommandId kCmdId = kTexImageIOSurface2DCHROMIUM; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init( + GLenum _target, GLsizei _width, GLsizei _height, GLuint _ioSurfaceId, + GLuint _plane) { + SetHeader(); + target = _target; + width = _width; + height = _height; + ioSurfaceId = _ioSurfaceId; + plane = _plane; + } + + void* Set( + void* cmd, GLenum _target, GLsizei _width, GLsizei _height, + GLuint _ioSurfaceId, GLuint _plane) { + static_cast<ValueType*>( + cmd)->Init(_target, _width, _height, _ioSurfaceId, _plane); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + int32 width; + int32 height; + uint32 ioSurfaceId; + uint32 plane; +}; + +COMPILE_ASSERT(sizeof(TexImageIOSurface2DCHROMIUM) == 24, + Sizeof_TexImageIOSurface2DCHROMIUM_is_not_24); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, header) == 0, + OffsetOf_TexImageIOSurface2DCHROMIUM_header_not_0); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, target) == 4, + OffsetOf_TexImageIOSurface2DCHROMIUM_target_not_4); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, width) == 8, + OffsetOf_TexImageIOSurface2DCHROMIUM_width_not_8); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, height) == 12, + OffsetOf_TexImageIOSurface2DCHROMIUM_height_not_12); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, ioSurfaceId) == 16, + OffsetOf_TexImageIOSurface2DCHROMIUM_ioSurfaceId_not_16); +COMPILE_ASSERT(offsetof(TexImageIOSurface2DCHROMIUM, plane) == 20, + OffsetOf_TexImageIOSurface2DCHROMIUM_plane_not_20); + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h index 9c414a9..9028708 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -3578,5 +3578,27 @@ TEST_F(GLES2FormatTest, PostSubBufferCHROMIUM) { next_cmd, sizeof(cmd)); } +TEST_F(GLES2FormatTest, TexImageIOSurface2DCHROMIUM) { + TexImageIOSurface2DCHROMIUM& cmd = + *GetBufferAs<TexImageIOSurface2DCHROMIUM>(); + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLsizei>(12), + static_cast<GLsizei>(13), + static_cast<GLuint>(14), + static_cast<GLuint>(15)); + EXPECT_EQ(static_cast<uint32>(TexImageIOSurface2DCHROMIUM::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLsizei>(12), cmd.width); + EXPECT_EQ(static_cast<GLsizei>(13), cmd.height); + EXPECT_EQ(static_cast<GLuint>(14), cmd.ioSurfaceId); + EXPECT_EQ(static_cast<GLuint>(15), cmd.plane); + CheckBytesWrittenMatchesExpectedSize( + next_cmd, sizeof(cmd)); +} + #endif // GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_FORMAT_TEST_AUTOGEN_H_ diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 498c625..6c01a6c 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -212,6 +212,7 @@ OP(GetProgramInfoCHROMIUM) /* 455 */ \ OP(GetTranslatedShaderSourceANGLE) /* 456 */ \ OP(PostSubBufferCHROMIUM) /* 457 */ \ + OP(TexImageIOSurface2DCHROMIUM) /* 458 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index 5834d2a0..22763b6 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc @@ -195,6 +195,8 @@ int GLES2Util::GLGetNumValuesReturned(int id) const { return 1; case GL_TEXTURE_BINDING_EXTERNAL_OES: return 1; + case GL_TEXTURE_BINDING_RECTANGLE_ARB: + return 1; case GL_UNPACK_ALIGNMENT: return 1; case GL_VIEWPORT: diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index 9b8d22b..72ddb4a 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -129,6 +129,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x84FE, "GL_TEXTURE_MAX_ANISOTROPY_EXT", }, { 0x0901, "GL_CCW", }, { 0x0900, "GL_CW", }, + { 0x8B63, "GL_SAMPLER_2D_RECT_ARB", }, { 0x8B60, "GL_SAMPLER_CUBE", }, { 0x00001000, "GL_DEPTH_BUFFER_BIT4_QCOM", }, { 0x00000080, "GL_COLOR_BUFFER_BIT7_QCOM", }, @@ -164,8 +165,10 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x813D, "GL_TEXTURE_MAX_LEVEL_APPLE", }, { 0x8CDD, "GL_FRAMEBUFFER_UNSUPPORTED", }, { 0x8CDF, "GL_MAX_COLOR_ATTACHMENTS_NV", }, + { 0x84F5, "GL_TEXTURE_RECTANGLE_ARB", }, { 0x882A, "GL_DRAW_BUFFER5_NV", }, { 0x80AA, "GL_SAMPLE_COVERAGE_VALUE", }, + { 0x84F6, "GL_TEXTURE_BINDING_RECTANGLE_ARB", }, { 0x80AB, "GL_SAMPLE_COVERAGE_INVERT", }, { 0x882B, "GL_DRAW_BUFFER6_NV", }, { 0x882C, "GL_DRAW_BUFFER7_NV", }, diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 6b26b91..66c05a8 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -8,6 +8,9 @@ #include "gpu/command_buffer/service/gl_utils.h" #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_implementation.h" +#if defined(OS_MACOSX) +#include "ui/gfx/surface/io_surface_support_mac.h" +#endif namespace gpu { namespace gles2 { @@ -354,6 +357,30 @@ void FeatureInfo::AddFeatures(const char* desired_features) { feature_flags_.chromium_stream_texture = true; } + // Ideally we would only expose this extension on Mac OS X, to + // support GL_CHROMIUM_iosurface and the compositor. We don't want + // applications to start using it; they should use ordinary non- + // power-of-two textures. However, for unit testing purposes we + // expose it on all supported platforms. + if (ext.HaveAndDesire("GL_ARB_texture_rectangle")) { + AddExtensionString("GL_ARB_texture_rectangle"); + feature_flags_.arb_texture_rectangle = true; + validators_.texture_bind_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); + // For the moment we don't add this enum to the texture_target + // validator. This implies that the only way to get image data into a + // rectangular texture is via glTexImageIOSurface2DCHROMIUM, which is + // just fine since again we don't want applications depending on this + // extension. + validators_.get_tex_param_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); + validators_.g_l_state.AddValue(GL_TEXTURE_BINDING_RECTANGLE_ARB); + } + +#if defined(OS_MACOSX) + if (IOSurfaceSupport::Initialize()) { + AddExtensionString("GL_CHROMIUM_iosurface"); + } +#endif + // TODO(gman): Add support for these extensions. // GL_OES_depth32 // GL_OES_element_index_uint diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index 485cbc9..fb4177b 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h @@ -25,7 +25,8 @@ class FeatureInfo { enable_texture_half_float_linear(false), chromium_webglsl(false), chromium_stream_texture(false), - angle_translated_shader_source(false) { + angle_translated_shader_source(false), + arb_texture_rectangle(false) { } bool chromium_framebuffer_multisample; @@ -37,6 +38,7 @@ class FeatureInfo { bool chromium_webglsl; bool chromium_stream_texture; bool angle_translated_shader_source; + bool arb_texture_rectangle; }; FeatureInfo(); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 70c7484..6ba84f9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -15,6 +15,9 @@ #include "base/atomicops.h" #include "base/at_exit.h" #include "base/bind.h" +#if defined(OS_MACOSX) +#include "base/mac/scoped_cftyperef.h" +#endif #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "build/build_config.h" @@ -41,6 +44,9 @@ #include "ui/gfx/gl/gl_context.h" #include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/gl/gl_surface.h" +#if defined(OS_MACOSX) +#include "ui/gfx/surface/io_surface_support_mac.h" +#endif #if !defined(GL_DEPTH24_STENCIL8) #define GL_DEPTH24_STENCIL8 0x88F0 @@ -560,12 +566,26 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // glBindTexture TextureManager::TextureInfo::Ref bound_texture_external_oes; + // texture currently bound to this unit's GL_TEXTURE_RECTANGLE_ARB with + // glBindTexture + TextureManager::TextureInfo::Ref bound_texture_rectangle_arb; + TextureManager::TextureInfo::Ref GetInfoForSamplerType(GLenum type) { DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || - type == GL_SAMPLER_EXTERNAL_OES); - return type == GL_SAMPLER_2D ? bound_texture_2d : - (type == GL_SAMPLER_EXTERNAL_OES ? bound_texture_external_oes : - bound_texture_cube_map); + type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); + switch (type) { + case GL_SAMPLER_2D: + return bound_texture_2d; + case GL_SAMPLER_CUBE: + return bound_texture_cube_map; + case GL_SAMPLER_EXTERNAL_OES: + return bound_texture_external_oes; + case GL_SAMPLER_2D_RECT_ARB: + return bound_texture_rectangle_arb; + } + + NOTREACHED(); + return NULL; } void Unbind(TextureManager::TextureInfo* texture) { @@ -723,6 +743,14 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLenum type, const void * data); + // Wrapper for TexImageIOSurface2DCHROMIUM. + void DoTexImageIOSurface2DCHROMIUM( + GLenum target, + GLsizei width, + GLsizei height, + GLuint io_surface_id, + GLuint plane); + // Creates a ProgramInfo for the given program. ProgramManager::ProgramInfo* CreateProgramInfo( GLuint client_id, GLuint service_id) { @@ -1181,10 +1209,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, case GL_TEXTURE_EXTERNAL_OES: info = unit.bound_texture_external_oes; break; - // Note: If we ever support TEXTURE_RECTANGLE as a target, be sure to - // track |texture_| with the currently bound TEXTURE_RECTANGLE texture, - // because |texture_| is used by the FBO rendering mechanism for readback - // to the bits that get sent to the browser. + case GL_TEXTURE_RECTANGLE_ARB: + info = unit.bound_texture_rectangle_arb; + break; default: NOTREACHED(); return NULL; @@ -1194,10 +1221,20 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLenum GetBindTargetForSamplerType(GLenum type) { DCHECK(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || - type == GL_SAMPLER_EXTERNAL_OES); - return type == GL_SAMPLER_2D ? GL_TEXTURE_2D : - (type == GL_SAMPLER_EXTERNAL_OES ? GL_TEXTURE_EXTERNAL_OES : - GL_TEXTURE_CUBE_MAP); + type == GL_SAMPLER_EXTERNAL_OES || type == GL_SAMPLER_2D_RECT_ARB); + switch (type) { + case GL_SAMPLER_2D: + return GL_TEXTURE_2D; + case GL_SAMPLER_CUBE: + return GL_TEXTURE_CUBE_MAP; + case GL_SAMPLER_EXTERNAL_OES: + return GL_TEXTURE_EXTERNAL_OES; + case GL_SAMPLER_2D_RECT_ARB: + return GL_TEXTURE_RECTANGLE_ARB; + } + + NOTREACHED(); + return 0; } // Gets the framebuffer info for a particular target. @@ -1245,6 +1282,10 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Returns true if the context was just lost due to e.g. GL_ARB_robustness. bool WasContextLost(); +#if defined(OS_MACOSX) + void ReleaseIOSurfaceForTexture(GLuint texture_id); +#endif + // Generate a member function prototype for each command in an automated and // typesafe way. #define GLES2_CMD_OP(name) \ @@ -1422,6 +1463,11 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, bool force_webgl_glsl_validation_; bool derivatives_explicitly_enabled_; +#if defined(OS_MACOSX) + typedef std::map<GLuint, CFTypeRef> TextureToIOSurfaceMap; + TextureToIOSurfaceMap texture_to_io_surface_map_; +#endif + DISALLOW_COPY_AND_ASSIGN(GLES2DecoderImpl); }; @@ -1883,6 +1929,11 @@ bool GLES2DecoderImpl::Initialize( texture_units_[tt].bound_texture_external_oes = info; glBindTexture(GL_TEXTURE_EXTERNAL_OES, info->service_id()); } + if (feature_info_->feature_flags().arb_texture_rectangle) { + info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_RECTANGLE_ARB); + texture_units_[tt].bound_texture_rectangle_arb = info; + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, info->service_id()); + } info = texture_manager()->GetDefaultTextureInfo(GL_TEXTURE_CUBE_MAP); texture_units_[tt].bound_texture_cube_map = info; glBindTexture(GL_TEXTURE_CUBE_MAP, info->service_id()); @@ -2103,6 +2154,8 @@ bool GLES2DecoderImpl::InitializeShaderTranslator() { } else { resources.OES_standard_derivatives = feature_info_->feature_flags().oes_standard_derivatives ? 1 : 0; + resources.ARB_texture_rectangle = + feature_info_->feature_flags().arb_texture_rectangle ? 1 : 0; } vertex_translator_.reset(new ShaderTranslator); @@ -2306,6 +2359,11 @@ void GLES2DecoderImpl::DeleteTexturesHelper( if (texture->IsStreamTexture() && stream_texture_manager_) { stream_texture_manager_->DestroyStreamTexture(service_id); } +#if defined(OS_MACOSX) + if (texture->target() == GL_TEXTURE_RECTANGLE_ARB) { + ReleaseIOSurfaceForTexture(service_id); + } +#endif glDeleteTextures(1, &service_id); RemoveTextureInfo(client_ids[ii]); } @@ -2618,6 +2676,14 @@ void GLES2DecoderImpl::Destroy() { offscreen_saved_color_texture_.reset(); offscreen_resolved_frame_buffer_.reset(); offscreen_resolved_color_texture_.reset(); + +#if defined(OS_MACOSX) + for (TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.begin(); + it != texture_to_io_surface_map_.end(); ++it) { + CFRelease(it->second); + } + texture_to_io_surface_map_.clear(); +#endif } bool GLES2DecoderImpl::SetParent(GLES2Decoder* new_parent, @@ -3131,6 +3197,9 @@ void GLES2DecoderImpl::DoBindTexture(GLenum target, GLuint client_id) { stream_tex->Update(); } break; + case GL_TEXTURE_RECTANGLE_ARB: + unit.bound_texture_rectangle_arb = info; + break; default: NOTREACHED(); // Validation should prevent us getting here. break; @@ -3473,6 +3542,20 @@ bool GLES2DecoderImpl::GetHelper( } } return true; + case GL_TEXTURE_BINDING_RECTANGLE_ARB: + *num_written = 1; + if (params) { + TextureUnit& unit = texture_units_[active_texture_unit_]; + if (unit.bound_texture_rectangle_arb) { + GLuint client_id = 0; + texture_manager()->GetClientId( + unit.bound_texture_rectangle_arb->service_id(), &client_id); + *params = client_id; + } else { + *params = 0; + } + } + return true; default: *num_written = util_.GLGetNumValuesReturned(pname); return false; @@ -7486,6 +7569,112 @@ error::Error GLES2DecoderImpl::HandleDestroyStreamTextureCHROMIUM( return error::kNoError; } +#if defined(OS_MACOSX) +void GLES2DecoderImpl::ReleaseIOSurfaceForTexture(GLuint texture_id) { + TextureToIOSurfaceMap::iterator it = texture_to_io_surface_map_.find( + texture_id); + if (it != texture_to_io_surface_map_.end()) { + // Found a previous IOSurface bound to this texture; release it. + CFTypeRef surface = it->second; + CFRelease(surface); + texture_to_io_surface_map_.erase(it); + } +} +#endif + +void GLES2DecoderImpl::DoTexImageIOSurface2DCHROMIUM( + GLenum target, GLsizei width, GLsizei height, + GLuint io_surface_id, GLuint plane) { +#if defined(OS_MACOSX) + if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) { + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: only supported on desktop GL."); + return; + } + + IOSurfaceSupport* surface_support = IOSurfaceSupport::Initialize(); + if (!surface_support) { + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: only supported on 10.6."); + return; + } + + if (target != GL_TEXTURE_RECTANGLE_ARB) { + // This might be supported in the future, and if we could require + // support for binding an IOSurface to a NPOT TEXTURE_2D texture, we + // could delete a lot of code. For now, perform strict validation so we + // know what's going on. + SetGLError( + GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: requires TEXTURE_RECTANGLE_ARB target"); + return; + } + + TextureManager::TextureInfo* info = GetTextureInfoForTarget(target); + if (!info) { + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: no rectangle texture bound"); + return; + } + if (info == texture_manager()->GetDefaultTextureInfo(target)) { + // Maybe this is conceptually valid, but disallow it to avoid accidents. + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: can't bind default texture"); + return; + } + + // Look up the new IOSurface. Note that because of asynchrony + // between processes this might fail; during live resizing the + // plugin process might allocate and release an IOSurface before + // this process gets a chance to look it up. Hold on to any old + // IOSurface in this case. + CFTypeRef surface = surface_support->IOSurfaceLookup(io_surface_id); + if (!surface) { + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: no IOSurface with the given ID"); + return; + } + + // Release any IOSurface previously bound to this texture. + ReleaseIOSurfaceForTexture(info->service_id()); + + // Make sure we release the IOSurface even if CGLTexImageIOSurface2D fails. + texture_to_io_surface_map_.insert( + std::make_pair(info->service_id(), surface)); + + CGLContextObj context = + static_cast<CGLContextObj>(context_->GetHandle()); + + CGLError err = surface_support->CGLTexImageIOSurface2D( + context, + target, + GL_RGBA, + width, + height, + GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, + surface, + plane); + + if (err != kCGLNoError) { + SetGLError( + GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: error in CGLTexImageIOSurface2D"); + return; + } + + texture_manager()->SetLevelInfo( + feature_info_, info, + target, 0, GL_RGBA, width, height, 1, 0, + GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, true); + +#else + SetGLError(GL_INVALID_OPERATION, + "glTexImageIOSurface2DCHROMIUM: not supported."); +#endif +} + + // 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. diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 680cc28..11a3caf 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2576,5 +2576,30 @@ error::Error GLES2DecoderImpl::HandlePlaceholder453CHROMIUM( uint32 immediate_data_size, const gles2::Placeholder453CHROMIUM& c) { return error::kUnknownCommand; } +error::Error GLES2DecoderImpl::HandleTexImageIOSurface2DCHROMIUM( + uint32 immediate_data_size, const gles2::TexImageIOSurface2DCHROMIUM& c) { + GLenum target = static_cast<GLenum>(c.target); + GLsizei width = static_cast<GLsizei>(c.width); + GLsizei height = static_cast<GLsizei>(c.height); + GLuint ioSurfaceId = static_cast<GLuint>(c.ioSurfaceId); + GLuint plane = static_cast<GLuint>(c.plane); + if (!validators_->texture_bind_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, + "glTexImageIOSurface2DCHROMIUM: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (width < 0) { + SetGLError(GL_INVALID_VALUE, "glTexImageIOSurface2DCHROMIUM: width < 0"); + return error::kNoError; + } + if (height < 0) { + SetGLError(GL_INVALID_VALUE, "glTexImageIOSurface2DCHROMIUM: height < 0"); + return error::kNoError; + } + DoTexImageIOSurface2DCHROMIUM(target, width, height, ioSurfaceId, plane); + return error::kNoError; +} + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc index cb52457..25d96c7 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc @@ -4874,6 +4874,214 @@ TEST_F(GLES2DecoderManualInitTest, StreamTextureCHROMIUMNullMgr) { GetGLError(); // ignore internal error } +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleBindTexture) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + EXPECT_CALL(*gl_, BindTexture(GL_TEXTURE_RECTANGLE_ARB, kNewServiceId)); + EXPECT_CALL(*gl_, GenTextures(1, _)) + .WillOnce(SetArgumentPointee<1>(kNewServiceId)); + BindTexture cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, kNewClientId); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + TextureManager::TextureInfo* info = GetTextureInfo(kNewClientId); + EXPECT_TRUE(info != NULL); + EXPECT_TRUE(info->target() == GL_TEXTURE_RECTANGLE_ARB); +} + +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleGetBinding) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, GetError()) + .WillOnce(Return(GL_NO_ERROR)) + .WillOnce(Return(GL_NO_ERROR)) + .RetiresOnSaturation(); + typedef GetIntegerv::Result Result; + Result* result = static_cast<Result*>(shared_memory_address_); + EXPECT_CALL(*gl_, GetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, + result->GetData())) + .Times(0); + result->size = 0; + GetIntegerv cmd; + cmd.Init(GL_TEXTURE_BINDING_RECTANGLE_ARB, + shared_memory_id_, + shared_memory_offset_); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(decoder_->GetGLES2Util()->GLGetNumValuesReturned( + GL_TEXTURE_BINDING_RECTANGLE_ARB), result->GetNumResults()); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + EXPECT_EQ(client_texture_id_, (uint32)result->GetData()[0]); +} + +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureDefaults) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id_); + EXPECT_TRUE(info != NULL); + EXPECT_TRUE(info->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(info->min_filter() == GL_LINEAR); + EXPECT_TRUE(info->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(info->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParam) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE)); + EXPECT_CALL(*gl_, TexParameteri(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE)); + TexParameteri cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_NO_ERROR, GetGLError()); + + TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id_); + EXPECT_TRUE(info != NULL); + EXPECT_TRUE(info->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(info->min_filter() == GL_LINEAR); + EXPECT_TRUE(info->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(info->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTextureParamInvalid) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + + TexParameteri cmd; + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_MIN_FILTER, + GL_NEAREST_MIPMAP_NEAREST); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_S, + GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + cmd.Init(GL_TEXTURE_RECTANGLE_ARB, + GL_TEXTURE_WRAP_T, + GL_REPEAT); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); + + TextureManager::TextureInfo* info = GetTextureInfo(client_texture_id_); + EXPECT_TRUE(info != NULL); + EXPECT_TRUE(info->target() == GL_TEXTURE_RECTANGLE_ARB); + EXPECT_TRUE(info->min_filter() == GL_LINEAR); + EXPECT_TRUE(info->wrap_s() == GL_CLAMP_TO_EDGE); + EXPECT_TRUE(info->wrap_t() == GL_CLAMP_TO_EDGE); +} + +TEST_F(GLES2DecoderManualInitTest, ARBTextureRectangleTexImage2DError) { + InitDecoder( + "GL_ARB_texture_rectangle", // extensions + false, // has alpha + false, // has depth + false, // has stencil + false, // request alpha + false, // request depth + false, // request stencil + true); // bind generates resource + + GLenum target = GL_TEXTURE_RECTANGLE_ARB; + GLint level = 0; + GLenum internal_format = GL_RGBA; + GLsizei width = 2; + GLsizei height = 4; + GLint border = 0; + GLenum format = GL_RGBA; + GLenum type = GL_UNSIGNED_BYTE; + DoBindTexture( + GL_TEXTURE_RECTANGLE_ARB, client_texture_id_, kServiceTextureId); + ASSERT_TRUE(GetTextureInfo(client_texture_id_) != NULL); + TexImage2D cmd; + cmd.Init(target, level, internal_format, width, height, border, format, + type, kSharedMemoryId, kSharedMemoryOffset); + EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); + + // TexImage2D is not allowed with GL_TEXTURE_RECTANGLE_ARB targets. + EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); +} + TEST_F(GLES2DecoderTest, EnableFeatureCHROMIUMBadBucket) { const uint32 kBadBucketId = 123; EnableFeatureCHROMIUM cmd; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h index c60e869..8cc7d9b 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h @@ -16,5 +16,6 @@ // TODO(gman): GetTranslatedShaderSourceANGLE // TODO(gman): PostSubBufferCHROMIUM +// TODO(gman): TexImageIOSurface2DCHROMIUM #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_3_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 70c269d..9010fb9 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -121,6 +121,13 @@ void GLES2DecoderTestBase::InitDecoder( .Times(1) .RetiresOnSaturation(); } + if (group_->feature_info()->feature_flags().arb_texture_rectangle) { + EXPECT_CALL(*gl_, BindTexture( + GL_TEXTURE_RECTANGLE_ARB, + TestHelper::kServiceDefaultRectangleTextureId)) + .Times(1) + .RetiresOnSaturation(); + } EXPECT_CALL(*gl_, BindTexture( GL_TEXTURE_CUBE_MAP, TestHelper::kServiceDefaultTextureCubemapId)) .Times(1) diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc index 7f712fe..0290980 100644 --- a/gpu/command_buffer/service/test_helper.cc +++ b/gpu/command_buffer/service/test_helper.cc @@ -29,11 +29,13 @@ namespace gles2 { // GCC requires these declarations, but MSVC requires they not be present #ifndef COMPILER_MSVC const GLuint TestHelper::kServiceBlackTexture2dId; -const GLuint TestHelper::kServiceBlackTextureCubemapId; const GLuint TestHelper::kServiceDefaultTexture2dId; +const GLuint TestHelper::kServiceBlackTextureCubemapId; const GLuint TestHelper::kServiceDefaultTextureCubemapId; -const GLuint TestHelper::kServiceDefaultExternalTextureId; const GLuint TestHelper::kServiceBlackExternalTextureId; +const GLuint TestHelper::kServiceDefaultExternalTextureId; +const GLuint TestHelper::kServiceBlackRectangleTextureId; +const GLuint TestHelper::kServiceDefaultRectangleTextureId; const GLint TestHelper::kMaxSamples; const GLint TestHelper::kMaxRenderbufferSize; @@ -51,74 +53,110 @@ const GLint TestHelper::kMaxVertexUniformVectors; const GLint TestHelper::kMaxVertexUniformComponents; #endif -void TestHelper::SetupTextureManagerInitExpectations( - ::gfx::MockGLInterface* gl, - const char* extensions) { - static GLuint texture_ids[] = { +void TestHelper::SetupTextureInitializationExpectations( + ::gfx::MockGLInterface* gl, GLenum target) { + InSequence sequence; + + bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); + bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); + + static GLuint texture_2d_ids[] = { kServiceBlackTexture2dId, - kServiceDefaultTexture2dId, + kServiceDefaultTexture2dId }; + static GLuint texture_cube_map_ids[] = { kServiceBlackTextureCubemapId, - kServiceDefaultTextureCubemapId, - }; - EXPECT_CALL(*gl, GenTextures(arraysize(texture_ids), _)) + kServiceDefaultTextureCubemapId }; + static GLuint texture_external_oes_ids[] = { + kServiceBlackExternalTextureId, + kServiceDefaultExternalTextureId }; + static GLuint texture_rectangle_arb_ids[] = { + kServiceBlackRectangleTextureId, + kServiceDefaultRectangleTextureId }; + + const GLuint* texture_ids = NULL; + switch (target) { + case GL_TEXTURE_2D: + texture_ids = &texture_2d_ids[0]; + break; + case GL_TEXTURE_CUBE_MAP: + texture_ids = &texture_cube_map_ids[0]; + break; + case GL_TEXTURE_EXTERNAL_OES: + texture_ids = &texture_external_oes_ids[0]; + break; + case GL_TEXTURE_RECTANGLE_ARB: + texture_ids = &texture_rectangle_arb_ids[0]; + break; + default: + NOTREACHED(); + } + + int array_size = 2; + + EXPECT_CALL(*gl, GenTextures(array_size, _)) .WillOnce(SetArrayArgument<1>(texture_ids, - texture_ids + arraysize(texture_ids))) - .RetiresOnSaturation(); - for (int ii = 0; ii < 2; ++ii) { - EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, texture_ids[ii])) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_CUBE_MAP, texture_ids[2 + ii])) + texture_ids + array_size)) + .RetiresOnSaturation(); + for (int ii = 0; ii < array_size; ++ii) { + EXPECT_CALL(*gl, BindTexture(target, texture_ids[ii])) .Times(1) .RetiresOnSaturation(); - static GLenum faces[] = { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - }; - for (size_t ii = 0; ii < arraysize(faces); ++ii) { - EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, _)) - .Times(1) - .RetiresOnSaturation(); + if (needs_initialization) { + if (needs_faces) { + static GLenum faces[] = { + GL_TEXTURE_CUBE_MAP_POSITIVE_X, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + }; + for (size_t ii = 0; ii < arraysize(faces); ++ii) { + EXPECT_CALL(*gl, TexImage2D(faces[ii], 0, GL_RGBA, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + } + } else { + EXPECT_CALL(*gl, TexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, _)) + .Times(1) + .RetiresOnSaturation(); + } } } - EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_2D, 0)) - .Times(1) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_CUBE_MAP, 0)) + EXPECT_CALL(*gl, BindTexture(target, 0)) .Times(1) .RetiresOnSaturation(); +} + +void TestHelper::SetupTextureManagerInitExpectations( + ::gfx::MockGLInterface* gl, + const char* extensions) { + InSequence sequence; + + SetupTextureInitializationExpectations(gl, GL_TEXTURE_2D); + SetupTextureInitializationExpectations(gl, GL_TEXTURE_CUBE_MAP); bool ext_image_external = false; + bool arb_texture_rectangle = false; CStringTokenizer t(extensions, extensions + strlen(extensions), " "); while (t.GetNext()) { if (t.token() == "GL_OES_EGL_image_external") { ext_image_external = true; break; } + if (t.token() == "GL_ARB_texture_rectangle") { + arb_texture_rectangle = true; + break; + } } if (ext_image_external) { - static GLuint external_texture_ids[] = { - kServiceDefaultExternalTextureId, - kServiceBlackExternalTextureId, - }; - EXPECT_CALL(*gl, GenTextures(arraysize(external_texture_ids), _)) - .WillOnce(SetArrayArgument<1>( - external_texture_ids, - external_texture_ids + arraysize(external_texture_ids))) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, BindTexture(GL_TEXTURE_EXTERNAL_OES, 0)) - .Times(1) - .RetiresOnSaturation(); + SetupTextureInitializationExpectations(gl, GL_TEXTURE_EXTERNAL_OES); + } + if (arb_texture_rectangle) { + SetupTextureInitializationExpectations(gl, GL_TEXTURE_RECTANGLE_ARB); } } diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h index 6c6dcd0..ec563315 100644 --- a/gpu/command_buffer/service/test_helper.h +++ b/gpu/command_buffer/service/test_helper.h @@ -15,11 +15,13 @@ struct DisallowedFeatures; class TestHelper { public: static const GLuint kServiceBlackTexture2dId = 701; - static const GLuint kServiceBlackTextureCubemapId = 702; - static const GLuint kServiceDefaultTexture2dId = 703; + static const GLuint kServiceDefaultTexture2dId = 702; + static const GLuint kServiceBlackTextureCubemapId = 703; static const GLuint kServiceDefaultTextureCubemapId = 704; - static const GLuint kServiceDefaultExternalTextureId = 705; - static const GLuint kServiceBlackExternalTextureId = 706; + static const GLuint kServiceBlackExternalTextureId = 705; + static const GLuint kServiceDefaultExternalTextureId = 706; + static const GLuint kServiceBlackRectangleTextureId = 707; + static const GLuint kServiceDefaultRectangleTextureId = 708; static const GLint kMaxSamples = 4; static const GLint kMaxRenderbufferSize = 1024; @@ -45,6 +47,9 @@ class TestHelper { ::gfx::MockGLInterface* gl, const char* extensions); static void SetupTextureManagerInitExpectations(::gfx::MockGLInterface* gl, const char* extensions); + private: + static void SetupTextureInitializationExpectations(::gfx::MockGLInterface* gl, + GLenum target); }; } // namespace gles2 diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc index 3a433d3..db0825c 100644 --- a/gpu/command_buffer/service/texture_manager.cc +++ b/gpu/command_buffer/service/texture_manager.cc @@ -20,6 +20,7 @@ static size_t GLTargetToFaceIndex(GLenum target) { switch (target) { case GL_TEXTURE_2D: case GL_TEXTURE_EXTERNAL_OES: + case GL_TEXTURE_RECTANGLE_ARB: return 0; case GL_TEXTURE_CUBE_MAP_POSITIVE_X: return 0; @@ -92,7 +93,8 @@ bool TextureManager::TextureInfo::CanRender( return false; } bool needs_mips = NeedsMips(); - if (npot() && !feature_info->feature_flags().npot_ok) { + if ((npot() && !feature_info->feature_flags().npot_ok) || + (target_ == GL_TEXTURE_RECTANGLE_ARB)) { return !needs_mips && wrap_s_ == GL_CLAMP_TO_EDGE && wrap_t_ == GL_CLAMP_TO_EDGE; @@ -151,7 +153,7 @@ void TextureManager::TextureInfo::SetTarget(GLenum target, GLint max_levels) { level_infos_[ii].resize(max_levels); } - if (target == GL_TEXTURE_EXTERNAL_OES) { + if (target == GL_TEXTURE_EXTERNAL_OES || target == GL_TEXTURE_RECTANGLE_ARB) { min_filter_ = GL_LINEAR; wrap_s_ = wrap_t_ = GL_CLAMP_TO_EDGE; } @@ -161,7 +163,8 @@ bool TextureManager::TextureInfo::CanGenerateMipmaps( const FeatureInfo* feature_info) const { if ((npot() && !feature_info->feature_flags().npot_ok) || level_infos_.empty() || - target_ == GL_TEXTURE_EXTERNAL_OES) { + target_ == GL_TEXTURE_EXTERNAL_OES || + target_ == GL_TEXTURE_RECTANGLE_ARB) { return false; } const TextureInfo::LevelInfo& first = level_infos_[0][0]; @@ -327,7 +330,8 @@ bool TextureManager::TextureInfo::SetParameter( const FeatureInfo* feature_info, GLenum pname, GLint param) { DCHECK(feature_info); - if (target_ == GL_TEXTURE_EXTERNAL_OES) { + if (target_ == GL_TEXTURE_EXTERNAL_OES || + target_ == GL_TEXTURE_RECTANGLE_ARB) { if (pname == GL_TEXTURE_MIN_FILTER && (param != GL_NEAREST && param != GL_LINEAR)) return false; @@ -540,7 +544,9 @@ TextureManager::TextureManager( num_unsafe_textures_(0), num_uncleared_mips_(0), black_2d_texture_id_(0), - black_cube_texture_id_(0) { + black_cube_texture_id_(0), + black_oes_external_texture_id_(0), + black_arb_texture_rectangle_id_(0) { } bool TextureManager::Initialize(const FeatureInfo* feature_info) { @@ -549,65 +555,86 @@ bool TextureManager::Initialize(const FeatureInfo* feature_info) { // resources and all contexts that share resource share the same default // texture. + default_texture_2d_ = CreateDefaultAndBlackTextures( + feature_info, GL_TEXTURE_2D, &black_2d_texture_id_); + default_texture_cube_map_ = CreateDefaultAndBlackTextures( + feature_info, GL_TEXTURE_CUBE_MAP, &black_cube_texture_id_); + + if (feature_info->feature_flags().oes_egl_image_external) { + default_texture_external_oes_ = CreateDefaultAndBlackTextures( + feature_info, GL_TEXTURE_EXTERNAL_OES, + &black_oes_external_texture_id_); + } + + if (feature_info->feature_flags().arb_texture_rectangle) { + default_texture_rectangle_arb_ = CreateDefaultAndBlackTextures( + feature_info, GL_TEXTURE_RECTANGLE_ARB, + &black_arb_texture_rectangle_id_); + } + + return true; +} + +TextureManager::TextureInfo::Ref TextureManager::CreateDefaultAndBlackTextures( + const FeatureInfo* feature_info, + GLenum target, + GLuint* black_texture) { + static uint8 black[] = {0, 0, 0, 255}; + + // Sampling a texture not associated with any EGLImage sibling will return + // black values according to the spec. + bool needs_initialization = (target != GL_TEXTURE_EXTERNAL_OES); + bool needs_faces = (target == GL_TEXTURE_CUBE_MAP); + // Make default textures and texture for replacing non-renderable textures. - GLuint ids[4]; + GLuint ids[2]; glGenTextures(arraysize(ids), ids); - static uint8 black[] = {0, 0, 0, 255}; - for (int ii = 0; ii < 2; ++ii) { - glBindTexture(GL_TEXTURE_2D, ids[ii]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, - GL_UNSIGNED_BYTE, black); - glBindTexture(GL_TEXTURE_CUBE_MAP, ids[2 + ii]); - for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { - glTexImage2D(GLES2Util::IndexToGLFaceTarget(ii), 0, GL_RGBA, 1, 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, black); + for (unsigned long ii = 0; ii < arraysize(ids); ++ii) { + glBindTexture(target, ids[ii]); + if (needs_initialization) { + if (needs_faces) { + for (int jj = 0; jj < GLES2Util::kNumFaces; ++jj) { + glTexImage2D(GLES2Util::IndexToGLFaceTarget(jj), 0, GL_RGBA, 1, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, black); + } + } else { + glTexImage2D(target, 0, GL_RGBA, 1, 1, 0, GL_RGBA, + GL_UNSIGNED_BYTE, black); + } } } - glBindTexture(GL_TEXTURE_2D, 0); - glBindTexture(GL_TEXTURE_CUBE_MAP, 0); + glBindTexture(target, 0); // Since we are manually setting up these textures // we need to manually manipulate some of the their bookkeeping. - num_unrenderable_textures_ += 2; + ++num_unrenderable_textures_; + TextureInfo::Ref default_texture = TextureInfo::Ref(new TextureInfo(ids[1])); + SetInfoTarget(feature_info, default_texture, target); FeatureInfo temp_feature_info; - default_texture_2d_ = TextureInfo::Ref(new TextureInfo(ids[1])); - SetInfoTarget(feature_info, default_texture_2d_, GL_TEXTURE_2D); - SetLevelInfo(&temp_feature_info, default_texture_2d_, - GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); - default_texture_cube_map_ = TextureInfo::Ref(new TextureInfo(ids[3])); - SetInfoTarget(feature_info, default_texture_cube_map_, GL_TEXTURE_CUBE_MAP); - for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { - SetLevelInfo( - &temp_feature_info, default_texture_cube_map_, - GLES2Util::IndexToGLFaceTarget(ii), - 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); - } - - black_2d_texture_id_ = ids[0]; - black_cube_texture_id_ = ids[2]; - - if (feature_info->feature_flags().oes_egl_image_external) { - // Since we are manually setting up these textures - // we need to manually manipulate some of the their bookkeeping. - num_unrenderable_textures_ += 1; - GLuint external_ids[2]; - glGenTextures(arraysize(external_ids), external_ids); - glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); - default_texture_external_oes_ = TextureInfo::Ref( - new TextureInfo(external_ids[0])); - SetInfoTarget(feature_info, - default_texture_external_oes_, - GL_TEXTURE_EXTERNAL_OES); - default_texture_external_oes_->SetLevelInfo( - &temp_feature_info, GL_TEXTURE_EXTERNAL_OES, 0, - GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); - - // Sampling a texture not associated with any EGLImage sibling will return - // black values according to the spec. - black_oes_external_texture_id_ = external_ids[1]; + if (needs_faces) { + for (int ii = 0; ii < GLES2Util::kNumFaces; ++ii) { + SetLevelInfo( + &temp_feature_info, default_texture, + GLES2Util::IndexToGLFaceTarget(ii), + 0, GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + } + } else { + // TODO(kbr): previous code called SetLevelInfo directly on the + // TextureInfo object for the GL_TEXTURE_EXTERNAL_OES case. + // Unclear whether this was deliberate. + if (needs_initialization) { + SetLevelInfo(&temp_feature_info, default_texture, + GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, true); + } else { + default_texture->SetLevelInfo( + &temp_feature_info, GL_TEXTURE_EXTERNAL_OES, 0, + GL_RGBA, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, true); + } } - return true; + *black_texture = ids[0]; + return default_texture; } bool TextureManager::ValidForTarget( diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h index 0fccbf6..aaeed80 100644 --- a/gpu/command_buffer/service/texture_manager.h +++ b/gpu/command_buffer/service/texture_manager.h @@ -253,7 +253,7 @@ class TextureManager { // Sets the TextureInfo's target // Parameters: // target: GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP or - // GL_TEXTURE_EXTERNAL_OES + // GL_TEXTURE_EXTERNAL_OES or GL_TEXTURE_RECTANGLE_ARB // max_levels: The maximum levels this type of target can have. void SetTarget(GLenum target, GLint max_levels); @@ -415,6 +415,8 @@ class TextureManager { return default_texture_cube_map_; case GL_TEXTURE_EXTERNAL_OES: return default_texture_external_oes_; + case GL_TEXTURE_RECTANGLE_ARB: + return default_texture_rectangle_arb_; default: NOTREACHED(); return NULL; @@ -441,6 +443,8 @@ class TextureManager { return black_cube_texture_id_; case GL_SAMPLER_EXTERNAL_OES: return black_oes_external_texture_id_; + case GL_SAMPLER_2D_RECT_ARB: + return black_arb_texture_rectangle_id_; default: NOTREACHED(); return 0; @@ -448,6 +452,12 @@ class TextureManager { } private: + // Helper for Initialize(). + TextureInfo::Ref CreateDefaultAndBlackTextures( + const FeatureInfo* feature_info, + GLenum target, + GLuint* black_texture); + // Info for each texture in the system. typedef base::hash_map<GLuint, TextureInfo::Ref> TextureInfoMap; TextureInfoMap texture_infos_; @@ -467,11 +477,13 @@ class TextureManager { GLuint black_2d_texture_id_; GLuint black_cube_texture_id_; GLuint black_oes_external_texture_id_; + GLuint black_arb_texture_rectangle_id_; // The default textures for each target (texture name = 0) TextureInfo::Ref default_texture_2d_; TextureInfo::Ref default_texture_cube_map_; TextureInfo::Ref default_texture_external_oes_; + TextureInfo::Ref default_texture_rectangle_arb_; DISALLOW_COPY_AND_ASSIGN(TextureManager); }; diff --git a/gpu/command_buffer/service/texture_manager_unittest.cc b/gpu/command_buffer/service/texture_manager_unittest.cc index 15fc02e..4481567 100644 --- a/gpu/command_buffer/service/texture_manager_unittest.cc +++ b/gpu/command_buffer/service/texture_manager_unittest.cc @@ -27,12 +27,6 @@ class TextureManagerTest : public testing::Test { static const GLint kMaxCubeMapLevels = 4; static const GLint kMaxExternalLevels = 1; - static const GLuint kServiceBlackTexture2dId = 701; - static const GLuint kServiceBlackTextureCubemapId = 702; - static const GLuint kServiceDefaultTexture2dId = 703; - static const GLuint kServiceDefaultTextureCubemapId = 704; - - TextureManagerTest() : manager_(kMaxTextureSize, kMaxCubeMapTextureSize) { } @@ -69,10 +63,6 @@ const GLint TextureManagerTest::kMaxExternalTextureSize; const GLint TextureManagerTest::kMax2dLevels; const GLint TextureManagerTest::kMaxCubeMapLevels; const GLint TextureManagerTest::kMaxExternalLevels; -const GLuint TextureManagerTest::kServiceBlackTexture2dId; -const GLuint TextureManagerTest::kServiceBlackTextureCubemapId; -const GLuint TextureManagerTest::kServiceDefaultTexture2dId; -const GLuint TextureManagerTest::kServiceDefaultTextureCubemapId; #endif TEST_F(TextureManagerTest, Basic) { |