diff options
author | kaanb@chromium.org <kaanb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:46:01 +0000 |
---|---|---|
committer | kaanb@chromium.org <kaanb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-16 10:46:01 +0000 |
commit | e9ec4269f805d8abcb187890a6ec82c4fffb861a (patch) | |
tree | 4e46f3971b5e764ea795305a6010dad3abf2ff1c | |
parent | b9ed58f046141b4610c1bdc966d962d5fb95ac6b (diff) | |
download | chromium_src-e9ec4269f805d8abcb187890a6ec82c4fffb861a.zip chromium_src-e9ec4269f805d8abcb187890a6ec82c4fffb861a.tar.gz chromium_src-e9ec4269f805d8abcb187890a6ec82c4fffb861a.tar.bz2 |
GPU client side changes for GpuMemoryBuffers:
- Introduces a new GL extension CHROMIUM_map_image that contains Create/Destroy/Map/Unmap/GetImageParameteriv methods.
- A new data structure called GpuMemoryBufferTracker to track these buffers and images on the client side.
BUG=175012
Review URL: https://chromiumcodereview.appspot.com/14456004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@200505 0039d316-1c4b-4281-b951-d872f2087c98
40 files changed, 1081 insertions, 18 deletions
diff --git a/android_webview/browser/gpu_memory_buffer_impl.cc b/android_webview/browser/gpu_memory_buffer_impl.cc index 561c7c9..c22fae8 100644 --- a/android_webview/browser/gpu_memory_buffer_impl.cc +++ b/android_webview/browser/gpu_memory_buffer_impl.cc @@ -63,7 +63,7 @@ bool GpuMemoryBufferImpl::IsMapped() { void GpuMemoryBufferImpl::SetAwDrawGLFunctionTable( AwDrawGLFunctionTable* table) { g_gl_draw_functions = table; - gpu::SetProcessDefaultGpuMemoryBufferFactory( + gpu::gles2::SetProcessDefaultGpuMemoryBufferFactory( base::Bind(&CreateGpuMemoryBuffer)); } diff --git a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc index 14b9914..b5ee5c4 100644 --- a/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc +++ b/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc @@ -368,7 +368,8 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext( share_group_context->GetImplementation()->share_group() : NULL, transfer_buffer_, attributes_.shareResources, - bind_generates_resources_); + bind_generates_resources_, + NULL); gl_ = real_gl_; if (!real_gl_->Initialize( diff --git a/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt new file mode 100644 index 0000000..6304fda --- /dev/null +++ b/gpu/GLES2/extensions/CHROMIUM/CHROMIUM_map_image.txt @@ -0,0 +1,107 @@ +Name + + CHROMIUM_map_image + +Name Strings + + GL_CHROMIUM_map_image + +Version + + Last Modifed Date: May 9, 2013 + +Dependencies + + OpenGL ES 2.0 is required. + +Overview + + This extension allows for more efficient uploading of texture data through + Chromium's OpenGL ES 2.0 implementation. + + For security reasons Chromium accesses the GPU from a separate process. User + processes are not allowed to access the GPU directly. This multi-process + architechure has the advantage that GPU operations can be secured and + pipelined but it has the disadvantage that all data that is going to be + passed to GPU must first be made available to the separate GPU process. + + This extension helps the application directly allocate and access texture + memory. + +Issues + + None + +New Tokens + + None + +New Procedures and Functions + + GLuint CreateImageCHROMIUM (GLsizei width, GLsizei height, + GLenum internalformat) + + Allocate an image with width equal to <width> and height equal + to <height> stored in format <internalformat>. + + Returns a unique identifier for the allocated image that could be used + in subsequent operations. + + INVALID_VALUE is generated if <width> or <height> is nonpositive. + + void DestroyImageCHROMIUM (GLuint image_id) + + Frees the image previously allocated by a call to CreateImageCHROMIUM. + + INVALID_OPERATION is generated if <image_id> is not a valid image id. + + void* MapImageCHROMIUM (GLuint image_id, GLenum access) + + Returns a pointer to in the user memory for the application to modify + the image. <access> parameter defines if the user will read or write the + pixels. + + INVALID_OPERATION is generated if <image_id> is not a valid image id. + + INVALID_OPERATION is generated if the image was already mapped by a previous + call to this method. + + INVALID_ENUM is generated if <access> is not one of WRITE_ONLY, READ_ONLY + and READ_WRITE. + + void UnmapImageCHROMIUM (GLuint image_id) + + Removes the mapping created by a call to MapImageCHROMIUM. + + Note that after calling UnmapImageCHROMIUM the application should assume + that the memory returned by MapImageCHROMIUM is off limits and is no longer + accessible by the application. Accessing it after calling + UnmapImageCHROMIUM will produce undefined results. + + INVALID_OPERATION is generated if <image_id> is not a valid image id. + + INVALID_OPERATION is generated if the image was not already mapped by a + previous call to MapImageCHROMIUM. + + void GetImageParameterivCHROMIUM(GLuint image_id, GLenum pname, + GLint* params) + + Sets <params> to the integer value of the parameter specified by <pname> + for the image specified by <image_id>. <params> is expected to be + properly allocated before calling this method. + + INVALID_OPERATION is generated if <image_id> is not a valid image id. + + INVALID_ENUM is generated if <pname> is not IMAGE_ROWBYTES_CHROMIUM. + +Errors + + None. + +New State + + None. + +Revision History + + 5/9/2013 Documented the extension diff --git a/gpu/GLES2/gl2chromium_autogen.h b/gpu/GLES2/gl2chromium_autogen.h index fa099e6..e8970e0 100644 --- a/gpu/GLES2/gl2chromium_autogen.h +++ b/gpu/GLES2/gl2chromium_autogen.h @@ -182,6 +182,8 @@ #define glEnableFeatureCHROMIUM GLES2_GET_FUN(EnableFeatureCHROMIUM) #define glMapBufferCHROMIUM GLES2_GET_FUN(MapBufferCHROMIUM) #define glUnmapBufferCHROMIUM GLES2_GET_FUN(UnmapBufferCHROMIUM) +#define glMapImageCHROMIUM GLES2_GET_FUN(MapImageCHROMIUM) +#define glUnmapImageCHROMIUM GLES2_GET_FUN(UnmapImageCHROMIUM) #define glMapBufferSubDataCHROMIUM GLES2_GET_FUN(MapBufferSubDataCHROMIUM) #define glUnmapBufferSubDataCHROMIUM GLES2_GET_FUN(UnmapBufferSubDataCHROMIUM) #define glMapTexSubImage2DCHROMIUM GLES2_GET_FUN(MapTexSubImage2DCHROMIUM) @@ -199,6 +201,10 @@ CreateStreamTextureCHROMIUM) #define glDestroyStreamTextureCHROMIUM GLES2_GET_FUN( \ DestroyStreamTextureCHROMIUM) +#define glCreateImageCHROMIUM GLES2_GET_FUN(CreateImageCHROMIUM) +#define glDestroyImageCHROMIUM GLES2_GET_FUN(DestroyImageCHROMIUM) +#define glGetImageParameterivCHROMIUM GLES2_GET_FUN( \ + GetImageParameterivCHROMIUM) #define glGetTranslatedShaderSourceANGLE GLES2_GET_FUN( \ GetTranslatedShaderSourceANGLE) #define glPostSubBufferCHROMIUM GLES2_GET_FUN(PostSubBufferCHROMIUM) diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h index 9193467..d23191c 100644 --- a/gpu/GLES2/gl2extchromium.h +++ b/gpu/GLES2/gl2extchromium.h @@ -94,6 +94,39 @@ typedef GLboolean (GL_APIENTRY PFNGLUNMAPBUFFERCHROMIUM) (GLuint target); #endif #endif /* GL_CHROMIUM_pixel_transfer_buffer_object */ +/* GL_CHROMIUM_map_image */ +#ifndef GL_CHROMIUM_map_image +#define GL_CHROMIUM_map_image 1 + +#ifndef GL_IMAGE_ROWBYTES_CHROMIUM +#define GL_IMAGE_ROWBYTES_CHROMIUM 0x78F0 +#endif + +#ifndef GL_READ_WRITE +#define GL_READ_WRITE 0x88BA +#endif + +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat); +GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM(GLuint image_id); +GL_APICALL void GL_APIENTRY glGetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params); +GL_APICALL void* GL_APIENTRY glMapImageCHROMIUM(GLuint image_id, GLenum access); +GL_APICALL void GL_APIENTRY glUnmapImageCHROMIUM(GLuint image_id); +#endif +typedef GLuint (GL_APIENTRYP PFNGLCREATEIMAGECHROMIUMPROC) ( + GLsizei width, GLsizei height, GLenum internalformat); +typedef void ( + GL_APIENTRYP PFNGLDESTROYIMAGECHROMIUMPROC) (GLuint image_id); +typedef void ( + GL_APIENTRYP PFNGLGETIMAGEPARAMETERIVCHROMIUMPROC) ( + GLuint image_id, GLenum pname, GLint* params); +typedef void* (GL_APIENTRYP PFNGLMAPIMAGECHROMIUMPROC) ( + GLuint image_id, GLenum access); +typedef void (GL_APIENTRYP PFNGLUNMAPIMAGECHROMIUMPROC) (GLuint image_id); +#endif /* GL_CHROMIUM_map_image */ + /* GL_CHROMIUM_map_sub */ #ifndef GL_CHROMIUM_map_sub #define GL_CHROMIUM_map_sub 1 diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index f8a355d..435d13a 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -1306,6 +1306,32 @@ _FUNCTION_INFO = { 'decoder_func': 'DoCopyTexSubImage2D', 'defer_reads': True, }, + 'CreateImageCHROMIUM': { + 'type': 'Manual', + 'cmd_args': 'GLsizei width, GLsizei height, GLenum internalformat', + 'result': ['GLuint'], + 'client_test': False, + 'gen_cmd': False, + 'expectation': False, + 'extension': True, + 'chromium': True, + }, + 'DestroyImageCHROMIUM': { + 'type': 'Manual', + 'immediate': True, + 'client_test': False, + 'gen_cmd': False, + 'extension': True, + 'chromium': True, + }, + 'GetImageParameterivCHROMIUM': { + 'type': 'Manual', + 'client_test': False, + 'gen_cmd': False, + 'expectation': False, + 'extension': True, + 'chromium': True, + }, 'CreateProgram': { 'type': 'Create', 'client_test': False, @@ -1780,7 +1806,6 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, 'client_test': False, - 'chromium': True, }, 'MapBufferSubDataCHROMIUM': { 'gen_cmd': False, @@ -1789,6 +1814,12 @@ _FUNCTION_INFO = { 'client_test': False, 'pepper_interface': 'ChromiumMapSub', }, + 'MapImageCHROMIUM': { + 'gen_cmd': False, + 'extension': True, + 'chromium': True, + 'client_test': False, + }, 'MapTexSubImage2DCHROMIUM': { 'gen_cmd': False, 'extension': True, @@ -2015,7 +2046,6 @@ _FUNCTION_INFO = { 'extension': True, 'chromium': True, 'client_test': False, - 'chromium': True, }, 'UnmapBufferSubDataCHROMIUM': { 'gen_cmd': False, @@ -2024,6 +2054,12 @@ _FUNCTION_INFO = { 'client_test': False, 'pepper_interface': 'ChromiumMapSub', }, + 'UnmapImageCHROMIUM': { + 'gen_cmd': False, + 'extension': True, + 'chromium': True, + 'client_test': False, + }, 'UnmapTexSubImage2DCHROMIUM': { 'gen_cmd': False, 'extension': True, diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index f1a5b08..6df6060 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -595,6 +595,12 @@ void* GLES2MapBufferCHROMIUM(GLuint target, GLenum access) { GLboolean GLES2UnmapBufferCHROMIUM(GLuint target) { return gles2::GetGLContext()->UnmapBufferCHROMIUM(target); } +void* GLES2MapImageCHROMIUM(GLuint image_id, GLenum access) { + return gles2::GetGLContext()->MapImageCHROMIUM(image_id, access); +} +void GLES2UnmapImageCHROMIUM(GLuint image_id) { + gles2::GetGLContext()->UnmapImageCHROMIUM(image_id); +} void* GLES2MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) { return gles2::GetGLContext()->MapBufferSubDataCHROMIUM( @@ -639,6 +645,18 @@ GLuint GLES2CreateStreamTextureCHROMIUM(GLuint texture) { void GLES2DestroyStreamTextureCHROMIUM(GLuint texture) { gles2::GetGLContext()->DestroyStreamTextureCHROMIUM(texture); } +GLuint GLES2CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) { + return gles2::GetGLContext()->CreateImageCHROMIUM( + width, height, internalformat); +} +void GLES2DestroyImageCHROMIUM(GLuint image_id) { + gles2::GetGLContext()->DestroyImageCHROMIUM(image_id); +} +void GLES2GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) { + gles2::GetGLContext()->GetImageParameterivCHROMIUM(image_id, pname, params); +} void GLES2GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) { gles2::GetGLContext()->GetTranslatedShaderSourceANGLE( @@ -1006,6 +1024,10 @@ NameToFunc g_gles2_function_table[] = { glMapBufferCHROMIUM), }, { "glUnmapBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( glUnmapBufferCHROMIUM), }, + { "glMapImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glMapImageCHROMIUM), }, + { "glUnmapImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glUnmapImageCHROMIUM), }, { "glMapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( glMapBufferSubDataCHROMIUM), }, { "glUnmapBufferSubDataCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( @@ -1028,6 +1050,12 @@ NameToFunc g_gles2_function_table[] = { glCreateStreamTextureCHROMIUM), }, { "glDestroyStreamTextureCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( glDestroyStreamTextureCHROMIUM), }, + { "glCreateImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glCreateImageCHROMIUM), }, + { "glDestroyImageCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glDestroyImageCHROMIUM), }, + { "glGetImageParameterivCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( + glGetImageParameterivCHROMIUM), }, { "glGetTranslatedShaderSourceANGLE", reinterpret_cast<GLES2FunctionPointer>( glGetTranslatedShaderSourceANGLE), }, { "glPostSubBufferCHROMIUM", reinterpret_cast<GLES2FunctionPointer>( diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 0ce55a5..e7dbdc2 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -16,6 +16,9 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include "../client/buffer_tracker.h" +#include "../client/gpu_memory_buffer.h" +#include "../client/gpu_memory_buffer_factory.h" +#include "../client/gpu_memory_buffer_tracker.h" #include "../client/mapped_memory.h" #include "../client/program_info_manager.h" #include "../client/query_tracker.h" @@ -84,7 +87,8 @@ GLES2Implementation::GLES2Implementation( ShareGroup* share_group, TransferBufferInterface* transfer_buffer, bool share_resources, - bool bind_generates_resource) + bool bind_generates_resource, + ImageFactory* image_factory) : helper_(helper), transfer_buffer_(transfer_buffer), angle_pack_reverse_row_order_status_(kUnknownExtensionStatus), @@ -108,7 +112,8 @@ GLES2Implementation::GLES2Implementation( debug_(false), use_count_(0), current_query_(NULL), - error_message_callback_(NULL) { + error_message_callback_(NULL), + image_factory_(image_factory) { GPU_DCHECK(helper); GPU_DCHECK(transfer_buffer); @@ -162,6 +167,7 @@ bool GLES2Implementation::Initialize( query_tracker_.reset(new QueryTracker(mapped_memory_.get())); buffer_tracker_.reset(new BufferTracker(mapped_memory_.get())); + gpu_memory_buffer_tracker_.reset(new GpuMemoryBufferTracker(image_factory_)); #if defined(GLES2_SUPPORT_CLIENT_SIDE_ARRAYS) GetIdHandler(id_namespaces::kBuffers)->MakeIds( @@ -2094,6 +2100,10 @@ const GLubyte* GLES2Implementation::GetStringHelper(GLenum name) { "GL_CHROMIUM_map_sub " "GL_CHROMIUM_shallow_flush " "GL_EXT_unpack_subimage"; + if (image_factory_ != NULL) { + // The first space character is intentional. + str += " GL_CHROMIUM_map_image"; + } break; default: break; @@ -3567,11 +3577,11 @@ GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { } BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); if (!buffer) { - SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "invalid buffer"); + SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "invalid buffer"); return false; } if (!buffer->mapped()) { - SetGLError(GL_INVALID_OPERATION, "glMapBufferCHROMIUM", "not mapped"); + SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); return false; } buffer->set_mapped(false); @@ -3687,6 +3697,163 @@ GLuint GLES2Implementation::InsertSyncPointCHROMIUM() { return helper_->InsertSyncPointCHROMIUM(); } +GLuint GLES2Implementation::CreateImageCHROMIUMHelper( + GLsizei width, GLsizei height, GLenum internalformat) { + if (width <= 0) { + SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "width <= 0"); + return 0; + } + + if (height <= 0) { + SetGLError(GL_INVALID_VALUE, "glCreateImageCHROMIUM", "height <= 0"); + return 0; + } + // Flush the command stream to ensure ordering in case the newly + // returned image_id has recently been in use with a different buffer. + helper_->CommandBufferHelper::Flush(); + + // Create new buffer. + return gpu_memory_buffer_tracker_->CreateBuffer( + width, height, internalformat); +} + +GLuint GLES2Implementation::CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glCreateImageCHROMIUM(" + << width << ", " + << height << ", " + << GLES2Util::GetStringTextureInternalFormat(internalformat) << ")"); + GLuint image_id = CreateImageCHROMIUMHelper(width, height, internalformat); + CheckGLError(); + return image_id; +} + +void GLES2Implementation::DestroyImageCHROMIUMHelper(GLuint image_id) { + GpuMemoryBuffer* gpu_buffer = + gpu_memory_buffer_tracker_->GetBuffer(image_id); + if (!gpu_buffer) { + SetGLError(GL_INVALID_OPERATION, "glDestroyImageCHROMIUM", + "invalid image"); + return; + } + + // Flush the command stream to make sure all pending commands + // that may refer to the image_id are executed on the service side. + helper_->CommandBufferHelper::Flush(); + gpu_memory_buffer_tracker_->RemoveBuffer(image_id); +} + +void GLES2Implementation::DestroyImageCHROMIUM(GLuint image_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glDestroyImageCHROMIUM(" + << image_id << ")"); + DestroyImageCHROMIUMHelper(image_id); + CheckGLError(); +} + +void GLES2Implementation::UnmapImageCHROMIUMHelper(GLuint image_id) { + GpuMemoryBuffer* gpu_buffer = + gpu_memory_buffer_tracker_->GetBuffer(image_id); + if (!gpu_buffer) { + SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "invalid image"); + return; + } + + if (!gpu_buffer->IsMapped()) { + SetGLError(GL_INVALID_OPERATION, "glUnmapImageCHROMIUM", "not mapped"); + return; + } + gpu_buffer->Unmap(); +} + +void GLES2Implementation::UnmapImageCHROMIUM(GLuint image_id) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glUnmapImageCHROMIUM(" + << image_id << ")"); + + UnmapImageCHROMIUMHelper(image_id); + CheckGLError(); +} + +void* GLES2Implementation::MapImageCHROMIUMHelper(GLuint image_id, + GLenum access) { + GpuMemoryBuffer* gpu_buffer = + gpu_memory_buffer_tracker_->GetBuffer(image_id); + if (!gpu_buffer) { + SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "invalid image"); + return NULL; + } + GpuMemoryBuffer::AccessMode mode; + switch(access) { + case GL_WRITE_ONLY: + mode = GpuMemoryBuffer::WRITE_ONLY; + break; + case GL_READ_ONLY: + mode = GpuMemoryBuffer::READ_ONLY; + break; + case GL_READ_WRITE: + mode = GpuMemoryBuffer::READ_WRITE; + break; + default: + SetGLError(GL_INVALID_ENUM, "glMapImageCHROMIUM", + "invalid GPU access mode"); + return NULL; + } + + if (gpu_buffer->IsMapped()) { + SetGLError(GL_INVALID_OPERATION, "glMapImageCHROMIUM", "already mapped"); + return NULL; + } + + void* mapped_buffer = NULL; + gpu_buffer->Map(mode, &mapped_buffer); + return mapped_buffer; +} + +void* GLES2Implementation::MapImageCHROMIUM( + GLuint image_id, GLenum access) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM(" + << image_id << ", " + << GLES2Util::GetStringEnum(access) << ")"); + + void* mapped = MapImageCHROMIUMHelper(image_id, access); + CheckGLError(); + return mapped; +} + +void GLES2Implementation::GetImageParameterivCHROMIUMHelper( + GLuint image_id, GLenum pname, GLint* params) { + if (pname != GL_IMAGE_ROWBYTES_CHROMIUM) { + SetGLError(GL_INVALID_ENUM, "glGetImageParameterivCHROMIUM", + "invalid parameter"); + return; + } + + GpuMemoryBuffer* gpu_buffer = + gpu_memory_buffer_tracker_->GetBuffer(image_id); + if (!gpu_buffer) { + SetGLError(GL_INVALID_OPERATION, "glGetImageParameterivCHROMIUM", + "invalid image"); + return; + } + + *params = gpu_buffer->GetStride(); +} + +void GLES2Implementation::GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) { + GPU_CLIENT_SINGLE_THREAD_CHECK(); + GPU_CLIENT_VALIDATE_DESTINATION_INITALIZATION(GLint, params); + GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glMapImageCHROMIUM(" + << image_id << ", " + << GLES2Util::GetStringBufferParameter(pname) << ", " + << static_cast<const void*>(params) << ")"); + GetImageParameterivCHROMIUM(image_id, pname, params); + CheckGLError(); +} + // 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/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index a633dd6..e8b367c 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -18,6 +18,8 @@ #include "../client/client_context_state.h" #include "../client/gles2_cmd_helper.h" #include "../client/gles2_interface.h" +#include "../client/gpu_memory_buffer_tracker.h" +#include "../client/image_factory.h" #include "../client/query_tracker.h" #include "../client/ref_counted.h" #include "../client/ring_buffer.h" @@ -102,6 +104,7 @@ class TransferBufferInterface; namespace gles2 { +class ImageFactory; class VertexArrayObjectManager; // This class emulates GLES2 over command buffers. It can be used by a client @@ -174,7 +177,8 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { ShareGroup* share_group, TransferBufferInterface* transfer_buffer, bool share_resources, - bool bind_generates_resource); + bool bind_generates_resource, + ImageFactory* image_factory); virtual ~GLES2Implementation(); @@ -496,6 +500,14 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { GLenum target, GLintptr offset, GLsizeiptr size, const void* data, ScopedTransferBufferPtr* buffer); + GLuint CreateImageCHROMIUMHelper( + GLsizei width, GLsizei height, GLenum internalformat); + void DestroyImageCHROMIUMHelper(GLuint image_id); + void* MapImageCHROMIUMHelper(GLuint image_id, GLenum access); + void UnmapImageCHROMIUMHelper(GLuint image_id); + void GetImageParameterivCHROMIUMHelper( + GLuint image_id, GLenum pname, GLint* params); + // Helper for GetVertexAttrib bool GetVertexAttribHelper(GLuint index, GLenum pname, uint32* param); @@ -654,10 +666,14 @@ class GLES2_IMPL_EXPORT GLES2Implementation : public GLES2Interface { scoped_ptr<BufferTracker> buffer_tracker_; + scoped_ptr<GpuMemoryBufferTracker> gpu_memory_buffer_tracker_; + ErrorMessageCallback* error_message_callback_; scoped_ptr<std::string> current_trace_name_; + ImageFactory* image_factory_; + DISALLOW_COPY_AND_ASSIGN(GLES2Implementation); }; diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 3510bbf..3123b59 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -438,6 +438,10 @@ virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE; virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE; +virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE; + +virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE; + virtual void* MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE; @@ -468,6 +472,14 @@ virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) OVERRIDE; virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE; +virtual GLuint CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE; + +virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE; + +virtual void GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) OVERRIDE; + virtual void GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE; diff --git a/gpu/command_buffer/client/gles2_implementation_unittest.cc b/gpu/command_buffer/client/gles2_implementation_unittest.cc index 4343ca8..7208425 100644 --- a/gpu/command_buffer/client/gles2_implementation_unittest.cc +++ b/gpu/command_buffer/client/gles2_implementation_unittest.cc @@ -401,7 +401,8 @@ class GLES2ImplementationTest : public testing::Test { NULL, transfer_buffer_.get(), shared_resources, - bind_generates_resource)); + bind_generates_resource, + NULL)); ASSERT_TRUE(gl_->Initialize( kTransferBufferSize, kTransferBufferSize, diff --git a/gpu/command_buffer/client/gles2_interface_autogen.h b/gpu/command_buffer/client/gles2_interface_autogen.h index 865f7ed..0fca7e8 100644 --- a/gpu/command_buffer/client/gles2_interface_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_autogen.h @@ -251,6 +251,8 @@ virtual void RegisterSharedIdsCHROMIUM( virtual GLboolean EnableFeatureCHROMIUM(const char* feature) = 0; virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) = 0; virtual GLboolean UnmapBufferCHROMIUM(GLuint target) = 0; +virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) = 0; +virtual void UnmapImageCHROMIUM(GLuint image_id) = 0; virtual void* MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) = 0; virtual void UnmapBufferSubDataCHROMIUM(const void* mem) = 0; @@ -268,6 +270,11 @@ virtual void GetProgramInfoCHROMIUM( GLuint program, GLsizei bufsize, GLsizei* size, void* info) = 0; virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) = 0; virtual void DestroyStreamTextureCHROMIUM(GLuint texture) = 0; +virtual GLuint CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) = 0; +virtual void DestroyImageCHROMIUM(GLuint image_id) = 0; +virtual void GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) = 0; virtual void GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) = 0; virtual void PostSubBufferCHROMIUM( diff --git a/gpu/command_buffer/client/gles2_interface_stub_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_autogen.h index 769b260..00c3a90 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_autogen.h @@ -279,6 +279,8 @@ virtual void RegisterSharedIdsCHROMIUM( virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE; virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE; virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE; +virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE; +virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE; virtual void* MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE; virtual void UnmapBufferSubDataCHROMIUM(const void* mem) OVERRIDE; @@ -297,6 +299,11 @@ virtual void GetProgramInfoCHROMIUM( GLuint program, GLsizei bufsize, GLsizei* size, void* info) OVERRIDE; virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) OVERRIDE; virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE; +virtual GLuint CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE; +virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE; +virtual void GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) OVERRIDE; virtual void GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE; virtual void PostSubBufferCHROMIUM( diff --git a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h index b1c4ac5..36ca9b8 100644 --- a/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_interface_stub_impl_autogen.h @@ -527,6 +527,12 @@ void* GLES2InterfaceStub::MapBufferCHROMIUM( GLboolean GLES2InterfaceStub::UnmapBufferCHROMIUM(GLuint /* target */) { return 0; } +void* GLES2InterfaceStub::MapImageCHROMIUM( + GLuint /* image_id */, GLenum /* access */) { + return 0; +} +void GLES2InterfaceStub::UnmapImageCHROMIUM(GLuint /* image_id */) { +} void* GLES2InterfaceStub::MapBufferSubDataCHROMIUM( GLuint /* target */, GLintptr /* offset */, GLsizeiptr /* size */, GLenum /* access */) { @@ -566,6 +572,15 @@ GLuint GLES2InterfaceStub::CreateStreamTextureCHROMIUM(GLuint /* texture */) { } void GLES2InterfaceStub::DestroyStreamTextureCHROMIUM(GLuint /* texture */) { } +GLuint GLES2InterfaceStub::CreateImageCHROMIUM( + GLsizei /* width */, GLsizei /* height */, GLenum /* internalformat */) { + return 0; +} +void GLES2InterfaceStub::DestroyImageCHROMIUM(GLuint /* image_id */) { +} +void GLES2InterfaceStub::GetImageParameterivCHROMIUM( + GLuint /* image_id */, GLenum /* pname */, GLint* /* params */) { +} void GLES2InterfaceStub::GetTranslatedShaderSourceANGLE( GLuint /* shader */, GLsizei /* bufsize */, GLsizei* /* length */, char* /* source */) { diff --git a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h index 7ec9eb6..9888a5d 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_autogen.h @@ -279,6 +279,8 @@ virtual void RegisterSharedIdsCHROMIUM( virtual GLboolean EnableFeatureCHROMIUM(const char* feature) OVERRIDE; virtual void* MapBufferCHROMIUM(GLuint target, GLenum access) OVERRIDE; virtual GLboolean UnmapBufferCHROMIUM(GLuint target) OVERRIDE; +virtual void* MapImageCHROMIUM(GLuint image_id, GLenum access) OVERRIDE; +virtual void UnmapImageCHROMIUM(GLuint image_id) OVERRIDE; virtual void* MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) OVERRIDE; virtual void UnmapBufferSubDataCHROMIUM(const void* mem) OVERRIDE; @@ -297,6 +299,11 @@ virtual void GetProgramInfoCHROMIUM( GLuint program, GLsizei bufsize, GLsizei* size, void* info) OVERRIDE; virtual GLuint CreateStreamTextureCHROMIUM(GLuint texture) OVERRIDE; virtual void DestroyStreamTextureCHROMIUM(GLuint texture) OVERRIDE; +virtual GLuint CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) OVERRIDE; +virtual void DestroyImageCHROMIUM(GLuint image_id) OVERRIDE; +virtual void GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) OVERRIDE; virtual void GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) OVERRIDE; virtual void PostSubBufferCHROMIUM( diff --git a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h index 0471880..40be4e9 100644 --- a/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h +++ b/gpu/command_buffer/client/gles2_trace_implementation_impl_autogen.h @@ -978,6 +978,17 @@ GLboolean GLES2TraceImplementation::UnmapBufferCHROMIUM(GLuint target) { return gl_->UnmapBufferCHROMIUM(target); } +void* GLES2TraceImplementation::MapImageCHROMIUM( + GLuint image_id, GLenum access) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapImageCHROMIUM"); + return gl_->MapImageCHROMIUM(image_id, access); +} + +void GLES2TraceImplementation::UnmapImageCHROMIUM(GLuint image_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::UnmapImageCHROMIUM"); + gl_->UnmapImageCHROMIUM(image_id); +} + void* GLES2TraceImplementation::MapBufferSubDataCHROMIUM( GLuint target, GLintptr offset, GLsizeiptr size, GLenum access) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::MapBufferSubDataCHROMIUM"); @@ -1045,6 +1056,23 @@ void GLES2TraceImplementation::DestroyStreamTextureCHROMIUM(GLuint texture) { gl_->DestroyStreamTextureCHROMIUM(texture); } +GLuint GLES2TraceImplementation::CreateImageCHROMIUM( + GLsizei width, GLsizei height, GLenum internalformat) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::CreateImageCHROMIUM"); + return gl_->CreateImageCHROMIUM(width, height, internalformat); +} + +void GLES2TraceImplementation::DestroyImageCHROMIUM(GLuint image_id) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::DestroyImageCHROMIUM"); + gl_->DestroyImageCHROMIUM(image_id); +} + +void GLES2TraceImplementation::GetImageParameterivCHROMIUM( + GLuint image_id, GLenum pname, GLint* params) { + TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetImageParameterivCHROMIUM"); // NOLINT + gl_->GetImageParameterivCHROMIUM(image_id, pname, params); +} + void GLES2TraceImplementation::GetTranslatedShaderSourceANGLE( GLuint shader, GLsizei bufsize, GLsizei* length, char* source) { TRACE_EVENT_BINARY_EFFICIENT0("gpu", "GLES2Trace::GetTranslatedShaderSourceANGLE"); // NOLINT diff --git a/gpu/command_buffer/client/gpu_memory_buffer.h b/gpu/command_buffer/client/gpu_memory_buffer.h index 14e95ee..b388f47 100644 --- a/gpu/command_buffer/client/gpu_memory_buffer.h +++ b/gpu/command_buffer/client/gpu_memory_buffer.h @@ -27,7 +27,7 @@ class GLES2_IMPL_EXPORT GpuMemoryBuffer { enum AccessMode { READ_ONLY, WRITE_ONLY, - READ_OR_WRITE, + READ_WRITE, }; // Frees a previously allocated buffer. Freeing a buffer that is still diff --git a/gpu/command_buffer/client/gpu_memory_buffer_factory.cc b/gpu/command_buffer/client/gpu_memory_buffer_factory.cc index c0e5b9f..57fcef7 100644 --- a/gpu/command_buffer/client/gpu_memory_buffer_factory.cc +++ b/gpu/command_buffer/client/gpu_memory_buffer_factory.cc @@ -7,19 +7,23 @@ #include "base/logging.h" namespace gpu { +namespace gles2 { namespace { GpuMemoryBuffer::Creator* g_gpu_memory_buffer_factory_ = NULL; } const GpuMemoryBuffer::Creator& GetProcessDefaultGpuMemoryBufferFactory() { + DCHECK(g_gpu_memory_buffer_factory_ != NULL); return *g_gpu_memory_buffer_factory_; } void SetProcessDefaultGpuMemoryBufferFactory( const GpuMemoryBuffer::Creator& factory) { DCHECK(g_gpu_memory_buffer_factory_ == NULL); + // TODO(kaanb): move the ownership of this memory to android_webview g_gpu_memory_buffer_factory_ = new GpuMemoryBuffer::Creator(factory); } +} // namespace gles2 } // namespace gpu diff --git a/gpu/command_buffer/client/gpu_memory_buffer_factory.h b/gpu/command_buffer/client/gpu_memory_buffer_factory.h index dd10a7d..191a2e2 100644 --- a/gpu/command_buffer/client/gpu_memory_buffer_factory.h +++ b/gpu/command_buffer/client/gpu_memory_buffer_factory.h @@ -9,6 +9,7 @@ #include "gpu/command_buffer/client/gpu_memory_buffer.h" namespace gpu { +namespace gles2 { // Getter and setter for a GpuMemoryBuffer factory for the current process. // Currently it is only used for Android Webview where both browser and @@ -22,6 +23,7 @@ GLES2_IMPL_EXPORT const GpuMemoryBuffer::Creator& GLES2_IMPL_EXPORT void SetProcessDefaultGpuMemoryBufferFactory( const GpuMemoryBuffer::Creator& factory); +} // namespace gles2 } // namespace gpu #endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_FACTORY_H_ diff --git a/gpu/command_buffer/client/gpu_memory_buffer_mock.cc b/gpu/command_buffer/client/gpu_memory_buffer_mock.cc new file mode 100644 index 0000000..1d24716 --- /dev/null +++ b/gpu/command_buffer/client/gpu_memory_buffer_mock.cc @@ -0,0 +1,16 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "../client/gpu_memory_buffer_mock.h" + +namespace gpu { + +GpuMemoryBufferMock::GpuMemoryBufferMock(int width, int height) { +} + +GpuMemoryBufferMock::~GpuMemoryBufferMock() { + Die(); +} + +} // namespace gpu diff --git a/gpu/command_buffer/client/gpu_memory_buffer_mock.h b/gpu/command_buffer/client/gpu_memory_buffer_mock.h new file mode 100644 index 0000000..e47dc74 --- /dev/null +++ b/gpu/command_buffer/client/gpu_memory_buffer_mock.h @@ -0,0 +1,32 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_ +#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_ + +#include "../client/gpu_memory_buffer.h" +#include "base/basictypes.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace gpu { + +class GpuMemoryBufferMock : public GpuMemoryBuffer { + public: + GpuMemoryBufferMock(int width, int height); + virtual ~GpuMemoryBufferMock(); + + MOCK_METHOD2(Map, void(GpuMemoryBuffer::AccessMode, void**)); + MOCK_METHOD0(Unmap, void()); + MOCK_METHOD0(IsMapped, bool()); + MOCK_METHOD0(GetNativeBuffer, void*()); + MOCK_METHOD0(GetStride, uint32()); + MOCK_METHOD0(Die, void()); + + private: + DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferMock); +}; + +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_MOCK_H_ diff --git a/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc b/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc new file mode 100644 index 0000000..b336796 --- /dev/null +++ b/gpu/command_buffer/client/gpu_memory_buffer_tracker.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "../client/gpu_memory_buffer_tracker.h" + +#include "../client/gles2_implementation.h" +#include "../client/gpu_memory_buffer.h" +#include "../client/image_factory.h" +#include "base/memory/scoped_ptr.h" + +namespace gpu { +namespace gles2 { + +GpuMemoryBufferTracker::GpuMemoryBufferTracker(ImageFactory* factory) + : buffers_(), + factory_(factory) { +} + +GpuMemoryBufferTracker::~GpuMemoryBufferTracker() { + while (!buffers_.empty()) { + RemoveBuffer(buffers_.begin()->first); + } +} + +GLuint GpuMemoryBufferTracker::CreateBuffer( + GLsizei width, GLsizei height, GLenum internalformat) { + GLuint image_id = 0; + DCHECK(factory_); + scoped_ptr<GpuMemoryBuffer> buffer = + factory_->CreateGpuMemoryBuffer(width, height, internalformat, &image_id); + + std::pair<BufferMap::iterator, bool> result = + buffers_.insert(std::make_pair(image_id, buffer.release())); + GPU_DCHECK(result.second); + + return image_id; +} + +GpuMemoryBuffer* GpuMemoryBufferTracker::GetBuffer(GLuint image_id) { + BufferMap::iterator it = buffers_.find(image_id); + return (it != buffers_.end()) ? it->second : NULL; +} + +void GpuMemoryBufferTracker::RemoveBuffer(GLuint image_id) { + BufferMap::iterator buffer_it = buffers_.find(image_id); + if (buffer_it != buffers_.end()) { + GpuMemoryBuffer* buffer = buffer_it->second; + buffers_.erase(buffer_it); + delete buffer; + } + DCHECK(factory_); + factory_->DeleteGpuMemoryBuffer(image_id); +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/client/gpu_memory_buffer_tracker.h b/gpu/command_buffer/client/gpu_memory_buffer_tracker.h new file mode 100644 index 0000000..2666c58 --- /dev/null +++ b/gpu/command_buffer/client/gpu_memory_buffer_tracker.h @@ -0,0 +1,43 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_ +#define GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_ + +#include <GLES2/gl2.h> + +#include "../client/hash_tables.h" +#include "base/basictypes.h" +#include "gles2_impl_export.h" + +namespace gpu { +class GpuMemoryBuffer; + +namespace gles2 { +class ImageFactory; + +// Tracks GPU memory buffer objects on the client side. +class GLES2_IMPL_EXPORT GpuMemoryBufferTracker { + public: + // Ownership of |factory| remains with caller. + explicit GpuMemoryBufferTracker(ImageFactory* factory); + virtual ~GpuMemoryBufferTracker(); + + GLuint CreateBuffer( + GLsizei width, GLsizei height, GLenum internalformat); + GpuMemoryBuffer* GetBuffer(GLuint image_id); + void RemoveBuffer(GLuint image_id); + + private: + typedef gpu::hash_map<GLuint, GpuMemoryBuffer*> BufferMap; + BufferMap buffers_; + ImageFactory* factory_; + + DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferTracker); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_GPU_MEMORY_BUFFER_TRACKER_H_ diff --git a/gpu/command_buffer/client/image_factory.h b/gpu/command_buffer/client/image_factory.h new file mode 100644 index 0000000..b752cb1 --- /dev/null +++ b/gpu/command_buffer/client/image_factory.h @@ -0,0 +1,33 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_ +#define GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_ + +#include <GLES2/gl2.h> + +#include "base/memory/scoped_ptr.h" +#include "gles2_impl_export.h" + +namespace gpu { +class GpuMemoryBuffer; + +namespace gles2 { + +class GLES2_IMPL_EXPORT ImageFactory { + + public: + virtual ~ImageFactory() {} + + // Create a GpuMemoryBuffer and makes it available to the + // service side by inserting it to the ImageManager. + virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( + int width, int height, GLenum internalformat, unsigned* image_id) = 0; + virtual void DeleteGpuMemoryBuffer(unsigned image_id) = 0; +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_H_ diff --git a/gpu/command_buffer/client/image_factory_mock.cc b/gpu/command_buffer/client/image_factory_mock.cc new file mode 100644 index 0000000..2d425f5 --- /dev/null +++ b/gpu/command_buffer/client/image_factory_mock.cc @@ -0,0 +1,17 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "../client/image_factory_mock.h" + +namespace gpu { +namespace gles2 { + +ImageFactoryMock::ImageFactoryMock(ImageManager* manager) { +} + +ImageFactoryMock::~ImageFactoryMock() { +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/client/image_factory_mock.h b/gpu/command_buffer/client/image_factory_mock.h new file mode 100644 index 0000000..101ee47 --- /dev/null +++ b/gpu/command_buffer/client/image_factory_mock.h @@ -0,0 +1,41 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_ +#define GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_ + +#include "../client/gpu_memory_buffer.h" +#include "../client/image_factory.h" +#include "base/memory/scoped_ptr.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace gpu { +namespace gles2 { +class ImageManager; + +// Mock implementation of ImageFactory +class ImageFactoryMock : public ImageFactory { + public: + ImageFactoryMock(ImageManager* image_manager); + virtual ~ImageFactoryMock(); + + MOCK_METHOD4(CreateGpuMemoryBufferMock, GpuMemoryBuffer*( + int width, int height, GLenum internalformat, unsigned* image_id)); + MOCK_METHOD1(DeleteGpuMemoryBuffer, void(unsigned)); + // Workaround for mocking methods that return scoped_ptrs + virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( + int width, int height, GLenum internalformat, + unsigned* image_id) OVERRIDE { + return scoped_ptr<GpuMemoryBuffer>(CreateGpuMemoryBufferMock( + width, height, internalformat, image_id)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ImageFactoryMock); +}; + +} // namespace gles2 +} // namespace gpu + +#endif // GPU_COMMAND_BUFFER_CLIENT_IMAGE_FACTORY_MOCK_H_ diff --git a/gpu/command_buffer/cmd_buffer_functions.txt b/gpu/command_buffer/cmd_buffer_functions.txt index 1a9268b..ec68be4 100644 --- a/gpu/command_buffer/cmd_buffer_functions.txt +++ b/gpu/command_buffer/cmd_buffer_functions.txt @@ -175,6 +175,8 @@ GL_APICALL void GL_APIENTRY glRegisterSharedIdsCHROMIUM (GLuint namespac GL_APICALL GLboolean GL_APIENTRY glEnableFeatureCHROMIUM (const char* feature); GL_APICALL void* GL_APIENTRY glMapBufferCHROMIUM (GLuint target, GLenum access); GL_APICALL GLboolean GL_APIENTRY glUnmapBufferCHROMIUM (GLuint target); +GL_APICALL void* GL_APIENTRY glMapImageCHROMIUM (GLuint image_id, GLenum access); +GL_APICALL void GL_APIENTRY glUnmapImageCHROMIUM (GLuint image_id); GL_APICALL void* GL_APIENTRY glMapBufferSubDataCHROMIUM (GLuint target, GLintptrNotNegative offset, GLsizeiptr size, GLenum access); GL_APICALL void GL_APIENTRY glUnmapBufferSubDataCHROMIUM (const void* mem); @@ -188,6 +190,9 @@ GL_APICALL void GL_APIENTRY glGetMultipleIntegervCHROMIUM (const GLenum* GL_APICALL void GL_APIENTRY glGetProgramInfoCHROMIUM (GLidProgram program, GLsizeiNotNegative bufsize, GLsizei* size, void* info); GL_APICALL GLuint GL_APIENTRY glCreateStreamTextureCHROMIUM (GLuint texture); GL_APICALL void GL_APIENTRY glDestroyStreamTextureCHROMIUM (GLuint texture); +GL_APICALL GLuint GL_APIENTRY glCreateImageCHROMIUM (GLsizei width, GLsizei height, GLenum internalformat); +GL_APICALL void GL_APIENTRY glDestroyImageCHROMIUM (GLuint image_id); +GL_APICALL void GL_APIENTRY glGetImageParameterivCHROMIUM (GLuint image_id, GLenum pname, GLint* params); GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLidShader shader, GLsizeiNotNegative bufsize, GLsizeiOptional* 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); 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 e78db86..1db8acf 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h @@ -41,6 +41,7 @@ static GLES2Util::EnumToString enum_to_string_table[] = { { 0x0003, "GL_LINE_STRIP", }, { 0x0000, "GL_POINTS", }, { 0x0001, "GL_LINES", }, + { 0x78F0, "GL_IMAGE_ROWBYTES_CHROMIUM", }, { 0x88B8, "GL_READ_ONLY", }, { 0x88B9, "GL_WRITE_ONLY_OES", }, { 0x8211, "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT", }, diff --git a/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc new file mode 100644 index 0000000..1598094 --- /dev/null +++ b/gpu/command_buffer/tests/gl_gpu_memory_buffer_unittests.cc @@ -0,0 +1,146 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <GLES2/gl2.h> +#include <GLES2/gl2chromium.h> +#include <GLES2/gl2ext.h> +#include <GLES2/gl2extchromium.h> + +#include "base/bind.h" +#include "base/memory/ref_counted.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_mock.h" +#include "gpu/command_buffer/client/image_factory_mock.h" +#include "gpu/command_buffer/service/image_manager.h" +#include "gpu/command_buffer/tests/gl_manager.h" +#include "gpu/command_buffer/tests/gl_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gl/gl_image.h" +#include "ui/gl/gl_image_mock.h" + +using testing::_; +using testing::IgnoreResult; +using testing::InvokeWithoutArgs; +using testing::Invoke; +using testing::Return; +using testing::SetArgPointee; +using testing::StrictMock; + +namespace gpu { +namespace gles2 { + +static const int kImageWidth = 256; +static const int kImageHeight = 256; +static const int kImageBytesPerPixel = 4; + +class MockGpuMemoryBufferTest : public testing::Test { + protected: + virtual void SetUp() { + GLManager::Options options; + image_manager_ = new ImageManager; + image_factory_.reset( + new StrictMock<ImageFactoryMock>(image_manager_)); + options.image_manager = image_manager_; + options.image_factory = image_factory_.get(); + + gl_.Initialize(options); + gl_.MakeCurrent(); + } + + virtual void TearDown() { + gl_.Destroy(); + } + + scoped_ptr<StrictMock<ImageFactoryMock> > image_factory_; + scoped_refptr<ImageManager> image_manager_; + GLManager gl_; +}; + +// An end to end test that tests the whole GpuMemoryBuffer lifecycle. +TEST_F(MockGpuMemoryBufferTest, Lifecycle) { + // Create a client texture id. + GLuint texture_id; + glGenTextures(1, &texture_id); + + // Buffer is owned and freed by GpuMemoryBufferTracker. + StrictMock<GpuMemoryBufferMock>* gpu_memory_buffer = + new StrictMock<GpuMemoryBufferMock>(kImageWidth, kImageHeight); + + const GLuint kImageId = 345u; + + EXPECT_CALL(*image_factory_.get(), CreateGpuMemoryBufferMock( + kImageWidth, kImageHeight, GL_RGBA8_OES, _)) + .Times(1) + .WillOnce(DoAll(SetArgPointee<3>(kImageId), + Return(gpu_memory_buffer))) + .RetiresOnSaturation(); + + // Create the GLImage and insert it into the ImageManager, which + // would be done within CreateGpuMemoryBufferMock if it weren't a mock. + GLuint image_id = glCreateImageCHROMIUM( + kImageWidth, kImageHeight, GL_RGBA8_OES); + EXPECT_EQ(kImageId, image_id); + + gfx::Size size(kImageWidth, kImageHeight); + scoped_refptr<gfx::GLImageMock> gl_image( + new gfx::GLImageMock(gpu_memory_buffer, size)); + image_manager_->AddImage(gl_image.get(), image_id); + + EXPECT_CALL(*gpu_memory_buffer, IsMapped()) + .WillOnce(Return(false)) + .RetiresOnSaturation(); + + scoped_ptr<uint8[]> buffer_pixels(new uint8[ + kImageWidth * kImageHeight * kImageBytesPerPixel]); + + EXPECT_CALL(*gpu_memory_buffer, Map(_, _)) + .Times(1) + .WillOnce(SetArgPointee<1>(buffer_pixels.get())) + .RetiresOnSaturation(); + void* mapped_buffer = + glMapImageCHROMIUM(image_id, GL_WRITE_ONLY); + EXPECT_EQ(buffer_pixels.get(), mapped_buffer); + + EXPECT_CALL(*gpu_memory_buffer, IsMapped()) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + + // Unmap the image. + EXPECT_CALL(*gpu_memory_buffer, Unmap()) + .Times(1) + .RetiresOnSaturation(); + glUnmapImageCHROMIUM(image_id); + + // Bind the texture and the image. + glBindTexture(GL_TEXTURE_2D, texture_id); + EXPECT_CALL(*gl_image, BindTexImage()) + .Times(1) + .WillOnce(Return(true)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl_image, GetSize()) + .Times(1) + .WillOnce(Return(size)) + .RetiresOnSaturation(); + glBindTexImage2DCHROMIUM(GL_TEXTURE_2D, image_id); + + // Destroy the image. + EXPECT_CALL(*gpu_memory_buffer, Die()) + .Times(1) + .RetiresOnSaturation(); + + EXPECT_CALL(*image_factory_.get(), DeleteGpuMemoryBuffer(image_id)) + .Times(1) + .RetiresOnSaturation(); + + glDestroyImageCHROMIUM(image_id); + + // Delete the texture. + glDeleteTextures(1, &texture_id); +} + +} // namespace gles2 +} // namespace gpu diff --git a/gpu/command_buffer/tests/gl_manager.cc b/gpu/command_buffer/tests/gl_manager.cc index 75a254a..3e55384 100644 --- a/gpu/command_buffer/tests/gl_manager.cc +++ b/gpu/command_buffer/tests/gl_manager.cc @@ -16,6 +16,7 @@ #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gpu_scheduler.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/mailbox_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_context.h" @@ -35,7 +36,9 @@ GLManager::Options::Options() share_mailbox_manager(NULL), virtual_manager(NULL), bind_generates_resource(false), - context_lost_allowed(false) { + context_lost_allowed(false), + image_manager(NULL), + image_factory(NULL) { } GLManager::GLManager() @@ -127,7 +130,7 @@ void GLManager::Initialize(const GLManager::Options& options) { if (!context_group) { context_group = new gles2::ContextGroup(mailbox_manager_.get(), - NULL, + options.image_manager, NULL, options.bind_generates_resource); } @@ -196,7 +199,8 @@ void GLManager::Initialize(const GLManager::Options& options) { client_share_group, transfer_buffer_.get(), kShareResources, - options.bind_generates_resource)); + options.bind_generates_resource, + options.image_factory)); ASSERT_TRUE(gles2_implementation_->Initialize( kStartTransferBufferSize, diff --git a/gpu/command_buffer/tests/gl_manager.h b/gpu/command_buffer/tests/gl_manager.h index 2ebe695..15fc9ef 100644 --- a/gpu/command_buffer/tests/gl_manager.h +++ b/gpu/command_buffer/tests/gl_manager.h @@ -30,6 +30,8 @@ class MailboxManager; class GLES2Decoder; class GLES2CmdHelper; class GLES2Implementation; +class ImageFactory; +class ImageManager; class ShareGroup; }; @@ -50,6 +52,10 @@ class GLManager { bool bind_generates_resource; // Whether or not it's ok to lose the context. bool context_lost_allowed; + // Image manager to be used. + gles2::ImageManager* image_manager; + // Image factory to be used. + gles2::ImageFactory* image_factory; }; GLManager(); ~GLManager(); diff --git a/gpu/gles2_conform_support/egl/display.cc b/gpu/gles2_conform_support/egl/display.cc index 1d3fea6..6eb6eab 100644 --- a/gpu/gles2_conform_support/egl/display.cc +++ b/gpu/gles2_conform_support/egl/display.cc @@ -230,7 +230,8 @@ EGLContext Display::CreateContext(EGLConfig config, NULL, transfer_buffer_.get(), share_resources, - true)); + true, + NULL)); if (!context_->Initialize( kTransferBufferSize, diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp index 0492532..371f5cd 100644 --- a/gpu/gpu.gyp +++ b/gpu/gpu.gyp @@ -243,10 +243,15 @@ ], 'sources': [ '<@(gles2_c_lib_source_files)', + 'command_buffer/client/gpu_memory_buffer_mock.cc', + 'command_buffer/client/gpu_memory_buffer_mock.h', + 'command_buffer/client/image_factory_mock.cc', + 'command_buffer/client/image_factory_mock.h', 'command_buffer/tests/gl_bind_uniform_location_unittest.cc', 'command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc', 'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc', 'command_buffer/tests/gl_depth_texture_unittest.cc', + 'command_buffer/tests/gl_gpu_memory_buffer_unittests.cc', 'command_buffer/tests/gl_lose_context_chromium_unittests.cc', 'command_buffer/tests/gl_manager.cc', 'command_buffer/tests/gl_manager.h', diff --git a/gpu/gpu_common.gypi b/gpu/gpu_common.gypi index 432457b..577c81b 100644 --- a/gpu/gpu_common.gypi +++ b/gpu/gpu_common.gypi @@ -39,6 +39,9 @@ 'command_buffer/client/gpu_memory_buffer.h', 'command_buffer/client/gpu_memory_buffer_factory.cc', 'command_buffer/client/gpu_memory_buffer_factory.h', + 'command_buffer/client/gpu_memory_buffer_tracker.h', + 'command_buffer/client/gpu_memory_buffer_tracker.cc', + 'command_buffer/client/image_factory.h', 'command_buffer/client/program_info_manager.cc', 'command_buffer/client/program_info_manager.h', 'command_buffer/client/query_tracker.cc', diff --git a/ppapi/shared_impl/ppb_graphics_3d_shared.cc b/ppapi/shared_impl/ppb_graphics_3d_shared.cc index e480e0c..fbe7221 100644 --- a/ppapi/shared_impl/ppb_graphics_3d_shared.cc +++ b/ppapi/shared_impl/ppb_graphics_3d_shared.cc @@ -129,7 +129,9 @@ bool PPB_Graphics3D_Shared::CreateGLES2Impl( share_gles2 ? share_gles2->share_group() : NULL, transfer_buffer_.get(), false, - true)); + true, + NULL // Do not use GpuMemoryBuffers. + )); if (!gles2_impl_->Initialize( transfer_buffer_size, diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp index bb89f59..f90b2dd 100644 --- a/ui/gl/gl.gyp +++ b/ui/gl/gl.gyp @@ -301,6 +301,8 @@ ], }, 'sources': [ + 'gl_image_mock.cc', + 'gl_image_mock.h', 'gl_mock.h', 'gl_mock.cc', '<(gl_binding_output_dir)/gl_mock_autogen_gl.h', diff --git a/ui/gl/gl_image_mock.cc b/ui/gl/gl_image_mock.cc new file mode 100644 index 0000000..fc3267da --- /dev/null +++ b/ui/gl/gl_image_mock.cc @@ -0,0 +1,15 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gl/gl_image_mock.h" + +namespace gfx { + +GLImageMock::GLImageMock(gfx::GpuMemoryBufferHandle handle, gfx::Size size) { +} + +GLImageMock::~GLImageMock() { +} + +} // namespace gfx diff --git a/ui/gl/gl_image_mock.h b/ui/gl/gl_image_mock.h new file mode 100644 index 0000000..25b7182 --- /dev/null +++ b/ui/gl/gl_image_mock.h @@ -0,0 +1,30 @@ +// Copyright (c) 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_GL_GL_IMAGE_MOCK_H_ +#define UI_GL_GL_IMAGE_MOCK_H_ + +#include "base/basictypes.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/size.h" +#include "ui/gl/gl_image.h" + +namespace gfx { + +class GLImageMock : public GLImage { + public: + GLImageMock(gfx::GpuMemoryBufferHandle handle, gfx::Size size); + + MOCK_METHOD0(BindTexImage, bool()); + MOCK_METHOD0(Destroy, void()); + MOCK_METHOD0(GetSize, gfx::Size()); + MOCK_METHOD0(ReleaseTexImage, void()); + private: + virtual ~GLImageMock(); + DISALLOW_COPY_AND_ASSIGN(GLImageMock); +}; + +} // namespace gfx + +#endif // UI_GL_GL_IMAGE_MOCK_H_ diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc index 4e48025..ba8f849 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.cc @@ -27,14 +27,18 @@ #include "base/synchronization/lock.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/gles2_lib.h" +#include "gpu/command_buffer/client/gpu_memory_buffer_factory.h" +#include "gpu/command_buffer/client/image_factory.h" #include "gpu/command_buffer/client/transfer_buffer.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/service/command_buffer_service.h" #include "gpu/command_buffer/service/context_group.h" #include "gpu/command_buffer/service/gl_context_virtual.h" #include "gpu/command_buffer/service/gpu_scheduler.h" +#include "gpu/command_buffer/service/image_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" #include "ui/gl/gl_context.h" +#include "ui/gl/gl_image.h" #include "ui/gl/gl_share_group.h" #include "ui/gl/gl_surface.h" #include "webkit/gpu/gl_bindings_skia_cmd_buffer.h" @@ -44,6 +48,9 @@ using gpu::CommandBuffer; using gpu::CommandBufferService; using gpu::gles2::GLES2CmdHelper; using gpu::gles2::GLES2Implementation; +using gpu::gles2::ImageFactory; +using gpu::gles2::ImageManager; +using gpu::GpuMemoryBuffer; using gpu::GpuScheduler; using gpu::TransferBuffer; using gpu::TransferBufferManager; @@ -51,6 +58,9 @@ using gpu::TransferBufferManagerInterface; namespace webkit { namespace gpu { +namespace { +class ImageFactoryInProcess; +} class GLInProcessContext { public: @@ -162,6 +172,10 @@ class GLInProcessContext { void OnContextLost(); + ::gpu::gles2::ImageManager* GetImageManager(); + + scoped_refptr<ImageFactoryInProcess> GetImageFactory(); + base::Closure context_lost_callback_; scoped_ptr<TransferBufferManagerInterface> transfer_buffer_manager_; scoped_ptr<CommandBufferService> command_buffer_; @@ -172,6 +186,7 @@ class GLInProcessContext { scoped_ptr<GLES2CmdHelper> gles2_helper_; scoped_ptr<TransferBuffer> transfer_buffer_; scoped_ptr<GLES2Implementation> gles2_implementation_; + scoped_refptr<ImageFactoryInProcess> image_factory_; scoped_ptr<WebKit::WebGraphicsContext3D::WebGraphicsSyncPointCallback> signal_sync_point_callback_; Error last_error_; @@ -287,6 +302,66 @@ AutoLockAndDecoderDetachThread::~AutoLockAndDecoderDetachThread() { &DetachThread); } +class ImageFactoryInProcess + : public ImageFactory, + public base::RefCountedThreadSafe<ImageFactoryInProcess> { + public: + explicit ImageFactoryInProcess(ImageManager* image_manager); + + // methods from ImageFactory + virtual scoped_ptr<GpuMemoryBuffer> CreateGpuMemoryBuffer( + int width, int height, GLenum internalformat, + unsigned* image_id) OVERRIDE; + virtual void DeleteGpuMemoryBuffer(unsigned image_id) OVERRIDE; + private: + friend class base::RefCountedThreadSafe<ImageFactoryInProcess>; + virtual ~ImageFactoryInProcess(); + + // ImageManager is referred by the ContextGroup and the + // ContextGroup outlives the client. + ImageManager* image_manager_; + unsigned next_id_; + + DISALLOW_COPY_AND_ASSIGN(ImageFactoryInProcess); +}; + +ImageFactoryInProcess::ImageFactoryInProcess( + ImageManager* image_manager) : image_manager_(image_manager), + next_id_(0) { +} + +ImageFactoryInProcess::~ImageFactoryInProcess() { +} + +scoped_ptr<GpuMemoryBuffer> ImageFactoryInProcess::CreateGpuMemoryBuffer( + int width, int height, GLenum internalformat, unsigned int* image_id) { + // We're taking the lock here because we're accessing the ContextGroup's + // shared ImageManager and next_id_. + AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), + g_all_shared_contexts.Get()); + // For Android WebView we assume the |internalformat| will always be + // GL_RGBA8_OES. + DCHECK_EQ(GL_RGBA8_OES, internalformat); + const GpuMemoryBuffer::Creator& create_gpu_memory_buffer_callback = + ::gpu::gles2::GetProcessDefaultGpuMemoryBufferFactory(); + scoped_ptr<GpuMemoryBuffer> buffer = + create_gpu_memory_buffer_callback.Run(width, height); + scoped_refptr<gfx::GLImage> gl_image = + gfx::GLImage::CreateGLImageForGpuMemoryBuffer(buffer->GetNativeBuffer(), + gfx::Size(width, height)); + *image_id = ++next_id_; // Valid image_ids start from 1. + image_manager_->AddImage(gl_image, *image_id); + return buffer.Pass(); +} + +void ImageFactoryInProcess::DeleteGpuMemoryBuffer(unsigned int image_id) { + // We're taking the lock here because we're accessing the ContextGroup's + // shared ImageManager. + AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), + g_all_shared_contexts.Get()); + image_manager_->RemoveImage(image_id); +} + } // namespace static void CallAndDestroy( @@ -417,6 +492,14 @@ GLES2Implementation* GLInProcessContext::GetImplementation() { return gles2_implementation_.get(); } +::gpu::gles2::ImageManager* GLInProcessContext::GetImageManager() { + return decoder_->GetContextGroup()->image_manager(); +} + +scoped_refptr<ImageFactoryInProcess> GLInProcessContext::GetImageFactory() { + return image_factory_; +} + GLInProcessContext::GLInProcessContext(bool share_resources) : last_error_(SUCCESS), share_resources_(share_resources), @@ -593,13 +676,30 @@ bool GLInProcessContext::Initialize( // Create a transfer buffer. transfer_buffer_.reset(new TransferBuffer(gles2_helper_.get())); + if (share_resources_) { + AutoLockAndDecoderDetachThread lock(g_decoder_lock.Get(), + g_all_shared_contexts.Get()); + if (g_all_shared_contexts.Get().empty()) { + // Create the image factory for the first context. + image_factory_ = new ImageFactoryInProcess(GetImageManager()); + } else { + // Share the image factory created by the first context. + GLInProcessContext* first_context = *g_all_shared_contexts.Get().begin(); + image_factory_ = first_context->GetImageFactory(); + } + } else { + // Create the image factory, this object retains its ownership. + image_factory_ = new ImageFactoryInProcess(GetImageManager()); + } + // Create the object exposing the OpenGL API. gles2_implementation_.reset(new GLES2Implementation( gles2_helper_.get(), context_group ? context_group->GetImplementation()->share_group() : NULL, transfer_buffer_.get(), true, - false)); + false, + image_factory_)); if (!gles2_implementation_->Initialize( kStartTransferBufferSize, @@ -1096,6 +1196,13 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ gl_->glname(a1, a2, a3); \ } +#define DELEGATE_TO_GL_3R(name, glname, t1, t2, t3, rt) \ +rt WebGraphicsContext3DInProcessCommandBufferImpl::name( \ + t1 a1, t2 a2, t3 a3) { \ + ClearContext(); \ + return gl_->glname(a1, a2, a3); \ +} + #define DELEGATE_TO_GL_4(name, glname, t1, t2, t3, t4) \ void WebGraphicsContext3DInProcessCommandBufferImpl::name( \ t1 a1, t2 a2, t3 a3, t4 a4) { \ @@ -1816,6 +1923,19 @@ void WebGraphicsContext3DInProcessCommandBufferImpl::OnContextLost() { } } +DELEGATE_TO_GL_3R(createImageCHROMIUM, CreateImageCHROMIUM, + WGC3Dsizei, WGC3Dsizei, WGC3Denum, WGC3Duint); + +DELEGATE_TO_GL_1(destroyImageCHROMIUM, DestroyImageCHROMIUM, WGC3Duint); + +DELEGATE_TO_GL_3(getImageParameterivCHROMIUM, GetImageParameterivCHROMIUM, + WGC3Duint, WGC3Denum, GLint*); + +DELEGATE_TO_GL_2R(mapImageCHROMIUM, MapImageCHROMIUM, + WGC3Duint, WGC3Denum, void*); + +DELEGATE_TO_GL_1(unmapImageCHROMIUM, UnmapImageCHROMIUM, WGC3Duint); + DELEGATE_TO_GL_3(bindUniformLocationCHROMIUM, BindUniformLocationCHROMIUM, WebGLId, WGC3Dint, const WGC3Dchar*) diff --git a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h index faa3e18..2bff591 100644 --- a/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h +++ b/webkit/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h @@ -474,7 +474,13 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl virtual void texStorage2DEXT( WGC3Denum target, WGC3Dint levels, WGC3Duint internalformat, WGC3Dint width, WGC3Dint height); - + virtual WGC3Duint createImageCHROMIUM( + WGC3Dsizei width, WGC3Dsizei height, WGC3Denum internalformat); + virtual void destroyImageCHROMIUM(WGC3Duint image_id); + virtual void getImageParameterivCHROMIUM( + WGC3Duint image_id, WGC3Denum pname, WGC3Dint* params); + virtual void* mapImageCHROMIUM(WGC3Duint image_id, WGC3Denum access); + virtual void unmapImageCHROMIUM(WGC3Duint image_id); virtual WebGLId createQueryEXT(); virtual void deleteQueryEXT(WebGLId query); virtual WGC3Dboolean isQueryEXT(WebGLId query); @@ -584,6 +590,7 @@ class WEBKIT_GPU_EXPORT WebGraphicsContext3DInProcessCommandBufferImpl std::vector<WGC3Denum> synthetic_errors_; std::vector<uint8> scanline_; + void FlipVertically(uint8* framebuffer, unsigned int width, unsigned int height); |