diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-23 18:46:30 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-08-23 18:46:30 +0000 |
commit | 8e3e066579460f88a19e2e6e091c396f3bd851c3 (patch) | |
tree | 06df7936a1cba62db31ee09f437d1328ba21fbcf /gpu | |
parent | 83f49d2a539d5c2752958d8b6d7c9c6644aab62c (diff) | |
download | chromium_src-8e3e066579460f88a19e2e6e091c396f3bd851c3.zip chromium_src-8e3e066579460f88a19e2e6e091c396f3bd851c3.tar.gz chromium_src-8e3e066579460f88a19e2e6e091c396f3bd851c3.tar.bz2 |
Adds support for EXT_framebuffer_multisample
I probably need more tests but in order to test
I need to figure out how to init the system
with different caps enabled from the unit tests
and that's probably not a small amount of work
so leaving that till later.
TEST=some unit tests, ran conformance tests
BUG=none
Review URL: http://codereview.chromium.org/3122033
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57081 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
18 files changed, 665 insertions, 62 deletions
diff --git a/gpu/GLES2/gl2ext.h b/gpu/GLES2/gl2ext.h index 6c94efe..cae6500 100644 --- a/gpu/GLES2/gl2ext.h +++ b/gpu/GLES2/gl2ext.h @@ -798,6 +798,77 @@ typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); #endif +/* GL_EXT_framebuffer_multisample */ +#ifndef GL_EXT_framebuffer_multisample +#define GL_EXT_framebuffer_multisample 1 + +#ifndef GL_DRAW_FRAMEBUFFER_BINDING +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#endif +#ifndef GL_DRAW_FRAMEBUFFER_BINDING_EXT +#define GL_DRAW_FRAMEBUFFER_BINDING_EXT GL_DRAW_FRAMEBUFFER_BINDING +#endif +#ifndef GL_FRAMEBUFFER_BINDING +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#endif +#ifndef GL_FRAMEBUFFER_BINDING_EXT +#define GL_FRAMEBUFFER_BINDING_EXT GL_FRAMEBUFFER_BINDING +#endif +#ifndef GL_RENDERBUFFER_BINDING +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#endif +#ifndef GL_RENDERBUFFER_BINDING_EXT +#define GL_RENDERBUFFER_BINDING_EXT GL_RENDERBUFFER_BINDING +#endif +#ifndef GL_READ_FRAMEBUFFER +#define GL_READ_FRAMEBUFFER 0x8CA8 +#endif +#ifndef GL_READ_FRAMEBUFFER_EXT +#define GL_READ_FRAMEBUFFER_EXT GL_READ_FRAMEBUFFER +#endif +#ifndef GL_DRAW_FRAMEBUFFER +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#endif +#ifndef GL_DRAW_FRAMEBUFFER_EXT +#define GL_DRAW_FRAMEBUFFER_EXT GL_DRAW_FRAMEBUFFER +#endif +#ifndef GL_READ_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#endif +#ifndef GL_READ_FRAMEBUFFER_BINDING_EXT +#define GL_READ_FRAMEBUFFER_BINDING_EXT GL_READ_FRAMEBUFFER_BINDING +#endif +#ifndef GL_RENDERBUFFER_SAMPLES +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#endif +#ifndef GL_RENDERBUFFER_SAMPLES_EXT +#define GL_RENDERBUFFER_SAMPLES_EXT GL_RENDERBUFFER_SAMPLES +#endif +#ifndef GL_MAX_SAMPLES +#define GL_MAX_SAMPLES 0x8D57 +#endif +#ifndef GL_MAX_SAMPLES_EXT +#define GL_MAX_SAMPLES_EXT GL_MAX_SAMPLES +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE +#endif + +#ifdef GL_GLEXT_PROTOTYPES +#define glBlitFramebufferEXT GLES2_GET_FUN(BlitFramebufferEXT) +#define glRenderbufferStorageMultisampleEXT GLES2_GET_FUN(RenderbufferStorageMultisampleEXT) +#if !defined(GLES2_USE_CPP_BINDINGS) +GL_APICALL void GL_APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +#endif +typedef void (GL_APIENTRY PFNGLBLITFRAMEBUFFEREXT) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GL_APIENTRY PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXT) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + /* GL_CHROMIUM_map_sub */ #ifndef GL_CHROMIUM_map_sub #define GL_CHROMIUM_map_sub 1 @@ -818,14 +889,12 @@ GL_APICALL void GL_APIENTRY glUnmapBufferSubData (const void* mem); GL_APICALL void* GL_APIENTRY glMapTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access); GL_APICALL void GL_APIENTRY glUnmapTexSubImage2D (const void* mem); #endif -#else +#endif typedef void* (GL_APIENTRYP PFNGLMAPBUFFERSUBDATA) (GLuint target, GLintptr offset, GLsizeiptr size, GLenum access); typedef void (GL_APIENTRYP PFNGLUNMAPBUFFERSUBDATA) (const void* mem); typedef void* (GL_APIENTRYP PFNGLMAPTEXSUBIMAGE2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLenum access); typedef void (GL_APIENTRYP PFNGLUNMAPTEXSUBIMAGE2D) (const void* mem); #endif -#endif - #ifdef __cplusplus } diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index f747f7a..05310a4 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -175,6 +175,8 @@ GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GL GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLintVertexAttribSize size, GLenumVertexAttribType type, GLboolean normalized, GLsizei stride, const void* ptr); GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glBlitFramebufferEXT (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenumBlitFilter filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenumRenderBufferTarget target, GLsizei samples, GLenumRenderBufferFormat internalformat, GLsizei width, GLsizei height); // Non-GL commands. GL_APICALL void GL_APIENTRY glSwapBuffers (void); GL_APICALL GLuint GL_APIENTRY glGetMaxValueInBuffer (GLidBuffer buffer_id, GLsizei count, GLenumGetMaxIndexType type, GLuint offset); @@ -383,18 +385,30 @@ _CMD_ID_TABLE = { 'CommandBufferEnable': 442, 'CompressedTexImage2DBucket': 443, 'CompressedTexSubImage2DBucket': 444, + 'RenderbufferStorageMultisampleEXT': 445, + 'BlitFramebufferEXT': 446, } # This is a list of enum names and their valid values. It is used to map # GLenum arguments to a specific set of valid values. _ENUM_LISTS = { + 'BlitFilter': { + 'type': 'GLenum', + 'valid': [ + 'GL_NEAREST', + 'GL_LINEAR', + ], + 'invalid': [ + 'GL_LINEAR_MIPMAP_LINEAR', + ], + }, 'FrameBufferTarget': { 'type': 'GLenum', 'valid': [ 'GL_FRAMEBUFFER', ], 'invalid': [ - 'GL_RENDERBUFFER', + 'GL_READ_FRAMEBUFFER' , ], }, 'RenderBufferTarget': { @@ -1030,6 +1044,10 @@ _FUNCTION_INFO = { 'decoder_func': 'DoBindTexture', 'gen_func': 'GenTextures', }, + 'BlitFramebufferEXT': { + 'decoder_func': 'DoBlitFramebufferEXT', + 'unit_test': False, + }, 'BufferData': {'type': 'Manual', 'immediate': True}, 'BufferSubData': {'type': 'Data', 'decoder_func': 'DoBufferSubData'}, 'CheckFramebufferStatus': { @@ -1355,6 +1373,12 @@ _FUNCTION_INFO = { 'gl_test_func': 'glRenderbufferStorageEXT', 'expectation': False, }, + 'RenderbufferStorageMultisampleEXT': { + 'decoder_func': 'DoRenderbufferStorageMultisample', + 'gl_test_func': 'glRenderbufferStorageMultisampleEXT', + 'expectation': False, + 'unit_test': False, + }, 'ReadPixels': { 'cmd_comment': '// ReadPixels has the result separated from the pixel buffer so that\n' @@ -1623,7 +1647,6 @@ class CHeaderWriter(CWriter): def __init__(self, filename, file_comment = None): CWriter.__init__(self, filename) - base = os.path.dirname( os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) hpath = os.path.abspath(filename)[len(base) + 1:] diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index bae1f9e..0aca957 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -500,6 +500,18 @@ void GLES2VertexAttribPointer( void GLES2Viewport(GLint x, GLint y, GLsizei width, GLsizei height) { gles2::GetGLContext()->Viewport(x, y, width, height); } +void GLES2BlitFramebufferEXT( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + gles2::GetGLContext()->BlitFramebufferEXT( + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); +} +void GLES2RenderbufferStorageMultisampleEXT( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height) { + gles2::GetGLContext()->RenderbufferStorageMultisampleEXT( + target, samples, internalformat, width, height); +} void GLES2SwapBuffers() { gles2::GetGLContext()->SwapBuffers(); } diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index aa2270b..0815df3 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -1131,6 +1131,22 @@ c.Init(x, y, width, height); } + void BlitFramebufferEXT( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + gles2::BlitFramebufferEXT& c = GetCmdSpace<gles2::BlitFramebufferEXT>(); + c.Init( + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + } + + void RenderbufferStorageMultisampleEXT( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height) { + gles2::RenderbufferStorageMultisampleEXT& c = + GetCmdSpace<gles2::RenderbufferStorageMultisampleEXT>(); + c.Init(target, samples, internalformat, width, height); + } + void SwapBuffers() { gles2::SwapBuffers& c = GetCmdSpace<gles2::SwapBuffers>(); c.Init(); diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 8dd914b..872bcf63 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -770,6 +770,35 @@ void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) { helper_->Viewport(x, y, width, height); } +void BlitFramebufferEXT( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, + GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { + helper_->BlitFramebufferEXT( + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); +} + +void RenderbufferStorageMultisampleEXT( + GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, + GLsizei height) { + if (samples < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: samples < 0"); + return; + } + if (width < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: width < 0"); + return; + } + if (height < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: height < 0"); + return; + } + helper_->RenderbufferStorageMultisampleEXT( + target, samples, internalformat, width, height); +} + void SwapBuffers(); GLuint GetMaxValueInBuffer( diff --git a/gpu/command_buffer/common/gles2_cmd_format_autogen.h b/gpu/command_buffer/common/gles2_cmd_format_autogen.h index eb46619..badcffa 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_autogen.h @@ -8321,6 +8321,141 @@ COMPILE_ASSERT(offsetof(Viewport, width) == 12, COMPILE_ASSERT(offsetof(Viewport, height) == 16, OffsetOf_Viewport_height_not_16); +struct BlitFramebufferEXT { + typedef BlitFramebufferEXT ValueType; + static const CommandId kCmdId = kBlitFramebufferEXT; + static const cmd::ArgFlags kArgFlags = cmd::kFixed; + + static uint32 ComputeSize() { + return static_cast<uint32>(sizeof(ValueType)); // NOLINT + } + + void SetHeader() { + header.SetCmd<ValueType>(); + } + + void Init( + GLint _srcX0, GLint _srcY0, GLint _srcX1, GLint _srcY1, GLint _dstX0, + GLint _dstY0, GLint _dstX1, GLint _dstY1, GLbitfield _mask, + GLenum _filter) { + SetHeader(); + srcX0 = _srcX0; + srcY0 = _srcY0; + srcX1 = _srcX1; + srcY1 = _srcY1; + dstX0 = _dstX0; + dstY0 = _dstY0; + dstX1 = _dstX1; + dstY1 = _dstY1; + mask = _mask; + filter = _filter; + } + + void* Set( + void* cmd, GLint _srcX0, GLint _srcY0, GLint _srcX1, GLint _srcY1, + GLint _dstX0, GLint _dstY0, GLint _dstX1, GLint _dstY1, GLbitfield _mask, + GLenum _filter) { + static_cast<ValueType*>( + cmd)->Init( + _srcX0, _srcY0, _srcX1, _srcY1, _dstX0, _dstY0, _dstX1, _dstY1, + _mask, _filter); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + int32 srcX0; + int32 srcY0; + int32 srcX1; + int32 srcY1; + int32 dstX0; + int32 dstY0; + int32 dstX1; + int32 dstY1; + uint32 mask; + uint32 filter; +}; + +COMPILE_ASSERT(sizeof(BlitFramebufferEXT) == 44, + Sizeof_BlitFramebufferEXT_is_not_44); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, header) == 0, + OffsetOf_BlitFramebufferEXT_header_not_0); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, srcX0) == 4, + OffsetOf_BlitFramebufferEXT_srcX0_not_4); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, srcY0) == 8, + OffsetOf_BlitFramebufferEXT_srcY0_not_8); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, srcX1) == 12, + OffsetOf_BlitFramebufferEXT_srcX1_not_12); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, srcY1) == 16, + OffsetOf_BlitFramebufferEXT_srcY1_not_16); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, dstX0) == 20, + OffsetOf_BlitFramebufferEXT_dstX0_not_20); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, dstY0) == 24, + OffsetOf_BlitFramebufferEXT_dstY0_not_24); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, dstX1) == 28, + OffsetOf_BlitFramebufferEXT_dstX1_not_28); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, dstY1) == 32, + OffsetOf_BlitFramebufferEXT_dstY1_not_32); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, mask) == 36, + OffsetOf_BlitFramebufferEXT_mask_not_36); +COMPILE_ASSERT(offsetof(BlitFramebufferEXT, filter) == 40, + OffsetOf_BlitFramebufferEXT_filter_not_40); + +struct RenderbufferStorageMultisampleEXT { + typedef RenderbufferStorageMultisampleEXT ValueType; + static const CommandId kCmdId = kRenderbufferStorageMultisampleEXT; + 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 _samples, GLenum _internalformat, GLsizei _width, + GLsizei _height) { + SetHeader(); + target = _target; + samples = _samples; + internalformat = _internalformat; + width = _width; + height = _height; + } + + void* Set( + void* cmd, GLenum _target, GLsizei _samples, GLenum _internalformat, + GLsizei _width, GLsizei _height) { + static_cast<ValueType*>( + cmd)->Init(_target, _samples, _internalformat, _width, _height); + return NextCmdAddress<ValueType>(cmd); + } + + gpu::CommandHeader header; + uint32 target; + int32 samples; + uint32 internalformat; + int32 width; + int32 height; +}; + +COMPILE_ASSERT(sizeof(RenderbufferStorageMultisampleEXT) == 24, + Sizeof_RenderbufferStorageMultisampleEXT_is_not_24); +COMPILE_ASSERT(offsetof(RenderbufferStorageMultisampleEXT, header) == 0, + OffsetOf_RenderbufferStorageMultisampleEXT_header_not_0); +COMPILE_ASSERT(offsetof(RenderbufferStorageMultisampleEXT, target) == 4, + OffsetOf_RenderbufferStorageMultisampleEXT_target_not_4); +COMPILE_ASSERT(offsetof(RenderbufferStorageMultisampleEXT, samples) == 8, + OffsetOf_RenderbufferStorageMultisampleEXT_samples_not_8); +COMPILE_ASSERT( + offsetof(RenderbufferStorageMultisampleEXT, internalformat) == 12, + OffsetOf_RenderbufferStorageMultisampleEXT_internalformat_not_12); // NOLINT +COMPILE_ASSERT(offsetof(RenderbufferStorageMultisampleEXT, width) == 16, + OffsetOf_RenderbufferStorageMultisampleEXT_width_not_16); +COMPILE_ASSERT(offsetof(RenderbufferStorageMultisampleEXT, height) == 20, + OffsetOf_RenderbufferStorageMultisampleEXT_height_not_20); + struct SwapBuffers { typedef SwapBuffers ValueType; static const CommandId kCmdId = kSwapBuffers; 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 9969c2f..177b084 100644 --- a/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_format_test_autogen.h @@ -3288,6 +3288,58 @@ TEST(GLES2FormatTest, Viewport) { EXPECT_EQ(static_cast<GLsizei>(14), cmd.height); } +TEST(GLES2FormatTest, BlitFramebufferEXT) { + BlitFramebufferEXT cmd = { { 0 } }; + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLint>(11), + static_cast<GLint>(12), + static_cast<GLint>(13), + static_cast<GLint>(14), + static_cast<GLint>(15), + static_cast<GLint>(16), + static_cast<GLint>(17), + static_cast<GLint>(18), + static_cast<GLbitfield>(19), + static_cast<GLenum>(20)); + EXPECT_EQ(static_cast<uint32>(BlitFramebufferEXT::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<char*>(next_cmd), + reinterpret_cast<char*>(&cmd) + sizeof(cmd)); + EXPECT_EQ(static_cast<GLint>(11), cmd.srcX0); + EXPECT_EQ(static_cast<GLint>(12), cmd.srcY0); + EXPECT_EQ(static_cast<GLint>(13), cmd.srcX1); + EXPECT_EQ(static_cast<GLint>(14), cmd.srcY1); + EXPECT_EQ(static_cast<GLint>(15), cmd.dstX0); + EXPECT_EQ(static_cast<GLint>(16), cmd.dstY0); + EXPECT_EQ(static_cast<GLint>(17), cmd.dstX1); + EXPECT_EQ(static_cast<GLint>(18), cmd.dstY1); + EXPECT_EQ(static_cast<GLbitfield>(19), cmd.mask); + EXPECT_EQ(static_cast<GLenum>(20), cmd.filter); +} + +TEST(GLES2FormatTest, RenderbufferStorageMultisampleEXT) { + RenderbufferStorageMultisampleEXT cmd = { { 0 } }; + void* next_cmd = cmd.Set( + &cmd, + static_cast<GLenum>(11), + static_cast<GLsizei>(12), + static_cast<GLenum>(13), + static_cast<GLsizei>(14), + static_cast<GLsizei>(15)); + EXPECT_EQ(static_cast<uint32>(RenderbufferStorageMultisampleEXT::kCmdId), + cmd.header.command); + EXPECT_EQ(sizeof(cmd), cmd.header.size * 4u); + EXPECT_EQ(static_cast<char*>(next_cmd), + reinterpret_cast<char*>(&cmd) + sizeof(cmd)); + EXPECT_EQ(static_cast<GLenum>(11), cmd.target); + EXPECT_EQ(static_cast<GLsizei>(12), cmd.samples); + EXPECT_EQ(static_cast<GLenum>(13), cmd.internalformat); + EXPECT_EQ(static_cast<GLsizei>(14), cmd.width); + EXPECT_EQ(static_cast<GLsizei>(15), cmd.height); +} + TEST(GLES2FormatTest, SwapBuffers) { SwapBuffers cmd = { { 0 } }; void* next_cmd = cmd.Set( diff --git a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h index a2890cc..7fc268d 100644 --- a/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_id_test_autogen.h @@ -377,6 +377,10 @@ TEST(GLES2CommandIdTest, CommandIdsMatch) { GLES2_VertexAttribPointer_kCmdId_mismatch); COMPILE_ASSERT(Viewport::kCmdId == 430, GLES2_Viewport_kCmdId_mismatch); + COMPILE_ASSERT(BlitFramebufferEXT::kCmdId == 446, + GLES2_BlitFramebufferEXT_kCmdId_mismatch); + COMPILE_ASSERT(RenderbufferStorageMultisampleEXT::kCmdId == 445, + GLES2_RenderbufferStorageMultisampleEXT_kCmdId_mismatch); COMPILE_ASSERT(SwapBuffers::kCmdId == 431, GLES2_SwapBuffers_kCmdId_mismatch); COMPILE_ASSERT(GetMaxValueInBuffer::kCmdId == 438, diff --git a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h index 9308fe0..f9ae357 100644 --- a/gpu/command_buffer/common/gles2_cmd_ids_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_ids_autogen.h @@ -197,6 +197,8 @@ OP(CommandBufferEnable) /* 442 */ \ OP(CompressedTexImage2DBucket) /* 443 */ \ OP(CompressedTexSubImage2DBucket) /* 444 */ \ + OP(RenderbufferStorageMultisampleEXT) /* 445 */ \ + OP(BlitFramebufferEXT) /* 446 */ \ enum CommandId { kStartPoint = cmd::kLastCommonId, // All GLES2 commands start after this. diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index c0a9a98..5cedbbd 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -142,6 +142,18 @@ bool ContextGroup::Initialize() { } } + // Check for multisample support + if (strstr(extensions, "GL_EXT_framebuffer_multisample")) { + extension_flags_.ext_framebuffer_multisample = true; + validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT); + validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT); + validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT); + validators_.g_l_state.AddValue(GL_DRAW_FRAMEBUFFER_BINDING_EXT); + validators_.render_buffer_parameter.AddValue(GL_MAX_SAMPLES_EXT); + AddExtensionString("GL_EXT_framebuffer_multisample"); + AddExtensionString("GL_EXT_framebuffer_blit"); + } + // TODO(gman): Add support for these extensions. // GL_OES_depth24 // GL_OES_depth32 diff --git a/gpu/command_buffer/service/context_group.h b/gpu/command_buffer/service/context_group.h index a38f369..77b1c7a 100644 --- a/gpu/command_buffer/service/context_group.h +++ b/gpu/command_buffer/service/context_group.h @@ -30,6 +30,14 @@ class TextureManager; // resources. class ContextGroup { public: + struct ExtensionFlags { + ExtensionFlags() + : ext_framebuffer_multisample(false) { + } + + bool ext_framebuffer_multisample; + }; + ContextGroup(); ~ContextGroup(); @@ -101,6 +109,10 @@ class ContextGroup { return extensions_; } + const ExtensionFlags& extension_flags() const { + return extension_flags_; + } + private: void AddExtensionString(const std::string& str); @@ -135,6 +147,9 @@ class ContextGroup { // The extensions string returned by glGetString(GL_EXTENSIONS); std::string extensions_; + // Flags for some extensions + ExtensionFlags extension_flags_; + DISALLOW_COPY_AND_ASSIGN(ContextGroup); }; diff --git a/gpu/command_buffer/service/context_group_unittest.cc b/gpu/command_buffer/service/context_group_unittest.cc index 34c8adc..c8717c4 100644 --- a/gpu/command_buffer/service/context_group_unittest.cc +++ b/gpu/command_buffer/service/context_group_unittest.cc @@ -122,6 +122,7 @@ TEST_F(ContextGroupTest, Basic) { EXPECT_TRUE(group_.texture_manager() == NULL); EXPECT_TRUE(group_.program_manager() == NULL); EXPECT_TRUE(group_.shader_manager() == NULL); + EXPECT_FALSE(group_.extension_flags().ext_framebuffer_multisample); } TEST_F(ContextGroupTest, InitializeNoExtensions) { @@ -286,6 +287,24 @@ TEST_F(ContextGroupTest, InitializeOES_texture_half_float_linearGLES2) { EXPECT_TRUE(group_.validators()->pixel_type.IsValid(GL_HALF_FLOAT_OES)); } +TEST_F(ContextGroupTest, InitializeEXT_framebuffer_multisample) { + SetupInitExpectations("GL_EXT_framebuffer_multisample"); + group_.Initialize(); + EXPECT_TRUE(group_.extension_flags().ext_framebuffer_multisample); + EXPECT_THAT(group_.extensions(), HasSubstr("GL_EXT_framebuffer_multisample")); + EXPECT_THAT(group_.extensions(), HasSubstr("GL_EXT_framebuffer_blit")); + EXPECT_TRUE(group_.validators()->frame_buffer_target.IsValid( + GL_READ_FRAMEBUFFER_EXT)); + EXPECT_TRUE(group_.validators()->frame_buffer_target.IsValid( + GL_DRAW_FRAMEBUFFER_EXT)); + EXPECT_TRUE(group_.validators()->g_l_state.IsValid( + GL_READ_FRAMEBUFFER_BINDING_EXT)); + EXPECT_TRUE(group_.validators()->g_l_state.IsValid( + GL_DRAW_FRAMEBUFFER_BINDING_EXT)); + EXPECT_TRUE(group_.validators()->render_buffer_parameter.IsValid( + GL_MAX_SAMPLES_EXT)); +} + } // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index ab36100..639ba86 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -556,11 +556,13 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, virtual void SetSwapBuffersCallback(Callback0::Type* callback); + // Restores the current state to the user's settings. + void RestoreCurrentFramebufferBindings(); + void RestoreCurrentRenderbufferBindings(); + void RestoreCurrentTexture2DBindings(); + private: friend class ScopedGLErrorSuppressor; - friend class ScopedTexture2DBinder; - friend class ScopedFrameBufferBinder; - friend class ScopedRenderBufferBinder; friend class ScopedDefaultGLContext; friend class RenderBuffer; friend class FrameBuffer; @@ -635,7 +637,7 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Get the size (in pixels) of the currently bound frame buffer (either FBO // or regular back buffer). - gfx::Size GetBoundFrameBufferSize(); + gfx::Size GetBoundReadFrameBufferSize(); // Wrapper for CompressedTexImage2D commands. error::Error DoCompressedTexImage2D( @@ -848,7 +850,8 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, GLuint client_id, const char* data, uint32 data_size); // Clears any uncleared render buffers attached to the given frame buffer. - void ClearUnclearedRenderbuffers(FramebufferManager::FramebufferInfo* info); + void ClearUnclearedRenderbuffers( + GLenum target, FramebufferManager::FramebufferInfo* info); // Remembers the state of some capabilities. void SetCapabilityState(GLenum cap, bool enabled); @@ -897,6 +900,12 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // Wrapper for glBindTexture since we need to track the current targets. void DoBindTexture(GLenum target, GLuint texture); + // Wrapper for glBlitFramebufferEXT. + void DoBlitFramebufferEXT( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter); + // Wrapper for glBufferData. void DoBufferData( GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage); @@ -1010,6 +1019,11 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, void DoRenderbufferStorage( GLenum target, GLenum internalformat, GLsizei width, GLsizei height); + // Wrapper for glRenderbufferStorageMultisampleEXT. + void DoRenderbufferStorageMultisample( + GLenum target, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height); + // Wrapper for glReleaseShaderCompiler. void DoReleaseShaderCompiler() { } @@ -1115,6 +1129,25 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, return (info && !info->IsDeleted()) ? info : NULL; } + // Gets the framebuffer info for a particular target. + FramebufferManager::FramebufferInfo* GetFramebufferInfoForTarget( + GLenum target) { + FramebufferManager::FramebufferInfo* info = NULL; + switch (target) { + case GL_FRAMEBUFFER: + case GL_DRAW_FRAMEBUFFER: + info = bound_draw_framebuffer_; + break; + case GL_READ_FRAMEBUFFER: + info = bound_read_framebuffer_; + break; + default: + NOTREACHED(); + break; + } + return (info && !info->IsDeleted()) ? info : NULL; + } + // Validates the program and location for a glGetUniform call and returns // a SizeResult setup to receive the result. Returns true if glGetUniform // should be called. @@ -1219,8 +1252,9 @@ class GLES2DecoderImpl : public base::SupportsWeakPtr<GLES2DecoderImpl>, // The program in use by glUseProgram ProgramManager::ProgramInfo::Ref current_program_; - // The currently bound framebuffer - FramebufferManager::FramebufferInfo::Ref bound_framebuffer_; + // The currently bound framebuffers + FramebufferManager::FramebufferInfo::Ref bound_read_framebuffer_; + FramebufferManager::FramebufferInfo::Ref bound_draw_framebuffer_; // The currently bound renderbuffer RenderbufferManager::RenderbufferInfo::Ref bound_renderbuffer_; @@ -1279,15 +1313,7 @@ ScopedTexture2DBinder::ScopedTexture2DBinder(GLES2DecoderImpl* decoder, ScopedTexture2DBinder::~ScopedTexture2DBinder() { ScopedGLErrorSuppressor suppressor(decoder_); - GLES2DecoderImpl::TextureUnit& info = decoder_->texture_units_[0]; - GLuint last_id; - if (info.bound_texture_2d) - last_id = info.bound_texture_2d->service_id(); - else - last_id = 0; - - glBindTexture(GL_TEXTURE_2D, last_id); - glActiveTexture(GL_TEXTURE0 + decoder_->active_texture_unit_); + decoder_->RestoreCurrentTexture2DBindings(); } ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, @@ -1299,10 +1325,7 @@ ScopedRenderBufferBinder::ScopedRenderBufferBinder(GLES2DecoderImpl* decoder, ScopedRenderBufferBinder::~ScopedRenderBufferBinder() { ScopedGLErrorSuppressor suppressor(decoder_); - glBindRenderbufferEXT( - GL_RENDERBUFFER, - decoder_->bound_renderbuffer_ ? - decoder_->bound_renderbuffer_->service_id() : 0); + decoder_->RestoreCurrentRenderbufferBindings(); } ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, @@ -1314,16 +1337,7 @@ ScopedFrameBufferBinder::ScopedFrameBufferBinder(GLES2DecoderImpl* decoder, ScopedFrameBufferBinder::~ScopedFrameBufferBinder() { ScopedGLErrorSuppressor suppressor(decoder_); - FramebufferManager::FramebufferInfo* info = - decoder_->bound_framebuffer_.get(); - GLuint framebuffer_id = info ? info->service_id() : 0; - if (framebuffer_id == 0 && - decoder_->offscreen_target_frame_buffer_.get()) { - glBindFramebufferEXT(GL_FRAMEBUFFER, - decoder_->offscreen_target_frame_buffer_->id()); - } else { - glBindFramebufferEXT(GL_FRAMEBUFFER, framebuffer_id); - } + decoder_->RestoreCurrentFramebufferBindings(); } ScopedDefaultGLContext::ScopedDefaultGLContext(GLES2DecoderImpl* decoder) @@ -1828,16 +1842,67 @@ bool GLES2DecoderImpl::MakeCurrent() { return context_.get() ? context_->MakeCurrent() : false; } -gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { - if (bound_framebuffer_ != 0) { +void GLES2DecoderImpl::RestoreCurrentRenderbufferBindings() { + glBindRenderbufferEXT( + GL_RENDERBUFFER, + bound_renderbuffer_ ? bound_renderbuffer_->service_id() : 0); +} + +static void RebindCurrentFramebuffer( + GLenum target, + FramebufferManager::FramebufferInfo* info, + FrameBuffer* offscreen_frame_buffer) { + GLuint framebuffer_id = info ? info->service_id() : 0; + if (framebuffer_id == 0 && offscreen_frame_buffer) { + framebuffer_id = offscreen_frame_buffer->id(); + } + glBindFramebufferEXT(target, framebuffer_id); +} + +void GLES2DecoderImpl::RestoreCurrentFramebufferBindings() { + if (!group_->extension_flags().ext_framebuffer_multisample) { + RebindCurrentFramebuffer( + GL_FRAMEBUFFER, + bound_draw_framebuffer_.get(), + offscreen_target_frame_buffer_.get()); + } else { + RebindCurrentFramebuffer( + GL_READ_FRAMEBUFFER_EXT, + bound_read_framebuffer_.get(), + offscreen_target_frame_buffer_.get()); + RebindCurrentFramebuffer( + GL_DRAW_FRAMEBUFFER_EXT, + bound_draw_framebuffer_.get(), + offscreen_target_frame_buffer_.get()); + } +} + +void GLES2DecoderImpl::RestoreCurrentTexture2DBindings() { + GLES2DecoderImpl::TextureUnit& info = texture_units_[0]; + GLuint last_id; + if (info.bound_texture_2d) { + last_id = info.bound_texture_2d->service_id(); + } else { + last_id = 0; + } + + glBindTexture(GL_TEXTURE_2D, last_id); + glActiveTexture(GL_TEXTURE0 + active_texture_unit_); +} + +gfx::Size GLES2DecoderImpl::GetBoundReadFrameBufferSize() { + if (bound_read_framebuffer_ != 0) { int width = 0; int height = 0; + GLenum target = group_->extension_flags().ext_framebuffer_multisample ? + GL_READ_FRAMEBUFFER_EXT : GL_FRAMEBUFFER; + // Assume we have to have COLOR_ATTACHMENT0. Should we check for depth and // stencil. GLint fb_type = 0; glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, + target, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &fb_type); @@ -1846,7 +1911,7 @@ gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { { GLint renderbuffer_id = 0; glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, + target, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &renderbuffer_id); @@ -1866,7 +1931,7 @@ gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { { GLint texture_id = 0; glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, + target, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &texture_id); @@ -1879,12 +1944,12 @@ gfx::Size GLES2DecoderImpl::GetBoundFrameBufferSize() { GLint level = 0; GLint face = 0; glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, + target, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, &level); glGetFramebufferAttachmentParameterivEXT( - GL_FRAMEBUFFER, + target, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, &face); @@ -2262,7 +2327,13 @@ void GLES2DecoderImpl::DoBindFramebuffer(GLenum target, GLuint client_id) { service_id = info->service_id(); } } - bound_framebuffer_ = info; + + if (target == GL_FRAMEBUFFER || target == GL_DRAW_FRAMEBUFFER_EXT) { + bound_draw_framebuffer_ = info; + } + if (target == GL_FRAMEBUFFER || target == GL_READ_FRAMEBUFFER_EXT) { + bound_read_framebuffer_ = info; + } // When rendering to an offscreen frame buffer, instead of unbinding from // the current frame buffer, bind to the offscreen target frame buffer. @@ -2458,12 +2529,26 @@ bool GLES2DecoderImpl::GetHelper( } return true; case GL_FRAMEBUFFER_BINDING: + // case GL_DRAW_FRAMEBUFFER_BINDING_EXT: (same as GL_FRAMEBUFFER_BINDING) + *num_written = 1; + if (params) { + if (bound_draw_framebuffer_) { + GLuint client_id = 0; + framebuffer_manager()->GetClientId( + bound_draw_framebuffer_->service_id(), &client_id); + *params = client_id; + } else { + *params = 0; + } + } + return true; + case GL_READ_FRAMEBUFFER_BINDING: *num_written = 1; if (params) { - if (bound_framebuffer_) { + if (bound_read_framebuffer_) { GLuint client_id = 0; framebuffer_manager()->GetClientId( - bound_framebuffer_->service_id(), &client_id); + bound_read_framebuffer_->service_id(), &client_id); *params = client_id; } else { *params = 0; @@ -2802,7 +2887,9 @@ void GLES2DecoderImpl::DoDrawArrays( void GLES2DecoderImpl::DoFramebufferRenderbuffer( GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint client_renderbuffer_id) { - if (!bound_framebuffer_) { + FramebufferManager::FramebufferInfo* framebuffer_info = + GetFramebufferInfoForTarget(target); + if (!framebuffer_info) { SetGLError(GL_INVALID_OPERATION, "glFramebufferRenderbuffer: no framebuffer bound"); return; @@ -2822,9 +2909,9 @@ void GLES2DecoderImpl::DoFramebufferRenderbuffer( target, attachment, renderbuffertarget, service_id); if (service_id == 0 || glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) { - bound_framebuffer_->AttachRenderbuffer(attachment, info); + framebuffer_info->AttachRenderbuffer(attachment, info); if (info) { - ClearUnclearedRenderbuffers(bound_framebuffer_); + ClearUnclearedRenderbuffers(target, framebuffer_info); } } } @@ -2901,7 +2988,10 @@ void GLES2DecoderImpl::DoStencilMaskSeparate(GLenum face, GLuint mask) { // are cleared because they are textures so we only need to clear // the renderbuffers. void GLES2DecoderImpl::ClearUnclearedRenderbuffers( - FramebufferManager::FramebufferInfo* info) { + GLenum target, FramebufferManager::FramebufferInfo* info) { + if (target == GL_READ_FRAMEBUFFER_EXT) { + // TODO(gman): bind this to the DRAW point, clear then bind back to READ + } GLbitfield clear_bits = 0; if (info->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)) { glClearColor(0, 0, 0, 0); @@ -2939,10 +3029,16 @@ void GLES2DecoderImpl::ClearUnclearedRenderbuffers( if (enable_scissor_test_) { glEnable(GL_SCISSOR_TEST); } + + if (target == GL_READ_FRAMEBUFFER_EXT) { + // TODO(gman): rebind draw. + } } GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) { - if (!bound_framebuffer_) { + FramebufferManager::FramebufferInfo* info = + GetFramebufferInfoForTarget(target); + if (!info) { return GL_FRAMEBUFFER_COMPLETE; } return glCheckFramebufferStatusEXT(target); @@ -2951,7 +3047,9 @@ GLenum GLES2DecoderImpl::DoCheckFramebufferStatus(GLenum target) { void GLES2DecoderImpl::DoFramebufferTexture2D( GLenum target, GLenum attachment, GLenum textarget, GLuint client_texture_id, GLint level) { - if (!bound_framebuffer_) { + FramebufferManager::FramebufferInfo* framebuffer_info = + GetFramebufferInfoForTarget(target); + if (!framebuffer_info) { SetGLError(GL_INVALID_OPERATION, "glFramebufferTexture2D: no framebuffer bound."); return; @@ -2970,13 +3068,15 @@ void GLES2DecoderImpl::DoFramebufferTexture2D( glFramebufferTexture2DEXT(target, attachment, textarget, service_id, level); if (service_id != 0 && glCheckFramebufferStatusEXT(target) == GL_FRAMEBUFFER_COMPLETE) { - ClearUnclearedRenderbuffers(bound_framebuffer_); + ClearUnclearedRenderbuffers(target, framebuffer_info); } } void GLES2DecoderImpl::DoGetFramebufferAttachmentParameteriv( GLenum target, GLenum attachment, GLenum pname, GLint* params) { - if (!bound_framebuffer_) { + FramebufferManager::FramebufferInfo* framebuffer_info = + GetFramebufferInfoForTarget(target); + if (!framebuffer_info) { SetGLError(GL_INVALID_OPERATION, "glFramebufferAttachmentParameteriv: no framebuffer bound"); return; @@ -3017,6 +3117,48 @@ void GLES2DecoderImpl::DoGetRenderbufferParameteriv( glGetRenderbufferParameterivEXT(target, pname, params); } +void GLES2DecoderImpl::DoBlitFramebufferEXT( + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) { + if (!group_->extension_flags().ext_framebuffer_multisample) { + SetGLError(GL_INVALID_OPERATION, + "glBlitFramebufferEXT: function not available"); + } + glBlitFramebufferEXT( + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); +} + +void GLES2DecoderImpl::DoRenderbufferStorageMultisample( + GLenum target, GLsizei samples, GLenum internalformat, + GLsizei width, GLsizei height) { + if (!group_->extension_flags().ext_framebuffer_multisample) { + SetGLError(GL_INVALID_OPERATION, + "glRenderbufferStorageMultisampleEXT: function not available"); + return; + } + bound_renderbuffer_->set_internal_format(internalformat); + + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + switch (internalformat) { + case GL_DEPTH_COMPONENT16: + internalformat = GL_DEPTH_COMPONENT; + break; + case GL_RGBA4: + case GL_RGB5_A1: + internalformat = GL_RGBA; + break; + case GL_RGB565: + internalformat = GL_RGB; + break; + } + } + + glRenderbufferStorageMultisampleEXT( + target, samples, internalformat, width, height); + // TODO(gman) should not set internal format unless this succeeds +} + void GLES2DecoderImpl::DoRenderbufferStorage( GLenum target, GLenum internalformat, GLsizei width, GLsizei height) { if (!bound_renderbuffer_) { @@ -3042,6 +3184,7 @@ void GLES2DecoderImpl::DoRenderbufferStorage( } glRenderbufferStorageEXT(target, internalformat, width, height); + // TODO(gman) should not set internal format unless this succeeds } void GLES2DecoderImpl::DoLinkProgram(GLuint program) { @@ -4087,7 +4230,7 @@ error::Error GLES2DecoderImpl::HandleReadPixels( CopyRealGLErrorsToWrapper(); // Get the size of the current fbo or backbuffer. - gfx::Size max_size = GetBoundFrameBufferSize(); + gfx::Size max_size = GetBoundReadFrameBufferSize(); GLint max_x; GLint max_y; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h index 0ae6355..aefe831 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h @@ -2723,6 +2723,68 @@ error::Error GLES2DecoderImpl::HandleViewport( return error::kNoError; } +error::Error GLES2DecoderImpl::HandleBlitFramebufferEXT( + uint32 immediate_data_size, const gles2::BlitFramebufferEXT& c) { + GLint srcX0 = static_cast<GLint>(c.srcX0); + GLint srcY0 = static_cast<GLint>(c.srcY0); + GLint srcX1 = static_cast<GLint>(c.srcX1); + GLint srcY1 = static_cast<GLint>(c.srcY1); + GLint dstX0 = static_cast<GLint>(c.dstX0); + GLint dstY0 = static_cast<GLint>(c.dstY0); + GLint dstX1 = static_cast<GLint>(c.dstX1); + GLint dstY1 = static_cast<GLint>(c.dstY1); + GLbitfield mask = static_cast<GLbitfield>(c.mask); + GLenum filter = static_cast<GLenum>(c.filter); + if (!validators_->blit_filter.IsValid(filter)) { + SetGLError( + GL_INVALID_ENUM, "glBlitFramebufferEXT: filter GL_INVALID_ENUM"); + return error::kNoError; + } + DoBlitFramebufferEXT( + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + return error::kNoError; +} + +error::Error GLES2DecoderImpl::HandleRenderbufferStorageMultisampleEXT( + uint32 immediate_data_size, + const gles2::RenderbufferStorageMultisampleEXT& c) { + GLenum target = static_cast<GLenum>(c.target); + GLsizei samples = static_cast<GLsizei>(c.samples); + GLenum internalformat = static_cast<GLenum>(c.internalformat); + GLsizei width = static_cast<GLsizei>(c.width); + GLsizei height = static_cast<GLsizei>(c.height); + if (!validators_->render_buffer_target.IsValid(target)) { + SetGLError( + GL_INVALID_ENUM, + "glRenderbufferStorageMultisampleEXT: target GL_INVALID_ENUM"); + return error::kNoError; + } + if (samples < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: samples < 0"); + return error::kNoError; + } + if (!validators_->render_buffer_format.IsValid(internalformat)) { + SetGLError( + GL_INVALID_ENUM, + "glRenderbufferStorageMultisampleEXT: internalformat GL_INVALID_ENUM"); + return error::kNoError; + } + if (width < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: width < 0"); + return error::kNoError; + } + if (height < 0) { + SetGLError( + GL_INVALID_VALUE, "glRenderbufferStorageMultisampleEXT: height < 0"); + return error::kNoError; + } + DoRenderbufferStorageMultisample( + target, samples, internalformat, width, height); + return error::kNoError; +} + error::Error GLES2DecoderImpl::HandleGetMaxValueInBuffer( uint32 immediate_data_size, const gles2::GetMaxValueInBuffer& c) { GLuint buffer_id = c.buffer_id; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h index 00fee19..4c7257e 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_1_autogen.h @@ -79,7 +79,7 @@ TEST_F(GLES2DecoderTest1, BindFramebufferInvalidArgs0_0) { EXPECT_CALL(*gl_, BindFramebufferEXT(_, _)).Times(0); SpecializedSetup<BindFramebuffer, 0>(false); BindFramebuffer cmd; - cmd.Init(GL_RENDERBUFFER, client_framebuffer_id_); + cmd.Init(GL_READ_FRAMEBUFFER, client_framebuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -274,7 +274,7 @@ TEST_F(GLES2DecoderTest1, CheckFramebufferStatusInvalidArgs0_0) { EXPECT_CALL(*gl_, CheckFramebufferStatusEXT(_)).Times(0); SpecializedSetup<CheckFramebufferStatus, 0>(false); CheckFramebufferStatus cmd; - cmd.Init(GL_RENDERBUFFER, shared_memory_id_, shared_memory_offset_); + cmd.Init(GL_READ_FRAMEBUFFER, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -780,7 +780,7 @@ TEST_F(GLES2DecoderTest1, FramebufferRenderbufferInvalidArgs0_0) { SpecializedSetup<FramebufferRenderbuffer, 0>(false); FramebufferRenderbuffer cmd; cmd.Init( - GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, + GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, client_renderbuffer_id_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); @@ -816,8 +816,8 @@ TEST_F(GLES2DecoderTest1, FramebufferTexture2DInvalidArgs0_0) { SpecializedSetup<FramebufferTexture2D, 0>(false); FramebufferTexture2D cmd; cmd.Init( - GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, client_texture_id_, - 5); + GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, + client_texture_id_, 5); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_ENUM, GetGLError()); } @@ -1300,7 +1300,7 @@ TEST_F(GLES2DecoderTest1, GetFramebufferAttachmentParameterivInvalidArgs0_0) { result->size = 0; GetFramebufferAttachmentParameteriv cmd; cmd.Init( - GL_RENDERBUFFER, GL_COLOR_ATTACHMENT0, + GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, shared_memory_id_, shared_memory_offset_); EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); @@ -1751,5 +1751,7 @@ TEST_F(GLES2DecoderTest1, GetTexParameterivInvalidArgs2_1) { // TODO(gman): GetUniformLocation +// TODO(gman): GetUniformLocationImmediate + #endif // GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_1_AUTOGEN_H_ diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h index 9d8cc0a..0b6aee3 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_2_autogen.h @@ -8,8 +8,6 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_DECODER_UNITTEST_2_AUTOGEN_H_ -// TODO(gman): GetUniformLocationImmediate - // TODO(gman): GetUniformLocationBucket @@ -1601,6 +1599,8 @@ TEST_F(GLES2DecoderTest2, ViewportInvalidArgs3_0) { EXPECT_EQ(error::kNoError, ExecuteCmd(cmd)); EXPECT_EQ(GL_INVALID_VALUE, GetGLError()); } +// TODO(gman): BlitFramebufferEXT +// TODO(gman): RenderbufferStorageMultisampleEXT // TODO(gman): SwapBuffers // TODO(gman): GetMaxValueInBuffer // TODO(gman): GenSharedIds diff --git a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h index f6500fd..455d593 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_autogen.h @@ -8,6 +8,7 @@ #define GPU_COMMAND_BUFFER_SERVICE_GLES2_CMD_VALIDATION_AUTOGEN_H_ ValueValidator<GLenum> attachment; +ValueValidator<GLenum> blit_filter; ValueValidator<GLenum> buffer_parameter; ValueValidator<GLenum> buffer_target; ValueValidator<GLenum> buffer_usage; diff --git a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h index 3b2407a..fda2b8b 100644 --- a/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h +++ b/gpu/command_buffer/service/gles2_cmd_validation_implementation_autogen.h @@ -13,6 +13,11 @@ static GLenum valid_attachment_table[] = { GL_STENCIL_ATTACHMENT, }; +static GLenum valid_blit_filter_table[] = { + GL_NEAREST, + GL_LINEAR, +}; + static GLenum valid_buffer_parameter_table[] = { GL_BUFFER_SIZE, GL_BUFFER_USAGE, @@ -413,6 +418,8 @@ static GLenum valid_vertex_pointer_table[] = { Validators::Validators() : attachment( valid_attachment_table, arraysize(valid_attachment_table)), + blit_filter( + valid_blit_filter_table, arraysize(valid_blit_filter_table)), buffer_parameter( valid_buffer_parameter_table, arraysize( valid_buffer_parameter_table)), |