summaryrefslogtreecommitdiffstats
path: root/gpu/command_buffer
diff options
context:
space:
mode:
Diffstat (limited to 'gpu/command_buffer')
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py8
-rw-r--r--gpu/command_buffer/client/gles2_c_lib_autogen.h6
-rw-r--r--gpu/command_buffer/client/gles2_cmd_helper_autogen.h8
-rw-r--r--gpu/command_buffer/client/gles2_implementation_autogen.h16
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_autogen.h55
-rw-r--r--gpu/command_buffer/common/gles2_cmd_format_test_autogen.h22
-rw-r--r--gpu/command_buffer/common/gles2_cmd_ids_autogen.h1
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils.cc2
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h3
-rw-r--r--gpu/command_buffer/service/feature_info.cc27
-rw-r--r--gpu/command_buffer/service/feature_info.h4
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc213
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h25
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest.cc208
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_3_autogen.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc7
-rw-r--r--gpu/command_buffer/service/test_helper.cc138
-rw-r--r--gpu/command_buffer/service/test_helper.h13
-rw-r--r--gpu/command_buffer/service/texture_manager.cc135
-rw-r--r--gpu/command_buffer/service/texture_manager.h14
-rw-r--r--gpu/command_buffer/service/texture_manager_unittest.cc10
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) {