diff options
author | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 19:13:19 +0000 |
---|---|---|
committer | apatrick@google.com <apatrick@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-25 19:13:19 +0000 |
commit | b9849abfc2e081a1d85bd5eda2c5c1d2fd9e35a5 (patch) | |
tree | 6d191fbaf63c019cf01f2c53598c8756cd2f75df /gpu/command_buffer/client | |
parent | 76180ea4287b9458d97f8d547daf785bf136fba1 (diff) | |
download | chromium_src-b9849abfc2e081a1d85bd5eda2c5c1d2fd9e35a5.zip chromium_src-b9849abfc2e081a1d85bd5eda2c5c1d2fd9e35a5.tar.gz chromium_src-b9849abfc2e081a1d85bd5eda2c5c1d2fd9e35a5.tar.bz2 |
Merged in recent changes to command buffer code.
TEST=none
BUG=none
Review URL: http://codereview.chromium.org/434063
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33095 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu/command_buffer/client')
-rw-r--r-- | gpu/command_buffer/client/gles2_c_lib_autogen.h | 4 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_cmd_helper.h | 40 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_cmd_helper_autogen.h | 29 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_demo.cc | 10 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_demo_c.c | 2 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_demo_cc.cc | 187 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.cc | 213 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation.h | 64 | ||||
-rw-r--r-- | gpu/command_buffer/client/gles2_implementation_autogen.h | 193 |
9 files changed, 497 insertions, 245 deletions
diff --git a/gpu/command_buffer/client/gles2_c_lib_autogen.h b/gpu/command_buffer/client/gles2_c_lib_autogen.h index c03a350..76f0973 100644 --- a/gpu/command_buffer/client/gles2_c_lib_autogen.h +++ b/gpu/command_buffer/client/gles2_c_lib_autogen.h @@ -214,7 +214,7 @@ void GLES2GetAttachedShaders( GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) { gles2::GetGLContext()->GetAttachedShaders(program, maxcount, count, shaders); } -int GLES2GetAttribLocation(GLuint program, const char* name) { +GLint GLES2GetAttribLocation(GLuint program, const char* name) { return gles2::GetGLContext()->GetAttribLocation(program, name); } void GLES2GetBooleanv(GLenum pname, GLboolean* params) { @@ -280,7 +280,7 @@ void GLES2GetUniformfv(GLuint program, GLint location, GLfloat* params) { void GLES2GetUniformiv(GLuint program, GLint location, GLint* params) { gles2::GetGLContext()->GetUniformiv(program, location, params); } -int GLES2GetUniformLocation(GLuint program, const char* name) { +GLint GLES2GetUniformLocation(GLuint program, const char* name) { return gles2::GetGLContext()->GetUniformLocation(program, name); } void GLES2GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { diff --git a/gpu/command_buffer/client/gles2_cmd_helper.h b/gpu/command_buffer/client/gles2_cmd_helper.h index 9a1a741..fbb1ce1 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper.h +++ b/gpu/command_buffer/client/gles2_cmd_helper.h @@ -25,6 +25,46 @@ class GLES2CmdHelper : public CommandBufferHelper { // file instead of having to edit some template or the code generator. #include "gpu/command_buffer/client/gles2_cmd_helper_autogen.h" + // Helpers that could not be auto-generated. + // TODO(gman): Auto generate these. + + void GetAttribLocation( + GLuint program, uint32 name_shm_id, uint32 name_shm_offset, + uint32 location_shm_id, uint32 location_shm_offset, uint32 data_size) { + gles2::GetAttribLocation& c = GetCmdSpace<gles2::GetAttribLocation>(); + c.Init( + program, name_shm_id, name_shm_offset, location_shm_id, + location_shm_offset, data_size); + } + + void GetAttribLocationImmediate( + GLuint program, const char* name, + uint32 location_shm_id, uint32 location_shm_offset) { + const uint32 size = gles2::GetAttribLocationImmediate::ComputeSize(name); + gles2::GetAttribLocationImmediate& c = + GetImmediateCmdSpaceTotalSize<gles2::GetAttribLocationImmediate>(size); + c.Init(program, name, location_shm_id, location_shm_offset); + } + + void GetUniformLocation( + GLuint program, uint32 name_shm_id, uint32 name_shm_offset, + uint32 location_shm_id, uint32 location_shm_offset, uint32 data_size) { + gles2::GetUniformLocation& c = GetCmdSpace<gles2::GetUniformLocation>(); + c.Init( + program, name_shm_id, name_shm_offset, location_shm_id, + location_shm_offset, data_size); + } + + void GetUniformLocationImmediate( + GLuint program, const char* name, + uint32 location_shm_id, uint32 location_shm_offset) { + const uint32 size = gles2::GetUniformLocationImmediate::ComputeSize(name); + gles2::GetUniformLocationImmediate& c = + GetImmediateCmdSpaceTotalSize<gles2::GetUniformLocationImmediate>(size); + c.Init(program, name, location_shm_id, location_shm_offset); + } + + private: DISALLOW_COPY_AND_ASSIGN(GLES2CmdHelper); }; diff --git a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h index 1cfee5b..f05c14b 100644 --- a/gpu/command_buffer/client/gles2_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/gles2_cmd_helper_autogen.h @@ -450,20 +450,6 @@ shaders_shm_offset); } - void GetAttribLocation( - GLuint program, uint32 name_shm_id, uint32 name_shm_offset, - uint32 data_size) { - gles2::GetAttribLocation& c = GetCmdSpace<gles2::GetAttribLocation>(); - c.Init(program, name_shm_id, name_shm_offset, data_size); - } - - void GetAttribLocationImmediate(GLuint program, const char* name) { - const uint32 size = gles2::GetAttribLocationImmediate::ComputeSize(name); - gles2::GetAttribLocationImmediate& c = - GetImmediateCmdSpaceTotalSize<gles2::GetAttribLocationImmediate>(size); - c.Init(program, name); - } - void GetBooleanv( GLenum pname, uint32 params_shm_id, uint32 params_shm_offset) { gles2::GetBooleanv& c = GetCmdSpace<gles2::GetBooleanv>(); @@ -599,21 +585,6 @@ c.Init(program, location, params_shm_id, params_shm_offset); } - void GetUniformLocation( - GLuint program, uint32 name_shm_id, uint32 name_shm_offset, - uint32 data_size) { - gles2::GetUniformLocation& c = GetCmdSpace<gles2::GetUniformLocation>(); - c.Init(program, name_shm_id, name_shm_offset, data_size); - } - - void GetUniformLocationImmediate(GLuint program, const char* name) { - const uint32 size = gles2::GetUniformLocationImmediate::ComputeSize(name); - gles2::GetUniformLocationImmediate& c = - GetImmediateCmdSpaceTotalSize<gles2::GetUniformLocationImmediate>( - size); - c.Init(program, name); - } - void GetVertexAttribfv( GLuint index, GLenum pname, uint32 params_shm_id, uint32 params_shm_offset) { diff --git a/gpu/command_buffer/client/gles2_demo.cc b/gpu/command_buffer/client/gles2_demo.cc index 04419c3..1595ea3 100644 --- a/gpu/command_buffer/client/gles2_demo.cc +++ b/gpu/command_buffer/client/gles2_demo.cc @@ -73,10 +73,18 @@ bool GLES2Demo::Setup(NPP npp, void* hwnd, int32 size) { size_t transfer_buffer_size = 512 * 1024; int32 transfer_buffer_id = command_buffer->CreateTransferBuffer(transfer_buffer_size); - void* transfer_buffer = + ::base::SharedMemory* shared_memory = command_buffer->GetTransferBuffer(transfer_buffer_id); + if (!shared_memory->Map(transfer_buffer_size)) { + return false; + } + void* transfer_buffer = shared_memory->memory(); + if (!transfer_buffer) { + return false; + } gles2::g_gl_impl = new GLES2Implementation(helper, + transfer_buffer_size, transfer_buffer, transfer_buffer_id); diff --git a/gpu/command_buffer/client/gles2_demo_c.c b/gpu/command_buffer/client/gles2_demo_c.c index 44b2c57..2f54bd1 100644 --- a/gpu/command_buffer/client/gles2_demo_c.c +++ b/gpu/command_buffer/client/gles2_demo_c.c @@ -9,7 +9,7 @@ #include "gpu/command_buffer/client/gles2_demo_c.h" void GLFromCTestFunction() { - glClear(GL_COLOR_BUFFER_BIT); + // glClear(GL_COLOR_BUFFER_BIT); } diff --git a/gpu/command_buffer/client/gles2_demo_cc.cc b/gpu/command_buffer/client/gles2_demo_cc.cc index d7a023c..ba5e618 100644 --- a/gpu/command_buffer/client/gles2_demo_cc.cc +++ b/gpu/command_buffer/client/gles2_demo_cc.cc @@ -8,14 +8,187 @@ #include <GLES2/gl2.h> #include "gpu/command_buffer/client/gles2_demo_cc.h" +namespace { + +int g_width = 512; +int g_height = 512; +GLuint g_texture = 0; +int g_textureLoc = -1; +GLuint g_programObject = 0; +GLuint g_vbo = 0; +GLsizei g_texCoordOffset = 0; + +void CheckGLError() { + GLenum error = glGetError(); + if (error != GL_NO_ERROR) { + DLOG(ERROR) << "GL Error: " << error; + } +} + +GLuint LoadShader(GLenum type, const char* shaderSrc) { + GLuint shader = glCreateShader(type); + if (shader == 0) { + return 0; + } + // Load the shader source + glShaderSource(shader, 1, &shaderSrc, NULL); + // Compile the shader + glCompileShader(shader); + // Check the compile status + GLint value; + glGetShaderiv(shader, GL_COMPILE_STATUS, &value); + if (value == 0) { + char buffer[1024]; + GLsizei length; + glGetShaderInfoLog(shader, sizeof(buffer), &length, buffer); + std::string log(buffer, length); + DLOG(ERROR) << "Error compiling shader:" << log; + glDeleteShader(shader); + return 0; + } + return shader; +} + +void InitShaders() { + static const char* vShaderStr = + "attribute vec3 g_Position;\n" + "attribute vec2 g_TexCoord0;\n" + "varying vec2 texCoord;\n" + "void main()\n" + "{\n" + " gl_Position = vec4(g_Position.x, g_Position.y, g_Position.z, 1.0);\n" + " texCoord = g_TexCoord0;\n" + "}\n"; + static const char* fShaderStr = + "uniform sampler2D tex;\n" + "varying vec2 texCoord;\n" + "void main()\n" + "{\n" + " gl_FragColor = texture2D(tex, texCoord);\n" + "}\n"; + + GLuint vertexShader = LoadShader(GL_VERTEX_SHADER, vShaderStr); + GLuint fragmentShader = LoadShader(GL_FRAGMENT_SHADER, fShaderStr); + // Create the program object + GLuint programObject = glCreateProgram(); + if (programObject == 0) { + DLOG(ERROR) << "Creating program failed"; + return; + } + glAttachShader(programObject, vertexShader); + glAttachShader(programObject, fragmentShader); + // Bind g_Position to attribute 0 + // Bind g_TexCoord0 to attribute 1 + glBindAttribLocation(programObject, 0, "g_Position"); + glBindAttribLocation(programObject, 1, "g_TexCoord0"); + // Link the program + glLinkProgram(programObject); + // Check the link status + GLint linked; + glGetProgramiv(programObject, GL_LINK_STATUS, &linked); + if (linked == 0) { + char buffer[1024]; + GLsizei length; + glGetProgramInfoLog(programObject, sizeof(buffer), &length, buffer); + std::string log(buffer, length); + DLOG(ERROR) << "Error linking program:" << log; + glDeleteProgram(programObject); + return; + } + g_programObject = programObject; + g_textureLoc = glGetUniformLocation(g_programObject, "tex"); + glGenBuffers(1, &g_vbo); + glBindBuffer(GL_ARRAY_BUFFER, g_vbo); + static float vertices[] = { + 0.25, 0.75, 0.0, + -0.75, 0.75, 0.0, + -0.75, -0.25, 0.0, + 0.25, 0.75, 0.0, + -0.75, -0.25, 0.0, + 0.25, -0.25, 0.0, + }; + static float texCoords[] = { + 1.0, 1.0, + 0.0, 1.0, + 0.0, 0.0, + 1.0, 1.0, + 0.0, 0.0, + 1.0, 0.0, + }; + g_texCoordOffset = sizeof(vertices); + glBufferData(GL_ARRAY_BUFFER, + sizeof(vertices) + sizeof(texCoords), + NULL, + GL_STATIC_DRAW); + glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices); + glBufferSubData(GL_ARRAY_BUFFER, g_texCoordOffset, + sizeof(texCoords), texCoords); + CheckGLError(); +} + +void Draw() { + // Note: the viewport is automatically set up to cover the entire Canvas. + // Clear the color buffer + glClear(GL_COLOR_BUFFER_BIT); + CheckGLError(); + // Use the program object + glUseProgram(g_programObject); + CheckGLError(); + // Load the vertex data + glBindBuffer(GL_ARRAY_BUFFER, g_vbo); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, + reinterpret_cast<const void*>(g_texCoordOffset)); + CheckGLError(); + // Bind the texture to texture unit 0 + glBindTexture(GL_TEXTURE_2D, g_texture); + CheckGLError(); + // Point the uniform sampler to texture unit 0 + glUniform1i(g_textureLoc, 0); + CheckGLError(); + glDrawArrays(GL_TRIANGLES, 0, 6); + CheckGLError(); + glFlush(); +} + +GLuint CreateCheckerboardTexture() { + static unsigned char pixels[] = { + 255, 255, 255, + 0, 0, 0, + 0, 0, 0, + 255, 255, 255, + }; + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, + pixels); + return texture; +} + +void Init() { + glClearColor(0.f, 0.f, .7f, 1.f); + g_texture = CreateCheckerboardTexture(); + InitShaders(); +} + +} // anonymous namespace. + void GLFromCPPTestFunction() { - static bool foo = true; - foo = !foo; - glClearColor( - foo ? 1.0f : 0.0f, - foo ? 0.0f : 1.0f, - 1.0f, - 1.0f); + static bool initialized = false; + if (!initialized) { + initialized = true; + Init(); + } + Draw(); } + diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index e60e68b..1208a57 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc @@ -14,13 +14,21 @@ namespace gles2 { GLES2Implementation::GLES2Implementation( GLES2CmdHelper* helper, + size_t transfer_buffer_size, void* transfer_buffer, - int transfer_buffer_id) + int32 transfer_buffer_id) : util_(0), // TODO(gman): Get real number of compressed texture formats. helper_(helper), - shared_memory_(transfer_buffer, transfer_buffer_id), + transfer_buffer_(transfer_buffer_size, helper, transfer_buffer), + transfer_buffer_id_(transfer_buffer_id), pack_alignment_(4), unpack_alignment_(4) { + // Eat 1 id so we start at 1 instead of 0. + GLuint eat; + MakeIds(1, &eat); + // Allocate space for simple GL results. + result_buffer_ = transfer_buffer_.Alloc(kMaxSizeOfSimpleResult); + result_shm_offset_ = transfer_buffer_.GetOffset(result_buffer_); } void GLES2Implementation::MakeIds(GLsizei n, GLuint* ids) { @@ -35,11 +43,47 @@ void GLES2Implementation::FreeIds(GLsizei n, const GLuint* ids) { } } +void GLES2Implementation::WaitForCmd() { + int32 token = helper_->InsertToken(); + helper_->WaitForToken(token); +} + void GLES2Implementation::DrawElements( GLenum mode, GLsizei count, GLenum type, const void* indices) { helper_->DrawElements(mode, count, type, reinterpret_cast<GLuint>(indices)); } +GLint GLES2Implementation::GetAttribLocation( + GLuint program, const char* name) { + helper_->GetAttribLocationImmediate( + program, name, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLint>(); +} + +GLint GLES2Implementation::GetUniformLocation( + GLuint program, const char* name) { + helper_->GetUniformLocationImmediate( + program, name, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLint>(); +} + +void GLES2Implementation::PixelStorei(GLenum pname, GLint param) { + switch (pname) { + case GL_PACK_ALIGNMENT: + pack_alignment_ = param; + break; + case GL_UNPACK_ALIGNMENT: + unpack_alignment_ = param; + break; + default: + break; + } + helper_->PixelStorei(pname, param); +} + + void GLES2Implementation::VertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) { @@ -48,103 +92,158 @@ void GLES2Implementation::VertexAttribPointer( } void GLES2Implementation::ShaderSource( - GLuint shader, GLsizei count, const char** string, const GLint* length) { + GLuint shader, GLsizei count, const char** source, const GLint* length) { // TODO(gman): change to use buckets and check that there is enough room. - uint32* offsets = shared_memory_.GetAddressAs<uint32*>(0); - char* strings = reinterpret_cast<char*>(offsets + count); + // Compute the total size. + uint32 total_size = count * sizeof(total_size); + for (GLsizei ii = 0; ii < count; ++ii) { + total_size += length ? length[ii] : strlen(source[ii]); + } + + // Create string table in transfer buffer. + char* strings = transfer_buffer_.AllocTyped<char>(total_size); + uint32* offsets = reinterpret_cast<uint32*>(strings); uint32 offset = count * sizeof(*offsets); for (GLsizei ii = 0; ii < count; ++ii) { - uint32 len = length ? length[ii] : strlen(string[ii]); - memcpy(strings + offset, string[ii], len); + uint32 len = length ? length[ii] : strlen(source[ii]); + memcpy(strings + offset, source[ii], len); offset += len; offsets[ii] = offset; } - helper_->ShaderSource(shader, count, shared_memory_.GetId(), 0, offset); - // TODO(gman): Should insert token but not wait until we need shared memory - // again. Really, I should implement a shared memory manager that puts - // things in the next unused part of shared memory and only blocks - // when it needs more memory. - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->ShaderSource(shader, count, + transfer_buffer_id_, + transfer_buffer_.GetOffset(strings), offset); + transfer_buffer_.FreePendingToken(strings, helper_->InsertToken()); } void GLES2Implementation::BufferData( GLenum target, GLsizeiptr size, const void* data, GLenum usage) { - // TODO(gman): Switch to use buckets alwayst or at least if no room in shared - // memory. - memcpy(shared_memory_.GetAddress(0), data, size); - helper_->BufferData(target, size, shared_memory_.GetId(), 0, usage); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + // NOTE: Should this be optimized for the case where we can call BufferData + // with the actual data in the case of our transfer buffer being big + // enough? + helper_->BufferData(target, size, 0, 0, usage); + if (data != NULL) { + BufferSubData(target, 0, size, data); + } } void GLES2Implementation::BufferSubData( GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { - // TODO(gman): Switch to use buckets alwayst or at least if no room in shared - // memory. - memcpy(shared_memory_.GetAddress(0), data, size); - helper_->BufferSubData(target, offset, size, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + const int8* source = static_cast<const int8*>(data); + GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); + while (size) { + GLsizeiptr part_size = std::min(size, max_size); + void* buffer = transfer_buffer_.Alloc(part_size); + memcpy(buffer, source, part_size); + helper_->BufferSubData(target, offset, part_size, + transfer_buffer_id_, + transfer_buffer_.GetOffset(buffer)); + transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); + offset += part_size; + source += part_size; + size -= part_size; + } } void GLES2Implementation::CompressedTexImage2D( GLenum target, GLint level, GLenum internalformat, GLsizei width, - GLsizei height, GLint border, GLsizei imageSize, const void* data) { + GLsizei height, GLint border, GLsizei image_size, const void* data) { // TODO(gman): Switch to use buckets alwayst or at least if no room in shared // memory. - memcpy(shared_memory_.GetAddress(0), data, imageSize); + DCHECK_LE(image_size, + static_cast<GLsizei>( + transfer_buffer_.GetLargestFreeOrPendingSize())); + void* buffer = transfer_buffer_.Alloc(image_size); + memcpy(buffer, data, image_size); helper_->CompressedTexImage2D( - target, level, internalformat, width, height, border, imageSize, - shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + target, level, internalformat, width, height, border, image_size, + transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); } void GLES2Implementation::CompressedTexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, - GLsizei height, GLenum format, GLsizei imageSize, const void* data) { + GLsizei height, GLenum format, GLsizei image_size, const void* data) { // TODO(gman): Switch to use buckets alwayst or at least if no room in shared // memory. - memcpy(shared_memory_.GetAddress(0), data, imageSize); + DCHECK_LE(image_size, + static_cast<GLsizei>( + transfer_buffer_.GetLargestFreeOrPendingSize())); + void* buffer = transfer_buffer_.Alloc(image_size); + memcpy(buffer, data, image_size); helper_->CompressedTexSubImage2D( - target, level, xoffset, yoffset, width, height, format, imageSize, - shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + target, level, xoffset, yoffset, width, height, format, image_size, + transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); } void GLES2Implementation::TexImage2D( GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) { - // TODO(gman): Switch to use buckets alwayst or at least if no room in shared - // memory. - uint32 pixels_size = GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_); - memcpy(shared_memory_.GetAddress(0), pixels, pixels_size); helper_->TexImage2D( - target, level, internalformat, width, height, border, format, type, - shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + target, level, internalformat, width, height, border, format, type, 0, 0); + if (pixels) { + TexSubImage2D(target, level, 0, 0, width, height, format, type, pixels); + } } void GLES2Implementation::TexSubImage2D( GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) { - // TODO(gman): Switch to use buckets alwayst or at least if no room in shared - // memory. - uint32 pixels_size = GLES2Util::ComputeImageDataSize( - width, height, format, type, unpack_alignment_); - memcpy(shared_memory_.GetAddress(0), pixels, pixels_size); - helper_->TexSubImage2D( - target, level, xoffset, yoffset, width, height, format, type, - shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + const int8* source = static_cast<const int8*>(pixels); + GLsizeiptr max_size = transfer_buffer_.GetLargestFreeOrPendingSize(); + + GLsizeiptr unpadded_row_size = GLES2Util::ComputeImageDataSize( + width, 1, format, type, unpack_alignment_); + GLsizeiptr padded_row_size = GLES2Util::ComputeImageDataSize( + width, 2, format, type, unpack_alignment_) - unpadded_row_size; + + if (padded_row_size <= max_size) { + // Transfer by rows. + GLint max_rows = max_size / padded_row_size; + while (height) { + GLint num_rows = std::min(height, max_rows); + GLsizeiptr part_size = num_rows * padded_row_size; + void* buffer = transfer_buffer_.Alloc(part_size); + memcpy(buffer, source, part_size); + helper_->TexSubImage2D( + target, level, xoffset, yoffset, width, num_rows, format, type, + transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); + yoffset += num_rows; + source += part_size; + height -= num_rows; + } + } else { + // Transfer by sub rows. Beacuse GL has no maximum texture dimensions. + GLsizeiptr element_size = GLES2Util::ComputeImageDataSize( + 1, 1, format, type, unpack_alignment_); + max_size -= max_size % element_size; + GLint max_sub_row_pixels = max_size / element_size; + for (; height; --height) { + GLint temp_width = width; + GLint temp_xoffset = xoffset; + const int8* row_source = source; + while (temp_width) { + GLint num_pixels = std::min(width, max_sub_row_pixels); + GLsizeiptr part_size = num_pixels * element_size; + void* buffer = transfer_buffer_.Alloc(part_size); + memcpy(buffer, row_source, part_size); + helper_->TexSubImage2D( + target, level, temp_xoffset, yoffset, temp_width, 1, format, type, + transfer_buffer_id_, transfer_buffer_.GetOffset(buffer)); + transfer_buffer_.FreePendingToken(buffer, helper_->InsertToken()); + row_source += part_size; + temp_xoffset += num_pixels; + temp_width -= num_pixels; + } + ++yoffset; + source += padded_row_size; + } + } } diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 2df52ca..fec3de9 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h @@ -9,43 +9,11 @@ #include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/client/gles2_cmd_helper.h" #include "gpu/command_buffer/client/id_allocator.h" +#include "gpu/command_buffer/client/fenced_allocator.h" namespace command_buffer { namespace gles2 { -// A class to help with shared memory. -class SharedMemoryHelper { - public: - SharedMemoryHelper(void* address, int id) - : address_(address), - id_(id) { - } - - unsigned int GetOffset(void* address) const { - return static_cast<int8*>(address) - - static_cast<int8*>(address_); - } - - void* GetAddress(unsigned int offset) const { - return static_cast<int8*>(address_) + offset; - } - - template <typename T> - T GetAddressAs(unsigned int offset) const { - return static_cast<T>(GetAddress(offset)); - } - - unsigned int GetId() const { - return id_; - } - - private: - void* address_; - int id_; - - DISALLOW_COPY_AND_ASSIGN(SharedMemoryHelper); -}; - // This class emulates GLES2 over command buffers. It can be used by a client // program so that the program does not need deal with shared memory and command // buffer management. See gl2_lib.h. Note that there is a performance gain to @@ -56,8 +24,9 @@ class GLES2Implementation { public: GLES2Implementation( GLES2CmdHelper* helper, + size_t transfer_buffer_size, void* transfer_buffer, - int transfer_buffer_id); // TODO: add size. + int32 transfer_buffer_id); // Include the auto-generated part of this class. We split this because // it means we can easily edit the non-auto generated parts right here in @@ -71,10 +40,35 @@ class GLES2Implementation { // Frees a set of Ids for glDelete___ functions. void FreeIds(GLsizei n, const GLuint* ids); + // Gets the shared memory id for the result buffer. + uint32 result_shm_id() const { + return transfer_buffer_id_; + } + + // Gets the shared memory offset for the result buffer. + uint32 result_shm_offset() const { + return result_shm_offset_; + } + + // Gets the value of the result. + template <typename T> + T GetResultAs() const { + return *static_cast<T*>(result_buffer_); + } + + // Waits for all commands to execute. + void WaitForCmd(); + + // The maxiumum result size from simple GL get commands. + static const size_t kMaxSizeOfSimpleResult = 4 * sizeof(uint32); // NOLINT. + GLES2Util util_; GLES2CmdHelper* helper_; IdAllocator id_allocator_; - SharedMemoryHelper shared_memory_; // TODO(gman): rename transfer_buffer_. + FencedAllocatorWrapper transfer_buffer_; + int transfer_buffer_id_; + void* result_buffer_; + uint32 result_shm_offset_; // pack alignment as last set by glPixelStorei GLint pack_alignment_; diff --git a/gpu/command_buffer/client/gles2_implementation_autogen.h b/gpu/command_buffer/client/gles2_implementation_autogen.h index 940454b..c4b34b9 100644 --- a/gpu/command_buffer/client/gles2_implementation_autogen.h +++ b/gpu/command_buffer/client/gles2_implementation_autogen.h @@ -252,77 +252,63 @@ void GetActiveUniform( void GetAttachedShaders( GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); -int GetAttribLocation(GLuint program, const char* name) { - // TODO(gman): This needs to change to use SendString. - GLint* result = shared_memory_.GetAddressAs<GLint*>(0); - DCHECK(false); // pass in shared memory - helper_->GetAttribLocationImmediate(program, name); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *result; -} +GLint GetAttribLocation(GLuint program, const char* name); void GetBooleanv(GLenum pname, GLboolean* params) { - helper_->GetBooleanv(pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetBooleanv(pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) { - helper_->GetBufferParameteriv(target, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetBufferParameteriv( + target, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } GLenum GetError() { - helper_->GetError(shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLenum*>(0); + helper_->GetError(result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLenum>(); } void GetFloatv(GLenum pname, GLfloat* params) { - helper_->GetFloatv(pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetFloatv(pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetFramebufferAttachmentParameteriv( GLenum target, GLenum attachment, GLenum pname, GLint* params) { helper_->GetFramebufferAttachmentParameteriv( - target, attachment, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + target, attachment, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetIntegerv(GLenum pname, GLint* params) { - helper_->GetIntegerv(pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetIntegerv(pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetProgramiv(GLuint program, GLenum pname, GLint* params) { - helper_->GetProgramiv(program, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetProgramiv(program, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } // TODO(gman): Implement this @@ -331,21 +317,19 @@ void GetProgramInfoLog( void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) { helper_->GetRenderbufferParameteriv( - target, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + target, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetShaderiv(GLuint shader, GLenum pname, GLint* params) { - helper_->GetShaderiv(shader, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetShaderiv(shader, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } // TODO(gman): Implement this @@ -362,53 +346,45 @@ void GetShaderSource( const GLubyte* GetString(GLenum name); void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) { - helper_->GetTexParameterfv(target, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetTexParameterfv( + target, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) { - helper_->GetTexParameteriv(target, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetTexParameteriv( + target, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetUniformfv(GLuint program, GLint location, GLfloat* params); void GetUniformiv(GLuint program, GLint location, GLint* params); -int GetUniformLocation(GLuint program, const char* name) { - // TODO(gman): This needs to change to use SendString. - GLint* result = shared_memory_.GetAddressAs<GLint*>(0); - DCHECK(false); // pass in shared memory - helper_->GetUniformLocationImmediate(program, name); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *result; -} +GLint GetUniformLocation(GLuint program, const char* name); void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) { - helper_->GetVertexAttribfv(index, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetVertexAttribfv( + index, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) { - helper_->GetVertexAttribiv(index, pname, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); + helper_->GetVertexAttribiv( + index, pname, result_shm_id(), result_shm_offset()); + WaitForCmd(); GLsizei num_values = util_.GLGetNumValuesReturned(pname); - memcpy(params, shared_memory_.GetAddress(0), - num_values * sizeof(*params)); + DCHECK_LE(num_values * sizeof(*params), kMaxSizeOfSimpleResult); + memcpy(params, result_buffer_, num_values * sizeof(*params)); } void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer); @@ -418,52 +394,45 @@ void Hint(GLenum target, GLenum mode) { } GLboolean IsBuffer(GLuint buffer) { - helper_->IsBuffer(buffer, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsBuffer(buffer, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsEnabled(GLenum cap) { - helper_->IsEnabled(cap, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsEnabled(cap, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsFramebuffer(GLuint framebuffer) { - helper_->IsFramebuffer(framebuffer, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsFramebuffer(framebuffer, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsProgram(GLuint program) { - helper_->IsProgram(program, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsProgram(program, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsRenderbuffer(GLuint renderbuffer) { - helper_->IsRenderbuffer(renderbuffer, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsRenderbuffer(renderbuffer, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsShader(GLuint shader) { - helper_->IsShader(shader, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsShader(shader, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } GLboolean IsTexture(GLuint texture) { - helper_->IsTexture(texture, shared_memory_.GetId(), 0); - int32 token = helper_->InsertToken(); - helper_->WaitForToken(token); - return *shared_memory_.GetAddressAs<GLboolean*>(0); + helper_->IsTexture(texture, result_shm_id(), result_shm_offset()); + WaitForCmd(); + return GetResultAs<GLboolean>(); } void LineWidth(GLfloat width) { @@ -474,9 +443,7 @@ void LinkProgram(GLuint program) { helper_->LinkProgram(program); } -void PixelStorei(GLenum pname, GLint param) { - helper_->PixelStorei(pname, param); -} +void PixelStorei(GLenum pname, GLint param); void PolygonOffset(GLfloat factor, GLfloat units) { helper_->PolygonOffset(factor, units); |